Merge branch 'omap-for-v3.8/fixes-for-merge-window' into omap-for-v3.8/fixes-for...
authorTony Lindgren <tony@atomide.com>
Sun, 16 Dec 2012 19:28:10 +0000 (11:28 -0800)
committerTony Lindgren <tony@atomide.com>
Sun, 16 Dec 2012 19:28:10 +0000 (11:28 -0800)
2562 files changed:
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus [new file with mode: 0644]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra [new file with mode: 0644]
Documentation/ABI/stable/sysfs-driver-ib_srp [new file with mode: 0644]
Documentation/ABI/stable/sysfs-transport-srp [new file with mode: 0644]
Documentation/ABI/testing/dev-kmsg
Documentation/ABI/testing/sysfs-bus-pci
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
Documentation/ABI/testing/sysfs-driver-hid-roccat-lua [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
Documentation/ABI/testing/sysfs-driver-ppi
Documentation/ABI/testing/sysfs-profiling
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
Documentation/DocBook/media/v4l/vidioc-expbuf.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/vidioc-qbuf.xml
Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
Documentation/DocBook/writing-an-alsa-driver.tmpl
Documentation/HOWTO
Documentation/PCI/pci-iov-howto.txt
Documentation/accounting/getdelays.c
Documentation/acpi/initrd_table_override.txt [new file with mode: 0644]
Documentation/arm/OMAP/DSS
Documentation/cgroups/cpusets.txt
Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/altera/socfpga-system.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt
Documentation/devicetree/bindings/arm/coherency-fabric.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/l2cc.txt
Documentation/devicetree/bindings/arm/spear/shirq.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/mvebu-core-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/crypto/fsl-sec4.txt
Documentation/devicetree/bindings/dma/mv-xor.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/ab8500.txt
Documentation/devicetree/bindings/misc/atmel-ssc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/marvell-orion-mdio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power_supply/ab8500/charger.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power_supply/ab8500/fg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/gpio-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8925-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8997-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/vexpress.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/ak4104.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs4271.txt
Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/omap-spi.txt
Documentation/devicetree/bindings/spi/spi-bus.txt
Documentation/devicetree/bindings/video/exynos_dp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/ssd1307fb.txt [new file with mode: 0644]
Documentation/dma-buf-sharing.txt
Documentation/dontdiff
Documentation/fault-injection/notifier-error-inject.txt
Documentation/filesystems/00-INDEX
Documentation/filesystems/efivarfs.txt [new file with mode: 0644]
Documentation/hid/uhid.txt
Documentation/hwmon/pmbus
Documentation/input/alps.txt
Documentation/input/event-codes.txt
Documentation/kbuild/modules.txt
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/memory-hotplug.txt
Documentation/misc-devices/mei/mei-amt-version.c
Documentation/power/power_supply_class.txt
Documentation/scsi/hptiop.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/video4linux/bttv/Cards
Documentation/video4linux/bttv/Sound-FAQ
Documentation/virtual/kvm/api.txt
Documentation/vm/frontswap.txt
Documentation/vm/transhuge.txt
MAINTAINERS
README
arch/alpha/include/asm/mmzone.h
arch/alpha/kernel/pci_iommu.c
arch/arm/Kconfig
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-370-mirabox.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/armada-xp-db.dts
arch/arm/boot/dts/armada-xp-mv78230.dtsi
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/armada-xp-mv78460.dtsi
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/spear1310-evb.dts
arch/arm/boot/dts/spear1310.dtsi
arch/arm/boot/dts/spear1340-evb.dts
arch/arm/boot/dts/spear1340.dtsi
arch/arm/boot/dts/spear13xx.dtsi
arch/arm/boot/dts/spear300-evb.dts
arch/arm/boot/dts/spear300.dtsi
arch/arm/boot/dts/spear310-evb.dts
arch/arm/boot/dts/spear310.dtsi
arch/arm/boot/dts/spear320-evb.dts
arch/arm/boot/dts/spear320-hmi.dts [new file with mode: 0644]
arch/arm/boot/dts/spear320.dtsi
arch/arm/boot/dts/spear3xx.dtsi
arch/arm/boot/dts/spear600-evb.dts
arch/arm/boot/dts/spear600.dtsi
arch/arm/configs/marzen_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/socfpga_defconfig
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/xen/interface.h
arch/arm/kernel/kprobes-test.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/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/pm_domain.c
arch/arm/mach-dove/Kconfig
arch/arm/mach-dove/common.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/include/mach/regs-clock.h
arch/arm/mach-exynos/include/mach/regs-pmu.h
arch/arm/mach-exynos/mach-armlex4210.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/pm.c
arch/arm/mach-kirkwood/Kconfig
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-mvebu/Makefile
arch/arm/mach-mvebu/addr-map.c
arch/arm/mach-mvebu/armada-370-xp.c
arch/arm/mach-mvebu/armada-370-xp.h
arch/arm/mach-mvebu/coherency.c [new file with mode: 0644]
arch/arm/mach-mvebu/coherency.h [new file with mode: 0644]
arch/arm/mach-mvebu/coherency_ll.S [new file with mode: 0644]
arch/arm/mach-mvebu/common.h
arch/arm/mach-mvebu/headsmp.S [new file with mode: 0644]
arch/arm/mach-mvebu/hotplug.c [new file with mode: 0644]
arch/arm/mach-mvebu/irq-armada-370-xp.c
arch/arm/mach-mvebu/platsmp.c [new file with mode: 0644]
arch/arm/mach-mvebu/pmsu.c [new file with mode: 0644]
arch/arm/mach-mvebu/pmsu.h [new file with mode: 0644]
arch/arm/mach-netx/xc.c
arch/arm/mach-omap2/board-rx51-video.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/common.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/display.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-s3c24xx/include/mach/bast-map.h
arch/arm/mach-s3c24xx/include/mach/dma.h
arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/pm.c
arch/arm/mach-s3c64xx/mach-crag6410.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-smdkc110.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/include/mach/sh7372.h
arch/arm/mach-shmobile/smp-emev2.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-sh73a0.c
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-socfpga/Makefile
arch/arm/mach-socfpga/core.h [new file with mode: 0644]
arch/arm/mach-socfpga/headsmp.S [new file with mode: 0644]
arch/arm/mach-socfpga/platsmp.c [new file with mode: 0644]
arch/arm/mach-socfpga/socfpga.c
arch/arm/mach-spear13xx/include/mach/spear.h
arch/arm/mach-spear13xx/spear1310.c
arch/arm/mach-spear13xx/spear13xx.c
arch/arm/mach-spear3xx/include/mach/irqs.h
arch/arm/mach-spear3xx/spear300.c
arch/arm/mach-spear3xx/spear310.c
arch/arm/mach-spear3xx/spear320.c
arch/arm/mach-spear3xx/spear3xx.c
arch/arm/mach-tegra/Kconfig
arch/arm/mm/Kconfig
arch/arm/mm/dma-mapping.c
arch/arm/mm/proc-v7.S
arch/arm/plat-omap/fb.c
arch/arm/plat-omap/include/plat/vram.h [deleted file]
arch/arm/plat-orion/addr-map.c
arch/arm/plat-orion/common.c
arch/arm/plat-orion/include/plat/addr-map.h
arch/arm/plat-orion/include/plat/common.h
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-samsung/clock.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-spear/Makefile
arch/arm/plat-spear/include/plat/shirq.h [deleted file]
arch/arm/plat-spear/shirq.c [deleted file]
arch/arm/xen/enlighten.c
arch/blackfin/mach-bf609/Kconfig
arch/blackfin/mm/sram-alloc.c
arch/cris/include/arch-v10/arch/irq.h
arch/cris/include/arch-v32/arch/irq.h
arch/frv/mm/pgalloc.c
arch/ia64/kvm/kvm-ia64.c
arch/m68k/Kconfig.bus
arch/m68k/Kconfig.cpu
arch/m68k/Kconfig.debug
arch/m68k/Kconfig.devices
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/hw_irq.h [deleted file]
arch/m68k/include/asm/shmparam.h [deleted file]
arch/m68k/include/asm/spinlock.h [deleted file]
arch/m68k/include/asm/termios.h [deleted file]
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/auxvec.h [deleted file]
arch/m68k/include/uapi/asm/msgbuf.h [deleted file]
arch/m68k/include/uapi/asm/sembuf.h [deleted file]
arch/m68k/include/uapi/asm/shmbuf.h [deleted file]
arch/m68k/include/uapi/asm/socket.h [deleted file]
arch/m68k/include/uapi/asm/sockios.h [deleted file]
arch/m68k/include/uapi/asm/termbits.h [deleted file]
arch/m68k/include/uapi/asm/termios.h [deleted file]
arch/m68k/kernel/traps.c
arch/m68k/math-emu/fp_log.c
arch/m68k/mm/init.c
arch/m68k/mm/init_mm.c [deleted file]
arch/m68k/mm/init_no.c [deleted file]
arch/m68k/mm/mcfmmu.c
arch/m68k/mm/motorola.c
arch/m68k/mm/sun3mmu.c
arch/m68k/sun3/sun3ints.c
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/asm/auxvec.h [deleted file]
arch/microblaze/include/asm/bitsperlong.h [deleted file]
arch/microblaze/include/asm/byteorder.h [deleted file]
arch/microblaze/include/asm/elf.h
arch/microblaze/include/asm/entry.h
arch/microblaze/include/asm/errno.h [deleted file]
arch/microblaze/include/asm/fcntl.h [deleted file]
arch/microblaze/include/asm/ioctl.h [deleted file]
arch/microblaze/include/asm/ioctls.h [deleted file]
arch/microblaze/include/asm/ipcbuf.h [deleted file]
arch/microblaze/include/asm/kvm_para.h [deleted file]
arch/microblaze/include/asm/mman.h [deleted file]
arch/microblaze/include/asm/msgbuf.h [deleted file]
arch/microblaze/include/asm/param.h [deleted file]
arch/microblaze/include/asm/poll.h [deleted file]
arch/microblaze/include/asm/posix_types.h [deleted file]
arch/microblaze/include/asm/ptrace.h
arch/microblaze/include/asm/resource.h [deleted file]
arch/microblaze/include/asm/sembuf.h [deleted file]
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/shmbuf.h [deleted file]
arch/microblaze/include/asm/sigcontext.h [deleted file]
arch/microblaze/include/asm/siginfo.h [deleted file]
arch/microblaze/include/asm/signal.h [deleted file]
arch/microblaze/include/asm/socket.h [deleted file]
arch/microblaze/include/asm/sockios.h [deleted file]
arch/microblaze/include/asm/stat.h [deleted file]
arch/microblaze/include/asm/statfs.h [deleted file]
arch/microblaze/include/asm/swab.h [deleted file]
arch/microblaze/include/asm/termbits.h [deleted file]
arch/microblaze/include/asm/termios.h [deleted file]
arch/microblaze/include/asm/types.h [deleted file]
arch/microblaze/include/asm/uaccess.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/include/uapi/asm/Kbuild
arch/microblaze/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/elf.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/errno.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/fcntl.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/ioctl.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/ipcbuf.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/mman.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/msgbuf.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/param.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/poll.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/resource.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/sembuf.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/setup.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/shmbuf.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/siginfo.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/signal.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/socket.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/stat.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/statfs.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/swab.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/termios.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/types.h [new file with mode: 0644]
arch/microblaze/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/process.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/signal.c
arch/microblaze/kernel/syscall_table.S
arch/microblaze/lib/libgcc.h
arch/microblaze/lib/muldi3.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/ar7/platform.c
arch/mips/bcm47xx/Kconfig
arch/mips/bcm47xx/Makefile
arch/mips/bcm47xx/gpio.c [deleted file]
arch/mips/bcm47xx/prom.c
arch/mips/bcm47xx/setup.c
arch/mips/bcm47xx/sprom.c
arch/mips/bcm47xx/wgt634u.c
arch/mips/bcm63xx/Makefile
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/bcm63xx/clk.c
arch/mips/bcm63xx/nvram.c [new file with mode: 0644]
arch/mips/bcm63xx/reset.c [new file with mode: 0644]
arch/mips/cavium-octeon/executive/cvmx-bootmem.c
arch/mips/cavium-octeon/flash_setup.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/octeon-memcpy.S
arch/mips/cavium-octeon/octeon-platform.c
arch/mips/cavium-octeon/setup.c
arch/mips/configs/ath79_defconfig [new file with mode: 0644]
arch/mips/configs/cavium_octeon_defconfig
arch/mips/configs/yosemite_defconfig [deleted file]
arch/mips/fw/sni/Makefile
arch/mips/include/asm/cpu.h
arch/mips/include/asm/fw/arc/types.h
arch/mips/include/asm/hazards.h
arch/mips/include/asm/kexec.h
arch/mips/include/asm/mach-ar7/war.h
arch/mips/include/asm/mach-ath79/war.h
arch/mips/include/asm/mach-au1x00/war.h
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
arch/mips/include/asm/mach-bcm47xx/gpio.h
arch/mips/include/asm/mach-bcm47xx/war.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h [new file with mode: 0644]
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h [new file with mode: 0644]
arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
arch/mips/include/asm/mach-bcm63xx/war.h
arch/mips/include/asm/mach-cavium-octeon/irq.h
arch/mips/include/asm/mach-cavium-octeon/war.h
arch/mips/include/asm/mach-cobalt/war.h
arch/mips/include/asm/mach-dec/war.h
arch/mips/include/asm/mach-emma2rh/war.h
arch/mips/include/asm/mach-generic/irq.h
arch/mips/include/asm/mach-ip22/war.h
arch/mips/include/asm/mach-ip27/war.h
arch/mips/include/asm/mach-ip28/war.h
arch/mips/include/asm/mach-ip32/war.h
arch/mips/include/asm/mach-jazz/war.h
arch/mips/include/asm/mach-jz4740/war.h
arch/mips/include/asm/mach-lantiq/war.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
arch/mips/include/asm/mach-lasat/war.h
arch/mips/include/asm/mach-loongson/war.h
arch/mips/include/asm/mach-loongson1/platform.h
arch/mips/include/asm/mach-loongson1/regs-clk.h
arch/mips/include/asm/mach-loongson1/war.h
arch/mips/include/asm/mach-malta/war.h
arch/mips/include/asm/mach-netlogic/irq.h
arch/mips/include/asm/mach-netlogic/multi-node.h [new file with mode: 0644]
arch/mips/include/asm/mach-netlogic/war.h
arch/mips/include/asm/mach-pnx833x/war.h
arch/mips/include/asm/mach-pnx8550/war.h
arch/mips/include/asm/mach-powertv/war.h
arch/mips/include/asm/mach-rc32434/war.h
arch/mips/include/asm/mach-rm/war.h
arch/mips/include/asm/mach-sead3/war.h
arch/mips/include/asm/mach-sibyte/war.h
arch/mips/include/asm/mach-tx39xx/war.h
arch/mips/include/asm/mach-tx49xx/war.h
arch/mips/include/asm/mach-vr41xx/war.h
arch/mips/include/asm/mach-wrppmc/war.h
arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h [deleted file]
arch/mips/include/asm/mach-yosemite/war.h [deleted file]
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/module.h
arch/mips/include/asm/netlogic/common.h
arch/mips/include/asm/netlogic/interrupt.h
arch/mips/include/asm/netlogic/mips-extns.h
arch/mips/include/asm/netlogic/xlp-hal/pic.h
arch/mips/include/asm/netlogic/xlp-hal/sys.h
arch/mips/include/asm/netlogic/xlr/fmn.h [new file with mode: 0644]
arch/mips/include/asm/netlogic/xlr/pic.h
arch/mips/include/asm/netlogic/xlr/xlr.h
arch/mips/include/asm/octeon/cvmx-bootmem.h
arch/mips/include/asm/octeon/cvmx-lmcx-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/octeon-model.h
arch/mips/include/asm/octeon/octeon.h
arch/mips/include/asm/page.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/pgtable-bits.h
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/pmc-sierra/msp71xx/war.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/sgiarcs.h
arch/mips/include/asm/smp.h
arch/mips/include/asm/smvp.h [deleted file]
arch/mips/include/asm/sparsemem.h
arch/mips/include/asm/time.h
arch/mips/include/asm/titan_dep.h [deleted file]
arch/mips/include/asm/war.h
arch/mips/kernel/Makefile
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/crash.c [new file with mode: 0644]
arch/mips/kernel/crash_dump.c [new file with mode: 0644]
arch/mips/kernel/irq-rm9000.c [deleted file]
arch/mips/kernel/machine_kexec.c
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/process.c
arch/mips/kernel/relocate_kernel.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/smp.c
arch/mips/kernel/traps.c
arch/mips/lantiq/Kconfig
arch/mips/lantiq/prom.c
arch/mips/lantiq/xway/Makefile
arch/mips/lantiq/xway/dma.c
arch/mips/lantiq/xway/reset.c
arch/mips/lantiq/xway/sysctrl.c
arch/mips/lantiq/xway/xrx200_phy_fw.c [new file with mode: 0644]
arch/mips/loongson1/Kconfig
arch/mips/loongson1/common/clock.c
arch/mips/loongson1/common/platform.c
arch/mips/loongson1/ls1b/board.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/c-octeon.c
arch/mips/mm/c-r4k.c
arch/mips/mm/highmem.c
arch/mips/mm/page.c
arch/mips/mm/pgtable-64.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/netlogic/Kconfig
arch/mips/netlogic/common/irq.c
arch/mips/netlogic/common/smp.c
arch/mips/netlogic/common/smpboot.S
arch/mips/netlogic/xlp/nlm_hal.c
arch/mips/netlogic/xlp/setup.c
arch/mips/netlogic/xlp/wakeup.c
arch/mips/netlogic/xlr/Makefile
arch/mips/netlogic/xlr/fmn-config.c [new file with mode: 0644]
arch/mips/netlogic/xlr/fmn.c [new file with mode: 0644]
arch/mips/netlogic/xlr/setup.c
arch/mips/netlogic/xlr/wakeup.c
arch/mips/oprofile/Makefile
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/oprofile/op_model_rm9000.c [deleted file]
arch/mips/pci/Makefile
arch/mips/pci/fixup-yosemite.c [deleted file]
arch/mips/pci/ops-bridge.c
arch/mips/pci/ops-titan-ht.c [deleted file]
arch/mips/pci/ops-titan.c [deleted file]
arch/mips/pci/pci-bcm63xx.c
arch/mips/pci/pci-octeon.c
arch/mips/pci/pci-xlr.c
arch/mips/pci/pci-yosemite.c [deleted file]
arch/mips/pmc-sierra/Kconfig
arch/mips/pmc-sierra/Platform
arch/mips/pmc-sierra/yosemite/Makefile [deleted file]
arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c [deleted file]
arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h [deleted file]
arch/mips/pmc-sierra/yosemite/ht-irq.c [deleted file]
arch/mips/pmc-sierra/yosemite/ht.c [deleted file]
arch/mips/pmc-sierra/yosemite/irq.c [deleted file]
arch/mips/pmc-sierra/yosemite/prom.c [deleted file]
arch/mips/pmc-sierra/yosemite/py-console.c [deleted file]
arch/mips/pmc-sierra/yosemite/setup.c [deleted file]
arch/mips/pmc-sierra/yosemite/setup.h [deleted file]
arch/mips/pmc-sierra/yosemite/smp.c [deleted file]
arch/mips/powertv/init.c
arch/mips/rb532/prom.c
arch/mips/sgi-ip22/ip22-eisa.c
arch/mips/sibyte/Kconfig
arch/mips/sni/setup.c
arch/mips/txx9/generic/pci.c
arch/mips/wrppmc/pci.c
arch/mn10300/mm/pgtable.c
arch/openrisc/Kconfig
arch/powerpc/include/asm/Kbuild
arch/powerpc/include/asm/epapr_hcalls.h
arch/powerpc/include/asm/fsl_hcalls.h
arch/powerpc/include/asm/kvm_asm.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/include/asm/kvm_booke_hv_asm.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_para.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/oprofile_impl.h
arch/powerpc/include/asm/pte-hash64-64k.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/smu.h
arch/powerpc/include/uapi/asm/Kbuild
arch/powerpc/include/uapi/asm/epapr_hcalls.h [new file with mode: 0644]
arch/powerpc/include/uapi/asm/kvm.h
arch/powerpc/include/uapi/asm/kvm_para.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/epapr_hcalls.S
arch/powerpc/kernel/epapr_paravirt.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kvm/44x.c
arch/powerpc/kvm/44x_emulate.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/Makefile
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_emulate.c
arch/powerpc/kvm/book3s_exports.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_ras.c [new file with mode: 0644]
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_mmu_hpte.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/booke.h
arch/powerpc/kvm/booke_emulate.c
arch/powerpc/kvm/bookehv_interrupts.S
arch/powerpc/kvm/e500.h
arch/powerpc/kvm/e500_emulate.c
arch/powerpc/kvm/e500_tlb.c
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/kvm/trace.h
arch/powerpc/mm/fault.c
arch/powerpc/mm/slice.c
arch/powerpc/platforms/52xx/mpc52xx_gpt.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_soc.c
arch/s390/Kbuild
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/crypto/aes_s390.c
arch/s390/crypto/des_s390.c
arch/s390/crypto/ghash_s390.c
arch/s390/crypto/sha_common.c
arch/s390/include/asm/bitops.h
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/ccwgroup.h
arch/s390/include/asm/clp.h [new file with mode: 0644]
arch/s390/include/asm/dma-mapping.h [new file with mode: 0644]
arch/s390/include/asm/dma.h
arch/s390/include/asm/hw_irq.h [new file with mode: 0644]
arch/s390/include/asm/io.h
arch/s390/include/asm/irq.h
arch/s390/include/asm/isc.h
arch/s390/include/asm/page.h
arch/s390/include/asm/pci.h
arch/s390/include/asm/pci_clp.h [new file with mode: 0644]
arch/s390/include/asm/pci_dma.h [new file with mode: 0644]
arch/s390/include/asm/pci_insn.h [new file with mode: 0644]
arch/s390/include/asm/pci_io.h [new file with mode: 0644]
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/sclp.h
arch/s390/include/asm/topology.h
arch/s390/include/asm/vga.h [new file with mode: 0644]
arch/s390/kernel/Makefile
arch/s390/kernel/dis.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/irq.c
arch/s390/kernel/pgm_check.S [new file with mode: 0644]
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/topology.c
arch/s390/kernel/traps.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/Makefile
arch/s390/mm/dump_pagetables.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/pageattr.c
arch/s390/mm/pgtable.c
arch/s390/mm/vmem.c
arch/s390/net/bpf_jit_comp.c
arch/s390/pci/Makefile [new file with mode: 0644]
arch/s390/pci/pci.c [new file with mode: 0644]
arch/s390/pci/pci_clp.c [new file with mode: 0644]
arch/s390/pci/pci_dma.c [new file with mode: 0644]
arch/s390/pci/pci_event.c [new file with mode: 0644]
arch/s390/pci/pci_msi.c [new file with mode: 0644]
arch/s390/pci/pci_sysfs.c [new file with mode: 0644]
arch/sh/boards/board-espt.c
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
arch/sh/boards/mach-kfr2r09/setup.c
arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
arch/sh/mm/fault.c
arch/x86/Kconfig
arch/x86/boot/.gitignore
arch/x86/boot/compressed/eboot.c
arch/x86/crypto/Makefile
arch/x86/crypto/camellia-aesni-avx-asm_64.S [new file with mode: 0644]
arch/x86/crypto/camellia_aesni_avx_glue.c [new file with mode: 0644]
arch/x86/crypto/camellia_glue.c
arch/x86/crypto/cast5-avx-x86_64-asm_64.S
arch/x86/crypto/cast5_avx_glue.c
arch/x86/crypto/cast6-avx-x86_64-asm_64.S
arch/x86/crypto/cast6_avx_glue.c
arch/x86/crypto/crc32c-intel.c [deleted file]
arch/x86/crypto/crc32c-intel_glue.c [new file with mode: 0644]
arch/x86/crypto/crc32c-pcl-intel-asm_64.S [new file with mode: 0644]
arch/x86/crypto/glue_helper-asm-avx.S [new file with mode: 0644]
arch/x86/crypto/glue_helper.c
arch/x86/crypto/serpent-avx-x86_64-asm_64.S
arch/x86/crypto/serpent_avx_glue.c
arch/x86/crypto/serpent_sse2_glue.c
arch/x86/crypto/twofish-avx-x86_64-asm_64.S
arch/x86/crypto/twofish_avx_glue.c
arch/x86/crypto/twofish_glue_3way.c
arch/x86/include/asm/Kbuild
arch/x86/include/asm/a.out.h [deleted file]
arch/x86/include/asm/auxvec.h [deleted file]
arch/x86/include/asm/bitsperlong.h [deleted file]
arch/x86/include/asm/boot.h
arch/x86/include/asm/bootparam.h [deleted file]
arch/x86/include/asm/byteorder.h [deleted file]
arch/x86/include/asm/clocksource.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/crypto/camellia.h [new file with mode: 0644]
arch/x86/include/asm/crypto/glue_helper.h
arch/x86/include/asm/crypto/serpent-avx.h
arch/x86/include/asm/crypto/twofish.h
arch/x86/include/asm/debugreg.h
arch/x86/include/asm/e820.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/errno.h [deleted file]
arch/x86/include/asm/fcntl.h [deleted file]
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/hw_breakpoint.h
arch/x86/include/asm/hyperv.h [deleted file]
arch/x86/include/asm/ioctl.h [deleted file]
arch/x86/include/asm/ioctls.h [deleted file]
arch/x86/include/asm/ipcbuf.h [deleted file]
arch/x86/include/asm/ist.h
arch/x86/include/asm/kexec.h
arch/x86/include/asm/kvm.h [deleted file]
arch/x86/include/asm/kvm_guest.h [new file with mode: 0644]
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/kvm_para.h
arch/x86/include/asm/ldt.h [deleted file]
arch/x86/include/asm/mce.h
arch/x86/include/asm/mman.h [deleted file]
arch/x86/include/asm/msgbuf.h [deleted file]
arch/x86/include/asm/msr-index.h [deleted file]
arch/x86/include/asm/msr.h
arch/x86/include/asm/mtrr.h
arch/x86/include/asm/numachip/numachip.h [new file with mode: 0644]
arch/x86/include/asm/param.h [deleted file]
arch/x86/include/asm/pci.h
arch/x86/include/asm/perf_regs.h [deleted file]
arch/x86/include/asm/poll.h [deleted file]
arch/x86/include/asm/posix_types.h
arch/x86/include/asm/posix_types_32.h [deleted file]
arch/x86/include/asm/posix_types_64.h [deleted file]
arch/x86/include/asm/posix_types_x32.h [deleted file]
arch/x86/include/asm/prctl.h [deleted file]
arch/x86/include/asm/processor-flags.h
arch/x86/include/asm/ptrace-abi.h [deleted file]
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/pvclock.h
arch/x86/include/asm/resource.h [deleted file]
arch/x86/include/asm/sembuf.h [deleted file]
arch/x86/include/asm/setup.h
arch/x86/include/asm/shmbuf.h [deleted file]
arch/x86/include/asm/sigcontext.h
arch/x86/include/asm/sigcontext32.h [deleted file]
arch/x86/include/asm/siginfo.h [deleted file]
arch/x86/include/asm/signal.h
arch/x86/include/asm/socket.h [deleted file]
arch/x86/include/asm/sockios.h [deleted file]
arch/x86/include/asm/stat.h [deleted file]
arch/x86/include/asm/statfs.h [deleted file]
arch/x86/include/asm/svm.h
arch/x86/include/asm/swab.h [deleted file]
arch/x86/include/asm/termbits.h [deleted file]
arch/x86/include/asm/termios.h [deleted file]
arch/x86/include/asm/types.h [deleted file]
arch/x86/include/asm/ucontext.h [deleted file]
arch/x86/include/asm/unistd.h
arch/x86/include/asm/vm86.h
arch/x86/include/asm/vmx.h
arch/x86/include/asm/vsyscall.h
arch/x86/include/asm/xen/interface.h
arch/x86/include/uapi/asm/Kbuild
arch/x86/include/uapi/asm/a.out.h [new file with mode: 0644]
arch/x86/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/x86/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
arch/x86/include/uapi/asm/boot.h [new file with mode: 0644]
arch/x86/include/uapi/asm/bootparam.h [new file with mode: 0644]
arch/x86/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/x86/include/uapi/asm/debugreg.h [new file with mode: 0644]
arch/x86/include/uapi/asm/e820.h [new file with mode: 0644]
arch/x86/include/uapi/asm/errno.h [new file with mode: 0644]
arch/x86/include/uapi/asm/fcntl.h [new file with mode: 0644]
arch/x86/include/uapi/asm/hw_breakpoint.h [new file with mode: 0644]
arch/x86/include/uapi/asm/hyperv.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ioctl.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ipcbuf.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ist.h [new file with mode: 0644]
arch/x86/include/uapi/asm/kvm.h [new file with mode: 0644]
arch/x86/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ldt.h [new file with mode: 0644]
arch/x86/include/uapi/asm/mce.h [new file with mode: 0644]
arch/x86/include/uapi/asm/mman.h [new file with mode: 0644]
arch/x86/include/uapi/asm/msgbuf.h [new file with mode: 0644]
arch/x86/include/uapi/asm/msr-index.h [new file with mode: 0644]
arch/x86/include/uapi/asm/msr.h [new file with mode: 0644]
arch/x86/include/uapi/asm/mtrr.h [new file with mode: 0644]
arch/x86/include/uapi/asm/param.h [new file with mode: 0644]
arch/x86/include/uapi/asm/perf_regs.h [new file with mode: 0644]
arch/x86/include/uapi/asm/poll.h [new file with mode: 0644]
arch/x86/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/x86/include/uapi/asm/posix_types_32.h [new file with mode: 0644]
arch/x86/include/uapi/asm/posix_types_64.h [new file with mode: 0644]
arch/x86/include/uapi/asm/posix_types_x32.h [new file with mode: 0644]
arch/x86/include/uapi/asm/prctl.h [new file with mode: 0644]
arch/x86/include/uapi/asm/processor-flags.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ptrace-abi.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/x86/include/uapi/asm/resource.h [new file with mode: 0644]
arch/x86/include/uapi/asm/sembuf.h [new file with mode: 0644]
arch/x86/include/uapi/asm/setup.h [new file with mode: 0644]
arch/x86/include/uapi/asm/shmbuf.h [new file with mode: 0644]
arch/x86/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/x86/include/uapi/asm/sigcontext32.h [new file with mode: 0644]
arch/x86/include/uapi/asm/siginfo.h [new file with mode: 0644]
arch/x86/include/uapi/asm/signal.h [new file with mode: 0644]
arch/x86/include/uapi/asm/socket.h [new file with mode: 0644]
arch/x86/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/x86/include/uapi/asm/stat.h [new file with mode: 0644]
arch/x86/include/uapi/asm/statfs.h [new file with mode: 0644]
arch/x86/include/uapi/asm/svm.h [new file with mode: 0644]
arch/x86/include/uapi/asm/swab.h [new file with mode: 0644]
arch/x86/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/x86/include/uapi/asm/termios.h [new file with mode: 0644]
arch/x86/include/uapi/asm/types.h [new file with mode: 0644]
arch/x86/include/uapi/asm/ucontext.h [new file with mode: 0644]
arch/x86/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/x86/include/uapi/asm/vm86.h [new file with mode: 0644]
arch/x86/include/uapi/asm/vmx.h [new file with mode: 0644]
arch/x86/include/uapi/asm/vsyscall.h [new file with mode: 0644]
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/cpu/mcheck/mce-internal.h
arch/x86/kernel/cpu/mcheck/mce-severity.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/crash.c
arch/x86/kernel/kvm.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/pvclock.c
arch/x86/kernel/setup.c
arch/x86/kernel/tboot.c
arch/x86/kernel/vm86_32.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lguest/boot.c
arch/x86/mm/fault.c
arch/x86/mm/init_64.c
arch/x86/mm/pageattr.c
arch/x86/mm/pgtable.c
arch/x86/pci/Makefile
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/numachip.c [new file with mode: 0644]
arch/x86/platform/efi/efi-bgrt.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/vdso/vclock_gettime.c
arch/x86/vdso/vgetcpu.c
arch/x86/xen/Kconfig
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/suspend.c
arch/x86/xen/xen-ops.h
crypto/Kconfig
crypto/Makefile
crypto/cast5_generic.c
crypto/cast6_generic.c
crypto/cast_common.c [new file with mode: 0644]
crypto/tcrypt.c
crypto/testmgr.c
crypto/testmgr.h
crypto/vmac.c
drivers/acpi/Kconfig
drivers/acpi/acpica/dsopcode.c
drivers/acpi/osl.c
drivers/acpi/pci_bind.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_root.c
drivers/ata/ahci_platform.c
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/pata_arasan_cf.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5536.c
drivers/ata/pata_ep93xx.c
drivers/ata/pata_imx.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_mpc52xx.c
drivers/ata/pata_octeon_cf.c
drivers/ata/pata_of_platform.c
drivers/ata/pata_palmld.c
drivers/ata/pata_platform.c
drivers/ata/pata_rdc.c
drivers/ata/sata_dwc_460ex.c [changed mode: 0755->0644]
drivers/ata/sata_highbank.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_promise.c
drivers/ata/sata_sil24.c
drivers/ata/sata_sx4.c
drivers/base/core.c
drivers/base/dma-mapping.c
drivers/base/node.c
drivers/bcma/Kconfig
drivers/bcma/Makefile
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon.c
drivers/bcma/driver_gpio.c [new file with mode: 0644]
drivers/bcma/main.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ppdev.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/mvebu/Kconfig [new file with mode: 0644]
drivers/clk/mvebu/Makefile [new file with mode: 0644]
drivers/clk/mvebu/clk-core.c [new file with mode: 0644]
drivers/clk/mvebu/clk-core.h [new file with mode: 0644]
drivers/clk/mvebu/clk-cpu.c [new file with mode: 0644]
drivers/clk/mvebu/clk-cpu.h [new file with mode: 0644]
drivers/clk/mvebu/clk-gating-ctrl.c [new file with mode: 0644]
drivers/clk/mvebu/clk-gating-ctrl.h [new file with mode: 0644]
drivers/clk/mvebu/clk.c [new file with mode: 0644]
drivers/clk/spear/spear1310_clock.c
drivers/clocksource/time-armada-370-xp.c
drivers/crypto/Kconfig
drivers/crypto/picoxcell_crypto.c
drivers/crypto/s5p-sss.c
drivers/crypto/talitos.c
drivers/crypto/tegra-aes.c
drivers/dma/mv_xor.c
drivers/dma/mv_xor.h
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/octeon_edac-l2c.c [new file with mode: 0644]
drivers/edac/octeon_edac-lmc.c [new file with mode: 0644]
drivers/edac/octeon_edac-pc.c [new file with mode: 0644]
drivers/edac/octeon_edac-pci.c [new file with mode: 0644]
drivers/eisa/eisa.ids
drivers/firewire/init_ohci1394_dma.c
drivers/firewire/net.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/firmware/efivars.c
drivers/gpio/Kconfig
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/vga/Kconfig
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-icade.c [new file with mode: 0644]
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-picolcd_cir.c
drivers/hid/hid-roccat-isku.c
drivers/hid/hid-roccat-isku.h
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-koneplus.h
drivers/hid/hid-roccat-kovaplus.c
drivers/hid/hid-roccat-kovaplus.h
drivers/hid/hid-roccat-lua.c [new file with mode: 0644]
drivers/hid/hid-roccat-lua.h [new file with mode: 0644]
drivers/hid/hid-roccat-pyra.c
drivers/hid/hid-roccat-pyra.h
drivers/hid/hid-roccat-savu.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/Kconfig [new file with mode: 0644]
drivers/hid/i2c-hid/Makefile [new file with mode: 0644]
drivers/hid/i2c-hid/i2c-hid.c [new file with mode: 0644]
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/i2c/busses/i2c-nuc900.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/infiniband/core/cma.c
drivers/infiniband/hw/amso1100/c2_ae.c
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/ipath/ipath_init_chip.c
drivers/infiniband/hw/mlx4/cm.c
drivers/infiniband/hw/mlx4/cq.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/user.h
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_mgt.c
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/input/input-mt.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/arizona-haptics.c [new file with mode: 0644]
drivers/irqchip/Makefile
drivers/irqchip/spear-shirq.c [new file with mode: 0644]
drivers/isdn/hisax/amd7930_fn.c
drivers/isdn/hisax/isar.c
drivers/leds/led-class.c
drivers/leds/led-triggers.c
drivers/leds/leds-88pm860x.c
drivers/leds/leds-adp5520.c
drivers/leds/leds-bd2802.c
drivers/leds/leds-clevo-mail.c
drivers/leds/leds-cobalt-qube.c
drivers/leds/leds-cobalt-raq.c
drivers/leds/leds-da903x.c
drivers/leds/leds-fsg.c
drivers/leds/leds-gpio.c
drivers/leds/leds-lm355x.c
drivers/leds/leds-lm3642.c
drivers/leds/leds-lp3944.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lt3593.c
drivers/leds/leds-net48xx.c
drivers/leds/leds-netxbig.c
drivers/leds/leds-ns2.c
drivers/leds/leds-pca955x.c
drivers/leds/leds-pwm.c
drivers/leds/leds-rb532.c
drivers/leds/leds-renesas-tpu.c
drivers/leds/leds-ss4200.c
drivers/leds/leds-wm8350.c
drivers/leds/leds-wrap.c
drivers/leds/ledtrig-backlight.c
drivers/leds/ledtrig-gpio.c
drivers/md/md.c
drivers/md/persistent-data/dm-block-manager.c
drivers/md/persistent-data/dm-btree.h
drivers/md/raid5.c
drivers/media/common/Kconfig
drivers/media/common/b2c2/Kconfig
drivers/media/common/siano/Kconfig
drivers/media/common/siano/Makefile
drivers/media/common/siano/smscoreapi.c
drivers/media/common/siano/smsir.c
drivers/media/common/siano/smsir.h
drivers/media/dvb-core/dmxdev.c
drivers/media/dvb-core/dmxdev.h
drivers/media/dvb-core/dvb-usb-ids.h
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-frontends/cx22700.c
drivers/media/dvb-frontends/cx24123.c
drivers/media/dvb-frontends/dib9000.h
drivers/media/dvb-frontends/drxd_hard.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/dvb-frontends/drxk_hard.h
drivers/media/dvb-frontends/ds3000.c
drivers/media/dvb-frontends/l64781.c
drivers/media/dvb-frontends/mt312.c
drivers/media/dvb-frontends/rtl2830.c
drivers/media/dvb-frontends/rtl2832.c
drivers/media/dvb-frontends/stb0899_drv.c
drivers/media/dvb-frontends/stv0367.c
drivers/media/dvb-frontends/tda10071.c
drivers/media/dvb-frontends/tda18271c2dd.c
drivers/media/firewire/firedtv.h
drivers/media/i2c/adp1653.c
drivers/media/i2c/adv7183.c
drivers/media/i2c/adv7604.c
drivers/media/i2c/cx25840/cx25840-core.c
drivers/media/i2c/ir-kbd-i2c.c
drivers/media/i2c/s5k4ecgx.c
drivers/media/i2c/smiapp-pll.c
drivers/media/i2c/smiapp-pll.h
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/i2c/smiapp/smiapp-limits.c
drivers/media/i2c/smiapp/smiapp-limits.h
drivers/media/i2c/smiapp/smiapp-quirk.c
drivers/media/i2c/smiapp/smiapp-quirk.h
drivers/media/i2c/smiapp/smiapp-reg-defs.h
drivers/media/i2c/smiapp/smiapp-reg.h
drivers/media/i2c/smiapp/smiapp-regs.c
drivers/media/i2c/smiapp/smiapp-regs.h
drivers/media/i2c/smiapp/smiapp.h
drivers/media/i2c/soc_camera/mt9v022.c
drivers/media/i2c/soc_camera/ov2640.c
drivers/media/i2c/vs6624.c
drivers/media/mmc/siano/Kconfig
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/cx18/cx18-alsa-main.c
drivers/media/pci/cx18/cx18-alsa-pcm.c
drivers/media/pci/cx18/cx18-i2c.c
drivers/media/pci/cx18/cx18-streams.c
drivers/media/pci/cx23885/altera-ci.c
drivers/media/pci/cx23885/cimax2.c
drivers/media/pci/cx23885/cx23885-alsa.c
drivers/media/pci/cx23885/cx23885-av.c
drivers/media/pci/cx23885/cx23885-cards.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/pci/cx23885/cx23885-f300.c
drivers/media/pci/cx23885/cx23885-input.c
drivers/media/pci/cx23885/cx23885-input.h
drivers/media/pci/cx23885/cx23885-ioctl.c
drivers/media/pci/cx23885/cx23885-ir.c
drivers/media/pci/cx23885/cx23888-ir.c
drivers/media/pci/cx23885/netup-init.c
drivers/media/pci/cx25821/cx25821-audio-upstream.c
drivers/media/pci/cx25821/cx25821-biffuncs.h
drivers/media/pci/cx25821/cx25821-i2c.c
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
drivers/media/pci/cx25821/cx25821-video-upstream.c
drivers/media/pci/cx25821/cx25821-video.c
drivers/media/pci/cx88/cx88-alsa.c
drivers/media/pci/cx88/cx88-blackbird.c
drivers/media/pci/cx88/cx88-core.c
drivers/media/pci/cx88/cx88-input.c
drivers/media/pci/cx88/cx88-mpeg.c
drivers/media/pci/cx88/cx88.h
drivers/media/pci/dm1105/dm1105.c
drivers/media/pci/ivtv/ivtv-alsa-main.c
drivers/media/pci/ivtv/ivtv-alsa-pcm.c
drivers/media/pci/ivtv/ivtv-alsa-pcm.h
drivers/media/pci/ivtv/ivtv-firmware.c
drivers/media/pci/ivtv/ivtv-i2c.c
drivers/media/pci/ivtv/ivtv-ioctl.c
drivers/media/pci/mantis/mantis_input.c
drivers/media/pci/mantis/mantis_uart.c
drivers/media/pci/mantis/mantis_vp1033.c
drivers/media/pci/meye/meye.c
drivers/media/pci/ngene/ngene-cards.c
drivers/media/pci/ngene/ngene-core.c
drivers/media/pci/saa7134/saa7134-core.c
drivers/media/pci/saa7134/saa7134-input.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/pci/saa7164/saa7164-api.c
drivers/media/pci/saa7164/saa7164-bus.c
drivers/media/pci/saa7164/saa7164-cmd.c
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/pci/saa7164/saa7164-encoder.c
drivers/media/pci/saa7164/saa7164-fw.c
drivers/media/pci/saa7164/saa7164-vbi.c
drivers/media/pci/ttpci/av7110.h
drivers/media/pci/ttpci/budget-av.c
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/blackfin/bfin_capture.c
drivers/media/platform/coda.c
drivers/media/platform/davinci/Kconfig
drivers/media/platform/davinci/dm355_ccdc.c
drivers/media/platform/davinci/dm644x_ccdc.c
drivers/media/platform/davinci/isif.c
drivers/media/platform/davinci/vpbe.c
drivers/media/platform/davinci/vpbe_display.c
drivers/media/platform/davinci/vpbe_osd.c
drivers/media/platform/davinci/vpif.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/exynos-gsc/gsc-m2m.c
drivers/media/platform/fsl-viu.c
drivers/media/platform/m2m-deinterlace.c
drivers/media/platform/mem2mem_testdev.c
drivers/media/platform/mx2_emmaprp.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/omap/omap_voutlib.c
drivers/media/platform/omap/omap_voutlib.h
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/isp.h
drivers/media/platform/omap3isp/ispcsi2.c
drivers/media/platform/omap3isp/ispcsiphy.c
drivers/media/platform/omap3isp/ispcsiphy.h
drivers/media/platform/omap3isp/isphist.c
drivers/media/platform/omap3isp/isppreview.c
drivers/media/platform/omap3isp/ispreg.h
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispstat.h
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s3c-camif/Makefile [new file with mode: 0644]
drivers/media/platform/s3c-camif/camif-capture.c [new file with mode: 0644]
drivers/media/platform/s3c-camif/camif-core.c [new file with mode: 0644]
drivers/media/platform/s3c-camif/camif-core.h [new file with mode: 0644]
drivers/media/platform/s3c-camif/camif-regs.c [new file with mode: 0644]
drivers/media/platform/s3c-camif/camif-regs.h [new file with mode: 0644]
drivers/media/platform/s5p-fimc/fimc-capture.c
drivers/media/platform/s5p-fimc/fimc-m2m.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/soc_camera/Kconfig
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/platform/vivi.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-isa.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/si4713-i2c.c
drivers/media/radio/wl128x/fmdrv.h
drivers/media/radio/wl128x/fmdrv_common.c
drivers/media/radio/wl128x/fmdrv_rx.c
drivers/media/rc/ati_remote.c
drivers/media/rc/ene_ir.c
drivers/media/rc/fintek-cir.c
drivers/media/rc/gpio-ir-recv.c
drivers/media/rc/iguanair.c
drivers/media/rc/imon.c
drivers/media/rc/ir-jvc-decoder.c
drivers/media/rc/ir-lirc-codec.c
drivers/media/rc/ir-mce_kbd-decoder.c
drivers/media/rc/ir-nec-decoder.c
drivers/media/rc/ir-rc5-decoder.c
drivers/media/rc/ir-rc5-sz-decoder.c
drivers/media/rc/ir-rc6-decoder.c
drivers/media/rc/ir-rx51.c
drivers/media/rc/ir-sanyo-decoder.c
drivers/media/rc/ir-sony-decoder.c
drivers/media/rc/ite-cir.c
drivers/media/rc/keymaps/rc-imon-mce.c
drivers/media/rc/keymaps/rc-rc6-mce.c
drivers/media/rc/mceusb.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/nuvoton-cir.h
drivers/media/rc/rc-loopback.c
drivers/media/rc/rc-main.c
drivers/media/rc/redrat3.c
drivers/media/rc/streamzap.c
drivers/media/rc/ttusbir.c
drivers/media/rc/winbond-cir.c
drivers/media/tuners/fc2580.c
drivers/media/tuners/max2165.c
drivers/media/tuners/tua9001.c
drivers/media/tuners/xc4000.c
drivers/media/usb/au0828/au0828-cards.c
drivers/media/usb/au0828/au0828-dvb.c
drivers/media/usb/au0828/au0828-video.c
drivers/media/usb/cx231xx/cx231xx-avcore.c
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/cx231xx/cx231xx-i2c.c
drivers/media/usb/cx231xx/cx231xx-input.c
drivers/media/usb/dvb-usb-v2/af9015.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/anysee.c
drivers/media/usb/dvb-usb-v2/az6007.c
drivers/media/usb/dvb-usb-v2/dvb_usb.h
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
drivers/media/usb/dvb-usb-v2/it913x.c
drivers/media/usb/dvb-usb-v2/lmedm04.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/dvb-usb-v2/usb_urb.c
drivers/media/usb/dvb-usb/az6027.c
drivers/media/usb/dvb-usb/dib0700.h
drivers/media/usb/dvb-usb/dib0700_core.c
drivers/media/usb/dvb-usb/dib0700_devices.c
drivers/media/usb/dvb-usb/dvb-usb.h
drivers/media/usb/dvb-usb/pctv452e.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/dvb-usb/ttusb2.c
drivers/media/usb/dvb-usb/vp702x.c
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx-dvb.c
drivers/media/usb/em28xx/em28xx-input.c
drivers/media/usb/em28xx/em28xx.h
drivers/media/usb/gspca/gspca.c
drivers/media/usb/gspca/gspca.h
drivers/media/usb/gspca/jeilinj.c
drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
drivers/media/usb/gspca/pac7302.c
drivers/media/usb/gspca/sonixb.c
drivers/media/usb/hdpvr/hdpvr-core.c
drivers/media/usb/hdpvr/hdpvr-i2c.c
drivers/media/usb/pvrusb2/pvrusb2-hdw.c
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
drivers/media/usb/pwc/pwc-ctrl.c
drivers/media/usb/pwc/pwc-if.c
drivers/media/usb/s2255/s2255drv.c
drivers/media/usb/siano/Kconfig
drivers/media/usb/sn9c102/sn9c102_core.c
drivers/media/usb/stk1160/stk1160-i2c.c
drivers/media/usb/stk1160/stk1160-video.c
drivers/media/usb/stk1160/stk1160.h
drivers/media/usb/stkwebcam/stk-webcam.c
drivers/media/usb/tlg2300/pd-dvb.c
drivers/media/usb/tlg2300/pd-video.c
drivers/media/usb/tm6000/tm6000-input.c
drivers/media/usb/tm6000/tm6000-video.c
drivers/media/usb/usbvision/usbvision.h
drivers/media/usb/uvc/uvc_ctrl.c
drivers/media/usb/uvc/uvc_driver.c
drivers/media/usb/uvc/uvc_entity.c
drivers/media/usb/uvc/uvc_queue.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/usb/uvc/uvcvideo.h
drivers/media/usb/zr364xx/zr364xx.c
drivers/media/v4l2-core/Kconfig
drivers/media/v4l2-core/v4l2-common.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-dev.c
drivers/media/v4l2-core/v4l2-event.c
drivers/media/v4l2-core/v4l2-fh.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/media/v4l2-core/videobuf-core.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-memops.c
drivers/media/v4l2-core/videobuf2-vmalloc.c
drivers/message/i2o/README.ioctl
drivers/message/i2o/i2o_block.c
drivers/message/i2o/i2o_config.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-core.c
drivers/mfd/arizona-core.c
drivers/mfd/max8997.c
drivers/mfd/tps6586x.c
drivers/mfd/wm5102-tables.c
drivers/mfd/wm8994-core.c
drivers/misc/atmel-ssc.c
drivers/mmc/host/Kconfig
drivers/mtd/maps/plat-ram.c
drivers/mtd/nand/s3c2410.c
drivers/net/bonding/bonding.h
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/marvell/Kconfig
drivers/net/ethernet/marvell/Makefile
drivers/net/ethernet/marvell/mvmdio.c [new file with mode: 0644]
drivers/net/ethernet/marvell/mvneta.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_cq.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/fw.h
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
drivers/net/sungem_phy.c
drivers/net/tun.c
drivers/net/wimax/i2400m/debugfs.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/atmel.c
drivers/net/wireless/ipw2x00/ipw2100.h
drivers/net/wireless/iwlegacy/4965.h
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/common.h
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/of/Kconfig
drivers/of/base.c
drivers/pci/bus.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/s390_pci_hpc.c [new file with mode: 0644]
drivers/pci/ioapic.c
drivers/pci/iov.c
drivers/pci/irq.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-stub.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/xen-pcifront.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/ab8500_bmdata.c [new file with mode: 0644]
drivers/power/ab8500_btemp.c
drivers/power/ab8500_charger.c
drivers/power/ab8500_fg.c
drivers/power/abx500_chargalg.c
drivers/power/bq2415x_charger.c [new file with mode: 0644]
drivers/power/bq27x00_battery.c
drivers/power/ds2782_battery.c
drivers/power/generic-adc-battery.c
drivers/power/jz4740-battery.c
drivers/power/lp8788-charger.c
drivers/power/max17042_battery.c
drivers/power/max8925_power.c
drivers/power/power_supply_core.c
drivers/power/power_supply_sysfs.c
drivers/power/rx51_battery.c [new file with mode: 0644]
drivers/power/twl4030_charger.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3711-regulator.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9055-regulator.c [new file with mode: 0644]
drivers/regulator/db8500-prcmu.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/dummy.c
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/lp872x.c
drivers/regulator/lp8788-buck.c
drivers/regulator/lp8788-ldo.c
drivers/regulator/max1586.c
drivers/regulator/max77686.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/max8952.c
drivers/regulator/max8973-regulator.c [new file with mode: 0644]
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/tps51632-regulator.c [new file with mode: 0644]
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65912-regulator.c
drivers/regulator/tps80031-regulator.c [new file with mode: 0644]
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c [new file with mode: 0644]
drivers/regulator/virtual.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
drivers/remoteproc/remoteproc_elf_loader.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-s3c.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/char/sclp.h
drivers/s390/char/sclp_cmd.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/chsc.c
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_ops.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype50.h
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/be2iscsi/be.h
drivers/scsi/be2iscsi/be_cmds.c
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_iscsi.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/be2iscsi/be_mgmt.h
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/csiostor/Kconfig [new file with mode: 0644]
drivers/scsi/csiostor/Makefile [new file with mode: 0644]
drivers/scsi/csiostor/csio_attr.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_defs.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_hw.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_hw.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_init.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_init.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_isr.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_lnode.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_lnode.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_mb.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_mb.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_rnode.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_rnode.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_scsi.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_scsi.h [new file with mode: 0644]
drivers/scsi/csiostor/csio_wr.c [new file with mode: 0644]
drivers/scsi/csiostor/csio_wr.h [new file with mode: 0644]
drivers/scsi/csiostor/t4fw_api_stor.h [new file with mode: 0644]
drivers/scsi/hptiop.c
drivers/scsi/hptiop.h
drivers/scsi/libsas/sas_expander.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.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_sli.h
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/mpt3sas/Kconfig [new file with mode: 0644]
drivers/scsi/mpt3sas/Makefile [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_init.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_ioc.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_raid.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_sas.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_tool.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpi/mpi2_type.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_base.c [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_base.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_config.c [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_ctl.c [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_ctl.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_debug.h [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_scsih.c [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_transport.c [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c [new file with mode: 0644]
drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h [new file with mode: 0644]
drivers/scsi/mvsas/mv_94xx.h
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/osd/osd_uld.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/scsi_pm.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/scsi_transport_srp.c
drivers/scsi/sd.c
drivers/scsi/virtio_scsi.c
drivers/sh/clk/cpg.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-bitbang.c
drivers/spi/spi-clps711x.c [new file with mode: 0644]
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-dw.c
drivers/spi/spi-ep93xx.c
drivers/spi/spi-falcon.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-fsl-lib.c
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-imx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mpc52xx-psc.c
drivers/spi/spi-mpc52xx.c
drivers/spi/spi-mxs.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-octeon.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pl022.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh.c
drivers/spi/spi-sirf.c
drivers/spi/spi-stmp.c [deleted file]
drivers/spi/spi-tegra20-sflash.c [new file with mode: 0644]
drivers/spi/spi-tegra20-slink.c [new file with mode: 0644]
drivers/spi/spi-ti-ssp.c
drivers/spi/spi-tle62x0.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-xcomm.c
drivers/spi/spi-xilinx.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/ssb/Kconfig
drivers/ssb/Makefile
drivers/ssb/driver_chipcommon.c
drivers/ssb/driver_extif.c
drivers/ssb/driver_gpio.c [new file with mode: 0644]
drivers/ssb/main.c
drivers/ssb/ssb_private.h
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/media/dt3155v4l/dt3155v4l.c
drivers/staging/media/go7007/go7007-fw.c
drivers/staging/media/go7007/go7007-v4l2.c
drivers/staging/media/go7007/s2250-board.c
drivers/staging/media/go7007/wis-ov7640.c
drivers/staging/media/go7007/wis-saa7113.c
drivers/staging/media/go7007/wis-saa7115.c
drivers/staging/media/go7007/wis-sony-tuner.c
drivers/staging/media/go7007/wis-tw2804.c
drivers/staging/media/go7007/wis-tw9903.c
drivers/staging/media/go7007/wis-uda1342.c
drivers/staging/media/lirc/lirc_serial.c
drivers/staging/omapdrm/omap_drv.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_util.c
drivers/thermal/Kconfig
drivers/tty/Kconfig
drivers/tty/hvc/hvc_opal.c
drivers/tty/hvc/hvc_vio.c
drivers/tty/ipwireless/setup_protocol.h
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/bfin_uart.c
drivers/tty/serial/icom.c
drivers/usb/core/driver.c
drivers/usb/gadget/at91_udc.c
drivers/usb/storage/realtek_cr.c
drivers/vhost/tcm_vhost.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/console/newport_con.c
drivers/video/console/softcursor.c
drivers/video/da8xx-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/fsl-diu-fb.c
drivers/video/omap2/Kconfig
drivers/video/omap2/Makefile
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-compat.c [new file with mode: 0644]
drivers/video/omap2/dss/dispc-compat.h [new file with mode: 0644]
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/display-sysfs.c [new file with mode: 0644]
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.c
drivers/video/omap2/dss/output.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/ti_hdmi.h
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/dss/venc_panel.c
drivers/video/omap2/omapfb/Kconfig
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb-sysfs.c
drivers/video/omap2/omapfb/omapfb.h
drivers/video/omap2/vram.c [deleted file]
drivers/video/s3c-fb.c
drivers/video/sh_mipi_dsi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_lcdcfb.h
drivers/video/ssd1307fb.c [new file with mode: 0644]
drivers/virt/Kconfig
drivers/watchdog/booke_wdt.c
drivers/xen/Kconfig
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/privcmd.c
drivers/xen/xen-acpi-pad.c [new file with mode: 0644]
drivers/xen/xen-pciback/pci_stub.c
drivers/xen/xenbus/xenbus_xs.c
fs/autofs4/expire.c
fs/autofs4/root.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_map.c
fs/btrfs/ordered-data.h
fs/btrfs/volumes.c
fs/buffer.c
fs/cifs/README
fs/ext4/ext4.h
fs/fhandle.c
fs/fs-writeback.c
fs/gfs2/aops.c
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/lock_dlm.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/gfs2/rgrp.h
fs/gfs2/trace_gfs2.h
fs/gfs2/xattr.c
fs/hugetlbfs/inode.c
fs/jbd/transaction.c
fs/jbd2/transaction.c
fs/logfs/inode.c
fs/ncpfs/mmap.c
fs/notify/fanotify/Kconfig
fs/notify/notification.c
fs/proc/kcore.c
fs/proc/task_mmu.c
fs/pstore/ftrace.c
fs/pstore/ram.c
include/acpi/acpi_drivers.h
include/asm-generic/io.h
include/asm-generic/pgtable.h
include/crypto/cast5.h
include/crypto/cast6.h
include/crypto/cast_common.h [new file with mode: 0644]
include/crypto/vmac.h
include/linux/acpi.h
include/linux/ata_platform.h
include/linux/atmel-ssc.h
include/linux/bcma/bcma_driver_chipcommon.h
include/linux/bootmem.h
include/linux/clk/mvebu.h [new file with mode: 0644]
include/linux/cpuset.h
include/linux/device.h
include/linux/dlm.h
include/linux/dvb/Kbuild [deleted file]
include/linux/dvb/dmx.h [deleted file]
include/linux/dvb/video.h [deleted file]
include/linux/earlycpio.h [new file with mode: 0644]
include/linux/efi.h
include/linux/fsl-diu-fb.h
include/linux/gfp.h
include/linux/hash.h
include/linux/hid-sensor-ids.h
include/linux/hid.h
include/linux/huge_mm.h
include/linux/i2c/i2c-hid.h [new file with mode: 0644]
include/linux/input/mt.h
include/linux/ipmi_smi.h
include/linux/irq.h
include/linux/irqchip/spear-shirq.h [new file with mode: 0644]
include/linux/kvm_host.h
include/linux/leds.h
include/linux/libata.h
include/linux/lru_cache.h
include/linux/memcontrol.h
include/linux/memory.h
include/linux/mfd/abx500.h
include/linux/mfd/arizona/core.h
include/linux/mfd/arizona/pdata.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/da9055/pdata.h
include/linux/mfd/lp8788.h
include/linux/mfd/max8997-private.h
include/linux/mfd/max8997.h
include/linux/mfd/tps65090.h
include/linux/mfd/tps6586x.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h
include/linux/miscdevice.h
include/linux/mlx4/device.h
include/linux/mmzone.h
include/linux/netdevice.h
include/linux/nodemask.h
include/linux/of.h
include/linux/of_i2c.h
include/linux/pci.h
include/linux/platform_data/asoc-s3c.h
include/linux/platform_data/davinci_asp.h
include/linux/platform_data/dma-mv_xor.h
include/linux/platform_data/omap-twl4030.h
include/linux/platform_data/spi-clps711x.h [new file with mode: 0644]
include/linux/platform_data/spi-omap2-mcspi.h
include/linux/power/bq2415x_charger.h [new file with mode: 0644]
include/linux/power_supply.h
include/linux/pvclock_gtod.h [new file with mode: 0644]
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/max8973-regulator.h [new file with mode: 0644]
include/linux/regulator/tps51632-regulator.h [new file with mode: 0644]
include/linux/regulator/tps65090-regulator.h [deleted file]
include/linux/res_counter.h
include/linux/sched.h
include/linux/spi/spi-tegra.h [new file with mode: 0644]
include/linux/spi/spi.h
include/linux/ssb/ssb.h
include/linux/ssb/ssb_driver_chipcommon.h
include/linux/ssb/ssb_driver_extif.h
include/linux/stmmac.h
include/linux/vgaarb.h
include/linux/vm_event_item.h
include/linux/watchdog.h
include/media/adp1653.h
include/media/davinci/vpbe_display.h
include/media/davinci/vpbe_osd.h
include/media/ir-kbd-i2c.h
include/media/mt9v022.h [new file with mode: 0644]
include/media/rc-core.h
include/media/rc-map.h
include/media/s3c_camif.h [new file with mode: 0644]
include/media/smiapp.h
include/media/v4l2-event.h
include/media/v4l2-fh.h
include/media/v4l2-ioctl.h
include/media/v4l2-mem2mem.h
include/media/videobuf2-core.h
include/media/videobuf2-memops.h
include/net/irda/irlmp.h
include/net/sock.h
include/rdma/Kbuild
include/rdma/ib_user_cm.h [deleted file]
include/rdma/ib_user_mad.h [deleted file]
include/rdma/ib_user_sa.h [deleted file]
include/rdma/ib_user_verbs.h [deleted file]
include/rdma/rdma_netlink.h
include/rdma/rdma_user_cm.h [deleted file]
include/scsi/scsi_device.h
include/scsi/scsi_transport_sas.h
include/scsi/scsi_transport_srp.h
include/sound/Kbuild
include/sound/asequencer.h
include/sound/asound.h
include/sound/asound_fm.h [deleted file]
include/sound/compress_offload.h [deleted file]
include/sound/compress_params.h [deleted file]
include/sound/cs4271.h
include/sound/emu10k1.h
include/sound/hdsp.h [deleted file]
include/sound/hdspm.h [deleted file]
include/sound/pcm.h
include/sound/sb16_csp.h
include/sound/sfnt_info.h [deleted file]
include/sound/sh_fsi.h
include/sound/tlv320aic32x4.h
include/sound/vx_core.h
include/uapi/linux/ethtool.h
include/uapi/linux/input.h
include/uapi/linux/kvm.h
include/uapi/linux/magic.h
include/uapi/linux/pci_regs.h
include/uapi/linux/videodev2.h
include/uapi/rdma/Kbuild
include/uapi/rdma/ib_user_cm.h [new file with mode: 0644]
include/uapi/rdma/ib_user_mad.h [new file with mode: 0644]
include/uapi/rdma/ib_user_sa.h [new file with mode: 0644]
include/uapi/rdma/ib_user_verbs.h [new file with mode: 0644]
include/uapi/rdma/rdma_netlink.h [new file with mode: 0644]
include/uapi/rdma/rdma_user_cm.h [new file with mode: 0644]
include/uapi/sound/Kbuild
include/uapi/sound/asequencer.h [new file with mode: 0644]
include/uapi/sound/asound.h [new file with mode: 0644]
include/uapi/sound/asound_fm.h [new file with mode: 0644]
include/uapi/sound/compress_offload.h [new file with mode: 0644]
include/uapi/sound/compress_params.h [new file with mode: 0644]
include/uapi/sound/emu10k1.h [new file with mode: 0644]
include/uapi/sound/hdsp.h [new file with mode: 0644]
include/uapi/sound/hdspm.h [new file with mode: 0644]
include/uapi/sound/sb16_csp.h [new file with mode: 0644]
include/uapi/sound/sfnt_info.h [new file with mode: 0644]
include/video/da8xx-fb.h
include/video/omapdss.h
include/video/samsung_fimd.h
include/video/sh_mipi_dsi.h
include/video/sh_mobile_lcdc.h
include/xen/interface/memory.h
include/xen/interface/platform.h
include/xen/xen-ops.h
init/main.c
kernel/cpuset.c
kernel/kthread.c
kernel/padata.c
kernel/pid.c
kernel/profile.c
kernel/res_counter.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/time/timekeeping.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_functions.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
kernel/wait.c
lib/Kconfig.debug
lib/Makefile
lib/bitmap.c
lib/earlycpio.c [new file with mode: 0644]
mm/Kconfig
mm/bootmem.c
mm/compaction.c
mm/huge_memory.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/migrate.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/nobootmem.c
mm/oom_kill.c
mm/page_alloc.c
mm/page_cgroup.c
mm/pagewalk.c
mm/rmap.c
mm/shmem.c
mm/util.c
mm/vmscan.c
mm/vmstat.c
net/bluetooth/hidp/core.c
net/bridge/br_multicast.c
net/can/proc.c
net/ipv4/tcp_cong.c
net/ipv6/ndisc.c
net/mac80211/driver-ops.h
net/netfilter/nf_log.c
net/nfc/llcp/sock.c
net/rfkill/core.c
net/sctp/endpointola.c
net/sctp/sm_statefuns.c
scripts/kernel-doc
security/keys/process_keys.c
sound/arm/aaci.c
sound/arm/pxa2xx-ac97-lib.c
sound/arm/pxa2xx-ac97.c
sound/atmel/abdac.c
sound/atmel/ac97c.c
sound/core/oss/pcm_plugin.c
sound/core/pcm.c
sound/core/pcm_compat.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/core/seq/seq_device.c
sound/drivers/Kconfig
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/ml403-ac97cr.c
sound/drivers/mpu401/mpu401.c
sound/drivers/mtpav.c
sound/drivers/mts64.c
sound/drivers/pcsp/pcsp.c
sound/drivers/pcsp/pcsp_input.c
sound/drivers/pcsp/pcsp_input.h
sound/drivers/pcsp/pcsp_lib.c
sound/drivers/pcsp/pcsp_mixer.c
sound/drivers/portman2x4.c
sound/drivers/serial-u16550.c
sound/drivers/virmidi.c
sound/drivers/vx/vx_hwdep.c
sound/firewire/Kconfig
sound/firewire/Makefile
sound/firewire/scs1x.c [new file with mode: 0644]
sound/firewire/speakers.c
sound/isa/Kconfig
sound/isa/ad1816a/ad1816a.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/als100.c
sound/isa/azt2320.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd.h
sound/isa/msnd/msnd_pinnacle.c
sound/isa/msnd/msnd_pinnacle_mixer.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/emu8000.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb8.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/isa/wavefront/wavefront_fx.c
sound/isa/wavefront/wavefront_midi.c
sound/isa/wavefront/wavefront_synth.c
sound/mips/au1x00.c
sound/mips/hal2.c
sound/mips/sgio2audio.c
sound/oss/ad1848.c
sound/oss/kahlua.c
sound/oss/sb_audio.c
sound/parisc/harmony.c
sound/pci/Kconfig
sound/pci/ad1889.c
sound/pci/ak4531_codec.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/hpidspcd.c
sound/pci/asihpi/hpioctl.c
sound/pci/asihpi/hpioctl.h
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0_a3d.c
sound/pci/au88x0/au88x0_core.c
sound/pci/au88x0/au88x0_eq.c
sound/pci/au88x0/au88x0_game.c
sound/pci/au88x0/au88x0_mixer.c
sound/pci/au88x0/au88x0_mpu401.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_proc.c
sound/pci/ca0106/ca_midi.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs5530.c
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio.h
sound/pci/cs5535audio/cs5535audio_olpc.c
sound/pci/cs5535audio/cs5535audio_pcm.c
sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctatc.h
sound/pci/ctxfi/cthardware.c
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/xfi.c
sound/pci/echoaudio/echoaudio.c
sound/pci/echoaudio/echoaudio.h
sound/pci/echoaudio/midi.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1_patch.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emumpu401.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/p16v.c
sound/pci/emu10k1/timer.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/Kconfig
sound/pci/hda/Makefile
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel_trace.h [new file with mode: 0644]
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_jack.h
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/Makefile
sound/pci/ice1712/amp.c
sound/pci/ice1712/aureon.c
sound/pci/ice1712/delta.c
sound/pci/ice1712/ews.c
sound/pci/ice1712/hoontech.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/maya44.c
sound/pci/ice1712/phase.c
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/ice1712/prodigy_hifi.c
sound/pci/ice1712/psc724.c [new file with mode: 0644]
sound/pci/ice1712/psc724.h [new file with mode: 0644]
sound/pci/ice1712/quartet.c
sound/pci/ice1712/revo.c
sound/pci/ice1712/se.c
sound/pci/ice1712/vt1720_mobo.c
sound/pci/ice1712/wm8766.c [new file with mode: 0644]
sound/pci/ice1712/wm8766.h [new file with mode: 0644]
sound/pci/ice1712/wm8776.c [new file with mode: 0644]
sound/pci/ice1712/wm8776.h [new file with mode: 0644]
sound/pci/ice1712/wtm.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola.c
sound/pci/lola/lola_clock.c
sound/pci/lola/lola_mixer.c
sound/pci/lola/lola_pcm.c
sound/pci/lola/lola_proc.c
sound/pci/lx6464es/lx6464es.c
sound/pci/lx6464es/lx_core.c
sound/pci/lx6464es/lx_core.h
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/mixart/mixart_hwdep.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/virtuoso.c
sound/pci/oxygen/xonar_cs43xx.c
sound/pci/oxygen/xonar_pcm179x.c
sound/pci/oxygen/xonar_wm87x6.c
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_hwdep.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sis7019.c
sound/pci/sonicvibes.c
sound/pci/trident/trident.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/ppc/awacs.c
sound/ppc/beep.c
sound/ppc/burgundy.c
sound/ppc/daca.c
sound/ppc/keywest.c
sound/ppc/pmac.c
sound/ppc/powermac.c
sound/ppc/snd_ps3.c
sound/ppc/tumbler.c
sound/sh/aica.c
sound/sh/sh_dac_audio.c
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/atmel/atmel-pcm-dma.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm-pdc.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/atmel-pcm.h
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/atmel_ssc_dai.h
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/au1x/ac97c.c
sound/soc/au1x/db1000.c
sound/soc/au1x/db1200.c
sound/soc/au1x/dbdma2.c
sound/soc/au1x/dma.c
sound/soc/au1x/i2sc.c
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc-i2s.c
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-ac97.c
sound/soc/blackfin/bf5xx-ad1836.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-tdm-pcm.c
sound/soc/blackfin/bf5xx-tdm.c
sound/soc/blackfin/bf6xx-i2s.c
sound/soc/blackfin/bfin-eval-adau1373.c
sound/soc/blackfin/bfin-eval-adau1701.c
sound/soc/blackfin/bfin-eval-adav80x.c
sound/soc/cirrus/edb93xx.c
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/cirrus/simone.c
sound/soc/cirrus/snappercl15.c
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/ac97.c
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/ad73311.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ads117x.c
sound/soc/codecs/ak4104.c
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/ak4671.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/alc5632.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cq93vc.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/cs42l73.c
sound/soc/codecs/da7210.c
sound/soc/codecs/da732x.c
sound/soc/codecs/da9055.c
sound/soc/codecs/dfbmcs320.c
sound/soc/codecs/dmic.c
sound/soc/codecs/isabelle.c
sound/soc/codecs/jz4740.c
sound/soc/codecs/lm4857.c
sound/soc/codecs/lm49453.c
sound/soc/codecs/max9768.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98090.c [new file with mode: 0644]
sound/soc/codecs/max98095.c
sound/soc/codecs/max9850.c
sound/soc/codecs/max9877.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/ml26124.c
sound/soc/codecs/omap-hdmi.c
sound/soc/codecs/pcm3008.c
sound/soc/codecs/rt5631.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/si476x.c [new file with mode: 0644]
sound/soc/codecs/sn95031.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/sta529.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic32x4.h
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/uda134x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm0010.c
sound/soc/codecs/wm1250-ev1.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8727.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8782.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8983.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm_adsp.c [new file with mode: 0644]
sound/soc/codecs/wm_adsp.h [new file with mode: 0644]
sound/soc/codecs/wmfw.h [new file with mode: 0644]
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/eukrea-tlv320.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-audmux.c
sound/soc/fsl/imx-mc13783.c
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/mpc5200_psc_ac97.c
sound/soc/fsl/mpc5200_psc_i2s.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/mx27vis-aic32x4.c
sound/soc/fsl/p1022_ds.c
sound/soc/fsl/p1022_rdk.c [new file with mode: 0644]
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/jz4740/jz4740-pcm.c
sound/soc/jz4740/qi_lb60.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/kirkwood/kirkwood-openrd.c
sound/soc/kirkwood/kirkwood-t5325.c
sound/soc/kirkwood/kirkwood.h
sound/soc/mid-x86/mfld_machine.c
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-saif.c
sound/soc/mxs/mxs-sgtl5000.c
sound/soc/nuc900/nuc900-ac97.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/ams-delta.c
sound/soc/omap/mcbsp.c
sound/soc/omap/mcbsp.h
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-hdmi-card.c
sound/soc/omap/omap-hdmi.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-twl4030.c
sound/soc/omap/zoom2.c
sound/soc/pxa/brownstone.c
sound/soc/pxa/corgi.c
sound/soc/pxa/e740_wm9705.c
sound/soc/pxa/e750_wm9705.c
sound/soc/pxa/e800_wm9712.c
sound/soc/pxa/hx4700.c
sound/soc/pxa/imote2.c
sound/soc/pxa/mioa701_wm9713.c
sound/soc/pxa/mmp-pcm.c
sound/soc/pxa/mmp-sspa.c
sound/soc/pxa/palm27x.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/tosa.c
sound/soc/pxa/ttc-dkb.c
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/ac97.c
sound/soc/samsung/bells.c
sound/soc/samsung/dma.c
sound/soc/samsung/dma.h
sound/soc/samsung/goni_wm8994.c
sound/soc/samsung/h1940_uda1380.c
sound/soc/samsung/i2s.c
sound/soc/samsung/idma.c
sound/soc/samsung/jive_wm8750.c
sound/soc/samsung/littlemill.c
sound/soc/samsung/ln2440sbc_alc650.c
sound/soc/samsung/lowland.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/samsung/pcm.c
sound/soc/samsung/rx1950_uda1380.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/samsung/s3c24xx-i2s.c
sound/soc/samsung/s3c24xx_simtec.c
sound/soc/samsung/s3c24xx_simtec_hermes.c
sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
sound/soc/samsung/s3c24xx_uda134x.c
sound/soc/samsung/smartq_wm8987.c
sound/soc/samsung/smdk2443_wm9710.c
sound/soc/samsung/smdk_spdif.c
sound/soc/samsung/smdk_wm8580.c
sound/soc/samsung/smdk_wm8580pcm.c
sound/soc/samsung/smdk_wm8994.c
sound/soc/samsung/smdk_wm8994pcm.c
sound/soc/samsung/smdk_wm9713.c
sound/soc/samsung/spdif.c
sound/soc/samsung/speyside.c
sound/soc/samsung/tobermory.c
sound/soc/sh/dma-sh7760.c
sound/soc/sh/fsi.c
sound/soc/sh/hac.c
sound/soc/sh/siu_dai.c
sound/soc/sh/ssi.c
sound/soc/soc-cache.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-dmaengine-pcm.c
sound/soc/soc-jack.c
sound/soc/soc-pcm.c
sound/soc/soc-utils.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/tegra20_das.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra_alc5632.c
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_wm8753.c
sound/soc/tegra/tegra_wm8903.c
sound/soc/tegra/trimslice.c
sound/soc/txx9/txx9aclc-ac97.c
sound/soc/txx9/txx9aclc.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_dai.c
sound/soc/ux500/ux500_msp_dai.h
sound/soc/ux500/ux500_pcm.c
sound/soc/ux500/ux500_pcm.h
sound/sparc/amd7930.c
sound/sparc/cs4231.c
sound/sparc/dbri.c
sound/spi/at73c213.c
sound/usb/6fire/chip.c
sound/usb/6fire/comm.c
sound/usb/6fire/comm.h
sound/usb/6fire/control.c
sound/usb/6fire/control.h
sound/usb/6fire/firmware.h
sound/usb/6fire/midi.c
sound/usb/6fire/midi.h
sound/usb/6fire/pcm.c
sound/usb/6fire/pcm.h
sound/usb/Kconfig
sound/usb/caiaq/control.c
sound/usb/caiaq/device.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/format.c
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/stream.c
sound/usb/usbaudio.h
tools/firewire/nosy-dump.c
tools/perf/Documentation/perf-record.txt
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf
usr/gen_init_cpio.c
virt/kvm/assigned-dev.c
virt/kvm/eventfd.c
virt/kvm/iommu.c
virt/kvm/irq_comm.c
virt/kvm/kvm_main.c

index c2a270b45b03ae20084b33aa7295bdee8eb6c445..833fd59926a73c1f3725559400b60b598f2446fa 100644 (file)
@@ -8,3 +8,41 @@ Description:   The integer value of this attribute ranges from 0-4.
                When written, this file sets the number of the startup profile
                and the mouse activates this profile immediately.
                Please use actual_profile, it does the same thing.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns the raw integer version number of the
+               firmware reported by the mouse. Using the integer value eases
+               further usage in other programs. To receive the real version
+               number the decimal point has to be shifted 2 positions to the
+               left. E.g. a returned value of 121 means 1.21
+               This file is readonly.
+               Please read binary attribute info which contains firmware version.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When read, these files return the respective profile buttons.
+               The returned data is 77 bytes in size.
+               This file is readonly.
+               Write control to select profile and read profile_buttons instead.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When read, these files return the respective profile settings.
+               The returned data is 43 bytes in size.
+               This file is readonly.
+               Write control to select profile and read profile_settings instead.
+Users:         http://roccat.sourceforge.net
\ No newline at end of file
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
new file mode 100644 (file)
index 0000000..4a98e02
--- /dev/null
@@ -0,0 +1,66 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 1-4.
+               When read, this attribute returns the number of the active
+               cpi level.
+               This file is readonly.
+               Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 1-10.
+               When read, this attribute returns the number of the actual
+               sensitivity in x direction.
+               This file is readonly.
+               Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 1-10.
+               When read, this attribute returns the number of the actual
+               sensitivity in y direction.
+               This file is readonly.
+               Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns the raw integer version number of the
+               firmware reported by the mouse. Using the integer value eases
+               further usage in other programs. To receive the real version
+               number the decimal point has to be shifted 2 positions to the
+               left. E.g. a returned value of 121 means 1.21
+               This file is readonly.
+               Obsoleted by binary sysfs attribute "info".
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When read, these files return the respective profile buttons.
+               The returned data is 23 bytes in size.
+               This file is readonly.
+               Write control to select profile and read profile_buttons instead.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When read, these files return the respective profile settings.
+               The returned data is 16 bytes in size.
+               This file is readonly.
+               Write control to select profile and read profile_settings instead.
+Users:         http://roccat.sourceforge.net
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
new file mode 100644 (file)
index 0000000..87ac87e
--- /dev/null
@@ -0,0 +1,73 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   It is possible to switch the cpi setting of the mouse with the
+               press of a button.
+               When read, this file returns the raw number of the actual cpi
+               setting reported by the mouse. This number has to be further
+               processed to receive the real dpi value.
+
+               VALUE DPI
+               1     400
+               2     800
+               4     1600
+
+               This file is readonly.
+               Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns the number of the actual profile in
+               range 0-4.
+               This file is readonly.
+               Please use binary attribute "settings" which provides this information.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns the raw integer version number of the
+               firmware reported by the mouse. Using the integer value eases
+               further usage in other programs. To receive the real version
+               number the decimal point has to be shifted 2 positions to the
+               left. E.g. a returned value of 138 means 1.38
+               This file is readonly.
+               Please use binary attribute "info" which provides this information.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When read, these files return the respective profile buttons.
+               The returned data is 19 bytes in size.
+               This file is readonly.
+               Write control to select profile and read profile_buttons instead.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When read, these files return the respective profile settings.
+               The returned data is 13 bytes in size.
+               This file is readonly.
+               Write control to select profile and read profile_settings instead.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 0-4.
+                When read, this attribute returns the number of the profile
+                that's active when the mouse is powered on.
+               This file is readonly.
+               Please use binary attribute "settings" which provides this information.
+Users:         http://roccat.sourceforge.net
diff --git a/Documentation/ABI/stable/sysfs-driver-ib_srp b/Documentation/ABI/stable/sysfs-driver-ib_srp
new file mode 100644 (file)
index 0000000..481aae9
--- /dev/null
@@ -0,0 +1,156 @@
+What:          /sys/class/infiniband_srp/srp-<hca>-<port_number>/add_target
+Date:          January 2, 2006
+KernelVersion: 2.6.15
+Contact:       linux-rdma@vger.kernel.org
+Description:   Interface for making ib_srp connect to a new target.
+               One can request ib_srp to connect to a new target by writing
+               a comma-separated list of login parameters to this sysfs
+               attribute. The supported parameters are:
+               * id_ext, a 16-digit hexadecimal number specifying the eight
+                 byte identifier extension in the 16-byte SRP target port
+                 identifier. The target port identifier is sent by ib_srp
+                 to the target in the SRP_LOGIN_REQ request.
+               * ioc_guid, a 16-digit hexadecimal number specifying the eight
+                 byte I/O controller GUID portion of the 16-byte target port
+                 identifier.
+               * dgid, a 32-digit hexadecimal number specifying the
+                 destination GID.
+               * pkey, a four-digit hexadecimal number specifying the
+                 InfiniBand partition key.
+               * service_id, a 16-digit hexadecimal number specifying the
+                 InfiniBand service ID used to establish communication with
+                 the SRP target. How to find out the value of the service ID
+                 is specified in the documentation of the SRP target.
+               * max_sect, a decimal number specifying the maximum number of
+                 512-byte sectors to be transferred via a single SCSI command.
+               * max_cmd_per_lun, a decimal number specifying the maximum
+                 number of outstanding commands for a single LUN.
+               * io_class, a hexadecimal number specifying the SRP I/O class.
+                 Must be either 0xff00 (rev 10) or 0x0100 (rev 16a). The I/O
+                 class defines the format of the SRP initiator and target
+                 port identifiers.
+               * initiator_ext, a 16-digit hexadecimal number specifying the
+                 identifier extension portion of the SRP initiator port
+                 identifier. This data is sent by the initiator to the target
+                 in the SRP_LOGIN_REQ request.
+               * cmd_sg_entries, a number in the range 1..255 that specifies
+                 the maximum number of data buffer descriptors stored in the
+                 SRP_CMD information unit itself. With allow_ext_sg=0 the
+                 parameter cmd_sg_entries defines the maximum S/G list length
+                 for a single SRP_CMD, and commands whose S/G list length
+                 exceeds this limit after S/G list collapsing will fail.
+               * allow_ext_sg, whether ib_srp is allowed to include a partial
+                 memory descriptor list in an SRP_CMD instead of the entire
+                 list. If a partial memory descriptor list has been included
+                 in an SRP_CMD the remaining memory descriptors are
+                 communicated from initiator to target via an additional RDMA
+                 transfer. Setting allow_ext_sg to 1 increases the maximum
+                 amount of data that can be transferred between initiator and
+                 target via a single SCSI command. Since not all SRP target
+                 implementations support partial memory descriptor lists the
+                 default value for this option is 0.
+               * sg_tablesize, a number in the range 1..2048 specifying the
+                 maximum S/G list length the SCSI layer is allowed to pass to
+                 ib_srp. Specifying a value that exceeds cmd_sg_entries is
+                 only safe with partial memory descriptor list support enabled
+                 (allow_ext_sg=1).
+
+What:          /sys/class/infiniband_srp/srp-<hca>-<port_number>/ibdev
+Date:          January 2, 2006
+KernelVersion: 2.6.15
+Contact:       linux-rdma@vger.kernel.org
+Description:   HCA name (<hca>).
+
+What:          /sys/class/infiniband_srp/srp-<hca>-<port_number>/port
+Date:          January 2, 2006
+KernelVersion: 2.6.15
+Contact:       linux-rdma@vger.kernel.org
+Description:   HCA port number (<port_number>).
+
+What:          /sys/class/scsi_host/host<n>/allow_ext_sg
+Date:          May 19, 2011
+KernelVersion: 2.6.39
+Contact:       linux-rdma@vger.kernel.org
+Description:   Whether ib_srp is allowed to include a partial memory
+               descriptor list in an SRP_CMD when communicating with an SRP
+               target.
+
+What:          /sys/class/scsi_host/host<n>/cmd_sg_entries
+Date:          May 19, 2011
+KernelVersion: 2.6.39
+Contact:       linux-rdma@vger.kernel.org
+Description:   Maximum number of data buffer descriptors that may be sent to
+               the target in a single SRP_CMD request.
+
+What:          /sys/class/scsi_host/host<n>/dgid
+Date:          June 17, 2006
+KernelVersion: 2.6.17
+Contact:       linux-rdma@vger.kernel.org
+Description:   InfiniBand destination GID used for communication with the SRP
+               target. Differs from orig_dgid if port redirection has happened.
+
+What:          /sys/class/scsi_host/host<n>/id_ext
+Date:          June 17, 2006
+KernelVersion: 2.6.17
+Contact:       linux-rdma@vger.kernel.org
+Description:   Eight-byte identifier extension portion of the 16-byte target
+               port identifier.
+
+What:          /sys/class/scsi_host/host<n>/ioc_guid
+Date:          June 17, 2006
+KernelVersion: 2.6.17
+Contact:       linux-rdma@vger.kernel.org
+Description:   Eight-byte I/O controller GUID portion of the 16-byte target
+               port identifier.
+
+What:          /sys/class/scsi_host/host<n>/local_ib_device
+Date:          November 29, 2006
+KernelVersion: 2.6.19
+Contact:       linux-rdma@vger.kernel.org
+Description:   Name of the InfiniBand HCA used for communicating with the
+               SRP target.
+
+What:          /sys/class/scsi_host/host<n>/local_ib_port
+Date:          November 29, 2006
+KernelVersion: 2.6.19
+Contact:       linux-rdma@vger.kernel.org
+Description:   Number of the HCA port used for communicating with the
+               SRP target.
+
+What:          /sys/class/scsi_host/host<n>/orig_dgid
+Date:          June 17, 2006
+KernelVersion: 2.6.17
+Contact:       linux-rdma@vger.kernel.org
+Description:   InfiniBand destination GID specified in the parameters
+               written to the add_target sysfs attribute.
+
+What:          /sys/class/scsi_host/host<n>/pkey
+Date:          June 17, 2006
+KernelVersion: 2.6.17
+Contact:       linux-rdma@vger.kernel.org
+Description:   A 16-bit number representing the InfiniBand partition key used
+               for communication with the SRP target.
+
+What:          /sys/class/scsi_host/host<n>/req_lim
+Date:          October 20, 2010
+KernelVersion: 2.6.36
+Contact:       linux-rdma@vger.kernel.org
+Description:   Number of requests ib_srp can send to the target before it has
+               to wait for more credits. For more information see also the
+               SRP credit algorithm in the SRP specification.
+
+What:          /sys/class/scsi_host/host<n>/service_id
+Date:          June 17, 2006
+KernelVersion: 2.6.17
+Contact:       linux-rdma@vger.kernel.org
+Description:   InfiniBand service ID used for establishing communication with
+               the SRP target.
+
+What:          /sys/class/scsi_host/host<n>/zero_req_lim
+Date:          September 20, 2006
+KernelVersion: 2.6.18
+Contact:       linux-rdma@vger.kernel.org
+Description:   Number of times the initiator had to wait before sending a
+               request to the target because it ran out of credits. For more
+               information see also the SRP credit algorithm in the SRP
+               specification.
diff --git a/Documentation/ABI/stable/sysfs-transport-srp b/Documentation/ABI/stable/sysfs-transport-srp
new file mode 100644 (file)
index 0000000..b36fb0d
--- /dev/null
@@ -0,0 +1,19 @@
+What:          /sys/class/srp_remote_ports/port-<h>:<n>/delete
+Date:          June 1, 2012
+KernelVersion: 3.7
+Contact:       linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
+Description:   Instructs an SRP initiator to disconnect from a target and to
+               remove all LUNs imported from that target.
+
+What:          /sys/class/srp_remote_ports/port-<h>:<n>/port_id
+Date:          June 27, 2007
+KernelVersion: 2.6.24
+Contact:       linux-scsi@vger.kernel.org
+Description:   16-byte local SRP port identifier in hexadecimal format. An
+               example: 4c:49:4e:55:58:20:56:49:4f:00:00:00:00:00:00:00.
+
+What:          /sys/class/srp_remote_ports/port-<h>:<n>/roles
+Date:          June 27, 2007
+KernelVersion: 2.6.24
+Contact:       linux-scsi@vger.kernel.org
+Description:   Role of the remote port. Either "SRP Initiator" or "SRP Target".
index 7e7e07a82e0ec15dbe3255683acd67dba8d2f429..bb820be48179000dd85472ca5d02286778880aeb 100644 (file)
@@ -92,7 +92,7 @@ Description:  The /dev/kmsg character device node provides userspace access
                The flags field carries '-' by default. A 'c' indicates a
                fragment of a line. All following fragments are flagged with
                '+'. Note, that these hints about continuation lines are not
-               neccessarily correct, and the stream could be interleaved with
+               necessarily correct, and the stream could be interleaved with
                unrelated messages, but merging the lines in the output
                usually produces better human readable results. A similar
                logic is used internally when messages are printed to the
index dff1f48d252d8f0d36aa31cccf6514cb02b3d333..1ce5ae329c048fa1f9c84523592d5bfc34c22614 100644 (file)
@@ -222,3 +222,37 @@ Description:
                satisfied too.  Reading this attribute will show the current
                value of d3cold_allowed bit.  Writing this attribute will set
                the value of d3cold_allowed bit.
+
+What:          /sys/bus/pci/devices/.../sriov_totalvfs
+Date:          November 2012
+Contact:       Donald Dutile <ddutile@redhat.com>
+Description:
+               This file appears when a physical PCIe device supports SR-IOV.
+               Userspace applications can read this file to determine the
+               maximum number of Virtual Functions (VFs) a PCIe physical
+               function (PF) can support. Typically, this is the value reported
+               in the PF's SR-IOV extended capability structure's TotalVFs
+               element.  Drivers have the ability at probe time to reduce the
+               value read from this file via the pci_sriov_set_totalvfs()
+               function.
+
+What:          /sys/bus/pci/devices/.../sriov_numvfs
+Date:          November 2012
+Contact:       Donald Dutile <ddutile@redhat.com>
+Description:
+               This file appears when a physical PCIe device supports SR-IOV.
+               Userspace applications can read and write to this file to
+               determine and control the enablement or disablement of Virtual
+               Functions (VFs) on the physical function (PF). A read of this
+               file will return the number of VFs that are enabled on this PF.
+               A number written to this file will enable the specified
+               number of VFs. A userspace application would typically read the
+               file and check that the value is zero, and then write the number
+               of VFs that should be enabled on the PF; the value written
+               should be less than or equal to the value in the sriov_totalvfs
+               file. A userspace application wanting to disable the VFs would
+               write a zero to this file. The core ensures that valid values
+               are written to this file, and returns errors when values are not
+               valid.  For example, writing a 2 to this file when sriov_numvfs
+               is not 0 and not 2 already will return an error. Writing a 10
+               when the value of sriov_totalvfs is 8 will return an error.
index 7fc2997b23a6e25e1690249b3161a29f6b950596..9d43e76708413bdf6b3d25a0b1179714b06680ba 100644 (file)
@@ -164,7 +164,7 @@ Contact:    Rafael J. Wysocki <rjw@sisk.pl>
 Description:
                The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
                contains the total time the device has been preventing
-               opportunistic transitions to sleep states from occuring.
+               opportunistic transitions to sleep states from occurring.
                This attribute is read-only.  If the device is not enabled to
                wake up the system from sleep states, this attribute is not
                present.
index 189dc43891bf24f57cce1806bbce0cc474763543..9eca5a182e64df28a22187ae05ff829b53de8f52 100644 (file)
@@ -117,6 +117,14 @@ Description:       When written, this file lets one store macros with max 500
                which profile and key to read.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/reset
+Date:          November 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written, this file lets one reset the device.
+               The data has to be 3 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control
 Date:          June 2011
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
index 65e6e5dd67e83a04cc0f8e93feffda8eb5c7be38..7bd776f9c3c70cc2f92290cbae254a9858c41daf 100644 (file)
@@ -9,15 +9,12 @@ Description:  The integer value of this attribute ranges from 0-4.
                and the mouse activates this profile immediately.
 Users:         http://roccat.sourceforge.net
 
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
-Date:          October 2010
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
+Date:          November 2012
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns the raw integer version number of the
-               firmware reported by the mouse. Using the integer value eases
-               further usage in other programs. To receive the real version
-               number the decimal point has to be shifted 2 positions to the
-               left. E.g. a returned value of 121 means 1.21
-               This file is readonly.
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 8 bytes long.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
@@ -42,18 +39,8 @@ Description: The mouse can store 5 profiles which can be switched by the
                The mouse will reject invalid data.
                Which profile to write is determined by the profile number
                contained in the data.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_buttons holds information about button layout.
-               When read, these files return the respective profile buttons.
-               The returned data is 77 bytes in size.
-               This file is readonly.
+               Before reading this file, control has to be written to select
+               which profile to read.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
@@ -68,19 +55,8 @@ Description: The mouse can store 5 profiles which can be switched by the
                The mouse will reject invalid data.
                Which profile to write is determined by the profile number
                contained in the data.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_settings holds information like resolution, sensitivity
-               and light effects.
-               When read, these files return the respective profile settings.
-               The returned data is 43 bytes in size.
-               This file is readonly.
+               Before reading this file, control has to be written to select
+               which profile to read.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
@@ -104,9 +80,9 @@ What:                /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:          October 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   When written a calibration process for the tracking control unit
-               can be initiated/cancelled.
-               The data has to be 3 bytes long.
-               This file is writeonly.
+               can be initiated/cancelled. Also lets one read/write sensor
+               registers.
+               The data has to be 4 bytes long.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
index 20f937c9d84f2ca713baaf4ef041bbaadc01da2e..a10404f15a54a510ec1dc96198363ea16b435070 100644 (file)
@@ -1,12 +1,3 @@
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 1-4.
-               When read, this attribute returns the number of the active
-               cpi level.
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
-
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
 Date:          January 2011
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -18,33 +9,12 @@ Description: The integer value of this attribute ranges from 0-4.
                active when the mouse is powered on.
 Users:         http://roccat.sourceforge.net
 
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
-Date:          January 2011
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
+Date:          November 2012
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 1-10.
-               When read, this attribute returns the number of the actual
-               sensitivity in x direction.
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 1-10.
-               When read, this attribute returns the number of the actual
-               sensitivity in y direction.
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns the raw integer version number of the
-               firmware reported by the mouse. Using the integer value eases
-               further usage in other programs. To receive the real version
-               number the decimal point has to be shifted 2 positions to the
-               left. E.g. a returned value of 121 means 1.21
-               This file is readonly.
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 6 bytes long.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
@@ -58,18 +28,8 @@ Description: The mouse can store 5 profiles which can be switched by the
                The mouse will reject invalid data.
                Which profile to write is determined by the profile number
                contained in the data.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_buttons holds information about button layout.
-               When read, these files return the respective profile buttons.
-               The returned data is 23 bytes in size.
-               This file is readonly.
+               Before reading this file, control has to be written to select
+               which profile to read.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
@@ -84,17 +44,6 @@ Description: The mouse can store 5 profiles which can be switched by the
                The mouse will reject invalid data.
                Which profile to write is determined by the profile number
                contained in the data.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_settings holds information like resolution, sensitivity
-               and light effects.
-               When read, these files return the respective profile settings.
-               The returned data is 16 bytes in size.
-               This file is readonly.
+               Before reading this file, control has to be written to select
+               which profile to read.
 Users:         http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
new file mode 100644 (file)
index 0000000..31c6c4c
--- /dev/null
@@ -0,0 +1,7 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/control
+Date:          October 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written, cpi, button and light settings can be configured.
+               When read, actual cpi setting and sensor data are returned.
+               The data has to be 8 bytes long.
+Users:         http://roccat.sourceforge.net
index 3f8de50e4ff1dfb017da9f57befc8a568361cc71..9fa9de30d14b9a339eb6ee68f0dd4831335901d6 100644 (file)
@@ -1,37 +1,9 @@
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   It is possible to switch the cpi setting of the mouse with the
-               press of a button.
-               When read, this file returns the raw number of the actual cpi
-               setting reported by the mouse. This number has to be further
-               processed to receive the real dpi value.
-
-               VALUE DPI
-               1     400
-               2     800
-               4     1600
-
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
-Date:          August 2010
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
+Date:          November 2012
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns the number of the actual profile in
-               range 0-4.
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns the raw integer version number of the
-               firmware reported by the mouse. Using the integer value eases
-               further usage in other programs. To receive the real version
-               number the decimal point has to be shifted 2 positions to the
-               left. E.g. a returned value of 138 means 1.38
-               This file is readonly.
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 6 bytes long.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
@@ -46,19 +18,8 @@ Description: The mouse can store 5 profiles which can be switched by the
                The mouse will reject invalid data.
                Which profile to write is determined by the profile number
                contained in the data.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_settings holds information like resolution, sensitivity
-               and light effects.
-               When read, these files return the respective profile settings.
-               The returned data is 13 bytes in size.
-               This file is readonly.
+               Before reading this file, control has to be written to select
+               which profile to read.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
@@ -72,27 +33,8 @@ Description: The mouse can store 5 profiles which can be switched by the
                The mouse will reject invalid data.
                Which profile to write is determined by the profile number
                contained in the data.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_buttons holds information about button layout.
-               When read, these files return the respective profile buttons.
-               The returned data is 19 bytes in size.
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 0-4.
-                When read, this attribute returns the number of the profile
-                that's active when the mouse is powered on.
-               This file is readonly.
+               Before reading this file, control has to be written to select
+               which profile to read.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
index b42922cf6b1f1840965708131d7762c241df6493..f1e02a98bd9ddb179d17843ad4d865a1c884fc01 100644 (file)
@@ -40,8 +40,8 @@ What:         /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:          Mai 2012
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
                The data is 8 bytes long.
-               This file is readonly.
 Users:         http://roccat.sourceforge.net
 
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro
@@ -74,4 +74,3 @@ Description:  The mouse has a Avago ADNS-3090 sensor.
                This file allows reading and writing of the mouse sensors registers.
                The data has to be 4 bytes long.
 Users:         http://roccat.sourceforge.net
-
index 97a003ee058bc79e444bf8e442fa87d93b8f8af3..7d1435bc976c702a7cb432a49632e7f3a6a2f6f3 100644 (file)
@@ -5,7 +5,7 @@ Contact:        xiaoyan.zhang@intel.com
 Description:
                This folder includes the attributes related with PPI (Physical
                Presence Interface). Only if TPM is supported by BIOS, this
-               folder makes sence. The folder path can be got by command
+               folder makes sense. The folder path can be got by command
                'find /sys/ -name 'pcrs''. For the detail information of PPI,
                please refer to the PPI specification from
                http://www.trustedcomputinggroup.org/
index b02d8b8c173a9678ba8459037cddd5ab8717c05c..8a8e466eb2c01d39ec2afb7cac46cc183dde94aa 100644 (file)
@@ -1,13 +1,13 @@
-What:          /sys/kernel/profile
+What:          /sys/kernel/profiling
 Date:          September 2008
 Contact:       Dave Hansen <dave@linux.vnet.ibm.com>
 Description:
-               /sys/kernel/profile is the runtime equivalent
+               /sys/kernel/profiling is the runtime equivalent
                of the boot-time profile= option.
 
                You can get the same effect running:
 
-                       echo 2 > /sys/kernel/profile
+                       echo 2 > /sys/kernel/profiling
 
                as you would by issuing profile=2 on the boot
                command line.
index 4fdf6b562d1cedb819c258f99820edfa4fafc7b3..3dd9e78815d1bca89576c2817bb050471419cf04 100644 (file)
@@ -2586,6 +2586,13 @@ ioctls.</para>
          <para>Vendor and device specific media bus pixel formats.
            <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
         </listitem>
+        <listitem>
+         <para>Importing DMABUF file descriptors as a new IO method described
+         in <xref linkend="dmabuf" />.</para>
+        </listitem>
+        <listitem>
+         <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
index b5d1cbdc558bdfa5cfbd6e451425dabc5456b0ce..388a3403265380f14128feb10b50543f69bd994c 100644 (file)
@@ -331,7 +331,7 @@ application until one or more buffers can be dequeued. By default
 outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
 given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
 returns immediately with an &EAGAIN; when no buffer is available. The
-&func-select; or &func-poll; function are always available.</para>
+&func-select; or &func-poll; functions are always available.</para>
 
     <para>To start and stop capturing or output applications call the
 &VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
@@ -472,6 +472,165 @@ rest should be evident.</para>
       </footnote></para>
   </section>
 
+  <section id="dmabuf">
+    <title>Streaming I/O (DMA buffer importing)</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental"> experimental </link>
+      interface and may change in the future.</para>
+    </note>
+
+<para>The DMABUF framework provides a generic method for sharing buffers
+between multiple devices. Device drivers that support DMABUF can export a DMA
+buffer to userspace as a file descriptor (known as the exporter role), import a
+DMA buffer from userspace using a file descriptor previously exported for a
+different or the same device (known as the importer role), or both. This
+section describes the DMABUF importer role API in V4L2.</para>
+
+    <para>Refer to <link linked="vidioc-expbuf"> DMABUF exporting </link> for
+details about exporting V4L2 buffers as DMABUF file descriptors.</para>
+
+<para>Input and output devices support the streaming I/O method when the
+<constant>V4L2_CAP_STREAMING</constant> flag in the
+<structfield>capabilities</structfield> field of &v4l2-capability; returned by
+the &VIDIOC-QUERYCAP; ioctl is set. Whether importing DMA buffers through
+DMABUF file descriptors is supported is determined by calling the
+&VIDIOC-REQBUFS; ioctl with the memory type set to
+<constant>V4L2_MEMORY_DMABUF</constant>.</para>
+
+    <para>This I/O method is dedicated to sharing DMA buffers between different
+devices, which may be V4L devices or other video-related devices (e.g. DRM).
+Buffers (planes) are allocated by a driver on behalf of an application. Next,
+these buffers are exported to the application as file descriptors using an API
+which is specific for an allocator driver.  Only such file descriptor are
+exchanged. The descriptors and meta-information are passed in &v4l2-buffer; (or
+in &v4l2-plane; in the multi-planar API case).  The driver must be switched
+into DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer
+type.</para>
+
+    <example>
+      <title>Initiating streaming I/O with DMABUF file descriptors</title>
+
+      <programlisting>
+&v4l2-requestbuffers; reqbuf;
+
+memset(&amp;reqbuf, 0, sizeof (reqbuf));
+reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+reqbuf.memory = V4L2_MEMORY_DMABUF;
+reqbuf.count = 1;
+
+if (ioctl(fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
+       if (errno == EINVAL)
+               printf("Video capturing or DMABUF streaming is not supported\n");
+       else
+               perror("VIDIOC_REQBUFS");
+
+       exit(EXIT_FAILURE);
+}
+      </programlisting>
+    </example>
+
+    <para>The buffer (plane) file descriptor is passed on the fly with the
+&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be
+associated with a different DMABUF descriptor. Although buffers are commonly
+cycled, applications can pass a different DMABUF descriptor at each
+<constant>VIDIOC_QBUF</constant> call.</para>
+
+    <example>
+      <title>Queueing DMABUF using single plane API</title>
+
+      <programlisting>
+int buffer_queue(int v4lfd, int index, int dmafd)
+{
+       &v4l2-buffer; buf;
+
+       memset(&amp;buf, 0, sizeof buf);
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf.memory = V4L2_MEMORY_DMABUF;
+       buf.index = index;
+       buf.m.fd = dmafd;
+
+       if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
+               perror("VIDIOC_QBUF");
+               return -1;
+       }
+
+       return 0;
+}
+      </programlisting>
+    </example>
+
+    <example>
+      <title>Queueing DMABUF using multi plane API</title>
+
+      <programlisting>
+int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
+{
+       &v4l2-buffer; buf;
+       &v4l2-plane; planes[VIDEO_MAX_PLANES];
+       int i;
+
+       memset(&amp;buf, 0, sizeof buf);
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       buf.memory = V4L2_MEMORY_DMABUF;
+       buf.index = index;
+       buf.m.planes = planes;
+       buf.length = n_planes;
+
+       memset(&amp;planes, 0, sizeof planes);
+
+       for (i = 0; i &lt; n_planes; ++i)
+               buf.m.planes[i].m.fd = dmafd[i];
+
+       if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
+               perror("VIDIOC_QBUF");
+               return -1;
+       }
+
+       return 0;
+}
+      </programlisting>
+    </example>
+
+    <para>Captured or displayed buffers are dequeued with the
+&VIDIOC-DQBUF; ioctl. The driver can unlock the buffer at any
+time between the completion of the DMA and this ioctl. The memory is
+also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or
+when the device is closed.</para>
+
+    <para>For capturing applications it is customary to enqueue a
+number of empty buffers, to start capturing and enter the read loop.
+Here the application waits until a filled buffer can be dequeued, and
+re-enqueues the buffer when the data is no longer needed. Output
+applications fill and enqueue buffers, when enough buffers are stacked
+up output is started. In the write loop, when the application
+runs out of free buffers it must wait until an empty buffer can be
+dequeued and reused. Two methods exist to suspend execution of the
+application until one or more buffers can be dequeued. By default
+<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
+outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
+given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
+returns immediately with an &EAGAIN; when no buffer is available. The
+&func-select; and &func-poll; functions are always available.</para>
+
+    <para>To start and stop capturing or displaying applications call the
+&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that
+<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both queues and
+unlocks all buffers as a side effect. Since there is no notion of doing
+anything "now" on a multitasking system, if an application needs to synchronize
+with another event it should examine the &v4l2-buffer;
+<structfield>timestamp</structfield> of captured buffers, or set the field
+before enqueuing buffers for output.</para>
+
+    <para>Drivers implementing DMABUF importing I/O must support the
+<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
+<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and
+<constant>VIDIOC_STREAMOFF</constant> ioctls, and the
+<function>select()</function> and <function>poll()</function> functions.</para>
+
+  </section>
+
   <section id="async">
     <title>Asynchronous I/O</title>
 
@@ -672,6 +831,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
            in the <structfield>length</structfield> field of this
            <structname>v4l2_buffer</structname> structure.</entry>
          </row>
+         <row>
+           <entry></entry>
+           <entry>int</entry>
+           <entry><structfield>fd</structfield></entry>
+           <entry>For the single-plane API and when
+<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this
+is the file descriptor associated with a DMABUF buffer.</entry>
+         </row>
          <row>
            <entry>__u32</entry>
            <entry><structfield>length</structfield></entry>
@@ -743,6 +910,15 @@ should set this to 0.</entry>
              pointer to the memory allocated for this plane by an application.
              </entry>
          </row>
+         <row>
+           <entry></entry>
+           <entry>int</entry>
+           <entry><structfield>fd</structfield></entry>
+           <entry>When the memory type in the containing &v4l2-buffer; is
+               <constant>V4L2_MEMORY_DMABUF</constant>, this is a file
+               descriptor associated with a DMABUF buffer, similar to the
+               <structfield>fd</structfield> field in &v4l2-buffer;.</entry>
+         </row>
          <row>
            <entry>__u32</entry>
            <entry><structfield>data_offset</structfield></entry>
@@ -923,7 +1099,7 @@ application. Drivers set or clear this flag when the
          </row>
          <row>
            <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
-           <entry>0x0400</entry>
+           <entry>0x0800</entry>
            <entry>Caches do not have to be invalidated for this buffer.
 Typically applications shall use this flag if the data captured in the buffer
 is not going to be touched by the CPU, instead the buffer will, probably, be
@@ -932,7 +1108,7 @@ passed on to a DMA-capable hardware unit for further processing or output.
          </row>
          <row>
            <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
-           <entry>0x0800</entry>
+           <entry>0x1000</entry>
            <entry>Caches do not have to be cleaned for this buffer.
 Typically applications shall use this flag for output buffers if the data
 in this buffer has not been created by the CPU but by some DMA-capable unit,
@@ -964,6 +1140,12 @@ pointer</link> I/O.</entry>
            <entry>3</entry>
            <entry>[to do]</entry>
          </row>
+         <row>
+           <entry><constant>V4L2_MEMORY_DMABUF</constant></entry>
+           <entry>4</entry>
+           <entry>The buffer is used for <link linkend="dmabuf">DMA shared
+buffer</link> I/O.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 10ccde9d16d016d6f141f62479afa8f73753850b..4d110b1ad3e93c6559b094ac5bd832f2e4bf3be0 100644 (file)
@@ -543,6 +543,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-enuminput;
     &sub-enumoutput;
     &sub-enumstd;
+    &sub-expbuf;
     &sub-g-audio;
     &sub-g-audioout;
     &sub-g-crop;
index a8cda1acacd9a129b47d15451bfe054d6fcfd9c8..cd9943672434e29b629bf5a46e5aa42749008171 100644 (file)
@@ -6,7 +6,8 @@
 
   <refnamediv>
     <refname>VIDIOC_CREATE_BUFS</refname>
-    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
+    <refpurpose>Create buffers for Memory Mapped or User Pointer or DMA Buffer
+    I/O</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     </note>
 
     <para>This ioctl is used to create buffers for <link linkend="mmap">memory
-mapped</link> or <link linkend="userp">user pointer</link>
-I/O. It can be used as an alternative or in addition to the
-<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
-is required. This ioctl can be called multiple times to create buffers of
-different sizes.</para>
+mapped</link> or <link linkend="userp">user pointer</link> or <link
+linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
+addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter
+control over buffers is required. This ioctl can be called multiple times to
+create buffers of different sizes.</para>
 
     <para>To allocate device buffers applications initialize relevant fields of
 the <structname>v4l2_create_buffers</structname> structure. They set the
@@ -109,7 +110,8 @@ information.</para>
            <entry>__u32</entry>
            <entry><structfield>memory</structfield></entry>
            <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_MMAP</constant>,
+<constant>V4L2_MEMORY_DMABUF</constant> or
 <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
 /></entry>
          </row>
diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
new file mode 100644 (file)
index 0000000..72dfbd2
--- /dev/null
@@ -0,0 +1,212 @@
+<refentry id="vidioc-expbuf">
+
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_EXPBUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_EXPBUF</refname>
+    <refpurpose>Export a buffer as a DMABUF file descriptor.</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>struct v4l2_exportbuffer *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>VIDIOC_EXPBUF</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para></para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</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 ioctl is an extension to the <link linkend="mmap">memory
+mapping</link> I/O method, therefore it is available only for
+<constant>V4L2_MEMORY_MMAP</constant> buffers.  It can be used to export a
+buffer as a DMABUF file at any time after buffers have been allocated with the
+&VIDIOC-REQBUFS; ioctl.</para>
+
+<para> To export a buffer, applications fill &v4l2-exportbuffer;.  The
+<structfield> type </structfield> field is set to the same buffer type as was
+previously used with  &v4l2-requestbuffers;<structfield> type </structfield>.
+Applications must also set the <structfield> index </structfield> field. Valid
+index numbers range from zero to the number of buffers allocated with
+&VIDIOC-REQBUFS; (&v4l2-requestbuffers;<structfield> count </structfield>)
+minus one.  For the multi-planar API, applications set the <structfield> plane
+</structfield> field to the index of the plane to be exported. Valid planes
+range from zero to the maximal number of valid planes for the currently active
+format. For the single-planar API, applications must set <structfield> plane
+</structfield> to zero.  Additional flags may be posted in the <structfield>
+flags </structfield> field.  Refer to a manual for open() for details.
+Currently only O_CLOEXEC is supported.  All other fields must be set to zero.
+In the case of multi-planar API, every plane is exported separately using
+multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
+
+<para> After calling <constant>VIDIOC_EXPBUF</constant> the <structfield> fd
+</structfield> field will be set by a driver.  This is a DMABUF file
+descriptor. The application may pass it to other DMABUF-aware devices. Refer to
+<link linkend="dmabuf">DMABUF importing</link> for details about importing
+DMABUF files into V4L2 nodes. It is recommended to close a DMABUF file when it
+is no longer used to allow the associated memory to be reclaimed. </para>
+
+  </refsect1>
+  <refsect1>
+   <section>
+      <title>Examples</title>
+
+      <example>
+       <title>Exporting a buffer.</title>
+       <programlisting>
+int buffer_export(int v4lfd, &v4l2-buf-type; bt, int index, int *dmafd)
+{
+       &v4l2-exportbuffer; expbuf;
+
+       memset(&amp;expbuf, 0, sizeof(expbuf));
+       expbuf.type = bt;
+       expbuf.index = index;
+       if (ioctl(v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
+               perror("VIDIOC_EXPBUF");
+               return -1;
+       }
+
+       *dmafd = expbuf.fd;
+
+       return 0;
+}
+        </programlisting>
+      </example>
+
+      <example>
+       <title>Exporting a buffer using the multi-planar API.</title>
+       <programlisting>
+int buffer_export_mp(int v4lfd, &v4l2-buf-type; bt, int index,
+       int dmafd[], int n_planes)
+{
+       int i;
+
+       for (i = 0; i &lt; n_planes; ++i) {
+               &v4l2-exportbuffer; expbuf;
+
+               memset(&amp;expbuf, 0, sizeof(expbuf));
+               expbuf.type = bt;
+               expbuf.index = index;
+               expbuf.plane = i;
+               if (ioctl(v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
+                       perror("VIDIOC_EXPBUF");
+                       while (i)
+                               close(dmafd[--i]);
+                       return -1;
+               }
+               dmafd[i] = expbuf.fd;
+       }
+
+       return 0;
+}
+        </programlisting>
+      </example>
+   </section>
+  </refsect1>
+
+  <refsect1>
+    <table pgwide="1" frame="none" id="v4l2-exportbuffer">
+      <title>struct <structname>v4l2_exportbuffer</structname></title>
+      <tgroup cols="3">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>type</structfield></entry>
+           <entry>Type of the buffer, same as &v4l2-format;
+<structfield>type</structfield> or &v4l2-requestbuffers;
+<structfield>type</structfield>, set by the application. See <xref
+linkend="v4l2-buf-type" /></entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>index</structfield></entry>
+           <entry>Number of the buffer, set by the application. This field is
+only used for <link linkend="mmap">memory mapping</link> I/O and can range from
+zero to the number of buffers allocated with the &VIDIOC-REQBUFS; and/or
+&VIDIOC-CREATE-BUFS; ioctls. </entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>plane</structfield></entry>
+           <entry>Index of the plane to be exported when using the
+multi-planar API. Otherwise this value must be set to zero. </entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>flags</structfield></entry>
+           <entry>Flags for the newly created file, currently only <constant>
+O_CLOEXEC </constant> is supported, refer to the manual of open() for more
+details.</entry>
+         </row>
+         <row>
+           <entry>__s32</entry>
+           <entry><structfield>fd</structfield></entry>
+           <entry>The DMABUF file descriptor associated with a buffer. Set by
+               the driver.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved[11]</structfield></entry>
+           <entry>Reserved field for future use. Must be set to zero.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>EINVAL</errorcode></term>
+       <listitem>
+         <para>A queue is not in MMAP mode or DMABUF exporting is not
+supported or <structfield> flags </structfield> or <structfield> type
+</structfield> or <structfield> index </structfield> or <structfield> plane
+</structfield> fields are invalid.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+</refentry>
index 2d37abefce13e90144941af12cc2baa71f78a700..3504a7f2f382c6f1818cf5a5983405f136e0fe94 100644 (file)
@@ -109,6 +109,23 @@ they cannot be swapped out to disk. Buffers remain locked until
 dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
 called, or until the device is closed.</para>
 
+    <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
+set the <structfield>memory</structfield> field to
+<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
+field to a file descriptor associated with a DMABUF buffer. When the
+multi-planar API is used the <structfield>m.fd</structfield> fields of the
+passed array of &v4l2-plane; have to be used instead. When
+<constant>VIDIOC_QBUF</constant> is called with a pointer to this structure the
+driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
+<constant>V4L2_BUF_FLAG_MAPPED</constant> and
+<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
+<structfield>flags</structfield> field, or it returns an error code.  This
+ioctl locks the buffer. Locking a buffer means passing it to a driver for a
+hardware access (usually DMA).  If an application accesses (reads/writes) a
+locked buffer then the result is undefined.  Buffers remain locked until
+dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or
+until the device is closed.</para>
+
     <para>Applications call the <constant>VIDIOC_DQBUF</constant>
 ioctl to dequeue a filled (capturing) or displayed (output) buffer
 from the driver's outgoing queue. They just set the
index 2b50ef2007f3cc96dc363176e2c173af96c3e2a8..78a06a9a5ece18c3cfe6967f8c18822e89ace6fa 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para>This ioctl is used to initiate <link linkend="mmap">memory
-mapped</link> or <link linkend="userp">user pointer</link>
-I/O. Memory mapped buffers are located in device memory and must be
-allocated with this ioctl before they can be mapped into the
-application's address space. User buffers are allocated by
-applications themselves, and this ioctl is merely used to switch the
-driver into user pointer I/O mode and to setup some internal structures.</para>
+<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
+<link linkend="userp">user pointer</link> or <link
+linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
+device memory and must be allocated with this ioctl before they can be mapped
+into the application's address space. User buffers are allocated by
+applications themselves, and this ioctl is merely used to switch the driver
+into user pointer I/O mode and to setup some internal structures.
+Similarly, DMABUF buffers are allocated by applications through a device
+driver, and this ioctl only configures the driver into DMABUF I/O mode without
+performing any direct allocation.</para>
 
-    <para>To allocate device buffers applications initialize all
-fields of the <structname>v4l2_requestbuffers</structname> structure.
-They set the <structfield>type</structfield> field to the respective
-stream or buffer type, the <structfield>count</structfield> field to
-the desired number of buffers, <structfield>memory</structfield>
-must be set to the requested I/O method and the <structfield>reserved</structfield> array
-must be zeroed. When the ioctl
-is called with a pointer to this structure the driver will attempt to allocate
-the requested number of buffers and it stores the actual number
-allocated in the <structfield>count</structfield> field. It can be
-smaller than the number requested, even zero, when the driver runs out
-of free memory. A larger number is also possible when the driver requires
-more buffers to function correctly. For example video output requires at least two buffers,
-one displayed and one filled by the application.</para>
+    <para>To allocate device buffers applications initialize all fields of the
+<structname>v4l2_requestbuffers</structname> structure.  They set the
+<structfield>type</structfield> field to the respective stream or buffer type,
+the <structfield>count</structfield> field to the desired number of buffers,
+<structfield>memory</structfield> must be set to the requested I/O method and
+the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
+called with a pointer to this structure the driver will attempt to allocate the
+requested number of buffers and it stores the actual number allocated in the
+<structfield>count</structfield> field. It can be smaller than the number
+requested, even zero, when the driver runs out of free memory. A larger number
+is also possible when the driver requires more buffers to function correctly.
+For example video output requires at least two buffers, one displayed and one
+filled by the application.</para>
     <para>When the I/O method is not supported the ioctl
 returns an &EINVAL;.</para>
 
@@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
            <entry>__u32</entry>
            <entry><structfield>memory</structfield></entry>
            <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_MMAP</constant>,
+<constant>V4L2_MEMORY_DMABUF</constant> or
 <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
 />.</entry>
          </row>
index cab4ec58e46e6570be19d7f343bfc5671804684f..fb32aead5a0b52a5dd72d1dbd6023472b7e1fda1 100644 (file)
   /* chip-specific constructor
    * (see "Management of Cards and Components")
    */
-  static int __devinit snd_mychip_create(struct snd_card *card,
-                                         struct pci_dev *pci,
-                                         struct mychip **rchip)
+  static int snd_mychip_create(struct snd_card *card,
+                               struct pci_dev *pci,
+                               struct mychip **rchip)
   {
           struct mychip *chip;
           int err;
   }
 
   /* constructor -- see "Constructor" sub-section */
-  static int __devinit snd_mychip_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
+  static int snd_mychip_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
   {
           static int dev;
           struct snd_card *card;
   }
 
   /* destructor -- see the "Destructor" sub-section */
-  static void __devexit snd_mychip_remove(struct pci_dev *pci)
+  static void snd_mychip_remove(struct pci_dev *pci)
   {
           snd_card_free(pci_get_drvdata(pci));
           pci_set_drvdata(pci, NULL);
       <para>
         The real constructor of PCI drivers is the <function>probe</function> callback.
       The <function>probe</function> callback and other component-constructors which are called
-      from the <function>probe</function> callback should be defined with
-      the <parameter>__devinit</parameter> prefix. You 
-      cannot use the <parameter>__init</parameter> prefix for them,
+      from the <function>probe</function> callback cannot be used with
+      the <parameter>__init</parameter> prefix
       because any PCI device could be a hotplug device. 
       </para>
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  static void __devexit snd_mychip_remove(struct pci_dev *pci)
+  static void snd_mychip_remove(struct pci_dev *pci)
   {
           snd_card_free(pci_get_drvdata(pci));
           pci_set_drvdata(pci, NULL);
       components are released automatically by this call. 
       </para>
 
-      <para>
-        As further notes, the destructors (both
-      <function>snd_mychip_dev_free</function> and
-      <function>snd_mychip_free</function>) cannot be defined with
-      the <parameter>__devexit</parameter> prefix, because they may be
-      called from the constructor, too, at the false path. 
-      </para>
-
       <para>
       For a device which allows hotplugging, you can use
       <function>snd_card_free_when_closed</function>.  This one will
   }
 
   /* chip-specific constructor */
-  static int __devinit snd_mychip_create(struct snd_card *card,
-                                         struct pci_dev *pci,
-                                         struct mychip **rchip)
+  static int snd_mychip_create(struct snd_card *card,
+                               struct pci_dev *pci,
+                               struct mychip **rchip)
   {
           struct mychip *chip;
           int err;
           .name = KBUILD_MODNAME,
           .id_table = snd_mychip_ids,
           .probe = snd_mychip_probe,
-          .remove = __devexit_p(snd_mychip_remove),
+          .remove = snd_mychip_remove,
   };
 
   /* module initialization */
         </informalexample>
       </para>
 
-      <para>
-      Again, remember that you cannot
-      use the <parameter>__devexit</parameter> prefix for this destructor. 
-      </para>
-
       <para>
       We didn't implement the hardware disabling part in the above.
       If you need to do this, please note that the destructor may be
           .name = KBUILD_MODNAME,
           .id_table = snd_mychip_ids,
           .probe = snd_mychip_probe,
-          .remove = __devexit_p(snd_mychip_remove),
+          .remove = snd_mychip_remove,
   };
 ]]>
           </programlisting>
         The <structfield>probe</structfield> and
       <structfield>remove</structfield> functions have already
       been defined in the previous sections.
-      The <structfield>remove</structfield> function should
-      be defined with the 
-      <function>__devexit_p()</function> macro, so that it's not
-      defined for built-in (and non-hot-pluggable) case. The
-      <structfield>name</structfield> 
+      The <structfield>name</structfield>
       field is the name string of this device. Note that you must not
       use a slash <quote>/</quote> in this string. 
       </para>
       <para>
         Note that these module entries are tagged with
       <parameter>__init</parameter> and 
-      <parameter>__exit</parameter> prefixes, not
-      <parameter>__devinit</parameter> nor
-      <parameter>__devexit</parameter>.
+      <parameter>__exit</parameter> prefixes.
       </para>
 
       <para>
    */
 
   /* create a pcm device */
-  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+  static int snd_mychip_new_pcm(struct mychip *chip)
   {
           struct snd_pcm *pcm;
           int err;
         <informalexample>
           <programlisting>
 <![CDATA[
-  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+  static int snd_mychip_new_pcm(struct mychip *chip)
   {
           struct snd_pcm *pcm;
           int err;
           ....
   }
 
-  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+  static int snd_mychip_new_pcm(struct mychip *chip)
   {
           struct snd_pcm *pcm;
           ....
@@ -3399,7 +3379,7 @@ struct _snd_pcm_runtime {
          <title>Definition of a Control</title>
           <programlisting>
 <![CDATA[
-  static struct snd_kcontrol_new my_control __devinitdata = {
+  static struct snd_kcontrol_new my_control = {
           .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
           .name = "PCM Playback Switch",
           .index = 0,
@@ -3414,13 +3394,6 @@ struct _snd_pcm_runtime {
         </example>
       </para>
 
-      <para>
-        Most likely the control is created via
-      <function>snd_ctl_new1()</function>, and in such a case, you can
-      add the <parameter>__devinitdata</parameter> prefix to the
-      definition as above. 
-      </para>
-
       <para>
         The <structfield>iface</structfield> field specifies the control
       type, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
@@ -3847,10 +3820,8 @@ struct _snd_pcm_runtime {
 
       <para>
         <function>snd_ctl_new1()</function> allocates a new
-      <structname>snd_kcontrol</structname> instance (that's why the definition
-      of <parameter>my_control</parameter> can be with
-      the <parameter>__devinitdata</parameter> 
-      prefix), and <function>snd_ctl_add</function> assigns the given
+      <structname>snd_kcontrol</structname> instance,
+      and <function>snd_ctl_add</function> assigns the given
       control component to the card. 
       </para>
     </section>
@@ -3896,7 +3867,7 @@ struct _snd_pcm_runtime {
 <![CDATA[
   static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
 
-  static struct snd_kcontrol_new my_control __devinitdata = {
+  static struct snd_kcontrol_new my_control = {
           ...
           .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
                     SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -5761,8 +5732,8 @@ struct _snd_pcm_runtime {
       <informalexample>
         <programlisting>
 <![CDATA[
-  static int __devinit snd_mychip_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
+  static int snd_mychip_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
   {
           ....
           struct snd_card *card;
@@ -5787,8 +5758,8 @@ struct _snd_pcm_runtime {
       <informalexample>
         <programlisting>
 <![CDATA[
-  static int __devinit snd_mychip_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
+  static int snd_mychip_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
   {
           ....
           struct snd_card *card;
@@ -5825,7 +5796,7 @@ struct _snd_pcm_runtime {
           .name = KBUILD_MODNAME,
           .id_table = snd_my_ids,
           .probe = snd_my_probe,
-          .remove = __devexit_p(snd_my_remove),
+          .remove = snd_my_remove,
   #ifdef CONFIG_PM
           .suspend = snd_my_suspend,
           .resume = snd_my_resume,
index 59c080f084ef3dcfb52a21e850334b66672fe6af..a9f288ff54f97214c3afd4fd10839a4e75de01ad 100644 (file)
@@ -462,7 +462,7 @@ Differences between the kernel community and corporate structures
 
 The kernel community works differently than most traditional corporate
 development environments.  Here are a list of things that you can try to
-do to try to avoid problems:
+do to avoid problems:
   Good things to say regarding your proposed changes:
     - "This solves multiple problems."
     - "This deletes 2000 lines of code."
index fc73ef5d65b81366360d9d213bc2d675875ad4b7..cfaca7e6989346246e3205c52a353ea960b50ce5 100644 (file)
@@ -2,6 +2,9 @@
                Copyright (C) 2009 Intel Corporation
                    Yu Zhao <yu.zhao@intel.com>
 
+               Update: November 2012
+                       -- sysfs-based SRIOV enable-/disable-ment
+               Donald Dutile <ddutile@redhat.com>
 
 1. Overview
 
@@ -24,10 +27,21 @@ real existing PCI device.
 
 2.1 How can I enable SR-IOV capability
 
-The device driver (PF driver) will control the enabling and disabling
-of the capability via API provided by SR-IOV core. If the hardware
-has SR-IOV capability, loading its PF driver would enable it and all
-VFs associated with the PF.
+Multiple methods are available for SR-IOV enablement.
+In the first method, the device driver (PF driver) will control the
+enabling and disabling of the capability via API provided by SR-IOV core.
+If the hardware has SR-IOV capability, loading its PF driver would
+enable it and all VFs associated with the PF.  Some PF drivers require
+a module parameter to be set to determine the number of VFs to enable.
+In the second method, a write to the sysfs file sriov_numvfs will
+enable and disable the VFs associated with a PCIe PF.  This method
+enables per-PF, VF enable/disable values versus the first method,
+which applies to all PFs of the same device.  Additionally, the
+PCI SRIOV core support ensures that enable/disable operations are
+valid to reduce duplication in multiple drivers for the same
+checks, e.g., check numvfs == 0 if enabling VFs, ensure
+numvfs <= totalvfs.
+The second method is the recommended method for new/future VF devices.
 
 2.2 How can I use the Virtual Functions
 
@@ -40,13 +54,22 @@ requires device driver that is same as a normal PCI device's.
 3.1 SR-IOV API
 
 To enable SR-IOV capability:
+(a) For the first method, in the driver:
        int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
        'nr_virtfn' is number of VFs to be enabled.
+(b) For the second method, from sysfs:
+       echo 'nr_virtfn' > \
+        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
 To disable SR-IOV capability:
+(a) For the first method, in the driver:
        void pci_disable_sriov(struct pci_dev *dev);
+(b) For the second method, from sysfs:
+       echo  0 > \
+        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
 To notify SR-IOV core of Virtual Function Migration:
+(a) In the driver:
        irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 
 3.2 Usage example
@@ -88,6 +111,22 @@ static void dev_shutdown(struct pci_dev *dev)
        ...
 }
 
+static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
+{
+       if (numvfs > 0) {
+               ...
+               pci_enable_sriov(dev, numvfs);
+               ...
+               return numvfs;
+       }
+       if (numvfs == 0) {
+               ....
+               pci_disable_sriov(dev);
+               ...
+               return 0;
+       }
+}
+
 static struct pci_driver dev_driver = {
        .name =         "SR-IOV Physical Function driver",
        .id_table =     dev_id_table,
@@ -96,4 +135,5 @@ static struct pci_driver dev_driver = {
        .suspend =      dev_suspend,
        .resume =       dev_resume,
        .shutdown =     dev_shutdown,
+       .sriov_configure = dev_sriov_configure,
 };
index 6f706aca2049718c436501f56b8e33592f7f14d6..f8ebcde43b174640ae1ab1d8ac47426a10688614 100644 (file)
@@ -51,7 +51,6 @@ int dbg;
 int print_delays;
 int print_io_accounting;
 int print_task_context_switch_counts;
-__u64 stime, utime;
 
 #define PRINTF(fmt, arg...) {                  \
            if (dbg) {                          \
diff --git a/Documentation/acpi/initrd_table_override.txt b/Documentation/acpi/initrd_table_override.txt
new file mode 100644 (file)
index 0000000..35c3f54
--- /dev/null
@@ -0,0 +1,94 @@
+Overriding ACPI tables via initrd
+=================================
+
+1) Introduction (What is this about)
+2) What is this for
+3) How does it work
+4) References (Where to retrieve userspace tools)
+
+1) What is this about
+---------------------
+
+If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
+override nearly any ACPI table provided by the BIOS with an instrumented,
+modified one.
+
+For a full list of ACPI tables that can be overridden, take a look at
+the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
+All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
+be overridable, except:
+   - ACPI_SIG_RSDP (has a signature of 6 bytes)
+   - ACPI_SIG_FACS (does not have an ordinary ACPI table header)
+Both could get implemented as well.
+
+
+2) What is this for
+-------------------
+
+Please keep in mind that this is a debug option.
+ACPI tables should not get overridden for productive use.
+If BIOS ACPI tables are overridden the kernel will get tainted with the
+TAINT_OVERRIDDEN_ACPI_TABLE flag.
+Complain to your platform/BIOS vendor if you find a bug which is so sever
+that a workaround is not accepted in the Linux kernel.
+
+Still, it can and should be enabled in any kernel, because:
+  - There is no functional change with not instrumented initrds
+  - It provides a powerful feature to easily debug and test ACPI BIOS table
+    compatibility with the Linux kernel.
+
+
+3) How does it work
+-------------------
+
+# Extract the machine's ACPI tables:
+cd /tmp
+acpidump >acpidump
+acpixtract -a acpidump
+# Disassemble, modify and recompile them:
+iasl -d *.dat
+# For example add this statement into a _PRT (PCI Routing Table) function
+# of the DSDT:
+Store("HELLO WORLD", debug)
+iasl -sa dsdt.dsl
+# Add the raw ACPI tables to an uncompressed cpio archive.
+# They must be put into a /kernel/firmware/acpi directory inside the
+# cpio archive.
+# The uncompressed cpio archive must be the first.
+# Other, typically compressed cpio archives, must be
+# concatenated on top of the uncompressed one.
+mkdir -p kernel/firmware/acpi
+cp dsdt.aml kernel/firmware/acpi
+# A maximum of: #define ACPI_OVERRIDE_TABLES 10
+# tables are  currently allowed (see osl.c):
+iasl -sa facp.dsl
+iasl -sa ssdt1.dsl
+cp facp.aml kernel/firmware/acpi
+cp ssdt1.aml kernel/firmware/acpi
+# Create the uncompressed cpio archive and concatenate the original initrd
+# on top:
+find kernel | cpio -H newc --create > /boot/instrumented_initrd
+cat /boot/initrd >>/boot/instrumented_initrd
+# reboot with increased acpi debug level, e.g. boot params:
+acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
+# and check your syslog:
+[    1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
+[    1.272091] [ACPI Debug]  String [0x0B] "HELLO WORLD"
+
+iasl is able to disassemble and recompile quite a lot different,
+also static ACPI tables.
+
+
+4) Where to retrieve userspace tools
+------------------------------------
+
+iasl and acpixtract are part of Intel's ACPICA project:
+http://acpica.org/
+and should be packaged by distributions (for example in the acpica package
+on SUSE).
+
+acpidump can be found in Len Browns pmtools:
+ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
+This tool is also part of the acpica package on SUSE.
+Alternatively, used ACPI tables can be retrieved via sysfs in latest kernels:
+/sys/firmware/acpi/tables
index a564ceea9e98cc9f5f423f0e80f54c85fe7b0ef3..4484e021290e22480fceb1c4bae5b168ca4239c6 100644 (file)
@@ -285,7 +285,10 @@ FB0 +-- GFX  ---- LCD ---- LCD
 Misc notes
 ----------
 
-OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
+OMAP FB allocates the framebuffer memory using the standard dma allocator. You
+can enable Contiguous Memory Allocator (CONFIG_CMA) to improve the dma
+allocator, and if CMA is enabled, you use "cma=" kernel parameter to increase
+the global memory area for CMA.
 
 Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
 of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
@@ -301,11 +304,6 @@ framebuffer parameters.
 Kernel boot arguments
 ---------------------
 
-vram=<size>[,<physaddr>]
-       - Amount of total VRAM to preallocate and optionally a physical start
-         memory address. For example, "10M". omapfb allocates memory for
-         framebuffers from VRAM.
-
 omapfb.mode=<display>:<mode>[,...]
        - Default video mode for specified displays. For example,
          "dvi:800x400MR-24@60".  See drivers/video/modedb.c.
index cefd3d8bbd11db69f51ffee25094e138fc5d0cbd..12e01d432bfef479bd690e81cf0339421e47b87d 100644 (file)
@@ -218,7 +218,7 @@ and name space for cpusets, with a minimum of additional kernel code.
 The cpus and mems files in the root (top_cpuset) cpuset are
 read-only.  The cpus file automatically tracks the value of
 cpu_online_mask using a CPU hotplug notifier, and the mems file
-automatically tracks the value of node_states[N_HIGH_MEMORY]--i.e.,
+automatically tracks the value of node_states[N_MEMORY]--i.e.,
 nodes with memory--using the cpuset_track_online_nodes() hook.
 
 
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt
new file mode 100644 (file)
index 0000000..ecdb57d
--- /dev/null
@@ -0,0 +1,11 @@
+Altera SOCFPGA Reset Manager
+
+Required properties:
+- compatible : "altr,rst-mgr"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+        rstmgr@ffd05000 {
+               compatible = "altr,rst-mgr";
+               reg = <0xffd05000 0x1000>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
new file mode 100644 (file)
index 0000000..07c65e3
--- /dev/null
@@ -0,0 +1,11 @@
+Altera SOCFPGA System Manager
+
+Required properties:
+- compatible : "altr,sys-mgr"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+        sysmgr@ffd08000 {
+               compatible = "altr,sys-mgr";
+               reg = <0xffd08000 0x1000>;
+       };
index 70c0dc5f00edef0414acf6519e1afcb43af230fd..61df564c0d238613e55b3057192528db54151e8b 100644 (file)
@@ -6,9 +6,15 @@ Required properties:
 - interrupt-controller: Identifies the node as an interrupt controller.
 - #interrupt-cells: The number of cells to define the interrupts. Should be 1.
   The cell is the IRQ number
+
 - reg: Should contain PMIC registers location and length. First pair
   for the main interrupt registers, second pair for the per-CPU
-  interrupt registers
+  interrupt registers. For this last pair, to be compliant with SMP
+  support, the "virtual" must be use (For the record, these registers
+  automatically map to the interrupt controller registers of the
+  current CPU)
+
+
 
 Example:
 
@@ -18,6 +24,6 @@ Example:
               #address-cells = <1>;
               #size-cells = <1>;
               interrupt-controller;
-              reg = <0xd0020000 0x1000>,
-                    <0xd0021000 0x1000>;
+              reg = <0xd0020a00 0x1d0>,
+                    <0xd0021070 0x58>;
         };
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt
new file mode 100644 (file)
index 0000000..926b4d6
--- /dev/null
@@ -0,0 +1,20 @@
+Power Management Service Unit(PMSU)
+-----------------------------------
+Available on Marvell SOCs: Armada 370 and Armada XP
+
+Required properties:
+
+- compatible: "marvell,armada-370-xp-pmsu"
+
+- reg: Should contain PMSU registers location and length. First pair
+  for the per-CPU SW Reset Control registers, second pair for the
+  Power Management Service Unit.
+
+Example:
+
+armada-370-xp-pmsu@d0022000 {
+       compatible = "marvell,armada-370-xp-pmsu";
+       reg = <0xd0022100 0x430>,
+             <0xd0020800 0x20>;
+};
+
index 8b6ea2267c94999ce0c64415b9474156352988b5..64830118b013fccea7e7ed878931e61baebc476f 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
 - compatible: Should be "marvell,armada-370-xp-timer"
 - interrupts: Should contain the list of Global Timer interrupts
 - reg: Should contain the base address of the Global Timer registers
+- clocks: clock driving the timer hardware
 
 Optional properties:
 - marvell,timer-25Mhz: Tells whether the Global timer supports the 25
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
new file mode 100644 (file)
index 0000000..17d8cd1
--- /dev/null
@@ -0,0 +1,21 @@
+Coherency fabric
+----------------
+Available on Marvell SOCs: Armada 370 and Armada XP
+
+Required properties:
+
+- compatible: "marvell,coherency-fabric"
+
+- reg: Should contain coherency fabric registers location and
+  length. First pair for the coherency fabric registers, second pair
+  for the per-CPU fabric registers registers.
+
+Example:
+
+coherency-fabric@d0020200 {
+       compatible = "marvell,coherency-fabric";
+       reg = <0xd0020200 0xb0>,
+               <0xd0021810 0x1c>;
+
+};
+
index 7c3ee3aeb7b706d6140bdcb2679beab497fdf357..cbef09b5c8a71672924360e028176488f03f2faa 100644 (file)
@@ -10,6 +10,12 @@ Required properties:
        "arm,pl310-cache"
        "arm,l220-cache"
        "arm,l210-cache"
+       "marvell,aurora-system-cache": Marvell Controller designed to be
+     compatible with the ARM one, with system cache mode (meaning
+     maintenance operations on L1 are broadcasted to the L2 and L2
+     performs the same operation).
+       "marvell,"aurora-outer-cache: Marvell Controller designed to be
+        compatible with the ARM one with outer cache mode.
 - cache-unified : Specifies the cache is a unified cache.
 - cache-level : Should be set to 2 for a level 2 cache.
 - reg : Physical base address and size of cache controller's memory mapped
@@ -29,6 +35,9 @@ Optional properties:
   filter. Addresses in the filter window are directed to the M1 port. Other
   addresses will go to the M0 port.
 - interrupts : 1 combined interrupt.
+- cache-id-part: cache id part number to be used if it is not present
+  on hardware
+- wt-override: If present then L2 is forced to Write through mode
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/spear/shirq.txt b/Documentation/devicetree/bindings/arm/spear/shirq.txt
new file mode 100644 (file)
index 0000000..13fbb88
--- /dev/null
@@ -0,0 +1,48 @@
+* SPEAr Shared IRQ layer (shirq)
+
+SPEAr3xx architecture includes shared/multiplexed irqs for certain set
+of devices. The multiplexor provides a single interrupt to parent
+interrupt controller (VIC) on behalf of a group of devices.
+
+There can be multiple groups available on SPEAr3xx variants but not
+exceeding 4. The number of devices in a group can differ, further they
+may share same set of status/mask registers spanning across different
+bit masks. Also in some cases the group may not have enable or other
+registers. This makes software little complex.
+
+A single node in the device tree is used to describe the shared
+interrupt multiplexor (one node for all groups). A group in the
+interrupt controller shares config/control registers with other groups.
+For example, a 32-bit interrupt enable/disable config register can
+accommodate upto 4 interrupt groups.
+
+Required properties:
+  - compatible: should be, either of
+     - "st,spear300-shirq"
+     - "st,spear310-shirq"
+     - "st,spear320-shirq"
+  - interrupt-controller: Identifies the node as an interrupt controller.
+  - #interrupt-cells: should be <1> which basically contains the offset
+    (starting from 0) of interrupts for all the groups.
+  - reg: Base address and size of shirq registers.
+  - interrupts: The list of interrupts generated by the groups which are
+    then connected to a parent interrupt controller. Each group is
+    associated with one of the interrupts, hence number of interrupts (to
+    parent) is equal to number of groups. The format of the interrupt
+    specifier depends in the interrupt parent controller.
+
+  Optional properties:
+  - interrupt-parent: pHandle of the parent interrupt controller, if not
+    inherited from the parent node.
+
+Example:
+
+The following is an example from the SPEAr320 SoC dtsi file.
+
+shirq: interrupt-controller@0xb3000000 {
+       compatible = "st,spear320-shirq";
+       reg = <0xb3000000 0x1000>;
+       interrupts = <28 29 30 1>;
+       #interrupt-cells = <1>;
+       interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
new file mode 100644 (file)
index 0000000..1e66294
--- /dev/null
@@ -0,0 +1,47 @@
+* Core Clock bindings for Marvell MVEBU SoCs
+
+Marvell MVEBU SoCs usually allow to determine core clock frequencies by
+reading the Sample-At-Reset (SAR) register. The core clock consumer should
+specify the desired clock by having the clock ID in its "clocks" phandle cell.
+
+The following is a list of provided IDs and clock names on Armada 370/XP:
+ 0 = tclk    (Internal Bus clock)
+ 1 = cpuclk  (CPU clock)
+ 2 = nbclk   (L2 Cache clock)
+ 3 = hclk    (DRAM control clock)
+ 4 = dramclk (DDR clock)
+
+The following is a list of provided IDs and clock names on Kirkwood and Dove:
+ 0 = tclk   (Internal Bus clock)
+ 1 = cpuclk (CPU0 clock)
+ 2 = l2clk  (L2 Cache clock derived from CPU0 clock)
+ 3 = ddrclk (DDR controller clock derived from CPU0 clock)
+
+Required properties:
+- compatible : shall be one of the following:
+       "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks
+       "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks
+       "marvell,dove-core-clock" - for Dove SoC core clocks
+       "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
+       "marvell,mv88f6180-core-clock" - for Kirkwood MV88f6180 SoC
+- reg : shall be the register address of the Sample-At-Reset (SAR) register
+- #clock-cells : from common clock binding; shall be set to 1
+
+Optional properties:
+- clock-output-names : from common clock binding; allows overwrite default clock
+       output names ("tclk", "cpuclk", "l2clk", "ddrclk")
+
+Example:
+
+core_clk: core-clocks@d0214 {
+       compatible = "marvell,dove-core-clock";
+       reg = <0xd0214 0x4>;
+       #clock-cells = <1>;
+};
+
+spi0: spi@10600 {
+       compatible = "marvell,orion-spi";
+       /* ... */
+       /* get tclk from core clock provider */
+       clocks = <&core_clk 0>;
+};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
new file mode 100644 (file)
index 0000000..feb8301
--- /dev/null
@@ -0,0 +1,21 @@
+Device Tree Clock bindings for cpu clock of Marvell EBU platforms
+
+Required properties:
+- compatible : shall be one of the following:
+       "marvell,armada-xp-cpu-clock" - cpu clocks for Armada XP
+- reg : Address and length of the clock complex register set
+- #clock-cells : should be set to 1.
+- clocks : shall be the input parent clock phandle for the clock.
+
+cpuclk: clock-complex@d0018700 {
+       #clock-cells = <1>;
+       compatible = "marvell,armada-xp-cpu-clock";
+       reg = <0xd0018700 0xA0>;
+       clocks = <&coreclk 1>;
+}
+
+cpu@0 {
+       compatible = "marvell,sheeva-v7";
+       reg = <0>;
+       clocks = <&cpuclk 0>;
+};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
new file mode 100644 (file)
index 0000000..7337005
--- /dev/null
@@ -0,0 +1,119 @@
+* Gated Clock bindings for Marvell Orion SoCs
+
+Marvell Dove and Kirkwood allow some peripheral clocks to be gated to save
+some power. The clock consumer should specify the desired clock by having
+the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to
+the corresponding clock gating control bit in HW to ease manual clock lookup
+in datasheet.
+
+The following is a list of provided IDs for Armada 370:
+ID     Clock   Peripheral
+-----------------------------------
+0      Audio   AC97 Cntrl
+1      pex0_en PCIe 0 Clock out
+2      pex1_en PCIe 1 Clock out
+3      ge1     Gigabit Ethernet 1
+4      ge0     Gigabit Ethernet 0
+5      pex0    PCIe Cntrl 0
+9      pex1    PCIe Cntrl 1
+15     sata0   SATA Host 0
+17     sdio    SDHCI Host
+25     tdm     Time Division Mplx
+28     ddr     DDR Cntrl
+30     sata1   SATA Host 0
+
+The following is a list of provided IDs for Armada XP:
+ID     Clock   Peripheral
+-----------------------------------
+0      audio   Audio Cntrl
+1      ge3     Gigabit Ethernet 3
+2      ge2     Gigabit Ethernet 2
+3      ge1     Gigabit Ethernet 1
+4      ge0     Gigabit Ethernet 0
+5      pex0    PCIe Cntrl 0
+6      pex1    PCIe Cntrl 1
+7      pex2    PCIe Cntrl 2
+8      pex3    PCIe Cntrl 3
+13     bp
+14     sata0lnk
+15     sata0   SATA Host 0
+16     lcd     LCD Cntrl
+17     sdio    SDHCI Host
+18     usb0    USB Host 0
+19     usb1    USB Host 1
+20     usb2    USB Host 2
+22     xor0    XOR DMA 0
+23     crypto  CESA engine
+25     tdm     Time Division Mplx
+28     xor1    XOR DMA 1
+29     sata1lnk
+30     sata1   SATA Host 0
+
+The following is a list of provided IDs for Dove:
+ID     Clock   Peripheral
+-----------------------------------
+0      usb0    USB Host 0
+1      usb1    USB Host 1
+2      ge      Gigabit Ethernet
+3      sata    SATA Host
+4      pex0    PCIe Cntrl 0
+5      pex1    PCIe Cntrl 1
+8      sdio0   SDHCI Host 0
+9      sdio1   SDHCI Host 1
+10     nand    NAND Cntrl
+11     camera  Camera Cntrl
+12     i2s0    I2S Cntrl 0
+13     i2s1    I2S Cntrl 1
+15     crypto  CESA engine
+21     ac97    AC97 Cntrl
+22     pdma    Peripheral DMA
+23     xor0    XOR DMA 0
+24     xor1    XOR DMA 1
+30     gephy   Gigabit Ethernel PHY
+Note: gephy(30) is implemented as a parent clock of ge(2)
+
+The following is a list of provided IDs for Kirkwood:
+ID     Clock   Peripheral
+-----------------------------------
+0      ge0     Gigabit Ethernet 0
+2      pex0    PCIe Cntrl 0
+3      usb0    USB Host 0
+4      sdio    SDIO Cntrl
+5      tsu     Transp. Stream Unit
+6      dunit   SDRAM Cntrl
+7      runit   Runit
+8      xor0    XOR DMA 0
+9      audio   I2S Cntrl 0
+14     sata0   SATA Host 0
+15     sata1   SATA Host 1
+16     xor1    XOR DMA 1
+17     crypto  CESA engine
+18     pex1    PCIe Cntrl 1
+19     ge1     Gigabit Ethernet 0
+20     tdm     Time Division Mplx
+
+Required properties:
+- compatible : shall be one of the following:
+       "marvell,dove-gating-clock" - for Dove SoC clock gating
+       "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
+- reg : shall be the register address of the Clock Gating Control register
+- #clock-cells : from common clock binding; shall be set to 1
+
+Optional properties:
+- clocks : default parent clock phandle (e.g. tclk)
+
+Example:
+
+gate_clk: clock-gating-control@d0038 {
+       compatible = "marvell,dove-gating-clock";
+       reg = <0xd0038 0x4>;
+       /* default parent clock is tclk */
+       clocks = <&core_clk 0>;
+       #clock-cells = <1>;
+};
+
+sdio0: sdio@92000 {
+       compatible = "marvell,dove-sdhci";
+       /* get clk gate bit 8 (sdio0) */
+       clocks = <&gate_clk 8>;
+};
index bd7ce120bc135e9eccb9f2cbdb3a38fdc15f9702..fc9ce6f1688cdb18db58a652f24fa4013de76bff 100644 (file)
@@ -54,7 +54,8 @@ PROPERTIES
    - compatible
       Usage: required
       Value type: <string>
-      Definition: Must include "fsl,sec-v4.0"
+      Definition: Must include "fsl,sec-v4.0". Also includes SEC
+           ERA versions (optional) with which the device is compatible.
 
    - #address-cells
        Usage: required
@@ -106,7 +107,7 @@ PROPERTIES
 
 EXAMPLE
        crypto@300000 {
-               compatible = "fsl,sec-v4.0";
+               compatible = "fsl,sec-v4.0", "fsl,sec-era-v2.0";
                #address-cells = <1>;
                #size-cells = <1>;
                reg = <0x300000 0x10000>;
diff --git a/Documentation/devicetree/bindings/dma/mv-xor.txt b/Documentation/devicetree/bindings/dma/mv-xor.txt
new file mode 100644 (file)
index 0000000..7c6cb7f
--- /dev/null
@@ -0,0 +1,40 @@
+* Marvell XOR engines
+
+Required properties:
+- compatible: Should be "marvell,orion-xor"
+- reg: Should contain registers location and length (two sets)
+    the first set is the low registers, the second set the high
+    registers for the XOR engine.
+- clocks: pointer to the reference clock
+
+The DT node must also contains sub-nodes for each XOR channel that the
+XOR engine has. Those sub-nodes have the following required
+properties:
+- interrupts: interrupt of the XOR channel
+
+And the following optional properties:
+- dmacap,memcpy to indicate that the XOR channel is capable of memcpy operations
+- dmacap,memset to indicate that the XOR channel is capable of memset operations
+- dmacap,xor to indicate that the XOR channel is capable of xor operations
+
+Example:
+
+xor@d0060900 {
+       compatible = "marvell,orion-xor";
+       reg = <0xd0060900 0x100
+              0xd0060b00 0x100>;
+       clocks = <&coreclk 0>;
+       status = "okay";
+
+       xor00 {
+             interrupts = <51>;
+             dmacap,memcpy;
+             dmacap,xor;
+       };
+       xor01 {
+             interrupts = <52>;
+             dmacap,memcpy;
+             dmacap,xor;
+             dmacap,memset;
+       };
+};
index ce83c8d3c00e262953b543717c00105ac92edf64..13b707b7355c005e9c877e860c93d4e9ca6baf12 100644 (file)
@@ -24,7 +24,32 @@ ab8500-bm                :                      :              : Battery Manager
 ab8500-btemp             :                      :              : Battery Temperature
 ab8500-charger           :                      :              : Battery Charger
 ab8500-codec             :                      :              : Audio Codec
-ab8500-fg                :                      :              : Fuel Gauge
+ab8500-fg                :                     : vddadc       : Fuel Gauge
+                        : NCONV_ACCU           :              : Accumulate N Sample Conversion
+                        : BATT_OVV             :              : Battery Over Voltage
+                        : LOW_BAT_F            :              : LOW threshold battery voltage
+                        : CC_INT_CALIB         :              : Coulomb Counter Internal Calibration
+                        : CCEOC                :              : Coulomb Counter End of Conversion
+ab8500-btemp            :                      : vtvout       : Battery Temperature
+                        : BAT_CTRL_INDB        :              : Battery Removal Indicator
+                        : BTEMP_LOW            :              : Btemp < BtempLow, if battery temperature is lower than -10°C
+                        : BTEMP_LOW_MEDIUM     :              : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C
+                        : BTEMP_MEDIUM_HIGH    :              : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp
+                        : BTEMP_HIGH           :              : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp
+ab8500-charger          :                      : vddadc       : Charger interface
+                        : MAIN_CH_UNPLUG_DET   :              : main charger unplug detection management (not in 8505)
+                        : MAIN_CHARGE_PLUG_DET :              : main charger plug detection management (not in 8505)
+                        : MAIN_EXT_CH_NOT_OK   :              : main charger not OK
+                        : MAIN_CH_TH_PROT_R    :              : Die temp is above main charger
+                        : MAIN_CH_TH_PROT_F    :              : Die temp is below main charger
+                        : VBUS_DET_F           :              : VBUS falling detected
+                        : VBUS_DET_R           :              : VBUS rising detected
+                        : USB_LINK_STATUS      :              : USB link status has changed
+                        : USB_CH_TH_PROT_R     :              : Die temp is above usb charger
+                        : USB_CH_TH_PROT_F     :              : Die temp is below usb charger
+                        : USB_CHARGER_NOT_OKR  :              : allowed USB charger not ok detection
+                        : VBUS_OVV             :              : Overvoltage on Vbus ball detected (USB charge is stopped)
+                        : CH_WD_EXP            :              : Charger watchdog detected
 ab8500-gpadc             : HW_CONV_END          : vddadc       : Analogue to Digital Converter
                            SW_CONV_END          :              :
 ab8500-gpio              :                      :              : GPIO Controller
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
new file mode 100644 (file)
index 0000000..38e51ad
--- /dev/null
@@ -0,0 +1,15 @@
+* Atmel SSC driver.
+
+Required properties:
+- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc"
+       - atmel,at91rm9200-ssc: support pdc transfer
+       - atmel,at91sam9g45-ssc: support dma transfer
+- reg: Should contain SSC registers location and length
+- interrupts: Should contain SSC interrupt
+
+Example:
+ssc0: ssc@fffbc000 {
+       compatible = "atmel,at91rm9200-ssc";
+       reg = <0xfffbc000 0x4000>;
+       interrupts = <14 4 5>;
+};
diff --git a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
new file mode 100644 (file)
index 0000000..859a6fa
--- /dev/null
@@ -0,0 +1,23 @@
+* Marvell Armada 370 / Armada XP Ethernet Controller (NETA)
+
+Required properties:
+- compatible: should be "marvell,armada-370-neta".
+- reg: address and length of the register set for the device.
+- interrupts: interrupt for the device
+- phy: A phandle to a phy node defining the PHY address (as the reg
+  property, a single integer).
+- phy-mode: The interface between the SoC and the PHY (a string that
+  of_get_phy_mode() can understand)
+- clocks: a pointer to the reference clock for this device.
+
+Example:
+
+ethernet@d0070000 {
+       compatible = "marvell,armada-370-neta";
+       reg = <0xd0070000 0x2500>;
+       interrupts = <8>;
+       clocks = <&gate_clk 4>;
+       status = "okay";
+       phy = <&phy0>;
+       phy-mode = "rgmii-id";
+};
diff --git a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
new file mode 100644 (file)
index 0000000..34e7aaf
--- /dev/null
@@ -0,0 +1,35 @@
+* Marvell MDIO Ethernet Controller interface
+
+The Ethernet controllers of the Marvel Kirkwood, Dove, Orion5x,
+MV78xx0, Armada 370 and Armada XP have an identical unit that provides
+an interface with the MDIO bus. This driver handles this MDIO
+interface.
+
+Required properties:
+- compatible: "marvell,orion-mdio"
+- reg: address and length of the SMI register
+
+The child nodes of the MDIO driver are the individual PHY devices
+connected to this MDIO bus. They must have a "reg" property given the
+PHY address on the MDIO bus.
+
+Example at the SoC level:
+
+mdio {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       compatible = "marvell,orion-mdio";
+       reg = <0xd0072004 0x4>;
+};
+
+And at the board level:
+
+mdio {
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+}
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt
new file mode 100644 (file)
index 0000000..0ba1bcc
--- /dev/null
@@ -0,0 +1,16 @@
+=== AB8500 Battery Temperature Monitor Driver ===
+
+The properties below describes the node for btemp driver.
+
+Required Properties:
+- compatible = Shall be: "stericsson,ab8500-btemp"
+- battery = Shall be battery specific information
+
+       Example:
+       ab8500_btemp {
+               compatible = "stericsson,ab8500-btemp";
+               battery    = <&ab8500_battery>;
+       };
+
+For information on battery specific node, Ref:
+Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt
new file mode 100644 (file)
index 0000000..ef53283
--- /dev/null
@@ -0,0 +1,16 @@
+=== AB8500 Charging Algorithm Driver ===
+
+The properties below describes the node for chargalg driver.
+
+Required Properties:
+- compatible = Shall be: "stericsson,ab8500-chargalg"
+- battery = Shall be battery specific information
+
+Example:
+ab8500_chargalg {
+       compatible = "stericsson,ab8500-chargalg";
+       battery    = <&ab8500_battery>;
+};
+
+For information on battery specific node, Ref:
+Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt
new file mode 100644 (file)
index 0000000..6bdbb08
--- /dev/null
@@ -0,0 +1,25 @@
+=== AB8500 Charger Driver ===
+
+Required Properties:
+- compatible = Shall be "stericsson,ab8500-charger"
+- battery = Shall be battery specific information
+       Example:
+       ab8500_charger {
+               compatible = "stericsson,ab8500-charger";
+               battery    = <&ab8500_battery>;
+       };
+
+- vddadc-supply: Supply for USB and Main charger
+       Example:
+       ab8500-charger {
+               vddadc-supply   = <&ab8500_ldo_tvout_reg>;
+       }
+- autopower_cfg:
+       Boolean value depicting the presence of 'automatic poweron after powerloss'
+       Example:
+       ab8500-charger {
+               autopower_cfg;
+       };
+
+For information on battery specific node, Ref:
+Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
new file mode 100644 (file)
index 0000000..ccafcb9
--- /dev/null
@@ -0,0 +1,58 @@
+=== AB8500 Fuel Gauge Driver ===
+
+AB8500 is a mixed signal multimedia and power management
+device comprising: power and energy-management-module,
+wall-charger, usb-charger, audio codec, general purpose adc,
+tvout, clock management and sim card interface.
+
+Fuelgauge support is part of energy-management-modules, other
+components of this module are:
+main-charger, usb-combo-charger and battery-temperature-monitoring.
+
+The properties below describes the node for fuelgauge driver.
+
+Required Properties:
+- compatible = This shall be: "stericsson,ab8500-fg"
+- battery = Shall be battery specific information
+       Example:
+       ab8500_fg {
+               compatible = "stericsson,ab8500-fg";
+               battery    = <&ab8500_battery>;
+       };
+
+dependent node:
+       ab8500_battery: ab8500_battery {
+       };
+       This node will provide information on 'thermistor interface' and
+       'battery technology type' used.
+
+Properties of this node are:
+thermistor-on-batctrl:
+       A boolean value indicating thermistor interface to battery
+
+       Note:
+       'btemp' and 'batctrl' are the pins interfaced for battery temperature
+       measurement, 'btemp' signal is used when NTC(negative temperature
+       coefficient) resister is interfaced external to battery whereas
+       'batctrl' pin is used when NTC resister is internal to battery.
+
+       Example:
+       ab8500_battery: ab8500_battery {
+               thermistor-on-batctrl;
+       };
+       indicates: NTC resister is internal to battery, 'batctrl' is used
+               for thermal measurement.
+
+       The absence of property 'thermal-on-batctrl' indicates
+       NTC resister is external to battery and  'btemp' signal is used
+       for thermal measurement.
+
+battery-type:
+       This shall be the battery manufacturing technology type,
+       allowed types are:
+               "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
+       Example:
+       ab8500_battery: ab8500_battery {
+               stericsson,battery-type = "LIPO";
+       }
+
diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
new file mode 100644 (file)
index 0000000..63c6598
--- /dev/null
@@ -0,0 +1,37 @@
+GPIO controlled regulators
+
+Required properties:
+- compatible           : Must be "regulator-gpio".
+- states               : Selection of available voltages and GPIO configs.
+                          if there are no states, then use a fixed regulator
+
+Optional properties:
+- enable-gpio          : GPIO to use to enable/disable the regulator.
+- gpios                        : GPIO group used to control voltage.
+- startup-delay-us     : Startup time in microseconds.
+- enable-active-high   : Polarity of GPIO is active high (default is low).
+
+Any property defined as part of the core regulator binding defined in
+regulator.txt can also be used.
+
+Example:
+
+       mmciv: gpio-regulator {
+               compatible = "regulator-gpio";
+
+               regulator-name = "mmci-gpio-supply";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2600000>;
+               regulator-boot-on;
+
+               enable-gpio = <&gpio0 23 0x4>;
+               gpios = <&gpio0 24 0x4
+                        &gpio0 25 0x4>;
+               states = <1800000 0x3
+                         2200000 0x2
+                         2600000 0x1
+                         2900000 0x0>;
+
+               startup-delay-us = <100000>;
+               enable-active-high;
+       };
diff --git a/Documentation/devicetree/bindings/regulator/max8925-regulator.txt b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
new file mode 100644 (file)
index 0000000..0057695
--- /dev/null
@@ -0,0 +1,40 @@
+Max8925 Voltage regulators
+
+Required nodes:
+-nodes:
+  - SDV1 for SDV SDV1
+  - SDV2 for SDV SDV2
+  - SDV3 for SDV SDV3
+  - LDO1 for LDO LDO1
+  - LDO2 for LDO LDO2
+  - LDO3 for LDO LDO3
+  - LDO4 for LDO LDO4
+  - LDO5 for LDO LDO5
+  - LDO6 for LDO LDO6
+  - LDO7 for LDO LDO7
+  - LDO8 for LDO LDO8
+  - LDO9 for LDO LDO9
+  - LDO10 for LDO LDO10
+  - LDO11 for LDO LDO11
+  - LDO12 for LDO LDO12
+  - LDO13 for LDO LDO13
+  - LDO14 for LDO LDO14
+  - LDO15 for LDO LDO15
+  - LDO16 for LDO LDO16
+  - LDO17 for LDO LDO17
+  - LDO18 for LDO LDO18
+  - LDO19 for LDO LDO19
+  - LDO20 for LDO LDO20
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+       SDV1 {
+               regulator-min-microvolt = <637500>;
+               regulator-max-microvolt = <1425000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
diff --git a/Documentation/devicetree/bindings/regulator/max8997-regulator.txt b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt
new file mode 100644 (file)
index 0000000..9fd69a1
--- /dev/null
@@ -0,0 +1,146 @@
+* Maxim MAX8997 Voltage and Current Regulator
+
+The Maxim MAX8997 is a multi-function device which includes volatage and
+current regulators, rtc, charger controller and other sub-blocks. It is
+interfaced to the host controller using a i2c interface. Each sub-block is
+addressed by the host system using different i2c slave address. This document
+describes the bindings for 'pmic' sub-block of max8997.
+
+Required properties:
+- compatible: Should be "maxim,max8997-pmic".
+- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
+
+- max8997,pmic-buck1-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck1 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+- max8997,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck2 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+- max8997,pmic-buck5-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck5 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+[1] If none of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+    property is specified, the 'max8997,pmic-buck[1/2/5]-dvs-voltage'
+    property should specify atleast one voltage level (which would be a
+    safe operating voltage).
+
+    If either of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+    property is specified, then all the eigth voltage values for the
+    'max8997,pmic-buck[1/2/5]-dvs-voltage' should be specified.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from max8997 are delivered to.
+- interrupts: Interrupt specifiers for two interrupt sources.
+  - First interrupt specifier is for 'irq1' interrupt.
+  - Second interrupt specifier is for 'alert' interrupt.
+- max8997,pmic-buck1-uses-gpio-dvs: 'buck1' can be controlled by gpio dvs.
+- max8997,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
+- max8997,pmic-buck5-uses-gpio-dvs: 'buck5' can be controlled by gpio dvs.
+
+Additional properties required if either of the optional properties are used:
+- max8997,pmic-ignore-gpiodvs-side-effect: When GPIO-DVS mode is used for
+  multiple bucks, changing the voltage value of one of the bucks may affect
+  that of another buck, which is the side effect of the change (set_voltage).
+  Use this property to ignore such side effects and change the voltage.
+
+- max8997,pmic-buck125-default-dvs-idx: Default voltage setting selected from
+  the possible 8 options selectable by the dvs gpios. The value of this
+  property should be between 0 and 7. If not specified or if out of range, the
+  default value of this property is set to 0.
+
+- max8997,pmic-buck125-dvs-gpios: GPIO specifiers for three host gpio's used
+  for dvs. The format of the gpio specifier depends in the gpio controller.
+
+Regulators: The regulators of max8997 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+       regulator_name {
+               standard regulator bindings here
+       };
+
+The following are the names of the regulators that the max8997 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of max8997.
+
+       - LDOn
+                 - valid values for n are 1 to 18 and 21
+                 - Example: LDO0, LD01, LDO2, LDO21
+       - BUCKn
+                 - valid values for n are 1 to 7.
+                 - Example: BUCK1, BUCK2, BUCK3, BUCK7
+
+       - ENVICHG: Battery Charging Current Monitor Output. This is a fixed
+                  voltage type regulator
+
+       - ESAFEOUT1: (ldo19)
+       - ESAFEOUT2: (ld020)
+
+       - CHARGER_CV: main battery charger voltage control
+       - CHARGER: main battery charger current control
+       - CHARGER_TOPOFF: end of charge current threshold level
+
+The bindings inside the regulator nodes use the standard regulator bindings
+which are documented elsewhere.
+
+Example:
+
+       max8997_pmic@66 {
+               compatible = "maxim,max8997-pmic";
+               interrupt-parent = <&wakeup_eint>;
+               reg = <0x66>;
+               interrupts = <4 0>, <3 0>;
+
+               max8997,pmic-buck1-uses-gpio-dvs;
+               max8997,pmic-buck2-uses-gpio-dvs;
+               max8997,pmic-buck5-uses-gpio-dvs;
+
+               max8997,pmic-ignore-gpiodvs-side-effect;
+               max8997,pmic-buck125-default-dvs-idx = <0>;
+
+               max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+                                                <&gpx0 1 1 0 0>, /* SET2 */
+                                                <&gpx0 2 1 0 0>; /* SET3 */
+
+               max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+                                                <1250000>, <1200000>,
+                                                <1150000>, <1100000>,
+                                                <1000000>, <950000>;
+
+               max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
+                                                <1100000>, <1100000>,
+                                                <1000000>, <1000000>,
+                                                <1000000>, <1000000>;
+
+               max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>;
+
+               regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "VDD_ABB_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       ldo2_reg: LDO2 {
+                               regulator-name = "VDD_ALIVE_1.1V";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "VDD_ARM_1.2V";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt
new file mode 100644 (file)
index 0000000..d775f72
--- /dev/null
@@ -0,0 +1,32 @@
+Versatile Express voltage regulators
+------------------------------------
+
+Requires node properties:
+- "compatible" value: "arm,vexpress-volt"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+  (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+  for more details)
+
+Required regulator properties:
+- "regulator-name"
+- "regulator-always-on"
+
+Optional regulator properties:
+- "regulator-min-microvolt"
+- "regulator-max-microvolt"
+
+See Documentation/devicetree/bindings/regulator/regulator.txt
+for more details about the regulator properties.
+
+When no "regulator-[min|max]-microvolt" properties are defined,
+the device is treated as fixed (or rather "read-only") regulator.
+
+Example:
+       volt@0 {
+               compatible = "arm,vexpress-volt";
+               arm,vexpress-sysreg,func = <2 0>;
+               regulator-name = "Cores";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1050000>;
+               regulator-always-on;
+       };
diff --git a/Documentation/devicetree/bindings/sound/ak4104.txt b/Documentation/devicetree/bindings/sound/ak4104.txt
new file mode 100644 (file)
index 0000000..b902ee3
--- /dev/null
@@ -0,0 +1,22 @@
+AK4104 S/PDIF transmitter
+
+This device supports SPI mode only.
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak4104"
+
+  - reg : The chip select number on the SPI bus
+
+Optional properties:
+
+  - reset-gpio : a GPIO spec for the reset pin. If specified, it will be
+                deasserted before communication to the device starts.
+
+Example:
+
+spdif: ak4104@0 {
+       compatible = "asahi-kasei,ak4104";
+       reg = <0>;
+       spi-max-frequency = <5000000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
new file mode 100644 (file)
index 0000000..9c5a994
--- /dev/null
@@ -0,0 +1,26 @@
+* Atmel at91sam9g20ek wm8731 audio complex
+
+Required properties:
+  - compatible: "atmel,at91sam9g20ek-wm8731-audio"
+  - atmel,model: The user-visible name of this sound complex.
+  - atmel,audio-routing: A list of the connections between audio components.
+  - atmel,ssc-controller: The phandle of the SSC controller
+  - atmel,audio-codec: The phandle of the WM8731 audio codec
+Optional properties:
+  - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
+
+Example:
+sound {
+       compatible = "atmel,at91sam9g20ek-wm8731-audio";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+       atmel,model = "wm8731 @ AT91SAMG20EK";
+
+       atmel,audio-routing =
+               "Ext Spk", "LHPOUT",
+               "Int MIC", "MICIN";
+
+       atmel,ssc-controller = <&ssc0>;
+       atmel,audio-codec = <&wm8731>;
+};
index c81b5fd5a5bc80459a1b2d626c9f20b5a86bfbe9..a850fb9c88eab2156ec89f0c76d8ca59073540f8 100644 (file)
@@ -18,6 +18,8 @@ Optional properties:
 
  - reset-gpio:         a GPIO spec to define which pin is connected to the chip's
                !RESET pin
+ - cirrus,amuteb-eq-bmutec:    When given, the Codec's AMUTEB=BMUTEC flag
+                               is enabled.
 
 Examples:
 
index 65dec876cb2d792813abc050833950ef48b53a66..fd40c852d7c7e18c12e5fabc49f0b141614267ac 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Optional properties:
 - ti,dmic: phandle for the OMAP dmic node if the machine have it connected
-- ti,jack_detection: Need to be set to <1> if the board capable to detect jack
+- ti,jack_detection: Need to be present if the board capable to detect jack
   insertion, removal.
 
 Available audio endpoints for the audio-routing table:
@@ -59,7 +59,7 @@ sound {
        compatible = "ti,abe-twl6040";
        ti,model = "SDP4430";
 
-       ti,jack-detection = <1>;
+       ti,jack-detection;
        ti,mclk-freq = <38400000>;
 
        ti,mcpdm = <&mcpdm>;
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt
new file mode 100644 (file)
index 0000000..8cf24f6
--- /dev/null
@@ -0,0 +1,26 @@
+NVIDIA Tegra20 SFLASH controller.
+
+Required properties:
+- compatible : should be "nvidia,tegra20-sflash".
+- reg: Should contain SFLASH registers location and length.
+- interrupts: Should contain SFLASH interrupts.
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this SFLASH controller.
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+spi@7000d600 {
+       compatible = "nvidia,tegra20-sflash";
+       reg = <0x7000c380 0x80>;
+       interrupts = <0 39 0x04>;
+       nvidia,dma-request-selector = <&apbdma 16>;
+       spi-max-frequency = <25000000>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       status = "disabled";
+};
+
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt
new file mode 100644 (file)
index 0000000..f5b1ad1
--- /dev/null
@@ -0,0 +1,26 @@
+NVIDIA Tegra20/Tegra30 SLINK controller.
+
+Required properties:
+- compatible : should be "nvidia,tegra20-slink", "nvidia,tegra30-slink".
+- reg: Should contain SLINK registers location and length.
+- interrupts: Should contain SLINK interrupts.
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this SLINK controller.
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+slink@7000d600 {
+       compatible = "nvidia,tegra20-slink";
+       reg = <0x7000d600 0x200>;
+       interrupts = <0 82 0x04>;
+       nvidia,dma-request-selector = <&apbdma 16>;
+       spi-max-frequency = <25000000>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       status = "disabled";
+};
+
index 81df374adbb97f53a8c7b8d56cb21e70e5d39cb3..938809c6829bfdffd6b14af8005a60c2e7e003be 100644 (file)
@@ -6,7 +6,9 @@ Required properties:
   - "ti,omap4-spi" for OMAP4+.
 - ti,spi-num-cs : Number of chipselect supported  by the instance.
 - ti,hwmods: Name of the hwmod associated to the McSPI
-
+- ti,pindir-d0-out-d1-in: Select the D0 pin as output and D1 as
+                         input. The default is D0 as input and
+                         D1 as output.
 
 Example:
 
index d2c33d0f533ec8702938b017c470faf073db9032..296015e3c632af7d7f6dbc85e862bfd20044a296 100644 (file)
@@ -12,6 +12,7 @@ The SPI master node requires the following properties:
 - #size-cells     - should be zero.
 - compatible      - name of SPI bus controller following generic names
                recommended practice.
+- cs-gpios       - (optional) gpios chip select.
 No other properties are required in the SPI bus node.  It is assumed
 that a driver for an SPI bus device will understand that it is an SPI bus.
 However, the binding does not attempt to define the specific method for
@@ -24,6 +25,22 @@ support describing the chip select layout.
 Optional property:
 - num-cs : total number of chipselects
 
+If cs-gpios is used the number of chip select will automatically increased
+with max(cs-gpios > hw cs)
+
+So if for example the controller has 2 CS lines, and the cs-gpios
+property looks like this:
+
+cs-gpios = <&gpio1 0 0> <0> <&gpio1 1 0> <&gpio1 2 0>;
+
+Then it should be configured so that num_chipselect = 4 with the
+following mapping:
+
+cs0 : &gpio1 0 0
+cs1 : native
+cs2 : &gpio1 1 0
+cs3 : &gpio1 2 0
+
 SPI slave nodes must be children of the SPI master node and can
 contain the following properties.
 - reg             - (required) chip select address of device.
@@ -36,6 +53,11 @@ contain the following properties.
                shifted clock phase (CPHA) mode
 - spi-cs-high     - (optional) Empty property indicating device requires
                chip select active high
+- spi-3wire       - (optional) Empty property indicating device requires
+                   3-wire mode.
+
+If a gpio chipselect is used for the SPI slave the gpio number will be passed
+via the cs_gpio
 
 SPI example for an MPC5200 SPI bus:
        spi@f00 {
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
new file mode 100644 (file)
index 0000000..c60da67
--- /dev/null
@@ -0,0 +1,80 @@
+The Exynos display port interface should be configured based on
+the type of panel connected to it.
+
+We use two nodes:
+       -dp-controller node
+       -dptx-phy node(defined inside dp-controller node)
+
+For the DP-PHY initialization, we use the dptx-phy node.
+Required properties for dptx-phy:
+       -reg:
+               Base address of DP PHY register.
+       -samsung,enable-mask:
+               The bit-mask used to enable/disable DP PHY.
+
+For the Panel initialization, we read data from dp-controller node.
+Required properties for dp-controller:
+       -compatible:
+               should be "samsung,exynos5-dp".
+       -reg:
+               physical base address of the controller and length
+               of memory mapped region.
+       -interrupts:
+               interrupt combiner values.
+       -interrupt-parent:
+               phandle to Interrupt combiner node.
+       -samsung,color-space:
+               input video data format.
+                       COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
+       -samsung,dynamic-range:
+               dynamic range for input video data.
+                       VESA = 0, CEA = 1
+       -samsung,ycbcr-coeff:
+               YCbCr co-efficients for input video.
+                       COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
+       -samsung,color-depth:
+               number of bits per colour component.
+                       COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
+       -samsung,link-rate:
+               link rate supported by the panel.
+                       LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
+       -samsung,lane-count:
+               number of lanes supported by the panel.
+                       LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+
+Optional properties for dp-controller:
+       -interlaced:
+               interlace scan mode.
+                       Progressive if defined, Interlaced if not defined
+       -vsync-active-high:
+               VSYNC polarity configuration.
+                       High if defined, Low if not defined
+       -hsync-active-high:
+               HSYNC polarity configuration.
+                       High if defined, Low if not defined
+
+Example:
+
+SOC specific portion:
+       dp-controller {
+               compatible = "samsung,exynos5-dp";
+               reg = <0x145b0000 0x10000>;
+               interrupts = <10 3>;
+               interrupt-parent = <&combiner>;
+
+               dptx-phy {
+                       reg = <0x10040720>;
+                       samsung,enable-mask = <1>;
+               };
+
+       };
+
+Board Specific portion:
+       dp-controller {
+               samsung,color-space = <0>;
+               samsung,dynamic-range = <0>;
+               samsung,ycbcr-coeff = <0>;
+               samsung,color-depth = <1>;
+               samsung,link-rate = <0x0a>;
+               samsung,lane-count = <4>;
+       };
diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
new file mode 100644 (file)
index 0000000..3d0060c
--- /dev/null
@@ -0,0 +1,24 @@
+* Solomon SSD1307 Framebuffer Driver
+
+Required properties:
+  - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
+    now is i2c.
+  - reg: Should contain address of the controller on the I2C bus. Most likely
+         0x3c or 0x3d
+  - pwm: Should contain the pwm to use according to the OF device tree PWM
+         specification [0]
+  - reset-gpios: Should contain the GPIO used to reset the OLED display
+
+Optional properties:
+  - reset-active-low: Is the reset gpio is active on physical low?
+
+[0]: Documentation/devicetree/bindings/pwm/pwm.txt
+
+Examples:
+ssd1307: oled@3c {
+        compatible = "solomon,ssd1307fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+};
index ad86fb86c9a0252ba7c51df8d5ddcf91d71eb6ed..0188903bc9e1ede2c5668d5d78c632d2c4f923b3 100644 (file)
@@ -376,7 +376,7 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
    leaving the cpu domain and flushing caches at fault time. Note that all the
    dma_buf files share the same anon inode, hence the exporter needs to replace
    the dma_buf file stored in vma->vm_file with it's own if pte shootdown is
-   requred. This is because the kernel uses the underlying inode's address_space
+   required. This is because the kernel uses the underlying inode's address_space
    for vma tracking (and hence pte tracking at shootdown time with
    unmap_mapping_range).
 
@@ -388,7 +388,7 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
    Exporters that shoot down mappings (for any reasons) shall not do any
    synchronization at fault time with outstanding device operations.
    Synchronization is an orthogonal issue to sharing the backing storage of a
-   buffer and hence should not be handled by dma-buf itself. This is explictly
+   buffer and hence should not be handled by dma-buf itself. This is explicitly
    mentioned here because many people seem to want something like this, but if
    different exporters handle this differently, buffer sharing can fail in
    interesting ways depending upong the exporter (if userspace starts depending
index 74c25c8d8884633c7275b590a48a229482685bbd..b89a739a32761db0f9100395fd6426352ad9167c 100644 (file)
@@ -181,7 +181,6 @@ modversions.h*
 nconf
 ncscope.*
 offset.h
-offsets.h
 oui.c*
 page-types
 parse.c
index c83526c364e58433ec96023d5e8fa4deeebe9f95..09adabef513ff863ae6f413a239b0b79f90d575b 100644 (file)
@@ -1,7 +1,7 @@
 Notifier error injection
 ========================
 
-Notifier error injection provides the ability to inject artifical errors to
+Notifier error injection provides the ability to inject artificial errors to
 specified notifier chain callbacks. It is useful to test the error handling of
 notifier call chain failures which is rarely executed.  There are kernel
 modules that can be used to test the following notifiers.
@@ -14,7 +14,7 @@ modules that can be used to test the following notifiers.
 CPU notifier error injection module
 -----------------------------------
 This feature can be used to test the error handling of the CPU notifiers by
-injecting artifical errors to CPU notifier chain callbacks.
+injecting artificial errors to CPU notifier chain callbacks.
 
 If the notifier call chain should be failed with some events notified, write
 the error code to debugfs interface
index 8c624a18f67d4391b897b5524f3bd28e4a979722..7b52ba7bf32aaf255c0bc7c584609834f6748c0b 100644 (file)
@@ -38,6 +38,8 @@ dnotify_test.c
        - example program for dnotify
 ecryptfs.txt
        - docs on eCryptfs: stacked cryptographic filesystem for Linux.
+efivarfs.txt
+       - info for the efivarfs filesystem.
 exofs.txt
        - info, usage, mount options, design about EXOFS.
 ext2.txt
diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt
new file mode 100644 (file)
index 0000000..c477af0
--- /dev/null
@@ -0,0 +1,16 @@
+
+efivarfs - a (U)EFI variable filesystem
+
+The efivarfs filesystem was created to address the shortcomings of
+using entries in sysfs to maintain EFI variables. The old sysfs EFI
+variables code only supported variables of up to 1024 bytes. This
+limitation existed in version 0.99 of the EFI specification, but was
+removed before any full releases. Since variables can now be larger
+than a single page, sysfs isn't the best interface for this.
+
+Variables can be created, deleted and modified with the efivarfs
+filesystem.
+
+efivarfs is typically mounted like this,
+
+       mount -t efivarfs none /sys/firmware/efi/efivars
index 4627c4241ece699cedbe6660c7754e12933c4c2c..3c741214dfbbb028044be22a88c5359f7ba49646 100644 (file)
@@ -108,7 +108,7 @@ the request was handled successfully.
   UHID_FEATURE_ANSWER:
   If you receive a UHID_FEATURE request you must answer with this request. You
   must copy the "id" field from the request into the answer. Set the "err" field
-  to 0 if no error occured or to EIO if an I/O error occurred.
+  to 0 if no error occurred or to EIO if an I/O error occurred.
   If "err" is 0 then you should fill the buffer of the answer with the results
   of the feature request and set "size" correspondingly.
 
index f90f99920cc5ea49664aa1c6ed334f1619cbd94c..3d3a0f97f966f677e76a5d9685036edc43022ca6 100644 (file)
@@ -138,7 +138,7 @@ Sysfs entries
 
 When probing the chip, the driver identifies which PMBus registers are
 supported, and determines available sensors from this information.
-Attribute files only exist if respective sensors are suported by the chip.
+Attribute files only exist if respective sensors are supported by the chip.
 Labels are provided to inform the user about the sensor associated with
 a given sysfs entry.
 
index ae8ba9a74ce13e68519c2afa535c4cd06a4827db..3262b6e4d686ac944f7e767642228f4d4cc2f8f6 100644 (file)
@@ -133,7 +133,7 @@ number of contacts (f1 and f0 in the table below).
 
 This packet only appears after a position packet with the mt bit set, and
 usually only appears when there are two or more contacts (although
-occassionally it's seen with only a single contact).
+occasionally it's seen with only a single contact).
 
 The final v3 packet type is the trackstick packet.
 
index 53305bd08182dac8db030112ed9dadf1bf99efc9..f1ea2c69648dcad46d061a78ac33036d3ac5c727 100644 (file)
@@ -196,6 +196,17 @@ EV_MSC:
 EV_MSC events are used for input and output events that do not fall under other
 categories.
 
+A few EV_MSC codes have special meaning:
+
+* MSC_TIMESTAMP:
+  - Used to report the number of microseconds since the last reset. This event
+    should be coded as an uint32 value, which is allowed to wrap around with
+    no special consequence. It is assumed that the time difference between two
+    consecutive events is reliable on a reasonable time scale (hours).
+    A reset to zero can happen, in which case the time since the last event is
+    unknown.  If the device does not provide this information, the driver must
+    not provide it to user space.
+
 EV_LED:
 ----------
 EV_LED events are used for input and output to set and query the state of
index 3fb39e0116b4c8e42d40009357ed5cf13c1f2888..69372fb98cf89e4971e1520cd335ff66f27f7a6f 100644 (file)
@@ -470,7 +470,7 @@ build.
 
        Sometimes, an external module uses exported symbols from
        another external module. kbuild needs to have full knowledge of
-       all symbols to avoid spitting out warnings about undefined
+       all symbols to avoid spliitting out warnings about undefined
        symbols. Three solutions exist for this situation.
 
        NOTE: The method with a top-level kbuild file is recommended
index 3d8a97747f7731c801ca7d3a1483858feeb76b6c..99b57abddf8a186e2dcb399e167778c3605147df 100644 (file)
@@ -64,6 +64,8 @@ Example kernel-doc function comment:
  * comment lines.
  *
  * The longer description can have multiple paragraphs.
+ *
+ * Return: Describe the return value of foobar.
  */
 
 The short description following the subject can span multiple lines
@@ -78,6 +80,8 @@ If a function parameter is "..." (varargs), it should be listed in
 kernel-doc notation as:
  * @...: description
 
+The return value, if any, should be described in a dedicated section
+named "Return".
 
 Example kernel-doc data structure comment.
 
@@ -222,6 +226,9 @@ only a "*").
 "section header:" names must be unique per function (or struct,
 union, typedef, enum).
 
+Use the section header "Return" for sections describing the return value
+of a function.
+
 Avoid putting a spurious blank line after the function name, or else the
 description will be repeated!
 
@@ -237,21 +244,21 @@ patterns, which are highlighted appropriately.
 NOTE 1:  The multi-line descriptive text you provide does *not* recognize
 line breaks, so if you try to format some text nicely, as in:
 
-  Return codes
+  Return:
     0 - cool
     1 - invalid arg
     2 - out of memory
 
 this will all run together and produce:
 
-  Return codes 0 - cool 1 - invalid arg 2 - out of memory
+  Return: 0 - cool 1 - invalid arg 2 - out of memory
 
 NOTE 2:  If the descriptive text you provide has lines that begin with
 some phrase followed by a colon, each of those phrases will be taken as
 a new section heading, which means you should similarly try to avoid text
 like:
 
-  Return codes:
+  Return:
     0: cool
     1: invalid arg
     2: out of memory
index c6f993d491b51982bbd4e8029dc8ff55a229d2af..8e5eacbdcfa3f44115ccbc66fff89601c1af38ed 100644 (file)
@@ -390,6 +390,7 @@ struct memory_notify {
        unsigned long start_pfn;
        unsigned long nr_pages;
        int status_change_nid_normal;
+       int status_change_nid_high;
        int status_change_nid;
 }
 
@@ -397,7 +398,9 @@ start_pfn is start_pfn of online/offline memory.
 nr_pages is # of pages of online/offline memory.
 status_change_nid_normal is set node id when N_NORMAL_MEMORY of nodemask
 is (will be) set/clear, if this is -1, then nodemask status is not changed.
-status_change_nid is set node id when N_HIGH_MEMORY of nodemask is (will be)
+status_change_nid_high is set node id when N_HIGH_MEMORY of nodemask
+is (will be) set/clear, if this is -1, then nodemask status is not changed.
+status_change_nid is set node id when N_MEMORY of nodemask is (will be)
 set/clear. It means a new(memoryless) node gets new memory by online and a
 node loses all memory. If this is -1, then nodemask status is not changed.
 If status_changed_nid* >= 0, callback should create/discard structures for the
index 01804f21631293b796a113319c202d2593330b5e..49e4f770864a5f1ee2211e75378719f39e91eafd 100644 (file)
@@ -214,7 +214,7 @@ out:
 }
 
 /***************************************************************************
- * Intel Advanced Management Technolgy ME Client
+ * Intel Advanced Management Technology ME Client
  ***************************************************************************/
 
 #define AMT_MAJOR_VERSION 1
@@ -256,7 +256,7 @@ struct amt_code_versions {
 } __attribute__((packed));
 
 /***************************************************************************
- * Intel Advanced Management Technolgy Host Interface
+ * Intel Advanced Management Technology Host Interface
  ***************************************************************************/
 
 struct amt_host_if_msg_header {
index 9c647bd7c5a9cf108746647b8f97ec4b70afe1ab..3f10b39b034639cd558e080d289ed361c7ea63f7 100644 (file)
@@ -123,6 +123,9 @@ CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
 CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
 power supply object.
 
+CHARGE_CONTROL_LIMIT - current charge control limit setting
+CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting
+
 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
 
 CAPACITY - capacity in percents.
index 9605179711f4db78f5f99c0d75296860c9c3e0e3..4a4f47e759cde1b852032d5bfb488023322df2b5 100644 (file)
@@ -37,7 +37,7 @@ For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0:
             0x40    Inbound Queue Port
             0x44    Outbound Queue Port
 
-For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
+For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
 
      BAR0 offset    Register
          0x20400    Inbound Doorbell Register
@@ -55,9 +55,31 @@ For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
      0x40-0x1040    Inbound Queue
    0x1040-0x2040    Outbound Queue
 
+For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
 
-I/O Request Workflow
-----------------------
+     BAR0 offset    Register
+             0x0    IOP configuration information.
+
+     BAR1 offset    Register
+          0x4000    Inbound List Base Address Low
+          0x4004    Inbound List Base Address High
+          0x4018    Inbound List Write Pointer
+          0x402C    Inbound List Configuration and Control
+          0x4050    Outbound List Base Address Low
+          0x4054    Outbound List Base Address High
+          0x4058    Outbound List Copy Pointer Shadow Base Address Low
+          0x405C    Outbound List Copy Pointer Shadow Base Address High
+          0x4088    Outbound List Interrupt Cause
+          0x408C    Outbound List Interrupt Enable
+         0x1020C    PCIe Function 0 Interrupt Enable
+         0x10400    PCIe Function 0 to CPU Message A
+         0x10420    CPU to PCIe Function 0 Message A
+         0x10480    CPU to PCIe Function 0 Doorbell
+         0x10484    CPU to PCIe Function 0 Doorbell Enable
+
+
+I/O Request Workflow of Not Marvell Frey
+------------------------------------------
 
 All queued requests are handled via inbound/outbound queue port.
 A request packet can be allocated in either IOP or host memory.
@@ -101,6 +123,45 @@ register 0. An outbound message with the same value indicates the completion
 of an inbound message.
 
 
+I/O Request Workflow of Marvell Frey
+--------------------------------------
+
+All queued requests are handled via inbound/outbound list.
+
+To send a request to the controller:
+
+    - Allocate a free request in host DMA coherent memory.
+
+      Requests allocated in host memory must be aligned on 32-bytes boundary.
+
+    - Fill the request with index of the request in the flag.
+
+      Fill a free inbound list unit with the physical address and the size of
+      the request.
+
+      Set up the inbound list write pointer with the index of previous unit,
+      round to 0 if the index reaches the supported count of requests.
+
+    - Post the inbound list writer pointer to IOP.
+
+    - The IOP process the request. When the request is completed, the flag of
+      the request with or-ed IOPMU_QUEUE_MASK_HOST_BITS will be put into a
+      free outbound list unit and the index of the outbound list unit will be
+      put into the copy pointer shadow register. An outbound interrupt will be
+      generated.
+
+    - The host read the outbound list copy pointer shadow register and compare
+      with previous saved read ponter N. If they are different, the host will
+      read the (N+1)th outbound list unit.
+
+      The host get the index of the request from the (N+1)th outbound list
+      unit and complete the request.
+
+Non-queued requests (reset communication/reset/flush etc) can be sent via PCIe
+Function 0 to CPU Message A register. The CPU to PCIe Function 0 Message register
+with the same value indicates the completion of message.
+
+
 User-level Interface
 ---------------------
 
@@ -112,7 +173,7 @@ The driver exposes following sysfs attributes:
 
 
 -----------------------------------------------------------------------------
-Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
 
   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index d90d8ec2853df3e49e18edefc1bffd8995826403..b9cfd339a6fa3d4e89cebb3316e5152f9ff0d252 100644 (file)
@@ -1905,7 +1905,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     vid             - Vendor ID for the device (optional)
     pid             - Product ID for the device (optional)
     nrpacks        - Max. number of packets per URB (default: 8)
-    async_unlink    - Use async unlink mode (default: yes)
     device_setup    - Device specific magic number (optional)
                     - Influence depends on the device
                     - Default: 0x0000 
@@ -1917,8 +1916,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     NB: nrpacks parameter can be modified dynamically via sysfs.
         Don't put the value over 20.  Changing via sysfs has no sanity
        check.
-    NB: async_unlink=0 would cause Oops.  It remains just for
-        debugging purpose (if any).
     NB: ignore_ctl_error=1 may help when you get an error at accessing
         the mixer element such as URB error -22.  This happens on some
         buggy USB device or the controller.
index db833ced2cb89cc68d9fa9c10c400cbdb64e056a..a8fb6e2d3c8bed16d0f32930ac6ba0006c7fa64a 100644 (file)
@@ -43,7 +43,7 @@ Very nice card if you only have satellite TV but several tuners connected
 to the card via composite.
 
 Many thanks to Matrix-Vision for giving us 2 cards for free which made
-Bt848a/Bt849 single crytal operation support possible!!!
+Bt848a/Bt849 single crystal operation support possible!!!
 
 
 
index 395f6c6fdd9899883e6e8a75ed7ae517a2efac62..d3f1d7783d1ccde25d42e496a69165244dee8728 100644 (file)
@@ -82,7 +82,7 @@ card installed, you might to check out if you can read these registers
 values used by the windows driver.  A tool to do this is available
 from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it
 does'nt work with bt878 boards according to some reports I received.
-Another one with bt878 suport is available from
+Another one with bt878 support is available from
 http://btwincap.sourceforge.net/Files/btspy2.00.zip
 
 You might also dig around in the *.ini files of the Windows applications.
index f6ec3a92e62148087b8ac0764e8f916e175d8eb8..a4df5535996b9bca097d65a7c7a2851d9ab46dfe 100644 (file)
@@ -1194,12 +1194,15 @@ struct kvm_ppc_pvinfo {
 This ioctl fetches PV specific information that need to be passed to the guest
 using the device tree or other means from vm context.
 
-For now the only implemented piece of information distributed here is an array
-of 4 instructions that make up a hypercall.
+The hcall array defines 4 instructions that make up a hypercall.
 
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
+The flags bitmap is defined as:
+
+   /* the host supports the ePAPR idle hcall
+   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
 
 4.48 KVM_ASSIGN_PCI_DEVICE
 
@@ -1731,7 +1734,46 @@ registers, find a list below:
   Arch  |       Register        | Width (bits)
         |                       |
   PPC   | KVM_REG_PPC_HIOR      | 64
-
+  PPC   | KVM_REG_PPC_IAC1      | 64
+  PPC   | KVM_REG_PPC_IAC2      | 64
+  PPC   | KVM_REG_PPC_IAC3      | 64
+  PPC   | KVM_REG_PPC_IAC4      | 64
+  PPC   | KVM_REG_PPC_DAC1      | 64
+  PPC   | KVM_REG_PPC_DAC2      | 64
+  PPC   | KVM_REG_PPC_DABR      | 64
+  PPC   | KVM_REG_PPC_DSCR      | 64
+  PPC   | KVM_REG_PPC_PURR      | 64
+  PPC   | KVM_REG_PPC_SPURR     | 64
+  PPC   | KVM_REG_PPC_DAR       | 64
+  PPC   | KVM_REG_PPC_DSISR     | 32
+  PPC   | KVM_REG_PPC_AMR       | 64
+  PPC   | KVM_REG_PPC_UAMOR     | 64
+  PPC   | KVM_REG_PPC_MMCR0     | 64
+  PPC   | KVM_REG_PPC_MMCR1     | 64
+  PPC   | KVM_REG_PPC_MMCRA     | 64
+  PPC   | KVM_REG_PPC_PMC1      | 32
+  PPC   | KVM_REG_PPC_PMC2      | 32
+  PPC   | KVM_REG_PPC_PMC3      | 32
+  PPC   | KVM_REG_PPC_PMC4      | 32
+  PPC   | KVM_REG_PPC_PMC5      | 32
+  PPC   | KVM_REG_PPC_PMC6      | 32
+  PPC   | KVM_REG_PPC_PMC7      | 32
+  PPC   | KVM_REG_PPC_PMC8      | 32
+  PPC   | KVM_REG_PPC_FPR0      | 64
+          ...
+  PPC   | KVM_REG_PPC_FPR31     | 64
+  PPC   | KVM_REG_PPC_VR0       | 128
+          ...
+  PPC   | KVM_REG_PPC_VR31      | 128
+  PPC   | KVM_REG_PPC_VSR0      | 128
+          ...
+  PPC   | KVM_REG_PPC_VSR31     | 128
+  PPC   | KVM_REG_PPC_FPSCR     | 64
+  PPC   | KVM_REG_PPC_VSCR      | 32
+  PPC   | KVM_REG_PPC_VPA_ADDR  | 64
+  PPC   | KVM_REG_PPC_VPA_SLB   | 128
+  PPC   | KVM_REG_PPC_VPA_DTL   | 128
+  PPC   | KVM_REG_PPC_EPCR     | 32
 
 4.69 KVM_GET_ONE_REG
 
@@ -1747,7 +1789,7 @@ kvm_one_reg struct passed in. On success, the register value can be found
 at the memory location pointed to by "addr".
 
 The list of registers accessible using this interface is identical to the
-list in 4.64.
+list in 4.68.
 
 
 4.70 KVM_KVMCLOCK_CTRL
@@ -1997,6 +2039,93 @@ return the hash table order in the parameter.  (If the guest is using
 the virtualized real-mode area (VRMA) facility, the kernel will
 re-create the VMRA HPTEs on the next KVM_RUN of any vcpu.)
 
+4.77 KVM_S390_INTERRUPT
+
+Capability: basic
+Architectures: s390
+Type: vm ioctl, vcpu ioctl
+Parameters: struct kvm_s390_interrupt (in)
+Returns: 0 on success, -1 on error
+
+Allows to inject an interrupt to the guest. Interrupts can be floating
+(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
+
+Interrupt parameters are passed via kvm_s390_interrupt:
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP (vcpu) - sigp restart
+KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
+KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
+KVM_S390_RESTART (vcpu) - restart
+KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
+                          parameters in parm and parm64
+KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
+KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
+KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
+
+Note that the vcpu ioctl is asynchronous to vcpu execution.
+
+4.78 KVM_PPC_GET_HTAB_FD
+
+Capability: KVM_CAP_PPC_HTAB_FD
+Architectures: powerpc
+Type: vm ioctl
+Parameters: Pointer to struct kvm_get_htab_fd (in)
+Returns: file descriptor number (>= 0) on success, -1 on error
+
+This returns a file descriptor that can be used either to read out the
+entries in the guest's hashed page table (HPT), or to write entries to
+initialize the HPT.  The returned fd can only be written to if the
+KVM_GET_HTAB_WRITE bit is set in the flags field of the argument, and
+can only be read if that bit is clear.  The argument struct looks like
+this:
+
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+       __u64   flags;
+       __u64   start_index;
+       __u64   reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY       ((__u64)0x1)
+#define KVM_GET_HTAB_WRITE             ((__u64)0x2)
+
+The `start_index' field gives the index in the HPT of the entry at
+which to start reading.  It is ignored when writing.
+
+Reads on the fd will initially supply information about all
+"interesting" HPT entries.  Interesting entries are those with the
+bolted bit set, if the KVM_GET_HTAB_BOLTED_ONLY bit is set, otherwise
+all entries.  When the end of the HPT is reached, the read() will
+return.  If read() is called again on the fd, it will start again from
+the beginning of the HPT, but will only return HPT entries that have
+changed since they were last read.
+
+Data read or written is structured as a header (8 bytes) followed by a
+series of valid HPT entries (16 bytes) each.  The header indicates how
+many valid HPT entries there are and how many invalid entries follow
+the valid entries.  The invalid entries are not represented explicitly
+in the stream.  The header format is:
+
+struct kvm_get_htab_header {
+       __u32   index;
+       __u16   n_valid;
+       __u16   n_invalid;
+};
+
+Writes to the fd create HPT entries starting at the index given in the
+header; first `n_valid' valid entries with contents from the data
+written, then `n_invalid' invalid entries, invalidating any previously
+valid entries found.
+
 
 5. The kvm_run structure
 ------------------------
@@ -2109,7 +2238,8 @@ executed a memory-mapped I/O instruction which could not be satisfied
 by kvm.  The 'data' member contains the written data if 'is_write' is
 true, and should be filled by application code otherwise.
 
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO and KVM_EXIT_OSI, the corresponding
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR
+      and KVM_EXIT_PAPR the corresponding
 operations are complete (and guest state is consistent) only after userspace
 has re-entered the kernel with KVM_RUN.  The kernel side will first finish
 incomplete operations and then check for pending signals.  Userspace
index 5ef2d1366425416128d252fab11f884350a758fc..c71a019be600bf7f7d54f1917cba50059bb9cdf6 100644 (file)
@@ -193,7 +193,7 @@ faster.
    or maybe swap-over-nbd/NFS)?
 
 No.  First, the existing swap subsystem doesn't allow for any kind of
-swap hierarchy.  Perhaps it could be rewritten to accomodate a hierarchy,
+swap hierarchy.  Perhaps it could be rewritten to accommodate a hierarchy,
 but this would require fairly drastic changes.  Even if it were
 rewritten, the existing swap subsystem uses the block I/O layer which
 assumes a swap device is fixed size and any page in it is linearly
index f734bb2a78dc797aa62a2d2b0e1e7cc3390fef87..8785fb87d9c79fe37f385bf3beb48e7ca72f4a41 100644 (file)
@@ -116,6 +116,13 @@ echo always >/sys/kernel/mm/transparent_hugepage/defrag
 echo madvise >/sys/kernel/mm/transparent_hugepage/defrag
 echo never >/sys/kernel/mm/transparent_hugepage/defrag
 
+By default kernel tries to use huge zero page on read page fault.
+It's possible to disable huge zero page by writing 0 or enable it
+back by writing 1:
+
+echo 0 >/sys/kernel/mm/transparent_hugepage/khugepaged/use_zero_page
+echo 1 >/sys/kernel/mm/transparent_hugepage/khugepaged/use_zero_page
+
 khugepaged will be automatically started when
 transparent_hugepage/enabled is set to "always" or "madvise, and it'll
 be automatically shutdown if it's set to "never".
@@ -197,6 +204,14 @@ thp_split is incremented every time a huge page is split into base
        pages. This can happen for a variety of reasons but a common
        reason is that a huge page is old and is being reclaimed.
 
+thp_zero_page_alloc is incremented every time a huge zero page is
+       successfully allocated. It includes allocations which where
+       dropped due race with other allocation. Note, it doesn't count
+       every map of the huge zero page, only its allocation.
+
+thp_zero_page_alloc_failed is incremented if kernel fails to allocate
+       huge zero page and falls back to using small pages.
+
 As the system ages, allocating huge pages may be expensive as the
 system uses memory compaction to copy data around memory to free a
 huge page for use. There are some counters in /proc/vmstat to help
@@ -276,7 +291,7 @@ unaffected. libhugetlbfs will also work fine as usual.
 == Graceful fallback ==
 
 Code walking pagetables but unware about huge pmds can simply call
-split_huge_page_pmd(mm, pmd) where the pmd is the one returned by
+split_huge_page_pmd(vma, addr, pmd) where the pmd is the one returned by
 pmd_offset. It's trivial to make the code transparent hugepage aware
 by just grepping for "pmd_offset" and adding split_huge_page_pmd where
 missing after pmd_offset returns the pmd. Thanks to the graceful
@@ -299,7 +314,7 @@ diff --git a/mm/mremap.c b/mm/mremap.c
                return NULL;
 
        pmd = pmd_offset(pud, addr);
-+      split_huge_page_pmd(mm, pmd);
++      split_huge_page_pmd(vma, addr, pmd);
        if (pmd_none_or_clear_bad(pmd))
                return NULL;
 
index 0bc485c4a88e8c81bb10bba3f04f48aeb5071127..f71d2f901a69d0e186d3a76ba61f37c5da47051f 100644 (file)
@@ -337,6 +337,13 @@ W: http://wireless.kernel.org/
 S:     Orphan
 F:     drivers/net/wireless/adm8211.*
 
+ADP1653 FLASH CONTROLLER DRIVER
+M:     Sakari Ailus <sakari.ailus@iki.fi>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/i2c/adp1653.c
+F:     include/media/adp1653.h
+
 ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501)
 M:     Michael Hennerich <michael.hennerich@analog.com>
 L:     device-drivers-devel@blackfin.uclinux.org
@@ -1494,6 +1501,14 @@ F:       include/linux/ax25.h
 F:     include/net/ax25.h
 F:     net/ax25/
 
+AZ6007 DVB DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/usb/dvb-usb-v2/az6007.c
+
 B43 WIRELESS DRIVER
 M:     Stefano Brivio <stefano.brivio@polimi.it>
 L:     linux-wireless@vger.kernel.org
@@ -1745,11 +1760,11 @@ F:      Documentation/filesystems/btrfs.txt
 F:     fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <mchehab@infradead.org>
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-S:     Maintained
+T:     git git://linuxtv.org/media_tree.git
+S:     Odd fixes
 F:     Documentation/video4linux/bttv/
 F:     drivers/media/pci/bt8xx/bttv*
 
@@ -1778,7 +1793,7 @@ F:        fs/cachefiles/
 CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
 M:     Jonathan Corbet <corbet@lwn.net>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     Documentation/video4linux/cafe_ccic
 F:     drivers/media/platform/marvell-ccic/
@@ -2164,12 +2179,22 @@ CX18 VIDEO4LINUX DRIVER
 M:     Andy Walls <awalls@md.metrocast.net>
 L:     ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 W:     http://linuxtv.org
 W:     http://www.ivtvdriver.org/index.php/Cx18
 S:     Maintained
 F:     Documentation/video4linux/cx18.txt
 F:     drivers/media/pci/cx18/
+F:     include/uapi/linux/ivtv*
+
+CX88 VIDEO4LINUX DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Odd fixes
+F:     Documentation/video4linux/cx88/
+F:     drivers/media/pci/cx88/
 
 CXD2820R MEDIA DRIVER
 M:     Antti Palosaari <crope@iki.fi>
@@ -2726,6 +2751,15 @@ W:       bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/amd64_edac*
 
+EDAC-CAVIUM
+M:     Ralf Baechle <ralf@linux-mips.org>
+M:     David Daney <david.daney@cavium.com>
+L:     linux-edac@vger.kernel.org
+L:     linux-mips@linux-mips.org
+W:     bluesmoke.sourceforge.net
+S:     Supported
+F:     drivers/edac/octeon_edac*
+
 EDAC-E752X
 M:     Mark Gross <mark.gross@intel.com>
 M:     Doug Thompson <dougthompson@xmission.com>
@@ -2856,6 +2890,14 @@ L:       netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/ibm/ehea/
 
+EM28XX VIDEO4LINUX DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/usb/em28xx/
+
 EMBEDDED LINUX
 M:     Paul Gortmaker <paul.gortmaker@windriver.com>
 M:     Matt Mackall <mpm@selenic.com>
@@ -3054,6 +3096,14 @@ T:       git git://git.alsa-project.org/alsa-kernel.git
 S:     Maintained
 F:     sound/firewire/
 
+FIREWIRE MEDIA DRIVERS (firedtv)
+M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
+L:     linux-media@vger.kernel.org
+L:     linux1394-devel@lists.sourceforge.net
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+S:     Maintained
+F:     drivers/media/firewire/
+
 FIREWIRE SBP-2 TARGET
 M:     Chris Boot <bootc@bootc.net>
 L:     linux-scsi@vger.kernel.org
@@ -3112,6 +3162,12 @@ F:       drivers/video/
 F:     include/video/
 F:     include/linux/fb.h
 
+FREESCALE DIU FRAMEBUFFER DRIVER
+M:     Timur Tabi <timur@freescale.com>
+L:     linux-fbdev@vger.kernel.org
+S:     Supported
+F:     drivers/video/fsl-diu-fb.*
+
 FREESCALE DMA DRIVER
 M:     Li Yang <leoli@freescale.com>
 M:     Zhang Wei <zw@zh-kernel.org>
@@ -3340,56 +3396,56 @@ F:      drivers/net/ethernet/aeroflex/
 GSPCA FINEPIX SUBDRIVER
 M:     Frank Zago <frank@zago.net>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/finepix.c
 
 GSPCA GL860 SUBDRIVER
 M:     Olivier Lorin <o.lorin@laposte.net>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/gl860/
 
 GSPCA M5602 SUBDRIVER
 M:     Erik Andren <erik.andren@gmail.com>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/m5602/
 
 GSPCA PAC207 SONIXB SUBDRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/pac207.c
 
 GSPCA SN9C20X SUBDRIVER
 M:     Brian Johnson <brijohn@gmail.com>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/sn9c20x.c
 
 GSPCA T613 SUBDRIVER
 M:     Leandro Costantino <lcostantino@gmail.com>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/t613.c
 
 GSPCA USB WEBCAM DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/
 
 STK1160 USB VIDEO CAPTURE DRIVER
 M:     Ezequiel Garcia <elezegarcia@gmail.com>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/stk1160/
 
@@ -3596,7 +3652,7 @@ S:        Maintained
 F:     drivers/input/touchscreen/htcpen.c
 
 HUGETLB FILESYSTEM
-M:     William Irwin <wli@holomorphy.com>
+M:     Nadia Yvette Chambers <nyc@holomorphy.com>
 S:     Maintained
 F:     fs/hugetlbfs/
 
@@ -3787,6 +3843,12 @@ F:       net/ieee802154/
 F:     net/mac802154/
 F:     drivers/ieee802154/
 
+IGUANAWORKS USB IR TRANSCEIVER
+M:     Sean Young <sean@mess.org>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/rc/iguanair.c
+
 IIO SUBSYSTEM AND DRIVERS
 M:     Jonathan Cameron <jic23@cam.ac.uk>
 L:     linux-iio@vger.kernel.org
@@ -4172,17 +4234,41 @@ S:      Maintained
 F:     Documentation/hwmon/it87
 F:     drivers/hwmon/it87.c
 
+IT913X MEDIA DRIVER
+M:     Malcolm Priestley <tvboxspy@gmail.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+S:     Maintained
+F:     drivers/media/usb/dvb-usb-v2/it913x*
+
+IT913X FE MEDIA DRIVER
+M:     Malcolm Priestley <tvboxspy@gmail.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+S:     Maintained
+F:     drivers/media/dvb-frontends/it913x-fe*
+
 IVTV VIDEO4LINUX DRIVER
 M:     Andy Walls <awalls@md.metrocast.net>
 L:     ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 W:     http://www.ivtvdriver.org
 S:     Maintained
 F:     Documentation/video4linux/*.ivtv
 F:     drivers/media/pci/ivtv/
 F:     include/linux/ivtv*
 
+IX2505V MEDIA DRIVER
+M:     Malcolm Priestley <tvboxspy@gmail.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+S:     Maintained
+F:     drivers/media/dvb-frontends/ix2505v*
+
 JC42.4 TEMPERATURE SENSOR DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
 L:     lm-sensors@lm-sensors.org
@@ -4314,10 +4400,10 @@ F:      include/linux/kvm*
 F:     virt/kvm/
 
 KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
-M:     Joerg Roedel <joerg.roedel@amd.com>
+M:     Joerg Roedel <joro@8bytes.org>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
-S:     Supported
+S:     Maintained
 F:     arch/x86/include/asm/svm.h
 F:     arch/x86/kvm/svm.c
 
@@ -4325,6 +4411,7 @@ KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
 M:     Alexander Graf <agraf@suse.de>
 L:     kvm-ppc@vger.kernel.org
 W:     http://kvm.qumranet.com
+T:     git git://github.com/agraf/linux-2.6.git
 S:     Supported
 F:     arch/powerpc/include/asm/kvm*
 F:     arch/powerpc/kvm/
@@ -4627,6 +4714,14 @@ S:       Maintained
 F:     Documentation/hwmon/lm90
 F:     drivers/hwmon/lm90.c
 
+LME2510 MEDIA DRIVER
+M:     Malcolm Priestley <tvboxspy@gmail.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+S:     Maintained
+F:     drivers/media/usb/dvb-usb-v2/lmedm04*
+
 LOCKDEP AND LOCKSTAT
 M:     Peter Zijlstra <peterz@infradead.org>
 M:     Ingo Molnar <mingo@redhat.com>
@@ -4654,13 +4749,16 @@ S:      Maintained
 F:     fs/logfs/
 
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
-M:     Eric Moore <Eric.Moore@lsi.com>
+M:     Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com>
+M:     Sreekanth Reddy <Sreekanth.Reddy@lsi.com>
 M:     support@lsi.com
 L:     DL-MPTFusionLinux@lsi.com
 L:     linux-scsi@vger.kernel.org
 W:     http://www.lsilogic.com/support
 S:     Supported
 F:     drivers/message/fusion/
+F:     drivers/scsi/mpt2sas/
+F:     drivers/scsi/mpt3sas/
 
 LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
 M:     Matthew Wilcox <matthew@wil.cx>
@@ -4717,6 +4815,14 @@ W:       http://www.tazenda.demon.co.uk/phil/linux-hp
 S:     Maintained
 F:     arch/m68k/hp300/
 
+M88RS2000 MEDIA DRIVER
+M:     Malcolm Priestley <tvboxspy@gmail.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+S:     Maintained
+F:     drivers/media/dvb-frontends/m88rs2000*
+
 MAC80211
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
@@ -4771,6 +4877,12 @@ S:       Maintained
 F:     drivers/net/ethernet/marvell/mv643xx_eth.*
 F:     include/linux/mv643xx.h
 
+MARVELL MVNETA ETHERNET DRIVER
+M:     Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/marvell/mvneta.*
+
 MARVELL MWIFIEX WIRELESS DRIVER
 M:     Bing Zhao <bzhao@marvell.com>
 L:     linux-wireless@vger.kernel.org
@@ -4809,12 +4921,12 @@ F:      Documentation/hwmon/max6650
 F:     drivers/hwmon/max6650.c
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M:     Mauro Carvalho Chehab <mchehab@infradead.org>
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 P:     LinuxTV.org Project
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 Q:     http://patchwork.kernel.org/project/linux-media/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     Documentation/dvb/
 F:     Documentation/video4linux/
@@ -4822,8 +4934,13 @@ F:       Documentation/DocBook/media/
 F:     drivers/media/
 F:     drivers/staging/media/
 F:     include/media/
-F:     include/linux/dvb/
-F:     include/linux/videodev*.h
+F:     include/uapi/linux/dvb/
+F:     include/uapi/linux/videodev2.h
+F:     include/uapi/linux/media.h
+F:     include/uapi/linux/v4l2-*
+F:     include/uapi/linux/meye.h
+F:     include/uapi/linux/ivtv*
+F:     include/uapi/linux/uvcvideo.h
 
 MEGARAID SCSI DRIVERS
 M:     Neela Syam Kolli <megaraidlinux@lsi.com>
@@ -4905,7 +5022,7 @@ W:        http://popies.net/meye/
 S:     Orphan
 F:     Documentation/video4linux/meye.txt
 F:     drivers/media/pci/meye/
-F:     include/linux/meye.h
+F:     include/uapi/linux/meye.h
 
 MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
 M:     Pavel Pisa <ppisa@pikron.com>
@@ -4919,6 +5036,13 @@ S:       Maintained
 F:     Documentation/serial/moxa-smartio
 F:     drivers/tty/mxser.*
 
+MR800 AVERMEDIA USB FM RADIO DRIVER
+M:     Alexey Klimov <klimov.linux@gmail.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/radio/radio-mr800.c
+
 MSI LAPTOP SUPPORT
 M:     "Lee, Chun-Yi" <jlee@novell.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -5381,7 +5505,7 @@ F:        drivers/char/pcmcia/cm4040_cs.*
 OMNIVISION OV7670 SENSOR DRIVER
 M:     Jonathan Corbet <corbet@lwn.net>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/i2c/ov7670.c
 
@@ -5930,11 +6054,18 @@ M:      Mike Isely <isely@pobox.com>
 L:     pvrusb2@isely.net       (subscribers-only)
 L:     linux-media@vger.kernel.org
 W:     http://www.isely.net/pvrusb2/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     Documentation/video4linux/README.pvrusb2
 F:     drivers/media/usb/pvrusb2/
 
+PWC WEBCAM DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/usb/pwc/*
+
 PWM SUBSYSTEM
 M:     Thierry Reding <thierry.reding@avionic-design.de>
 L:     linux-kernel@vger.kernel.org
@@ -6077,6 +6208,21 @@ S:       Maintained
 F:     drivers/video/aty/radeon*
 F:     include/linux/radeonfb.h
 
+RADIOSHARK RADIO DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/radio/radio-shark.c
+
+RADIOSHARK2 RADIO DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/radio/radio-shark2.c
+F:     drivers/media/radio/radio-tea5777.c
+
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
 M:     Paul Mackerras <paulus@samba.org>
 L:     linux-fbdev@vger.kernel.org
@@ -6317,10 +6463,19 @@ L:      linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/mmc/host/s3cmci.*
 
+SAA7134 VIDEO4LINUX DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Odd fixes
+F:     Documentation/video4linux/saa7134/
+F:     drivers/media/pci/saa7134/
+
 SAA7146 VIDEO4LINUX-2 DRIVER
 M:     Michael Hunold <michael@mihu.de>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 W:     http://www.mihu.de/linux/saa7146
 S:     Maintained
 F:     drivers/media/common/saa7146/
@@ -6355,6 +6510,14 @@ F:       drivers/regulator/s5m*.c
 F:     drivers/rtc/rtc-sec.c
 F:     include/linux/mfd/samsung/
 
+SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER
+M:     Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+L:     linux-media@vger.kernel.org
+L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/media/platform/s3c-camif/
+F:     include/media/s3c_camif.h
+
 SERIAL DRIVERS
 M:     Alan Cox <alan@linux.intel.com>
 L:     linux-serial@vger.kernel.org
@@ -6649,6 +6812,18 @@ S:       Supported
 F:     arch/arm/mach-davinci
 F:     drivers/i2c/busses/i2c-davinci.c
 
+TI DAVINCI SERIES MEDIA DRIVER
+M:     Manjunath Hadli <manjunath.hadli@ti.com>
+M:     Prabhakar Lad <prabhakar.lad@ti.com>
+L:     linux-media@vger.kernel.org
+L:     davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
+S:     Supported
+F:     drivers/media/platform/davinci/
+F:     include/media/davinci/
+
 SIS 190 ETHERNET DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
@@ -6715,6 +6890,15 @@ M:       Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
 F:     drivers/net/ethernet/smsc/smc91x.*
 
+SMIA AND SMIA++ IMAGE SENSOR DRIVER
+M:     Sakari Ailus <sakari.ailus@iki.fi>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/i2c/smiapp
+F:     include/media/smiapp.h
+F:     drivers/media/i2c/smiapp-pll.c
+F:     drivers/media/i2c/smiapp-pll.h
+
 SMM665 HARDWARE MONITOR DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
 L:     lm-sensors@lm-sensors.org
@@ -6773,7 +6957,7 @@ F:        arch/ia64/sn/
 SOC-CAMERA V4L2 SUBSYSTEM
 M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     include/media/soc*
 F:     drivers/media/i2c/soc_camera/
@@ -7263,6 +7447,22 @@ T:       git git://linuxtv.org/mkrufky/tuners.git
 S:     Maintained
 F:     drivers/media/tuners/tda8290.*
 
+TEA5761 TUNER DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Odd fixes
+F:     drivers/media/tuners/tea5761.*
+
+TEA5767 TUNER DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/tuners/tea5767.*
+
 TEAM DRIVER
 M:     Jiri Pirko <jpirko@redhat.com>
 L:     netdev@vger.kernel.org
@@ -7270,6 +7470,12 @@ S:       Supported
 F:     drivers/net/team/
 F:     include/linux/if_team.h
 
+TECHNOTREND USB IR RECEIVER
+M:     Sean Young <sean@mess.org>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/rc/ttusbir.c
+
 TEGRA SUPPORT
 M:     Stephen Warren <swarren@wwwdotorg.org>
 L:     linux-tegra@vger.kernel.org
@@ -7422,6 +7628,14 @@ S:       Maintained
 F:     include/linux/shmem_fs.h
 F:     mm/shmem.c
 
+TM6000 VIDEO4LINUX DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Odd fixes
+F:     drivers/media/usb/tm6000/
+
 TPM DEVICE DRIVER
 M:     Kent Yoder <key@linux.vnet.ibm.com>
 M:     Rajiv Andrade <mail@srajiv.net>
@@ -7816,7 +8030,7 @@ USB SN9C1xx DRIVER
 M:     Luca Risolia <luca.risolia@studio.unibo.it>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 W:     http://www.linux-projects.org
 S:     Maintained
 F:     Documentation/video4linux/sn9c102.txt
@@ -7852,10 +8066,11 @@ USB VIDEO CLASS
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     linux-uvc-devel@lists.sourceforge.net (subscribers-only)
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 W:     http://www.ideasonboard.org/uvc/
 S:     Maintained
 F:     drivers/media/usb/uvc/
+F:     include/uapi/linux/uvcvideo.h
 
 USB WEBCAM GADGET
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -7887,7 +8102,7 @@ USB ZR364XX DRIVER
 M:     Antoine Jacquet <royale@zerezo.com>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:     git git://linuxtv.org/media_tree.git
 W:     http://royale.zerezo.com/zr364xx/
 S:     Maintained
 F:     Documentation/video4linux/zr364xx.txt
@@ -8242,6 +8457,14 @@ L:       linux-edac@vger.kernel.org
 S:     Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
 
+XC2028/3028 TUNER DRIVER
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/tuners/tuner-xc2028.*
+
 XEN HYPERVISOR INTERFACE
 M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 M:     Jeremy Fitzhardinge <jeremy@goop.org>
diff --git a/README b/README
index f32710a817fc392262f5f890cb637e5e0b1b5d1a..a24ec89ba4420ad38e8848422ca5f69baa5ffe1c 100644 (file)
--- a/README
+++ b/README
@@ -180,6 +180,10 @@ CONFIGURING the kernel:
                         with questions already answered.
                         Additionally updates the dependencies.
 
+     "make olddefconfig"
+                        Like above, but sets new symbols to their default
+                        values without prompting.
+
      "make defconfig"   Create a ./.config file by using the default
                         symbol values from either arch/$ARCH/defconfig
                         or arch/$ARCH/configs/${PLATFORM}_defconfig,
index 445dc42e033495be2ac6b1ae37fe3a8221c483e8..c5b5d6bac9ed1ac42b93275cf0602200ddf479f5 100644 (file)
@@ -66,7 +66,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
     ((unsigned long)__va(NODE_DATA(kvaddr_to_nid(kaddr))->node_start_pfn  \
                         << PAGE_SHIFT))
 
-/* XXX: FIXME -- wli */
+/* XXX: FIXME -- nyc */
 #define kern_addr_valid(kaddr) (0)
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
index 3f844d26d2c71e072d28fb71a232e444daba281b..a21d0ab3b19e1cf3f57f7c95e2a0b5dbe4ab8e9d 100644 (file)
@@ -354,8 +354,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
        struct pci_dev *pdev = alpha_gendev_to_pci(dev);
        int dac_allowed;
 
-       if (dir == PCI_DMA_NONE)
-               BUG();
+       BUG_ON(dir == PCI_DMA_NONE);
 
        dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
        return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
@@ -378,8 +377,7 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
        struct pci_iommu_arena *arena;
        long dma_ofs, npages;
 
-       if (dir == PCI_DMA_NONE)
-               BUG();
+       BUG_ON(dir == PCI_DMA_NONE);
 
        if (dma_addr >= __direct_map_base
            && dma_addr < __direct_map_base + __direct_map_size) {
@@ -662,8 +660,7 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
        dma_addr_t max_dma;
        int dac_allowed;
 
-       if (dir == PCI_DMA_NONE)
-               BUG();
+       BUG_ON(dir == PCI_DMA_NONE);
 
        dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
 
@@ -742,8 +739,7 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
        dma_addr_t max_dma;
        dma_addr_t fbeg, fend;
 
-       if (dir == PCI_DMA_NONE)
-               BUG();
+       BUG_ON(dir == PCI_DMA_NONE);
 
        if (! alpha_mv.mv_pci_tbi)
                return;
index 2277f9530b0078886b052306d76452b268014e67..8c83d98424c7a68703261d8bbc496130c784c21c 100644 (file)
@@ -533,6 +533,7 @@ config ARCH_IXP4XX
 config ARCH_DOVE
        bool "Marvell Dove"
        select ARCH_REQUIRE_GPIOLIB
+       select COMMON_CLK_DOVE
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select MIGHT_HAVE_PCI
index f8b4ff49b237e2cdc496f201f53d796d687217c4..b4015854d1ce7fdc644cac95f0f56350ed055a5d 100644 (file)
@@ -77,7 +77,9 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
 dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
        msm8960-cdp.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
-       armada-xp-db.dtb
+       armada-370-mirabox.dtb \
+       armada-xp-db.dtb \
+       armada-xp-openblocks-ax3-4.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx51-babbage.dtb \
        imx53-ard.dtb \
        imx53-evk.dtb \
@@ -127,7 +129,8 @@ dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
        spear1340-evb.dtb
 dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
        spear310-evb.dtb \
-       spear320-evb.dtb
+       spear320-evb.dtb \
+       spear320-hmi.dtb
 dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun4i-cubieboard.dtb \
        sun5i-olinuxino.dtb
index fffd5c2a3041c3854ebe92ff6e0c4d05661512ce..00044026ef1f470bd6bc6eb85b3409d2c0bf6556 100644 (file)
                        clock-frequency = <200000000>;
                        status = "okay";
                };
-               timer@d0020300 {
-                       clock-frequency = <600000000>;
+               sata@d00a0000 {
+                       nr-ports = <2>;
                        status = "okay";
                };
+
+               mdio {
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+
+               ethernet@d0070000 {
+                       status = "okay";
+                       phy = <&phy0>;
+                       phy-mode = "rgmii-id";
+               };
+               ethernet@d0074000 {
+                       status = "okay";
+                       phy = <&phy1>;
+                       phy-mode = "rgmii-id";
+               };
        };
 };
diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts
new file mode 100644 (file)
index 0000000..3b40713
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Device Tree file for Globalscale Mirabox
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "armada-370.dtsi"
+
+/ {
+       model = "Globalscale Mirabox";
+       compatible = "globalscale,mirabox", "marvell,armada370", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>; /* 512 MB */
+       };
+
+       soc {
+               serial@d0012000 {
+                       clock-frequency = <200000000>;
+                       status = "okay";
+               };
+               timer@d0020300 {
+                       clock-frequency = <600000000>;
+                       status = "okay";
+               };
+               mdio {
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+               ethernet@d0070000 {
+                       status = "okay";
+                       phy = <&phy0>;
+                       phy-mode = "rgmii-id";
+               };
+               ethernet@d0074000 {
+                       status = "okay";
+                       phy = <&phy1>;
+                       phy-mode = "rgmii-id";
+               };
+       };
+};
index 16cc82cdaa817aef1cb2e235c93b8412ddfb7af8..cf6c48a09eacf36e84b4caf4b83be0c35d0b22e8 100644 (file)
@@ -20,7 +20,7 @@
 
 / {
        model = "Marvell Armada 370 and XP SoC";
-       compatible = "marvell,armada_370_xp";
+       compatible = "marvell,armada-370-xp";
 
        cpus {
                cpu@0 {
              interrupt-controller;
        };
 
+       coherency-fabric@d0020200 {
+               compatible = "marvell,coherency-fabric";
+               reg = <0xd0020200 0xb0>,
+                     <0xd0021810 0x1c>;
+       };
+
        soc {
                #address-cells = <1>;
                #size-cells = <1>;
                               compatible = "marvell,armada-370-xp-timer";
                               reg = <0xd0020300 0x30>;
                               interrupts = <37>, <38>, <39>, <40>;
+                              clocks = <&coreclk 2>;
                };
 
                addr-decoding@d0020000 {
                        compatible = "marvell,armada-addr-decoding-controller";
                        reg = <0xd0020000 0x258>;
                };
+
+               sata@d00a0000 {
+                       compatible = "marvell,orion-sata";
+                       reg = <0xd00a0000 0x2400>;
+                       interrupts = <55>;
+                       clocks = <&gateclk 15>, <&gateclk 30>;
+                       clock-names = "0", "1";
+                       status = "disabled";
+               };
+
+               mdio {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "marvell,orion-mdio";
+                       reg = <0xd0072004 0x4>;
+               };
+
+               ethernet@d0070000 {
+                               compatible = "marvell,armada-370-neta";
+                               reg = <0xd0070000 0x2500>;
+                               interrupts = <8>;
+                               clocks = <&gateclk 4>;
+                               status = "disabled";
+               };
+
+               ethernet@d0074000 {
+                               compatible = "marvell,armada-370-neta";
+                               reg = <0xd0074000 0x2500>;
+                               interrupts = <10>;
+                               clocks = <&gateclk 3>;
+                               status = "disabled";
+               };
+
+               i2c0: i2c@d0011000 {
+                       compatible = "marvell,mv64xxx-i2c";
+                       reg = <0xd0011000 0x20>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <31>;
+                       timeout-ms = <1000>;
+                       clocks = <&coreclk 0>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@d0011100 {
+                       compatible = "marvell,mv64xxx-i2c";
+                       reg = <0xd0011100 0x20>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <32>;
+                       timeout-ms = <1000>;
+                       clocks = <&coreclk 0>;
+                       status = "disabled";
+               };
        };
 };
 
index 2069151afe01583ecb07c07f7f3cb91477a889d9..636cf7d4009ecf343d3b9a8d596bf092360a59b0 100644 (file)
 / {
        model = "Marvell Armada 370 family SoC";
        compatible = "marvell,armada370", "marvell,armada-370-xp";
+       L2: l2-cache {
+               compatible = "marvell,aurora-outer-cache";
+               reg = <0xd0008000 0x1000>;
+               cache-id-part = <0x100>;
+               wt-override;
+       };
 
        aliases {
                gpio0 = &gpio0;
                        #interrupts-cells = <2>;
                        interrupts = <91>;
                };
+
+               coreclk: mvebu-sar@d0018230 {
+                       compatible = "marvell,armada-370-core-clock";
+                       reg = <0xd0018230 0x08>;
+                       #clock-cells = <1>;
+               };
+
+               gateclk: clock-gating-control@d0018220 {
+                       compatible = "marvell,armada-370-gating-clock";
+                       reg = <0xd0018220 0x4>;
+                       clocks = <&coreclk 0>;
+                       #clock-cells = <1>;
+               };
+
+               xor@d0060800 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0xd0060800 0x100
+                              0xd0060A00 0x100>;
+                       status = "okay";
+
+                       xor00 {
+                               interrupts = <51>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+                       xor01 {
+                               interrupts = <52>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                               dmacap,memset;
+                       };
+               };
+
+               xor@d0060900 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0xd0060900 0x100
+                              0xd0060b00 0x100>;
+                       status = "okay";
+
+                       xor10 {
+                               interrupts = <94>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+                       xor11 {
+                               interrupts = <95>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                               dmacap,memset;
+                       };
+               };
        };
 };
index b1fc728515e9c739ae272004c86a5e6ec1de393e..8e53b25b55084ed3b8712156f21d357510be207c 100644 (file)
                        clock-frequency = <250000000>;
                        status = "okay";
                };
+
+               sata@d00a0000 {
+                       nr-ports = <2>;
+                       status = "okay";
+               };
+
+               mdio {
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+
+                       phy2: ethernet-phy@2 {
+                               reg = <25>;
+                       };
+
+                       phy3: ethernet-phy@3 {
+                               reg = <27>;
+                       };
+               };
+
+               ethernet@d0070000 {
+                       status = "okay";
+                       phy = <&phy0>;
+                       phy-mode = "rgmii-id";
+               };
+               ethernet@d0074000 {
+                       status = "okay";
+                       phy = <&phy1>;
+                       phy-mode = "rgmii-id";
+               };
+               ethernet@d0030000 {
+                       status = "okay";
+                       phy = <&phy2>;
+                       phy-mode = "sgmii";
+               };
+               ethernet@d0034000 {
+                       status = "okay";
+                       phy = <&phy3>;
+                       phy-mode = "sgmii";
+               };
        };
 };
index ea355192be6f0e25968a7b05d1a42cbe4c5dacd3..c45c7b4dc35230c52957fb1d32054a261e66e2ad 100644 (file)
                gpio1 = &gpio1;
        };
 
+       cpus {
+           #address-cells = <1>;
+           #size-cells = <0>;
+
+           cpu@0 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <0>;
+               clocks = <&cpuclk 0>;
+           };
+       }
+
        soc {
                pinctrl {
                        compatible = "marvell,mv78230-pinctrl";
index 2057863f3dfa5c81e586a4fea92308ff9d3c2bca..a2aee5707377c3886a51217d40c102ed5e68c1e1 100644 (file)
                gpio2 = &gpio2;
        };
 
+       cpus {
+           #address-cells = <1>;
+           #size-cells = <0>;
+
+           cpu@0 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <0>;
+               clocks = <&cpuclk 0>;
+           };
+
+           cpu@1 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <1>;
+               clocks = <&cpuclk 1>;
+           };
+       };
+
        soc {
                pinctrl {
                        compatible = "marvell,mv78260-pinctrl";
index ffac98373792dd3755226ef9cd664a6dcd507175..da03a129243a548853e5afa611b84f1b5fd73ebe 100644 (file)
                gpio2 = &gpio2;
        };
 
+
+       cpus {
+           #address-cells = <1>;
+           #size-cells = <0>;
+
+           cpu@0 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <0>;
+               clocks = <&cpuclk 0>;
+           };
+
+           cpu@1 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <1>;
+               clocks = <&cpuclk 1>;
+           };
+
+           cpu@2 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <2>;
+               clocks = <&cpuclk 2>;
+           };
+
+           cpu@3 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <3>;
+               clocks = <&cpuclk 3>;
+           };
+       };
+
        soc {
                pinctrl {
                        compatible = "marvell,mv78460-pinctrl";
diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
new file mode 100644 (file)
index 0000000..b42652f
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Device Tree file for OpenBlocks AX3-4 board
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "armada-xp-mv78260.dtsi"
+
+/ {
+       model = "PlatHome OpenBlocks AX3-4 board";
+       compatible = "plathome,openblocks-ax3-4", "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0xC0000000>; /* 3 GB */
+       };
+
+       soc {
+               serial@d0012000 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012100 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               pinctrl {
+                       led_pins: led-pins-0 {
+                               marvell,pins = "mpp49", "mpp51", "mpp53";
+                               marvell,function = "gpio";
+                       };
+               };
+               leds {
+                       compatible = "gpio-leds";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&led_pins>;
+
+                       red_led {
+                               label = "red_led";
+                               gpios = <&gpio1 17 1>;
+                               default-state = "off";
+                       };
+
+                       yellow_led {
+                               label = "yellow_led";
+                               gpios = <&gpio1 19 1>;
+                               default-state = "off";
+                       };
+
+                       green_led {
+                               label = "green_led";
+                               gpios = <&gpio1 21 1>;
+                               default-state = "off";
+                               linux,default-trigger = "heartbeat";
+                       };
+               };
+
+               mdio {
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+
+                       phy2: ethernet-phy@2 {
+                               reg = <2>;
+                       };
+
+                       phy3: ethernet-phy@3 {
+                               reg = <3>;
+                       };
+               };
+
+               ethernet@d0070000 {
+                       status = "okay";
+                       phy = <&phy0>;
+                       phy-mode = "sgmii";
+               };
+               ethernet@d0074000 {
+                       status = "okay";
+                       phy = <&phy1>;
+                       phy-mode = "sgmii";
+               };
+               ethernet@d0030000 {
+                       status = "okay";
+                       phy = <&phy2>;
+                       phy-mode = "sgmii";
+               };
+               ethernet@d0034000 {
+                       status = "okay";
+                       phy = <&phy3>;
+                       phy-mode = "sgmii";
+               };
+               i2c@d0011000 {
+                       status = "okay";
+                       clock-frequency = <400000>;
+               };
+               i2c@d0011100 {
+                       status = "okay";
+                       clock-frequency = <400000>;
+
+                       s35390a: s35390a@30 {
+                               compatible = "s35390a";
+                               reg = <0x30>;
+                       };
+               };
+               sata@d00a0000 {
+                       nr-ports = <2>;
+                       status = "okay";
+               };
+       };
+};
index 71d6b5d0daf1ca8a03360ba74b62922bf9de36b1..367aa3f94912ac9d78a35d22321c64667af406cf 100644 (file)
        model = "Marvell Armada XP family SoC";
        compatible = "marvell,armadaxp", "marvell,armada-370-xp";
 
+       L2: l2-cache {
+               compatible = "marvell,aurora-system-cache";
+               reg = <0xd0008000 0x1000>;
+               cache-id-part = <0x100>;
+               wt-override;
+       };
+
        mpic: interrupt-controller@d0020000 {
              reg = <0xd0020a00 0x1d0>,
-                   <0xd0021870 0x58>;
+                   <0xd0021070 0x58>;
+       };
+
+       armada-370-xp-pmsu@d0022000 {
+               compatible = "marvell,armada-370-xp-pmsu";
+               reg = <0xd0022100 0x430>,
+                     <0xd0020800 0x20>;
        };
 
        soc {
                                marvell,timer-25Mhz;
                };
 
+               coreclk: mvebu-sar@d0018230 {
+                       compatible = "marvell,armada-xp-core-clock";
+                       reg = <0xd0018230 0x08>;
+                       #clock-cells = <1>;
+               };
+
+               cpuclk: clock-complex@d0018700 {
+                       #clock-cells = <1>;
+                       compatible = "marvell,armada-xp-cpu-clock";
+                       reg = <0xd0018700 0xA0>;
+                       clocks = <&coreclk 1>;
+               };
+
+               gateclk: clock-gating-control@d0018220 {
+                       compatible = "marvell,armada-xp-gating-clock";
+                       reg = <0xd0018220 0x4>;
+                       clocks = <&coreclk 0>;
+                       #clock-cells = <1>;
+               };
+
                system-controller@d0018200 {
                                compatible = "marvell,armada-370-xp-system-controller";
                                reg = <0xd0018200 0x500>;
                };
+
+               ethernet@d0030000 {
+                               compatible = "marvell,armada-370-neta";
+                               reg = <0xd0030000 0x2500>;
+                               interrupts = <12>;
+                               clocks = <&gateclk 2>;
+                               status = "disabled";
+               };
+
+               ethernet@d0034000 {
+                               compatible = "marvell,armada-370-neta";
+                               reg = <0xd0034000 0x2500>;
+                               interrupts = <14>;
+                               clocks = <&gateclk 1>;
+                               status = "disabled";
+               };
+
+               xor@d0060900 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0xd0060900 0x100
+                              0xd0060b00 0x100>;
+                       clocks = <&gateclk 22>;
+                       status = "okay";
+
+                       xor10 {
+                               interrupts = <51>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+                       xor11 {
+                               interrupts = <52>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                               dmacap,memset;
+                       };
+               };
+
+               xor@d00f0900 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0xd00F0900 0x100
+                              0xd00F0B00 0x100>;
+                       clocks = <&gateclk 28>;
+                       status = "okay";
+
+                       xor00 {
+                               interrupts = <94>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+                       xor01 {
+                               interrupts = <95>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                               dmacap,memset;
+                       };
+               };
        };
 };
index c528b4b429b96efa5f3473fe4f8287711e6d2e56..68bccf41a2c6a1855c6dfd87555faabf81306cb7 100644 (file)
@@ -29,6 +29,7 @@
                tcb0 = &tcb0;
                tcb1 = &tcb1;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fffbc000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfffbc000 0x4000>;
+                               interrupts = <14 4 5>;
+                               status = "disabled";
+                       };
+
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
index 00485e1dff93e87ffc99aaf3d11a1b731e73074b..8e6251f1f7a3d9ee36008f4ad9ee73b49f2e3cd9 100644 (file)
@@ -25,6 +25,8 @@
                gpio4 = &pioE;
                tcb0 = &tcb0;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fff98000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfff98000 0x4000>;
+                               interrupts = <16 4 5>;
+                               status = "disable";
+                       };
+
+                       ssc1: ssc@fff9c000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfff9c000 0x4000>;
+                               interrupts = <17 4 5>;
+                               status = "disable";
+                       };
+
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
index 32a500a0e481f7473de51be152546081b8bddd15..da15e83e7f179deceb146b19e5d3b8d7ddb8e90d 100644 (file)
 
        ahb {
                apb {
+                       pinctrl@fffff400 {
+                               board {
+                                       pinctrl_pck0_as_mck: pck0_as_mck {
+                                               atmel,pins =
+                                                       <2 1 0x2 0x0>;  /* PC1 periph B */
+                                       };
+
+                               };
+                       };
+
                        dbgu: serial@fffff200 {
                                status = "okay";
                        };
                                        };
                                };
                        };
+
+                       ssc0: ssc@fffbc000 {
+                               status = "okay";
+                               pinctrl-0 = <&pinctrl_ssc0_tx>;
+                       };
                };
 
                nand0: nand@40000000 {
                        reg = <0x50>;
                };
 
-               wm8731@1b {
+               wm8731: wm8731@1b {
                        compatible = "wm8731";
                        reg = <0x1b>;
                };
                        gpio-key,wakeup;
                };
        };
+
+       sound {
+               compatible = "atmel,at91sam9g20ek-wm8731-audio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+               atmel,model = "wm8731 @ AT91SAMG20EK";
+
+               atmel,audio-routing =
+                       "Ext Spk", "LHPOUT",
+                       "Int Mic", "MICIN";
+
+               atmel,ssc-controller = <&ssc0>;
+               atmel,audio-codec = <&wm8731>;
+       };
 };
index 485fc395efc69968c0d09b6dfa31643f44b438e9..fa1ae0c5479c0480022fac86fe576806154da73e 100644 (file)
@@ -31,6 +31,8 @@
                tcb1 = &tcb1;
                i2c0 = &i2c0;
                i2c1 = &i2c1;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fff9c000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfff9c000 0x4000>;
+                               interrupts = <16 4 5>;
+                               status = "disable";
+                       };
+
+                       ssc1: ssc@fffa0000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfffa0000 0x4000>;
+                               interrupts = <17 4 5>;
+                               status = "disable";
+                       };
+
                        adc0: adc@fffb0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffb0000 0x100>;
index 7ee49e8daf987af65060b8b058f8b29a6ff2e6d0..617ede541ca273b76d7ca6961c6cbd6273073c3d 100644 (file)
@@ -30,6 +30,7 @@
                i2c0 = &i2c0;
                i2c1 = &i2c1;
                i2c2 = &i2c2;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                interrupts = <1 4 7>;
                        };
 
+                       ssc0: ssc@f0010000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xf0010000 0x4000>;
+                               interrupts = <28 4 5>;
+                               status = "disable";
+                       };
+
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
index 0d69322f689f03bbe16b1d061d33cd847ced989f..2efd9c891bc91f85522a6158854fd14e89b7f65f 100644 (file)
                                        vddadc-supply = <&ab8500_ldo_tvout_reg>;
                                };
 
-                               ab8500-usb {
+                               ab8500_battery: ab8500_battery {
+                                       stericsson,battery-type = "LIPO";
+                                       thermistor-on-batctrl;
+                               };
+
+                               ab8500_fg {
+                                       compatible = "stericsson,ab8500-fg";
+                                       battery    = <&ab8500_battery>;
+                               };
+
+                               ab8500_btemp {
+                                       compatible = "stericsson,ab8500-btemp";
+                                       battery    = <&ab8500_battery>;
+                               };
+
+                               ab8500_charger {
+                                       compatible      = "stericsson,ab8500-charger";
+                                       battery         = <&ab8500_battery>;
+                                       vddadc-supply   = <&ab8500_ldo_tvout_reg>;
+                               };
+
+                               ab8500_chargalg {
+                                       compatible      = "stericsson,ab8500-chargalg";
+                                       battery         = <&ab8500_battery>;
+                               };
+
+                               ab8500_usb {
                                        compatible = "stericsson,ab8500-usb";
                                        interrupts = < 90 0x4
                                                       96 0x4
index 61f391412a5a60cd3ae310c9576d057df97f9e98..f3f7e9d8adca4862c92cd22d00eb6d15267a8a8c 100644 (file)
                        reg = <0x20204 0x04>, <0x20214 0x04>;
                };
 
+               core_clk: core-clocks@d0214 {
+                       compatible = "marvell,dove-core-clock";
+                       reg = <0xd0214 0x4>;
+                       #clock-cells = <1>;
+               };
+
+               gate_clk: clock-gating-control@d0038 {
+                       compatible = "marvell,dove-gating-clock";
+                       reg = <0xd0038 0x4>;
+                       clocks = <&core_clk 0>;
+                       #clock-cells = <1>;
+               };
+
                uart0: serial@12000 {
                        compatible = "ns16550a";
                        reg = <0x12000 0x100>;
                        cell-index = <0>;
                        interrupts = <6>;
                        reg = <0x10600 0x28>;
+                       clocks = <&core_clk 0>;
                        status = "disabled";
                };
 
                        cell-index = <1>;
                        interrupts = <5>;
                        reg = <0x14600 0x28>;
+                       clocks = <&core_clk 0>;
                        status = "disabled";
                };
 
                        interrupts = <11>;
                        clock-frequency = <400000>;
                        timeout-ms = <1000>;
+                       clocks = <&core_clk 0>;
                        status = "disabled";
                };
 
                        compatible = "marvell,dove-sdhci";
                        reg = <0x92000 0x100>;
                        interrupts = <35>, <37>;
+                       clocks = <&gate_clk 8>;
                        status = "disabled";
                };
 
                        compatible = "marvell,dove-sdhci";
                        reg = <0x90000 0x100>;
                        interrupts = <36>, <38>;
+                       clocks = <&gate_clk 9>;
                        status = "disabled";
                };
 
                        compatible = "marvell,orion-sata";
                        reg = <0xa0000 0x2400>;
                        interrupts = <62>;
+                       clocks = <&gate_clk 3>;
                        nr-ports = <1>;
                        status = "disabled";
                };
                              <0xc8000000 0x800>;
                        reg-names = "regs", "sram";
                        interrupts = <31>;
+                       clocks = <&gate_clk 15>;
+                       status = "okay";
+               };
+
+               xor0: dma-engine@60800 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0x60800 0x100
+                              0x60a00 0x100>;
+                       clocks = <&gate_clk 23>;
                        status = "okay";
+
+                       channel0 {
+                               interrupts = <39>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+
+                       channel1 {
+                               interrupts = <40>;
+                               dmacap,memset;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+               };
+
+               xor1: dma-engine@60900 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0x60900 0x100
+                              0x60b00 0x100>;
+                       clocks = <&gate_clk 24>;
+                       status = "okay";
+
+                       channel0 {
+                               interrupts = <42>;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
+
+                       channel1 {
+                               interrupts = <43>;
+                               dmacap,memset;
+                               dmacap,memcpy;
+                               dmacap,xor;
+                       };
                };
        };
 };
index 36d8246ea50eaef5e5cae9c719b8ade854a17bd1..2e3b6efaf1a2632062fd93a8ca7d0eec792a9c0c 100644 (file)
                mshc1 = &dwmmc_1;
                mshc2 = &dwmmc_2;
                mshc3 = &dwmmc_3;
+               i2c0 = &i2c_0;
+               i2c1 = &i2c_1;
+               i2c2 = &i2c_2;
+               i2c3 = &i2c_3;
+               i2c4 = &i2c_4;
+               i2c5 = &i2c_5;
+               i2c6 = &i2c_6;
+               i2c7 = &i2c_7;
+               i2c8 = &i2c_8;
        };
 
        gic:interrupt-controller@10481000 {
                reg = <0x12170000 0x1ff>;
        };
 
-       i2c@12C60000 {
+       i2c_0: i2c@12C60000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C60000 0x100>;
                interrupts = <0 56 0>;
                #size-cells = <0>;
        };
 
-       i2c@12C70000 {
+       i2c_1: i2c@12C70000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C70000 0x100>;
                interrupts = <0 57 0>;
                #size-cells = <0>;
        };
 
-       i2c@12C80000 {
+       i2c_2: i2c@12C80000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C80000 0x100>;
                interrupts = <0 58 0>;
                #size-cells = <0>;
        };
 
-       i2c@12C90000 {
+       i2c_3: i2c@12C90000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C90000 0x100>;
                interrupts = <0 59 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CA0000 {
+       i2c_4: i2c@12CA0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CA0000 0x100>;
                interrupts = <0 60 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CB0000 {
+       i2c_5: i2c@12CB0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CB0000 0x100>;
                interrupts = <0 61 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CC0000 {
+       i2c_6: i2c@12CC0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CC0000 0x100>;
                interrupts = <0 62 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CD0000 {
+       i2c_7: i2c@12CD0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CD0000 0x100>;
                interrupts = <0 63 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CE0000 {
+       i2c_8: i2c@12CE0000 {
                compatible = "samsung,s3c2440-hdmiphy-i2c";
                reg = <0x12CE0000 0x1000>;
                interrupts = <0 64 0>;
index a990c30f0a2602936f76c3cd79cca99e2966ad40..7735cee4a9c6fb8a34ffb001eed617137a0fef6c 100644 (file)
                #address-cells = <1>;
                #size-cells = <1>;
 
+               core_clk: core-clocks@10030 {
+                       compatible = "marvell,kirkwood-core-clock";
+                       reg = <0x10030 0x4>;
+                       #clock-cells = <1>;
+               };
+
                gpio0: gpio@10100 {
                        compatible = "marvell,orion-gpio";
                        #gpio-cells = <2>;
@@ -48,6 +54,7 @@
                        reg = <0x12000 0x100>;
                        reg-shift = <2>;
                        interrupts = <33>;
+                       clocks = <&gate_clk 7>;
                        /* set clock-frequency in board dts */
                        status = "disabled";
                };
@@ -57,6 +64,7 @@
                        reg = <0x12100 0x100>;
                        reg-shift = <2>;
                        interrupts = <34>;
+                       clocks = <&gate_clk 7>;
                        /* set clock-frequency in board dts */
                        status = "disabled";
                };
                        cell-index = <0>;
                        interrupts = <23>;
                        reg = <0x10600 0x28>;
+                       clocks = <&gate_clk 7>;
                        status = "disabled";
                };
 
+               gate_clk: clock-gating-control@2011c {
+                       compatible = "marvell,kirkwood-gating-clock";
+                       reg = <0x2011c 0x4>;
+                       clocks = <&core_clk 0>;
+                       #clock-cells = <1>;
+               };
+
                wdt@20300 {
                        compatible = "marvell,orion-wdt";
                        reg = <0x20300 0x28>;
+                       clocks = <&gate_clk 7>;
+                       status = "okay";
+               };
+
+               xor@60800 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0x60800 0x100
+                              0x60A00 0x100>;
+                       status = "okay";
+                       clocks = <&gate_clk 8>;
+
+                       xor00 {
+                             interrupts = <5>;
+                             dmacap,memcpy;
+                             dmacap,xor;
+                       };
+                       xor01 {
+                             interrupts = <6>;
+                             dmacap,memcpy;
+                             dmacap,xor;
+                             dmacap,memset;
+                       };
+               };
+
+               xor@60900 {
+                       compatible = "marvell,orion-xor";
+                       reg = <0x60900 0x100
+                              0xd0B00 0x100>;
                        status = "okay";
+                       clocks = <&gate_clk 16>;
+
+                       xor00 {
+                             interrupts = <7>;
+                             dmacap,memcpy;
+                             dmacap,xor;
+                       };
+                       xor01 {
+                             interrupts = <8>;
+                             dmacap,memcpy;
+                             dmacap,xor;
+                             dmacap,memset;
+                       };
                };
 
                ehci@50000 {
                        compatible = "marvell,orion-sata";
                        reg = <0x80000 0x5000>;
                        interrupts = <21>;
+                       clocks = <&gate_clk 14>, <&gate_clk 15>;
+                       clock-names = "0", "1";
                        status = "disabled";
                };
 
                        reg = <0x3000000 0x400>;
                        chip-delay = <25>;
                        /* set partition map and/or chip-delay in board dts */
+                       clocks = <&gate_clk 7>;
                        status = "disabled";
                };
 
                        #size-cells = <0>;
                        interrupts = <29>;
                        clock-frequency = <100000>;
+                       clocks = <&gate_clk 7>;
                        status = "disabled";
                };
 
                              <0xf5000000 0x800>;
                        reg-names = "regs", "sram";
                        interrupts = <22>;
+                       clocks = <&gate_clk 17>;
                        status = "okay";
                };
        };
index 0772f5739f59573aa1403b6cc0e6efd8a873892a..19aec421bb26bab363a059e2395ebfe8fc0489a9 100644 (file)
                        reg-shift = <2>;
                        reg-io-width = <4>;
                };
+
+               rstmgr@ffd05000 {
+                               compatible = "altr,rst-mgr";
+                               reg = <0xffd05000 0x1000>;
+                       };
+
+               sysmgr@ffd08000 {
+                               compatible = "altr,sys-mgr";
+                               reg = <0xffd08000 0x4000>;
+                       };
        };
 };
index 2e4c5727468e1c4362c911f44dd44c44d0431524..b56a801e42a206451535684d6314a09063d6351c 100644 (file)
                        pinctrl-0 = <&state_default>;
 
                        state_default: pinmux {
-                               i2c0-pmx {
+                               i2c0 {
                                        st,pins = "i2c0_grp";
                                        st,function = "i2c0";
                                };
+                               i2s0 {
+                                       st,pins = "i2s0_grp";
+                                       st,function = "i2s0";
+                               };
                                i2s1 {
                                        st,pins = "i2s1_grp";
                                        st,function = "i2s1";
                                        st,pins = "arm_gpio_grp";
                                        st,function = "arm_gpio";
                                };
+                               clcd {
+                                       st,pins = "clcd_grp" , "clcd_high_res";
+                                       st,function = "clcd";
+                               };
                                eth {
                                        st,pins = "gmii_grp";
                                        st,function = "gmii";
                                        st,pins = "i2c_1_2_grp";
                                        st,function = "i2c_1_2";
                                };
-                               pci {
-                                       st,pins = "pcie0_grp","pcie1_grp",
-                                               "pcie2_grp";
-                                       st,function = "pci";
-                               };
                                smii {
                                        st,pins = "smii_0_1_2_grp";
                                        st,function = "smii_0_1_2";
                                                "nand_16bit_grp";
                                        st,function = "nand";
                                };
+                               sata {
+                                       st,pins = "sata0_grp";
+                                       st,function = "sata";
+                               };
+                               pcie {
+                                       st,pins = "pcie1_grp", "pcie2_grp";
+                                       st,function = "pci_express";
+                               };
                        };
                };
 
 
                fsmc: flash@b0000000 {
                        status = "okay";
+
+                       partition@0 {
+                               label = "xloader";
+                               reg = <0x0 0x80000>;
+                       };
+                       partition@80000 {
+                               label = "u-boot";
+                               reg = <0x80000 0x140000>;
+                       };
+                       partition@1C0000 {
+                               label = "environment";
+                               reg = <0x1C0000 0x40000>;
+                       };
+                       partition@200000 {
+                               label = "dtb";
+                               reg = <0x200000 0x40000>;
+                       };
+                       partition@240000 {
+                               label = "linux";
+                               reg = <0x240000 0xC00000>;
+                       };
+                       partition@E40000 {
+                               label = "rootfs";
+                               reg = <0xE40000 0x0>;
+                       };
+               };
+
+               gpio_keys {
+                       compatible = "gpio-keys";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       button@1 {
+                               label = "wakeup";
+                               linux,code = <0x100>;
+                               gpios = <&gpio0 7 0x4>;
+                               debounce-interval = <20>;
+                               gpio-key,wakeup = <1>;
+                       };
                };
 
                gmac0: eth@e2000000 {
+                       phy-mode = "gmii";
                        status = "okay";
                };
 
                                };
                                partition@10000 {
                                        label = "u-boot";
-                                       reg = <0x10000 0x40000>;
+                                       reg = <0x10000 0x50000>;
+                               };
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
                                };
-                               partition@50000 {
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
+                               };
+                               partition@80000 {
                                        label = "linux";
-                                       reg = <0x50000 0x2c0000>;
+                                       reg = <0x80000 0x310000>;
                                };
-                               partition@310000 {
+                               partition@390000 {
                                        label = "rootfs";
-                                       reg = <0x310000 0x4f0000>;
+                                       reg = <0x390000 0x0>;
                                };
                        };
                };
 
-               spi0: spi@e0100000 {
-                       status = "okay";
-               };
-
                ehci@e4800000 {
                        status = "okay";
                };
                               status = "okay";
                        };
 
-                       i2c1: i2c@5cd00000 {
-                              status = "okay";
-                       };
-
                        kbd@e0300000 {
                                linux,keymap = < 0x00000001
                                                 0x00010002
                                                 0x08080052 >;
                               autorepeat;
                               st,mode = <0>;
+                              suspended_rate = <2000000>;
                               status = "okay";
                        };
 
 
                        serial@e0000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
+                       };
+
+                       spi0: spi@e0100000 {
+                               status = "okay";
+                               num-cs = <3>;
+                               cs-gpios = <&gpio1 7 0>, <&spics 0>, <&spics 1>;
+
+                               stmpe610@0 {
+                                       compatible = "st,stmpe610";
+                                       reg = <0>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       spi-max-frequency = <1000000>;
+                                       spi-cpha;
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable;
+                                       pl022,com-mode = <0>;
+                                       pl022,rx-level-trig = <0>;
+                                       pl022,tx-level-trig = <0>;
+                                       pl022,ctrl-len = <0x7>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+                                       interrupts = <6 0x4>;
+                                       interrupt-parent = <&gpio1>;
+                                       irq-trigger = <0x2>;
+
+                                       stmpe_touchscreen {
+                                               compatible = "st,stmpe-ts";
+                                               ts,sample-time = <4>;
+                                               ts,mod-12b = <1>;
+                                               ts,ref-sel = <0>;
+                                               ts,adc-freq = <1>;
+                                               ts,ave-ctrl = <1>;
+                                               ts,touch-det-delay = <2>;
+                                               ts,settling = <2>;
+                                               ts,fraction-z = <7>;
+                                               ts,i-drive = <1>;
+                                       };
+                               };
+
+                               m25p80@1 {
+                                       compatible = "st,m25p80";
+                                       reg = <1>;
+                                       spi-max-frequency = <12000000>;
+                                       spi-cpol;
+                                       spi-cpha;
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable;
+                                       pl022,com-mode = <0x2>;
+                                       pl022,rx-level-trig = <0>;
+                                       pl022,tx-level-trig = <0>;
+                                       pl022,ctrl-len = <0x11>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+                               };
+
+                               spidev@2 {
+                                       compatible = "spidev";
+                                       reg = <2>;
+                                       spi-max-frequency = <25000000>;
+                                       spi-cpha;
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable;
+                                       pl022,com-mode = <0x2>;
+                                       pl022,rx-level-trig = <0>;
+                                       pl022,tx-level-trig = <0>;
+                                       pl022,ctrl-len = <0x11>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+                               };
                        };
 
                        wdt@ec800620 {
index 7cd25eb4f8e00a14c317fbbc46854bd7641bdeb9..1513c1927cc8f2b2e3d7e64e3eabfd0c4ec1ff96 100644 (file)
        compatible = "st,spear1310";
 
        ahb {
+               spics: spics@e0700000{
+                       compatible = "st,spear-spics-gpio";
+                       reg = <0xe0700000 0x1000>;
+                       st-spics,peripcfg-reg = <0x3b0>;
+                       st-spics,sw-enable-bit = <12>;
+                       st-spics,cs-value-bit = <11>;
+                       st-spics,cs-enable-mask = <3>;
+                       st-spics,cs-enable-shift = <8>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
                ahci@b1000000 {
                        compatible = "snps,spear-ahci";
                        reg = <0xb1000000 0x10000>;
@@ -43,6 +55,7 @@
                        reg = <0x5c400000 0x8000>;
                        interrupts = <0 95 0x4>;
                        interrupt-names = "macirq";
+                       phy-mode = "mii";
                        status = "disabled";
                };
 
@@ -51,6 +64,7 @@
                        reg = <0x5c500000 0x8000>;
                        interrupts = <0 96 0x4>;
                        interrupt-names = "macirq";
+                       phy-mode = "mii";
                        status = "disabled";
                };
 
@@ -59,6 +73,7 @@
                        reg = <0x5c600000 0x8000>;
                        interrupts = <0 97 0x4>;
                        interrupt-names = "macirq";
+                       phy-mode = "rmii";
                        status = "disabled";
                };
 
@@ -67,6 +82,7 @@
                        reg = <0x5c700000 0x8000>;
                        interrupts = <0 98 0x4>;
                        interrupt-names = "macirq";
+                       phy-mode = "rgmii";
                        status = "disabled";
                };
 
                        #gpio-range-cells = <2>;
                };
 
-               spi1: spi@5d400000 {
-                       compatible = "arm,pl022", "arm,primecell";
-                       reg = <0x5d400000 0x1000>;
-                       interrupts = <0 99 0x4>;
-                       status = "disabled";
-               };
-
                apb {
                        i2c1: i2c@5cd00000 {
                                #address-cells = <1>;
                                status = "disabled";
                        };
 
+                       spi1: spi@5d400000 {
+                               compatible = "arm,pl022", "arm,primecell";
+                               reg = <0x5d400000 0x1000>;
+                               interrupts = <0 99 0x4>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        serial@5c800000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x5c800000 0x1000>;
index 045f7123ffac5a26eb42e4e025ec88015164075a..d6c30ae0a8d75edc1fee019b1892d341401818fd 100644 (file)
                                        st,pins = "fsmc_8bit_grp";
                                        st,function = "fsmc";
                                };
-                               kbd {
-                                       st,pins = "keyboard_row_col_grp",
-                                               "keyboard_col5_grp";
-                                       st,function = "keyboard";
-                               };
                                uart0 {
-                                       st,pins = "uart0_grp", "uart0_enh_grp";
+                                       st,pins = "uart0_grp";
                                        st,function = "uart0";
                                };
-                               i2c0-pmx {
+                               i2c0 {
                                        st,pins = "i2c0_grp";
                                        st,function = "i2c0";
                                };
-                               i2c1-pmx {
+                               i2c1 {
                                        st,pins = "i2c1_grp";
                                        st,function = "i2c1";
                                };
                                        st,function = "spdif_out";
                                };
                                ssp0 {
-                                       st,pins = "ssp0_grp", "ssp0_cs1_grp",
-                                               "ssp0_cs3_grp";
+                                       st,pins = "ssp0_grp", "ssp0_cs1_grp", "ssp0_cs2_grp", "ssp0_cs3_grp";
                                        st,function = "ssp0";
                                };
-                               pwm {
-                                       st,pins = "pwm2_grp", "pwm3_grp";
-                                       st,function = "pwm";
-                               };
                                smi-pmx {
                                        st,pins = "smi_grp";
                                        st,function = "smi";
                                        st,pins = "gmii_grp", "rgmii_grp";
                                        st,function = "gmac";
                                };
+                               cam0 {
+                                       st,pins = "cam0_grp";
+                                       st,function = "cam0";
+                               };
+                               cam1 {
+                                       st,pins = "cam1_grp";
+                                       st,function = "cam1";
+                               };
+                               cam2 {
+                                       st,pins = "cam2_grp";
+                                       st,function = "cam2";
+                               };
                                cam3 {
                                        st,pins = "cam3_grp";
                                        st,function = "cam3";
                                        st,pins = "sata_grp";
                                        st,function = "sata";
                                };
+                               pcie {
+                                       st,pins = "pcie_grp";
+                                       st,function = "pcie";
+                               };
+
                        };
                };
 
+               ahci@b1000000 {
+                       status = "okay";
+               };
+
                dma@ea800000 {
                        status = "okay";
                };
 
                fsmc: flash@b0000000 {
                        status = "okay";
+
+                       partition@0 {
+                               label = "xloader";
+                               reg = <0x0 0x200000>;
+                       };
+                       partition@200000 {
+                               label = "u-boot";
+                               reg = <0x200000 0x200000>;
+                       };
+                       partition@400000 {
+                               label = "environment";
+                               reg = <0x400000 0x100000>;
+                       };
+                       partition@500000 {
+                               label = "dtb";
+                               reg = <0x500000 0x100000>;
+                       };
+                       partition@600000 {
+                               label = "linux";
+                               reg = <0x600000 0xC00000>;
+                       };
+                       partition@1200000 {
+                               label = "rootfs";
+                               reg = <0x1200000 0x0>;
+                       };
                };
 
                gmac0: eth@e2000000 {
+                       phy-mode = "rgmii";
                        status = "okay";
                };
 
                                };
                                partition@10000 {
                                        label = "u-boot";
-                                       reg = <0x10000 0x40000>;
+                                       reg = <0x10000 0x50000>;
+                               };
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
                                };
-                               partition@50000 {
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
+                               };
+                               partition@80000 {
                                        label = "linux";
-                                       reg = <0x50000 0x2c0000>;
+                                       reg = <0x80000 0x310000>;
                                };
-                               partition@310000 {
+                               partition@390000 {
                                        label = "rootfs";
-                                       reg = <0x310000 0x4f0000>;
+                                       reg = <0x390000 0x0>;
                                };
                        };
                };
 
-               spi0: spi@e0100000 {
+               ehci@e4800000 {
                        status = "okay";
                };
 
-               ehci@e4800000 {
-                       status = "okay";
+               gpio_keys {
+                       compatible = "gpio-keys";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       button@1 {
+                               label = "wakeup";
+                               linux,code = <0x100>;
+                               gpios = <&gpio1 1 0x4>;
+                               debounce-interval = <20>;
+                               gpio-key,wakeup = <1>;
+                       };
                };
 
                ehci@e5800000 {
                        status = "okay";
                };
 
+               i2s0: i2s-play@b2400000 {
+                       status = "okay";
+               };
+
+               i2s1: i2s-rec@b2000000 {
+                       status = "okay";
+               };
+
+               incodec: dir-hifi {
+                       compatible = "dummy,dir-hifi";
+                       status = "okay";
+               };
+
                ohci@e4000000 {
                        status = "okay";
                };
                        status = "okay";
                };
 
+               outcodec: dit-hifi {
+                       compatible = "dummy,dit-hifi";
+                       status = "okay";
+               };
+
+               sound {
+                       compatible = "spear,spear-evb";
+                       audio-controllers = <&spdif0 &spdif1 &i2s0 &i2s1>;
+                       audio-codecs = <&incodec &outcodec &sta529 &sta529>;
+                       codec_dai_name = "dir-hifi", "dit-hifi", "sta529-audio", "sta529-audio";
+                       stream_name = "spdif-cap", "spdif-play", "i2s-play", "i2s-cap";
+                       dai_name = "spdifin-pcm", "spdifout-pcm", "i2s0-pcm", "i2s1-pcm";
+                       nr_controllers = <4>;
+                       status = "okay";
+               };
+
+               spdif0: spdif-in@d0100000 {
+                       status = "okay";
+               };
+
+               spdif1: spdif-out@d0000000 {
+                       status = "okay";
+               };
+
                apb {
                        adc@e0080000 {
                                status = "okay";
                        };
 
+                       i2s-play@b2400000 {
+                               status = "okay";
+                       };
+
+                       i2s-rec@b2000000 {
+                               status = "okay";
+                       };
+
                        gpio0: gpio@e0600000 {
                               status = "okay";
                        };
 
                        i2c0: i2c@e0280000 {
                               status = "okay";
+
+                               sta529: sta529@1a {
+                                       compatible = "st,sta529";
+                                       reg = <0x1a>;
+                               };
                        };
 
                        i2c1: i2c@b4000000 {
                               status = "okay";
+
+                               eeprom0@56 {
+                                       compatible = "st,eeprom";
+                                       reg = <0x56>;
+                               };
+
+                               stmpe801@41 {
+                                       compatible = "st,stmpe801";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x41>;
+                                       interrupts = <4 0x4>;
+                                       interrupt-parent = <&gpio0>;
+                                       irq-trigger = <0x2>;
+
+                                       stmpegpio: stmpe_gpio {
+                                               compatible = "st,stmpe-gpio";
+                                               gpio-controller;
+                                               #gpio-cells = <2>;
+                                       };
+                               };
                        };
 
                        kbd@e0300000 {
                                                 0x08080052 >;
                               autorepeat;
                               st,mode = <0>;
+                              suspended_rate = <2000000>;
                               status = "okay";
                        };
 
 
                        serial@e0000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@b4100000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
+                       };
+
+                       spi0: spi@e0100000 {
+                               status = "okay";
+                               num-cs = <3>;
+                               cs-gpios = <&gpiopinctrl 80 0>, <&gpiopinctrl 24 0>,
+                                          <&gpiopinctrl 85 0>;
+
+                               m25p80@0 {
+                                       compatible = "m25p80";
+                                       reg = <0>;
+                                       spi-max-frequency = <12000000>;
+                                       spi-cpol;
+                                       spi-cpha;
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable;
+                                       pl022,com-mode = <0x2>;
+                                       pl022,rx-level-trig = <0>;
+                                       pl022,tx-level-trig = <0>;
+                                       pl022,ctrl-len = <0x11>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+                               };
+
+                               stmpe610@1 {
+                                       compatible = "st,stmpe610";
+                                       spi-max-frequency = <1000000>;
+                                       spi-cpha;
+                                       reg = <1>;
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable;
+                                       pl022,com-mode = <0>;
+                                       pl022,rx-level-trig = <0>;
+                                       pl022,tx-level-trig = <0>;
+                                       pl022,ctrl-len = <0x7>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+                                       interrupts = <100 0>;
+                                       interrupt-parent = <&gpiopinctrl>;
+                                       irq-trigger = <0x2>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       stmpe_touchscreen {
+                                               compatible = "st,stmpe-ts";
+                                               ts,sample-time = <4>;
+                                               ts,mod-12b = <1>;
+                                               ts,ref-sel = <0>;
+                                               ts,adc-freq = <1>;
+                                               ts,ave-ctrl = <1>;
+                                               ts,touch-det-delay = <2>;
+                                               ts,settling = <2>;
+                                               ts,fraction-z = <7>;
+                                               ts,i-drive = <1>;
+                                       };
+                               };
+
+                               spidev@2 {
+                                       compatible = "spidev";
+                                       reg = <2>;
+                                       spi-max-frequency = <25000000>;
+                                       spi-cpha;
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable;
+                                       pl022,com-mode = <0x2>;
+                                       pl022,rx-level-trig = <0>;
+                                       pl022,tx-level-trig = <0>;
+                                       pl022,ctrl-len = <0x11>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+                               };
+                       };
+
+                       timer@ec800600 {
+                               status = "okay";
                        };
 
                        wdt@ec800620 {
index 6c09eb0a1b2bbad90683f7311c14f052a2e21ac7..34da11aa679504616359ec759568d31160eb829a 100644 (file)
        compatible = "st,spear1340";
 
        ahb {
+
+               spics: spics@e0700000{
+                       compatible = "st,spear-spics-gpio";
+                       reg = <0xe0700000 0x1000>;
+                       st-spics,peripcfg-reg = <0x42c>;
+                       st-spics,sw-enable-bit = <21>;
+                       st-spics,cs-value-bit = <20>;
+                       st-spics,cs-enable-mask = <3>;
+                       st-spics,cs-enable-shift = <18>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       status = "disabled";
+               };
+
                ahci@b1000000 {
                        compatible = "snps,spear-ahci";
                        reg = <0xb1000000 0x10000>;
                        status = "disabled";
                };
 
+               i2s-play@b2400000 {
+                       compatible = "snps,designware-i2s";
+                       reg = <0xb2400000 0x10000>;
+                       interrupt-names = "play_irq";
+                       interrupts = <0 98 0x4
+                                     0 99 0x4>;
+                       play;
+                       channel = <8>;
+                       status = "disabled";
+               };
+
+               i2s-rec@b2000000 {
+                       compatible = "snps,designware-i2s";
+                       reg = <0xb2000000 0x10000>;
+                       interrupt-names = "record_irq";
+                       interrupts = <0 100  0x4
+                                     0 101 0x4>;
+                       record;
+                       channel = <8>;
+                       status = "disabled";
+               };
+
                pinmux: pinmux@e0700000 {
                        compatible = "st,spear1340-pinmux";
                        reg = <0xe0700000 0x1000>;
                        #gpio-range-cells = <2>;
                };
 
+               pwm: pwm@e0180000 {
+                       compatible ="st,spear13xx-pwm";
+                       reg = <0xe0180000 0x1000>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               spdif-in@d0100000 {
+                       compatible = "st,spdif-in";
+                       reg = < 0xd0100000 0x20000
+                               0xd0110000 0x10000 >;
+                       interrupts = <0 84 0x4>;
+                       status = "disabled";
+               };
+
+               spdif-out@d0000000 {
+                       compatible = "st,spdif-out";
+                       reg = <0xd0000000 0x20000>;
+                       interrupts = <0 85 0x4>;
+                       status = "disabled";
+               };
+
                spi1: spi@5d400000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0x5d400000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        interrupts = <0 99 0x4>;
                        status = "disabled";
                };
                                compatible = "snps,designware-i2c";
                                reg = <0xb4000000 0x1000>;
                                interrupts = <0 104 0x4>;
+                               write-16bit;
                                status = "disabled";
                        };
 
index f7b84aced654ca643bc49ebe83b376425a6b893f..009096d1d2c37694bbd30d82f90ee294bbe18b2c 100644 (file)
                bootargs = "console=ttyAMA0,115200";
        };
 
+       cpufreq {
+               compatible = "st,cpufreq-spear";
+               cpufreq_tbl = < 166000
+                               200000
+                               250000
+                               300000
+                               400000
+                               500000
+                               600000 >;
+               status = "disable";
+       };
+
        ahb {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
                ranges = <0x50000000 0x50000000 0x10000000
                          0xb0000000 0xb0000000 0x10000000
+                         0xd0000000 0xd0000000 0x02000000
+                         0xd8000000 0xd8000000 0x01000000
                          0xe0000000 0xe0000000 0x10000000>;
 
                sdhci@b3000000 {
@@ -81,7 +95,7 @@
 
                cf@b2800000 {
                        compatible = "arasan,cf-spear1340";
-                       reg = <0xb2800000 0x100>;
+                       reg = <0xb2800000 0x1000>;
                        interrupts = <0 29 0x4>;
                        status = "disabled";
                };
                                      0 23 0x4>;
                        st,ale-off = <0x20000>;
                        st,cle-off = <0x10000>;
+                       st,mode = <2>;
                        status = "disabled";
                };
 
                        status = "disabled";
                };
 
+               pcm {
+                       compatible = "st,pcm-audio";
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       status = "disable";
+               };
+
                smi: flash@ea000000 {
                        compatible = "st,spear600-smi";
                        #address-cells = <1>;
                        status = "disabled";
                };
 
-               spi0: spi@e0100000 {
-                       compatible = "arm,pl022", "arm,primecell";
-                       reg = <0xe0100000 0x1000>;
-                       interrupts = <0 31 0x4>;
-                       status = "disabled";
-               };
-
                ehci@e4800000 {
                        compatible = "st,spear600-ehci", "usb-ehci";
                        reg = <0xe4800000 0x1000>;
                        interrupts = <0 64 0x4>;
+                       usbh0_id = <0>;
                        status = "disabled";
                };
 
                        compatible = "st,spear600-ehci", "usb-ehci";
                        reg = <0xe5800000 0x1000>;
                        interrupts = <0 66 0x4>;
+                       usbh1_id = <1>;
                        status = "disabled";
                };
 
                        compatible = "st,spear600-ohci", "usb-ohci";
                        reg = <0xe4000000 0x1000>;
                        interrupts = <0 65 0x4>;
+                       usbh0_id = <0>;
                        status = "disabled";
                };
 
                        compatible = "st,spear600-ohci", "usb-ohci";
                        reg = <0xe5000000 0x1000>;
                        interrupts = <0 67 0x4>;
+                       usbh1_id = <1>;
                        status = "disabled";
                };
 
                        compatible = "simple-bus";
                        ranges = <0x50000000 0x50000000 0x10000000
                                  0xb0000000 0xb0000000 0x10000000
+                                 0xd0000000 0xd0000000 0x02000000
+                                 0xd8000000 0xd8000000 0x01000000
                                  0xe0000000 0xe0000000 0x10000000>;
 
                        gpio0: gpio@e0600000 {
                                status = "disabled";
                        };
 
+                       i2s@e0180000 {
+                               compatible = "st,designware-i2s";
+                               reg = <0xe0180000 0x1000>;
+                               interrupt-names = "play_irq", "record_irq";
+                               interrupts = <0 10 0x4
+                                             0 11 0x4 >;
+                               status = "disabled";
+                       };
+
+                       i2s@e0200000 {
+                               compatible = "st,designware-i2s";
+                               reg = <0xe0200000 0x1000>;
+                               interrupt-names = "play_irq", "record_irq";
+                               interrupts = <0 26 0x4
+                                             0 53 0x4>;
+                               status = "disabled";
+                       };
+
+                       spi0: spi@e0100000 {
+                               compatible = "arm,pl022", "arm,primecell";
+                               reg = <0xe0100000 0x1000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               interrupts = <0 31 0x4>;
+                               status = "disabled";
+                       };
+
                        rtc@e0580000 {
-                               compatible = "st,spear-rtc";
+                               compatible = "st,spear600-rtc";
                                reg = <0xe0580000 0x1000>;
                                interrupts = <0 36 0x4>;
                                status = "disabled";
                        adc@e0080000 {
                                compatible = "st,spear600-adc";
                                reg = <0xe0080000 0x1000>;
-                               interrupts = <0 44 0x4>;
+                               interrupts = <0 12 0x4>;
                                status = "disabled";
                        };
 
                        timer@ec800600 {
                                compatible = "arm,cortex-a9-twd-timer";
                                reg = <0xec800600 0x20>;
-                               interrupts = <1 13 0x301>;
+                               interrupts = <1 13 0x4>;
+                               status = "disabled";
                        };
 
                        wdt@ec800620 {
                        thermal@e07008c4 {
                                compatible = "st,thermal-spear1340";
                                reg = <0xe07008c4 0x4>;
+                               thermal_flags = <0x7000>;
                        };
                };
        };
index 1e7c7a8e2123f63b3f671d4f5fcb8bd2fe1f8dd1..5de1431653e4c5a9f4152ce8323b0c111dd80b65 100644 (file)
                                };
                                partition@10000 {
                                        label = "u-boot";
-                                       reg = <0x10000 0x40000>;
+                                       reg = <0x10000 0x50000>;
                                };
-                               partition@50000 {
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
+                               };
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
+                               };
+                               partition@80000 {
                                        label = "linux";
-                                       reg = <0x50000 0x2c0000>;
+                                       reg = <0x80000 0x310000>;
                                };
-                               partition@310000 {
+                               partition@390000 {
                                        label = "rootfs";
-                                       reg = <0x310000 0x4f0000>;
+                                       reg = <0x390000 0x0>;
                                };
                        };
                };
 
                        serial@d0000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        wdt@fc880000 {
index ed3627c116ccbd7c5e8f90208fab4c37ef7a97d0..090adc65601504d4744f3d8156d3fdc464c60521 100644 (file)
@@ -27,7 +27,7 @@
                };
 
                clcd@60000000 {
-                       compatible = "arm,clcd-pl110", "arm,primecell";
+                       compatible = "arm,pl110", "arm,primecell";
                        reg = <0x60000000 0x1000>;
                        interrupts = <30>;
                        status = "disabled";
                        status = "disabled";
                };
 
+               shirq: interrupt-controller@0x50000000 {
+                       compatible = "st,spear300-shirq";
+                       reg = <0x50000000 0x1000>;
+                       interrupts = <28>;
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+               };
+
                apb {
                        #address-cells = <1>;
                        #size-cells = <1>;
                                compatible = "arm,pl061", "arm,primecell";
                                gpio-controller;
                                reg = <0xa9000000 0x1000>;
+                               interrupts = <8>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        kbd@a0000000 {
                                compatible = "st,spear300-kbd";
                                reg = <0xa0000000 0x1000>;
+                               interrupts = <7>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
                };
index b00544e0cd5d18e313eaf6807dc4c8a18294548b..b09632963d158dfa1f505fc8b0325b5aaa64f42e 100644 (file)
                                };
                                partition@10000 {
                                        label = "u-boot";
-                                       reg = <0x10000 0x40000>;
+                                       reg = <0x10000 0x50000>;
                                };
-                               partition@50000 {
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
+                               };
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
+                               };
+                               partition@80000 {
                                        label = "linux";
-                                       reg = <0x50000 0x2c0000>;
+                                       reg = <0x80000 0x310000>;
                                };
-                               partition@310000 {
+                               partition@390000 {
                                        label = "rootfs";
-                                       reg = <0x310000 0x4f0000>;
+                                       reg = <0x390000 0x0>;
                                };
                        };
                };
 
                        serial@d0000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@b2000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@b2080000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@b2100000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@b2180000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@b2200000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        wdt@fc880000 {
index 930303e48df932e42f1c9d4042cbe5290fff4d20..e814e5e9708318f968ca03224efae27d92242bb6 100644 (file)
                        status = "disabled";
                };
 
+               shirq: interrupt-controller@0xb4000000 {
+                       compatible = "st,spear310-shirq";
+                       reg = <0xb4000000 0x1000>;
+                       interrupts = <28 29 30 1>;
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+               };
+
                apb {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        serial@b2000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2000000 0x1000>;
+                               interrupts = <8>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        serial@b2080000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2080000 0x1000>;
+                               interrupts = <9>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        serial@b2100000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2100000 0x1000>;
+                               interrupts = <10>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        serial@b2180000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2180000 0x1000>;
+                               interrupts = <11>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        serial@b2200000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2200000 0x1000>;
+                               interrupts = <12>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
index ad4bfc68ee059b4632cde6b69f9a851a064cf90e..fdedbb514102b2920a2ea45edcbfa860b28b346e 100644 (file)
                                        st,function = "mii2";
                                };
                                pwm0_1 {
-                                       st,pins = "pwm0_1_pin_14_15_grp";
+                                       st,pins = "pwm0_1_pin_37_38_grp";
                                        st,function = "pwm0_1";
                                };
-                               pwm2 {
-                                       st,pins = "pwm2_pin_13_grp";
-                                       st,function = "pwm2";
-                               };
                        };
                };
 
-               clcd@90000000 {
-                       status = "okay";
-               };
-
                dma@fc400000 {
                        status = "okay";
                };
                };
 
                sdhci@70000000 {
+                       power-gpio = <&gpiopinctrl 61 1>;
                        status = "okay";
                };
 
                                };
                                partition@10000 {
                                        label = "u-boot";
-                                       reg = <0x10000 0x40000>;
+                                       reg = <0x10000 0x50000>;
+                               };
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
+                               };
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
                                };
-                               partition@50000 {
+                               partition@80000 {
                                        label = "linux";
-                                       reg = <0x50000 0x2c0000>;
+                                       reg = <0x80000 0x310000>;
                                };
-                               partition@310000 {
+                               partition@390000 {
                                        label = "rootfs";
-                                       reg = <0x310000 0x4f0000>;
+                                       reg = <0x390000 0x0>;
                                };
                        };
                };
 
                        serial@d0000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@a3000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@a4000000 {
                               status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        wdt@fc880000 {
diff --git a/arch/arm/boot/dts/spear320-hmi.dts b/arch/arm/boot/dts/spear320-hmi.dts
new file mode 100644 (file)
index 0000000..3075d2d
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * DTS file for SPEAr320 Evaluation Baord
+ *
+ * Copyright 2012 Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "spear320.dtsi"
+
+/ {
+       model = "ST SPEAr320 HMI Board";
+       compatible = "st,spear320-hmi", "st,spear320";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory {
+               reg = <0 0x40000000>;
+       };
+
+       ahb {
+               pinmux@b3000000 {
+                       st,pinmux-mode = <4>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&state_default>;
+
+                       state_default: pinmux {
+                               i2c0 {
+                                       st,pins = "i2c0_grp";
+                                       st,function = "i2c0";
+                               };
+                               ssp0 {
+                                       st,pins = "ssp0_grp";
+                                       st,function = "ssp0";
+                               };
+                               uart0 {
+                                       st,pins = "uart0_grp";
+                                       st,function = "uart0";
+                               };
+                               clcd {
+                                       st,pins = "clcd_grp";
+                                       st,function = "clcd";
+                               };
+                               fsmc {
+                                       st,pins = "fsmc_8bit_grp";
+                                       st,function = "fsmc";
+                               };
+                               sdhci {
+                                       st,pins = "sdhci_cd_12_grp";
+                                       st,function = "sdhci";
+                               };
+                               i2s {
+                                       st,pins = "i2s_grp";
+                                       st,function = "i2s";
+                               };
+                               uart1 {
+                                       st,pins = "uart1_grp";
+                                       st,function = "uart1";
+                               };
+                               uart2 {
+                                       st,pins = "uart2_grp";
+                                       st,function = "uart2";
+                               };
+                               can0 {
+                                       st,pins = "can0_grp";
+                                       st,function = "can0";
+                               };
+                               can1 {
+                                       st,pins = "can1_grp";
+                                       st,function = "can1";
+                               };
+                               mii0_1 {
+                                       st,pins = "rmii0_1_grp";
+                                       st,function = "mii0_1";
+                               };
+                               pwm0_1 {
+                                       st,pins = "pwm0_1_pin_37_38_grp";
+                                       st,function = "pwm0_1";
+                               };
+                               pwm2 {
+                                       st,pins = "pwm2_pin_34_grp";
+                                       st,function = "pwm2";
+                               };
+                       };
+               };
+
+               clcd@90000000 {
+                       status = "okay";
+               };
+
+               dma@fc400000 {
+                       status = "okay";
+               };
+
+               ehci@e1800000 {
+                       status = "okay";
+               };
+
+               fsmc: flash@4c000000 {
+                       status = "okay";
+
+                       partition@0 {
+                               label = "xloader";
+                               reg = <0x0 0x80000>;
+                       };
+                       partition@80000 {
+                               label = "u-boot";
+                               reg = <0x80000 0x140000>;
+                       };
+                       partition@1C0000 {
+                               label = "environment";
+                               reg = <0x1C0000 0x40000>;
+                       };
+                       partition@200000 {
+                               label = "dtb";
+                               reg = <0x200000 0x40000>;
+                       };
+                       partition@240000 {
+                               label = "linux";
+                               reg = <0x240000 0xC00000>;
+                       };
+                       partition@E40000 {
+                               label = "rootfs";
+                               reg = <0xE40000 0x0>;
+                       };
+               };
+
+               gpio_keys {
+                       compatible = "gpio-keys";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       button@1 {
+                               label = "user button 1";
+                               linux,code = <0x100>;
+                               gpios = <&stmpegpio 3 0x4>;
+                               debounce-interval = <20>;
+                               gpio-key,wakeup = <1>;
+                       };
+
+                       button@2 {
+                               label = "user button 2";
+                               linux,code = <0x200>;
+                               gpios = <&stmpegpio 2 0x4>;
+                               debounce-interval = <20>;
+                               gpio-key,wakeup = <1>;
+                       };
+               };
+
+               ohci@e1900000 {
+                       status = "okay";
+               };
+
+               ohci@e2100000 {
+                       status = "okay";
+               };
+
+               pwm: pwm@a8000000 {
+                       status = "okay";
+               };
+
+               sdhci@70000000 {
+                       power-gpio = <&gpiopinctrl 50 1>;
+                       power_always_enb;
+                       status = "okay";
+               };
+
+               smi: flash@fc000000 {
+                       status = "okay";
+                       clock-rate=<50000000>;
+
+                       flash@f8000000 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0xf8000000 0x800000>;
+                               st,smi-fast-mode;
+
+                               partition@0 {
+                                       label = "xloader";
+                                       reg = <0x0 0x10000>;
+                               };
+                               partition@10000 {
+                                       label = "u-boot";
+                                       reg = <0x10000 0x50000>;
+                               };
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
+                               };
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
+                               };
+                               partition@80000 {
+                                       label = "linux";
+                                       reg = <0x80000 0x310000>;
+                               };
+                               partition@390000 {
+                                       label = "rootfs";
+                                       reg = <0x390000 0x0>;
+                               };
+                       };
+               };
+
+               spi0: spi@d0100000 {
+                       status = "okay";
+               };
+
+               spi1: spi@a5000000 {
+                       status = "okay";
+               };
+
+               spi2: spi@a6000000 {
+                       status = "okay";
+               };
+
+               usbd@e1100000 {
+                       status = "okay";
+               };
+
+               apb {
+                       gpio0: gpio@fc980000 {
+                              status = "okay";
+                       };
+
+                       gpio@b3000000 {
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@d0180000 {
+                               status = "okay";
+
+                               stmpe811@41 {
+                                       compatible = "st,stmpe811";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x41>;
+                                       irq-over-gpio;
+                                       irq-gpios = <&gpiopinctrl 29 0x4>;
+                                       id = <0>;
+                                       blocks = <0x5>;
+                                       irq-trigger = <0x1>;
+
+                                       stmpegpio: stmpe-gpio {
+                                               compatible = "stmpe,gpio";
+                                               reg = <0>;
+                                               gpio-controller;
+                                               #gpio-cells = <2>;
+                                               gpio,norequest-mask = <0xF3>;
+                                       };
+
+                                       stmpe610-ts {
+                                               compatible = "stmpe,ts";
+                                               reg = <0>;
+                                               ts,sample-time = <4>;
+                                               ts,mod-12b = <1>;
+                                               ts,ref-sel = <0>;
+                                               ts,adc-freq = <1>;
+                                               ts,ave-ctrl = <1>;
+                                               ts,touch-det-delay = <3>;
+                                               ts,settling = <4>;
+                                               ts,fraction-z = <7>;
+                                               ts,i-drive = <1>;
+                                       };
+                               };
+                       };
+
+                       i2c1: i2c@a7000000 {
+                              status = "okay";
+                       };
+
+                       rtc@fc900000 {
+                              status = "okay";
+                       };
+
+                       serial@d0000000 {
+                              status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
+                       };
+
+                       serial@a3000000 {
+                              status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
+                       };
+
+                       serial@a4000000 {
+                              status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
+                       };
+
+                       wdt@fc880000 {
+                              status = "okay";
+                       };
+               };
+       };
+};
index 67d7ada7127556eb5b5264ae171145744f82b36d..c056a84deabf90cfdf0ae937faaabf6fd5ff13ec 100644 (file)
                };
 
                clcd@90000000 {
-                       compatible = "arm,clcd-pl110", "arm,primecell";
+                       compatible = "arm,pl110", "arm,primecell";
                        reg = <0x90000000 0x1000>;
-                       interrupts = <33>;
+                       interrupts = <8>;
+                       interrupt-parent = <&shirq>;
                        status = "disabled";
                };
 
                sdhci@70000000 {
                        compatible = "st,sdhci-spear";
                        reg = <0x70000000 0x100>;
-                       interrupts = <29>;
+                       interrupts = <10>;
+                       interrupt-parent = <&shirq>;
                        status = "disabled";
                };
 
+               shirq: interrupt-controller@0xb3000000 {
+                       compatible = "st,spear320-shirq";
+                       reg = <0xb3000000 0x1000>;
+                       interrupts = <30 28 29 1>;
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+               };
+
                spi1: spi@a5000000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0xa5000000 0x1000>;
+                       interrupts = <15>;
+                       interrupt-parent = <&shirq>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        status = "disabled";
                };
 
                spi2: spi@a6000000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0xa6000000 0x1000>;
+                       interrupts = <16>;
+                       interrupt-parent = <&shirq>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        status = "disabled";
                };
 
+               pwm: pwm@a8000000 {
+                       compatible ="st,spear-pwm";
+                       reg = <0xa8000000 0x1000>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+                };
+
                apb {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "simple-bus";
-                       ranges = <0xa0000000 0xa0000000 0x10000000
+                       ranges = <0xa0000000 0xa0000000 0x20000000
                                  0xd0000000 0xd0000000 0x30000000>;
 
                        i2c1: i2c@a7000000 {
                                #size-cells = <0>;
                                compatible = "snps,designware-i2c";
                                reg = <0xa7000000 0x1000>;
+                               interrupts = <21>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        serial@a3000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xa3000000 0x1000>;
+                               interrupts = <13>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
                        serial@a4000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xa4000000 0x1000>;
+                               interrupts = <14>;
+                               interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 
index 3a8bb5736928292b1a78359342550e709e052a2d..c2a852d43c4895fe543b0849f9580d594bca4531 100644 (file)
@@ -53,6 +53,7 @@
                        reg = <0xe0800000 0x8000>;
                        interrupts = <23 22>;
                        interrupt-names = "macirq", "eth_wake_irq";
+                       phy-mode = "mii";
                        status = "disabled";
                };
 
@@ -69,6 +70,8 @@
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0xd0100000 0x1000>;
                        interrupts = <20>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        status = "disabled";
                };
 
                        };
 
                        rtc@fc900000 {
-                               compatible = "st,spear-rtc";
+                               compatible = "st,spear600-rtc";
                                reg = <0xfc900000 0x1000>;
                                interrupts = <10>;
                                status = "disabled";
index 1119c22c9a829479b716263d1faf3b5db0c7c601..d865a891776df9cf60d6052bf1cdfc753400ebd9 100644 (file)
        };
 
        ahb {
+               clcd@fc200000 {
+                       status = "okay";
+               };
+
                dma@fc400000 {
                        status = "okay";
                };
 
+               ehci@e1800000 {
+                       status = "okay";
+               };
+
+               ehci@e2000000 {
+                       status = "okay";
+               };
+
                gmac: ethernet@e0800000 {
                        phy-mode = "gmii";
                        status = "okay";
                };
 
+               ohci@e1900000 {
+                       status = "okay";
+               };
+
+               ohci@e2100000 {
+                       status = "okay";
+               };
+
                smi: flash@fc000000 {
                        status = "okay";
                        clock-rate=<50000000>;
                                };
                                partition@10000 {
                                        label = "u-boot";
-                                       reg = <0x10000 0x40000>;
+                                       reg = <0x10000 0x50000>;
                                };
-                               partition@50000 {
+                               partition@60000 {
+                                       label = "environment";
+                                       reg = <0x60000 0x10000>;
+                               };
+                               partition@70000 {
+                                       label = "dtb";
+                                       reg = <0x70000 0x10000>;
+                               };
+                               partition@80000 {
                                        label = "linux";
-                                       reg = <0x50000 0x2c0000>;
+                                       reg = <0x80000 0x310000>;
                                };
-                               partition@310000 {
+                               partition@390000 {
                                        label = "rootfs";
-                                       reg = <0x310000 0x4f0000>;
+                                       reg = <0x390000 0x0>;
                                };
                        };
                };
                apb {
                        serial@d0000000 {
                                status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
                        };
 
                        serial@d0080000 {
                                status = "okay";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <>;
+                       };
+
+                       rtc@fc900000 {
+                              status = "okay";
                        };
 
                        i2c@d0200000 {
index a3c36e47d7efcafee29eb73865eb5dec5651d4a4..e051dde5181f31d56f3ad099e3df49c0d5e308a4 100644 (file)
                        #interrupt-cells = <1>;
                };
 
+               clcd@fc200000 {
+                       compatible = "arm,pl110", "arm,primecell";
+                       reg = <0xfc200000 0x1000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <12>;
+                       status = "disabled";
+               };
+
                dma@fc400000 {
                        compatible = "arm,pl080", "arm,primecell";
                        reg = <0xfc400000 0x1000>;
@@ -59,6 +67,7 @@
                        interrupt-parent = <&vic1>;
                        interrupts = <24 23>;
                        interrupt-names = "macirq", "eth_wake_irq";
+                       phy-mode = "gmii";
                        status = "disabled";
                };
 
                                status = "disabled";
                        };
 
+                       rtc@fc900000 {
+                               compatible = "st,spear600-rtc";
+                               reg = <0xfc900000 0x1000>;
+                               interrupts = <10>;
+                               status = "disabled";
+                       };
+
                        timer@f0000000 {
                                compatible = "st,spear-timer";
                                reg = <0xf0000000 0x400>;
index 5b8215f424c5a72e283fb979b5d4828f1d386738..728a43c446f8a5e2acd25f66ae03c2bd867fa0fb 100644 (file)
@@ -47,6 +47,8 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -59,9 +61,8 @@ CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
@@ -78,9 +79,16 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
 CONFIG_SSB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_RCAR_PHY=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
index 159f75fc4377a81b9cc515667d8a88bfb8bb4627..dbea6f4efe9f7775879032ddf4ff3444a7a80a63 100644 (file)
@@ -17,8 +17,10 @@ CONFIG_ARM_APPENDED_DTB=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_NET=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_SATA_HIGHBANK=y
+CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_CALXEDA_XGMAC=y
 CONFIG_SMSC911X=y
index 3458752c4bb277da7d3574e050f847add462cc0a..a702fb345c01e5693d82f22d0eeb5fc2d7c88b2a 100644 (file)
@@ -12,6 +12,9 @@ CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
 CONFIG_MACH_ARMADA_XP=y
 # CONFIG_CACHE_L2X0 is not set
+# CONFIG_SWP_EMULATE is not set
+CONFIG_SMP=y
+# CONFIG_LOCAL_TIMERS is not set
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 # CONFIG_COMPACTION is not set
@@ -19,13 +22,27 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_VFP=y
+CONFIG_NET=y
+CONFIG_INET=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_MV=y
+CONFIG_NETDEVICES=y
+CONFIG_MVNETA=y
+CONFIG_MARVELL_PHY=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_I2C=y
+CONFIG_I2C_MV64XXX=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_DMADEVICES=y
+CONFIG_MV_XOR=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
index 0ac1293dba102dce226b510d2aca075558e16cfe..4e1ce211d43f101153f676cc2114a791b4a6ea52 100644 (file)
@@ -18,9 +18,10 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_MACH_SOCFPGA_CYCLONE5=y
 CONFIG_ARM_THUMBEE=y
+# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
 # CONFIG_CACHE_L2X0 is not set
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_VMSPLIT_2G=y
+CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
index 8ea02ac3ec1a8d2a4d659f179ed135b05b9075ff..67d06324e74a310084e1b35f89dca05cf910e345 100644 (file)
@@ -111,6 +111,8 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
 
 extern int dma_supported(struct device *dev, u64 mask);
 
+extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
+
 /**
  * arm_dma_alloc - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
index 5000397134b4e5ceb06521ecf1d22622a0918a82..1151188bcd83c391c0ba0ca3d51b4b32226aa4be 100644 (file)
@@ -49,6 +49,7 @@ DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
 DEFINE_GUEST_HANDLE(xen_pfn_t);
+DEFINE_GUEST_HANDLE(xen_ulong_t);
 
 /* Maximum number of virtual CPUs in multi-processor guests. */
 #define MAX_VIRT_CPUS 1
index 1862d8f2fd44c00d1d535a1b447a5ab6cdf333b7..0cd63d080c7bf2d93f35db5a69e3debc5147351e 100644 (file)
@@ -1598,7 +1598,7 @@ static int __init run_all_tests(void)
 {
        int ret = 0;
 
-       pr_info("Begining kprobe tests...\n");
+       pr_info("Beginning kprobe tests...\n");
 
 #ifndef CONFIG_THUMB2_KERNEL
 
index 8ce068240c69284a30ee54c8de879b0c38572ff6..7aeb473ee539b42a3b0bfc028bdd111cabd0c14c 100644 (file)
@@ -184,9 +184,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        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", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd0000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd4000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd8000.ssc", &ssc2_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
index 2a1f8e67683d90c6916b9c3657f7975b9760775c..3ebc9792560cebed75a53883e42e774742c5660c 100644 (file)
@@ -752,7 +752,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -794,7 +794,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -836,7 +836,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc2_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 2,
        .dev    = {
                .dma_mask               = &ssc2_dmamask,
index c65e7b8d7a8115c66d830761fe138a7e91c70969..b67cd5374117b4405e0f153d77cd4040bb3f83c5 100644 (file)
@@ -210,7 +210,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        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("pclk", "at91rm9200_ssc.0", &ssc_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
        /* more usart lookup table for DT entries */
index 1f6fac21b2c88fb95c187df78402f5dbf5b99931..eda8d1679d404ef3a75ad999fabd333c23296b58 100644 (file)
@@ -742,7 +742,7 @@ static struct resource ssc_resources[] = {
 };
 
 static struct platform_device at91sam9260_ssc_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc_dmamask,
index 9d3e9b8b9926bfd7b5a259f9d36e96e67a927261..2998a08afc2d91a020700807ff9fcd0ca813b68c 100644 (file)
@@ -174,9 +174,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        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("pclk", "ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc2_clk),
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
index 6ce6d27e2442d453213a0952180368ea62d95c81..92e0f861084aad210fab02837401eb5185255c98 100644 (file)
@@ -706,7 +706,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -748,7 +748,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -790,7 +790,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc2_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 2,
        .dev    = {
                .dma_mask               = &ssc2_dmamask,
index 82deb4d748b26a135834151dc8bb411191b44f63..b9fc60d1b33a2f2e6f0e4feef4f44fb82dda38e9 100644 (file)
@@ -186,8 +186,10 @@ static struct clk *periph_clocks[] __initdata = {
 static struct clk_lookup periph_clocks_lookups[] = {
        /* One additional fake clock for macb_hclk */
        CLKDEV_CON_ID("hclk", &macb_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
index fb98163b9b3adc6750520295b14c9a83137895bc..ed666f5cb01d577ffb219f2a7857ba84e913e619 100644 (file)
@@ -1199,7 +1199,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -1241,7 +1241,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index 45d753d473f68b086cb828873d20990a03fe2635..d3addee43d8dac22689c5e3b3970564dbc0d2aca 100644 (file)
@@ -239,8 +239,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        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("pclk", "at91sam9g45_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffa0000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
index e35964201a10b877f1e05fbabf4af782d0cbd4a3..827c9f2a70fb9a3f36c40570694bd2ed6960e652 100644 (file)
@@ -1459,7 +1459,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91sam9g45_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -1501,7 +1501,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91sam9g45_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index 44e3a633fda7d071c0a22a158523adf5c9613788..eb98704db2d92a4b24835b226cedcf7814260529 100644 (file)
@@ -184,8 +184,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        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("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &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),
index 160384d93db204a6ff3d7fb468a15e37f254e04a..ddf223ff35c41ba21999cc1a829975843bab51f3 100644 (file)
@@ -832,7 +832,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -874,7 +874,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index dfb2c0c13fb560331fc3179e3272cb909a77eecd..44a9a62dcc139f1b096d44b5e1c158cea168b3f2 100644 (file)
@@ -233,6 +233,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_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("pclk", "f0010000.ssc", &ssc_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),
index 7b512380236884722faca87b0a9a07789a5f7b58..1b7dd9f688d36b14f772725dbc7c6c079c4d64f9 100644 (file)
@@ -353,6 +353,16 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
         },
 };
 
+static struct platform_device sam9g20ek_audio_device = {
+       .name   = "at91sam9g20ek-audio",
+       .id     = -1,
+};
+
+static void __init ek_add_device_audio(void)
+{
+       platform_device_register(&sam9g20ek_audio_device);
+}
+
 
 static void __init ek_board_init(void)
 {
@@ -394,6 +404,7 @@ static void __init ek_board_init(void)
        at91_set_B_periph(AT91_PIN_PC1, 0);
        /* SSC (for WM8731) */
        at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+       ek_add_device_audio();
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
index d4f4dbfc0e59bf97682e950012828efb966a22c7..7211772edd9dee20e51501750b66f33448cabbd1 100644 (file)
@@ -763,16 +763,19 @@ static u8 da850_iis_serializer_direction[] = {
 };
 
 static struct snd_platform_data da850_evm_snd_data = {
-       .tx_dma_offset  = 0x2000,
-       .rx_dma_offset  = 0x2000,
-       .op_mode        = DAVINCI_MCASP_IIS_MODE,
-       .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
-       .tdm_slots      = 2,
-       .serial_dir     = da850_iis_serializer_direction,
-       .asp_chan_q     = EVENTQ_0,
-       .version        = MCASP_VERSION_2,
-       .txnumevt       = 1,
-       .rxnumevt       = 1,
+       .tx_dma_offset          = 0x2000,
+       .rx_dma_offset          = 0x2000,
+       .op_mode                = DAVINCI_MCASP_IIS_MODE,
+       .num_serializer         = ARRAY_SIZE(da850_iis_serializer_direction),
+       .tdm_slots              = 2,
+       .serial_dir             = da850_iis_serializer_direction,
+       .asp_chan_q             = EVENTQ_0,
+       .ram_chan_q             = EVENTQ_1,
+       .version                = MCASP_VERSION_2,
+       .txnumevt               = 1,
+       .rxnumevt               = 1,
+       .sram_size_playback     = SZ_8K,
+       .sram_size_capture      = SZ_8K,
 };
 
 static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1510,6 +1513,7 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
                                ret);
 
+       da850_evm_snd_data.sram_pool = sram_get_gen_pool();
        da8xx_register_mcasp(0, &da850_evm_snd_data);
 
        ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
index 510648e0394b80d4f6186f93ae4516f7624d7dbb..678a54a64daee17b09cf096cf4bcb2f31199383b 100644 (file)
@@ -408,7 +408,7 @@ static struct clk_lookup da830_clks[] = {
        CLK(NULL,               "pwm2",         &pwm2_clk),
        CLK("eqep.0",           NULL,           &eqep0_clk),
        CLK("eqep.1",           NULL,           &eqep1_clk),
-       CLK("da8xx_lcdc.0",     NULL,           &lcdc_clk),
+       CLK("da8xx_lcdc.0",     "fck",          &lcdc_clk),
        CLK("davinci-mcasp.0",  NULL,           &mcasp0_clk),
        CLK("davinci-mcasp.1",  NULL,           &mcasp1_clk),
        CLK("davinci-mcasp.2",  NULL,           &mcasp2_clk),
index 68c5fe01857cad4bfb97191b43a0e7f67ade4f78..6b9154e9f9080f082442b85915d8092af06866b5 100644 (file)
@@ -403,7 +403,7 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "rmii",         &rmii_clk),
        CLK("davinci_emac.1",   NULL,           &emac_clk),
        CLK("davinci-mcasp.0",  NULL,           &mcasp_clk),
-       CLK("da8xx_lcdc.0",     NULL,           &lcdc_clk),
+       CLK("da8xx_lcdc.0",     "fck",          &lcdc_clk),
        CLK("davinci_mmc.0",    NULL,           &mmcsd0_clk),
        CLK("davinci_mmc.1",    NULL,           &mmcsd1_clk),
        CLK(NULL,               "aemif",        &aemif_clk),
index 46c9a0c09ae5d83e6895edde655e9581656e93bf..fcdbe437409e3a5141b5b7231a143fecf7c933a4 100644 (file)
@@ -589,29 +589,9 @@ int __init da8xx_register_uio_pruss(void)
        return platform_device_register(&da8xx_uio_pruss_dev);
 }
 
-static const struct display_panel disp_panel = {
-       QVGA,
-       16,
-       16,
-       COLOR_ACTIVE,
-};
-
 static struct lcd_ctrl_config lcd_cfg = {
-       &disp_panel,
-       .ac_bias                = 255,
-       .ac_bias_intrpt         = 0,
-       .dma_burst_sz           = 16,
+       .panel_shade            = COLOR_ACTIVE,
        .bpp                    = 16,
-       .fdd                    = 255,
-       .tft_alt_mode           = 0,
-       .stn_565_mode           = 0,
-       .mono_8bit_mode         = 0,
-       .invert_line_clock      = 1,
-       .invert_frm_clock       = 1,
-       .sync_edge              = 0,
-       .sync_ctrl              = 1,
-       .raster_order           = 0,
-       .fifo_th                = 6,
 };
 
 struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
index 00946e23c1ee3100a2027a2e1d918d261ca89517..c90250e3bef8068f0333c2387fb9ae96c84cd7a3 100644 (file)
@@ -53,6 +53,7 @@ static struct dev_pm_domain davinci_pm_domain = {
 
 static struct pm_clk_notifier_block platform_bus_notifier = {
        .pm_domain = &davinci_pm_domain,
+       .con_ids = { "fck", NULL, },
 };
 
 static int __init davinci_pm_runtime_init(void)
index 00154e74ce6b11d892840315ddedd9366b73e86d..603c5fd99e8a30df2ecb63af8011c23a28ef90f2 100644 (file)
@@ -17,6 +17,8 @@ config MACH_CM_A510
 
 config MACH_DOVE_DT
        bool "Marvell Dove Flattened Device Tree"
+       select MVEBU_CLK_CORE
+       select MVEBU_CLK_GATING
        select USE_OF
        help
          Say 'Y' here if you want your kernel to support the
index f723fe13d0f032c48126c1e745c894e296d7ccbf..89f4f993cd03fb4c0d4ed6eac000d1131aa351ac 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/pci.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/mvebu.h>
 #include <linux/ata_platform.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
@@ -32,6 +33,7 @@
 #include <linux/irq.h>
 #include <plat/time.h>
 #include <linux/platform_data/usb-ehci-orion.h>
+#include <linux/platform_data/dma-mv_xor.h>
 #include <plat/irq.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
@@ -123,8 +125,8 @@ static void __init dove_clk_init(void)
        orion_clkdev_add(NULL, "mv_crypto", crypto);
        orion_clkdev_add(NULL, "dove-ac97", ac97);
        orion_clkdev_add(NULL, "dove-pdma", pdma);
-       orion_clkdev_add(NULL, "mv_xor_shared.0", xor0);
-       orion_clkdev_add(NULL, "mv_xor_shared.1", xor1);
+       orion_clkdev_add(NULL, MV_XOR_NAME ".0", xor0);
+       orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
 }
 
 /*****************************************************************************
@@ -376,19 +378,44 @@ void dove_restart(char mode, const char *cmd)
 
 #if defined(CONFIG_MACH_DOVE_DT)
 /*
- * Auxdata required until real OF clock provider
+ * There are still devices that doesn't even know about DT,
+ * get clock gates here and add a clock lookup.
  */
-struct of_dev_auxdata dove_auxdata_lookup[] __initdata = {
-       OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
-       OF_DEV_AUXDATA("marvell,orion-spi", 0xf1014600, "orion_spi.1", NULL),
-       OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
-       OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
-                      NULL),
-       OF_DEV_AUXDATA("marvell,orion-sata", 0xf10a0000, "sata_mv.0", NULL),
-       OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1092000, "sdhci-dove.0", NULL),
-       OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1090000, "sdhci-dove.1", NULL),
-       {},
-};
+static void __init dove_legacy_clk_init(void)
+{
+       struct device_node *np = of_find_compatible_node(NULL, NULL,
+                                        "marvell,dove-gating-clock");
+       struct of_phandle_args clkspec;
+
+       clkspec.np = np;
+       clkspec.args_count = 1;
+
+       clkspec.args[0] = CLOCK_GATING_BIT_USB0;
+       orion_clkdev_add(NULL, "orion-ehci.0",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CLOCK_GATING_BIT_USB1;
+       orion_clkdev_add(NULL, "orion-ehci.1",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CLOCK_GATING_BIT_GBE;
+       orion_clkdev_add(NULL, "mv643xx_eth_port.0",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CLOCK_GATING_BIT_PCIE0;
+       orion_clkdev_add("0", "pcie",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CLOCK_GATING_BIT_PCIE1;
+       orion_clkdev_add("1", "pcie",
+                        of_clk_get_from_provider(&clkspec));
+}
+
+static void __init dove_of_clk_init(void)
+{
+       mvebu_clocks_init();
+       dove_legacy_clk_init();
+}
 
 static struct mv643xx_eth_platform_data dove_dt_ge00_data = {
        .phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT,
@@ -405,20 +432,17 @@ static void __init dove_dt_init(void)
        dove_setup_cpu_mbus();
 
        /* Setup root of clk tree */
-       dove_clk_init();
+       dove_of_clk_init();
 
        /* Internal devices not ported to DT yet */
        dove_rtc_init();
-       dove_xor0_init();
-       dove_xor1_init();
 
        dove_ge00_init(&dove_dt_ge00_data);
        dove_ehci0_init();
        dove_ehci1_init();
        dove_pcie_init(1, 1);
 
-       of_platform_populate(NULL, of_default_bus_match_table,
-                            dove_auxdata_lookup, NULL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const dove_dt_board_compat[] = {
index 7652f5d78a56664dba722ec0dea19e51d0dd3937..e9d7b80bae492cf241818d989e3f926d9577761e 100644 (file)
@@ -80,6 +80,8 @@ static struct sleep_save exynos5_clock_save[] = {
        SAVE_ITEM(EXYNOS5_VPLL_CON0),
        SAVE_ITEM(EXYNOS5_VPLL_CON1),
        SAVE_ITEM(EXYNOS5_VPLL_CON2),
+       SAVE_ITEM(EXYNOS5_PWR_CTRL1),
+       SAVE_ITEM(EXYNOS5_PWR_CTRL2),
 };
 #endif
 
@@ -661,15 +663,20 @@ static struct clk exynos5_init_clocks_off[] = {
                .ctrlbit        = (1 << 15),
        }, {
                .name           = "sata",
-               .devname        = "ahci",
+               .devname        = "exynos5-sata",
+               .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 6),
        }, {
-               .name           = "sata_phy",
+               .name           = "sata-phy",
+               .devname        = "exynos5-sata-phy",
+               .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 24),
        }, {
-               .name           = "sata_phy_i2c",
+               .name           = "i2c",
+               .devname        = "exynos5-sata-phy-i2c",
+               .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 25),
        }, {
@@ -692,6 +699,11 @@ static struct clk exynos5_init_clocks_off[] = {
                .devname        = "exynos5-mixer",
                .enable         = exynos5_clk_ip_disp1_ctrl,
                .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "dp",
+               .devname        = "exynos-dp",
+               .enable         = exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 4),
        }, {
                .name           = "jpeg",
                .enable         = exynos5_clk_ip_gen_ctrl,
@@ -1239,6 +1251,16 @@ static struct clksrc_clk exynos5_clksrcs[] = {
                .sources = &exynos5_clkset_aclk,
                .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
                .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_sata",
+                       .devname        = "exynos5-sata",
+                       .enable         = exynos5_clksrc_mask_fsys_ctrl,
+                       .ctrlbit        = (1 << 24),
+               },
+               .sources = &exynos5_clkset_aclk,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
        }, {
                .clk    = {
                        .name           = "sclk_gscl_wrap",
index 8e4ec21ef2cf6ba3790b222e3e1ced6684ee2387..05092415277688605e4c2dc5ede85ba60c94e678 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/suspend.h>
 #include <asm/unified.h>
 #include <asm/cpuidle.h>
+#include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 #include <mach/pmu.h>
 
@@ -157,12 +158,47 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
                return exynos4_enter_core0_aftr(dev, drv, new_index);
 }
 
+static void __init exynos5_core_down_clk(void)
+{
+       unsigned int tmp;
+
+       /*
+        * Enable arm clock down (in idle) and set arm divider
+        * ratios in WFI/WFE state.
+        */
+       tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
+             PWR_CTRL1_CORE1_DOWN_RATIO | \
+             PWR_CTRL1_DIV2_DOWN_EN     | \
+             PWR_CTRL1_DIV1_DOWN_EN     | \
+             PWR_CTRL1_USE_CORE1_WFE    | \
+             PWR_CTRL1_USE_CORE0_WFE    | \
+             PWR_CTRL1_USE_CORE1_WFI    | \
+             PWR_CTRL1_USE_CORE0_WFI;
+       __raw_writel(tmp, EXYNOS5_PWR_CTRL1);
+
+       /*
+        * Enable arm clock up (on exiting idle). Set arm divider
+        * ratios when not in idle along with the standby duration
+        * ratios.
+        */
+       tmp = PWR_CTRL2_DIV2_UP_EN       | \
+             PWR_CTRL2_DIV1_UP_EN       | \
+             PWR_CTRL2_DUR_STANDBY2_VAL | \
+             PWR_CTRL2_DUR_STANDBY1_VAL | \
+             PWR_CTRL2_CORE2_UP_RATIO   | \
+             PWR_CTRL2_CORE1_UP_RATIO;
+       __raw_writel(tmp, EXYNOS5_PWR_CTRL2);
+}
+
 static int __init exynos4_init_cpuidle(void)
 {
        int i, max_cpuidle_state, cpu_id;
        struct cpuidle_device *device;
        struct cpuidle_driver *drv = &exynos4_idle_driver;
 
+       if (soc_is_exynos5250())
+               exynos5_core_down_clk();
+
        /* Setup cpuidle driver */
        drv->state_count = (sizeof(exynos4_cpuidle_set) /
                                       sizeof(struct cpuidle_state));
index 8c9b38c9c5042d931ede0f3ab6f569cc3406dd86..d36ad76ad6a46cbab1f07e1c3d9e2a4cde230cd7 100644 (file)
 #define EXYNOS5_CLKDIV_STATCPU0                        EXYNOS_CLKREG(0x00600)
 #define EXYNOS5_CLKDIV_STATCPU1                        EXYNOS_CLKREG(0x00604)
 
+#define EXYNOS5_PWR_CTRL1                      EXYNOS_CLKREG(0x01020)
+#define EXYNOS5_PWR_CTRL2                      EXYNOS_CLKREG(0x01024)
+
 #define EXYNOS5_MPLL_CON0                      EXYNOS_CLKREG(0x04100)
 #define EXYNOS5_CLKSRC_CORE1                   EXYNOS_CLKREG(0x04204)
 
 
 #define EXYNOS5_EPLLCON0_LOCKED_SHIFT          (29)
 
+#define PWR_CTRL1_CORE2_DOWN_RATIO             (7 << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO             (7 << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN                 (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN                 (1 << 8)
+#define PWR_CTRL1_USE_CORE1_WFE                        (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE                        (1 << 4)
+#define PWR_CTRL1_USE_CORE1_WFI                        (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI                        (1 << 0)
+
+#define PWR_CTRL2_DIV2_UP_EN                   (1 << 25)
+#define PWR_CTRL2_DIV1_UP_EN                   (1 << 24)
+#define PWR_CTRL2_DUR_STANDBY2_VAL             (1 << 16)
+#define PWR_CTRL2_DUR_STANDBY1_VAL             (1 << 8)
+#define PWR_CTRL2_CORE2_UP_RATIO               (1 << 4)
+#define PWR_CTRL2_CORE1_UP_RATIO               (1 << 0)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
index 84428e72cf5e771fd6e42fd066879bfb36395272..3f30aa1ae3547897410d64471cdd20eca2372b95 100644 (file)
@@ -15,6 +15,7 @@
 #include <mach/map.h>
 
 #define S5P_PMUREG(x)                          (S5P_VA_PMU + (x))
+#define S5P_SYSREG(x)                          (S3C_VA_SYS + (x))
 
 #define S5P_CENTRAL_SEQ_CONFIGURATION          S5P_PMUREG(0x0200)
 
 
 /* For EXYNOS5 */
 
+#define EXYNOS5_SYS_I2C_CFG                                    S5P_SYSREG(0x0234)
+
 #define EXYNOS5_AUTO_WDTRESET_DISABLE                          S5P_PMUREG(0x0408)
 #define EXYNOS5_MASK_WDTRESET_REQUEST                          S5P_PMUREG(0x040C)
 
index 3f37a5e8a1f450d4d4e6797d0570c51df5b2805c..b938f9fc1dd1288d781241366daaa90d65582907 100644 (file)
@@ -147,7 +147,6 @@ static struct platform_device *armlex4210_devices[] __initdata = {
        &s3c_device_hsmmc3,
        &s3c_device_rtc,
        &s3c_device_wdt,
-       &samsung_asoc_dma,
        &armlex4210_smsc911x,
        &exynos4_device_ahci,
 };
index 929de766d4906cdb8856da45baf47301528fb3ae..f038c8cadca484e1831cd3277394bd8565ab88c1 100644 (file)
 #include <linux/of_fdt.h>
 #include <linux/serial_core.h>
 #include <linux/memblock.h>
-#include <linux/of_fdt.h>
+#include <linux/io.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <mach/map.h>
+#include <mach/regs-pmu.h>
 
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
@@ -124,6 +125,28 @@ static void __init exynos5_dt_map_io(void)
 
 static void __init exynos5_dt_machine_init(void)
 {
+       struct device_node *i2c_np;
+       const char *i2c_compat = "samsung,s3c2440-i2c";
+       unsigned int tmp;
+
+       /*
+        * Exynos5's legacy i2c controller and new high speed i2c
+        * controller have muxed interrupt sources. By default the
+        * interrupts for 4-channel HS-I2C controller are enabled.
+        * If node for first four channels of legacy i2c controller
+        * are available then re-configure the interrupts via the
+        * system register.
+        */
+       for_each_compatible_node(i2c_np, NULL, i2c_compat) {
+               if (of_device_is_available(i2c_np)) {
+                       if (of_alias_get_id(i2c_np, "i2c") < 4) {
+                               tmp = readl(EXYNOS5_SYS_I2C_CFG);
+                               writel(tmp & ~(0x1 << of_alias_get_id(i2c_np, "i2c")),
+                                               EXYNOS5_SYS_I2C_CFG);
+                       }
+               }
+       }
+
        if (of_machine_is_compatible("samsung,exynos5250"))
                of_platform_populate(NULL, of_default_bus_match_table,
                                     exynos5250_auxdata_lookup, NULL);
index 063cb94b934de4ede84ade62cb09609c5e3ada78..b7384241fb03ac836e08a74bab3cac4aae8c8881 100644 (file)
@@ -308,7 +308,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
        &exynos4_device_spdif,
-       &samsung_asoc_dma,
        &samsung_asoc_idma,
        &s5p_device_fimd0,
        &smdkv310_device_audio,
index 8df6ec547f78fcaa4234c8a08c0fe4a32187414f..b9b539cac81e12869523ceb6c8e5e0817f6092a0 100644 (file)
@@ -62,6 +62,10 @@ static struct sleep_save exynos4_vpll_save[] = {
        SAVE_ITEM(EXYNOS4_VPLL_CON1),
 };
 
+static struct sleep_save exynos5_sys_save[] = {
+       SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
+};
+
 static struct sleep_save exynos_core_save[] = {
        /* SROM side */
        SAVE_ITEM(S5P_SROM_BW),
@@ -101,6 +105,7 @@ static void exynos_pm_prepare(void)
                s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
                s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
        } else {
+               s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
                /* Disable USE_RETENTION of JPEG_MEM_OPTION */
                tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
                tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
@@ -304,6 +309,10 @@ static void exynos_pm_resume(void)
        __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
        __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
 
+       if (soc_is_exynos5250())
+               s3c_pm_do_restore(exynos5_sys_save,
+                       ARRAY_SIZE(exynos5_sys_save));
+
        s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
        if (!soc_is_exynos5250()) {
index 503d7dd944ffcbacf0548c4ef093eae1d688a8ba..f91cdff5a3e469a6ddce7f072a0e74084af07fa4 100644 (file)
@@ -51,6 +51,8 @@ config ARCH_KIRKWOOD_DT
        select POWER_RESET_GPIO
        select REGULATOR
        select REGULATOR_FIXED_VOLTAGE
+       select MVEBU_CLK_CORE
+       select MVEBU_CLK_GATING
        select USE_OF
        help
          Say 'Y' here if you want your kernel to support the
index 375f7d88551c00989d6eb2e68b687ec816fa6bb1..ff4150a2ad05259383d147626fbae49648e1a256 100644 (file)
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/mvebu.h>
 #include <linux/kexec.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/bridge-regs.h>
+#include <linux/platform_data/usb-ehci-orion.h>
 #include <plat/irq.h>
+#include <plat/common.h>
 #include "common.h"
 
 static struct of_device_id kirkwood_dt_match_table[] __initdata = {
@@ -26,18 +30,50 @@ static struct of_device_id kirkwood_dt_match_table[] __initdata = {
        { }
 };
 
-static struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = {
-       OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
-       OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
-                      NULL),
-       OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011100, "mv64xxx_i2c.1",
-                      NULL),
-       OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
-       OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL),
-       OF_DEV_AUXDATA("marvell,orion-nand", 0xf4000000, "orion_nand", NULL),
-       OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1030000, "mv_crypto", NULL),
-       {},
-};
+/*
+ * There are still devices that doesn't know about DT yet.  Get clock
+ * gates here and add a clock lookup alias, so that old platform
+ * devices still work.
+*/
+
+static void __init kirkwood_legacy_clk_init(void)
+{
+
+       struct device_node *np = of_find_compatible_node(
+               NULL, NULL, "marvell,kirkwood-gating-clock");
+
+       struct of_phandle_args clkspec;
+
+       clkspec.np = np;
+       clkspec.args_count = 1;
+
+       clkspec.args[0] = CGC_BIT_GE0;
+       orion_clkdev_add(NULL, "mv643xx_eth_port.0",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CGC_BIT_PEX0;
+       orion_clkdev_add("0", "pcie",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CGC_BIT_USB0;
+       orion_clkdev_add(NULL, "orion-ehci.0",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CGC_BIT_PEX1;
+       orion_clkdev_add("1", "pcie",
+                        of_clk_get_from_provider(&clkspec));
+
+       clkspec.args[0] = CGC_BIT_GE1;
+       orion_clkdev_add(NULL, "mv643xx_eth_port.1",
+                        of_clk_get_from_provider(&clkspec));
+
+}
+
+static void __init kirkwood_of_clk_init(void)
+{
+       mvebu_clocks_init();
+       kirkwood_legacy_clk_init();
+}
 
 static void __init kirkwood_dt_init(void)
 {
@@ -56,11 +92,7 @@ static void __init kirkwood_dt_init(void)
        kirkwood_l2_init();
 
        /* Setup root of clk tree */
-       kirkwood_clk_init();
-
-       /* internal devices that every board has */
-       kirkwood_xor0_init();
-       kirkwood_xor1_init();
+       kirkwood_of_clk_init();
 
 #ifdef CONFIG_KEXEC
        kexec_reinit = kirkwood_enable_pcie;
@@ -115,8 +147,7 @@ static void __init kirkwood_dt_init(void)
        if (of_machine_is_compatible("zyxel,nsa310"))
                nsa310_init();
 
-       of_platform_populate(NULL, kirkwood_dt_match_table,
-                            kirkwood_auxdata_lookup, NULL);
+       of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL);
 }
 
 static const char * const kirkwood_dt_board_compat[] = {
index 5303be62b3116618367908b1c86ed44a5247526f..bac21a554c91b90d9edf4dc14533f6ebc4450c52 100644 (file)
@@ -260,8 +260,8 @@ void __init kirkwood_clk_init(void)
        orion_clkdev_add(NULL, "orion_nand", runit);
        orion_clkdev_add(NULL, "mvsdio", sdio);
        orion_clkdev_add(NULL, "mv_crypto", crypto);
-       orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".0", xor0);
-       orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".1", xor1);
+       orion_clkdev_add(NULL, MV_XOR_NAME ".0", xor0);
+       orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
        orion_clkdev_add("0", "pcie", pex0);
        orion_clkdev_add("1", "pcie", pex1);
        orion_clkdev_add(NULL, "kirkwood-i2s", audio);
index 416d46ef7ebd3f3a477225327a708e5dd339a126..440b13ef1fedeecffd308f448dad7ae27cb8d4d7 100644 (file)
@@ -9,6 +9,10 @@ config ARCH_MVEBU
        select PINCTRL
        select PLAT_ORION
        select SPARSE_IRQ
+       select CLKDEV_LOOKUP
+       select MVEBU_CLK_CORE
+       select MVEBU_CLK_CPU
+       select MVEBU_CLK_GATING
 
 if ARCH_MVEBU
 
@@ -17,7 +21,9 @@ menu "Marvell SOC with device tree"
 config MACH_ARMADA_370_XP
        bool
        select ARMADA_370_XP_TIMER
-       select CPU_V7
+       select HAVE_SMP
+       select CACHE_L2X0
+       select CPU_PJ4B
 
 config MACH_ARMADA_370
        bool "Marvell Armada 370 boards"
index 57f996b6aa0e36a3beb0481d39973e25d927aa54..5dcb369b58aa0c79e55159f9affbd8b0c2a105d2 100644 (file)
@@ -2,4 +2,6 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
        -I$(srctree)/arch/arm/plat-orion/include
 
 obj-y += system-controller.o
-obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o
+obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
+obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)        += hotplug.o
index fe454a4430be853678b1661af6840019b2dc14c0..ab9b3bd4fef5547c9d7bb2b296c83d8a74221be5 100644 (file)
@@ -78,7 +78,7 @@ armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
        if (win < 8)
                offset = (win << 4);
        else
-               offset = ARMADA_WINDOW_8_PLUS_OFFSET + (win << 3);
+               offset = ARMADA_WINDOW_8_PLUS_OFFSET + ((win - 8) << 3);
 
        return cfg->bridge_virt_base + offset;
 }
@@ -108,6 +108,9 @@ static int __init armada_setup_cpu_mbus(void)
 
        addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base;
 
+       if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
+               addr_map_cfg.hw_io_coherency = 1;
+
        /*
         * Disable, clear and configure windows.
         */
index 49d791548ad60c026c324cffc753a90b1f73844b..7434b5e361979a9f4170e6224fc4873a5636afd8 100644 (file)
 #include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/time-armada-370-xp.h>
+#include <linux/clk/mvebu.h>
+#include <linux/dma-mapping.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include "armada-370-xp.h"
 #include "common.h"
+#include "coherency.h"
 
 static struct map_desc armada_370_xp_io_desc[] __initdata = {
        {
@@ -37,27 +40,45 @@ void __init armada_370_xp_map_io(void)
        iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
 }
 
+void __init armada_370_xp_timer_and_clk_init(void)
+{
+       mvebu_clocks_init();
+       armada_370_xp_timer_init();
+}
+
+void __init armada_370_xp_init_early(void)
+{
+       /*
+        * Some Armada 370/XP devices allocate their coherent buffers
+        * from atomic context. Increase size of atomic coherent pool
+        * to make sure such the allocations won't fail.
+        */
+       init_dma_coherent_pool_size(SZ_1M);
+}
+
 struct sys_timer armada_370_xp_timer = {
-       .init           = armada_370_xp_timer_init,
+       .init           = armada_370_xp_timer_and_clk_init,
 };
 
 static void __init armada_370_xp_dt_init(void)
 {
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       coherency_init();
 }
 
-static const char * const armada_370_xp_dt_board_dt_compat[] = {
-       "marvell,a370-db",
-       "marvell,axp-db",
+static const char * const armada_370_xp_dt_compat[] = {
+       "marvell,armada-370-xp",
        NULL,
 };
 
-DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)")
+DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)")
+       .smp            = smp_ops(armada_xp_smp_ops),
        .init_machine   = armada_370_xp_dt_init,
        .map_io         = armada_370_xp_map_io,
+       .init_early     = armada_370_xp_init_early,
        .init_irq       = armada_370_xp_init_irq,
        .handle_irq     = armada_370_xp_handle_irq,
        .timer          = &armada_370_xp_timer,
        .restart        = mvebu_restart,
-       .dt_compat      = armada_370_xp_dt_board_dt_compat,
+       .dt_compat      = armada_370_xp_dt_compat,
 MACHINE_END
index aac9bebc6b03da7f865381f1efa335a4c31532b2..c6a7d74fddfec24f719ade3fdd1a1ce649742cec 100644 (file)
 #define ARMADA_370_XP_REGS_VIRT_BASE   IOMEM(0xfeb00000)
 #define ARMADA_370_XP_REGS_SIZE                SZ_1M
 
+#ifdef CONFIG_SMP
+#include <linux/cpumask.h>
+
+void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq);
+void armada_xp_mpic_smp_cpu_init(void);
+#endif
+
 #endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
new file mode 100644 (file)
index 0000000..8278960
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Coherency fabric (Aurora) support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory Clement <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The Armada 370 and Armada XP SOCs have a coherency fabric which is
+ * responsible for ensuring hardware coherency between all CPUs and between
+ * CPUs and I/O masters. This file initializes the coherency fabric and
+ * supplies basic routines for configuring and controlling hardware coherency
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <asm/smp_plat.h>
+#include "armada-370-xp.h"
+
+/*
+ * Some functions in this file are called very early during SMP
+ * initialization. At that time the device tree framework is not yet
+ * ready, and it is not possible to get the register address to
+ * ioremap it. That's why the pointer below is given with an initial
+ * value matching its virtual mapping
+ */
+static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200;
+static void __iomem *coherency_cpu_base;
+
+/* Coherency fabric registers */
+#define COHERENCY_FABRIC_CFG_OFFSET               0x4
+
+#define IO_SYNC_BARRIER_CTL_OFFSET                0x0
+
+static struct of_device_id of_coherency_table[] = {
+       {.compatible = "marvell,coherency-fabric"},
+       { /* end of list */ },
+};
+
+#ifdef CONFIG_SMP
+int coherency_get_cpu_count(void)
+{
+       int reg, cnt;
+
+       reg = readl(coherency_base + COHERENCY_FABRIC_CFG_OFFSET);
+       cnt = (reg & 0xF) + 1;
+
+       return cnt;
+}
+#endif
+
+/* Function defined in coherency_ll.S */
+int ll_set_cpu_coherent(void __iomem *base_addr, unsigned int hw_cpu_id);
+
+int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
+{
+       if (!coherency_base) {
+               pr_warn("Can't make CPU %d cache coherent.\n", hw_cpu_id);
+               pr_warn("Coherency fabric is not initialized\n");
+               return 1;
+       }
+
+       return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
+}
+
+static inline void mvebu_hwcc_sync_io_barrier(void)
+{
+       writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
+       while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
+}
+
+static dma_addr_t mvebu_hwcc_dma_map_page(struct device *dev, struct page *page,
+                                 unsigned long offset, size_t size,
+                                 enum dma_data_direction dir,
+                                 struct dma_attrs *attrs)
+{
+       if (dir != DMA_TO_DEVICE)
+               mvebu_hwcc_sync_io_barrier();
+       return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
+
+static void mvebu_hwcc_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
+                             size_t size, enum dma_data_direction dir,
+                             struct dma_attrs *attrs)
+{
+       if (dir != DMA_TO_DEVICE)
+               mvebu_hwcc_sync_io_barrier();
+}
+
+static void mvebu_hwcc_dma_sync(struct device *dev, dma_addr_t dma_handle,
+                       size_t size, enum dma_data_direction dir)
+{
+       if (dir != DMA_TO_DEVICE)
+               mvebu_hwcc_sync_io_barrier();
+}
+
+static struct dma_map_ops mvebu_hwcc_dma_ops = {
+       .alloc                  = arm_dma_alloc,
+       .free                   = arm_dma_free,
+       .mmap                   = arm_dma_mmap,
+       .map_page               = mvebu_hwcc_dma_map_page,
+       .unmap_page             = mvebu_hwcc_dma_unmap_page,
+       .get_sgtable            = arm_dma_get_sgtable,
+       .map_sg                 = arm_dma_map_sg,
+       .unmap_sg               = arm_dma_unmap_sg,
+       .sync_single_for_cpu    = mvebu_hwcc_dma_sync,
+       .sync_single_for_device = mvebu_hwcc_dma_sync,
+       .sync_sg_for_cpu        = arm_dma_sync_sg_for_cpu,
+       .sync_sg_for_device     = arm_dma_sync_sg_for_device,
+       .set_dma_mask           = arm_dma_set_mask,
+};
+
+static int mvebu_hwcc_platform_notifier(struct notifier_block *nb,
+                                      unsigned long event, void *__dev)
+{
+       struct device *dev = __dev;
+
+       if (event != BUS_NOTIFY_ADD_DEVICE)
+               return NOTIFY_DONE;
+       set_dma_ops(dev, &mvebu_hwcc_dma_ops);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block mvebu_hwcc_platform_nb = {
+       .notifier_call = mvebu_hwcc_platform_notifier,
+};
+
+int __init coherency_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, of_coherency_table);
+       if (np) {
+               pr_info("Initializing Coherency fabric\n");
+               coherency_base = of_iomap(np, 0);
+               coherency_cpu_base = of_iomap(np, 1);
+               set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+               bus_register_notifier(&platform_bus_type,
+                                       &mvebu_hwcc_platform_nb);
+       }
+
+       return 0;
+}
diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h
new file mode 100644 (file)
index 0000000..2f42813
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-mvebu/include/mach/coherency.h
+ *
+ *
+ * Coherency fabric (Aurora) support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_370_XP_COHERENCY_H
+#define __MACH_370_XP_COHERENCY_H
+
+#ifdef CONFIG_SMP
+int coherency_get_cpu_count(void);
+#endif
+
+int set_cpu_coherent(int cpu_id, int smp_group_id);
+int coherency_init(void);
+
+#endif /* __MACH_370_XP_COHERENCY_H */
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S
new file mode 100644 (file)
index 0000000..53e8391
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Coherency fabric: low level functions
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This file implements the assembly function to add a CPU to the
+ * coherency fabric. This function is called by each of the secondary
+ * CPUs during their early boot in an SMP kernel, this why this
+ * function have to callable from assembly. It can also be called by a
+ * primary CPU from C code during its boot.
+ */
+
+#include <linux/linkage.h>
+#define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
+#define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
+
+       .text
+/*
+ * r0: Coherency fabric base register address
+ * r1: HW CPU id
+ */
+ENTRY(ll_set_cpu_coherent)
+       /* Create bit by cpu index */
+       mov     r3, #(1 << 24)
+       lsl     r1, r3, r1
+
+       /* Add CPU to SMP group - Atomic */
+       add     r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET
+       ldr     r2, [r3]
+       orr     r2, r2, r1
+       str     r2, [r3]
+
+       /* Enable coherency on CPU - Atomic */
+       add     r3, r0, #ARMADA_XP_CFB_CFG_REG_OFFSET
+       ldr     r2, [r3]
+       orr     r2, r2, r1
+       str     r2, [r3]
+
+       dsb
+
+       mov     r0, #0
+       mov     pc, lr
+ENDPROC(ll_set_cpu_coherent)
index 02f89eaa25fe02eb2115def89c47ac5bf042b5f3..aa27bc2ffb6013575ff8d889b919a9b9b5369cb8 100644 (file)
@@ -20,4 +20,9 @@ void mvebu_restart(char mode, const char *cmd);
 void armada_370_xp_init_irq(void);
 void armada_370_xp_handle_irq(struct pt_regs *regs);
 
+void armada_xp_cpu_die(unsigned int cpu);
+int armada_370_xp_coherency_init(void);
+int armada_370_xp_pmsu_init(void);
+void armada_xp_secondary_startup(void);
+extern struct smp_operations armada_xp_smp_ops;
 #endif
diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S
new file mode 100644 (file)
index 0000000..a06e0ed
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SMP support: Entry point for secondary CPUs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This file implements the assembly entry point for secondary CPUs in
+ * an SMP kernel. The only thing we need to do is to add the CPU to
+ * the coherency fabric by writing to 2 registers. Currently the base
+ * register addresses are hard coded due to the early initialisation
+ * problems.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+/*
+ * At this stage the secondary CPUs don't have acces yet to the MMU, so
+ * we have to provide physical addresses
+ */
+#define ARMADA_XP_CFB_BASE          0xD0020200
+
+       __CPUINIT
+
+/*
+ * Armada XP specific entry point for secondary CPUs.
+ * We add the CPU to the coherency fabric and then jump to secondary
+ * startup
+ */
+ENTRY(armada_xp_secondary_startup)
+
+       /* Read CPU id */
+       mrc     p15, 0, r1, c0, c0, 5
+       and     r1, r1, #0xF
+
+       /* Add CPU to coherency fabric */
+       ldr     r0, =ARMADA_XP_CFB_BASE
+
+       bl      ll_set_cpu_coherent
+       b       secondary_startup
+
+ENDPROC(armada_xp_secondary_startup)
diff --git a/arch/arm/mach-mvebu/hotplug.c b/arch/arm/mach-mvebu/hotplug.c
new file mode 100644 (file)
index 0000000..b228b6a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Symmetric Multi Processing (SMP) support for Armada XP
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <asm/proc-fns.h>
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void __ref armada_xp_cpu_die(unsigned int cpu)
+{
+       cpu_do_idle();
+
+       /* We should never return from idle */
+       panic("mvebu: cpu %d unexpectedly exit from shutdown\n", cpu);
+}
index 5f5f9394b6b2fed42f014d3848d0d8a0d0163877..8e3fb082c3c6e350232d3e91ffc8c4dc9c805643 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/irqdomain.h>
 #include <asm/mach/arch.h>
 #include <asm/exception.h>
+#include <asm/smp_plat.h>
+#include <asm/hardware/cache-l2x0.h>
 
 /* Interrupt Controller Registers Map */
 #define ARMADA_370_XP_INT_SET_MASK_OFFS                (0x48)
 
 #define ARMADA_370_XP_CPU_INTACK_OFFS          (0x44)
 
+#define ARMADA_370_XP_SW_TRIG_INT_OFFS           (0x4)
+#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS          (0xc)
+#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS        (0x8)
+
+#define ACTIVE_DOORBELLS                       (8)
+
 static void __iomem *per_cpu_int_base;
 static void __iomem *main_int_base;
 static struct irq_domain *armada_370_xp_mpic_domain;
@@ -51,11 +59,22 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
               per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
 }
 
+#ifdef CONFIG_SMP
+static int armada_xp_set_affinity(struct irq_data *d,
+                                 const struct cpumask *mask_val, bool force)
+{
+       return 0;
+}
+#endif
+
 static struct irq_chip armada_370_xp_irq_chip = {
        .name           = "armada_370_xp_irq",
        .irq_mask       = armada_370_xp_irq_mask,
        .irq_mask_ack   = armada_370_xp_irq_mask,
        .irq_unmask     = armada_370_xp_irq_unmask,
+#ifdef CONFIG_SMP
+       .irq_set_affinity = armada_xp_set_affinity,
+#endif
 };
 
 static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
@@ -72,6 +91,41 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
        return 0;
 }
 
+#ifdef CONFIG_SMP
+void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq)
+{
+       int cpu;
+       unsigned long map = 0;
+
+       /* Convert our logical CPU mask into a physical one. */
+       for_each_cpu(cpu, mask)
+               map |= 1 << cpu_logical_map(cpu);
+
+       /*
+        * Ensure that stores to Normal memory are visible to the
+        * other CPUs before issuing the IPI.
+        */
+       dsb();
+
+       /* submit softirq */
+       writel((map << 8) | irq, main_int_base +
+               ARMADA_370_XP_SW_TRIG_INT_OFFS);
+}
+
+void armada_xp_mpic_smp_cpu_init(void)
+{
+       /* Clear pending IPIs */
+       writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+       /* Enable first 8 IPIs */
+       writel((1 << ACTIVE_DOORBELLS) - 1, per_cpu_int_base +
+               ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+
+       /* Unmask IPI interrupt */
+       writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+}
+#endif /* CONFIG_SMP */
+
 static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
        .map = armada_370_xp_mpic_irq_map,
        .xlate = irq_domain_xlate_onecell,
@@ -91,13 +145,18 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
        control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
 
        armada_370_xp_mpic_domain =
-           irq_domain_add_linear(node, (control >> 2) & 0x3ff,
-                                 &armada_370_xp_mpic_irq_ops, NULL);
+               irq_domain_add_linear(node, (control >> 2) & 0x3ff,
+                               &armada_370_xp_mpic_irq_ops, NULL);
 
        if (!armada_370_xp_mpic_domain)
                panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
 
        irq_set_default_host(armada_370_xp_mpic_domain);
+
+#ifdef CONFIG_SMP
+       armada_xp_mpic_smp_cpu_init();
+#endif
+
        return 0;
 }
 
@@ -111,14 +170,36 @@ asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs
                                        ARMADA_370_XP_CPU_INTACK_OFFS);
                irqnr = irqstat & 0x3FF;
 
-               if (irqnr < 1023) {
-                       irqnr =
-                           irq_find_mapping(armada_370_xp_mpic_domain, irqnr);
+               if (irqnr > 1022)
+                       break;
+
+               if (irqnr >= 8) {
+                       irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
+                                       irqnr);
                        handle_IRQ(irqnr, regs);
                        continue;
                }
+#ifdef CONFIG_SMP
+               /* IPI Handling */
+               if (irqnr == 0) {
+                       u32 ipimask, ipinr;
+
+                       ipimask = readl_relaxed(per_cpu_int_base +
+                                               ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
+                               & 0xFF;
+
+                       writel(0x0, per_cpu_int_base +
+                               ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+                       /* Handle all pending doorbells */
+                       for (ipinr = 0; ipinr < ACTIVE_DOORBELLS; ipinr++) {
+                               if (ipimask & (0x1 << ipinr))
+                                       handle_IPI(ipinr, regs);
+                       }
+                       continue;
+               }
+#endif
 
-               break;
        } while (1);
 }
 
@@ -130,4 +211,7 @@ static const struct of_device_id mpic_of_match[] __initconst = {
 void __init armada_370_xp_init_irq(void)
 {
        of_irq_init(mpic_of_match);
+#ifdef CONFIG_CACHE_L2X0
+       l2x0_of_init(0, ~0UL);
+#endif
 }
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
new file mode 100644 (file)
index 0000000..fe16aaf
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Symmetric Multi Processing (SMP) support for Armada XP
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The Armada XP SoC has 4 ARMv7 PJ4B CPUs running in full HW coherency
+ * This file implements the routines for preparing the SMP infrastructure
+ * and waking up the secondary CPUs
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include "common.h"
+#include "armada-370-xp.h"
+#include "pmsu.h"
+#include "coherency.h"
+
+void __init set_secondary_cpus_clock(void)
+{
+       int thiscpu;
+       unsigned long rate;
+       struct clk *cpu_clk = NULL;
+       struct device_node *np = NULL;
+
+       thiscpu = smp_processor_id();
+       for_each_node_by_type(np, "cpu") {
+               int err;
+               int cpu;
+
+               err = of_property_read_u32(np, "reg", &cpu);
+               if (WARN_ON(err))
+                       return;
+
+               if (cpu == thiscpu) {
+                       cpu_clk = of_clk_get(np, 0);
+                       break;
+               }
+       }
+       if (WARN_ON(IS_ERR(cpu_clk)))
+               return;
+       clk_prepare_enable(cpu_clk);
+       rate = clk_get_rate(cpu_clk);
+
+       /* set all the other CPU clk to the same rate than the boot CPU */
+       for_each_node_by_type(np, "cpu") {
+               int err;
+               int cpu;
+
+               err = of_property_read_u32(np, "reg", &cpu);
+               if (WARN_ON(err))
+                       return;
+
+               if (cpu != thiscpu) {
+                       cpu_clk = of_clk_get(np, 0);
+                       clk_set_rate(cpu_clk, rate);
+               }
+       }
+}
+
+static void __cpuinit armada_xp_secondary_init(unsigned int cpu)
+{
+       armada_xp_mpic_smp_cpu_init();
+}
+
+static int __cpuinit armada_xp_boot_secondary(unsigned int cpu,
+                                             struct task_struct *idle)
+{
+       pr_info("Booting CPU %d\n", cpu);
+
+       armada_xp_boot_cpu(cpu, armada_xp_secondary_startup);
+
+       return 0;
+}
+
+static void __init armada_xp_smp_init_cpus(void)
+{
+       unsigned int i, ncores;
+       ncores = coherency_get_cpu_count();
+
+       /* Limit possible CPUs to defconfig */
+       if (ncores > nr_cpu_ids) {
+               pr_warn("SMP: %d CPUs physically present. Only %d configured.",
+                       ncores, nr_cpu_ids);
+               pr_warn("Clipping CPU count to %d\n", nr_cpu_ids);
+               ncores = nr_cpu_ids;
+       }
+
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+
+       set_smp_cross_call(armada_mpic_send_doorbell);
+}
+
+void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
+{
+       set_secondary_cpus_clock();
+       flush_cache_all();
+       set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+}
+
+struct smp_operations armada_xp_smp_ops __initdata = {
+       .smp_init_cpus          = armada_xp_smp_init_cpus,
+       .smp_prepare_cpus       = armada_xp_smp_prepare_cpus,
+       .smp_secondary_init     = armada_xp_secondary_init,
+       .smp_boot_secondary     = armada_xp_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die                = armada_xp_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
new file mode 100644 (file)
index 0000000..3cc4bef
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Power Management Service Unit(PMSU) support for Armada 370/XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory Clement <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The Armada 370 and Armada XP SOCs have a power management service
+ * unit which is responsible for powering down and waking up CPUs and
+ * other SOC units
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+#include <asm/smp_plat.h>
+
+static void __iomem *pmsu_mp_base;
+static void __iomem *pmsu_reset_base;
+
+#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu)    ((cpu * 0x100) + 0x24)
+#define PMSU_RESET_CTL_OFFSET(cpu)             (cpu * 0x8)
+
+static struct of_device_id of_pmsu_table[] = {
+       {.compatible = "marvell,armada-370-xp-pmsu"},
+       { /* end of list */ },
+};
+
+#ifdef CONFIG_SMP
+int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr)
+{
+       int reg, hw_cpu;
+
+       if (!pmsu_mp_base || !pmsu_reset_base) {
+               pr_warn("Can't boot CPU. PMSU is uninitialized\n");
+               return 1;
+       }
+
+       hw_cpu = cpu_logical_map(cpu_id);
+
+       writel(virt_to_phys(boot_addr), pmsu_mp_base +
+                       PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
+
+       /* Release CPU from reset by clearing reset bit*/
+       reg = readl(pmsu_reset_base + PMSU_RESET_CTL_OFFSET(hw_cpu));
+       reg &= (~0x1);
+       writel(reg, pmsu_reset_base + PMSU_RESET_CTL_OFFSET(hw_cpu));
+
+       return 0;
+}
+#endif
+
+int __init armada_370_xp_pmsu_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, of_pmsu_table);
+       if (np) {
+               pr_info("Initializing Power Management Service Unit\n");
+               pmsu_mp_base = of_iomap(np, 0);
+               pmsu_reset_base = of_iomap(np, 1);
+       }
+
+       return 0;
+}
+
+early_initcall(armada_370_xp_pmsu_init);
diff --git a/arch/arm/mach-mvebu/pmsu.h b/arch/arm/mach-mvebu/pmsu.h
new file mode 100644 (file)
index 0000000..07a737c
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Power Management Service Unit (PMSU) support for Armada 370/XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_MVEBU_PMSU_H
+#define __MACH_MVEBU_PMSU_H
+
+int armada_xp_boot_cpu(unsigned int cpu_id, void *phys_addr);
+
+#endif /* __MACH_370_XP_PMSU_H */
index e4cfb7e5361d2fa25978502fbab1ac296208d61e..f1c972d87bacc164b297b6e7f8088818a09aa168 100644 (file)
@@ -136,7 +136,7 @@ int xc_request_firmware(struct xc *x)
        if (head->magic != 0x4e657458) {
                if (head->magic == 0x5874654e) {
                        dev_err(x->dev,
-                           "firmware magic is 'XteN'. Endianess problems?\n");
+                           "firmware magic is 'XteN'. Endianness problems?\n");
                        ret = -ENODEV;
                        goto exit_release_firmware;
                }
index c22e111bcd00e2b17205bd5e764d46db6513ab2c..46f4fc982766e638b920c456114b58d94eab7888 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <asm/mach-types.h>
 #include <video/omapdss.h>
-#include <plat/vram.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include "board-rx51.h"
@@ -87,17 +86,4 @@ static int __init rx51_video_init(void)
 }
 
 subsys_initcall(rx51_video_init);
-
-void __init rx51_video_mem_init(void)
-{
-       /*
-        * GFX 864x480x32bpp
-        * VID1/2 1280x720x32bpp double buffered
-        */
-       omap_vram_set_sdram_vram(PAGE_ALIGN(864 * 480 * 4) +
-                       2 * PAGE_ALIGN(1280 * 720 * 4 * 2), 0);
-}
-
-#else
-void __init rx51_video_mem_init(void) { }
 #endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */
index f1d6efe079ca27476a21302faa09049d20e7430e..d0374ea2dfb0ef21288c0a47a27dc1e9fc17ce2e 100644 (file)
@@ -34,8 +34,6 @@
 
 #define RX51_GPIO_SLEEP_IND 162
 
-extern void rx51_video_mem_init(void);
-
 static struct gpio_led gpio_leds[] = {
        {
                .name   = "sleep_ind",
@@ -112,7 +110,6 @@ static void __init rx51_init(void)
 
 static void __init rx51_reserve(void)
 {
-       rx51_video_mem_init();
        omap_reserve();
 }
 
index 5c2fd4863b2bc7f32b4289cc1fb0059d5fec82e2..2dabb9ecb986adc2abcbc851f54ecd5c4875adf9 100644 (file)
@@ -16,8 +16,6 @@
 #include <linux/init.h>
 #include <linux/platform_data/dsp-omap.h>
 
-#include <plat/vram.h>
-
 #include "common.h"
 #include "omap-secure.h"
 
@@ -32,7 +30,6 @@ int __weak omap_secure_ram_reserve_memblock(void)
 
 void __init omap_reserve(void)
 {
-       omap_vram_reserve_sdram_memblock();
        omap_dsp_reserve_sdram_memblock();
        omap_secure_ram_reserve_memblock();
        omap_barrier_reserve_memblock();
index c67a731cfbb708f9e36d5d8f843d3ffb6119fb31..4abb8b5e9bc09f8b514a3ad2958ef8a8dead7041 100644 (file)
@@ -202,6 +202,16 @@ static struct resource omap3isp_resources[] = {
                .end            = OMAP3630_ISP_CSI2C_REGS2_END,
                .flags          = IORESOURCE_MEM,
        },
+       {
+               .start          = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE,
+               .end            = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE + 3,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL,
+               .end            = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL + 3,
+               .flags          = IORESOURCE_MEM,
+       },
        {
                .start          = 24 + OMAP_INTC_START,
                .flags          = IORESOURCE_IRQ,
index 38ba58c97628efd6a99d61377eeff545d09e9cc4..cc75aaf6e7642396947a9dac47c12115edc45fae 100644 (file)
@@ -102,17 +102,20 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
-static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
+static void __init omap4_tpd12s015_mux_pads(void)
 {
-       u32 reg;
-       u16 control_i2c_1;
-
        omap_mux_init_signal("hdmi_cec",
                        OMAP_PIN_INPUT_PULLUP);
        omap_mux_init_signal("hdmi_ddc_scl",
                        OMAP_PIN_INPUT_PULLUP);
        omap_mux_init_signal("hdmi_ddc_sda",
                        OMAP_PIN_INPUT_PULLUP);
+}
+
+static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
+{
+       u32 reg;
+       u16 control_i2c_1;
 
        /*
         * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
@@ -163,8 +166,10 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 
 int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
-       if (cpu_is_omap44xx())
+       if (cpu_is_omap44xx()) {
                omap4_hdmi_mux_pads(flags);
+               omap4_tpd12s015_mux_pads();
+       }
 
        return 0;
 }
index 113c57a035653aeb5215b1fcfefff7e12450e427..fb7f1d1627dc1d11863ae4bcaeeabb0bccda4524 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/pwm_backlight.h>
 
+#include <media/mt9v022.h>
 #include <media/soc_camera.h>
 
 #include <linux/platform_data/camera-pxa.h>
@@ -468,6 +469,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
        },
 };
 
+static struct mt9v022_platform_data mt9v022_pdata = {
+       .y_skip_top = 1,
+};
+
 static struct i2c_board_info pcm990_camera_i2c[] = {
        {
                I2C_BOARD_INFO("mt9v022", 0x48),
@@ -480,6 +485,7 @@ static struct soc_camera_link iclink[] = {
        {
                .bus_id                 = 0, /* Must match with the camera ID */
                .board_info             = &pcm990_camera_i2c[0],
+               .priv                   = &mt9v022_pdata,
                .i2c_adapter_id         = 0,
                .query_bus_param        = pcm990_camera_query_bus_param,
                .set_bus_param          = pcm990_camera_set_bus_param,
index 6e7dc9d0cf0ebee796a953acca878822b245dff3..eecea2a50f8f893bf79ec5f4727e005dfbd19158 100644 (file)
@@ -74,7 +74,7 @@
 
 
 /* 0xE0000000 contains the IO space that is split by speed and
- * wether the access is for 8 or 16bit IO... this ensures that
+ * whether the access is for 8 or 16bit IO... this ensures that
  * the correct access is made
  *
  * 0x10000000 of space, partitioned as so:
index ee99fd56c0439f5bdc22152fa2c530282424fd70..6b72d5a4b377981eca1944ecd1f07a0d51871bd4 100644 (file)
@@ -88,7 +88,7 @@ enum s3c2410_dma_state {
  *
  * This represents the state of the DMA engine, wrt to the loaded / running
  * transfers. Since we don't have any way of knowing exactly the state of
- * the DMA transfers, we need to know the state to make decisions on wether
+ * the DMA transfers, we need to know the state to make decisions on whether
  * we can
  *
  * S3C2410_DMA_NONE
index 99612fcc4eb20e3c1b822b48b7b407cbf2542029..28376e56dd3bd3ba30924e71569f739e19786534 100644 (file)
@@ -51,7 +51,7 @@
 #define VR1000_VA_PC104_IRQMASK VR1000_IOADDR(0x00600000)
 
 /* 0xE0000000 contains the IO space that is split by speed and
- * wether the access is for 8 or 16bit IO... this ensures that
+ * whether the access is for 8 or 16bit IO... this ensures that
  * the correct access is made
  *
  * 0x10000000 of space, partitioned as so:
index 4a963467b7eeb46b272d13dde73ea652473961d9..973b87ca87f4a065fd212090ab67eb68fbfe5b73 100644 (file)
@@ -521,7 +521,6 @@ static struct platform_device *gta02_devices[] __initdata = {
        &gta02_nor_flash,
        &s3c24xx_pwm_device,
        &s3c_device_iis,
-       &samsung_asoc_dma,
        &s3c_device_i2c0,
        &gta02_dfbmcs320_device,
        &gta02_buttons_device,
index 63aaf076f61198cb6cdad6e69a93c443b46eaa5a..b23dd1b106e8a6d132578097aba863d48750a18c 100644 (file)
@@ -632,7 +632,6 @@ static struct platform_device *h1940_devices[] __initdata = {
        &s3c_device_wdt,
        &s3c_device_i2c0,
        &s3c_device_iis,
-       &samsung_asoc_dma,
        &s3c_device_usbgadget,
        &h1940_device_leds,
        &h1940_device_bluetooth,
index 393c0f1ac11aa38c5921827b9e6229ec61bcea16..a31d5b83e5f77f9218f19b959ea5ccb0f6d0be39 100644 (file)
@@ -519,7 +519,6 @@ static struct platform_device *mini2440_devices[] __initdata = {
        &s3c_device_iis,
        &uda1340_codec,
        &mini2440_audio,
-       &samsung_asoc_dma,
 };
 
 static void __init mini2440_map_io(void)
index 379fde521d3704cee3817aff65e01b7390f0bf3e..0606f2faaa5c5261eaa916fe374aa21f7bb5da4f 100644 (file)
@@ -712,7 +712,6 @@ static struct platform_device *rx1950_devices[] __initdata = {
        &s3c_device_wdt,
        &s3c_device_i2c0,
        &s3c_device_iis,
-       &samsung_asoc_dma,
        &s3c_device_usbgadget,
        &s3c_device_rtc,
        &s3c_device_nand,
index 60627e63a254671ffcf9bd49d098695ca0d31842..724755f0b0f5b0b9ebfdf00b4bdd7ccb8930cad7 100644 (file)
@@ -121,7 +121,7 @@ void s3c_pm_configure_extint(void)
        int pin;
 
        /* for each of the external interrupts (EINT0..EINT15) we
-        * need to check wether it is an external interrupt source,
+        * need to check whether it is an external interrupt source,
         * and then configure it as an input if it is not
        */
 
index 701f421de1a8c9c44c333590835b366d1fc73f51..cdde249166b5011cb1d075fed3caa212963427d5 100644 (file)
@@ -379,7 +379,6 @@ static struct platform_device *crag6410_devices[] __initdata = {
        &s3c_device_timer[0],
        &s3c64xx_device_iis0,
        &s3c64xx_device_iis1,
-       &samsung_asoc_dma,
        &samsung_device_keypad,
        &crag6410_gpio_keydev,
        &crag6410_dm9k_device,
index da1a771a29e9f1493ce192d35fde34f6fa23ed01..574a9eef588dc4b6fd764449d3893811e27e7c3f 100644 (file)
@@ -275,7 +275,6 @@ static struct platform_device *smdk6410_devices[] __initdata = {
        &s3c_device_fb,
        &s3c_device_ohci,
        &s3c_device_usb_hsotg,
-       &samsung_asoc_dma,
        &s3c64xx_device_iisv4,
        &samsung_device_keypad,
 
index 96ea1fe0ec94a9d3b0393704b9bf63cbd63bf89b..1af823558c60509d571ee0024b9fca2492496ba4 100644 (file)
@@ -165,7 +165,6 @@ static struct platform_device *smdk6440_devices[] __initdata = {
        &s3c_device_i2c1,
        &s3c_device_ts,
        &s3c_device_wdt,
-       &samsung_asoc_dma,
        &s5p6440_device_iis,
        &s3c_device_fb,
        &smdk6440_lcd_lte480wv,
index 12748b6eaa7b8af25e6ab9033a535e61cae98326..62526ccf6b70243be2e6e4c2f5834b7a87f0aedb 100644 (file)
@@ -183,7 +183,6 @@ static struct platform_device *smdk6450_devices[] __initdata = {
        &s3c_device_i2c1,
        &s3c_device_ts,
        &s3c_device_wdt,
-       &samsung_asoc_dma,
        &s5p6450_device_iis0,
        &s3c_device_fb,
        &smdk6450_lcd_lte480wv,
index dba7384a87bde67d48256dd3e0a95cc61735be55..9abe95e806abfe3bd9a85bc6eee3cd964d9d92af 100644 (file)
@@ -197,7 +197,6 @@ static struct platform_device *smdkc100_devices[] __initdata = {
        &s3c_device_ts,
        &s3c_device_wdt,
        &smdkc100_lcd_powerdev,
-       &samsung_asoc_dma,
        &s5pc100_device_iis0,
        &samsung_device_keypad,
        &s5pc100_device_ac97,
index d9c99fcc1aa7fa97e81b1d930e2523457128f836..f1f3bd37ecda7d53db021a9f69d1cc3432b3159f 100644 (file)
@@ -85,7 +85,6 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = {
 };
 
 static struct platform_device *smdkc110_devices[] __initdata = {
-       &samsung_asoc_dma,
        &s5pv210_device_iis0,
        &s5pv210_device_ac97,
        &s5pv210_device_spdif,
index 4cdb5bb7bbcf024613689228d746b914c9140de5..6bc8404bf6784cfee3751eed9e6fdd0f24b18152 100644 (file)
@@ -234,7 +234,6 @@ static struct platform_device *smdkv210_devices[] __initdata = {
        &s5pv210_device_ac97,
        &s5pv210_device_iis0,
        &s5pv210_device_spdif,
-       &samsung_asoc_dma,
        &samsung_asoc_idma,
        &samsung_device_keypad,
        &smdkv210_dm9000,
index 4eddca14ae07db254083d883bc64aeed1b402713..9255546e7bf64fb98fce8bbfb3bb7830ce51f2cd 100644 (file)
@@ -29,6 +29,8 @@ config ARCH_R8A7779
        select ARM_GIC
        select CPU_V7
        select SH_CLK_CPG
+       select USB_ARCH_HAS_EHCI
+       select USB_ARCH_HAS_OHCI
 
 config ARCH_EMEV2
        bool "Emma Mobile EV2"
index 25eb88a923e6097f66af5157d8bd998e9a2e53f1..032d10817e795663c017cc85edf9660f840217e8 100644 (file)
@@ -213,95 +213,6 @@ static struct platform_device irda_device = {
        .num_resources  = ARRAY_SIZE(irda_resources),
 };
 
-static unsigned char lcd_backlight_seq[3][2] = {
-       { 0x04, 0x07 },
-       { 0x23, 0x80 },
-       { 0x03, 0x01 },
-};
-
-static void lcd_backlight_on(void)
-{
-       struct i2c_adapter *a;
-       struct i2c_msg msg;
-       int k;
-
-       a = i2c_get_adapter(1);
-       for (k = 0; a && k < 3; k++) {
-               msg.addr = 0x6d;
-               msg.buf = &lcd_backlight_seq[k][0];
-               msg.len = 2;
-               msg.flags = 0;
-               if (i2c_transfer(a, &msg, 1) != 1)
-                       break;
-       }
-}
-
-static void lcd_backlight_reset(void)
-{
-       gpio_set_value(GPIO_PORT235, 0);
-       mdelay(24);
-       gpio_set_value(GPIO_PORT235, 1);
-}
-
-/* LCDC0 */
-static const struct fb_videomode lcdc0_modes[] = {
-       {
-               .name           = "R63302(QHD)",
-               .xres           = 544,
-               .yres           = 961,
-               .left_margin    = 72,
-               .right_margin   = 600,
-               .hsync_len      = 16,
-               .upper_margin   = 8,
-               .lower_margin   = 8,
-               .vsync_len      = 2,
-               .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-       },
-};
-
-static struct sh_mobile_lcdc_info lcdc0_info = {
-       .clock_source = LCDC_CLK_PERIPHERAL,
-       .ch[0] = {
-               .chan = LCDC_CHAN_MAINLCD,
-               .interface_type = RGB24,
-               .clock_divider = 1,
-               .flags = LCDC_FLAGS_DWPOL,
-               .fourcc = V4L2_PIX_FMT_RGB565,
-               .lcd_modes = lcdc0_modes,
-               .num_modes = ARRAY_SIZE(lcdc0_modes),
-               .panel_cfg = {
-                       .width = 44,
-                       .height = 79,
-                       .display_on = lcd_backlight_on,
-                       .display_off = lcd_backlight_reset,
-               },
-       }
-};
-
-static struct resource lcdc0_resources[] = {
-       [0] = {
-               .name   = "LCDC0",
-               .start  = 0xfe940000, /* P4-only space */
-               .end    = 0xfe943fff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = intcs_evt2irq(0x580),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device lcdc0_device = {
-       .name           = "sh_mobile_lcdc_fb",
-       .num_resources  = ARRAY_SIZE(lcdc0_resources),
-       .resource       = lcdc0_resources,
-       .id             = 0,
-       .dev    = {
-               .platform_data  = &lcdc0_info,
-               .coherent_dma_mask = ~0,
-       },
-};
-
 /* MIPI-DSI */
 static struct resource mipidsi0_resources[] = {
        [0] = {
@@ -358,7 +269,7 @@ sh_mipi_set_dot_clock_pck_err:
 
 static struct sh_mipi_dsi_info mipidsi0_info = {
        .data_format    = MIPI_RGB888,
-       .lcd_chan       = &lcdc0_info.ch[0],
+       .channel        = LCDC_CHAN_MAINLCD,
        .lane           = 2,
        .vsynw_offset   = 20,
        .clksrc         = 1,
@@ -378,6 +289,109 @@ static struct platform_device mipidsi0_device = {
        },
 };
 
+static unsigned char lcd_backlight_seq[3][2] = {
+       { 0x04, 0x07 },
+       { 0x23, 0x80 },
+       { 0x03, 0x01 },
+};
+
+static int lcd_backlight_set_brightness(int brightness)
+{
+       struct i2c_adapter *adap;
+       struct i2c_msg msg;
+       unsigned int i;
+       int ret;
+
+       if (brightness == 0) {
+               /* Reset the chip */
+               gpio_set_value(GPIO_PORT235, 0);
+               mdelay(24);
+               gpio_set_value(GPIO_PORT235, 1);
+               return 0;
+       }
+
+       adap = i2c_get_adapter(1);
+       if (adap == NULL)
+               return -ENODEV;
+
+       for (i = 0; i < ARRAY_SIZE(lcd_backlight_seq); i++) {
+               msg.addr = 0x6d;
+               msg.buf = &lcd_backlight_seq[i][0];
+               msg.len = 2;
+               msg.flags = 0;
+
+               ret = i2c_transfer(adap, &msg, 1);
+               if (ret < 0)
+                       break;
+       }
+
+       i2c_put_adapter(adap);
+       return ret < 0 ? ret : 0;
+}
+
+/* LCDC0 */
+static const struct fb_videomode lcdc0_modes[] = {
+       {
+               .name           = "R63302(QHD)",
+               .xres           = 544,
+               .yres           = 961,
+               .left_margin    = 72,
+               .right_margin   = 600,
+               .hsync_len      = 16,
+               .upper_margin   = 8,
+               .lower_margin   = 8,
+               .vsync_len      = 2,
+               .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+       },
+};
+
+static struct sh_mobile_lcdc_info lcdc0_info = {
+       .clock_source = LCDC_CLK_PERIPHERAL,
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .interface_type = RGB24,
+               .clock_divider = 1,
+               .flags = LCDC_FLAGS_DWPOL,
+               .fourcc = V4L2_PIX_FMT_RGB565,
+               .lcd_modes = lcdc0_modes,
+               .num_modes = ARRAY_SIZE(lcdc0_modes),
+               .panel_cfg = {
+                       .width = 44,
+                       .height = 79,
+               },
+               .bl_info = {
+                       .name = "sh_mobile_lcdc_bl",
+                       .max_brightness = 1,
+                       .set_brightness = lcd_backlight_set_brightness,
+               },
+               .tx_dev = &mipidsi0_device,
+       }
+};
+
+static struct resource lcdc0_resources[] = {
+       [0] = {
+               .name   = "LCDC0",
+               .start  = 0xfe940000, /* P4-only space */
+               .end    = 0xfe943fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = intcs_evt2irq(0x580),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device lcdc0_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(lcdc0_resources),
+       .resource       = lcdc0_resources,
+       .id             = 0,
+       .dev    = {
+               .platform_data  = &lcdc0_info,
+               .coherent_dma_mask = ~0,
+       },
+};
+
 /* Fixed 2.8V regulators to be used by SDHI0 */
 static struct regulator_consumer_supply fixed2v8_power_consumers[] =
 {
@@ -531,8 +545,8 @@ static struct platform_device *ag5evm_devices[] __initdata = {
        &fsi_device,
        &mmc_device,
        &irda_device,
-       &lcdc0_device,
        &mipidsi0_device,
+       &lcdc0_device,
        &sdhi0_device,
        &sdhi1_device,
 };
@@ -621,7 +635,7 @@ static void __init ag5evm_init(void)
        /* LCD backlight controller */
        gpio_request(GPIO_PORT235, NULL); /* RESET */
        gpio_direction_output(GPIO_PORT235, 0);
-       lcd_backlight_reset();
+       lcd_backlight_set_brightness(0);
 
        /* enable SDHI0 on CN15 [SD I/F] */
        gpio_request(GPIO_FN_SDHIWP0, NULL);
index cefdd030361d21fe2120626ccfc1e1f2b726e951..99ef190d0909d5ee5bf633efd0b660061244e71b 100644 (file)
@@ -552,11 +552,9 @@ static struct resource mipidsi0_resources[] = {
        },
 };
 
-static struct sh_mobile_lcdc_info lcdc_info;
-
 static struct sh_mipi_dsi_info mipidsi0_info = {
        .data_format    = MIPI_RGB888,
-       .lcd_chan       = &lcdc_info.ch[0],
+       .channel        = LCDC_CHAN_MAINLCD,
        .lane           = 2,
        .vsynw_offset   = 17,
        .phyctrl        = 0x6 << 8,
@@ -658,133 +656,16 @@ static struct platform_device lcdc_device = {
 
 /* FSI */
 #define IRQ_FSI                evt2irq(0x1840)
-static int __fsi_set_rate(struct clk *clk, long rate, int enable)
-{
-       int ret = 0;
-
-       if (rate <= 0)
-               return ret;
-
-       if (enable) {
-               ret = clk_set_rate(clk, rate);
-               if (0 == ret)
-                       ret = clk_enable(clk);
-       } else {
-               clk_disable(clk);
-       }
-
-       return ret;
-}
-
-static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
-{
-       return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable);
-}
-
-static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable)
-{
-       struct clk *fsia_ick;
-       struct clk *fsiack;
-       int ret = -EIO;
-
-       fsia_ick = clk_get(dev, "icka");
-       if (IS_ERR(fsia_ick))
-               return PTR_ERR(fsia_ick);
-
-       /*
-        * FSIACK is connected to AK4642,
-        * and use external clock pin from it.
-        * it is parent of fsia_ick now.
-        */
-       fsiack = clk_get_parent(fsia_ick);
-       if (!fsiack)
-               goto fsia_ick_out;
-
-       /*
-        * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick
-        *
-        ** FIXME **
-        * Because the freq_table of external clk (fsiack) are all 0,
-        * the return value of clk_round_rate became 0.
-        * So, it use __fsi_set_rate here.
-        */
-       ret = __fsi_set_rate(fsiack, rate, enable);
-       if (ret < 0)
-               goto fsiack_out;
-
-       ret = __fsi_set_round_rate(fsia_ick, rate, enable);
-       if ((ret < 0) && enable)
-               __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */
-
-fsiack_out:
-       clk_put(fsiack);
-
-fsia_ick_out:
-       clk_put(fsia_ick);
-
-       return 0;
-}
-
-static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-{
-       struct clk *fsib_clk;
-       struct clk *fdiv_clk = clk_get(NULL, "fsidivb");
-       long fsib_rate = 0;
-       long fdiv_rate = 0;
-       int ackmd_bpfmd;
-       int ret;
-
-       switch (rate) {
-       case 44100:
-               fsib_rate       = rate * 256;
-               ackmd_bpfmd     = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-               break;
-       case 48000:
-               fsib_rate       = 85428000; /* around 48kHz x 256 x 7 */
-               fdiv_rate       = rate * 256;
-               ackmd_bpfmd     = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-               break;
-       default:
-               pr_err("unsupported rate in FSI2 port B\n");
-               return -EINVAL;
-       }
-
-       /* FSI B setting */
-       fsib_clk = clk_get(dev, "ickb");
-       if (IS_ERR(fsib_clk))
-               return -EIO;
-
-       ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
-       if (ret < 0)
-               goto fsi_set_rate_end;
-
-       /* FSI DIV setting */
-       ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
-       if (ret < 0) {
-               /* disable FSI B */
-               if (enable)
-                       __fsi_set_round_rate(fsib_clk, fsib_rate, 0);
-               goto fsi_set_rate_end;
-       }
-
-       ret = ackmd_bpfmd;
-
-fsi_set_rate_end:
-       clk_put(fsib_clk);
-       return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
        .port_a = {
                .flags          = SH_FSI_BRS_INV,
-               .set_rate       = fsi_ak4642_set_rate,
        },
        .port_b = {
                .flags          = SH_FSI_BRS_INV |
                                  SH_FSI_BRM_INV |
                                  SH_FSI_LRS_INV |
+                                 SH_FSI_CLK_CPG |
                                  SH_FSI_FMT_SPDIF,
-               .set_rate       = fsi_hdmi_set_rate,
        },
 };
 
@@ -1144,25 +1025,6 @@ out:
                clk_put(hdmi_ick);
 }
 
-static void __init fsi_init_pm_clock(void)
-{
-       struct clk *fsia_ick;
-       int ret;
-
-       fsia_ick = clk_get(&fsi_device.dev, "icka");
-       if (IS_ERR(fsia_ick)) {
-               ret = PTR_ERR(fsia_ick);
-               pr_err("Cannot get FSI ICK: %d\n", ret);
-               return;
-       }
-
-       ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
-       if (ret < 0)
-               pr_err("Cannot set FSI-A parent: %d\n", ret);
-
-       clk_put(fsia_ick);
-}
-
 /* TouchScreen */
 #ifdef CONFIG_AP4EVB_QHD
 # define GPIO_TSC_IRQ  GPIO_FN_IRQ28_123
@@ -1476,7 +1338,6 @@ static void __init ap4evb_init(void)
                                       ARRAY_SIZE(domain_devices));
 
        hdmi_init_pm_clock();
-       fsi_init_pm_clock();
        sh7372_pm_init();
        pm_clk_add(&fsi_device.dev, "spu2");
        pm_clk_add(&lcdc1_device.dev, "hdmi");
index 499e6e3766660817fef28cc9022596ab11633dd3..5353adf6b828a55446933e070968c9b4bec20a94 100644 (file)
@@ -768,32 +768,6 @@ static struct platform_device ceu0_device = {
 };
 
 /* FSI */
-static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-{
-       struct clk *fsib;
-       int ret;
-
-       /* it support 48KHz only */
-       if (48000 != rate)
-               return -EINVAL;
-
-       fsib = clk_get(dev, "ickb");
-       if (IS_ERR(fsib))
-               return -EINVAL;
-
-       if (enable) {
-               ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-               clk_enable(fsib);
-       } else {
-               ret = 0;
-               clk_disable(fsib);
-       }
-
-       clk_put(fsib);
-
-       return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
        /* FSI-WM8978 */
        .port_a = {
@@ -802,8 +776,8 @@ static struct sh_fsi_platform_info fsi_info = {
        /* FSI-HDMI */
        .port_b = {
                .flags          = SH_FSI_FMT_SPDIF |
-                                 SH_FSI_ENABLE_STREAM_MODE,
-               .set_rate       = fsi_hdmi_set_rate,
+                                 SH_FSI_ENABLE_STREAM_MODE |
+                                 SH_FSI_CLK_CPG,
                .tx_id          = SHDMA_SLAVE_FSIB_TX,
        }
 };
@@ -938,13 +912,11 @@ static void __init eva_clock_init(void)
        struct clk *xtal1       = clk_get(NULL, "extal1");
        struct clk *usb24s      = clk_get(NULL, "usb24s");
        struct clk *fsibck      = clk_get(NULL, "fsibck");
-       struct clk *fsib        = clk_get(&fsi_device.dev, "ickb");
 
        if (IS_ERR(system)      ||
            IS_ERR(xtal1)       ||
            IS_ERR(usb24s)      ||
-           IS_ERR(fsibck)      ||
-           IS_ERR(fsib)) {
+           IS_ERR(fsibck)) {
                pr_err("armadillo800eva board clock init failed\n");
                goto clock_error;
        }
@@ -956,9 +928,7 @@ static void __init eva_clock_init(void)
        clk_set_parent(usb24s, system);
 
        /* FSIBCK is 12.288MHz, and it is parent of FSI-B */
-       clk_set_parent(fsib, fsibck);
        clk_set_rate(fsibck, 12288000);
-       clk_set_rate(fsib,   12288000);
 
 clock_error:
        if (!IS_ERR(system))
@@ -969,8 +939,6 @@ clock_error:
                clk_put(usb24s);
        if (!IS_ERR(fsibck))
                clk_put(fsibck);
-       if (!IS_ERR(fsib))
-               clk_put(fsib);
 }
 
 /*
index f274252e470521bda095df8a2a8c2ee3611ccddf..2fed62f660459ccae4b08f8548543309587eb0fc 100644 (file)
@@ -370,11 +370,6 @@ static int mackerel_set_brightness(int brightness)
        return 0;
 }
 
-static int mackerel_get_brightness(void)
-{
-       return gpio_get_value(GPIO_PORT31);
-}
-
 static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
        .icb[0] = {
                .meram_size     = 0x40,
@@ -403,7 +398,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                        .name = "sh_mobile_lcdc_bl",
                        .max_brightness = 1,
                        .set_brightness = mackerel_set_brightness,
-                       .get_brightness = mackerel_get_brightness,
                },
                .meram_cfg = &lcd_meram_cfg,
        }
@@ -816,6 +810,8 @@ static struct platform_device usbhs1_device = {
        .id     = 1,
        .dev = {
                .platform_data          = &usbhs1_private.info,
+               .dma_mask               = &usbhs1_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
        .num_resources  = ARRAY_SIZE(usbhs1_resources),
        .resource       = usbhs1_resources,
@@ -860,76 +856,6 @@ static struct platform_device leds_device = {
 
 /* FSI */
 #define IRQ_FSI evt2irq(0x1840)
-static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
-{
-       int ret;
-
-       if (rate <= 0)
-               return 0;
-
-       if (!enable) {
-               clk_disable(clk);
-               return 0;
-       }
-
-       ret = clk_set_rate(clk, clk_round_rate(clk, rate));
-       if (ret < 0)
-               return ret;
-
-       return clk_enable(clk);
-}
-
-static int fsi_b_set_rate(struct device *dev, int rate, int enable)
-{
-       struct clk *fsib_clk;
-       struct clk *fdiv_clk = clk_get(NULL, "fsidivb");
-       long fsib_rate = 0;
-       long fdiv_rate = 0;
-       int ackmd_bpfmd;
-       int ret;
-
-       /* clock start */
-       switch (rate) {
-       case 44100:
-               fsib_rate       = rate * 256;
-               ackmd_bpfmd     = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-               break;
-       case 48000:
-               fsib_rate       = 85428000; /* around 48kHz x 256 x 7 */
-               fdiv_rate       = rate * 256;
-               ackmd_bpfmd     = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-               break;
-       default:
-               pr_err("unsupported rate in FSI2 port B\n");
-               return -EINVAL;
-       }
-
-       /* FSI B setting */
-       fsib_clk = clk_get(dev, "ickb");
-       if (IS_ERR(fsib_clk))
-               return -EIO;
-
-       /* fsib */
-       ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
-       if (ret < 0)
-               goto fsi_set_rate_end;
-
-       /* FSI DIV */
-       ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
-       if (ret < 0) {
-               /* disable FSI B */
-               if (enable)
-                       __fsi_set_round_rate(fsib_clk, fsib_rate, 0);
-               goto fsi_set_rate_end;
-       }
-
-       ret = ackmd_bpfmd;
-
-fsi_set_rate_end:
-       clk_put(fsib_clk);
-       return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
        .port_a = {
                .flags = SH_FSI_BRS_INV,
@@ -940,8 +866,8 @@ static struct sh_fsi_platform_info fsi_info = {
                .flags = SH_FSI_BRS_INV |
                        SH_FSI_BRM_INV  |
                        SH_FSI_LRS_INV  |
+                       SH_FSI_CLK_CPG  |
                        SH_FSI_FMT_SPDIF,
-               .set_rate = fsi_b_set_rate,
        }
 };
 
@@ -1018,7 +944,11 @@ static struct resource nand_flash_resources[] = {
                .start  = 0xe6a30000,
                .end    = 0xe6a3009b,
                .flags  = IORESOURCE_MEM,
-       }
+       },
+       [1] = {
+               .start  = evt2irq(0x0d80), /* flstei: status error irq */
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static struct sh_flctl_platform_data nand_flash_data = {
index 69f7f464eff84bb4446e76500e627d5e03e12d78..449f9289567db20a919dcff45d68bfafe193fb68 100644 (file)
 #include <linux/spi/sh_hspi.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/pm_runtime.h>
 #include <mach/hardware.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
@@ -144,13 +148,185 @@ static struct platform_device hspi_device = {
        .num_resources  = ARRAY_SIZE(hspi_resources),
 };
 
+/* USB PHY */
+static struct resource usb_phy_resources[] = {
+       [0] = {
+               .start          = 0xffe70000,
+               .end            = 0xffe70900 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = 0xfff70000,
+               .end            = 0xfff70900 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device usb_phy_device = {
+       .name           = "rcar_usb_phy",
+       .resource       = usb_phy_resources,
+       .num_resources  = ARRAY_SIZE(usb_phy_resources),
+};
+
 static struct platform_device *marzen_devices[] __initdata = {
        &eth_device,
        &sdhi0_device,
        &thermal_device,
        &hspi_device,
+       &usb_phy_device,
+};
+
+/* USB */
+static struct usb_phy *phy;
+static int usb_power_on(struct platform_device *pdev)
+{
+       if (!phy)
+               return -EIO;
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
+       usb_phy_init(phy);
+
+       return 0;
+}
+
+static void usb_power_off(struct platform_device *pdev)
+{
+       if (!phy)
+               return;
+
+       usb_phy_shutdown(phy);
+
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+}
+
+static struct usb_ehci_pdata ehcix_pdata = {
+       .power_on       = usb_power_on,
+       .power_off      = usb_power_off,
+       .power_suspend  = usb_power_off,
+};
+
+static struct resource ehci0_resources[] = {
+       [0] = {
+               .start  = 0xffe70000,
+               .end    = 0xffe70400 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = gic_spi(44),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ehci0_device = {
+       .name   = "ehci-platform",
+       .id     = 0,
+       .dev    = {
+               .dma_mask               = &ehci0_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &ehcix_pdata,
+       },
+       .num_resources  = ARRAY_SIZE(ehci0_resources),
+       .resource       = ehci0_resources,
 };
 
+static struct resource ehci1_resources[] = {
+       [0] = {
+               .start  = 0xfff70000,
+               .end    = 0xfff70400 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = gic_spi(45),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ehci1_device = {
+       .name   = "ehci-platform",
+       .id     = 1,
+       .dev    = {
+               .dma_mask               = &ehci1_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &ehcix_pdata,
+       },
+       .num_resources  = ARRAY_SIZE(ehci1_resources),
+       .resource       = ehci1_resources,
+};
+
+static struct usb_ohci_pdata ohcix_pdata = {
+       .power_on       = usb_power_on,
+       .power_off      = usb_power_off,
+       .power_suspend  = usb_power_off,
+};
+
+static struct resource ohci0_resources[] = {
+       [0] = {
+               .start  = 0xffe70400,
+               .end    = 0xffe70800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = gic_spi(44),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ohci0_device = {
+       .name   = "ohci-platform",
+       .id     = 0,
+       .dev    = {
+               .dma_mask               = &ohci0_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &ohcix_pdata,
+       },
+       .num_resources  = ARRAY_SIZE(ohci0_resources),
+       .resource       = ohci0_resources,
+};
+
+static struct resource ohci1_resources[] = {
+       [0] = {
+               .start  = 0xfff70400,
+               .end    = 0xfff70800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = gic_spi(45),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ohci1_device = {
+       .name   = "ohci-platform",
+       .id     = 1,
+       .dev    = {
+               .dma_mask               = &ohci1_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &ohcix_pdata,
+       },
+       .num_resources  = ARRAY_SIZE(ohci1_resources),
+       .resource       = ohci1_resources,
+};
+
+static struct platform_device *marzen_late_devices[] __initdata = {
+       &ehci0_device,
+       &ehci1_device,
+       &ohci0_device,
+       &ohci1_device,
+};
+
+void __init marzen_init_late(void)
+{
+       /* get usb phy */
+       phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+       shmobile_init_late();
+       platform_add_devices(marzen_late_devices,
+                            ARRAY_SIZE(marzen_late_devices));
+}
+
 static void __init marzen_init(void)
 {
        regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
@@ -188,6 +364,14 @@ static void __init marzen_init(void)
        gpio_request(GPIO_FN_HSPI_TX0,  NULL);
        gpio_request(GPIO_FN_HSPI_RX0,  NULL);
 
+       /* USB (CN21) */
+       gpio_request(GPIO_FN_USB_OVC0, NULL);
+       gpio_request(GPIO_FN_USB_OVC1, NULL);
+       gpio_request(GPIO_FN_USB_OVC2, NULL);
+
+       /* USB (CN22) */
+       gpio_request(GPIO_FN_USB_PENC2, NULL);
+
        r8a7779_add_standard_devices();
        platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 }
@@ -200,6 +384,6 @@ MACHINE_START(MARZEN, "marzen")
        .init_irq       = r8a7779_init_irq,
        .handle_irq     = gic_handle_irq,
        .init_machine   = marzen_init,
-       .init_late      = shmobile_init_late,
+       .init_late      = marzen_init_late,
        .timer          = &shmobile_timer,
 MACHINE_END
index 4d57e342537b6b24bde3dd17d189887636dcbaa4..3ca6757b129ad7da9be7b8654e61402b8647f012 100644 (file)
@@ -295,10 +295,10 @@ struct clk sh7372_pllc2_clk = {
 };
 
 /* External input clock (pin name: FSIACK/FSIBCK ) */
-struct clk sh7372_fsiack_clk = {
+static struct clk fsiack_clk = {
 };
 
-struct clk sh7372_fsibck_clk = {
+static struct clk fsibck_clk = {
 };
 
 static struct clk *main_clks[] = {
@@ -314,8 +314,8 @@ static struct clk *main_clks[] = {
        &pllc1_clk,
        &pllc1_div2_clk,
        &sh7372_pllc2_clk,
-       &sh7372_fsiack_clk,
-       &sh7372_fsibck_clk,
+       &fsiack_clk,
+       &fsibck_clk,
 };
 
 static void div4_kick(struct clk *clk)
@@ -399,14 +399,14 @@ static struct clk *hdmi_parent[] = {
 static struct clk *fsiackcr_parent[] = {
        [0] = &pllc1_div2_clk,
        [1] = &sh7372_pllc2_clk,
-       [2] = &sh7372_fsiack_clk, /* external input for FSI A */
+       [2] = &fsiack_clk, /* external input for FSI A */
        [3] = NULL,     /* setting prohibited */
 };
 
 static struct clk *fsibckcr_parent[] = {
        [0] = &pllc1_div2_clk,
        [1] = &sh7372_pllc2_clk,
-       [2] = &sh7372_fsibck_clk, /* external input for FSI B */
+       [2] = &fsibck_clk, /* external input for FSI B */
        [3] = NULL,     /* setting prohibited */
 };
 
@@ -507,8 +507,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
        CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
        CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
-       CLKDEV_CON_ID("fsidiva", &fsidivs[FSIDIV_A]),
-       CLKDEV_CON_ID("fsidivb", &fsidivs[FSIDIV_B]),
+       CLKDEV_CON_ID("fsiack", &fsiack_clk),
+       CLKDEV_CON_ID("fsibck", &fsibck_clk),
 
        /* DIV4 clocks */
        CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -606,8 +606,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
        CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
        CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
-       CLKDEV_ICK_ID("xcka", "sh_fsi2", &sh7372_fsiack_clk),
-       CLKDEV_ICK_ID("xckb", "sh_fsi2", &sh7372_fsibck_clk),
+       CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
+       CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
 };
 
 void __init sh7372_clock_init(void)
index 26cd1016fad85dde44d9e0d9b21f6ebab0678d66..b582facc1cf6b174d3bcbfe56ef2bb0ac0a6634f 100644 (file)
@@ -477,8 +477,6 @@ extern struct clk sh7372_extal2_clk;
 extern struct clk sh7372_dv_clki_clk;
 extern struct clk sh7372_dv_clki_div2_clk;
 extern struct clk sh7372_pllc2_clk;
-extern struct clk sh7372_fsiack_clk;
-extern struct clk sh7372_fsibck_clk;
 
 extern void sh7372_intcs_suspend(void);
 extern void sh7372_intcs_resume(void);
index 535426c306bd70e7cae25c24ac550d516005999f..f6745628628003f6f23e5e16c3ea175177f256a6 100644 (file)
 
 #define EMEV2_SCU_BASE 0x1e000000
 
+static DEFINE_SPINLOCK(scu_lock);
 static void __iomem *scu_base;
 
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+       unsigned long tmp;
+
+       /* we assume this code is running on a different cpu
+        * than the one that is changing coherency setting */
+       spin_lock(&scu_lock);
+       tmp = readl(scu_base + 8);
+       tmp &= ~clr;
+       tmp |= set;
+       writel(tmp, scu_base + 8);
+       spin_unlock(&scu_lock);
+
+}
+
 static unsigned int __init emev2_get_core_count(void)
 {
        if (!scu_base) {
@@ -79,7 +95,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
        cpu = cpu_logical_map(cpu);
 
        /* enable cache coherency */
-       scu_power_mode(scu_base, 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        /* Tell ROM loader about our vector (in headsmp.S) */
        emev2_set_boot_vector(__pa(shmobile_secondary_vector));
@@ -90,10 +106,12 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
 
 static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
 {
+       int cpu = cpu_logical_map(0);
+
        scu_enable(scu_base);
 
        /* enable cache coherency on CPU0 */
-       scu_power_mode(scu_base, 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
 
 static void __init emev2_smp_init_cpus(void)
index 9def0f22bf22cacfb1891e69b947e72874964132..2ce6af9a6a3763954c79b757450adc20007cfd40 100644 (file)
@@ -61,6 +61,9 @@ static void __iomem *scu_base_addr(void)
        return (void __iomem *)0xf0000000;
 }
 
+static DEFINE_SPINLOCK(scu_lock);
+static unsigned long tmp;
+
 #ifdef CONFIG_HAVE_ARM_TWD
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
 
@@ -70,6 +73,20 @@ void __init r8a7779_register_twd(void)
 }
 #endif
 
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+       void __iomem *scu_base = scu_base_addr();
+
+       spin_lock(&scu_lock);
+       tmp = __raw_readl(scu_base + 8);
+       tmp &= ~clr;
+       tmp |= set;
+       spin_unlock(&scu_lock);
+
+       /* disable cache coherency after releasing the lock */
+       __raw_writel(tmp, scu_base + 8);
+}
+
 static unsigned int __init r8a7779_get_core_count(void)
 {
        void __iomem *scu_base = scu_base_addr();
@@ -85,7 +102,7 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
        cpu = cpu_logical_map(cpu);
 
        /* disable cache coherency */
-       scu_power_mode(scu_base_addr(), 3);
+       modify_scu_cpu_psr(3 << (cpu * 8), 0);
 
        if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
                ch = r8a7779_ch_cpu[cpu];
@@ -128,7 +145,7 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
        cpu = cpu_logical_map(cpu);
 
        /* enable cache coherency */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
                ch = r8a7779_ch_cpu[cpu];
@@ -141,13 +158,15 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
+       int cpu = cpu_logical_map(0);
+
        scu_enable(scu_base_addr());
 
        /* Map the reset vector (in headsmp.S) */
        __raw_writel(__pa(shmobile_secondary_vector), AVECR);
 
        /* enable cache coherency on CPU0 */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        r8a7779_pm_init();
 
index 96ddb97babbee92ca4080d45a463817234d2fbfc..624f00f70abf79e266504073ce99e8a170f43e77 100644 (file)
@@ -41,6 +41,9 @@ static void __iomem *scu_base_addr(void)
        return (void __iomem *)0xf0000000;
 }
 
+static DEFINE_SPINLOCK(scu_lock);
+static unsigned long tmp;
+
 #ifdef CONFIG_HAVE_ARM_TWD
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
 void __init sh73a0_register_twd(void)
@@ -49,6 +52,20 @@ void __init sh73a0_register_twd(void)
 }
 #endif
 
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+       void __iomem *scu_base = scu_base_addr();
+
+       spin_lock(&scu_lock);
+       tmp = __raw_readl(scu_base + 8);
+       tmp &= ~clr;
+       tmp |= set;
+       spin_unlock(&scu_lock);
+
+       /* disable cache coherency after releasing the lock */
+       __raw_writel(tmp, scu_base + 8);
+}
+
 static unsigned int __init sh73a0_get_core_count(void)
 {
        void __iomem *scu_base = scu_base_addr();
@@ -66,7 +83,7 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
        cpu = cpu_logical_map(cpu);
 
        /* enable cache coherency */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
                __raw_writel(1 << cpu, WUPCR);  /* wake up */
@@ -78,6 +95,8 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
+       int cpu = cpu_logical_map(0);
+
        scu_enable(scu_base_addr());
 
        /* Map the reset vector (in headsmp.S) */
@@ -85,7 +104,7 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
        __raw_writel(__pa(shmobile_secondary_vector), SBAR);
 
        /* enable cache coherency on CPU0 */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
 
 static void __init sh73a0_smp_init_cpus(void)
index 803a3281feb581a6123fb5fc7232951c765e8cbe..566e804d40367c8a13bf83164b4c3af7b7320750 100644 (file)
@@ -12,5 +12,6 @@ config ARCH_SOCFPGA
        select GENERIC_CLOCKEVENTS
        select GPIO_PL061 if GPIOLIB
        select HAVE_ARM_SCU
+       select HAVE_SMP
        select SPARSE_IRQ
        select USE_OF
index 4fb93240971d369a51de869d0198c021f1e28274..6dd7a93a90fea07c472c8cbcbd6f0a0ec5a4d779 100644 (file)
@@ -3,3 +3,4 @@
 #
 
 obj-y                                  := socfpga.o
+obj-$(CONFIG_SMP)      += headsmp.o platsmp.o
diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h
new file mode 100644 (file)
index 0000000..9941caa
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Copyright (C) 2012 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_CORE_H
+#define __MACH_CORE_H
+
+extern void secondary_startup(void);
+extern void __iomem *socfpga_scu_base_addr;
+
+extern void socfpga_init_clocks(void);
+extern void socfpga_sysmgr_init(void);
+
+extern struct smp_operations socfpga_smp_ops;
+extern char secondary_trampoline, secondary_trampoline_end;
+
+#define SOCFPGA_SCU_VIRT_BASE   0xfffec000
+
+#endif
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
new file mode 100644 (file)
index 0000000..f09b128
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2003 ARM Limited
+ *  Copyright (c) u-boot contributors
+ *  Copyright (c) 2012 Pavel Machek <pavel@denx.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
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+       __CPUINIT
+       .arch   armv7-a
+
+#define CPU1_START_ADDR                0xffd08010
+
+ENTRY(secondary_trampoline)
+       movw    r0, #:lower16:CPU1_START_ADDR
+       movt  r0, #:upper16:CPU1_START_ADDR
+
+       ldr     r1, [r0]
+       bx      r1
+
+ENTRY(secondary_trampoline_end)
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
new file mode 100644 (file)
index 0000000..68dd1b6
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ * Copyright (C) 2012 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+
+#include "core.h"
+
+extern void __iomem *sys_manager_base_addr;
+extern void __iomem *rst_manager_base_addr;
+
+static void __cpuinit socfpga_secondary_init(unsigned int cpu)
+{
+       /*
+        * if any interrupts are already enabled for the primary
+        * core (e.g. timer irq), then they will not have been enabled
+        * for us: do so
+        */
+       gic_secondary_init(0);
+}
+
+static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
+
+       memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+
+       __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
+
+       flush_cache_all();
+       smp_wmb();
+       outer_clean_range(0, trampoline_size);
+
+       /* This will release CPU #1 out of reset.*/
+       __raw_writel(0, rst_manager_base_addr + 0x10);
+
+       return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+static void __init socfpga_smp_init_cpus(void)
+{
+       unsigned int i, ncores;
+
+       ncores = scu_get_core_count(socfpga_scu_base_addr);
+
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+
+       /* sanity check */
+       if (ncores > num_possible_cpus()) {
+               pr_warn("socfpga: no. of cores (%d) greater than configured"
+                       "maximum of %d - clipping\n", ncores, num_possible_cpus());
+               ncores = num_possible_cpus();
+       }
+
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+
+       set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
+{
+       scu_enable(socfpga_scu_base_addr);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+static void socfpga_cpu_die(unsigned int cpu)
+{
+       cpu_do_idle();
+
+       /* We should have never returned from idle */
+       panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+struct smp_operations socfpga_smp_ops __initdata = {
+       .smp_init_cpus          = socfpga_smp_init_cpus,
+       .smp_prepare_cpus       = socfpga_smp_prepare_cpus,
+       .smp_secondary_init     = socfpga_secondary_init,
+       .smp_boot_secondary     = socfpga_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die                = socfpga_cpu_die,
+#endif
+};
index f01e1ebf539601dd772eb9237eea5252800fb806..6732924a5fee2900fb8b9bc97c39921cd966b136 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/dw_apb_timer.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 
-extern void socfpga_init_clocks(void);
+#include "core.h"
+
+void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
+void __iomem *sys_manager_base_addr;
+void __iomem *rst_manager_base_addr;
+
+static struct map_desc scu_io_desc __initdata = {
+       .virtual        = SOCFPGA_SCU_VIRT_BASE,
+       .pfn            = 0, /* run-time */
+       .length         = SZ_8K,
+       .type           = MT_DEVICE,
+};
+
+static struct map_desc uart_io_desc __initdata = {
+       .virtual        = 0xfec02000,
+       .pfn            = __phys_to_pfn(0xffc02000),
+       .length         = SZ_8K,
+       .type           = MT_DEVICE,
+};
+
+static void __init socfpga_scu_map_io(void)
+{
+       unsigned long base;
+
+       /* Get SCU base */
+       asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+       scu_io_desc.pfn = __phys_to_pfn(base);
+       iotable_init(&scu_io_desc, 1);
+}
+
+static void __init socfpga_map_io(void)
+{
+       socfpga_scu_map_io();
+       iotable_init(&uart_io_desc, 1);
+       early_printk("Early printk initialized\n");
+}
 
 const static struct of_device_id irq_match[] = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
        {}
 };
 
+void __init socfpga_sysmgr_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
+       sys_manager_base_addr = of_iomap(np, 0);
+
+       np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
+       rst_manager_base_addr = of_iomap(np, 0);
+}
+
 static void __init gic_init_irq(void)
 {
        of_irq_init(irq_match);
+       socfpga_sysmgr_init();
 }
 
 static void socfpga_cyclone5_restart(char mode, const char *cmd)
@@ -53,6 +103,8 @@ static const char *altera_dt_match[] = {
 };
 
 DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
+       .smp            = smp_ops(socfpga_smp_ops),
+       .map_io         = socfpga_map_io,
        .init_irq       = gic_init_irq,
        .handle_irq     = gic_handle_irq,
        .timer          = &dw_apb_timer,
index 07d90acc92c86ffdb0493c12aa14ff7b8f7caa8e..7cfa6818865a144f2a8d8935eb88ebdb67a053d3 100644 (file)
 #define DMAC1_BASE                             UL(0xEB000000)
 #define MCIF_CF_BASE                           UL(0xB2800000)
 
-/* Devices present in SPEAr1310 */
-#ifdef CONFIG_MACH_SPEAR1310
-#define SPEAR1310_RAS_GRP1_BASE                        UL(0xD8000000)
-#define VA_SPEAR1310_RAS_GRP1_BASE             UL(0xFA000000)
-#define SPEAR1310_RAS_BASE                     UL(0xD8400000)
-#define VA_SPEAR1310_RAS_BASE                  IOMEM(UL(0xFA400000))
-#endif /* CONFIG_MACH_SPEAR1310 */
-
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE                    UART_BASE
 #define VA_SPEAR_DBG_UART_BASE                 VA_UART_BASE
index 9fbbfc5650aa608f5afe6b5d8f43efefd8b36b85..02f4724bb0d487d4d6440e302ccd4cb0d0993301 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/of_platform.h>
+#include <linux/pata_arasan_cf_data.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #define SPEAR1310_SATA1_BASE                   UL(0xB1800000)
 #define SPEAR1310_SATA2_BASE                   UL(0xB4000000)
 
+#define SPEAR1310_RAS_GRP1_BASE                        UL(0xD8000000)
+#define VA_SPEAR1310_RAS_GRP1_BASE             UL(0xFA000000)
+#define SPEAR1310_RAS_BASE                     UL(0xD8400000)
+#define VA_SPEAR1310_RAS_BASE                  IOMEM(UL(0xFA400000))
+
+static struct arasan_cf_pdata cf_pdata = {
+       .cf_if_clk = CF_IF_CLK_166M,
+       .quirk = CF_BROKEN_UDMA,
+       .dma_priv = &cf_dma_priv,
+};
+
 /* ssp device registration */
 static struct pl022_ssp_controller ssp1_plat_data = {
-       .bus_id = 0,
        .enable_dma = 0,
-       .num_chipselect = 3,
 };
 
 /* Add SPEAr1310 auxdata to pass platform data */
 static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
-       OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
+       OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
        OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
        OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
        OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
index 5633d698f1e189c29d04eb09f8f18276f9d85b73..c4af775a8451a6067f5c4c8ecb30ef1da2d902f8 100644 (file)
@@ -57,12 +57,10 @@ static struct dw_dma_slave ssp_dma_param[] = {
 };
 
 struct pl022_ssp_controller pl022_plat_data = {
-       .bus_id = 0,
        .enable_dma = 1,
        .dma_filter = dw_dma_filter,
        .dma_rx_param = &ssp_dma_param[1],
        .dma_tx_param = &ssp_dma_param[0],
-       .num_chipselect = 3,
 };
 
 /* CF device registration */
index 803de76f5f36fb5535c632c385869d70c86e61b8..f95e5b2b668674a7b5b6bc1c58a0187c46372051 100644 (file)
 #ifndef __MACH_IRQS_H
 #define __MACH_IRQS_H
 
-/* FIXME: probe all these from DT */
-#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM          1
-#define SPEAR3XX_IRQ_GEN_RAS_1                 28
-#define SPEAR3XX_IRQ_GEN_RAS_2                 29
-#define SPEAR3XX_IRQ_GEN_RAS_3                 30
-#define SPEAR3XX_IRQ_VIC_END                   32
-#define SPEAR3XX_VIRQ_START                    SPEAR3XX_IRQ_VIC_END
-
-#define NR_IRQS                        160
+#define NR_IRQS                        256
 
 #endif /* __MACH_IRQS_H */
index 6ec300549960196d83ab1542e8715c200f83e50b..a69cbfdb07ee42c17451bf9cfa52952b5ca1382b 100644 (file)
 #include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
-#include <plat/shirq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
-/* Base address of various IPs */
-#define SPEAR300_TELECOM_BASE          UL(0x50000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR300_INT_ENB_MASK_REG      0x54
-#define SPEAR300_INT_STS_MASK_REG      0x58
-#define SPEAR300_IT_PERS_S_IRQ_MASK    (1 << 0)
-#define SPEAR300_IT_CHANGE_S_IRQ_MASK  (1 << 1)
-#define SPEAR300_I2S_IRQ_MASK          (1 << 2)
-#define SPEAR300_TDM_IRQ_MASK          (1 << 3)
-#define SPEAR300_CAMERA_L_IRQ_MASK     (1 << 4)
-#define SPEAR300_CAMERA_F_IRQ_MASK     (1 << 5)
-#define SPEAR300_CAMERA_V_IRQ_MASK     (1 << 6)
-#define SPEAR300_KEYBOARD_IRQ_MASK     (1 << 7)
-#define SPEAR300_GPIO1_IRQ_MASK                (1 << 8)
-
-#define SPEAR300_SHIRQ_RAS1_MASK       0x1FF
-
-#define SPEAR300_SOC_CONFIG_BASE       UL(0x99000000)
-
-
-/* SPEAr300 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR300_VIRQ_IT_PERS_S                        (SPEAR3XX_VIRQ_START + 0)
-#define SPEAR300_VIRQ_IT_CHANGE_S              (SPEAR3XX_VIRQ_START + 1)
-#define SPEAR300_VIRQ_I2S                      (SPEAR3XX_VIRQ_START + 2)
-#define SPEAR300_VIRQ_TDM                      (SPEAR3XX_VIRQ_START + 3)
-#define SPEAR300_VIRQ_CAMERA_L                 (SPEAR3XX_VIRQ_START + 4)
-#define SPEAR300_VIRQ_CAMERA_F                 (SPEAR3XX_VIRQ_START + 5)
-#define SPEAR300_VIRQ_CAMERA_V                 (SPEAR3XX_VIRQ_START + 6)
-#define SPEAR300_VIRQ_KEYBOARD                 (SPEAR3XX_VIRQ_START + 7)
-#define SPEAR300_VIRQ_GPIO1                    (SPEAR3XX_VIRQ_START + 8)
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR300_IRQ_CLCD                      SPEAR3XX_IRQ_GEN_RAS_3
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR300_IRQ_SDHCI                     SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
-
-/* spear3xx shared irq */
-static struct shirq_dev_config shirq_ras1_config[] = {
-       {
-               .virq = SPEAR300_VIRQ_IT_PERS_S,
-               .enb_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
-               .status_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_IT_CHANGE_S,
-               .enb_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
-               .status_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_I2S,
-               .enb_mask = SPEAR300_I2S_IRQ_MASK,
-               .status_mask = SPEAR300_I2S_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_TDM,
-               .enb_mask = SPEAR300_TDM_IRQ_MASK,
-               .status_mask = SPEAR300_TDM_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_CAMERA_L,
-               .enb_mask = SPEAR300_CAMERA_L_IRQ_MASK,
-               .status_mask = SPEAR300_CAMERA_L_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_CAMERA_F,
-               .enb_mask = SPEAR300_CAMERA_F_IRQ_MASK,
-               .status_mask = SPEAR300_CAMERA_F_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_CAMERA_V,
-               .enb_mask = SPEAR300_CAMERA_V_IRQ_MASK,
-               .status_mask = SPEAR300_CAMERA_V_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_KEYBOARD,
-               .enb_mask = SPEAR300_KEYBOARD_IRQ_MASK,
-               .status_mask = SPEAR300_KEYBOARD_IRQ_MASK,
-       }, {
-               .virq = SPEAR300_VIRQ_GPIO1,
-               .enb_mask = SPEAR300_GPIO1_IRQ_MASK,
-               .status_mask = SPEAR300_GPIO1_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_ras1 = {
-       .irq = SPEAR3XX_IRQ_GEN_RAS_1,
-       .dev_config = shirq_ras1_config,
-       .dev_count = ARRAY_SIZE(shirq_ras1_config),
-       .regs = {
-               .enb_reg = SPEAR300_INT_ENB_MASK_REG,
-               .status_reg = SPEAR300_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR300_SHIRQ_RAS1_MASK,
-               .clear_reg = -1,
-       },
-};
-
 /* DMAC platform data's slave info */
 struct pl08x_channel_data spear300_dma_info[] = {
        {
@@ -285,21 +192,11 @@ static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
 
 static void __init spear300_dt_init(void)
 {
-       int ret;
-
        pl080_plat_data.slave_channels = spear300_dma_info;
        pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
 
        of_platform_populate(NULL, of_default_bus_match_table,
                        spear300_auxdata_lookup, NULL);
-
-       /* shared irq registration */
-       shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
-       if (shirq_ras1.regs.base) {
-               ret = spear_shirq_register(&shirq_ras1);
-               if (ret)
-                       pr_err("Error registering Shared IRQ\n");
-       }
 }
 
 static const char * const spear300_dt_board_compat[] = {
index 1d0e435b904525e1d2070bfbc6f68e3ba91eea83..b963ebb10b564edaaa37ba5028887fb557dcd920 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
-#include <plat/shirq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
 #define SPEAR310_UART3_BASE            UL(0xB2100000)
 #define SPEAR310_UART4_BASE            UL(0xB2180000)
 #define SPEAR310_UART5_BASE            UL(0xB2200000)
-#define SPEAR310_SOC_CONFIG_BASE       UL(0xB4000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR310_INT_STS_MASK_REG      0x04
-#define SPEAR310_SMII0_IRQ_MASK                (1 << 0)
-#define SPEAR310_SMII1_IRQ_MASK                (1 << 1)
-#define SPEAR310_SMII2_IRQ_MASK                (1 << 2)
-#define SPEAR310_SMII3_IRQ_MASK                (1 << 3)
-#define SPEAR310_WAKEUP_SMII0_IRQ_MASK (1 << 4)
-#define SPEAR310_WAKEUP_SMII1_IRQ_MASK (1 << 5)
-#define SPEAR310_WAKEUP_SMII2_IRQ_MASK (1 << 6)
-#define SPEAR310_WAKEUP_SMII3_IRQ_MASK (1 << 7)
-#define SPEAR310_UART1_IRQ_MASK                (1 << 8)
-#define SPEAR310_UART2_IRQ_MASK                (1 << 9)
-#define SPEAR310_UART3_IRQ_MASK                (1 << 10)
-#define SPEAR310_UART4_IRQ_MASK                (1 << 11)
-#define SPEAR310_UART5_IRQ_MASK                (1 << 12)
-#define SPEAR310_EMI_IRQ_MASK          (1 << 13)
-#define SPEAR310_TDM_HDLC_IRQ_MASK     (1 << 14)
-#define SPEAR310_RS485_0_IRQ_MASK      (1 << 15)
-#define SPEAR310_RS485_1_IRQ_MASK      (1 << 16)
-
-#define SPEAR310_SHIRQ_RAS1_MASK       0x000FF
-#define SPEAR310_SHIRQ_RAS2_MASK       0x01F00
-#define SPEAR310_SHIRQ_RAS3_MASK       0x02000
-#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK       0x1C000
-
-/* SPEAr310 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR310_VIRQ_SMII0                    (SPEAR3XX_VIRQ_START + 0)
-#define SPEAR310_VIRQ_SMII1                    (SPEAR3XX_VIRQ_START + 1)
-#define SPEAR310_VIRQ_SMII2                    (SPEAR3XX_VIRQ_START + 2)
-#define SPEAR310_VIRQ_SMII3                    (SPEAR3XX_VIRQ_START + 3)
-#define SPEAR310_VIRQ_WAKEUP_SMII0             (SPEAR3XX_VIRQ_START + 4)
-#define SPEAR310_VIRQ_WAKEUP_SMII1             (SPEAR3XX_VIRQ_START + 5)
-#define SPEAR310_VIRQ_WAKEUP_SMII2             (SPEAR3XX_VIRQ_START + 6)
-#define SPEAR310_VIRQ_WAKEUP_SMII3             (SPEAR3XX_VIRQ_START + 7)
-
-/* IRQs sharing IRQ_GEN_RAS_2 */
-#define SPEAR310_VIRQ_UART1                    (SPEAR3XX_VIRQ_START + 8)
-#define SPEAR310_VIRQ_UART2                    (SPEAR3XX_VIRQ_START + 9)
-#define SPEAR310_VIRQ_UART3                    (SPEAR3XX_VIRQ_START + 10)
-#define SPEAR310_VIRQ_UART4                    (SPEAR3XX_VIRQ_START + 11)
-#define SPEAR310_VIRQ_UART5                    (SPEAR3XX_VIRQ_START + 12)
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR310_VIRQ_EMI                      (SPEAR3XX_VIRQ_START + 13)
-#define SPEAR310_VIRQ_PLGPIO                   (SPEAR3XX_VIRQ_START + 14)
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR310_VIRQ_TDM_HDLC                 (SPEAR3XX_VIRQ_START + 15)
-#define SPEAR310_VIRQ_RS485_0                  (SPEAR3XX_VIRQ_START + 16)
-#define SPEAR310_VIRQ_RS485_1                  (SPEAR3XX_VIRQ_START + 17)
-
-
-/* spear3xx shared irq */
-static struct shirq_dev_config shirq_ras1_config[] = {
-       {
-               .virq = SPEAR310_VIRQ_SMII0,
-               .status_mask = SPEAR310_SMII0_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_SMII1,
-               .status_mask = SPEAR310_SMII1_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_SMII2,
-               .status_mask = SPEAR310_SMII2_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_SMII3,
-               .status_mask = SPEAR310_SMII3_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_WAKEUP_SMII0,
-               .status_mask = SPEAR310_WAKEUP_SMII0_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_WAKEUP_SMII1,
-               .status_mask = SPEAR310_WAKEUP_SMII1_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_WAKEUP_SMII2,
-               .status_mask = SPEAR310_WAKEUP_SMII2_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_WAKEUP_SMII3,
-               .status_mask = SPEAR310_WAKEUP_SMII3_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_ras1 = {
-       .irq = SPEAR3XX_IRQ_GEN_RAS_1,
-       .dev_config = shirq_ras1_config,
-       .dev_count = ARRAY_SIZE(shirq_ras1_config),
-       .regs = {
-               .enb_reg = -1,
-               .status_reg = SPEAR310_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR310_SHIRQ_RAS1_MASK,
-               .clear_reg = -1,
-       },
-};
-
-static struct shirq_dev_config shirq_ras2_config[] = {
-       {
-               .virq = SPEAR310_VIRQ_UART1,
-               .status_mask = SPEAR310_UART1_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_UART2,
-               .status_mask = SPEAR310_UART2_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_UART3,
-               .status_mask = SPEAR310_UART3_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_UART4,
-               .status_mask = SPEAR310_UART4_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_UART5,
-               .status_mask = SPEAR310_UART5_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_ras2 = {
-       .irq = SPEAR3XX_IRQ_GEN_RAS_2,
-       .dev_config = shirq_ras2_config,
-       .dev_count = ARRAY_SIZE(shirq_ras2_config),
-       .regs = {
-               .enb_reg = -1,
-               .status_reg = SPEAR310_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR310_SHIRQ_RAS2_MASK,
-               .clear_reg = -1,
-       },
-};
-
-static struct shirq_dev_config shirq_ras3_config[] = {
-       {
-               .virq = SPEAR310_VIRQ_EMI,
-               .status_mask = SPEAR310_EMI_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_ras3 = {
-       .irq = SPEAR3XX_IRQ_GEN_RAS_3,
-       .dev_config = shirq_ras3_config,
-       .dev_count = ARRAY_SIZE(shirq_ras3_config),
-       .regs = {
-               .enb_reg = -1,
-               .status_reg = SPEAR310_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR310_SHIRQ_RAS3_MASK,
-               .clear_reg = -1,
-       },
-};
-
-static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
-       {
-               .virq = SPEAR310_VIRQ_TDM_HDLC,
-               .status_mask = SPEAR310_TDM_HDLC_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_RS485_0,
-               .status_mask = SPEAR310_RS485_0_IRQ_MASK,
-       }, {
-               .virq = SPEAR310_VIRQ_RS485_1,
-               .status_mask = SPEAR310_RS485_1_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_intrcomm_ras = {
-       .irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
-       .dev_config = shirq_intrcomm_ras_config,
-       .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
-       .regs = {
-               .enb_reg = -1,
-               .status_reg = SPEAR310_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR310_SHIRQ_INTRCOMM_RAS_MASK,
-               .clear_reg = -1,
-       },
-};
 
 /* DMAC platform data's slave info */
 struct pl08x_channel_data spear310_dma_info[] = {
@@ -405,42 +234,11 @@ static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
 
 static void __init spear310_dt_init(void)
 {
-       void __iomem *base;
-       int ret;
-
        pl080_plat_data.slave_channels = spear310_dma_info;
        pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
 
        of_platform_populate(NULL, of_default_bus_match_table,
                        spear310_auxdata_lookup, NULL);
-
-       /* shared irq registration */
-       base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
-       if (base) {
-               /* shirq 1 */
-               shirq_ras1.regs.base = base;
-               ret = spear_shirq_register(&shirq_ras1);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 1\n");
-
-               /* shirq 2 */
-               shirq_ras2.regs.base = base;
-               ret = spear_shirq_register(&shirq_ras2);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 2\n");
-
-               /* shirq 3 */
-               shirq_ras3.regs.base = base;
-               ret = spear_shirq_register(&shirq_ras3);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 3\n");
-
-               /* shirq 4 */
-               shirq_intrcomm_ras.regs.base = base;
-               ret = spear_shirq_register(&shirq_intrcomm_ras);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 4\n");
-       }
 }
 
 static const char * const spear310_dt_board_compat[] = {
index fd823c624575f12991e99eafdaeb2a3a6e8a4e11..66e3a0c33e757c84d25ec218a2815f456cda3c47 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
-#include <plat/shirq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
 #define SPEAR320_SSP0_BASE             UL(0xA5000000)
 #define SPEAR320_SSP1_BASE             UL(0xA6000000)
 
-/* Interrupt registers offsets and masks */
-#define SPEAR320_INT_STS_MASK_REG              0x04
-#define SPEAR320_INT_CLR_MASK_REG              0x04
-#define SPEAR320_INT_ENB_MASK_REG              0x08
-#define SPEAR320_GPIO_IRQ_MASK                 (1 << 0)
-#define SPEAR320_I2S_PLAY_IRQ_MASK             (1 << 1)
-#define SPEAR320_I2S_REC_IRQ_MASK              (1 << 2)
-#define SPEAR320_EMI_IRQ_MASK                  (1 << 7)
-#define SPEAR320_CLCD_IRQ_MASK                 (1 << 8)
-#define SPEAR320_SPP_IRQ_MASK                  (1 << 9)
-#define SPEAR320_SDHCI_IRQ_MASK                        (1 << 10)
-#define SPEAR320_CAN_U_IRQ_MASK                        (1 << 11)
-#define SPEAR320_CAN_L_IRQ_MASK                        (1 << 12)
-#define SPEAR320_UART1_IRQ_MASK                        (1 << 13)
-#define SPEAR320_UART2_IRQ_MASK                        (1 << 14)
-#define SPEAR320_SSP1_IRQ_MASK                 (1 << 15)
-#define SPEAR320_SSP2_IRQ_MASK                 (1 << 16)
-#define SPEAR320_SMII0_IRQ_MASK                        (1 << 17)
-#define SPEAR320_MII1_SMII1_IRQ_MASK           (1 << 18)
-#define SPEAR320_WAKEUP_SMII0_IRQ_MASK         (1 << 19)
-#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK    (1 << 20)
-#define SPEAR320_I2C1_IRQ_MASK                 (1 << 21)
-
-#define SPEAR320_SHIRQ_RAS1_MASK               0x000380
-#define SPEAR320_SHIRQ_RAS3_MASK               0x000007
-#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK       0x3FF800
-
-/* SPEAr320 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR320_VIRQ_EMI                      (SPEAR3XX_VIRQ_START + 0)
-#define SPEAR320_VIRQ_CLCD                     (SPEAR3XX_VIRQ_START + 1)
-#define SPEAR320_VIRQ_SPP                      (SPEAR3XX_VIRQ_START + 2)
-
-/* IRQs sharing IRQ_GEN_RAS_2 */
-#define SPEAR320_IRQ_SDHCI                     SPEAR3XX_IRQ_GEN_RAS_2
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR320_VIRQ_PLGPIO                   (SPEAR3XX_VIRQ_START + 3)
-#define SPEAR320_VIRQ_I2S_PLAY                 (SPEAR3XX_VIRQ_START + 4)
-#define SPEAR320_VIRQ_I2S_REC                  (SPEAR3XX_VIRQ_START + 5)
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR320_VIRQ_CANU                     (SPEAR3XX_VIRQ_START + 6)
-#define SPEAR320_VIRQ_CANL                     (SPEAR3XX_VIRQ_START + 7)
-#define SPEAR320_VIRQ_UART1                    (SPEAR3XX_VIRQ_START + 8)
-#define SPEAR320_VIRQ_UART2                    (SPEAR3XX_VIRQ_START + 9)
-#define SPEAR320_VIRQ_SSP1                     (SPEAR3XX_VIRQ_START + 10)
-#define SPEAR320_VIRQ_SSP2                     (SPEAR3XX_VIRQ_START + 11)
-#define SPEAR320_VIRQ_SMII0                    (SPEAR3XX_VIRQ_START + 12)
-#define SPEAR320_VIRQ_MII1_SMII1               (SPEAR3XX_VIRQ_START + 13)
-#define SPEAR320_VIRQ_WAKEUP_SMII0             (SPEAR3XX_VIRQ_START + 14)
-#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1                (SPEAR3XX_VIRQ_START + 15)
-#define SPEAR320_VIRQ_I2C1                     (SPEAR3XX_VIRQ_START + 16)
-
-/* spear3xx shared irq */
-static struct shirq_dev_config shirq_ras1_config[] = {
-       {
-               .virq = SPEAR320_VIRQ_EMI,
-               .status_mask = SPEAR320_EMI_IRQ_MASK,
-               .clear_mask = SPEAR320_EMI_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_CLCD,
-               .status_mask = SPEAR320_CLCD_IRQ_MASK,
-               .clear_mask = SPEAR320_CLCD_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_SPP,
-               .status_mask = SPEAR320_SPP_IRQ_MASK,
-               .clear_mask = SPEAR320_SPP_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_ras1 = {
-       .irq = SPEAR3XX_IRQ_GEN_RAS_1,
-       .dev_config = shirq_ras1_config,
-       .dev_count = ARRAY_SIZE(shirq_ras1_config),
-       .regs = {
-               .enb_reg = -1,
-               .status_reg = SPEAR320_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR320_SHIRQ_RAS1_MASK,
-               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
-               .reset_to_clear = 1,
-       },
-};
-
-static struct shirq_dev_config shirq_ras3_config[] = {
-       {
-               .virq = SPEAR320_VIRQ_PLGPIO,
-               .enb_mask = SPEAR320_GPIO_IRQ_MASK,
-               .status_mask = SPEAR320_GPIO_IRQ_MASK,
-               .clear_mask = SPEAR320_GPIO_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_I2S_PLAY,
-               .enb_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
-               .status_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
-               .clear_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_I2S_REC,
-               .enb_mask = SPEAR320_I2S_REC_IRQ_MASK,
-               .status_mask = SPEAR320_I2S_REC_IRQ_MASK,
-               .clear_mask = SPEAR320_I2S_REC_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_ras3 = {
-       .irq = SPEAR3XX_IRQ_GEN_RAS_3,
-       .dev_config = shirq_ras3_config,
-       .dev_count = ARRAY_SIZE(shirq_ras3_config),
-       .regs = {
-               .enb_reg = SPEAR320_INT_ENB_MASK_REG,
-               .reset_to_enb = 1,
-               .status_reg = SPEAR320_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR320_SHIRQ_RAS3_MASK,
-               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
-               .reset_to_clear = 1,
-       },
-};
-
-static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
-       {
-               .virq = SPEAR320_VIRQ_CANU,
-               .status_mask = SPEAR320_CAN_U_IRQ_MASK,
-               .clear_mask = SPEAR320_CAN_U_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_CANL,
-               .status_mask = SPEAR320_CAN_L_IRQ_MASK,
-               .clear_mask = SPEAR320_CAN_L_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_UART1,
-               .status_mask = SPEAR320_UART1_IRQ_MASK,
-               .clear_mask = SPEAR320_UART1_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_UART2,
-               .status_mask = SPEAR320_UART2_IRQ_MASK,
-               .clear_mask = SPEAR320_UART2_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_SSP1,
-               .status_mask = SPEAR320_SSP1_IRQ_MASK,
-               .clear_mask = SPEAR320_SSP1_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_SSP2,
-               .status_mask = SPEAR320_SSP2_IRQ_MASK,
-               .clear_mask = SPEAR320_SSP2_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_SMII0,
-               .status_mask = SPEAR320_SMII0_IRQ_MASK,
-               .clear_mask = SPEAR320_SMII0_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_MII1_SMII1,
-               .status_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
-               .clear_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_WAKEUP_SMII0,
-               .status_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
-               .clear_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_WAKEUP_MII1_SMII1,
-               .status_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
-               .clear_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
-       }, {
-               .virq = SPEAR320_VIRQ_I2C1,
-               .status_mask = SPEAR320_I2C1_IRQ_MASK,
-               .clear_mask = SPEAR320_I2C1_IRQ_MASK,
-       },
-};
-
-static struct spear_shirq shirq_intrcomm_ras = {
-       .irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
-       .dev_config = shirq_intrcomm_ras_config,
-       .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
-       .regs = {
-               .enb_reg = -1,
-               .status_reg = SPEAR320_INT_STS_MASK_REG,
-               .status_reg_mask = SPEAR320_SHIRQ_INTRCOMM_RAS_MASK,
-               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
-               .reset_to_clear = 1,
-       },
-};
-
 /* DMAC platform data's slave info */
 struct pl08x_channel_data spear320_dma_info[] = {
        {
@@ -416,41 +237,17 @@ static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
 
 static void __init spear320_dt_init(void)
 {
-       void __iomem *base;
-       int ret;
-
        pl080_plat_data.slave_channels = spear320_dma_info;
        pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
 
        of_platform_populate(NULL, of_default_bus_match_table,
                        spear320_auxdata_lookup, NULL);
-
-       /* shared irq registration */
-       base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
-       if (base) {
-               /* shirq 1 */
-               shirq_ras1.regs.base = base;
-               ret = spear_shirq_register(&shirq_ras1);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 1\n");
-
-               /* shirq 3 */
-               shirq_ras3.regs.base = base;
-               ret = spear_shirq_register(&shirq_ras3);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 3\n");
-
-               /* shirq 4 */
-               shirq_intrcomm_ras.regs.base = base;
-               ret = spear_shirq_register(&shirq_intrcomm_ras);
-               if (ret)
-                       pr_err("Error registering Shared IRQ 4\n");
-       }
 }
 
 static const char * const spear320_dt_board_compat[] = {
        "st,spear320",
        "st,spear320-evb",
+       "st,spear320-hmi",
        NULL,
 };
 
index 98144baf88838243d8a45c5bded0f606bd7d99d7..38fe95db31a70a69c241699edf2b5022be8d698a 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/amba/pl08x.h>
+#include <linux/irqchip/spear-shirq.h>
 #include <linux/of_irq.h>
 #include <linux/io.h>
 #include <asm/hardware/pl080.h>
@@ -121,6 +122,9 @@ struct sys_timer spear3xx_timer = {
 
 static const struct of_device_id vic_of_match[] __initconst = {
        { .compatible = "arm,pl190-vic", .data = vic_of_init, },
+       { .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, },
+       { .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, },
+       { .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, },
        { /* Sentinel */ }
 };
 
index e426d1b7747e8c5f8ab417de2a4e515e6631e9b0..b442f15fd01a8b7d49b14337c68896486da66cce 100644 (file)
@@ -55,7 +55,7 @@ config TEGRA_AHB
        help
          Adds AHB configuration functionality for NVIDIA Tegra SoCs,
          which controls AHB bus master arbitration and some
-         perfomance parameters(priority, prefech size).
+         performance parameters(priority, prefech size).
 
 config TEGRA_EMC_SCALING_ENABLE
        bool "Enable scaling the memory frequency"
index 94186b6c685fbecf6f84514885b1e5acee68cf8e..3fd629d5a5132c27caf14d25b4d15366eca23ca2 100644 (file)
@@ -352,6 +352,10 @@ config CPU_PJ4
        select ARM_THUMBEE
        select CPU_V7
 
+config CPU_PJ4B
+       bool
+       select CPU_V7
+
 # ARMv6
 config CPU_V6
        bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
index 58bc3e4d3bd0a76094d8a2a40c0be9bece4eaf7a..5383bc0185713d68be350602dff677d334c19f02 100644 (file)
@@ -124,8 +124,6 @@ static void arm_dma_sync_single_for_device(struct device *dev,
        __dma_page_cpu_to_dev(page, offset, size, dir);
 }
 
-static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
-
 struct dma_map_ops arm_dma_ops = {
        .alloc                  = arm_dma_alloc,
        .free                   = arm_dma_free,
@@ -971,7 +969,7 @@ int dma_supported(struct device *dev, u64 mask)
 }
 EXPORT_SYMBOL(dma_supported);
 
-static int arm_dma_set_mask(struct device *dev, u64 dma_mask)
+int arm_dma_set_mask(struct device *dev, u64 dma_mask)
 {
        if (!dev->dma_mask || !dma_supported(dev, dma_mask))
                return -EIO;
index 42cc833aa02f7b43aa6e851328a4ef5e4734b30e..350f6a74992b9200618e52ed07a2ec9dd1bde407 100644 (file)
@@ -169,6 +169,63 @@ __v7_ca15mp_setup:
        orreq   r0, r0, r10                     @ Enable CPU-specific SMP bits
        mcreq   p15, 0, r0, c1, c0, 1
 #endif
+
+__v7_pj4b_setup:
+#ifdef CONFIG_CPU_PJ4B
+
+/* Auxiliary Debug Modes Control 1 Register */
+#define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */
+#define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */
+#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */
+#define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */
+
+/* Auxiliary Debug Modes Control 2 Register */
+#define PJ4B_FAST_LDR (1 << 23) /* Disable fast LDR */
+#define PJ4B_SNOOP_DATA (1 << 25) /* Do not interleave write and snoop data */
+#define PJ4B_CWF (1 << 27) /* Disable Critical Word First feature */
+#define PJ4B_OUTSDNG_NC (1 << 29) /* Disable outstanding non cacheable rqst */
+#define PJ4B_L1_REP_RR (1 << 30) /* L1 replacement - Strict round robin */
+#define PJ4B_AUX_DBG_CTRL2 (PJ4B_SNOOP_DATA | PJ4B_CWF |\
+                           PJ4B_OUTSDNG_NC | PJ4B_L1_REP_RR)
+
+/* Auxiliary Functional Modes Control Register 0 */
+#define PJ4B_SMP_CFB (1 << 1) /* Set SMP mode. Join the coherency fabric */
+#define PJ4B_L1_PAR_CHK (1 << 2) /* Support L1 parity checking */
+#define PJ4B_BROADCAST_CACHE (1 << 8) /* Broadcast Cache and TLB maintenance */
+
+/* Auxiliary Debug Modes Control 0 Register */
+#define PJ4B_WFI_WFE (1 << 22) /* WFI/WFE - serve the DVM and back to idle */
+
+       /* Auxiliary Debug Modes Control 1 Register */
+       mrc     p15, 1, r0, c15, c1, 1
+       orr     r0, r0, #PJ4B_CLEAN_LINE
+       orr     r0, r0, #PJ4B_BCK_OFF_STREX
+       orr     r0, r0, #PJ4B_INTER_PARITY
+       bic     r0, r0, #PJ4B_STATIC_BP
+       mcr     p15, 1, r0, c15, c1, 1
+
+       /* Auxiliary Debug Modes Control 2 Register */
+       mrc     p15, 1, r0, c15, c1, 2
+       bic     r0, r0, #PJ4B_FAST_LDR
+       orr     r0, r0, #PJ4B_AUX_DBG_CTRL2
+       mcr     p15, 1, r0, c15, c1, 2
+
+       /* Auxiliary Functional Modes Control Register 0 */
+       mrc     p15, 1, r0, c15, c2, 0
+#ifdef CONFIG_SMP
+       orr     r0, r0, #PJ4B_SMP_CFB
+#endif
+       orr     r0, r0, #PJ4B_L1_PAR_CHK
+       orr     r0, r0, #PJ4B_BROADCAST_CACHE
+       mcr     p15, 1, r0, c15, c2, 0
+
+       /* Auxiliary Debug Modes Control 0 Register */
+       mrc     p15, 1, r0, c15, c1, 0
+       orr     r0, r0, #PJ4B_WFI_WFE
+       mcr     p15, 1, r0, c15, c1, 0
+
+#endif /* CONFIG_CPU_PJ4B */
+
 __v7_setup:
        adr     r12, __v7_setup_stack           @ the local stack
        stmia   r12, {r0-r5, r7, r9, r11, lr}
@@ -342,6 +399,16 @@ __v7_ca9mp_proc_info:
        .long   0xff0ffff0
        __v7_proc __v7_ca9mp_setup
        .size   __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
+
+       /*
+        * Marvell PJ4B processor.
+        */
+       .type   __v7_pj4b_proc_info, #object
+__v7_pj4b_proc_info:
+       .long   0x562f5840
+       .long   0xfffffff0
+       __v7_proc __v7_pj4b_setup
+       .size   __v7_pj4b_proc_info, . - __v7_pj4b_proc_info
 #endif /* CONFIG_ARM_LPAE */
 
        /*
index 3a77b30f53d4550707a4744642b2fad1e128df38..a3367b783fc7f84c973a2dea20526dd7fc9d0a66 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/memblock.h>
 #include <linux/io.h>
 #include <linux/omapfb.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/map.h>
 
@@ -105,7 +106,7 @@ static struct platform_device omap_fb_device = {
        .id             = -1,
        .dev = {
                .dma_mask               = &omap_fb_dma_mask,
-               .coherent_dma_mask      = ~(u32)0,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
                .platform_data          = &omapfb_config,
        },
        .num_resources = 0,
@@ -141,7 +142,7 @@ static struct platform_device omap_fb_device = {
        .id             = -1,
        .dev = {
                .dma_mask               = &omap_fb_dma_mask,
-               .coherent_dma_mask      = ~(u32)0,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
                .platform_data          = &omapfb_config,
        },
        .num_resources = 0,
diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h
deleted file mode 100644 (file)
index 4d65b7d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __OMAP_VRAM_H__
-#define __OMAP_VRAM_H__
-
-#include <linux/types.h>
-
-extern int omap_vram_add_region(unsigned long paddr, size_t size);
-extern int omap_vram_free(unsigned long paddr, size_t size);
-extern int omap_vram_alloc(size_t size, unsigned long *paddr);
-extern int omap_vram_reserve(unsigned long paddr, size_t size);
-extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
-               unsigned long *largest_free_block);
-
-#ifdef CONFIG_OMAP2_VRAM
-extern void omap_vram_set_sdram_vram(u32 size, u32 start);
-
-extern void omap_vram_reserve_sdram_memblock(void);
-#else
-static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
-
-static inline void omap_vram_reserve_sdram_memblock(void) { }
-#endif
-
-#endif
index a7b8060c293a47d2394515c4751e9ea5f0311d6e..febe3862873ca2238aaaccf3265991c97fe5384c 100644 (file)
@@ -42,6 +42,8 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
 #define WIN_REMAP_LO_OFF       0x0008
 #define WIN_REMAP_HI_OFF       0x000c
 
+#define ATTR_HW_COHERENCY      (0x1 << 4)
+
 /*
  * Default implementation
  */
@@ -163,6 +165,8 @@ void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
                        w = &orion_mbus_dram_info.cs[cs++];
                        w->cs_index = i;
                        w->mbus_attr = 0xf & ~(1 << i);
+                       if (cfg->hw_io_coherency)
+                               w->mbus_attr |= ATTR_HW_COHERENCY;
                        w->base = base & 0xffff0000;
                        w->size = (size | 0x0000ffff) + 1;
                }
index b8a688cad4c277119281b44b629a9bcfc8eb0717..2d4b6414609f6edf2df165ccb14b01527246ad93 100644 (file)
@@ -606,26 +606,6 @@ void __init orion_wdt_init(void)
  ****************************************************************************/
 static u64 orion_xor_dmamask = DMA_BIT_MASK(32);
 
-void __init orion_xor_init_channels(
-       struct mv_xor_platform_data *orion_xor0_data,
-       struct platform_device *orion_xor0_channel,
-       struct mv_xor_platform_data *orion_xor1_data,
-       struct platform_device *orion_xor1_channel)
-{
-       /*
-        * two engines can't do memset simultaneously, this limitation
-        * satisfied by removing memset support from one of the engines.
-        */
-       dma_cap_set(DMA_MEMCPY, orion_xor0_data->cap_mask);
-       dma_cap_set(DMA_XOR, orion_xor0_data->cap_mask);
-       platform_device_register(orion_xor0_channel);
-
-       dma_cap_set(DMA_MEMCPY, orion_xor1_data->cap_mask);
-       dma_cap_set(DMA_MEMSET, orion_xor1_data->cap_mask);
-       dma_cap_set(DMA_XOR, orion_xor1_data->cap_mask);
-       platform_device_register(orion_xor1_channel);
-}
-
 /*****************************************************************************
  * XOR0
  ****************************************************************************/
@@ -636,61 +616,30 @@ static struct resource orion_xor0_shared_resources[] = {
        }, {
                .name   = "xor 0 high",
                .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "irq channel 0",
+               .flags  = IORESOURCE_IRQ,
+       }, {
+               .name   = "irq channel 1",
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
-static struct platform_device orion_xor0_shared = {
-       .name           = MV_XOR_SHARED_NAME,
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(orion_xor0_shared_resources),
-       .resource       = orion_xor0_shared_resources,
-};
+static struct mv_xor_channel_data orion_xor0_channels_data[2];
 
-static struct resource orion_xor00_resources[] = {
-       [0] = {
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct mv_xor_platform_data orion_xor00_data = {
-       .shared         = &orion_xor0_shared,
-       .hw_id          = 0,
-       .pool_size      = PAGE_SIZE,
+static struct mv_xor_platform_data orion_xor0_pdata = {
+       .channels = orion_xor0_channels_data,
 };
 
-static struct platform_device orion_xor00_channel = {
+static struct platform_device orion_xor0_shared = {
        .name           = MV_XOR_NAME,
        .id             = 0,
-       .num_resources  = ARRAY_SIZE(orion_xor00_resources),
-       .resource       = orion_xor00_resources,
-       .dev            = {
-               .dma_mask               = &orion_xor_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(64),
-               .platform_data          = &orion_xor00_data,
-       },
-};
-
-static struct resource orion_xor01_resources[] = {
-       [0] = {
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct mv_xor_platform_data orion_xor01_data = {
-       .shared         = &orion_xor0_shared,
-       .hw_id          = 1,
-       .pool_size      = PAGE_SIZE,
-};
-
-static struct platform_device orion_xor01_channel = {
-       .name           = MV_XOR_NAME,
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(orion_xor01_resources),
-       .resource       = orion_xor01_resources,
-       .dev            = {
-               .dma_mask               = &orion_xor_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(64),
-               .platform_data          = &orion_xor01_data,
+       .num_resources  = ARRAY_SIZE(orion_xor0_shared_resources),
+       .resource       = orion_xor0_shared_resources,
+       .dev            = {
+               .dma_mask               = &orion_xor_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(64),
+               .platform_data          = &orion_xor0_pdata,
        },
 };
 
@@ -704,15 +653,23 @@ void __init orion_xor0_init(unsigned long mapbase_low,
        orion_xor0_shared_resources[1].start = mapbase_high;
        orion_xor0_shared_resources[1].end = mapbase_high + 0xff;
 
-       orion_xor00_resources[0].start = irq_0;
-       orion_xor00_resources[0].end = irq_0;
-       orion_xor01_resources[0].start = irq_1;
-       orion_xor01_resources[0].end = irq_1;
+       orion_xor0_shared_resources[2].start = irq_0;
+       orion_xor0_shared_resources[2].end = irq_0;
+       orion_xor0_shared_resources[3].start = irq_1;
+       orion_xor0_shared_resources[3].end = irq_1;
 
-       platform_device_register(&orion_xor0_shared);
+       /*
+        * two engines can't do memset simultaneously, this limitation
+        * satisfied by removing memset support from one of the engines.
+        */
+       dma_cap_set(DMA_MEMCPY, orion_xor0_channels_data[0].cap_mask);
+       dma_cap_set(DMA_XOR, orion_xor0_channels_data[0].cap_mask);
+
+       dma_cap_set(DMA_MEMSET, orion_xor0_channels_data[1].cap_mask);
+       dma_cap_set(DMA_MEMCPY, orion_xor0_channels_data[1].cap_mask);
+       dma_cap_set(DMA_XOR, orion_xor0_channels_data[1].cap_mask);
 
-       orion_xor_init_channels(&orion_xor00_data, &orion_xor00_channel,
-                               &orion_xor01_data, &orion_xor01_channel);
+       platform_device_register(&orion_xor0_shared);
 }
 
 /*****************************************************************************
@@ -725,61 +682,30 @@ static struct resource orion_xor1_shared_resources[] = {
        }, {
                .name   = "xor 1 high",
                .flags  = IORESOURCE_MEM,
+       }, {
+               .name   = "irq channel 0",
+               .flags  = IORESOURCE_IRQ,
+       }, {
+               .name   = "irq channel 1",
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
-static struct platform_device orion_xor1_shared = {
-       .name           = MV_XOR_SHARED_NAME,
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(orion_xor1_shared_resources),
-       .resource       = orion_xor1_shared_resources,
-};
-
-static struct resource orion_xor10_resources[] = {
-       [0] = {
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct mv_xor_platform_data orion_xor10_data = {
-       .shared         = &orion_xor1_shared,
-       .hw_id          = 0,
-       .pool_size      = PAGE_SIZE,
-};
-
-static struct platform_device orion_xor10_channel = {
-       .name           = MV_XOR_NAME,
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(orion_xor10_resources),
-       .resource       = orion_xor10_resources,
-       .dev            = {
-               .dma_mask               = &orion_xor_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(64),
-               .platform_data          = &orion_xor10_data,
-       },
-};
-
-static struct resource orion_xor11_resources[] = {
-       [0] = {
-               .flags  = IORESOURCE_IRQ,
-       },
-};
+static struct mv_xor_channel_data orion_xor1_channels_data[2];
 
-static struct mv_xor_platform_data orion_xor11_data = {
-       .shared         = &orion_xor1_shared,
-       .hw_id          = 1,
-       .pool_size      = PAGE_SIZE,
+static struct mv_xor_platform_data orion_xor1_pdata = {
+       .channels = orion_xor1_channels_data,
 };
 
-static struct platform_device orion_xor11_channel = {
+static struct platform_device orion_xor1_shared = {
        .name           = MV_XOR_NAME,
-       .id             = 3,
-       .num_resources  = ARRAY_SIZE(orion_xor11_resources),
-       .resource       = orion_xor11_resources,
-       .dev            = {
-               .dma_mask               = &orion_xor_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(64),
-               .platform_data          = &orion_xor11_data,
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(orion_xor1_shared_resources),
+       .resource       = orion_xor1_shared_resources,
+       .dev            = {
+               .dma_mask               = &orion_xor_dmamask,
+               .coherent_dma_mask      = DMA_BIT_MASK(64),
+               .platform_data          = &orion_xor1_pdata,
        },
 };
 
@@ -793,15 +719,23 @@ void __init orion_xor1_init(unsigned long mapbase_low,
        orion_xor1_shared_resources[1].start = mapbase_high;
        orion_xor1_shared_resources[1].end = mapbase_high + 0xff;
 
-       orion_xor10_resources[0].start = irq_0;
-       orion_xor10_resources[0].end = irq_0;
-       orion_xor11_resources[0].start = irq_1;
-       orion_xor11_resources[0].end = irq_1;
+       orion_xor1_shared_resources[2].start = irq_0;
+       orion_xor1_shared_resources[2].end = irq_0;
+       orion_xor1_shared_resources[3].start = irq_1;
+       orion_xor1_shared_resources[3].end = irq_1;
 
-       platform_device_register(&orion_xor1_shared);
+       /*
+        * two engines can't do memset simultaneously, this limitation
+        * satisfied by removing memset support from one of the engines.
+        */
+       dma_cap_set(DMA_MEMCPY, orion_xor1_channels_data[0].cap_mask);
+       dma_cap_set(DMA_XOR, orion_xor1_channels_data[0].cap_mask);
 
-       orion_xor_init_channels(&orion_xor10_data, &orion_xor10_channel,
-                               &orion_xor11_data, &orion_xor11_channel);
+       dma_cap_set(DMA_MEMSET, orion_xor1_channels_data[1].cap_mask);
+       dma_cap_set(DMA_MEMCPY, orion_xor1_channels_data[1].cap_mask);
+       dma_cap_set(DMA_XOR, orion_xor1_channels_data[1].cap_mask);
+
+       platform_device_register(&orion_xor1_shared);
 }
 
 /*****************************************************************************
index ec63e4a627d07c3f007bdc897a4c5daa55c2860e..b76c06569fe5c122ada0a7f7ff5fda83937c8507 100644 (file)
@@ -17,6 +17,7 @@ struct orion_addr_map_cfg {
        const int num_wins;     /* Total number of windows */
        const int remappable_wins;
        void __iomem *bridge_virt_base;
+       int hw_io_coherency;
 
        /* If NULL, the default cpu_win_can_remap will be used, using
           the value in remappable_wins */
index 6bbc3fe5f58eec878490bc31c8173e336a644d1b..e06fc5fefa14c9ec7d0b46b002da64bc8cb425f8 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mv643xx_eth.h>
 
 struct dsa_platform_data;
+struct mv_sata_platform_data;
 
 void __init orion_uart0_init(void __iomem *membase,
                             resource_size_t mapbase,
index 0abd1c4698875f4edbb5be3cd506206c676019b6..ba3e76c9550489d18a50c8b9d4931c225c5edb73 100644 (file)
@@ -325,7 +325,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
 
        chan->state = S3C2410_DMA_RUNNING;
 
-       /* check wether there is anything to load, and if not, see
+       /* check whether there is anything to load, and if not, see
         * if we can find anything to load
         */
 
index 012bbd0b8d81063fa7db1547f440b7ca97adca74..47c9fad43f00124ce8e78e3f04b141f716034cd6 100644 (file)
@@ -389,6 +389,72 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal)
 
 static struct dentry *clk_debugfs_root;
 
+static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
+{
+       struct clk *child;
+       const char *state;
+       char buf[255] = { 0 };
+       int n = 0;
+
+       if (c->name)
+               n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
+
+       if (c->devname)
+               n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
+
+       state = (c->usage > 0) ? "on" : "off";
+
+       seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
+                  level * 3 + 1, "",
+                  50 - level * 3, buf,
+                  state, c->usage, clk_get_rate(c));
+
+       list_for_each_entry(child, &clocks, list) {
+               if (child->parent != c)
+                       continue;
+
+               clock_tree_show_one(s, child, level + 1);
+       }
+}
+
+static int clock_tree_show(struct seq_file *s, void *data)
+{
+       struct clk *c;
+       unsigned long flags;
+
+       seq_printf(s, " clock state ref rate\n");
+       seq_printf(s, "----------------------------------------------------\n");
+
+       spin_lock_irqsave(&clocks_lock, flags);
+
+       list_for_each_entry(c, &clocks, list)
+               if (c->parent == NULL)
+                       clock_tree_show_one(s, c, 0);
+
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return 0;
+}
+
+static int clock_tree_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clock_tree_show, inode->i_private);
+}
+
+static const struct file_operations clock_tree_fops = {
+       .open           = clock_tree_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int clock_rate_show(void *data, u64 *val)
+{
+       struct clk *c = data;
+       *val = clk_get_rate(c);
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
+
 static int clk_debugfs_register_one(struct clk *c)
 {
        int err;
@@ -411,7 +477,7 @@ static int clk_debugfs_register_one(struct clk *c)
                goto err_out;
        }
 
-       d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+       d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
        if (!d) {
                err = -ENOMEM;
                goto err_out;
@@ -446,13 +512,18 @@ static int __init clk_debugfs_init(void)
 {
        struct clk *c;
        struct dentry *d;
-       int err;
+       int err = -ENOMEM;
 
        d = debugfs_create_dir("clock", NULL);
        if (!d)
                return -ENOMEM;
        clk_debugfs_root = d;
 
+       d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
+                                &clock_tree_fops);
+       if (!d)
+               goto err_out;
+
        list_for_each_entry(c, &clocks, list) {
                err = clk_debugfs_register(c);
                if (err)
index bc50b20a8ffc5163f699304eb58dabedf3d82578..51afedda9ab61fd761114d79422fb2e34d6e138b 100644 (file)
@@ -146,15 +146,6 @@ struct platform_device s3c_device_camif = {
 
 /* ASOC DMA */
 
-struct platform_device samsung_asoc_dma = {
-       .name           = "samsung-audio",
-       .id             = -1,
-       .dev            = {
-               .dma_mask               = &samsung_device_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       }
-};
-
 struct platform_device samsung_asoc_idma = {
        .name           = "samsung-idma",
        .id             = -1,
index f53beba2b63df952770e50d51f71c7bca9560e23..87d501ff332852124b48180793f3d7e86ef2bbe6 100644 (file)
@@ -132,7 +132,6 @@ extern struct platform_device exynos4_device_pcm1;
 extern struct platform_device exynos4_device_pcm2;
 extern struct platform_device exynos4_device_spdif;
 
-extern struct platform_device samsung_asoc_dma;
 extern struct platform_device samsung_asoc_idma;
 extern struct platform_device samsung_device_keypad;
 
index 2607bd05c525ed12f4821064529269a7ae4169f2..01e88532a5db43931026d1ae307250ebb0a65732 100644 (file)
@@ -5,5 +5,5 @@
 # Common support
 obj-y  := restart.o time.o
 
-obj-$(CONFIG_ARCH_SPEAR3XX)    += pl080.o shirq.o
+obj-$(CONFIG_ARCH_SPEAR3XX)    += pl080.o
 obj-$(CONFIG_ARCH_SPEAR6XX)    += pl080.o
diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h
deleted file mode 100644 (file)
index 88a7fbd..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/shirq.h
- *
- * SPEAr platform shared irq layer header file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_SHIRQ_H
-#define __PLAT_SHIRQ_H
-
-#include <linux/irq.h>
-#include <linux/types.h>
-
-/*
- * struct shirq_dev_config: shared irq device configuration
- *
- * virq: virtual irq number of device
- * enb_mask: enable mask of device
- * status_mask: status mask of device
- * clear_mask: clear mask of device
- */
-struct shirq_dev_config {
-       u32 virq;
-       u32 enb_mask;
-       u32 status_mask;
-       u32 clear_mask;
-};
-
-/*
- * struct shirq_regs: shared irq register configuration
- *
- * base: base address of shared irq register
- * enb_reg: enable register offset
- * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
- * status_reg: status register offset
- * status_reg_mask: status register valid mask
- * clear_reg: clear register offset
- * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
- */
-struct shirq_regs {
-       void __iomem *base;
-       u32 enb_reg;
-       u32 reset_to_enb;
-       u32 status_reg;
-       u32 status_reg_mask;
-       u32 clear_reg;
-       u32 reset_to_clear;
-};
-
-/*
- * struct spear_shirq: shared irq structure
- *
- * irq: hardware irq number
- * dev_config: array of device config structures which are using "irq" line
- * dev_count: size of dev_config array
- * regs: register configuration for shared irq block
- */
-struct spear_shirq {
-       u32 irq;
-       struct shirq_dev_config *dev_config;
-       u32 dev_count;
-       struct shirq_regs regs;
-};
-
-int spear_shirq_register(struct spear_shirq *shirq);
-
-#endif /* __PLAT_SHIRQ_H */
diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c
deleted file mode 100644 (file)
index 853e891..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * arch/arm/plat-spear/shirq.c
- *
- * SPEAr platform shared irq layer source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/spinlock.h>
-#include <plat/shirq.h>
-
-struct spear_shirq *shirq;
-static DEFINE_SPINLOCK(lock);
-
-static void shirq_irq_mask(struct irq_data *d)
-{
-       struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
-       u32 val, id = d->irq - shirq->dev_config[0].virq;
-       unsigned long flags;
-
-       if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
-               return;
-
-       spin_lock_irqsave(&lock, flags);
-       val = readl(shirq->regs.base + shirq->regs.enb_reg);
-       if (shirq->regs.reset_to_enb)
-               val |= shirq->dev_config[id].enb_mask;
-       else
-               val &= ~(shirq->dev_config[id].enb_mask);
-       writel(val, shirq->regs.base + shirq->regs.enb_reg);
-       spin_unlock_irqrestore(&lock, flags);
-}
-
-static void shirq_irq_unmask(struct irq_data *d)
-{
-       struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
-       u32 val, id = d->irq - shirq->dev_config[0].virq;
-       unsigned long flags;
-
-       if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
-               return;
-
-       spin_lock_irqsave(&lock, flags);
-       val = readl(shirq->regs.base + shirq->regs.enb_reg);
-       if (shirq->regs.reset_to_enb)
-               val &= ~(shirq->dev_config[id].enb_mask);
-       else
-               val |= shirq->dev_config[id].enb_mask;
-       writel(val, shirq->regs.base + shirq->regs.enb_reg);
-       spin_unlock_irqrestore(&lock, flags);
-}
-
-static struct irq_chip shirq_chip = {
-       .name           = "spear_shirq",
-       .irq_ack        = shirq_irq_mask,
-       .irq_mask       = shirq_irq_mask,
-       .irq_unmask     = shirq_irq_unmask,
-};
-
-static void shirq_handler(unsigned irq, struct irq_desc *desc)
-{
-       u32 i, val, mask;
-       struct spear_shirq *shirq = irq_get_handler_data(irq);
-
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-       while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
-                               shirq->regs.status_reg_mask)) {
-               for (i = 0; (i < shirq->dev_count) && val; i++) {
-                       if (!(shirq->dev_config[i].status_mask & val))
-                               continue;
-
-                       generic_handle_irq(shirq->dev_config[i].virq);
-
-                       /* clear interrupt */
-                       val &= ~shirq->dev_config[i].status_mask;
-                       if ((shirq->regs.clear_reg == -1) ||
-                                       shirq->dev_config[i].clear_mask == -1)
-                               continue;
-                       mask = readl(shirq->regs.base + shirq->regs.clear_reg);
-                       if (shirq->regs.reset_to_clear)
-                               mask &= ~shirq->dev_config[i].clear_mask;
-                       else
-                               mask |= shirq->dev_config[i].clear_mask;
-                       writel(mask, shirq->regs.base + shirq->regs.clear_reg);
-               }
-       }
-       desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-int spear_shirq_register(struct spear_shirq *shirq)
-{
-       int i;
-
-       if (!shirq || !shirq->dev_config || !shirq->regs.base)
-               return -EFAULT;
-
-       if (!shirq->dev_count)
-               return -EINVAL;
-
-       irq_set_chained_handler(shirq->irq, shirq_handler);
-       for (i = 0; i < shirq->dev_count; i++) {
-               irq_set_chip_and_handler(shirq->dev_config[i].virq,
-                                        &shirq_chip, handle_simple_irq);
-               set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
-               irq_set_chip_data(shirq->dev_config[i].virq, shirq);
-       }
-
-       irq_set_handler_data(shirq->irq, shirq);
-       return 0;
-}
index f57609275449e704892101a514ecc40ee3021a3c..7a32976fa2a3644af886006478aa791cf1f3779f 100644 (file)
@@ -8,6 +8,8 @@
 #include <xen/features.h>
 #include <xen/platform_pci.h>
 #include <xen/xenbus.h>
+#include <xen/page.h>
+#include <xen/xen-ops.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 #include <linux/interrupt.h>
@@ -17,6 +19,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 
+#include <linux/mm.h>
+
 struct start_info _xen_start_info;
 struct start_info *xen_start_info = &_xen_start_info;
 EXPORT_SYMBOL_GPL(xen_start_info);
@@ -29,6 +33,10 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
 
+/* These are unused until we support booting "pre-ballooned" */
+unsigned long xen_released_pages;
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
+
 /* TODO: to be removed */
 __read_mostly int xen_have_vector_callback;
 EXPORT_SYMBOL_GPL(xen_have_vector_callback);
@@ -38,15 +46,106 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
 
 static __read_mostly int xen_events_irq = -1;
 
+/* map fgmfn of domid to lpfn in the current domain */
+static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn,
+                           unsigned int domid)
+{
+       int rc;
+       struct xen_add_to_physmap_range xatp = {
+               .domid = DOMID_SELF,
+               .foreign_domid = domid,
+               .size = 1,
+               .space = XENMAPSPACE_gmfn_foreign,
+       };
+       xen_ulong_t idx = fgmfn;
+       xen_pfn_t gpfn = lpfn;
+
+       set_xen_guest_handle(xatp.idxs, &idx);
+       set_xen_guest_handle(xatp.gpfns, &gpfn);
+
+       rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+       if (rc) {
+               pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n",
+                       rc, lpfn, fgmfn);
+               return 1;
+       }
+       return 0;
+}
+
+struct remap_data {
+       xen_pfn_t fgmfn; /* foreign domain's gmfn */
+       pgprot_t prot;
+       domid_t  domid;
+       struct vm_area_struct *vma;
+       int index;
+       struct page **pages;
+       struct xen_remap_mfn_info *info;
+};
+
+static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
+                       void *data)
+{
+       struct remap_data *info = data;
+       struct page *page = info->pages[info->index++];
+       unsigned long pfn = page_to_pfn(page);
+       pte_t pte = pfn_pte(pfn, info->prot);
+
+       if (map_foreign_page(pfn, info->fgmfn, info->domid))
+               return -EFAULT;
+       set_pte_at(info->vma->vm_mm, addr, ptep, pte);
+
+       return 0;
+}
+
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
                               unsigned long addr,
-                              unsigned long mfn, int nr,
-                              pgprot_t prot, unsigned domid)
+                              xen_pfn_t mfn, int nr,
+                              pgprot_t prot, unsigned domid,
+                              struct page **pages)
 {
-       return -ENOSYS;
+       int err;
+       struct remap_data data;
+
+       /* TBD: Batching, current sole caller only does page at a time */
+       if (nr > 1)
+               return -EINVAL;
+
+       data.fgmfn = mfn;
+       data.prot = prot;
+       data.domid = domid;
+       data.vma = vma;
+       data.index = 0;
+       data.pages = pages;
+       err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
+                                 remap_pte_fn, &data);
+       return err;
 }
 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
 
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+                              int nr, struct page **pages)
+{
+       int i;
+
+       for (i = 0; i < nr; i++) {
+               struct xen_remove_from_physmap xrp;
+               unsigned long rc, pfn;
+
+               pfn = page_to_pfn(pages[i]);
+
+               xrp.domid = DOMID_SELF;
+               xrp.gpfn = pfn;
+               rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+               if (rc) {
+                       pr_warn("Failed to unmap pfn:%lx rc:%ld\n",
+                               pfn, rc);
+                       return rc;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
+
 /*
  * see Documentation/devicetree/bindings/arm/xen.txt for the
  * documentation of the Xen Device Tree format.
@@ -149,24 +248,6 @@ static int __init xen_init_events(void)
 }
 postcore_initcall(xen_init_events);
 
-/* XXX: only until balloon is properly working */
-int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
-{
-       *pages = alloc_pages(highmem ? GFP_HIGHUSER : GFP_KERNEL,
-                       get_order(nr_pages));
-       if (*pages == NULL)
-               return -ENOMEM;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(alloc_xenballooned_pages);
-
-void free_xenballooned_pages(int nr_pages, struct page **pages)
-{
-       kfree(*pages);
-       *pages = NULL;
-}
-EXPORT_SYMBOL_GPL(free_xenballooned_pages);
-
 /* In the hypervisor.S file. */
 EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
index 101b33ee9bbab914d75a7e2295feb6a57290aafa..95a4f1b676cead2006dfa3b44280020b4cb248ab 100644 (file)
@@ -56,7 +56,7 @@ config SEC_IRQ_PRIORITY_LEVELS
        default 7
        range 0 7
        help
-         Devide the total number of interrupt priority levels into sub-levels.
+         Divide the total number of interrupt priority levels into sub-levels.
          There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different levels.
 
 endmenu
index 342e378da1ece760b2c2b3531780cad9b897b95a..1f3b3ef3e103fbe3581670a62d03db2c5da9e153 100644 (file)
@@ -191,7 +191,7 @@ static irqreturn_t l2_ecc_err(int irq, void *dev_id)
 {
        int status;
 
-       printk(KERN_ERR "L2 ecc error happend\n");
+       printk(KERN_ERR "L2 ecc error happened\n");
        status = bfin_read32(L2CTL0_STAT);
        if (status & 0x1)
                printk(KERN_ERR "Core channel error type:0x%x, addr:0x%x\n",
index 7d345947b3ee271f0bc9d5206431d419d56f470c..ca2675ae08ed95d1c3de56ad0a507af390b348e3 100644 (file)
@@ -142,7 +142,7 @@ __asm__ ( \
  * it here, we would not get the multiple_irq at all.
  *
  * The non-blocking here is based on the knowledge that the timer interrupt is 
- * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
+ * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
  * be an sti() before the timer irq handler is run to acknowledge the interrupt.
  */
 
index b31e9984f84964570b16e743892f4432af730269..fe3cdd22bed4590315268c156e28076c26cff238 100644 (file)
@@ -103,7 +103,7 @@ __asm__ (                           \
  * if we had BLOCK'edit here, we would not get the multiple_irq at all.
  *
  * The non-blocking here is based on the knowledge that the timer interrupt is
- * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
+ * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
  * be an sti() before the timer irq handler is run to acknowledge the interrupt.
  */
 #define BUILD_TIMER_IRQ(nr, mask)      \
index 4fb63a36bd52ff0333f9d849a0a75479008aaa5e..f6084bc524e85e578487d34dea06f0e23b4a8214 100644 (file)
@@ -77,7 +77,7 @@ void __set_pmd(pmd_t *pmdptr, unsigned long pmd)
  * checks at dup_mmap(), exec(), and other mmlist addition points
  * could be used. The locking scheme was chosen on the basis of
  * manfred's recommendations and having no core impact whatsoever.
- * -- wli
+ * -- nyc
  */
 DEFINE_SPINLOCK(pgd_lock);
 struct page *pgd_list;
index 8b3a9c0e771dc3926131b428ba2472a337d41845..bd1c515550389819abbe8322f897154bd391d9a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * kvm_ia64.c: Basic KVM suppport On Itanium series processors
+ * kvm_ia64.c: Basic KVM support On Itanium series processors
  *
  *
  *     Copyright (C) 2007, Intel Corporation.
@@ -1330,6 +1330,11 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        return -EINVAL;
@@ -1362,11 +1367,9 @@ static void kvm_release_vm_pages(struct kvm *kvm)
        struct kvm_memslots *slots;
        struct kvm_memory_slot *memslot;
        int j;
-       unsigned long base_gfn;
 
        slots = kvm_memslots(kvm);
        kvm_for_each_memslot(memslot, slots) {
-               base_gfn = memslot->base_gfn;
                for (j = 0; j < memslot->npages; j++) {
                        if (memslot->rmap[j])
                                put_page((struct page *)memslot->rmap[j]);
index ffc0601a2a19f2a0d195bc750e21ef23cd4a0d23..93ef0346b209c961606c31acfe6791c710721aed 100644 (file)
@@ -28,8 +28,8 @@ config ZORRO
          Linux use these.
 
 config AMIGA_PCMCIA
-       bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
-       depends on AMIGA && EXPERIMENTAL
+       bool "Amiga 1200/600 PCMCIA support"
+       depends on AMIGA
        help
          Include support in the kernel for pcmcia on Amiga 1200 and Amiga
          600. If you intend to use pcmcia cards say Y; otherwise say N.
index c4eb79edecec04d58d5ad681c389118a3472cec5..2f2d87b40341fc859506a2a3489faefeb60d902f 100644 (file)
@@ -274,9 +274,8 @@ endif # COLDFIRE
 comment "Processor Specific Options"
 
 config M68KFPU_EMU
-       bool "Math emulation support (EXPERIMENTAL)"
+       bool "Math emulation support"
        depends on MMU
-       depends on EXPERIMENTAL
        help
          At some point in the future, this will cause floating-point math
          instructions to be emulated by the kernel on machines that lack a
index 87233acef18bea1d20a8f67b471bfd7654f56ff0..fa12283d58fccdd0f92638ff75996bf8debc845a 100644 (file)
@@ -41,7 +41,7 @@ config NO_KERNEL_MSG
 
 config BDM_DISABLE
        bool "Disable BDM signals"
-       depends on (EXPERIMENTAL && COLDFIRE)
+       depends on COLDFIRE
        help
          Disable the ColdFire CPU's BDM signals.
 
index 04a3d9be90e946b27c7407b7a033712c15695d37..c4cdfe444c64817f01eac43b561ab6096e44ae24 100644 (file)
@@ -60,8 +60,8 @@ endmenu
 menu "Character devices"
 
 config ATARI_DSP56K
-       tristate "Atari DSP56k support (EXPERIMENTAL)"
-       depends on ATARI && EXPERIMENTAL
+       tristate "Atari DSP56k support"
+       depends on ATARI
        help
          If you want to be able to use the DSP56001 in Falcons, say Y. This
          driver is still experimental, and if you don't know what it is, or
@@ -87,7 +87,7 @@ config HPDCA
 
 config HPAPCI
        tristate "HP APCI serial support"
-       depends on HP300 && SERIAL_8250 && EXPERIMENTAL
+       depends on HP300 && SERIAL_8250
        help
          If you want to use the internal "APCI" serial ports on an HP400
          machine, say Y here.
index 7f1949c0e089e37bae15a368cda041ade22e509c..c7933e41f10d7a5d864731467bc6435d0eb0b5a5 100644 (file)
@@ -7,6 +7,7 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
 generic-y += futex.h
+generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
@@ -21,8 +22,11 @@ generic-y += percpu.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
+generic-y += shmparam.h
 generic-y += siginfo.h
+generic-y += spinlock.h
 generic-y += statfs.h
+generic-y += termios.h
 generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += types.h
diff --git a/arch/m68k/include/asm/hw_irq.h b/arch/m68k/include/asm/hw_irq.h
deleted file mode 100644 (file)
index eacef09..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_M68K_HW_IRQ_H
-#define __ASM_M68K_HW_IRQ_H
-
-/* Dummy include. */
-
-#endif
diff --git a/arch/m68k/include/asm/shmparam.h b/arch/m68k/include/asm/shmparam.h
deleted file mode 100644 (file)
index 558892a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_SHMPARAM_H
-#define _M68K_SHMPARAM_H
-
-#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
-
-#endif /* _M68K_SHMPARAM_H */
diff --git a/arch/m68k/include/asm/spinlock.h b/arch/m68k/include/asm/spinlock.h
deleted file mode 100644 (file)
index 20f46e2..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __M68K_SPINLOCK_H
-#define __M68K_SPINLOCK_H
-
-#error "m68k doesn't do SMP yet"
-
-#endif
diff --git a/arch/m68k/include/asm/termios.h b/arch/m68k/include/asm/termios.h
deleted file mode 100644 (file)
index ad8efb0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _M68K_TERMIOS_H
-#define _M68K_TERMIOS_H
-
-#include <uapi/asm/termios.h>
-
-/*     intr=^C         quit=^|         erase=del       kill=^U
-       eof=^D          vtime=\0        vmin=\1         sxtc=\0
-       start=^Q        stop=^S         susp=^Z         eol=\0
-       reprint=^R      discard=^U      werase=^W       lnext=^V
-       eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-       unsigned short tmp; \
-       get_user(tmp, &(termio)->c_iflag); \
-       (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
-       get_user(tmp, &(termio)->c_oflag); \
-       (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
-       get_user(tmp, &(termio)->c_cflag); \
-       (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
-       get_user(tmp, &(termio)->c_lflag); \
-       (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
-       get_user((termios)->c_line, &(termio)->c_line); \
-       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-       put_user((termios)->c_iflag, &(termio)->c_iflag); \
-       put_user((termios)->c_oflag, &(termio)->c_oflag); \
-       put_user((termios)->c_cflag, &(termio)->c_cflag); \
-       put_user((termios)->c_lflag, &(termio)->c_lflag); \
-       put_user((termios)->c_line,  &(termio)->c_line); \
-       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#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 /* _M68K_TERMIOS_H */
index 972bce120e1e94b8550408f788e0502ecd3d308f..1fef45ada0973c7d83494f42c0c780ebc18f5ca3 100644 (file)
@@ -1,26 +1,27 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += auxvec.h
+generic-y += msgbuf.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += termbits.h
+generic-y += termios.h
+
 header-y += a.out.h
-header-y += auxvec.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += fcntl.h
 header-y += ioctls.h
-header-y += msgbuf.h
 header-y += param.h
 header-y += poll.h
 header-y += posix_types.h
 header-y += ptrace.h
-header-y += sembuf.h
 header-y += setup.h
-header-y += shmbuf.h
 header-y += sigcontext.h
 header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
 header-y += stat.h
 header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
 header-y += unistd.h
diff --git a/arch/m68k/include/uapi/asm/auxvec.h b/arch/m68k/include/uapi/asm/auxvec.h
deleted file mode 100644 (file)
index 844d6d5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMm68k_AUXVEC_H
-#define __ASMm68k_AUXVEC_H
-
-#endif
diff --git a/arch/m68k/include/uapi/asm/msgbuf.h b/arch/m68k/include/uapi/asm/msgbuf.h
deleted file mode 100644 (file)
index 243cb79..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _M68K_MSGBUF_H
-#define _M68K_MSGBUF_H
-
-/*
- * The msqid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned long   __unused1;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned long   __unused2;
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned long   __unused3;
-       unsigned long  msg_cbytes;      /* current number of bytes on queue */
-       unsigned long  msg_qnum;        /* number of messages in queue */
-       unsigned long  msg_qbytes;      /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-#endif /* _M68K_MSGBUF_H */
diff --git a/arch/m68k/include/uapi/asm/sembuf.h b/arch/m68k/include/uapi/asm/sembuf.h
deleted file mode 100644 (file)
index 2308052..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _M68K_SEMBUF_H
-#define _M68K_SEMBUF_H
-
-/*
- * The semid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems;              /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SEMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/shmbuf.h b/arch/m68k/include/uapi/asm/shmbuf.h
deleted file mode 100644 (file)
index f8928d6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _M68K_SHMBUF_H
-#define _M68K_SHMBUF_H
-
-/*
- * The shmid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
deleted file mode 100644 (file)
index 285da3b..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-#define SO_GET_FILTER          SO_ATTACH_FILTER
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#define SO_TIMESTAMPING                37
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#define SO_PROTOCOL            38
-#define SO_DOMAIN              39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS         41
-#define SCM_WIFI_STATUS                SO_WIFI_STATUS
-#define SO_PEEK_OFF            42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS               43
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/uapi/asm/sockios.h b/arch/m68k/include/uapi/asm/sockios.h
deleted file mode 100644 (file)
index c04a239..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_M68K_SOCKIOS__
-#define __ARCH_M68K_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* __ARCH_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/uapi/asm/termbits.h b/arch/m68k/include/uapi/asm/termbits.h
deleted file mode 100644 (file)
index aea1e37..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_M68K_TERMBITS_H__
-#define __ARCH_M68K_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-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 */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-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];                /* 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];                /* 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 VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-#define CBAUD  0010017
-#define  B0    0000000         /* hang up */
-#define  B50   0000001
-#define  B75   0000002
-#define  B110  0000003
-#define  B134  0000004
-#define  B150  0000005
-#define  B200  0000006
-#define  B300  0000007
-#define  B600  0000010
-#define  B1200 0000011
-#define  B1800 0000012
-#define  B2400 0000013
-#define  B4800 0000014
-#define  B9600 0000015
-#define  B19200        0000016
-#define  B38400        0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define   CS5  0000000
-#define   CS6  0000020
-#define   CS7  0000040
-#define   CS8  0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD   002003600000          /* input baud rate */
-#define CMSPAR   010000000000          /* mark or space (stick) parity */
-#define CRTSCTS          020000000000          /* flow control */
-
-#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC        0200000
-
-
-/* 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 /* __ARCH_M68K_TERMBITS_H__ */
diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h
deleted file mode 100644 (file)
index ce2142c..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _UAPI_M68K_TERMIOS_H
-#define _UAPI_M68K_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_M68K_TERMIOS_H */
index 388e5cc895990ec7d7d0e838f0f1de0d78f1105d..cbc624af4494dfcbf0d5516282697f3b9a92e9bf 100644 (file)
@@ -506,7 +506,7 @@ static inline void bus_error030 (struct frame *fp)
                addr -= 2;
 
        if (buserr_type & SUN3_BUSERR_INVALID) {
-               if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
+               if (!mmu_emu_handle_fault(addr, 1, 0))
                        do_page_fault (&fp->ptregs, addr, 0);
        } else {
 #ifdef DEBUG
index 3384a5244fbdc147155278729ef979eca593c3b2..0663067870f2a9166dbdacb001cbeefdb97b37a7 100644 (file)
@@ -50,7 +50,7 @@ fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
         * sqrt(m*2^e) =
         *               sqrt(2*m) * 2^(p)      , if e = 2*p + 1
         *
-        * So we use the last bit of the exponent to decide wether to
+        * So we use the last bit of the exponent to decide whether to
         * use the m or 2*m.
         *
         * Since only the fractional part of the mantissa is stored and
index 27b5ce089a34f5e33afae745490f3462311482e2..f0e05bce92f2533ee8dc78ade768595d825646df 100644 (file)
@@ -1,5 +1,225 @@
+/*
+ *  linux/arch/m68k/mm/init.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  Contains common initialization routines, specific init code moved
+ *  to motorola.c and sun3mmu.c
+ */
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#ifdef CONFIG_ATARI
+#include <asm/atari_stram.h>
+#endif
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+/*
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+void *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
 #ifdef CONFIG_MMU
-#include "init_mm.c"
+
+pg_data_t pg_data_map[MAX_NUMNODES];
+EXPORT_SYMBOL(pg_data_map);
+
+int m68k_virt_to_node_shift;
+
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+pg_data_t *pg_data_table[65];
+EXPORT_SYMBOL(pg_data_table);
+#endif
+
+void __init m68k_setup_node(int node)
+{
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+       struct mem_info *info = m68k_memory + node;
+       int i, end;
+
+       i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
+       end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
+       for (; i <= end; i++) {
+               if (pg_data_table[i])
+                       printk("overlap at %u for chunk %u\n", i, node);
+               pg_data_table[i] = pg_data_map + node;
+       }
+#endif
+       pg_data_map[node].bdata = bootmem_node_data + node;
+       node_set_online(node);
+}
+
+extern void init_pointer_table(unsigned long ptable);
+extern pmd_t *zero_pgtable;
+
+#else /* CONFIG_MMU */
+
+/*
+ * paging_init() continues the virtual memory environment setup which
+ * was begun by the code in arch/head.S.
+ * The parameters are pointers to where to stick the starting and ending
+ * addresses of available kernel virtual memory.
+ */
+void __init paging_init(void)
+{
+       /*
+        * Make sure start_mem is page aligned, otherwise bootmem and
+        * page_alloc get different views of the world.
+        */
+       unsigned long end_mem = memory_end & PAGE_MASK;
+       unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+
+       high_memory = (void *) end_mem;
+
+       empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+       memset(empty_zero_page, 0, PAGE_SIZE);
+
+       /*
+        * Set up SFC/DFC registers (user data space).
+        */
+       set_fs (USER_DS);
+
+       zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
+       free_area_init(zones_size);
+}
+
+#endif /* CONFIG_MMU */
+
+void free_initmem(void)
+{
+#ifndef CONFIG_MMU_SUN3
+       unsigned long addr;
+
+       addr = (unsigned long) __init_begin;
+       for (; addr < ((unsigned long) __init_end); addr += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(addr));
+               init_page_count(virt_to_page(addr));
+               free_page(addr);
+               totalram_pages++;
+       }
+       pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
+               (addr - (unsigned long) __init_begin) >> 10,
+               (unsigned int) __init_begin, (unsigned int) __init_end);
+#endif /* CONFIG_MMU_SUN3 */
+}
+
+#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
+#define VECTORS        &vectors[0]
 #else
-#include "init_no.c"
+#define VECTORS        _ramvec
+#endif
+
+void __init print_memmap(void)
+{
+#define UL(x) ((unsigned long) (x))
+#define MLK(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 10
+#define MLM(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 20
+#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), 1024)
+
+       pr_notice("Virtual kernel memory layout:\n"
+               "    vector  : 0x%08lx - 0x%08lx   (%4ld KiB)\n"
+               "    kmap    : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
+               "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
+               "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
+               "      .init : 0x%p" " - 0x%p" "   (%4d KiB)\n"
+               "      .text : 0x%p" " - 0x%p" "   (%4d KiB)\n"
+               "      .data : 0x%p" " - 0x%p" "   (%4d KiB)\n"
+               "      .bss  : 0x%p" " - 0x%p" "   (%4d KiB)\n",
+               MLK(VECTORS, VECTORS + 256),
+               MLM(KMAP_START, KMAP_END),
+               MLM(VMALLOC_START, VMALLOC_END),
+               MLM(PAGE_OFFSET, (unsigned long)high_memory),
+               MLK_ROUNDUP(__init_begin, __init_end),
+               MLK_ROUNDUP(_stext, _etext),
+               MLK_ROUNDUP(_sdata, _edata),
+               MLK_ROUNDUP(__bss_start, __bss_stop));
+}
+
+void __init mem_init(void)
+{
+       pg_data_t *pgdat;
+       int codepages = 0;
+       int datapages = 0;
+       int initpages = 0;
+       int i;
+
+       /* this will put all memory onto the freelists */
+       totalram_pages = num_physpages = 0;
+       for_each_online_pgdat(pgdat) {
+               num_physpages += pgdat->node_present_pages;
+
+               totalram_pages += free_all_bootmem_node(pgdat);
+               for (i = 0; i < pgdat->node_spanned_pages; i++) {
+                       struct page *page = pgdat->node_mem_map + i;
+                       char *addr = page_to_virt(page);
+
+                       if (!PageReserved(page))
+                               continue;
+                       if (addr >= _text &&
+                           addr < _etext)
+                               codepages++;
+                       else if (addr >= __init_begin &&
+                                addr < __init_end)
+                               initpages++;
+                       else
+                               datapages++;
+               }
+       }
+
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+       /* insert pointer tables allocated so far into the tablelist */
+       init_pointer_table((unsigned long)kernel_pg_dir);
+       for (i = 0; i < PTRS_PER_PGD; i++) {
+               if (pgd_present(kernel_pg_dir[i]))
+                       init_pointer_table(__pgd_page(kernel_pg_dir[i]));
+       }
+
+       /* insert also pointer table that we used to unmap the zero page */
+       if (zero_pgtable)
+               init_pointer_table((unsigned long)zero_pgtable);
+#endif
+
+       pr_info("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
+              nr_free_pages() << (PAGE_SHIFT-10),
+              totalram_pages << (PAGE_SHIFT-10),
+              codepages << (PAGE_SHIFT-10),
+              datapages << (PAGE_SHIFT-10),
+              initpages << (PAGE_SHIFT-10));
+       print_memmap();
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+       int pages = 0;
+       for (; start < end; start += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(start));
+               init_page_count(virt_to_page(start));
+               free_page(start);
+               totalram_pages++;
+               pages++;
+       }
+       pr_notice("Freeing initrd memory: %dk freed\n",
+               pages << (PAGE_SHIFT - 10));
+}
 #endif
diff --git a/arch/m68k/mm/init_mm.c b/arch/m68k/mm/init_mm.c
deleted file mode 100644 (file)
index 282f9de..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *  linux/arch/m68k/mm/init.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  Contains common initialization routines, specific init code moved
- *  to motorola.c and sun3mmu.c
- */
-
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#ifdef CONFIG_ATARI
-#include <asm/atari_stram.h>
-#endif
-#include <asm/sections.h>
-#include <asm/tlb.h>
-
-pg_data_t pg_data_map[MAX_NUMNODES];
-EXPORT_SYMBOL(pg_data_map);
-
-int m68k_virt_to_node_shift;
-
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-pg_data_t *pg_data_table[65];
-EXPORT_SYMBOL(pg_data_table);
-#endif
-
-void __init m68k_setup_node(int node)
-{
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-       struct mem_info *info = m68k_memory + node;
-       int i, end;
-
-       i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
-       end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
-       for (; i <= end; i++) {
-               if (pg_data_table[i])
-                       printk("overlap at %u for chunk %u\n", i, node);
-               pg_data_table[i] = pg_data_map + node;
-       }
-#endif
-       pg_data_map[node].bdata = bootmem_node_data + node;
-       node_set_online(node);
-}
-
-
-/*
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-
-void *empty_zero_page;
-EXPORT_SYMBOL(empty_zero_page);
-
-extern void init_pointer_table(unsigned long ptable);
-
-/* References to section boundaries */
-
-extern pmd_t *zero_pgtable;
-
-#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
-#define VECTORS        &vectors[0]
-#else
-#define VECTORS        _ramvec
-#endif
-
-void __init print_memmap(void)
-{
-#define UL(x) ((unsigned long) (x))
-#define MLK(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 10
-#define MLM(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 20
-#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), 1024)
-
-       pr_notice("Virtual kernel memory layout:\n"
-               "    vector  : 0x%08lx - 0x%08lx   (%4ld KiB)\n"
-               "    kmap    : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
-               "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
-               "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
-               "      .init : 0x%p" " - 0x%p" "   (%4d KiB)\n"
-               "      .text : 0x%p" " - 0x%p" "   (%4d KiB)\n"
-               "      .data : 0x%p" " - 0x%p" "   (%4d KiB)\n"
-               "      .bss  : 0x%p" " - 0x%p" "   (%4d KiB)\n",
-               MLK(VECTORS, VECTORS + 256),
-               MLM(KMAP_START, KMAP_END),
-               MLM(VMALLOC_START, VMALLOC_END),
-               MLM(PAGE_OFFSET, (unsigned long)high_memory),
-               MLK_ROUNDUP(__init_begin, __init_end),
-               MLK_ROUNDUP(_stext, _etext),
-               MLK_ROUNDUP(_sdata, _edata),
-               MLK_ROUNDUP(__bss_start, __bss_stop));
-}
-
-void __init mem_init(void)
-{
-       pg_data_t *pgdat;
-       int codepages = 0;
-       int datapages = 0;
-       int initpages = 0;
-       int i;
-
-       /* this will put all memory onto the freelists */
-       totalram_pages = num_physpages = 0;
-       for_each_online_pgdat(pgdat) {
-               num_physpages += pgdat->node_present_pages;
-
-               totalram_pages += free_all_bootmem_node(pgdat);
-               for (i = 0; i < pgdat->node_spanned_pages; i++) {
-                       struct page *page = pgdat->node_mem_map + i;
-                       char *addr = page_to_virt(page);
-
-                       if (!PageReserved(page))
-                               continue;
-                       if (addr >= _text &&
-                           addr < _etext)
-                               codepages++;
-                       else if (addr >= __init_begin &&
-                                addr < __init_end)
-                               initpages++;
-                       else
-                               datapages++;
-               }
-       }
-
-#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
-       /* insert pointer tables allocated so far into the tablelist */
-       init_pointer_table((unsigned long)kernel_pg_dir);
-       for (i = 0; i < PTRS_PER_PGD; i++) {
-               if (pgd_present(kernel_pg_dir[i]))
-                       init_pointer_table(__pgd_page(kernel_pg_dir[i]));
-       }
-
-       /* insert also pointer table that we used to unmap the zero page */
-       if (zero_pgtable)
-               init_pointer_table((unsigned long)zero_pgtable);
-#endif
-
-       printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
-              nr_free_pages() << (PAGE_SHIFT-10),
-              totalram_pages << (PAGE_SHIFT-10),
-              codepages << (PAGE_SHIFT-10),
-              datapages << (PAGE_SHIFT-10),
-              initpages << (PAGE_SHIFT-10));
-       print_memmap();
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       int pages = 0;
-       for (; start < end; start += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(start));
-               init_page_count(virt_to_page(start));
-               free_page(start);
-               totalram_pages++;
-               pages++;
-       }
-       printk ("Freeing initrd memory: %dk freed\n", pages);
-}
-#endif
diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c
deleted file mode 100644 (file)
index 688e366..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *  linux/arch/m68knommu/mm/init.c
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com) 
- *
- *  Based on:
- *
- *  linux/arch/m68k/mm/init.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
- *  DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
- */
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/init.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/sections.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-
-/*
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-void *empty_zero_page;
-
-/*
- * paging_init() continues the virtual memory environment setup which
- * was begun by the code in arch/head.S.
- * The parameters are pointers to where to stick the starting and ending
- * addresses of available kernel virtual memory.
- */
-void __init paging_init(void)
-{
-       /*
-        * Make sure start_mem is page aligned, otherwise bootmem and
-        * page_alloc get different views of the world.
-        */
-       unsigned long end_mem   = memory_end & PAGE_MASK;
-       unsigned long zones_size[MAX_NR_ZONES] = {0, };
-
-       empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
-       memset(empty_zero_page, 0, PAGE_SIZE);
-
-       /*
-        * Set up SFC/DFC registers (user data space).
-        */
-       set_fs (USER_DS);
-
-       zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
-       free_area_init(zones_size);
-}
-
-void __init mem_init(void)
-{
-       int codek = 0, datak = 0, initk = 0;
-       unsigned long tmp;
-       unsigned long len = _ramend - _rambase;
-       unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
-       unsigned long end_mem   = memory_end; /* DAVIDM - this must not include kernel stack at top */
-
-       pr_debug("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
-
-       end_mem &= PAGE_MASK;
-       high_memory = (void *) end_mem;
-
-       start_mem = PAGE_ALIGN(start_mem);
-       max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
-
-       /* this will put all memory onto the freelists */
-       totalram_pages = free_all_bootmem();
-
-       codek = (_etext - _stext) >> 10;
-       datak = (__bss_stop - _sdata) >> 10;
-       initk = (__init_begin - __init_end) >> 10;
-
-       tmp = nr_free_pages() << PAGE_SHIFT;
-       printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
-              tmp >> 10,
-              len >> 10,
-              codek,
-              datak
-              );
-}
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       int pages = 0;
-       for (; start < end; start += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(start));
-               init_page_count(virt_to_page(start));
-               free_page(start);
-               totalram_pages++;
-               pages++;
-       }
-       pr_notice("Freeing initrd memory: %luk freed\n",
-                 pages * (PAGE_SIZE / 1024));
-}
-#endif
-
-void free_initmem(void)
-{
-#ifdef CONFIG_RAMKERNEL
-       unsigned long addr;
-       /*
-        * The following code should be cool even if these sections
-        * are not page aligned.
-        */
-       addr = PAGE_ALIGN((unsigned long) __init_begin);
-       /* next to check that the page we free is not a partial page */
-       for (; addr + PAGE_SIZE < ((unsigned long) __init_end); addr += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(addr));
-               init_page_count(virt_to_page(addr));
-               free_page(addr);
-               totalram_pages++;
-       }
-       pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
-                       (addr - PAGE_ALIGN((unsigned long) __init_begin)) >> 10,
-                       (int)(PAGE_ALIGN((unsigned long) __init_begin)),
-                       (int)(addr - PAGE_SIZE));
-#endif
-}
-
index 875b800ef0ddb765d9785ecb9d179eb919526c92..f58fafe7e4c9f37980c84bab6e4360120c9da88a 100644 (file)
@@ -29,10 +29,6 @@ atomic_t nr_free_contexts;
 struct mm_struct *context_mm[LAST_CONTEXT+1];
 extern unsigned long num_pages;
 
-void free_initmem(void)
-{
-}
-
 /*
  * ColdFire paging_init derived from sun3.
  */
index 0dafa693515b880450835d9a9fe87f68c87389c2..251c5437787be6054086b4d5586adfc0887e0472 100644 (file)
@@ -304,17 +304,3 @@ void __init paging_init(void)
        }
 }
 
-void free_initmem(void)
-{
-       unsigned long addr;
-
-       addr = (unsigned long)__init_begin;
-       for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
-               virt_to_page(addr)->flags &= ~(1 << PG_reserved);
-               init_page_count(virt_to_page(addr));
-               free_page(addr);
-               totalram_pages++;
-       }
-}
-
-
index e0804060501e653d39392cd98e89a0e7f9e72695..269f81158a33108e9568e83f096acd9c750b1814 100644 (file)
@@ -30,10 +30,6 @@ const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
 
 extern unsigned long num_pages;
 
-void free_initmem(void)
-{
-}
-
 /* For the sun3 we try to follow the i386 paging_init() more closely */
 /* start_mem and end_mem have PAGE_OFFSET added already */
 /* now sets up tables using sun3 PTEs rather than i386 as before. --m */
index 78b60f53e90af7f668dd64ab3cf9071a66d59276..6bbca30c91884850e45cc07db24b4b17a00b06e5 100644 (file)
@@ -66,6 +66,8 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
+       sun3_disable_irq(5);
+       sun3_enable_irq(5);
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
@@ -79,41 +81,18 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
 
 static irqreturn_t sun3_vec255(int irq, void *dev_id)
 {
-//     intersil_clear();
        return IRQ_HANDLED;
 }
 
-static void sun3_irq_enable(struct irq_data *data)
-{
-    sun3_enable_irq(data->irq);
-};
-
-static void sun3_irq_disable(struct irq_data *data)
-{
-    sun3_disable_irq(data->irq);
-};
-
-static struct irq_chip sun3_irq_chip = {
-       .name           = "sun3",
-       .irq_startup    = m68k_irq_startup,
-       .irq_shutdown   = m68k_irq_shutdown,
-       .irq_enable     = sun3_irq_enable,
-       .irq_disable    = sun3_irq_disable,
-       .irq_mask       = sun3_irq_disable,
-       .irq_unmask     = sun3_irq_enable,
-};
-
 void __init sun3_init_IRQ(void)
 {
        *sun3_intreg = 1;
 
-       m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
-                                 7);
        m68k_setup_user_interrupt(VEC_USER, 128);
 
-       if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
+       if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "clock", NULL))
                pr_err("Couldn't register %s interrupt\n", "int5");
-       if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
+       if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "nmi", NULL))
                pr_err("Couldn't register %s interrupt\n", "int7");
        if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
                pr_err("Couldn't register %s interrupt\n", "vec255");
index eb3a46c096fe57baf3075dfda129dd75187d4e43..d3c51a6a601dd2017c5ce6a03b86aae95cfe78b7 100644 (file)
@@ -1,6 +1,4 @@
-include include/asm-generic/Kbuild.asm
 
-header-y  += elf.h
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/auxvec.h b/arch/microblaze/include/asm/auxvec.h
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/arch/microblaze/include/asm/bitsperlong.h b/arch/microblaze/include/asm/bitsperlong.h
deleted file mode 100644 (file)
index 6dc0bb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h
deleted file mode 100644 (file)
index 3190276..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_MICROBLAZE_BYTEORDER_H
-#define _ASM_MICROBLAZE_BYTEORDER_H
-
-#ifdef __MICROBLAZEEL__
-#include <linux/byteorder/little_endian.h>
-#else
-#include <linux/byteorder/big_endian.h>
-#endif
-
-#endif /* _ASM_MICROBLAZE_BYTEORDER_H */
index 640ddd4b6a9b2cf6bc58e159a46bf9490069e188..659024449064887f303966e707d255b2faed4220 100644 (file)
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_ELF_H
 #define _ASM_MICROBLAZE_ELF_H
 
-/*
- * Note there is no "official" ELF designation for Microblaze.
- * I've snaffled the value from the microblaze binutils source code
- * /binutils/microblaze/include/elf/microblaze.h
- */
-#define EM_MICROBLAZE          189
-#define EM_MICROBLAZE_OLD      0xbaab
-#define ELF_ARCH               EM_MICROBLAZE
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x)      ((x)->e_machine == EM_MICROBLAZE \
-                                || (x)->e_machine == EM_MICROBLAZE_OLD)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS      ELFCLASS32
+#include <uapi/asm/elf.h>
 
 #ifndef __uClinux__
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/byteorder.h>
-
 #ifndef ELF_GREG_T
-#define ELF_GREG_T
-typedef unsigned long elf_greg_t;
 #endif
-
 #ifndef ELF_NGREG
-#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
 #endif
-
 #ifndef ELF_GREGSET_T
-#define ELF_GREGSET_T
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #endif
-
 #ifndef ELF_FPREGSET_T
-#define ELF_FPREGSET_T
-
-/* TBD */
-#define ELF_NFPREG     33      /* includes fsr */
-typedef unsigned long elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-
-/* typedef struct user_fpu_struct elf_fpregset_t; */
 #endif
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
- * use of this is to invoke "./ld.so someprog" to test out a new version of
- * the loader.  We need to make sure that it is out of the way of the program
- * that it will "exec", and that there is sufficient room for the brk.
- */
-
-#define ELF_ET_DYN_BASE         (0x08000000)
-
 #ifdef __MICROBLAZEEL__
-#define ELF_DATA       ELFDATA2LSB
 #else
-#define ELF_DATA       ELFDATA2MSB
 #endif
-
-#define ELF_EXEC_PAGESIZE      PAGE_SIZE
-
-
-#define ELF_CORE_COPY_REGS(_dest, _regs)                       \
-       memcpy((char *) &_dest, (char *) _regs,         \
-       sizeof(struct pt_regs));
-
-/* This yields a mask that user programs can use to figure out what
- * instruction set this CPU supports.  This could be done in user space,
- * but it's not easy, and we've already done it here.
- */
-#define ELF_HWCAP      (0)
-
-/* This yields a string that ld.so will use to load implementation
- * specific libraries for optimization.  This is more specific in
- * intent than poking at uname or /proc/cpuinfo.
-
- * For the moment, we have only optimizations for the Intel generations,
- * but that could change...
- */
-#define ELF_PLATFORM  (NULL)
-
-/* Added _f parameter. Is this definition correct: TBD */
-#define ELF_PLAT_INIT(_r, _f)                          \
-do {                                                   \
-       _r->r1 =  _r->r1 =  _r->r2 =  _r->r3 =          \
-       _r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =          \
-       _r->r8 =  _r->r9 =  _r->r10 = _r->r11 =         \
-       _r->r12 = _r->r13 = _r->r14 = _r->r15 =         \
-       _r->r16 = _r->r17 = _r->r18 = _r->r19 =         \
-       _r->r20 = _r->r21 = _r->r22 = _r->r23 =         \
-       _r->r24 = _r->r25 = _r->r26 = _r->r27 =         \
-       _r->r28 = _r->r29 = _r->r30 = _r->r31 =         \
-       0;                                              \
-} while (0)
-
-#ifdef __KERNEL__
 #define SET_PERSONALITY(ex) \
        set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
-#endif
-
 #endif /* __uClinux__ */
-
 #endif /* _ASM_MICROBLAZE_ELF_H */
index af0144b91b79c36382e986b76d956492fd4bbd25..b4a4cb150aa998af14d3d359db7c2b73f26397db 100644 (file)
@@ -29,6 +29,8 @@ DECLARE_PER_CPU(unsigned int, KM); /* Kernel/user mode */
 DECLARE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */
 DECLARE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */
 DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
+
+extern asmlinkage void do_notify_resume(struct pt_regs *regs, int in_syscall);
 # endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_MICROBLAZE_ENTRY_H */
diff --git a/arch/microblaze/include/asm/errno.h b/arch/microblaze/include/asm/errno.h
deleted file mode 100644 (file)
index 4c82b50..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/microblaze/include/asm/fcntl.h b/arch/microblaze/include/asm/fcntl.h
deleted file mode 100644 (file)
index 46ab12d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
diff --git a/arch/microblaze/include/asm/ioctl.h b/arch/microblaze/include/asm/ioctl.h
deleted file mode 100644 (file)
index b279fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/microblaze/include/asm/ioctls.h b/arch/microblaze/include/asm/ioctls.h
deleted file mode 100644 (file)
index ec34c76..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctls.h>
diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h
deleted file mode 100644 (file)
index 84c7e51..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/microblaze/include/asm/kvm_para.h b/arch/microblaze/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/microblaze/include/asm/mman.h b/arch/microblaze/include/asm/mman.h
deleted file mode 100644 (file)
index 8eebf89..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/microblaze/include/asm/msgbuf.h b/arch/microblaze/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 809134c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/msgbuf.h>
diff --git a/arch/microblaze/include/asm/param.h b/arch/microblaze/include/asm/param.h
deleted file mode 100644 (file)
index 965d454..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
diff --git a/arch/microblaze/include/asm/poll.h b/arch/microblaze/include/asm/poll.h
deleted file mode 100644 (file)
index c98509d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff --git a/arch/microblaze/include/asm/posix_types.h b/arch/microblaze/include/asm/posix_types.h
deleted file mode 100644 (file)
index 0e15039..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
-#define _ASM_MICROBLAZE_POSIX_TYPES_H
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
index 94e92c8058592f786cfd6fac942c90b308664e85..3732bcf186fd5b6a3438464b9a570a914501fdc0 100644 (file)
@@ -5,56 +5,12 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_PTRACE_H
 #define _ASM_MICROBLAZE_PTRACE_H
 
-#ifndef __ASSEMBLY__
-
-typedef unsigned long microblaze_reg_t;
+#include <uapi/asm/ptrace.h>
 
-struct pt_regs {
-       microblaze_reg_t r0;
-       microblaze_reg_t r1;
-       microblaze_reg_t r2;
-       microblaze_reg_t r3;
-       microblaze_reg_t r4;
-       microblaze_reg_t r5;
-       microblaze_reg_t r6;
-       microblaze_reg_t r7;
-       microblaze_reg_t r8;
-       microblaze_reg_t r9;
-       microblaze_reg_t r10;
-       microblaze_reg_t r11;
-       microblaze_reg_t r12;
-       microblaze_reg_t r13;
-       microblaze_reg_t r14;
-       microblaze_reg_t r15;
-       microblaze_reg_t r16;
-       microblaze_reg_t r17;
-       microblaze_reg_t r18;
-       microblaze_reg_t r19;
-       microblaze_reg_t r20;
-       microblaze_reg_t r21;
-       microblaze_reg_t r22;
-       microblaze_reg_t r23;
-       microblaze_reg_t r24;
-       microblaze_reg_t r25;
-       microblaze_reg_t r26;
-       microblaze_reg_t r27;
-       microblaze_reg_t r28;
-       microblaze_reg_t r29;
-       microblaze_reg_t r30;
-       microblaze_reg_t r31;
-       microblaze_reg_t pc;
-       microblaze_reg_t msr;
-       microblaze_reg_t ear;
-       microblaze_reg_t esr;
-       microblaze_reg_t fsr;
-       int pt_mode;
-};
-
-#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 #define kernel_mode(regs)              ((regs)->pt_mode)
 #define user_mode(regs)                        (!kernel_mode(regs))
 
@@ -66,19 +22,5 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->r3;
 }
 
-#else /* __KERNEL__ */
-
-/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
-#define PT_GPR(n)      ((n) * sizeof(microblaze_reg_t))
-#define PT_PC          (32 * sizeof(microblaze_reg_t))
-#define PT_MSR         (33 * sizeof(microblaze_reg_t))
-#define PT_EAR         (34 * sizeof(microblaze_reg_t))
-#define PT_ESR         (35 * sizeof(microblaze_reg_t))
-#define PT_FSR         (36 * sizeof(microblaze_reg_t))
-#define PT_KERNEL_MODE (37 * sizeof(microblaze_reg_t))
-
-#endif /* __KERNEL */
-
 #endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_MICROBLAZE_PTRACE_H */
diff --git a/arch/microblaze/include/asm/resource.h b/arch/microblaze/include/asm/resource.h
deleted file mode 100644 (file)
index 04bc4db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/microblaze/include/asm/sembuf.h b/arch/microblaze/include/asm/sembuf.h
deleted file mode 100644 (file)
index 7673b83..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sembuf.h>
index 0061aa13a340a3ca8be926a2e056b4a808e923cc..0e0b0a5ec7568655e35a220635ffd07eac18f65e 100644 (file)
@@ -7,15 +7,12 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_SETUP_H
 #define _ASM_MICROBLAZE_SETUP_H
 
-#define COMMAND_LINE_SIZE      256
+#include <uapi/asm/setup.h>
 
 # ifndef __ASSEMBLY__
-
-#  ifdef __KERNEL__
 extern unsigned int boot_cpuid; /* move to smp.h */
 
 extern char cmd_line[COMMAND_LINE_SIZE];
@@ -53,6 +50,5 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end);
 extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
-#  endif/* __KERNEL__ */
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/asm/shmbuf.h b/arch/microblaze/include/asm/shmbuf.h
deleted file mode 100644 (file)
index 83c05fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmbuf.h>
diff --git a/arch/microblaze/include/asm/sigcontext.h b/arch/microblaze/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 55873c8..0000000
+++ /dev/null
@@ -1,20 +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_SIGCONTEXT_H
-#define _ASM_MICROBLAZE_SIGCONTEXT_H
-
-/* FIXME should be linux/ptrace.h */
-#include <asm/ptrace.h>
-
-struct sigcontext {
-       struct pt_regs regs;
-       unsigned long oldmask;
-};
-
-#endif /* _ASM_MICROBLAZE_SIGCONTEXT_H */
diff --git a/arch/microblaze/include/asm/siginfo.h b/arch/microblaze/include/asm/siginfo.h
deleted file mode 100644 (file)
index 0815d29..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/siginfo.h>
diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h
deleted file mode 100644 (file)
index 7b1573c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/signal.h>
diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h
deleted file mode 100644 (file)
index 6b71384..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/socket.h>
diff --git a/arch/microblaze/include/asm/sockios.h b/arch/microblaze/include/asm/sockios.h
deleted file mode 100644 (file)
index def6d47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sockios.h>
diff --git a/arch/microblaze/include/asm/stat.h b/arch/microblaze/include/asm/stat.h
deleted file mode 100644 (file)
index 3dc90fa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/stat.h>
diff --git a/arch/microblaze/include/asm/statfs.h b/arch/microblaze/include/asm/statfs.h
deleted file mode 100644 (file)
index 0b91fe1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/statfs.h>
diff --git a/arch/microblaze/include/asm/swab.h b/arch/microblaze/include/asm/swab.h
deleted file mode 100644 (file)
index 7847e56..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/swab.h>
diff --git a/arch/microblaze/include/asm/termbits.h b/arch/microblaze/include/asm/termbits.h
deleted file mode 100644 (file)
index 3935b10..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/microblaze/include/asm/termios.h b/arch/microblaze/include/asm/termios.h
deleted file mode 100644 (file)
index 280d78a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h
deleted file mode 100644 (file)
index b9e79bc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/types.h>
index ef25f7538d4a04090180c1062b5d1c965d06156e..927540d3cb7d1ee9ddb62a6b1b0915f758dc8761 100644 (file)
@@ -298,11 +298,10 @@ extern long __user_bad(void);
 
 #define __put_user_check(x, ptr, size)                                 \
 ({                                                                     \
-       typeof(*(ptr)) __pu_val;                                        \
+       typeof(*(ptr)) volatile __pu_val = x;                                   \
        typeof(*(ptr)) __user *__pu_addr = (ptr);                       \
        int __pu_err = 0;                                               \
                                                                        \
-       __pu_val = (x);                                                 \
        if (access_ok(VERIFY_WRITE, __pu_addr, size)) {                 \
                switch (size) {                                         \
                case 1:                                                 \
index 94d978986b756a61d026d87b98b6c50775e6faf2..99e23937a31aa05c0efec1b44588584490130808 100644 (file)
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_UNISTD_H
 #define _ASM_MICROBLAZE_UNISTD_H
 
-#define __NR_restart_syscall   0 /* ok */
-#define __NR_exit              1 /* ok */
-#define __NR_fork              2 /* not for no MMU - weird */
-#define __NR_read              3 /* ok */
-#define __NR_write             4 /* ok */
-#define __NR_open              5 /* openat */
-#define __NR_close             6 /* ok */
-#define __NR_waitpid           7 /* waitid */
-#define __NR_creat             8 /* openat */
-#define __NR_link              9 /* linkat */
-#define __NR_unlink            10 /* unlinkat */
-#define __NR_execve            11 /* ok */
-#define __NR_chdir             12 /* ok */
-#define __NR_time              13 /* obsolete -> sys_gettimeofday */
-#define __NR_mknod             14 /* mknodat */
-#define __NR_chmod             15 /* fchmodat */
-#define __NR_lchown            16 /* ok */
-#define __NR_break             17 /* don't know */
-#define __NR_oldstat           18 /* remove */
-#define __NR_lseek             19 /* ok */
-#define __NR_getpid            20 /* ok */
-#define __NR_mount             21 /* ok */
-#define __NR_umount            22 /* ok */  /* use only umount2 */
-#define __NR_setuid            23 /* ok */
-#define __NR_getuid            24 /* ok */
-#define __NR_stime             25 /* obsolete -> sys_settimeofday */
-#define __NR_ptrace            26 /* ok */
-#define __NR_alarm             27 /* obsolete -> sys_setitimer */
-#define __NR_oldfstat          28 /* remove */
-#define __NR_pause             29 /* obsolete -> sys_rt_sigtimedwait */
-#define __NR_utime             30 /* obsolete -> sys_utimesat */
-#define __NR_stty              31 /* remove */
-#define __NR_gtty              32 /* remove */
-#define __NR_access            33 /* faccessat */
-/* can be implemented by sys_setpriority */
-#define __NR_nice              34
-#define __NR_ftime             35 /* remove */
-#define __NR_sync              36 /* ok */
-#define __NR_kill              37 /* ok */
-#define __NR_rename            38 /* renameat */
-#define __NR_mkdir             39 /* mkdirat */
-#define __NR_rmdir             40 /* unlinkat */
-#define __NR_dup               41 /* ok */
-#define __NR_pipe              42 /* ok */
-#define __NR_times             43 /* ok */
-#define __NR_prof              44 /* remove */
-#define __NR_brk               45 /* ok -mmu, nommu specific */
-#define __NR_setgid            46 /* ok */
-#define __NR_getgid            47 /* ok */
-#define __NR_signal            48 /* obsolete -> sys_rt_sigaction */
-#define __NR_geteuid           49 /* ok */
-#define __NR_getegid           50 /* ok */
-#define __NR_acct              51 /* add it and then I can disable it */
-#define __NR_umount2           52 /* remove */
-#define __NR_lock              53 /* remove */
-#define __NR_ioctl             54 /* ok */
-#define __NR_fcntl             55 /* ok -> 64bit version*/
-#define __NR_mpx               56 /* remove */
-#define __NR_setpgid           57 /* ok */
-#define __NR_ulimit            58 /* remove */
-#define __NR_oldolduname       59 /* remove */
-#define __NR_umask             60 /* ok */
-#define __NR_chroot            61 /* ok */
-#define __NR_ustat             62 /* obsolete -> statfs64 */
-#define __NR_dup2              63 /* ok */
-#define __NR_getppid           64 /* ok */
-#define __NR_getpgrp           65 /* obsolete -> sys_getpgid */
-#define __NR_setsid            66 /* ok */
-#define __NR_sigaction         67 /* obsolete -> rt_sigaction */
-#define __NR_sgetmask          68 /* obsolete -> sys_rt_sigprocmask */
-#define __NR_ssetmask          69 /* obsolete ->sys_rt_sigprocmask */
-#define __NR_setreuid          70 /* ok */
-#define __NR_setregid          71 /* ok */
-#define __NR_sigsuspend                72 /* obsolete -> rt_sigsuspend */
-#define __NR_sigpending                73 /* obsolete -> sys_rt_sigpending */
-#define __NR_sethostname       74 /* ok */
-#define __NR_setrlimit         75 /* ok */
-#define __NR_getrlimit         76 /* ok Back compatible 2G limited rlimit */
-#define __NR_getrusage         77 /* ok */
-#define __NR_gettimeofday      78 /* ok */
-#define __NR_settimeofday      79 /* ok */
-#define __NR_getgroups         80 /* ok */
-#define __NR_setgroups         81 /* ok */
-#define __NR_select            82 /* obsolete -> sys_pselect7 */
-#define __NR_symlink           83 /* symlinkat */
-#define __NR_oldlstat          84 /* remove */
-#define __NR_readlink          85 /* obsolete -> sys_readlinkat */
-#define __NR_uselib            86 /* remove */
-#define __NR_swapon            87 /* ok */
-#define __NR_reboot            88 /* ok */
-#define __NR_readdir           89 /* remove ? */
-#define __NR_mmap              90 /* obsolete -> sys_mmap2 */
-#define __NR_munmap            91 /* ok - mmu and nommu */
-#define __NR_truncate          92 /* ok or truncate64 */
-#define __NR_ftruncate         93 /* ok or ftruncate64 */
-#define __NR_fchmod            94 /* ok */
-#define __NR_fchown            95 /* ok */
-#define __NR_getpriority       96 /* ok */
-#define __NR_setpriority       97 /* ok */
-#define __NR_profil            98 /* remove */
-#define __NR_statfs            99 /* ok or statfs64 */
-#define __NR_fstatfs           100  /* ok or fstatfs64 */
-#define __NR_ioperm            101 /* remove */
-#define __NR_socketcall                102 /* remove */
-#define __NR_syslog            103 /* ok */
-#define __NR_setitimer         104 /* ok */
-#define __NR_getitimer         105 /* ok */
-#define __NR_stat              106 /* remove */
-#define __NR_lstat             107 /* remove */
-#define __NR_fstat             108 /* remove */
-#define __NR_olduname          109 /* remove */
-#define __NR_iopl              110 /* remove */
-#define __NR_vhangup           111 /* ok */
-#define __NR_idle              112 /* remove */
-#define __NR_vm86old           113 /* remove */
-#define __NR_wait4             114 /* obsolete -> waitid */
-#define __NR_swapoff           115 /* ok */
-#define __NR_sysinfo           116 /* ok */
-#define __NR_ipc               117 /* remove - direct call */
-#define __NR_fsync             118 /* ok */
-#define __NR_sigreturn         119 /* obsolete -> sys_rt_sigreturn */
-#define __NR_clone             120 /* ok */
-#define __NR_setdomainname     121 /* ok */
-#define __NR_uname             122 /* remove */
-#define __NR_modify_ldt                123 /* remove */
-#define __NR_adjtimex          124 /* ok */
-#define __NR_mprotect          125 /* remove */
-#define __NR_sigprocmask       126 /* obsolete -> sys_rt_sigprocmask */
-#define __NR_create_module     127 /* remove */
-#define __NR_init_module       128 /* ok */
-#define __NR_delete_module     129 /* ok */
-#define __NR_get_kernel_syms   130 /* remove */
-#define __NR_quotactl          131 /* ok */
-#define __NR_getpgid           132 /* ok */
-#define __NR_fchdir            133 /* ok */
-#define __NR_bdflush           134 /* remove */
-#define __NR_sysfs             135 /* needed for busybox */
-#define __NR_personality       136 /* ok */
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138 /* ok */
-#define __NR_setfsgid          139 /* ok */
-#define __NR__llseek           140 /* remove only lseek */
-#define __NR_getdents          141 /* ok or getdents64 */
-#define __NR__newselect                142 /* remove */
-#define __NR_flock             143 /* ok */
-#define __NR_msync             144 /* remove */
-#define __NR_readv             145 /* ok */
-#define __NR_writev            146 /* ok */
-#define __NR_getsid            147 /* ok */
-#define __NR_fdatasync         148 /* ok */
-#define __NR__sysctl           149 /* remove */
-#define __NR_mlock             150 /* ok - nommu or mmu */
-#define __NR_munlock           151 /* ok - nommu or mmu */
-#define __NR_mlockall          152 /* ok - nommu or mmu */
-#define __NR_munlockall                153 /* ok - nommu or mmu */
-#define __NR_sched_setparam            154 /* ok */
-#define __NR_sched_getparam            155 /* ok */
-#define __NR_sched_setscheduler                156 /* ok */
-#define __NR_sched_getscheduler                157 /* ok */
-#define __NR_sched_yield               158 /* ok */
-#define __NR_sched_get_priority_max    159 /* ok */
-#define __NR_sched_get_priority_min    160 /* ok */
-#define __NR_sched_rr_get_interval     161 /* ok */
-#define __NR_nanosleep         162 /* ok */
-#define __NR_mremap            163 /* ok - nommu or mmu */
-#define __NR_setresuid         164 /* ok */
-#define __NR_getresuid         165 /* ok */
-#define __NR_vm86              166 /* remove */
-#define __NR_query_module      167 /* ok */
-#define __NR_poll              168 /* obsolete -> sys_ppoll */
-#define __NR_nfsservctl                169 /* ok */
-#define __NR_setresgid         170 /* ok */
-#define __NR_getresgid         171 /* ok */
-#define __NR_prctl             172 /* ok */
-#define __NR_rt_sigreturn      173 /* ok */
-#define __NR_rt_sigaction      174 /* ok */
-#define __NR_rt_sigprocmask    175 /* ok */
-#define __NR_rt_sigpending     176 /* ok */
-#define __NR_rt_sigtimedwait   177 /* ok */
-#define __NR_rt_sigqueueinfo   178 /* ok */
-#define __NR_rt_sigsuspend     179 /* ok */
-#define __NR_pread64           180 /* ok */
-#define __NR_pwrite64          181 /* ok */
-#define __NR_chown             182 /* obsolete -> fchownat */
-#define __NR_getcwd            183 /* ok */
-#define __NR_capget            184 /* ok */
-#define __NR_capset            185 /* ok */
-#define __NR_sigaltstack       186 /* remove */
-#define __NR_sendfile          187 /* ok -> exist 64bit version*/
-#define __NR_getpmsg           188 /* remove */
-/* remove - some people actually want streams */
-#define __NR_putpmsg           189
-/* for noMMU - group with clone -> maybe remove */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191 /* remove - SuS compliant getrlimit */
-#define __NR_mmap2             192 /* ok */
-#define __NR_truncate64                193 /* ok */
-#define __NR_ftruncate64       194 /* ok */
-#define __NR_stat64            195 /* remove _ARCH_WANT_STAT64 */
-#define __NR_lstat64           196 /* remove _ARCH_WANT_STAT64 */
-#define __NR_fstat64           197 /* remove _ARCH_WANT_STAT64 */
-#define __NR_lchown32          198 /* ok - without 32 */
-#define __NR_getuid32          199 /* ok - without 32 */
-#define __NR_getgid32          200 /* ok - without 32 */
-#define __NR_geteuid32         201 /* ok - without 32 */
-#define __NR_getegid32         202 /* ok - without 32 */
-#define __NR_setreuid32                203 /* ok - without 32 */
-#define __NR_setregid32                204 /* ok - without 32 */
-#define __NR_getgroups32       205 /* ok - without 32 */
-#define __NR_setgroups32       206 /* ok - without 32 */
-#define __NR_fchown32          207 /* ok - without 32 */
-#define __NR_setresuid32       208 /* ok - without 32 */
-#define __NR_getresuid32       209 /* ok - without 32 */
-#define __NR_setresgid32       210 /* ok - without 32 */
-#define __NR_getresgid32       211 /* ok - without 32 */
-#define __NR_chown32           212 /* ok - without 32 -obsolete -> fchownat */
-#define __NR_setuid32          213 /* ok - without 32 */
-#define __NR_setgid32          214 /* ok - without 32 */
-#define __NR_setfsuid32                215 /* ok - without 32 */
-#define __NR_setfsgid32                216 /* ok - without 32 */
-#define __NR_pivot_root                217 /* ok */
-#define __NR_mincore           218 /* ok */
-#define __NR_madvise           219 /* ok */
-#define __NR_getdents64                220 /* ok */
-#define __NR_fcntl64           221 /* ok */
-/* 223 is unused */
-#define __NR_gettid            224 /* ok */
-#define __NR_readahead         225 /* ok */
-#define __NR_setxattr          226 /* ok */
-#define __NR_lsetxattr         227 /* ok */
-#define __NR_fsetxattr         228 /* ok */
-#define __NR_getxattr          229 /* ok */
-#define __NR_lgetxattr         230 /* ok */
-#define __NR_fgetxattr         231 /* ok */
-#define __NR_listxattr         232 /* ok */
-#define __NR_llistxattr                233 /* ok */
-#define __NR_flistxattr                234 /* ok */
-#define __NR_removexattr       235 /* ok */
-#define __NR_lremovexattr      236 /* ok */
-#define __NR_fremovexattr      237 /* ok */
-#define __NR_tkill             238 /* ok */
-#define __NR_sendfile64                239 /* ok */
-#define __NR_futex             240 /* ok */
-#define __NR_sched_setaffinity 241 /* ok */
-#define __NR_sched_getaffinity 242 /* ok */
-#define __NR_set_thread_area   243 /* remove */
-#define __NR_get_thread_area   244 /* remove */
-#define __NR_io_setup          245 /* ok */
-#define __NR_io_destroy                246 /* ok */
-#define __NR_io_getevents      247 /* ok */
-#define __NR_io_submit         248 /* ok */
-#define __NR_io_cancel         249 /* ok */
-#define __NR_fadvise64         250 /* remove -> sys_fadvise64_64 */
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group                252 /* ok */
-#define __NR_lookup_dcookie    253 /* ok */
-#define __NR_epoll_create      254 /* ok */
-#define __NR_epoll_ctl         255 /* ok */
-#define __NR_epoll_wait                256 /* obsolete -> sys_epoll_pwait */
-#define __NR_remap_file_pages  257 /* only for mmu */
-#define __NR_set_tid_address   258 /* ok */
-#define __NR_timer_create      259 /* ok */
-#define __NR_timer_settime     (__NR_timer_create+1) /* 260 */ /* ok */
-#define __NR_timer_gettime     (__NR_timer_create+2) /* 261 */ /* ok */
-#define __NR_timer_getoverrun  (__NR_timer_create+3) /* 262 */ /* ok */
-#define __NR_timer_delete      (__NR_timer_create+4) /* 263 */ /* ok */
-#define __NR_clock_settime     (__NR_timer_create+5) /* 264 */ /* ok */
-#define __NR_clock_gettime     (__NR_timer_create+6) /* 265 */ /* ok */
-#define __NR_clock_getres      (__NR_timer_create+7) /* 266 */ /* ok */
-#define __NR_clock_nanosleep   (__NR_timer_create+8) /* 267 */ /* ok */
-#define __NR_statfs64          268 /* ok */
-#define __NR_fstatfs64         269 /* ok */
-#define __NR_tgkill            270 /* ok */
-#define __NR_utimes            271 /* obsolete -> sys_futimesat */
-#define __NR_fadvise64_64      272 /* ok */
-#define __NR_vserver           273 /* ok */
-#define __NR_mbind             274 /* only for mmu */
-#define __NR_get_mempolicy     275 /* only for mmu */
-#define __NR_set_mempolicy     276 /* only for mmu */
-#define __NR_mq_open           277 /* ok */
-#define __NR_mq_unlink         (__NR_mq_open+1) /* 278 */ /* ok */
-#define __NR_mq_timedsend      (__NR_mq_open+2) /* 279 */ /* ok */
-#define __NR_mq_timedreceive   (__NR_mq_open+3) /* 280 */ /* ok */
-#define __NR_mq_notify         (__NR_mq_open+4) /* 281 */ /* ok */
-#define __NR_mq_getsetattr     (__NR_mq_open+5) /* 282 */ /* ok */
-#define __NR_kexec_load                283 /* ok */
-#define __NR_waitid            284 /* ok */
-/* #define __NR_sys_setaltroot 285 */
-#define __NR_add_key           286 /* ok */
-#define __NR_request_key       287 /* ok */
-#define __NR_keyctl            288 /* ok */
-#define __NR_ioprio_set                289 /* ok */
-#define __NR_ioprio_get                290 /* ok */
-#define __NR_inotify_init      291 /* ok */
-#define __NR_inotify_add_watch 292 /* ok */
-#define __NR_inotify_rm_watch  293 /* ok */
-#define __NR_migrate_pages     294 /* mmu */
-#define __NR_openat            295 /* ok */
-#define __NR_mkdirat           296 /* ok */
-#define __NR_mknodat           297 /* ok */
-#define __NR_fchownat          298 /* ok */
-#define __NR_futimesat         299 /* obsolete -> sys_utimesat */
-#define __NR_fstatat64         300 /* stat64 */
-#define __NR_unlinkat          301 /* ok */
-#define __NR_renameat          302 /* ok */
-#define __NR_linkat            303 /* ok */
-#define __NR_symlinkat         304 /* ok */
-#define __NR_readlinkat                305 /* ok */
-#define __NR_fchmodat          306 /* ok */
-#define __NR_faccessat         307 /* ok */
-#define __NR_pselect6          308 /* obsolete -> sys_pselect7 */
-#define __NR_ppoll             309 /* ok */
-#define __NR_unshare           310 /* ok */
-#define __NR_set_robust_list   311 /* ok */
-#define __NR_get_robust_list   312 /* ok */
-#define __NR_splice            313 /* ok */
-#define __NR_sync_file_range   314 /* ok */
-#define __NR_tee               315 /* ok */
-#define __NR_vmsplice          316 /* ok */
-#define __NR_move_pages                317 /* mmu */
-#define __NR_getcpu            318 /* ok */
-#define __NR_epoll_pwait       319 /* ok */
-#define __NR_utimensat         320 /* ok */
-#define __NR_signalfd          321 /* ok */
-#define __NR_timerfd_create    322 /* ok */
-#define __NR_eventfd           323 /* ok */
-#define __NR_fallocate         324 /* ok */
-#define __NR_semtimedop                325 /* ok - semaphore group */
-#define __NR_timerfd_settime   326 /* ok */
-#define __NR_timerfd_gettime   327 /* ok */
-/* sysv ipc syscalls */
-#define __NR_semctl            328 /* ok */
-#define __NR_semget            329 /* ok */
-#define __NR_semop             330 /* ok */
-#define __NR_msgctl            331 /* ok */
-#define __NR_msgget            332 /* ok */
-#define __NR_msgrcv            333 /* ok */
-#define __NR_msgsnd            334 /* ok */
-#define __NR_shmat             335 /* ok */
-#define __NR_shmctl            336 /* ok */
-#define __NR_shmdt             337 /* ok */
-#define __NR_shmget            338 /* ok */
-
-
-#define __NR_signalfd4         339 /* new */
-#define __NR_eventfd2          340 /* new */
-#define __NR_epoll_create1     341 /* new */
-#define __NR_dup3              342 /* new */
-#define __NR_pipe2             343 /* new */
-#define __NR_inotify_init1     344 /* new */
-#define __NR_socket            345 /* new */
-#define __NR_socketpair                346 /* new */
-#define __NR_bind              347 /* new */
-#define __NR_listen            348 /* new */
-#define __NR_accept            349 /* new */
-#define __NR_connect           350 /* new */
-#define __NR_getsockname       351 /* new */
-#define __NR_getpeername       352 /* new */
-#define __NR_sendto            353 /* new */
-#define __NR_send              354 /* new */
-#define __NR_recvfrom          355 /* new */
-#define __NR_recv              356 /* new */
-#define __NR_setsockopt                357 /* new */
-#define __NR_getsockopt                358 /* new */
-#define __NR_shutdown          359 /* new */
-#define __NR_sendmsg           360 /* new */
-#define __NR_recvmsg           361 /* new */
-#define __NR_accept4           362 /* new */
-#define __NR_preadv            363 /* new */
-#define __NR_pwritev           364 /* new */
-#define __NR_rt_tgsigqueueinfo 365 /* new */
-#define __NR_perf_event_open   366 /* new */
-#define __NR_recvmmsg          367 /* new */
-#define __NR_fanotify_init     368
-#define __NR_fanotify_mark     369
-#define __NR_prlimit64         370
-#define __NR_name_to_handle_at 371
-#define __NR_open_by_handle_at 372
-#define __NR_clock_adjtime     373
-#define __NR_syncfs            374
-#define __NR_setns             375
-#define __NR_sendmmsg          376
-#define __NR_process_vm_readv  377
-#define __NR_process_vm_writev 378
-
-#define __NR_syscalls          379
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 /* #define __ARCH_WANT_OLD_READDIR */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
index baebb3da1d44160fc6f6f259886656e6f494b167..6d7d7f4aaae8679846945e11c5ab0872c5cfdfb5 100644 (file)
@@ -1,3 +1,35 @@
 # 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 += elf.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += kvm_para.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.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 += types.h
+header-y += unistd.h
diff --git a/arch/microblaze/include/uapi/asm/auxvec.h b/arch/microblaze/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/uapi/asm/bitsperlong.h b/arch/microblaze/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..6dc0bb0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/microblaze/include/uapi/asm/byteorder.h b/arch/microblaze/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..3190276
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _ASM_MICROBLAZE_BYTEORDER_H
+#define _ASM_MICROBLAZE_BYTEORDER_H
+
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
+#include <linux/byteorder/big_endian.h>
+#endif
+
+#endif /* _ASM_MICROBLAZE_BYTEORDER_H */
diff --git a/arch/microblaze/include/uapi/asm/elf.h b/arch/microblaze/include/uapi/asm/elf.h
new file mode 100644 (file)
index 0000000..be1731d
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
+ * 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 _UAPI_ASM_MICROBLAZE_ELF_H
+#define _UAPI_ASM_MICROBLAZE_ELF_H
+
+/*
+ * Note there is no "official" ELF designation for Microblaze.
+ * I've snaffled the value from the microblaze binutils source code
+ * /binutils/microblaze/include/elf/microblaze.h
+ */
+#define EM_MICROBLAZE          189
+#define EM_MICROBLAZE_OLD      0xbaab
+#define ELF_ARCH               EM_MICROBLAZE
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x)      ((x)->e_machine == EM_MICROBLAZE \
+                                || (x)->e_machine == EM_MICROBLAZE_OLD)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+
+#ifndef __uClinux__
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/byteorder.h>
+
+#ifndef ELF_GREG_T
+#define ELF_GREG_T
+typedef unsigned long elf_greg_t;
+#endif
+
+#ifndef ELF_NGREG
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+#endif
+
+#ifndef ELF_GREGSET_T
+#define ELF_GREGSET_T
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+#endif
+
+#ifndef ELF_FPREGSET_T
+#define ELF_FPREGSET_T
+
+/* TBD */
+#define ELF_NFPREG     33      /* includes fsr */
+typedef unsigned long elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* typedef struct user_fpu_struct elf_fpregset_t; */
+#endif
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+
+#define ELF_ET_DYN_BASE         (0x08000000)
+
+#ifdef __MICROBLAZEEL__
+#define ELF_DATA       ELFDATA2LSB
+#else
+#define ELF_DATA       ELFDATA2MSB
+#endif
+
+#define ELF_EXEC_PAGESIZE      PAGE_SIZE
+
+
+#define ELF_CORE_COPY_REGS(_dest, _regs)                       \
+       memcpy((char *) &_dest, (char *) _regs,         \
+       sizeof(struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports.  This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+#define ELF_HWCAP      (0)
+
+/* This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+#define ELF_PLATFORM  (NULL)
+
+/* Added _f parameter. Is this definition correct: TBD */
+#define ELF_PLAT_INIT(_r, _f)                          \
+do {                                                   \
+       _r->r0 =  _r->r1 =  _r->r2 =  _r->r3 =          \
+       _r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =          \
+       _r->r8 =  _r->r9 =  _r->r10 = _r->r11 =         \
+       _r->r12 = _r->r13 = _r->r14 = _r->r15 =         \
+       _r->r16 = _r->r17 = _r->r18 = _r->r19 =         \
+       _r->r20 = _r->r21 = _r->r22 = _r->r23 =         \
+       _r->r24 = _r->r25 = _r->r26 = _r->r27 =         \
+       _r->r28 = _r->r29 = _r->r30 = _r->r31 =         \
+       0;                                              \
+} while (0)
+
+
+#endif /* __uClinux__ */
+
+#endif /* _UAPI_ASM_MICROBLAZE_ELF_H */
diff --git a/arch/microblaze/include/uapi/asm/errno.h b/arch/microblaze/include/uapi/asm/errno.h
new file mode 100644 (file)
index 0000000..4c82b50
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/microblaze/include/uapi/asm/fcntl.h b/arch/microblaze/include/uapi/asm/fcntl.h
new file mode 100644 (file)
index 0000000..46ab12d
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/fcntl.h>
diff --git a/arch/microblaze/include/uapi/asm/ioctl.h b/arch/microblaze/include/uapi/asm/ioctl.h
new file mode 100644 (file)
index 0000000..b279fe0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/microblaze/include/uapi/asm/ioctls.h b/arch/microblaze/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..ec34c76
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ioctls.h>
diff --git a/arch/microblaze/include/uapi/asm/ipcbuf.h b/arch/microblaze/include/uapi/asm/ipcbuf.h
new file mode 100644 (file)
index 0000000..84c7e51
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ipcbuf.h>
diff --git a/arch/microblaze/include/uapi/asm/kvm_para.h b/arch/microblaze/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..14fab8f
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/arch/microblaze/include/uapi/asm/mman.h b/arch/microblaze/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..8eebf89
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/mman.h>
diff --git a/arch/microblaze/include/uapi/asm/msgbuf.h b/arch/microblaze/include/uapi/asm/msgbuf.h
new file mode 100644 (file)
index 0000000..809134c
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/msgbuf.h>
diff --git a/arch/microblaze/include/uapi/asm/param.h b/arch/microblaze/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..965d454
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/param.h>
diff --git a/arch/microblaze/include/uapi/asm/poll.h b/arch/microblaze/include/uapi/asm/poll.h
new file mode 100644 (file)
index 0000000..c98509d
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/poll.h>
diff --git a/arch/microblaze/include/uapi/asm/posix_types.h b/arch/microblaze/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..0e15039
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
+#define _ASM_MICROBLAZE_POSIX_TYPES_H
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
diff --git a/arch/microblaze/include/uapi/asm/ptrace.h b/arch/microblaze/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..d31238a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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 _UAPI_ASM_MICROBLAZE_PTRACE_H
+#define _UAPI_ASM_MICROBLAZE_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long microblaze_reg_t;
+
+struct pt_regs {
+       microblaze_reg_t r0;
+       microblaze_reg_t r1;
+       microblaze_reg_t r2;
+       microblaze_reg_t r3;
+       microblaze_reg_t r4;
+       microblaze_reg_t r5;
+       microblaze_reg_t r6;
+       microblaze_reg_t r7;
+       microblaze_reg_t r8;
+       microblaze_reg_t r9;
+       microblaze_reg_t r10;
+       microblaze_reg_t r11;
+       microblaze_reg_t r12;
+       microblaze_reg_t r13;
+       microblaze_reg_t r14;
+       microblaze_reg_t r15;
+       microblaze_reg_t r16;
+       microblaze_reg_t r17;
+       microblaze_reg_t r18;
+       microblaze_reg_t r19;
+       microblaze_reg_t r20;
+       microblaze_reg_t r21;
+       microblaze_reg_t r22;
+       microblaze_reg_t r23;
+       microblaze_reg_t r24;
+       microblaze_reg_t r25;
+       microblaze_reg_t r26;
+       microblaze_reg_t r27;
+       microblaze_reg_t r28;
+       microblaze_reg_t r29;
+       microblaze_reg_t r30;
+       microblaze_reg_t r31;
+       microblaze_reg_t pc;
+       microblaze_reg_t msr;
+       microblaze_reg_t ear;
+       microblaze_reg_t esr;
+       microblaze_reg_t fsr;
+       int pt_mode;
+};
+
+#ifndef __KERNEL__
+
+/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
+#define PT_GPR(n)      ((n) * sizeof(microblaze_reg_t))
+#define PT_PC          (32 * sizeof(microblaze_reg_t))
+#define PT_MSR         (33 * sizeof(microblaze_reg_t))
+#define PT_EAR         (34 * sizeof(microblaze_reg_t))
+#define PT_ESR         (35 * sizeof(microblaze_reg_t))
+#define PT_FSR         (36 * sizeof(microblaze_reg_t))
+#define PT_KERNEL_MODE (37 * sizeof(microblaze_reg_t))
+
+#endif /* __KERNEL */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_MICROBLAZE_PTRACE_H */
diff --git a/arch/microblaze/include/uapi/asm/resource.h b/arch/microblaze/include/uapi/asm/resource.h
new file mode 100644 (file)
index 0000000..04bc4db
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/resource.h>
diff --git a/arch/microblaze/include/uapi/asm/sembuf.h b/arch/microblaze/include/uapi/asm/sembuf.h
new file mode 100644 (file)
index 0000000..7673b83
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/sembuf.h>
diff --git a/arch/microblaze/include/uapi/asm/setup.h b/arch/microblaze/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..76bc2ac
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
+ * 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 _UAPI_ASM_MICROBLAZE_SETUP_H
+#define _UAPI_ASM_MICROBLAZE_SETUP_H
+
+#define COMMAND_LINE_SIZE      256
+
+# ifndef __ASSEMBLY__
+
+# endif /* __ASSEMBLY__ */
+#endif /* _UAPI_ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/uapi/asm/shmbuf.h b/arch/microblaze/include/uapi/asm/shmbuf.h
new file mode 100644 (file)
index 0000000..83c05fc
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/shmbuf.h>
diff --git a/arch/microblaze/include/uapi/asm/sigcontext.h b/arch/microblaze/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..55873c8
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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_SIGCONTEXT_H
+#define _ASM_MICROBLAZE_SIGCONTEXT_H
+
+/* FIXME should be linux/ptrace.h */
+#include <asm/ptrace.h>
+
+struct sigcontext {
+       struct pt_regs regs;
+       unsigned long oldmask;
+};
+
+#endif /* _ASM_MICROBLAZE_SIGCONTEXT_H */
diff --git a/arch/microblaze/include/uapi/asm/siginfo.h b/arch/microblaze/include/uapi/asm/siginfo.h
new file mode 100644 (file)
index 0000000..0815d29
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/siginfo.h>
diff --git a/arch/microblaze/include/uapi/asm/signal.h b/arch/microblaze/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..7b1573c
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/signal.h>
diff --git a/arch/microblaze/include/uapi/asm/socket.h b/arch/microblaze/include/uapi/asm/socket.h
new file mode 100644 (file)
index 0000000..6b71384
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/socket.h>
diff --git a/arch/microblaze/include/uapi/asm/sockios.h b/arch/microblaze/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..def6d47
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/sockios.h>
diff --git a/arch/microblaze/include/uapi/asm/stat.h b/arch/microblaze/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..3dc90fa
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/stat.h>
diff --git a/arch/microblaze/include/uapi/asm/statfs.h b/arch/microblaze/include/uapi/asm/statfs.h
new file mode 100644 (file)
index 0000000..0b91fe1
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/statfs.h>
diff --git a/arch/microblaze/include/uapi/asm/swab.h b/arch/microblaze/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..7847e56
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/swab.h>
diff --git a/arch/microblaze/include/uapi/asm/termbits.h b/arch/microblaze/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..3935b10
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/termbits.h>
diff --git a/arch/microblaze/include/uapi/asm/termios.h b/arch/microblaze/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..280d78a
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/termios.h>
diff --git a/arch/microblaze/include/uapi/asm/types.h b/arch/microblaze/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..b9e79bc
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/types.h>
diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..ccb6920
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu>
+ * 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 _UAPI_ASM_MICROBLAZE_UNISTD_H
+#define _UAPI_ASM_MICROBLAZE_UNISTD_H
+
+#define __NR_restart_syscall   0 /* ok */
+#define __NR_exit              1 /* ok */
+#define __NR_fork              2 /* not for no MMU - weird */
+#define __NR_read              3 /* ok */
+#define __NR_write             4 /* ok */
+#define __NR_open              5 /* openat */
+#define __NR_close             6 /* ok */
+#define __NR_waitpid           7 /* waitid */
+#define __NR_creat             8 /* openat */
+#define __NR_link              9 /* linkat */
+#define __NR_unlink            10 /* unlinkat */
+#define __NR_execve            11 /* ok */
+#define __NR_chdir             12 /* ok */
+#define __NR_time              13 /* obsolete -> sys_gettimeofday */
+#define __NR_mknod             14 /* mknodat */
+#define __NR_chmod             15 /* fchmodat */
+#define __NR_lchown            16 /* ok */
+#define __NR_break             17 /* don't know */
+#define __NR_oldstat           18 /* remove */
+#define __NR_lseek             19 /* ok */
+#define __NR_getpid            20 /* ok */
+#define __NR_mount             21 /* ok */
+#define __NR_umount            22 /* ok */  /* use only umount2 */
+#define __NR_setuid            23 /* ok */
+#define __NR_getuid            24 /* ok */
+#define __NR_stime             25 /* obsolete -> sys_settimeofday */
+#define __NR_ptrace            26 /* ok */
+#define __NR_alarm             27 /* obsolete -> sys_setitimer */
+#define __NR_oldfstat          28 /* remove */
+#define __NR_pause             29 /* obsolete -> sys_rt_sigtimedwait */
+#define __NR_utime             30 /* obsolete -> sys_utimesat */
+#define __NR_stty              31 /* remove */
+#define __NR_gtty              32 /* remove */
+#define __NR_access            33 /* faccessat */
+/* can be implemented by sys_setpriority */
+#define __NR_nice              34
+#define __NR_ftime             35 /* remove */
+#define __NR_sync              36 /* ok */
+#define __NR_kill              37 /* ok */
+#define __NR_rename            38 /* renameat */
+#define __NR_mkdir             39 /* mkdirat */
+#define __NR_rmdir             40 /* unlinkat */
+#define __NR_dup               41 /* ok */
+#define __NR_pipe              42 /* ok */
+#define __NR_times             43 /* ok */
+#define __NR_prof              44 /* remove */
+#define __NR_brk               45 /* ok -mmu, nommu specific */
+#define __NR_setgid            46 /* ok */
+#define __NR_getgid            47 /* ok */
+#define __NR_signal            48 /* obsolete -> sys_rt_sigaction */
+#define __NR_geteuid           49 /* ok */
+#define __NR_getegid           50 /* ok */
+#define __NR_acct              51 /* add it and then I can disable it */
+#define __NR_umount2           52 /* remove */
+#define __NR_lock              53 /* remove */
+#define __NR_ioctl             54 /* ok */
+#define __NR_fcntl             55 /* ok -> 64bit version*/
+#define __NR_mpx               56 /* remove */
+#define __NR_setpgid           57 /* ok */
+#define __NR_ulimit            58 /* remove */
+#define __NR_oldolduname       59 /* remove */
+#define __NR_umask             60 /* ok */
+#define __NR_chroot            61 /* ok */
+#define __NR_ustat             62 /* obsolete -> statfs64 */
+#define __NR_dup2              63 /* ok */
+#define __NR_getppid           64 /* ok */
+#define __NR_getpgrp           65 /* obsolete -> sys_getpgid */
+#define __NR_setsid            66 /* ok */
+#define __NR_sigaction         67 /* obsolete -> rt_sigaction */
+#define __NR_sgetmask          68 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_ssetmask          69 /* obsolete ->sys_rt_sigprocmask */
+#define __NR_setreuid          70 /* ok */
+#define __NR_setregid          71 /* ok */
+#define __NR_sigsuspend                72 /* obsolete -> rt_sigsuspend */
+#define __NR_sigpending                73 /* obsolete -> sys_rt_sigpending */
+#define __NR_sethostname       74 /* ok */
+#define __NR_setrlimit         75 /* ok */
+#define __NR_getrlimit         76 /* ok Back compatible 2G limited rlimit */
+#define __NR_getrusage         77 /* ok */
+#define __NR_gettimeofday      78 /* ok */
+#define __NR_settimeofday      79 /* ok */
+#define __NR_getgroups         80 /* ok */
+#define __NR_setgroups         81 /* ok */
+#define __NR_select            82 /* obsolete -> sys_pselect7 */
+#define __NR_symlink           83 /* symlinkat */
+#define __NR_oldlstat          84 /* remove */
+#define __NR_readlink          85 /* obsolete -> sys_readlinkat */
+#define __NR_uselib            86 /* remove */
+#define __NR_swapon            87 /* ok */
+#define __NR_reboot            88 /* ok */
+#define __NR_readdir           89 /* remove ? */
+#define __NR_mmap              90 /* obsolete -> sys_mmap2 */
+#define __NR_munmap            91 /* ok - mmu and nommu */
+#define __NR_truncate          92 /* ok or truncate64 */
+#define __NR_ftruncate         93 /* ok or ftruncate64 */
+#define __NR_fchmod            94 /* ok */
+#define __NR_fchown            95 /* ok */
+#define __NR_getpriority       96 /* ok */
+#define __NR_setpriority       97 /* ok */
+#define __NR_profil            98 /* remove */
+#define __NR_statfs            99 /* ok or statfs64 */
+#define __NR_fstatfs           100  /* ok or fstatfs64 */
+#define __NR_ioperm            101 /* remove */
+#define __NR_socketcall                102 /* remove */
+#define __NR_syslog            103 /* ok */
+#define __NR_setitimer         104 /* ok */
+#define __NR_getitimer         105 /* ok */
+#define __NR_stat              106 /* remove */
+#define __NR_lstat             107 /* remove */
+#define __NR_fstat             108 /* remove */
+#define __NR_olduname          109 /* remove */
+#define __NR_iopl              110 /* remove */
+#define __NR_vhangup           111 /* ok */
+#define __NR_idle              112 /* remove */
+#define __NR_vm86old           113 /* remove */
+#define __NR_wait4             114 /* obsolete -> waitid */
+#define __NR_swapoff           115 /* ok */
+#define __NR_sysinfo           116 /* ok */
+#define __NR_ipc               117 /* remove - direct call */
+#define __NR_fsync             118 /* ok */
+#define __NR_sigreturn         119 /* obsolete -> sys_rt_sigreturn */
+#define __NR_clone             120 /* ok */
+#define __NR_setdomainname     121 /* ok */
+#define __NR_uname             122 /* remove */
+#define __NR_modify_ldt                123 /* remove */
+#define __NR_adjtimex          124 /* ok */
+#define __NR_mprotect          125 /* remove */
+#define __NR_sigprocmask       126 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_create_module     127 /* remove */
+#define __NR_init_module       128 /* ok */
+#define __NR_delete_module     129 /* ok */
+#define __NR_get_kernel_syms   130 /* remove */
+#define __NR_quotactl          131 /* ok */
+#define __NR_getpgid           132 /* ok */
+#define __NR_fchdir            133 /* ok */
+#define __NR_bdflush           134 /* remove */
+#define __NR_sysfs             135 /* needed for busybox */
+#define __NR_personality       136 /* ok */
+#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
+#define __NR_setfsuid          138 /* ok */
+#define __NR_setfsgid          139 /* ok */
+#define __NR__llseek           140 /* remove only lseek */
+#define __NR_getdents          141 /* ok or getdents64 */
+#define __NR__newselect                142 /* remove */
+#define __NR_flock             143 /* ok */
+#define __NR_msync             144 /* remove */
+#define __NR_readv             145 /* ok */
+#define __NR_writev            146 /* ok */
+#define __NR_getsid            147 /* ok */
+#define __NR_fdatasync         148 /* ok */
+#define __NR__sysctl           149 /* remove */
+#define __NR_mlock             150 /* ok - nommu or mmu */
+#define __NR_munlock           151 /* ok - nommu or mmu */
+#define __NR_mlockall          152 /* ok - nommu or mmu */
+#define __NR_munlockall                153 /* ok - nommu or mmu */
+#define __NR_sched_setparam            154 /* ok */
+#define __NR_sched_getparam            155 /* ok */
+#define __NR_sched_setscheduler                156 /* ok */
+#define __NR_sched_getscheduler                157 /* ok */
+#define __NR_sched_yield               158 /* ok */
+#define __NR_sched_get_priority_max    159 /* ok */
+#define __NR_sched_get_priority_min    160 /* ok */
+#define __NR_sched_rr_get_interval     161 /* ok */
+#define __NR_nanosleep         162 /* ok */
+#define __NR_mremap            163 /* ok - nommu or mmu */
+#define __NR_setresuid         164 /* ok */
+#define __NR_getresuid         165 /* ok */
+#define __NR_vm86              166 /* remove */
+#define __NR_query_module      167 /* ok */
+#define __NR_poll              168 /* obsolete -> sys_ppoll */
+#define __NR_nfsservctl                169 /* ok */
+#define __NR_setresgid         170 /* ok */
+#define __NR_getresgid         171 /* ok */
+#define __NR_prctl             172 /* ok */
+#define __NR_rt_sigreturn      173 /* ok */
+#define __NR_rt_sigaction      174 /* ok */
+#define __NR_rt_sigprocmask    175 /* ok */
+#define __NR_rt_sigpending     176 /* ok */
+#define __NR_rt_sigtimedwait   177 /* ok */
+#define __NR_rt_sigqueueinfo   178 /* ok */
+#define __NR_rt_sigsuspend     179 /* ok */
+#define __NR_pread64           180 /* ok */
+#define __NR_pwrite64          181 /* ok */
+#define __NR_chown             182 /* obsolete -> fchownat */
+#define __NR_getcwd            183 /* ok */
+#define __NR_capget            184 /* ok */
+#define __NR_capset            185 /* ok */
+#define __NR_sigaltstack       186 /* remove */
+#define __NR_sendfile          187 /* ok -> exist 64bit version*/
+#define __NR_getpmsg           188 /* remove */
+/* remove - some people actually want streams */
+#define __NR_putpmsg           189
+/* for noMMU - group with clone -> maybe remove */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191 /* remove - SuS compliant getrlimit */
+#define __NR_mmap2             192 /* ok */
+#define __NR_truncate64                193 /* ok */
+#define __NR_ftruncate64       194 /* ok */
+#define __NR_stat64            195 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lstat64           196 /* remove _ARCH_WANT_STAT64 */
+#define __NR_fstat64           197 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lchown32          198 /* ok - without 32 */
+#define __NR_getuid32          199 /* ok - without 32 */
+#define __NR_getgid32          200 /* ok - without 32 */
+#define __NR_geteuid32         201 /* ok - without 32 */
+#define __NR_getegid32         202 /* ok - without 32 */
+#define __NR_setreuid32                203 /* ok - without 32 */
+#define __NR_setregid32                204 /* ok - without 32 */
+#define __NR_getgroups32       205 /* ok - without 32 */
+#define __NR_setgroups32       206 /* ok - without 32 */
+#define __NR_fchown32          207 /* ok - without 32 */
+#define __NR_setresuid32       208 /* ok - without 32 */
+#define __NR_getresuid32       209 /* ok - without 32 */
+#define __NR_setresgid32       210 /* ok - without 32 */
+#define __NR_getresgid32       211 /* ok - without 32 */
+#define __NR_chown32           212 /* ok - without 32 -obsolete -> fchownat */
+#define __NR_setuid32          213 /* ok - without 32 */
+#define __NR_setgid32          214 /* ok - without 32 */
+#define __NR_setfsuid32                215 /* ok - without 32 */
+#define __NR_setfsgid32                216 /* ok - without 32 */
+#define __NR_pivot_root                217 /* ok */
+#define __NR_mincore           218 /* ok */
+#define __NR_madvise           219 /* ok */
+#define __NR_getdents64                220 /* ok */
+#define __NR_fcntl64           221 /* ok */
+/* 223 is unused */
+#define __NR_gettid            224 /* ok */
+#define __NR_readahead         225 /* ok */
+#define __NR_setxattr          226 /* ok */
+#define __NR_lsetxattr         227 /* ok */
+#define __NR_fsetxattr         228 /* ok */
+#define __NR_getxattr          229 /* ok */
+#define __NR_lgetxattr         230 /* ok */
+#define __NR_fgetxattr         231 /* ok */
+#define __NR_listxattr         232 /* ok */
+#define __NR_llistxattr                233 /* ok */
+#define __NR_flistxattr                234 /* ok */
+#define __NR_removexattr       235 /* ok */
+#define __NR_lremovexattr      236 /* ok */
+#define __NR_fremovexattr      237 /* ok */
+#define __NR_tkill             238 /* ok */
+#define __NR_sendfile64                239 /* ok */
+#define __NR_futex             240 /* ok */
+#define __NR_sched_setaffinity 241 /* ok */
+#define __NR_sched_getaffinity 242 /* ok */
+#define __NR_set_thread_area   243 /* remove */
+#define __NR_get_thread_area   244 /* remove */
+#define __NR_io_setup          245 /* ok */
+#define __NR_io_destroy                246 /* ok */
+#define __NR_io_getevents      247 /* ok */
+#define __NR_io_submit         248 /* ok */
+#define __NR_io_cancel         249 /* ok */
+#define __NR_fadvise64         250 /* remove -> sys_fadvise64_64 */
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_exit_group                252 /* ok */
+#define __NR_lookup_dcookie    253 /* ok */
+#define __NR_epoll_create      254 /* ok */
+#define __NR_epoll_ctl         255 /* ok */
+#define __NR_epoll_wait                256 /* obsolete -> sys_epoll_pwait */
+#define __NR_remap_file_pages  257 /* only for mmu */
+#define __NR_set_tid_address   258 /* ok */
+#define __NR_timer_create      259 /* ok */
+#define __NR_timer_settime     (__NR_timer_create+1) /* 260 */ /* ok */
+#define __NR_timer_gettime     (__NR_timer_create+2) /* 261 */ /* ok */
+#define __NR_timer_getoverrun  (__NR_timer_create+3) /* 262 */ /* ok */
+#define __NR_timer_delete      (__NR_timer_create+4) /* 263 */ /* ok */
+#define __NR_clock_settime     (__NR_timer_create+5) /* 264 */ /* ok */
+#define __NR_clock_gettime     (__NR_timer_create+6) /* 265 */ /* ok */
+#define __NR_clock_getres      (__NR_timer_create+7) /* 266 */ /* ok */
+#define __NR_clock_nanosleep   (__NR_timer_create+8) /* 267 */ /* ok */
+#define __NR_statfs64          268 /* ok */
+#define __NR_fstatfs64         269 /* ok */
+#define __NR_tgkill            270 /* ok */
+#define __NR_utimes            271 /* obsolete -> sys_futimesat */
+#define __NR_fadvise64_64      272 /* ok */
+#define __NR_vserver           273 /* ok */
+#define __NR_mbind             274 /* only for mmu */
+#define __NR_get_mempolicy     275 /* only for mmu */
+#define __NR_set_mempolicy     276 /* only for mmu */
+#define __NR_mq_open           277 /* ok */
+#define __NR_mq_unlink         (__NR_mq_open+1) /* 278 */ /* ok */
+#define __NR_mq_timedsend      (__NR_mq_open+2) /* 279 */ /* ok */
+#define __NR_mq_timedreceive   (__NR_mq_open+3) /* 280 */ /* ok */
+#define __NR_mq_notify         (__NR_mq_open+4) /* 281 */ /* ok */
+#define __NR_mq_getsetattr     (__NR_mq_open+5) /* 282 */ /* ok */
+#define __NR_kexec_load                283 /* ok */
+#define __NR_waitid            284 /* ok */
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_add_key           286 /* ok */
+#define __NR_request_key       287 /* ok */
+#define __NR_keyctl            288 /* ok */
+#define __NR_ioprio_set                289 /* ok */
+#define __NR_ioprio_get                290 /* ok */
+#define __NR_inotify_init      291 /* ok */
+#define __NR_inotify_add_watch 292 /* ok */
+#define __NR_inotify_rm_watch  293 /* ok */
+#define __NR_migrate_pages     294 /* mmu */
+#define __NR_openat            295 /* ok */
+#define __NR_mkdirat           296 /* ok */
+#define __NR_mknodat           297 /* ok */
+#define __NR_fchownat          298 /* ok */
+#define __NR_futimesat         299 /* obsolete -> sys_utimesat */
+#define __NR_fstatat64         300 /* stat64 */
+#define __NR_unlinkat          301 /* ok */
+#define __NR_renameat          302 /* ok */
+#define __NR_linkat            303 /* ok */
+#define __NR_symlinkat         304 /* ok */
+#define __NR_readlinkat                305 /* ok */
+#define __NR_fchmodat          306 /* ok */
+#define __NR_faccessat         307 /* ok */
+#define __NR_pselect6          308 /* obsolete -> sys_pselect7 */
+#define __NR_ppoll             309 /* ok */
+#define __NR_unshare           310 /* ok */
+#define __NR_set_robust_list   311 /* ok */
+#define __NR_get_robust_list   312 /* ok */
+#define __NR_splice            313 /* ok */
+#define __NR_sync_file_range   314 /* ok */
+#define __NR_tee               315 /* ok */
+#define __NR_vmsplice          316 /* ok */
+#define __NR_move_pages                317 /* mmu */
+#define __NR_getcpu            318 /* ok */
+#define __NR_epoll_pwait       319 /* ok */
+#define __NR_utimensat         320 /* ok */
+#define __NR_signalfd          321 /* ok */
+#define __NR_timerfd_create    322 /* ok */
+#define __NR_eventfd           323 /* ok */
+#define __NR_fallocate         324 /* ok */
+#define __NR_semtimedop                325 /* ok - semaphore group */
+#define __NR_timerfd_settime   326 /* ok */
+#define __NR_timerfd_gettime   327 /* ok */
+/* sysv ipc syscalls */
+#define __NR_semctl            328 /* ok */
+#define __NR_semget            329 /* ok */
+#define __NR_semop             330 /* ok */
+#define __NR_msgctl            331 /* ok */
+#define __NR_msgget            332 /* ok */
+#define __NR_msgrcv            333 /* ok */
+#define __NR_msgsnd            334 /* ok */
+#define __NR_shmat             335 /* ok */
+#define __NR_shmctl            336 /* ok */
+#define __NR_shmdt             337 /* ok */
+#define __NR_shmget            338 /* ok */
+
+
+#define __NR_signalfd4         339 /* new */
+#define __NR_eventfd2          340 /* new */
+#define __NR_epoll_create1     341 /* new */
+#define __NR_dup3              342 /* new */
+#define __NR_pipe2             343 /* new */
+#define __NR_inotify_init1     344 /* new */
+#define __NR_socket            345 /* new */
+#define __NR_socketpair                346 /* new */
+#define __NR_bind              347 /* new */
+#define __NR_listen            348 /* new */
+#define __NR_accept            349 /* new */
+#define __NR_connect           350 /* new */
+#define __NR_getsockname       351 /* new */
+#define __NR_getpeername       352 /* new */
+#define __NR_sendto            353 /* new */
+#define __NR_send              354 /* new */
+#define __NR_recvfrom          355 /* new */
+#define __NR_recv              356 /* new */
+#define __NR_setsockopt                357 /* new */
+#define __NR_getsockopt                358 /* new */
+#define __NR_shutdown          359 /* new */
+#define __NR_sendmsg           360 /* new */
+#define __NR_recvmsg           361 /* new */
+#define __NR_accept4           362 /* new */
+#define __NR_preadv            363 /* new */
+#define __NR_pwritev           364 /* new */
+#define __NR_rt_tgsigqueueinfo 365 /* new */
+#define __NR_perf_event_open   366 /* new */
+#define __NR_recvmmsg          367 /* new */
+#define __NR_fanotify_init     368
+#define __NR_fanotify_mark     369
+#define __NR_prlimit64         370
+#define __NR_name_to_handle_at 371
+#define __NR_open_by_handle_at 372
+#define __NR_clock_adjtime     373
+#define __NR_syncfs            374
+#define __NR_setns             375
+#define __NR_sendmmsg          376
+#define __NR_process_vm_readv  377
+#define __NR_process_vm_writev 378
+#define __NR_kcmp              379
+
+#define __NR_syscalls          380
+
+#endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
index cb0327f204ab562b8141e5637ca27e08d03518f4..70da83a49670539829365a7012395de497a348be 100644 (file)
@@ -465,7 +465,6 @@ ENTRY(_switch_to)
 
 ENTRY(ret_from_fork)
        addk    r5, r0, r3
-       addk    r6, r0, r1
        brlid   r15, schedule_tail
        nop
        swi     r31, r1, PT_R31         /* save r31 in user context. */
index 6c54d4dcdec311e0f6f5fce32a6635cf0095883f..7a1a8d4354feeb6f10767d7947baef8fa6546512 100644 (file)
@@ -44,7 +44,6 @@ static void intc_enable_or_unmask(struct irq_data *d)
        unsigned long mask = 1 << d->hwirq;
 
        pr_debug("enable_or_unmask: %ld\n", d->hwirq);
-       out_be32(INTC_BASE + SIE, mask);
 
        /* ack level irqs because they can't be acked during
         * ack function since the handle_level_irq function
@@ -52,6 +51,8 @@ static void intc_enable_or_unmask(struct irq_data *d)
         */
        if (irqd_is_level_type(d))
                out_be32(INTC_BASE + IAR, mask);
+
+       out_be32(INTC_BASE + SIE, mask);
 }
 
 static void intc_disable_or_mask(struct irq_data *d)
@@ -98,7 +99,7 @@ unsigned int get_irq(void)
        return irq;
 }
 
-int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
        u32 intr_mask = (u32)d->host_data;
 
index 40823fd1db0bb915c87ef33650166281660ddf58..a5b74f729e5bade2c12ca66fff5503161ad671f7 100644 (file)
@@ -162,7 +162,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
         * excepting for VM and UMS
         * don't touch UMS , CARRY and cache bits
         * right now MSR is a copy of parent one */
-       childregs->msr |= MSR_BIP;
        childregs->msr &= ~MSR_EIP;
        childregs->msr |= MSR_IE;
        childregs->msr &= ~MSR_VM;
index 4a764ccb9f26a81963ac2fffb3c6f0a452d8d87f..a744e3f1888381053bc419ba9e769cb1e5920c85 100644 (file)
@@ -52,9 +52,9 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_EARLY_PRINTK
-char *stdout;
+static char *stdout;
 
-int __init early_init_dt_scan_chosen_serial(unsigned long node,
+static int __init early_init_dt_scan_chosen_serial(unsigned long node,
                                const char *uname, int depth, void *data)
 {
        unsigned long l;
index 3903e3d11f5a557d673fbcfcb051e1fd17e49392..ac3d0a0f4814ea3d115c79d61f687a081f08691b 100644 (file)
@@ -354,7 +354,7 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
        restore_saved_sigmask();
 }
 
-void do_notify_resume(struct pt_regs *regs, int in_syscall)
+asmlinkage void do_notify_resume(struct pt_regs *regs, int in_syscall)
 {
        /*
         * We want the common case to go fast, which
index ff6431e54680418b7e550417a747a2310b5ee4aa..1cbace29b5e2495f567abb04b261e4341b316cc0 100644 (file)
@@ -379,3 +379,4 @@ ENTRY(sys_call_table)
        .long sys_sendmmsg
        .long sys_process_vm_readv
        .long sys_process_vm_writev
+       .long sys_kcmp
index 05909d58e2fe1c278e3f30a3d196e1c214724194..ab077ef7e14b14c28656ed5ac3589353f1926a18 100644 (file)
@@ -22,4 +22,11 @@ typedef union {
        long long ll;
 } DWunion;
 
+extern long long __ashldi3(long long u, word_type b);
+extern long long __ashrdi3(long long u, word_type b);
+extern word_type __cmpdi2(long long a, long long b);
+extern long long __lshrdi3(long long u, word_type b);
+extern long long __muldi3(long long u, long long v);
+extern word_type __ucmpdi2(unsigned long long a, unsigned long long b);
+
 #endif /* __ASM_LIBGCC_H */
index 0585bccb7fad2f30d6ad8110eff7bc0b80771dff..d3659244ab6fac432bce8ff362bbf12dd5bc68cc 100644 (file)
@@ -2,32 +2,28 @@
 
 #include "libgcc.h"
 
-#define DWtype long long
-#define UWtype unsigned long
-#define UHWtype unsigned short
-
 #define W_TYPE_SIZE 32
 
-#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
-#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+#define __ll_B ((unsigned long) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((unsigned long) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((unsigned long) (t) >> (W_TYPE_SIZE / 2))
 
 /* If we still don't have umul_ppmm, define it using plain C.  */
 #if !defined(umul_ppmm)
 #define umul_ppmm(w1, w0, u, v)                                                \
        do {                                                            \
-               UWtype __x0, __x1, __x2, __x3;                          \
-               UHWtype __ul, __vl, __uh, __vh;                         \
+               unsigned long __x0, __x1, __x2, __x3;                   \
+               unsigned short __ul, __vl, __uh, __vh;                  \
                                                                        \
                __ul = __ll_lowpart(u);                                 \
                __uh = __ll_highpart(u);                                \
                __vl = __ll_lowpart(v);                                 \
                __vh = __ll_highpart(v);                                \
                                                                        \
-               __x0 = (UWtype) __ul * __vl;                            \
-               __x1 = (UWtype) __ul * __vh;                            \
-               __x2 = (UWtype) __uh * __vl;                            \
-               __x3 = (UWtype) __uh * __vh;                            \
+               __x0 = (unsigned long) __ul * __vl;                     \
+               __x1 = (unsigned long) __ul * __vh;                     \
+               __x2 = (unsigned long) __uh * __vl;                     \
+               __x3 = (unsigned long) __uh * __vh;                     \
                                                                        \
                __x1 += __ll_highpart(__x0); /* this can't give carry */\
                __x1 += __x2; /* but this indeed can */                 \
        })
 #endif
 
-DWtype __muldi3(DWtype u, DWtype v)
+long long __muldi3(long long u, long long v)
 {
        const DWunion uu = {.ll = u};
        const DWunion vv = {.ll = v};
        DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low)};
 
-       w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
-               + (UWtype) uu.s.high * (UWtype) vv.s.low);
+       w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high
+               + (unsigned long) uu.s.high * (unsigned long) vv.s.low);
 
        return w.ll;
 }
index 4183e62f178cd9d85027c32e95392f2f51f409ad..d971d1586f1cfa80828e16796c45ab2a4cca3844 100644 (file)
@@ -19,6 +19,7 @@ config MIPS
        select HAVE_KRETPROBES
        select HAVE_DEBUG_KMEMLEAK
        select ARCH_BINFMT_ELF_RANDOMIZE_PIE
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select RTC_LIB if !MACH_LOONGSON
        select GENERIC_ATOMIC64 if !64BIT
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -55,8 +56,8 @@ choice
 config MIPS_ALCHEMY
        bool "Alchemy processor based machines"
        select 64BIT_PHYS_ADDR
-       select CEVT_R4K_LIB
-       select CSRC_R4K_LIB
+       select CEVT_R4K
+       select CSRC_R4K
        select IRQ_CPU
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_SUPPORTS_32BIT_KERNEL
@@ -107,16 +108,16 @@ config ATH79
 
 config BCM47XX
        bool "Broadcom BCM47XX based boards"
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        select CEVT_R4K
        select CSRC_R4K
        select DMA_NONCOHERENT
+       select FW_CFE
        select HW_HAS_PCI
        select IRQ_CPU
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
-       select GENERIC_GPIO
        select SYS_HAS_EARLY_PRINTK
-       select CFE
        help
         Support for BCM47XX based boards
 
@@ -193,8 +194,8 @@ config MACH_DECSTATION
 
 config MACH_JAZZ
        bool "Jazz family of machines"
-       select ARC
-       select ARC32
+       select FW_ARC
+       select FW_ARC32
        select ARCH_MAY_HAVE_PC_FDC
        select CEVT_R4K
        select CSRC_R4K
@@ -417,27 +418,6 @@ config PMC_MSP
          of integrated peripherals, interfaces and DSPs in addition to
          a variety of MIPS cores.
 
-config PMC_YOSEMITE
-       bool "PMC-Sierra Yosemite eval board"
-       select CEVT_R4K
-       select CSRC_R4K
-       select DMA_COHERENT
-       select HW_HAS_PCI
-       select IRQ_CPU
-       select IRQ_CPU_RM7K
-       select IRQ_CPU_RM9K
-       select SWAP_IO_SPACE
-       select SYS_HAS_CPU_RM9000
-       select SYS_HAS_EARLY_PRINTK
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
-       select SYS_SUPPORTS_HIGHMEM
-       select SYS_SUPPORTS_SMP
-       help
-         Yosemite is an evaluation board for the RM9000x2 processor
-         manufactured by PMC-Sierra.
-
 config POWERTV
        bool "Cisco PowerTV"
        select BOOT_ELF32
@@ -458,8 +438,8 @@ config POWERTV
 
 config SGI_IP22
        bool "SGI IP22 (Indy/Indigo2)"
-       select ARC
-       select ARC32
+       select FW_ARC
+       select FW_ARC32
        select BOOT_ELF32
        select CEVT_R4K
        select CSRC_R4K
@@ -498,8 +478,8 @@ config SGI_IP22
 
 config SGI_IP27
        bool "SGI IP27 (Origin200/2000)"
-       select ARC
-       select ARC64
+       select FW_ARC
+       select FW_ARC64
        select BOOT_ELF64
        select DEFAULT_SGI_PARTITION
        select DMA_COHERENT
@@ -519,8 +499,8 @@ config SGI_IP27
 config SGI_IP28
        bool "SGI IP28 (Indigo2 R10k) (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       select ARC
-       select ARC64
+       select FW_ARC
+       select FW_ARC64
        select BOOT_ELF64
        select CEVT_R4K
        select CSRC_R4K
@@ -555,8 +535,8 @@ config SGI_IP28
 
 config SGI_IP32
        bool "SGI IP32 (O2)"
-       select ARC
-       select ARC32
+       select FW_ARC
+       select FW_ARC32
        select BOOT_ELF32
        select CEVT_R4K
        select CSRC_R4K
@@ -674,8 +654,8 @@ config SIBYTE_BIGSUR
 
 config SNI_RM
        bool "SNI RM200/300/400"
-       select ARC if CPU_LITTLE_ENDIAN
-       select ARC32 if CPU_LITTLE_ENDIAN
+       select FW_ARC if CPU_LITTLE_ENDIAN
+       select FW_ARC32 if CPU_LITTLE_ENDIAN
        select SNIPROM if CPU_BIG_ENDIAN
        select ARCH_MAY_HAVE_PC_FDC
        select BOOT_ELF32
@@ -776,6 +756,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
        select DMA_COHERENT
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
+       select EDAC_SUPPORT
        select SYS_SUPPORTS_HOTPLUG_CPU
        select SYS_HAS_EARLY_PRINTK
        select SYS_HAS_CPU_CAVIUM_OCTEON
@@ -819,7 +800,7 @@ config NLM_XLR_BOARD
        select CSRC_R4K
        select IRQ_CPU
        select ARCH_SUPPORTS_MSI
-       select ZONE_DMA if 64BIT
+       select ZONE_DMA32 if 64BIT
        select SYNC_R4K
        select SYS_HAS_EARLY_PRINTK
        select USB_ARCH_HAS_OHCI if USB_SUPPORT
@@ -847,7 +828,7 @@ config NLM_XLP_BOARD
        select CEVT_R4K
        select CSRC_R4K
        select IRQ_CPU
-       select ZONE_DMA if 64BIT
+       select ZONE_DMA32 if 64BIT
        select SYNC_R4K
        select SYS_HAS_EARLY_PRINTK
        select USE_OF
@@ -908,7 +889,7 @@ config SCHED_OMIT_FRAME_POINTER
 #
 # Select some configuration options automatically based on user selections.
 #
-config ARC
+config FW_ARC
        bool
 
 config ARCH_MAY_HAVE_PC_FDC
@@ -926,11 +907,7 @@ config CEVT_DS1287
 config CEVT_GT641XX
        bool
 
-config CEVT_R4K_LIB
-       bool
-
 config CEVT_R4K
-       select CEVT_R4K_LIB
        bool
 
 config CEVT_SB1250
@@ -948,11 +925,7 @@ config CSRC_IOASIC
 config CSRC_POWERTV
        bool
 
-config CSRC_R4K_LIB
-       bool
-
 config CSRC_R4K
-       select CSRC_R4K_LIB
        bool
 
 config CSRC_SB1250
@@ -963,7 +936,7 @@ config GPIO_TXX9
        select ARCH_REQUIRE_GPIOLIB
        bool
 
-config CFE
+config FW_CFE
        bool
 
 config ARCH_DMA_ADDR_T_64BIT
@@ -1079,15 +1052,15 @@ config SYS_SUPPORTS_HUGETLBFS
        depends on CPU_SUPPORTS_HUGEPAGES && 64BIT
        default y
 
+config MIPS_HUGE_TLB_SUPPORT
+       def_bool HUGETLB_PAGE || TRANSPARENT_HUGEPAGE
+
 config IRQ_CPU
        bool
 
 config IRQ_CPU_RM7K
        bool
 
-config IRQ_CPU_RM9K
-       bool
-
 config IRQ_MSP_SLP
        bool
 
@@ -1112,10 +1085,6 @@ config PCI_GT64XXX_PCI0
 config NO_EXCEPT_FILL
        bool
 
-config MIPS_RM9122
-       bool
-       select SERIAL_RM9000
-
 config SOC_EMMA2RH
        bool
        select CEVT_R4K
@@ -1161,9 +1130,6 @@ config SOC_PNX8550
 config SWAP_IO_SPACE
        bool
 
-config SERIAL_RM9000
-       bool
-
 config SGI_HAS_INDYDOG
        bool
 
@@ -1185,7 +1151,7 @@ config SGI_HAS_I8042
 config DEFAULT_SGI_PARTITION
        bool
 
-config ARC32
+config FW_ARC32
        bool
 
 config SNIPROM
@@ -1218,7 +1184,7 @@ config ARC_PROMLIB
        depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32
        default y
 
-config ARC64
+config FW_ARC64
        bool
 
 config BOOT_ELF64
@@ -1370,6 +1336,7 @@ config CPU_R4X00
        depends on SYS_HAS_CPU_R4X00
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
        help
          MIPS Technologies R4000-series processors other than 4300, including
          the R4000, R4400, R4600, and 4700.
@@ -1380,12 +1347,14 @@ config CPU_TX49XX
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_R5000
        bool "R5000"
        depends on SYS_HAS_CPU_R5000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
        help
          MIPS Technologies R5000-series processors other than the Nevada.
 
@@ -1394,6 +1363,7 @@ config CPU_R5432
        depends on SYS_HAS_CPU_R5432
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_R5500
        bool "R5500"
@@ -1419,6 +1389,7 @@ config CPU_NEVADA
        depends on SYS_HAS_CPU_NEVADA
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_SUPPORTS_HUGEPAGES
        help
          QED / PMC-Sierra RM52xx-series ("Nevada") processors.
 
@@ -1439,6 +1410,7 @@ config CPU_R10000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        help
          MIPS Technologies R10000-series processors.
 
@@ -1449,15 +1421,7 @@ config CPU_RM7000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
-
-config CPU_RM9000
-       bool "RM9000"
-       depends on SYS_HAS_CPU_RM9000
-       select CPU_HAS_PREFETCH
-       select CPU_SUPPORTS_32BIT_KERNEL
-       select CPU_SUPPORTS_64BIT_KERNEL
-       select CPU_SUPPORTS_HIGHMEM
-       select WEAK_ORDERING
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_SB1
        bool "SB1"
@@ -1465,6 +1429,7 @@ config CPU_SB1
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
 
 config CPU_CAVIUM_OCTEON
@@ -1528,9 +1493,9 @@ config CPU_XLR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
-       select CPU_SUPPORTS_HUGEPAGES
        help
          Netlogic Microsystems XLR/XLS processors.
 
@@ -1544,6 +1509,7 @@ config CPU_XLP
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
        select CPU_HAS_PREFETCH
+       select CPU_MIPSR2
        help
          Netlogic Microsystems XLP processors.
 endchoice
@@ -1591,6 +1557,7 @@ config CPU_LOONGSON2
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
+       select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_LOONGSON1
        bool
@@ -1675,9 +1642,6 @@ config SYS_HAS_CPU_R10000
 config SYS_HAS_CPU_RM7000
        bool
 
-config SYS_HAS_CPU_RM9000
-       bool
-
 config SYS_HAS_CPU_SB1
        bool
 
@@ -1757,7 +1721,7 @@ config CPU_SUPPORTS_UNCACHED_ACCELERATED
        bool
 config MIPS_PGD_C0_CONTEXT
        bool
-       default y if 64BIT && CPU_MIPSR2
+       default y if 64BIT && CPU_MIPSR2 && !CPU_XLP
 
 #
 # Set to y for ptrace access to watch registers.
@@ -2188,7 +2152,7 @@ config NODES_SHIFT
 
 config HW_PERF_EVENTS
        bool "Enable hardware performance counter support for perf events"
-       depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON)
+       depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
        default y
        help
          Enable hardware performance counter support for perf events. If
@@ -2366,6 +2330,29 @@ config KEXEC
          support.  As of this writing the exact hardware interface is
          strongly in flux, so no good recommendation can be made.
 
+config CRASH_DUMP
+         bool "Kernel crash dumps"
+         help
+         Generate crash dump after being started by kexec.
+         This should be normally only set in special crash dump kernels
+         which are loaded in the main kernel with kexec-tools into
+         a specially reserved region and then later executed after
+         a crash by kdump/kexec. The crash dump kernel must be compiled
+         to a memory address not used by the main kernel or firmware using
+         PHYSICAL_START.
+
+config PHYSICAL_START
+         hex "Physical address where the kernel is loaded"
+         default "0xffffffff84000000" if 64BIT
+         default "0x84000000" if 32BIT
+         depends on CRASH_DUMP
+         help
+         This gives the CKSEG0 or KSEG0 address where the kernel is loaded.
+         If you plan to use kernel for capturing the crash dump change
+         this value to start of the reserved region (the "X" value as
+         specified in the "crashkernel=YM@XM" command line boot parameter
+         passed to the panic-ed kernel).
+
 config SECCOMP
        bool "Enable seccomp to safely compute untrusted bytecode"
        depends on PROC_FS
@@ -2572,6 +2559,8 @@ source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+source "drivers/firmware/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/mips/Kconfig.debug"
index 654b1ad39f05fb983e33bfb68a88eaeceb903e01..f2dfd404550c787b4e8dda7acddae03c60e12282 100644 (file)
@@ -145,8 +145,6 @@ cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
                        -Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)    += $(call cc-option,-march=rm7000,-march=r5000) \
                        -Wa,--trap
-cflags-$(CONFIG_CPU_RM9000)    += $(call cc-option,-march=rm9000,-march=r5000) \
-                       -Wa,--trap
 cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-march=sb1,-march=r5000) \
                        -Wa,--trap
 cflags-$(CONFIG_CPU_R8000)     += -march=r8000 -Wa,--trap
@@ -173,9 +171,9 @@ endif
 #
 # Firmware support
 #
-libs-$(CONFIG_ARC)             += arch/mips/fw/arc/
-libs-$(CONFIG_CFE)             += arch/mips/fw/cfe/
-libs-$(CONFIG_SNIPROM)         += arch/mips/fw/sni/
+libs-$(CONFIG_FW_ARC)          += arch/mips/fw/arc/
+libs-$(CONFIG_FW_CFE)          += arch/mips/fw/cfe/
+libs-$(CONFIG_FW_SNIPROM)      += arch/mips/fw/sni/
 libs-y                         += arch/mips/fw/lib/
 
 #
@@ -192,6 +190,10 @@ endif
 #
 include $(srctree)/arch/mips/Kbuild.platforms
 
+ifdef CONFIG_PHYSICAL_START
+load-y                                  = $(CONFIG_PHYSICAL_START)
+endif
+
 cflags-y                       += -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)          += arch/mips/pci/
 
index 1bbc24b086854592ee95ddda56a7254efde92595..7477fd2127ad52316e340da93c82522e2ab98fa7 100644 (file)
@@ -202,8 +202,11 @@ static struct resource physmap_flash_resource = {
        .end    = 0x107fffff,
 };
 
+static const char *ar7_probe_types[] = { "ar7part", NULL };
+
 static struct physmap_flash_data physmap_flash_data = {
        .width  = 2,
+       .part_probe_types = ar7_probe_types,
 };
 
 static struct platform_device physmap_flash = {
index b311be45a7207028a7cf6df754a8b54c0f259938..d7af29f1fcf0079c7ccdcae5af9f0add4c8c2c80 100644 (file)
@@ -9,6 +9,7 @@ config BCM47XX_SSB
        select SSB_EMBEDDED
        select SSB_B43_PCI_BRIDGE if PCI
        select SSB_PCICORE_HOSTMODE if PCI
+       select SSB_DRIVER_GPIO
        default y
        help
         Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -23,6 +24,7 @@ config BCM47XX_BCMA
        select BCMA_DRIVER_MIPS
        select BCMA_HOST_PCI if PCI
        select BCMA_DRIVER_PCI_HOSTMODE if PCI
+       select BCMA_DRIVER_GPIO
        default y
        help
         Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
index 4389de182eb476a5cf3ff50565e7f13b86585611..1a3567f07e734e9a81384e61e8d94c0f34c2a1fc 100644 (file)
@@ -3,5 +3,5 @@
 # under Linux.
 #
 
-obj-y                          += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
+obj-y                          += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
 obj-$(CONFIG_BCM47XX_SSB)      += wgt634u.o
diff --git a/arch/mips/bcm47xx/gpio.c b/arch/mips/bcm47xx/gpio.c
deleted file mode 100644 (file)
index 5ebdf62..0000000
+++ /dev/null
@@ -1,102 +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) 2007 Aurelien Jarno <aurelien@aurel32.net>
- */
-
-#include <linux/export.h>
-#include <linux/ssb/ssb.h>
-#include <linux/ssb/ssb_driver_chipcommon.h>
-#include <linux/ssb/ssb_driver_extif.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
-#include <asm/mach-bcm47xx/gpio.h>
-
-#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
-static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
-#else
-static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
-#endif
-
-int gpio_request(unsigned gpio, const char *tag)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
-                   ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-                       return -EINVAL;
-
-               if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
-                   ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-                       return -EINVAL;
-
-               if (test_and_set_bit(gpio, gpio_in_use))
-                       return -EBUSY;
-
-               return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
-                       return -EINVAL;
-
-               if (test_and_set_bit(gpio, gpio_in_use))
-                       return -EBUSY;
-
-               return 0;
-#endif
-       }
-       return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_request);
-
-void gpio_free(unsigned gpio)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
-                   ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-                       return;
-
-               if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
-                   ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-                       return;
-
-               clear_bit(gpio, gpio_in_use);
-               return;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
-                       return;
-
-               clear_bit(gpio, gpio_in_use);
-               return;
-#endif
-       }
-}
-EXPORT_SYMBOL(gpio_free);
-
-int gpio_to_irq(unsigned gpio)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
-                       return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
-               else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
-                       return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
-               else
-                       return -EINVAL;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
-#endif
-       }
-       return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(gpio_to_irq);
index f6e9063cc4c2011f057f468a30a8ab7c4c0e4ecd..8c155afb1299e7eda1a413cf4fe4fff3e3d2f093 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
  *  Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
+ *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -27,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/smp.h>
 #include <asm/bootinfo.h>
 #include <asm/fw/cfe/cfe_api.h>
 #include <asm/fw/cfe/cfe_error.h>
@@ -127,6 +129,8 @@ static __init void prom_init_mem(void)
 {
        unsigned long mem;
        unsigned long max;
+       unsigned long off;
+       struct cpuinfo_mips *c = &current_cpu_data;
 
        /* Figure out memory size by finding aliases.
         *
@@ -143,18 +147,26 @@ static __init void prom_init_mem(void)
         * max contains the biggest possible address supported by the platform.
         * If the method wants to try something above we assume 128MB ram.
         */
-       max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
+       off = (unsigned long)prom_init;
+       max = off | ((128 << 20) - 1);
        for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
-               if (((unsigned long)(prom_init) + mem) > max) {
+               if ((off + mem) > max) {
                        mem = (128 << 20);
                        printk(KERN_DEBUG "assume 128MB RAM\n");
                        break;
                }
-               if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
-                   *(unsigned long *)(prom_init))
+               if (!memcmp(prom_init, prom_init + mem, 32))
                        break;
        }
 
+       /* Ignoring the last page when ddr size is 128M. Cached
+        * accesses to last page is causing the processor to prefetch
+        * using address above 128M stepping out of the ddr address
+        * space.
+        */
+       if (c->cputype == CPU_74K && (mem == (128  << 20)))
+               mem -= 0x1000;
+
        add_memory_region(0, mem, BOOT_MEM_RAM);
 }
 
index 95bf4d7bac21146062e6ae2c62998b8981dea6b3..4d54b58dbd32d618aa50ae565acbf3d0de729f58 100644 (file)
@@ -94,7 +94,7 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
                snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
                         bus->host_pci->bus->number + 1,
                         PCI_SLOT(bus->host_pci->devfn));
-               bcm47xx_fill_sprom(out, prefix);
+               bcm47xx_fill_sprom(out, prefix, false);
                return 0;
        } else {
                printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
@@ -113,7 +113,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
        bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
 
        memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
-       bcm47xx_fill_sprom(&iv->sprom, NULL);
+       bcm47xx_fill_sprom(&iv->sprom, NULL, false);
 
        if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
                iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
@@ -165,16 +165,17 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
                snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
                         bus->host_pci->bus->number + 1,
                         PCI_SLOT(bus->host_pci->devfn));
-               bcm47xx_fill_sprom(out, prefix);
+               bcm47xx_fill_sprom(out, prefix, false);
                return 0;
        case BCMA_HOSTTYPE_SOC:
                memset(out, 0, sizeof(struct ssb_sprom));
-               bcm47xx_fill_sprom_ethernet(out, NULL);
                core = bcma_find_core(bus, BCMA_CORE_80211);
                if (core) {
                        snprintf(prefix, sizeof(prefix), "sb/%u/",
                                 core->core_index);
-                       bcm47xx_fill_sprom(out, prefix);
+                       bcm47xx_fill_sprom(out, prefix, true);
+               } else {
+                       bcm47xx_fill_sprom(out, NULL, false);
                }
                return 0;
        default:
index d3a889745e20a71e11e5bf0810177fc5288c70a3..289cc0a386380e9cfa6c49eb86b1b89c0f917352 100644 (file)
@@ -42,25 +42,39 @@ static void create_key(const char *prefix, const char *postfix,
                snprintf(buf, len, "%s", name);
 }
 
+static int get_nvram_var(const char *prefix, const char *postfix,
+                        const char *name, char *buf, int len, bool fallback)
+{
+       char key[40];
+       int err;
+
+       create_key(prefix, postfix, name, key, sizeof(key));
+
+       err = nvram_getenv(key, buf, len);
+       if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
+               create_key(NULL, postfix, name, key, sizeof(key));
+               err = nvram_getenv(key, buf, len);
+       }
+       return err;
+}
+
 #define NVRAM_READ_VAL(type)                                           \
 static void nvram_read_ ## type (const char *prefix,                   \
                                 const char *postfix, const char *name, \
-                                type *val, type allset)                \
+                                type *val, type allset, bool fallback) \
 {                                                                      \
        char buf[100];                                                  \
-       char key[40];                                                   \
        int err;                                                        \
        type var;                                                       \
                                                                        \
-       create_key(prefix, postfix, name, key, sizeof(key));            \
-                                                                       \
-       err = nvram_getenv(key, buf, sizeof(buf));                      \
+       err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf),    \
+                           fallback);                                  \
        if (err < 0)                                                    \
                return;                                                 \
        err = kstrto ## type (buf, 0, &var);                            \
        if (err) {                                                      \
-               pr_warn("can not parse nvram name %s with value %s"     \
-                       " got %i", key, buf, err);                      \
+               pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",       \
+                       prefix, name, postfix, buf, err);               \
                return;                                                 \
        }                                                               \
        if (allset && var == allset)                                    \
@@ -76,22 +90,19 @@ NVRAM_READ_VAL(u32)
 #undef NVRAM_READ_VAL
 
 static void nvram_read_u32_2(const char *prefix, const char *name,
-                            u16 *val_lo, u16 *val_hi)
+                            u16 *val_lo, u16 *val_hi, bool fallback)
 {
        char buf[100];
-       char key[40];
        int err;
        u32 val;
 
-       create_key(prefix, NULL, name, key, sizeof(key));
-
-       err = nvram_getenv(key, buf, sizeof(buf));
+       err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
        if (err < 0)
                return;
        err = kstrtou32(buf, 0, &val);
        if (err) {
-               pr_warn("can not parse nvram name %s with value %s got %i",
-                       key, buf, err);
+               pr_warn("can not parse nvram name %s%s with value %s got %i\n",
+                       prefix, name, buf, err);
                return;
        }
        *val_lo = (val & 0x0000FFFFU);
@@ -99,22 +110,20 @@ static void nvram_read_u32_2(const char *prefix, const char *name,
 }
 
 static void nvram_read_leddc(const char *prefix, const char *name,
-                            u8 *leddc_on_time, u8 *leddc_off_time)
+                            u8 *leddc_on_time, u8 *leddc_off_time,
+                            bool fallback)
 {
        char buf[100];
-       char key[40];
        int err;
        u32 val;
 
-       create_key(prefix, NULL, name, key, sizeof(key));
-
-       err = nvram_getenv(key, buf, sizeof(buf));
+       err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
        if (err < 0)
                return;
        err = kstrtou32(buf, 0, &val);
        if (err) {
-               pr_warn("can not parse nvram name %s with value %s got %i",
-                       key, buf, err);
+               pr_warn("can not parse nvram name %s%s with value %s got %i\n",
+                       prefix, name, buf, err);
                return;
        }
 
@@ -126,355 +135,435 @@ static void nvram_read_leddc(const char *prefix, const char *name,
 }
 
 static void nvram_read_macaddr(const char *prefix, const char *name,
-                              u8 (*val)[6])
+                              u8 (*val)[6], bool fallback)
 {
        char buf[100];
-       char key[40];
        int err;
 
-       create_key(prefix, NULL, name, key, sizeof(key));
-
-       err = nvram_getenv(key, buf, sizeof(buf));
+       err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
        if (err < 0)
                return;
+
        nvram_parse_macaddr(buf, *val);
 }
 
 static void nvram_read_alpha2(const char *prefix, const char *name,
-                            char (*val)[2])
+                            char (*val)[2], bool fallback)
 {
        char buf[10];
-       char key[40];
        int err;
 
-       create_key(prefix, NULL, name, key, sizeof(key));
-
-       err = nvram_getenv(key, buf, sizeof(buf));
+       err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
        if (err < 0)
                return;
        if (buf[0] == '0')
                return;
        if (strlen(buf) > 2) {
-               pr_warn("alpha2 is too long %s", buf);
+               pr_warn("alpha2 is too long %s\n", buf);
                return;
        }
        memcpy(val, buf, sizeof(val));
 }
 
 static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
-                                       const char *prefix)
+                                       const char *prefix, bool fallback)
 {
-       nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
-       if (!sprom->board_rev)
-               nvram_read_u16(NULL, NULL, "boardrev", &sprom->board_rev, 0);
-       nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
-       nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
-       nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
-       nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff);
-       nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff);
-       nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0);
-       nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0);
-       nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0);
-       nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0);
-       nvram_read_alpha2(prefix, "ccode", &sprom->alpha2);
+       nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback);
+       nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback);
+       nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback);
+       nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff, fallback);
+       nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0,
+                     fallback);
+       nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0,
+                     fallback);
+       nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0,
+                     fallback);
+       nvram_read_alpha2(prefix, "ccode", &sprom->alpha2, fallback);
 }
 
 static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
-                                     const char *prefix)
+                                     const char *prefix, bool fallback)
 {
-       nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0);
-       nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0);
-       nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0);
-       nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0);
-       nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0);
-       nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0);
-       nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0);
-       nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0);
-       nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0);
-       nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
+       nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0, fallback);
+       nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0, fallback);
+       nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0,
+                     fallback);
+       nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0, fallback);
+       nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0, fallback);
+       nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0, fallback);
 }
 
-static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix,
+                                 bool fallback)
 {
-       nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0);
-       nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0);
+       nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0,
+                      fallback);
+       nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0, fallback);
 }
 
 static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
-                                    const char *prefix)
-{
-       nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
-       nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
-       nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
-       nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
-       nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
-       nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
-       nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
-       nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
-       nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
-}
-
-static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
+                                    const char *prefix, bool fallback)
 {
-       nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-                        &sprom->boardflags_hi);
-       nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+       nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0, fallback);
+       nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0, fallback);
+       nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0,
+                     fallback);
 }
 
-static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix,
+                                   bool fallback)
 {
-       nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0);
-       nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0);
-       nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0);
-       nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0);
-       nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0);
-       nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0);
-       nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0);
-       nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0);
-       nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0);
-       nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0);
-       nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0);
-       nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0);
-       nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0);
-       nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0);
+       nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0, fallback);
+       nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0, fallback);
+       nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0, fallback);
+       nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0, fallback);
+       nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0, fallback);
+       nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0, fallback);
+       nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0, fallback);
+       nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0, fallback);
 }
 
-static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix,
+                                 bool fallback)
 {
-       nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-                        &sprom->boardflags_hi);
-       nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
-       nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
+       nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback);
        nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
-                        &sprom->leddc_off_time);
+                        &sprom->leddc_off_time, fallback);
 }
 
 static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
-                                    const char *prefix)
+                                    const char *prefix, bool fallback)
 {
-       nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-                        &sprom->boardflags_hi);
-       nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
-                        &sprom->boardflags2_hi);
-       nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
-       nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
-       nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0);
-       nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0);
-       nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf);
-       nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
-       nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
+       nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback);
+       nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0,
+                     fallback);
+       nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf, fallback);
+       nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf, fallback);
+       nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff,
+                     fallback);
        nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
-                        &sprom->leddc_off_time);
+                        &sprom->leddc_off_time, fallback);
 }
 
-static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix,
+                                   bool fallback)
 {
-       nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0);
-       nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
-       nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0);
-       nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0);
-       nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0);
-       nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0);
-       nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0);
-       nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0);
-       nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0);
-       nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0);
-       nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0);
-       nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0);
-       nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
+       nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0,
+                      fallback);
+       nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0, fallback);
+       nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0, fallback);
+       nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0, fallback);
+       nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0, fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0,
+                      fallback);
 }
 
-static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix,
+                                  bool fallback)
 {
-       nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
-       nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
-       nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0);
-       nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0);
-       nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0);
-       nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0);
-       nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0);
-       nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0);
-       nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
+       nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0,
+                     fallback);
 }
 
-static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix,
+                                  bool fallback)
 {
-       nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
+       nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0,
+                     fallback);
        nvram_read_u8(prefix, NULL, "extpagain2g",
-                     &sprom->fem.ghz2.extpa_gain, 0);
+                     &sprom->fem.ghz2.extpa_gain, 0, fallback);
        nvram_read_u8(prefix, NULL, "pdetrange2g",
-                     &sprom->fem.ghz2.pdet_range, 0);
-       nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0);
-       nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0);
-       nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0);
+                     &sprom->fem.ghz2.pdet_range, 0, fallback);
+       nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0,
+                     fallback);
        nvram_read_u8(prefix, NULL, "extpagain5g",
-                     &sprom->fem.ghz5.extpa_gain, 0);
+                     &sprom->fem.ghz5.extpa_gain, 0, fallback);
        nvram_read_u8(prefix, NULL, "pdetrange5g",
-                     &sprom->fem.ghz5.pdet_range, 0);
-       nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0);
-       nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0);
-       nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0);
-       nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0);
-       nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0);
-       nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0);
+                     &sprom->fem.ghz5.pdet_range, 0, fallback);
+       nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0,
+                     fallback);
+       nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0,
+                      fallback);
+       nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0,
+                     fallback);
        nvram_read_u8(prefix, NULL, "tempsense_slope",
-                     &sprom->tempsense_slope, 0);
-       nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0);
+                     &sprom->tempsense_slope, 0, fallback);
+       nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0,
+                      fallback);
        nvram_read_u8(prefix, NULL, "tempsense_option",
-                     &sprom->tempsense_option, 0);
+                     &sprom->tempsense_option, 0, fallback);
        nvram_read_u8(prefix, NULL, "freqoffset_corr",
-                     &sprom->freqoffset_corr, 0);
-       nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0);
-       nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0);
-       nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0);
-       nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0);
+                     &sprom->freqoffset_corr, 0, fallback);
+       nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0, fallback);
+       nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0, fallback);
        nvram_read_u8(prefix, NULL, "phycal_tempdelta",
-                     &sprom->phycal_tempdelta, 0);
-       nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0);
+                     &sprom->phycal_tempdelta, 0, fallback);
+       nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0,
+                     fallback);
        nvram_read_u8(prefix, NULL, "temps_hysteresis",
-                     &sprom->temps_hysteresis, 0);
-       nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0);
-       nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0);
+                     &sprom->temps_hysteresis, 0, fallback);
+       nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0,
+                     fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
-                     &sprom->rxgainerr2ga[0], 0);
+                     &sprom->rxgainerr2ga[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
-                     &sprom->rxgainerr2ga[1], 0);
+                     &sprom->rxgainerr2ga[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
-                     &sprom->rxgainerr2ga[2], 0);
+                     &sprom->rxgainerr2ga[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
-                     &sprom->rxgainerr5gla[0], 0);
+                     &sprom->rxgainerr5gla[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
-                     &sprom->rxgainerr5gla[1], 0);
+                     &sprom->rxgainerr5gla[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
-                     &sprom->rxgainerr5gla[2], 0);
+                     &sprom->rxgainerr5gla[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
-                     &sprom->rxgainerr5gma[0], 0);
+                     &sprom->rxgainerr5gma[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
-                     &sprom->rxgainerr5gma[1], 0);
+                     &sprom->rxgainerr5gma[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
-                     &sprom->rxgainerr5gma[2], 0);
+                     &sprom->rxgainerr5gma[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
-                     &sprom->rxgainerr5gha[0], 0);
+                     &sprom->rxgainerr5gha[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
-                     &sprom->rxgainerr5gha[1], 0);
+                     &sprom->rxgainerr5gha[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
-                     &sprom->rxgainerr5gha[2], 0);
+                     &sprom->rxgainerr5gha[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
-                     &sprom->rxgainerr5gua[0], 0);
+                     &sprom->rxgainerr5gua[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
-                     &sprom->rxgainerr5gua[1], 0);
+                     &sprom->rxgainerr5gua[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
-                     &sprom->rxgainerr5gua[2], 0);
-       nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0);
-       nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0);
-       nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0);
+                     &sprom->rxgainerr5gua[2], 0, fallback);
+       nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0,
+                     fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gla0",
-                     &sprom->noiselvl5gla[0], 0);
+                     &sprom->noiselvl5gla[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gla1",
-                     &sprom->noiselvl5gla[1], 0);
+                     &sprom->noiselvl5gla[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gla2",
-                     &sprom->noiselvl5gla[2], 0);
+                     &sprom->noiselvl5gla[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gma0",
-                     &sprom->noiselvl5gma[0], 0);
+                     &sprom->noiselvl5gma[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gma1",
-                     &sprom->noiselvl5gma[1], 0);
+                     &sprom->noiselvl5gma[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gma2",
-                     &sprom->noiselvl5gma[2], 0);
+                     &sprom->noiselvl5gma[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gha0",
-                     &sprom->noiselvl5gha[0], 0);
+                     &sprom->noiselvl5gha[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gha1",
-                     &sprom->noiselvl5gha[1], 0);
+                     &sprom->noiselvl5gha[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gha2",
-                     &sprom->noiselvl5gha[2], 0);
+                     &sprom->noiselvl5gha[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gua0",
-                     &sprom->noiselvl5gua[0], 0);
+                     &sprom->noiselvl5gua[0], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gua1",
-                     &sprom->noiselvl5gua[1], 0);
+                     &sprom->noiselvl5gua[1], 0, fallback);
        nvram_read_u8(prefix, NULL, "noiselvl5gua2",
-                     &sprom->noiselvl5gua[2], 0);
+                     &sprom->noiselvl5gua[2], 0, fallback);
        nvram_read_u8(prefix, NULL, "pcieingress_war",
-                     &sprom->pcieingress_war, 0);
+                     &sprom->pcieingress_war, 0, fallback);
 }
 
-static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix,
+                                 bool fallback)
 {
-       nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
-       nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
+       nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0,
+                      fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
-                      &sprom->legofdmbw202gpo, 0);
+                      &sprom->legofdmbw202gpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
-                      &sprom->legofdmbw20ul2gpo, 0);
+                      &sprom->legofdmbw20ul2gpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
-                      &sprom->legofdmbw205glpo, 0);
+                      &sprom->legofdmbw205glpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
-                      &sprom->legofdmbw20ul5glpo, 0);
+                      &sprom->legofdmbw20ul5glpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
-                      &sprom->legofdmbw205gmpo, 0);
+                      &sprom->legofdmbw205gmpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
-                      &sprom->legofdmbw20ul5gmpo, 0);
+                      &sprom->legofdmbw20ul5gmpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
-                      &sprom->legofdmbw205ghpo, 0);
+                      &sprom->legofdmbw205ghpo, 0, fallback);
        nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
-                      &sprom->legofdmbw20ul5ghpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0);
+                      &sprom->legofdmbw20ul5ghpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0,
+                      fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0,
+                      fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0,
+                      fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0,
+                      fallback);
        nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
-                      &sprom->mcsbw20ul5glpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0);
+                      &sprom->mcsbw20ul5glpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0,
+                      fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0,
+                      fallback);
        nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
-                      &sprom->mcsbw20ul5gmpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0);
+                      &sprom->mcsbw20ul5gmpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0,
+                      fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0,
+                      fallback);
        nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
-                      &sprom->mcsbw20ul5ghpo, 0);
-       nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0);
-       nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0);
+                      &sprom->mcsbw20ul5ghpo, 0, fallback);
+       nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0, fallback);
        nvram_read_u16(prefix, NULL, "legofdm40duppo",
-                      &sprom->legofdm40duppo, 0);
-       nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0);
-       nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0);
+                      &sprom->legofdm40duppo, 0, fallback);
+       nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0, fallback);
+       nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0, fallback);
 }
 
 static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
-                                         const char *prefix)
+                                         const char *prefix, bool fallback)
 {
        char postfix[2];
        int i;
@@ -483,46 +572,46 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
                struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
                snprintf(postfix, sizeof(postfix), "%i", i);
                nvram_read_u8(prefix, postfix, "maxp2ga",
-                             &pwr_info->maxpwr_2g, 0);
+                             &pwr_info->maxpwr_2g, 0, fallback);
                nvram_read_u8(prefix, postfix, "itt2ga",
-                             &pwr_info->itssi_2g, 0);
+                             &pwr_info->itssi_2g, 0, fallback);
                nvram_read_u8(prefix, postfix, "itt5ga",
-                             &pwr_info->itssi_5g, 0);
+                             &pwr_info->itssi_5g, 0, fallback);
                nvram_read_u16(prefix, postfix, "pa2gw0a",
-                              &pwr_info->pa_2g[0], 0);
+                              &pwr_info->pa_2g[0], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa2gw1a",
-                              &pwr_info->pa_2g[1], 0);
+                              &pwr_info->pa_2g[1], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa2gw2a",
-                              &pwr_info->pa_2g[2], 0);
+                              &pwr_info->pa_2g[2], 0, fallback);
                nvram_read_u8(prefix, postfix, "maxp5ga",
-                             &pwr_info->maxpwr_5g, 0);
+                             &pwr_info->maxpwr_5g, 0, fallback);
                nvram_read_u8(prefix, postfix, "maxp5gha",
-                             &pwr_info->maxpwr_5gh, 0);
+                             &pwr_info->maxpwr_5gh, 0, fallback);
                nvram_read_u8(prefix, postfix, "maxp5gla",
-                             &pwr_info->maxpwr_5gl, 0);
+                             &pwr_info->maxpwr_5gl, 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5gw0a",
-                              &pwr_info->pa_5g[0], 0);
+                              &pwr_info->pa_5g[0], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5gw1a",
-                              &pwr_info->pa_5g[1], 0);
+                              &pwr_info->pa_5g[1], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5gw2a",
-                              &pwr_info->pa_5g[2], 0);
+                              &pwr_info->pa_5g[2], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5glw0a",
-                              &pwr_info->pa_5gl[0], 0);
+                              &pwr_info->pa_5gl[0], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5glw1a",
-                              &pwr_info->pa_5gl[1], 0);
+                              &pwr_info->pa_5gl[1], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5glw2a",
-                              &pwr_info->pa_5gl[2], 0);
+                              &pwr_info->pa_5gl[2], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5ghw0a",
-                              &pwr_info->pa_5gh[0], 0);
+                              &pwr_info->pa_5gh[0], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5ghw1a",
-                              &pwr_info->pa_5gh[1], 0);
+                              &pwr_info->pa_5gh[1], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5ghw2a",
-                              &pwr_info->pa_5gh[2], 0);
+                              &pwr_info->pa_5gh[2], 0, fallback);
        }
 }
 
 static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
-                                       const char *prefix)
+                                       const char *prefix, bool fallback)
 {
        char postfix[2];
        int i;
@@ -531,91 +620,112 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
                struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
                snprintf(postfix, sizeof(postfix), "%i", i);
                nvram_read_u16(prefix, postfix, "pa2gw3a",
-                              &pwr_info->pa_2g[3], 0);
+                              &pwr_info->pa_2g[3], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5gw3a",
-                              &pwr_info->pa_5g[3], 0);
+                              &pwr_info->pa_5g[3], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5glw3a",
-                              &pwr_info->pa_5gl[3], 0);
+                              &pwr_info->pa_5gl[3], 0, fallback);
                nvram_read_u16(prefix, postfix, "pa5ghw3a",
-                              &pwr_info->pa_5gh[3], 0);
+                              &pwr_info->pa_5gh[3], 0, fallback);
        }
 }
 
-void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
+                                       const char *prefix, bool fallback)
 {
-       nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac);
-       nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0);
-       nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0);
-
-       nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac);
-       nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0);
-       nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0);
+       nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac, fallback);
+       nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
+                     fallback);
+
+       nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac, fallback);
+       nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
+                     fallback);
+       nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
+                     fallback);
+
+       nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac, fallback);
+       nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac, fallback);
+}
 
-       nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac);
-       nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac);
+static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
+                                   bool fallback)
+{
+       nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0,
+                      fallback);
+       nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0,
+                      fallback);
+       nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+                        &sprom->boardflags_hi, fallback);
+       nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
+                        &sprom->boardflags2_hi, fallback);
 }
 
-void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
+                       bool fallback)
 {
-       bcm47xx_fill_sprom_ethernet(sprom, prefix);
+       bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback);
+       bcm47xx_fill_board_data(sprom, prefix, fallback);
 
-       nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
+       nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback);
 
        switch (sprom->revision) {
        case 1:
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r12389(sprom, prefix);
-               bcm47xx_fill_sprom_r1(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r1(sprom, prefix, fallback);
                break;
        case 2:
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r12389(sprom, prefix);
-               bcm47xx_fill_sprom_r2389(sprom, prefix);
-               bcm47xx_fill_sprom_r2(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
                break;
        case 3:
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r12389(sprom, prefix);
-               bcm47xx_fill_sprom_r2389(sprom, prefix);
-               bcm47xx_fill_sprom_r389(sprom, prefix);
-               bcm47xx_fill_sprom_r3(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r3(sprom, prefix, fallback);
                break;
        case 4:
        case 5:
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r4589(sprom, prefix);
-               bcm47xx_fill_sprom_r458(sprom, prefix);
-               bcm47xx_fill_sprom_r45(sprom, prefix);
-               bcm47xx_fill_sprom_path_r4589(sprom, prefix);
-               bcm47xx_fill_sprom_path_r45(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r458(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r45(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);
                break;
        case 8:
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r12389(sprom, prefix);
-               bcm47xx_fill_sprom_r2389(sprom, prefix);
-               bcm47xx_fill_sprom_r389(sprom, prefix);
-               bcm47xx_fill_sprom_r4589(sprom, prefix);
-               bcm47xx_fill_sprom_r458(sprom, prefix);
-               bcm47xx_fill_sprom_r89(sprom, prefix);
-               bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r458(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r89(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
                break;
        case 9:
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r12389(sprom, prefix);
-               bcm47xx_fill_sprom_r2389(sprom, prefix);
-               bcm47xx_fill_sprom_r389(sprom, prefix);
-               bcm47xx_fill_sprom_r4589(sprom, prefix);
-               bcm47xx_fill_sprom_r89(sprom, prefix);
-               bcm47xx_fill_sprom_r9(sprom, prefix);
-               bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r89(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r9(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
                break;
        default:
                pr_warn("Unsupported SPROM revision %d detected. Will extract"
                        " v1\n", sprom->revision);
                sprom->revision = 1;
-               bcm47xx_fill_sprom_r1234589(sprom, prefix);
-               bcm47xx_fill_sprom_r12389(sprom, prefix);
-               bcm47xx_fill_sprom_r1(sprom, prefix);
+               bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+               bcm47xx_fill_sprom_r1(sprom, prefix, fallback);
        }
 }
 
@@ -623,11 +733,12 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
 void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
                                const char *prefix)
 {
-       nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
+       nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
+                      true);
        if (!boardinfo->vendor)
                boardinfo->vendor = SSB_BOARDVENDOR_BCM;
 
-       nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
+       nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
 }
 #endif
 
@@ -635,10 +746,11 @@ void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
 void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
                                 const char *prefix)
 {
-       nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
+       nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
+                      true);
        if (!boardinfo->vendor)
                boardinfo->vendor = SSB_BOARDVENDOR_BCM;
 
-       nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
+       nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
 }
 #endif
index e80d585731aa8ed8d2e89597e2ddeb65150ce036..9d111e8087ecff0c7740b9179db2ecdeacd4047c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/leds.h>
 #include <linux/mtd/physmap.h>
 #include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_embedded.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/gpio.h>
@@ -116,7 +117,8 @@ static irqreturn_t gpio_interrupt(int irq, void *ignored)
 
        /* Interrupt are level triggered, revert the interrupt polarity
           to clear the interrupt. */
-       gpio_polarity(WGT634U_GPIO_RESET, state);
+       ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << WGT634U_GPIO_RESET,
+                         state ? 1 << WGT634U_GPIO_RESET : 0);
 
        if (!state) {
                printk(KERN_INFO "Reset button pressed");
@@ -150,7 +152,9 @@ static int __init wgt634u_init(void)
                                 gpio_interrupt, IRQF_SHARED,
                                 "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
                        gpio_direction_input(WGT634U_GPIO_RESET);
-                       gpio_intmask(WGT634U_GPIO_RESET, 1);
+                       ssb_gpio_intmask(&bcm47xx_bus.ssb,
+                                        1 << WGT634U_GPIO_RESET,
+                                        1 << WGT634U_GPIO_RESET);
                        ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
                                            SSB_CHIPCO_IRQ_GPIO,
                                            SSB_CHIPCO_IRQ_GPIO);
index 9bbb30a9dc2061e586eefe8b7a38a7192010d468..ac2807397c1c8c80be2d525eeb8cc5307ff7c406 100644 (file)
@@ -1,6 +1,7 @@
-obj-y          += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
-                  dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
-                  dev-spi.o dev-uart.o dev-wdt.o dev-usb-usbd.o
+obj-y          += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
+                  setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
+                  dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \
+                  dev-usb-usbd.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
 obj-y          += boards/
index 1cd4d73f23c77529e2bce3aea1502c27400aae0a..73be9b3496901510d7afdfc01e71e13c70ac52cb 100644 (file)
@@ -18,6 +18,7 @@
 #include <bcm63xx_dev_uart.h>
 #include <bcm63xx_regs.h>
 #include <bcm63xx_io.h>
+#include <bcm63xx_nvram.h>
 #include <bcm63xx_dev_pci.h>
 #include <bcm63xx_dev_enet.h>
 #include <bcm63xx_dev_dsp.h>
@@ -29,8 +30,6 @@
 
 #define PFX    "board_bcm963xx: "
 
-static struct bcm963xx_nvram nvram;
-static unsigned int mac_addr_used;
 static struct board_info board;
 
 /*
@@ -715,51 +714,15 @@ const char *board_get_name(void)
        return board.name;
 }
 
-/*
- * register & return a new board mac address
- */
-static int board_get_mac_address(u8 *mac)
-{
-       u8 *oui;
-       int count;
-
-       if (mac_addr_used >= nvram.mac_addr_count) {
-               printk(KERN_ERR PFX "not enough mac address\n");
-               return -ENODEV;
-       }
-
-       memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
-       oui = mac + ETH_ALEN/2 - 1;
-       count = mac_addr_used;
-
-       while (count--) {
-               u8 *p = mac + ETH_ALEN - 1;
-
-               do {
-                       (*p)++;
-                       if (*p != 0)
-                               break;
-                       p--;
-               } while (p != oui);
-
-               if (p == oui) {
-                       printk(KERN_ERR PFX "unable to fetch mac address\n");
-                       return -ENODEV;
-               }
-       }
-
-       mac_addr_used++;
-       return 0;
-}
-
 /*
  * early init callback, read nvram data from flash and checksum it
  */
 void __init board_prom_init(void)
 {
-       unsigned int check_len, i;
-       u8 *boot_addr, *cfe, *p;
+       unsigned int i;
+       u8 *boot_addr, *cfe;
        char cfe_version[32];
+       char *board_name;
        u32 val;
 
        /* read base address of boot chip select (0)
@@ -782,27 +745,15 @@ void __init board_prom_init(void)
                strcpy(cfe_version, "unknown");
        printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
 
-       /* extract nvram data */
-       memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
-
-       /* check checksum before using data */
-       if (nvram.version <= 4)
-               check_len = offsetof(struct bcm963xx_nvram, checksum_old);
-       else
-               check_len = sizeof(nvram);
-       val = 0;
-       p = (u8 *)&nvram;
-       while (check_len--)
-               val += *p;
-       if (val) {
+       if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
                printk(KERN_ERR PFX "invalid nvram checksum\n");
                return;
        }
 
+       board_name = bcm63xx_nvram_get_name();
        /* find board by name */
        for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
-               if (strncmp(nvram.name, bcm963xx_boards[i]->name,
-                           sizeof(nvram.name)))
+               if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
                        continue;
                /* copy, board desc array is marked initdata */
                memcpy(&board, bcm963xx_boards[i], sizeof(board));
@@ -812,7 +763,7 @@ void __init board_prom_init(void)
        /* bail out if board is not found, will complain later */
        if (!board.name[0]) {
                char name[17];
-               memcpy(name, nvram.name, 16);
+               memcpy(name, board_name, 16);
                name[16] = 0;
                printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
                       name);
@@ -890,11 +841,11 @@ int __init board_register_devices(void)
                bcm63xx_pcmcia_register();
 
        if (board.has_enet0 &&
-           !board_get_mac_address(board.enet0.mac_addr))
+           !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
                bcm63xx_enet_register(0, &board.enet0);
 
        if (board.has_enet1 &&
-           !board_get_mac_address(board.enet1.mac_addr))
+           !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
                bcm63xx_enet_register(1, &board.enet1);
 
        if (board.has_usbd)
@@ -907,7 +858,7 @@ int __init board_register_devices(void)
         * do this after registering enet devices
         */
 #ifdef CONFIG_SSB_PCIHOST
-       if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
+       if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
                memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
                memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
                if (ssb_arch_register_fallback_sprom(
index dff79ab6005e725930e530134b769b0545473209..b9e948d594300281cc4199c3a89e5756630e111d 100644 (file)
@@ -14,6 +14,7 @@
 #include <bcm63xx_cpu.h>
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
+#include <bcm63xx_reset.h>
 #include <bcm63xx_clk.h>
 
 static DEFINE_MUTEX(clocks_mutex);
@@ -124,15 +125,10 @@ static void enetsw_set(struct clk *clk, int enable)
                        CKCTL_6368_SWPKT_USB_EN |
                        CKCTL_6368_SWPKT_SAR_EN, enable);
        if (enable) {
-               u32 val;
-
                /* reset switch core afer clock change */
-               val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
-               val &= ~SOFTRESET_6368_ENETSW_MASK;
-               bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+               bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
                msleep(10);
-               val |= SOFTRESET_6368_ENETSW_MASK;
-               bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+               bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
                msleep(10);
        }
 }
@@ -222,15 +218,10 @@ static void xtm_set(struct clk *clk, int enable)
                        CKCTL_6368_SWPKT_SAR_EN, enable);
 
        if (enable) {
-               u32 val;
-
                /* reset sar core afer clock change */
-               val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
-               val &= ~SOFTRESET_6368_SAR_MASK;
-               bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+               bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
                mdelay(1);
-               val |= SOFTRESET_6368_SAR_MASK;
-               bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+               bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
                mdelay(1);
        }
 }
@@ -252,6 +243,19 @@ static struct clk clk_ipsec = {
        .set    = ipsec_set,
 };
 
+/*
+ * PCIe clock
+ */
+
+static void pcie_set(struct clk *clk, int enable)
+{
+       bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
+}
+
+static struct clk clk_pcie = {
+       .set    = pcie_set,
+};
+
 /*
  * Internal peripheral clock
  */
@@ -313,6 +317,8 @@ struct clk *clk_get(struct device *dev, const char *id)
                return &clk_pcm;
        if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
                return &clk_ipsec;
+       if (BCMCPU_IS_6328() && !strcmp(id, "pcie"))
+               return &clk_pcie;
        return ERR_PTR(-ENOENT);
 }
 
diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
new file mode 100644 (file)
index 0000000..6206116
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
+
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+
+#include <bcm63xx_nvram.h>
+
+/*
+ * nvram structure
+ */
+struct bcm963xx_nvram {
+       u32     version;
+       u8      reserved1[256];
+       u8      name[16];
+       u32     main_tp_number;
+       u32     psi_size;
+       u32     mac_addr_count;
+       u8      mac_addr_base[ETH_ALEN];
+       u8      reserved2[2];
+       u32     checksum_old;
+       u8      reserved3[720];
+       u32     checksum_high;
+};
+
+static struct bcm963xx_nvram nvram;
+static int mac_addr_used;
+
+int __init bcm63xx_nvram_init(void *addr)
+{
+       unsigned int check_len;
+       u32 crc, expected_crc;
+
+       /* extract nvram data */
+       memcpy(&nvram, addr, sizeof(nvram));
+
+       /* check checksum before using data */
+       if (nvram.version <= 4) {
+               check_len = offsetof(struct bcm963xx_nvram, reserved3);
+               expected_crc = nvram.checksum_old;
+               nvram.checksum_old = 0;
+       } else {
+               check_len = sizeof(nvram);
+               expected_crc = nvram.checksum_high;
+               nvram.checksum_high = 0;
+       }
+
+       crc = crc32_le(~0, (u8 *)&nvram, check_len);
+
+       if (crc != expected_crc)
+               return -EINVAL;
+
+       return 0;
+}
+
+u8 *bcm63xx_nvram_get_name(void)
+{
+       return nvram.name;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_name);
+
+int bcm63xx_nvram_get_mac_address(u8 *mac)
+{
+       u8 *oui;
+       int count;
+
+       if (mac_addr_used >= nvram.mac_addr_count) {
+               pr_err("not enough mac addresses\n");
+               return -ENODEV;
+       }
+
+       memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
+       oui = mac + ETH_ALEN/2 - 1;
+       count = mac_addr_used;
+
+       while (count--) {
+               u8 *p = mac + ETH_ALEN - 1;
+
+               do {
+                       (*p)++;
+                       if (*p != 0)
+                               break;
+                       p--;
+               } while (p != oui);
+
+               if (p == oui) {
+                       pr_err("unable to fetch mac address\n");
+                       return -ENODEV;
+               }
+       }
+
+       mac_addr_used++;
+       return 0;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c
new file mode 100644 (file)
index 0000000..68a31bb
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * 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) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_reset.h>
+
+#define __GEN_RESET_BITS_TABLE(__cpu)                                  \
+       [BCM63XX_RESET_SPI]             = BCM## __cpu ##_RESET_SPI,     \
+       [BCM63XX_RESET_ENET]            = BCM## __cpu ##_RESET_ENET,    \
+       [BCM63XX_RESET_USBH]            = BCM## __cpu ##_RESET_USBH,    \
+       [BCM63XX_RESET_USBD]            = BCM## __cpu ##_RESET_USBD,    \
+       [BCM63XX_RESET_DSL]             = BCM## __cpu ##_RESET_DSL,     \
+       [BCM63XX_RESET_SAR]             = BCM## __cpu ##_RESET_SAR,     \
+       [BCM63XX_RESET_EPHY]            = BCM## __cpu ##_RESET_EPHY,    \
+       [BCM63XX_RESET_ENETSW]          = BCM## __cpu ##_RESET_ENETSW,  \
+       [BCM63XX_RESET_PCM]             = BCM## __cpu ##_RESET_PCM,     \
+       [BCM63XX_RESET_MPI]             = BCM## __cpu ##_RESET_MPI,     \
+       [BCM63XX_RESET_PCIE]            = BCM## __cpu ##_RESET_PCIE,    \
+       [BCM63XX_RESET_PCIE_EXT]        = BCM## __cpu ##_RESET_PCIE_EXT,
+
+#define BCM6328_RESET_SPI      SOFTRESET_6328_SPI_MASK
+#define BCM6328_RESET_ENET     0
+#define BCM6328_RESET_USBH     SOFTRESET_6328_USBH_MASK
+#define BCM6328_RESET_USBD     SOFTRESET_6328_USBS_MASK
+#define BCM6328_RESET_DSL      0
+#define BCM6328_RESET_SAR      SOFTRESET_6328_SAR_MASK
+#define BCM6328_RESET_EPHY     SOFTRESET_6328_EPHY_MASK
+#define BCM6328_RESET_ENETSW   SOFTRESET_6328_ENETSW_MASK
+#define BCM6328_RESET_PCM      SOFTRESET_6328_PCM_MASK
+#define BCM6328_RESET_MPI      0
+#define BCM6328_RESET_PCIE     \
+                               (SOFTRESET_6328_PCIE_MASK |             \
+                                SOFTRESET_6328_PCIE_CORE_MASK |        \
+                                SOFTRESET_6328_PCIE_HARD_MASK)
+#define BCM6328_RESET_PCIE_EXT SOFTRESET_6328_PCIE_EXT_MASK
+
+#define BCM6338_RESET_SPI      SOFTRESET_6338_SPI_MASK
+#define BCM6338_RESET_ENET     SOFTRESET_6338_ENET_MASK
+#define BCM6338_RESET_USBH     SOFTRESET_6338_USBH_MASK
+#define BCM6338_RESET_USBD     SOFTRESET_6338_USBS_MASK
+#define BCM6338_RESET_DSL      SOFTRESET_6338_ADSL_MASK
+#define BCM6338_RESET_SAR      SOFTRESET_6338_SAR_MASK
+#define BCM6338_RESET_EPHY     0
+#define BCM6338_RESET_ENETSW   0
+#define BCM6338_RESET_PCM      0
+#define BCM6338_RESET_MPI      0
+#define BCM6338_RESET_PCIE     0
+#define BCM6338_RESET_PCIE_EXT 0
+
+#define BCM6348_RESET_SPI      SOFTRESET_6348_SPI_MASK
+#define BCM6348_RESET_ENET     SOFTRESET_6348_ENET_MASK
+#define BCM6348_RESET_USBH     SOFTRESET_6348_USBH_MASK
+#define BCM6348_RESET_USBD     SOFTRESET_6348_USBS_MASK
+#define BCM6348_RESET_DSL      SOFTRESET_6348_ADSL_MASK
+#define BCM6348_RESET_SAR      SOFTRESET_6348_SAR_MASK
+#define BCM6348_RESET_EPHY     0
+#define BCM6348_RESET_ENETSW   0
+#define BCM6348_RESET_PCM      0
+#define BCM6348_RESET_MPI      0
+#define BCM6348_RESET_PCIE     0
+#define BCM6348_RESET_PCIE_EXT 0
+
+#define BCM6358_RESET_SPI      SOFTRESET_6358_SPI_MASK
+#define BCM6358_RESET_ENET     SOFTRESET_6358_ENET_MASK
+#define BCM6358_RESET_USBH     SOFTRESET_6358_USBH_MASK
+#define BCM6358_RESET_USBD     0
+#define BCM6358_RESET_DSL      SOFTRESET_6358_ADSL_MASK
+#define BCM6358_RESET_SAR      SOFTRESET_6358_SAR_MASK
+#define BCM6358_RESET_EPHY     SOFTRESET_6358_EPHY_MASK
+#define BCM6358_RESET_ENETSW   0
+#define BCM6358_RESET_PCM      SOFTRESET_6358_PCM_MASK
+#define BCM6358_RESET_MPI      SOFTRESET_6358_MPI_MASK
+#define BCM6358_RESET_PCIE     0
+#define BCM6358_RESET_PCIE_EXT 0
+
+#define BCM6368_RESET_SPI      SOFTRESET_6368_SPI_MASK
+#define BCM6368_RESET_ENET     0
+#define BCM6368_RESET_USBH     SOFTRESET_6368_USBH_MASK
+#define BCM6368_RESET_USBD     SOFTRESET_6368_USBS_MASK
+#define BCM6368_RESET_DSL      0
+#define BCM6368_RESET_SAR      SOFTRESET_6368_SAR_MASK
+#define BCM6368_RESET_EPHY     SOFTRESET_6368_EPHY_MASK
+#define BCM6368_RESET_ENETSW   0
+#define BCM6368_RESET_PCM      SOFTRESET_6368_PCM_MASK
+#define BCM6368_RESET_MPI      SOFTRESET_6368_MPI_MASK
+#define BCM6368_RESET_PCIE     0
+#define BCM6368_RESET_PCIE_EXT 0
+
+#ifdef BCMCPU_RUNTIME_DETECT
+
+/*
+ * core reset bits
+ */
+static const u32 bcm6328_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6328)
+};
+
+static const u32 bcm6338_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6338)
+};
+
+static const u32 bcm6348_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6348)
+};
+
+static const u32 bcm6358_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6358)
+};
+
+static const u32 bcm6368_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6368)
+};
+
+const u32 *bcm63xx_reset_bits;
+static int reset_reg;
+
+static int __init bcm63xx_reset_bits_init(void)
+{
+       if (BCMCPU_IS_6328()) {
+               reset_reg = PERF_SOFTRESET_6328_REG;
+               bcm63xx_reset_bits = bcm6328_reset_bits;
+       } else if (BCMCPU_IS_6338()) {
+               reset_reg = PERF_SOFTRESET_REG;
+               bcm63xx_reset_bits = bcm6338_reset_bits;
+       } else if (BCMCPU_IS_6348()) {
+               reset_reg = PERF_SOFTRESET_REG;
+               bcm63xx_reset_bits = bcm6348_reset_bits;
+       } else if (BCMCPU_IS_6358()) {
+               reset_reg = PERF_SOFTRESET_6358_REG;
+               bcm63xx_reset_bits = bcm6358_reset_bits;
+       } else if (BCMCPU_IS_6368()) {
+               reset_reg = PERF_SOFTRESET_6368_REG;
+               bcm63xx_reset_bits = bcm6368_reset_bits;
+       }
+
+       return 0;
+}
+#else
+
+#ifdef CONFIG_BCM63XX_CPU_6328
+static const u32 bcm63xx_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6328)
+};
+#define reset_reg PERF_SOFTRESET_6328_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6338
+static const u32 bcm63xx_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6338)
+};
+#define reset_reg PERF_SOFTRESET_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6345
+static const u32 bcm63xx_reset_bits[] = { };
+#define reset_reg 0
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6348
+static const u32 bcm63xx_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6348)
+};
+#define reset_reg PERF_SOFTRESET_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6358
+static const u32 bcm63xx_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6358)
+};
+#define reset_reg PERF_SOFTRESET_6358_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6368
+static const u32 bcm63xx_reset_bits[] = {
+       __GEN_RESET_BITS_TABLE(6368)
+};
+#define reset_reg PERF_SOFTRESET_6368_REG
+#endif
+
+static int __init bcm63xx_reset_bits_init(void) { return 0; }
+#endif
+
+static DEFINE_SPINLOCK(reset_mutex);
+
+static void __bcm63xx_core_set_reset(u32 mask, int enable)
+{
+       unsigned long flags;
+       u32 val;
+
+       if (!mask)
+               return;
+
+       spin_lock_irqsave(&reset_mutex, flags);
+       val = bcm_perf_readl(reset_reg);
+
+       if (enable)
+               val &= ~mask;
+       else
+               val |= mask;
+
+       bcm_perf_writel(val, reset_reg);
+       spin_unlock_irqrestore(&reset_mutex, flags);
+}
+
+void bcm63xx_core_set_reset(enum bcm63xx_core_reset core, int reset)
+{
+       __bcm63xx_core_set_reset(bcm63xx_reset_bits[core], reset);
+}
+EXPORT_SYMBOL(bcm63xx_core_set_reset);
+
+postcore_initcall(bcm63xx_reset_bits_init);
index fdf5f19bfdb06226b0296ab52ce1d3b453c1ccdd..6d5ddbc112cc355a8dbfbbddd3e2136e81a06957 100644 (file)
@@ -688,3 +688,8 @@ int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
                cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
        return addr_allocated;
 }
+
+struct cvmx_bootmem_desc *cvmx_bootmem_get_desc(void)
+{
+       return cvmx_bootmem_desc;
+}
index e44a55bc7f0dc13c5901a47ddfb00c5c6ed8f6d5..237e5b1a72d8e51357c3a38edc9120565e460dbd 100644 (file)
@@ -51,7 +51,8 @@ static int __init flash_init(void)
                flash_map.name = "phys_mapped_flash";
                flash_map.phys = region_cfg.s.base << 16;
                flash_map.size = 0x1fc00000 - flash_map.phys;
-               flash_map.bankwidth = 1;
+               /* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */
+               flash_map.bankwidth = region_cfg.s.width + 1;
                flash_map.virt = ioremap(flash_map.phys, flash_map.size);
                pr_notice("Bootbus flash: Setting flash for %luMB flash at "
                          "0x%08llx\n", flash_map.size >> 20, flash_map.phys);
index 02b15eed4bcd379cc0312cba80a5feb10655fa7d..46f5dbceeeccb3a04485a8adf816a91b2e3cef4e 100644 (file)
@@ -1266,7 +1266,6 @@ static void __init octeon_irq_init_ciu(void)
                octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
 
        octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
-       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_BOOTDMA, 0, 63);
 
        /* CIU_1 */
        for (i = 0; i < 16; i++)
index db478dbb9c7beb87c1cef87932e9a5e107ce8991..0ba0eb96d9ac1e3706c613335fd14104ff1c62b5 100644 (file)
 /*
  * Only on the 64-bit kernel we can made use of 64-bit registers.
  */
-#ifdef CONFIG_64BIT
-#define USE_DOUBLE
-#endif
-
-#ifdef USE_DOUBLE
 
 #define LOAD   ld
 #define LOADL  ldl
 #define t6     $14
 #define t7     $15
 
-#else
-
-#define LOAD   lw
-#define LOADL  lwl
-#define LOADR  lwr
-#define STOREL swl
-#define STORER swr
-#define STORE  sw
-#define ADD    addu
-#define SUB    subu
-#define SRL    srl
-#define SLL    sll
-#define SRA    sra
-#define SLLV   sllv
-#define SRLV   srlv
-#define NBYTES 4
-#define LOG_NBYTES 2
-
-#endif /* USE_DOUBLE */
-
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 #define LDFIRST LOADR
 #define LDREST  LOADL
@@ -395,12 +370,10 @@ EXC(       sb     t0, N(dst), s_exc_p1)
 
        COPY_BYTE(0)
        COPY_BYTE(1)
-#ifdef USE_DOUBLE
        COPY_BYTE(2)
        COPY_BYTE(3)
        COPY_BYTE(4)
        COPY_BYTE(5)
-#endif
 EXC(   lb      t0, NBYTES-2(src), l_exc)
        SUB     len, len, 1
        jr      ra
index 0938df10a71c54f8816c866b86e602deef54102b..3c1b625a5859046a9d186fb18f4ed691854e892c 100644 (file)
 #include <asm/octeon/cvmx-helper.h>
 #include <asm/octeon/cvmx-helper-board.h>
 
-static struct octeon_cf_data octeon_cf_data;
-
-static int __init octeon_cf_device_init(void)
-{
-       union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
-       unsigned long base_ptr, region_base, region_size;
-       struct platform_device *pd;
-       struct resource cf_resources[3];
-       unsigned int num_resources;
-       int i;
-       int ret = 0;
-
-       /* Setup octeon-cf platform device if present. */
-       base_ptr = 0;
-       if (octeon_bootinfo->major_version == 1
-               && octeon_bootinfo->minor_version >= 1) {
-               if (octeon_bootinfo->compact_flash_common_base_addr)
-                       base_ptr =
-                               octeon_bootinfo->compact_flash_common_base_addr;
-       } else {
-               base_ptr = 0x1d000800;
-       }
-
-       if (!base_ptr)
-               return ret;
-
-       /* Find CS0 region. */
-       for (i = 0; i < 8; i++) {
-               mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i));
-               region_base = mio_boot_reg_cfg.s.base << 16;
-               region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
-               if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
-                   && base_ptr < region_base + region_size)
-                       break;
-       }
-       if (i >= 7) {
-               /* i and i + 1 are CS0 and CS1, both must be less than 8. */
-               goto out;
-       }
-       octeon_cf_data.base_region = i;
-       octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width;
-       octeon_cf_data.base_region_bias = base_ptr - region_base;
-       memset(cf_resources, 0, sizeof(cf_resources));
-       num_resources = 0;
-       cf_resources[num_resources].flags       = IORESOURCE_MEM;
-       cf_resources[num_resources].start       = region_base;
-       cf_resources[num_resources].end = region_base + region_size - 1;
-       num_resources++;
-
-
-       if (!(base_ptr & 0xfffful)) {
-               /*
-                * Boot loader signals availability of DMA (true_ide
-                * mode) by setting low order bits of base_ptr to
-                * zero.
-                */
-
-               /* Assume that CS1 immediately follows. */
-               mio_boot_reg_cfg.u64 =
-                       cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1));
-               region_base = mio_boot_reg_cfg.s.base << 16;
-               region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
-               if (!mio_boot_reg_cfg.s.en)
-                       goto out;
-
-               cf_resources[num_resources].flags       = IORESOURCE_MEM;
-               cf_resources[num_resources].start       = region_base;
-               cf_resources[num_resources].end = region_base + region_size - 1;
-               num_resources++;
-
-               octeon_cf_data.dma_engine = 0;
-               cf_resources[num_resources].flags       = IORESOURCE_IRQ;
-               cf_resources[num_resources].start       = OCTEON_IRQ_BOOTDMA;
-               cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA;
-               num_resources++;
-       } else {
-               octeon_cf_data.dma_engine = -1;
-       }
-
-       pd = platform_device_alloc("pata_octeon_cf", -1);
-       if (!pd) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       pd->dev.platform_data = &octeon_cf_data;
-
-       ret = platform_device_add_resources(pd, cf_resources, num_resources);
-       if (ret)
-               goto fail;
-
-       ret = platform_device_add(pd);
-       if (ret)
-               goto fail;
-
-       return ret;
-fail:
-       platform_device_put(pd);
-out:
-       return ret;
-}
-device_initcall(octeon_cf_device_init);
-
 /* Octeon Random Number Generator.  */
 static int __init octeon_rng_device_init(void)
 {
index 04dd8ff0e0d8979b639c60b932be4eabee951903..d7e0a09f77c2db27ab7657b40d56894a24ab6c2e 100644 (file)
@@ -4,9 +4,11 @@
  * for more details.
  *
  * Copyright (C) 2004-2007 Cavium Networks
- * Copyright (C) 2008 Wind River Systems
+ * Copyright (C) 2008, 2009 Wind River Systems
+ *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/export.h>
@@ -23,6 +25,7 @@
 #include <linux/serial_8250.h>
 #include <linux/of_fdt.h>
 #include <linux/libfdt.h>
+#include <linux/kexec.h>
 
 #include <asm/processor.h>
 #include <asm/reboot.h>
@@ -56,11 +59,208 @@ struct octeon_boot_descriptor *octeon_boot_desc_ptr;
 struct cvmx_bootinfo *octeon_bootinfo;
 EXPORT_SYMBOL(octeon_bootinfo);
 
+static unsigned long long RESERVE_LOW_MEM = 0ull;
+#ifdef CONFIG_KEXEC
+#ifdef CONFIG_SMP
+/*
+ * Wait for relocation code is prepared and send
+ * secondary CPUs to spin until kernel is relocated.
+ */
+static void octeon_kexec_smp_down(void *ignored)
+{
+       int cpu = smp_processor_id();
+
+       local_irq_disable();
+       set_cpu_online(cpu, false);
+       while (!atomic_read(&kexec_ready_to_reboot))
+               cpu_relax();
+
+       asm volatile (
+       "       sync                                            \n"
+       "       synci   ($0)                                    \n");
+
+       relocated_kexec_smp_wait(NULL);
+}
+#endif
+
+#define OCTEON_DDR0_BASE    (0x0ULL)
+#define OCTEON_DDR0_SIZE    (0x010000000ULL)
+#define OCTEON_DDR1_BASE    (0x410000000ULL)
+#define OCTEON_DDR1_SIZE    (0x010000000ULL)
+#define OCTEON_DDR2_BASE    (0x020000000ULL)
+#define OCTEON_DDR2_SIZE    (0x3e0000000ULL)
+#define OCTEON_MAX_PHY_MEM_SIZE (16*1024*1024*1024ULL)
+
+static struct kimage *kimage_ptr;
+
+static void kexec_bootmem_init(uint64_t mem_size, uint32_t low_reserved_bytes)
+{
+       int64_t addr;
+       struct cvmx_bootmem_desc *bootmem_desc;
+
+       bootmem_desc = cvmx_bootmem_get_desc();
+
+       if (mem_size > OCTEON_MAX_PHY_MEM_SIZE) {
+               mem_size = OCTEON_MAX_PHY_MEM_SIZE;
+               pr_err("Error: requested memory too large,"
+                      "truncating to maximum size\n");
+       }
+
+       bootmem_desc->major_version = CVMX_BOOTMEM_DESC_MAJ_VER;
+       bootmem_desc->minor_version = CVMX_BOOTMEM_DESC_MIN_VER;
+
+       addr = (OCTEON_DDR0_BASE + RESERVE_LOW_MEM + low_reserved_bytes);
+       bootmem_desc->head_addr = 0;
+
+       if (mem_size <= OCTEON_DDR0_SIZE) {
+               __cvmx_bootmem_phy_free(addr,
+                               mem_size - RESERVE_LOW_MEM -
+                               low_reserved_bytes, 0);
+               return;
+       }
+
+       __cvmx_bootmem_phy_free(addr,
+                       OCTEON_DDR0_SIZE - RESERVE_LOW_MEM -
+                       low_reserved_bytes, 0);
+
+       mem_size -= OCTEON_DDR0_SIZE;
+
+       if (mem_size > OCTEON_DDR1_SIZE) {
+               __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, OCTEON_DDR1_SIZE, 0);
+               __cvmx_bootmem_phy_free(OCTEON_DDR2_BASE,
+                               mem_size - OCTEON_DDR1_SIZE, 0);
+       } else
+               __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, mem_size, 0);
+}
+
+static int octeon_kexec_prepare(struct kimage *image)
+{
+       int i;
+       char *bootloader = "kexec";
+
+       octeon_boot_desc_ptr->argc = 0;
+       for (i = 0; i < image->nr_segments; i++) {
+               if (!strncmp(bootloader, (char *)image->segment[i].buf,
+                               strlen(bootloader))) {
+                       /*
+                        * convert command line string to array
+                        * of parameters (as bootloader does).
+                        */
+                       int argc = 0, offt;
+                       char *str = (char *)image->segment[i].buf;
+                       char *ptr = strchr(str, ' ');
+                       while (ptr && (OCTEON_ARGV_MAX_ARGS > argc)) {
+                               *ptr = '\0';
+                               if (ptr[1] != ' ') {
+                                       offt = (int)(ptr - str + 1);
+                                       octeon_boot_desc_ptr->argv[argc] =
+                                               image->segment[i].mem + offt;
+                                       argc++;
+                               }
+                               ptr = strchr(ptr + 1, ' ');
+                       }
+                       octeon_boot_desc_ptr->argc = argc;
+                       break;
+               }
+       }
+
+       /*
+        * Information about segments will be needed during pre-boot memory
+        * initialization.
+        */
+       kimage_ptr = image;
+       return 0;
+}
+
+static void octeon_generic_shutdown(void)
+{
+       int cpu, i;
+       struct cvmx_bootmem_desc *bootmem_desc;
+       void *named_block_array_ptr;
+
+       bootmem_desc = cvmx_bootmem_get_desc();
+       named_block_array_ptr =
+               cvmx_phys_to_ptr(bootmem_desc->named_block_array_addr);
+
+#ifdef CONFIG_SMP
+       /* disable watchdogs */
+       for_each_online_cpu(cpu)
+               cvmx_write_csr(CVMX_CIU_WDOGX(cpu_logical_map(cpu)), 0);
+#else
+       cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0);
+#endif
+       if (kimage_ptr != kexec_crash_image) {
+               memset(named_block_array_ptr,
+                       0x0,
+                       CVMX_BOOTMEM_NUM_NAMED_BLOCKS *
+                       sizeof(struct cvmx_bootmem_named_block_desc));
+               /*
+                * Mark all memory (except low 0x100000 bytes) as free.
+                * It is the same thing that bootloader does.
+                */
+               kexec_bootmem_init(octeon_bootinfo->dram_size*1024ULL*1024ULL,
+                               0x100000);
+               /*
+                * Allocate all segments to avoid their corruption during boot.
+                */
+               for (i = 0; i < kimage_ptr->nr_segments; i++)
+                       cvmx_bootmem_alloc_address(
+                               kimage_ptr->segment[i].memsz + 2*PAGE_SIZE,
+                               kimage_ptr->segment[i].mem - PAGE_SIZE,
+                               PAGE_SIZE);
+       } else {
+               /*
+                * Do not mark all memory as free. Free only named sections
+                * leaving the rest of memory unchanged.
+                */
+               struct cvmx_bootmem_named_block_desc *ptr =
+                       (struct cvmx_bootmem_named_block_desc *)
+                       named_block_array_ptr;
+
+               for (i = 0; i < bootmem_desc->named_block_num_blocks; i++)
+                       if (ptr[i].size)
+                               cvmx_bootmem_free_named(ptr[i].name);
+       }
+       kexec_args[2] = 1UL; /* running on octeon_main_processor */
+       kexec_args[3] = (unsigned long)octeon_boot_desc_ptr;
+#ifdef CONFIG_SMP
+       secondary_kexec_args[2] = 0UL; /* running on secondary cpu */
+       secondary_kexec_args[3] = (unsigned long)octeon_boot_desc_ptr;
+#endif
+}
+
+static void octeon_shutdown(void)
+{
+       octeon_generic_shutdown();
+#ifdef CONFIG_SMP
+       smp_call_function(octeon_kexec_smp_down, NULL, 0);
+       smp_wmb();
+       while (num_online_cpus() > 1) {
+               cpu_relax();
+               mdelay(1);
+       }
+#endif
+}
+
+static void octeon_crash_shutdown(struct pt_regs *regs)
+{
+       octeon_generic_shutdown();
+       default_machine_crash_shutdown(regs);
+}
+
+#endif /* CONFIG_KEXEC */
+
 #ifdef CONFIG_CAVIUM_RESERVE32
 uint64_t octeon_reserve32_memory;
 EXPORT_SYMBOL(octeon_reserve32_memory);
 #endif
 
+#ifdef CONFIG_KEXEC
+/* crashkernel cmdline parameter is parsed _after_ memory setup
+ * we also parse it here (workaround for EHB5200) */
+static uint64_t crashk_size, crashk_base;
+#endif
+
 static int octeon_uart;
 
 extern asmlinkage void handle_int(void);
@@ -415,6 +615,8 @@ void octeon_user_io_init(void)
 void __init prom_init(void)
 {
        struct cvmx_sysinfo *sysinfo;
+       const char *arg;
+       char *p;
        int i;
        int argc;
 #ifdef CONFIG_CAVIUM_RESERVE32
@@ -566,6 +768,15 @@ void __init prom_init(void)
        if (octeon_is_simulation())
                MAX_MEMORY = 64ull << 20;
 
+       arg = strstr(arcs_cmdline, "mem=");
+       if (arg) {
+               MAX_MEMORY = memparse(arg + 4, &p);
+               if (MAX_MEMORY == 0)
+                       MAX_MEMORY = 32ull << 30;
+               if (*p == '@')
+                       RESERVE_LOW_MEM = memparse(p + 1, &p);
+       }
+
        arcs_cmdline[0] = 0;
        argc = octeon_boot_desc_ptr->argc;
        for (i = 0; i < argc; i++) {
@@ -573,15 +784,29 @@ void __init prom_init(void)
                        cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]);
                if ((strncmp(arg, "MEM=", 4) == 0) ||
                    (strncmp(arg, "mem=", 4) == 0)) {
-                       sscanf(arg + 4, "%llu", &MAX_MEMORY);
-                       MAX_MEMORY <<= 20;
+                       MAX_MEMORY = memparse(arg + 4, &p);
                        if (MAX_MEMORY == 0)
                                MAX_MEMORY = 32ull << 30;
+                       if (*p == '@')
+                               RESERVE_LOW_MEM = memparse(p + 1, &p);
                } else if (strcmp(arg, "ecc_verbose") == 0) {
 #ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC
                        __cvmx_interrupt_ecc_report_single_bit_errors = 1;
                        pr_notice("Reporting of single bit ECC errors is "
                                  "turned on\n");
+#endif
+#ifdef CONFIG_KEXEC
+               } else if (strncmp(arg, "crashkernel=", 12) == 0) {
+                       crashk_size = memparse(arg+12, &p);
+                       if (*p == '@')
+                               crashk_base = memparse(p+1, &p);
+                       strcat(arcs_cmdline, " ");
+                       strcat(arcs_cmdline, arg);
+                       /*
+                        * To do: switch parsing to new style, something like:
+                        * parse_crashkernel(arg, sysinfo->system_dram_size,
+                        *                &crashk_size, &crashk_base);
+                        */
 #endif
                } else if (strlen(arcs_cmdline) + strlen(arg) + 1 <
                           sizeof(arcs_cmdline) - 1) {
@@ -617,11 +842,18 @@ void __init prom_init(void)
        _machine_restart = octeon_restart;
        _machine_halt = octeon_halt;
 
+#ifdef CONFIG_KEXEC
+       _machine_kexec_shutdown = octeon_shutdown;
+       _machine_crash_shutdown = octeon_crash_shutdown;
+       _machine_kexec_prepare = octeon_kexec_prepare;
+#endif
+
        octeon_user_io_init();
        register_smp_ops(&octeon_smp_ops);
 }
 
 /* Exclude a single page from the regions obtained in plat_mem_setup. */
+#ifndef CONFIG_CRASH_DUMP
 static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size)
 {
        if (addr > *mem && addr < *mem + *size) {
@@ -636,14 +868,21 @@ static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size)
                *size -= PAGE_SIZE;
        }
 }
+#endif /* CONFIG_CRASH_DUMP */
 
 void __init plat_mem_setup(void)
 {
        uint64_t mem_alloc_size;
        uint64_t total;
+       uint64_t crashk_end;
+#ifndef CONFIG_CRASH_DUMP
        int64_t memory;
+       uint64_t kernel_start;
+       uint64_t kernel_size;
+#endif
 
        total = 0;
+       crashk_end = 0;
 
        /*
         * The Mips memory init uses the first memory location for
@@ -656,6 +895,17 @@ void __init plat_mem_setup(void)
        if (mem_alloc_size > MAX_MEMORY)
                mem_alloc_size = MAX_MEMORY;
 
+/* Crashkernel ignores bootmem list. It relies on mem=X@Y option */
+#ifdef CONFIG_CRASH_DUMP
+       add_memory_region(RESERVE_LOW_MEM, MAX_MEMORY, BOOT_MEM_RAM);
+       total += MAX_MEMORY;
+#else
+#ifdef CONFIG_KEXEC
+       if (crashk_size > 0) {
+               add_memory_region(crashk_base, crashk_size, BOOT_MEM_RAM);
+               crashk_end = crashk_base + crashk_size;
+       }
+#endif
        /*
         * When allocating memory, we want incrementing addresses from
         * bootmem_alloc so the code in add_memory_region can merge
@@ -664,22 +914,15 @@ void __init plat_mem_setup(void)
        cvmx_bootmem_lock();
        while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX)
                && (total < MAX_MEMORY)) {
-#if defined(CONFIG_64BIT) || defined(CONFIG_64BIT_PHYS_ADDR)
                memory = cvmx_bootmem_phy_alloc(mem_alloc_size,
                                                __pa_symbol(&__init_end), -1,
                                                0x100000,
                                                CVMX_BOOTMEM_FLAG_NO_LOCKING);
-#elif defined(CONFIG_HIGHMEM)
-               memory = cvmx_bootmem_phy_alloc(mem_alloc_size, 0, 1ull << 31,
-                                               0x100000,
-                                               CVMX_BOOTMEM_FLAG_NO_LOCKING);
-#else
-               memory = cvmx_bootmem_phy_alloc(mem_alloc_size, 0, 512 << 20,
-                                               0x100000,
-                                               CVMX_BOOTMEM_FLAG_NO_LOCKING);
-#endif
                if (memory >= 0) {
                        u64 size = mem_alloc_size;
+#ifdef CONFIG_KEXEC
+                       uint64_t end;
+#endif
 
                        /*
                         * exclude a page at the beginning and end of
@@ -692,20 +935,67 @@ void __init plat_mem_setup(void)
                        memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE +
                                            CVMX_PCIE_BAR1_PHYS_SIZE,
                                            &memory, &size);
+#ifdef CONFIG_KEXEC
+                       end = memory + mem_alloc_size;
 
                        /*
-                        * This function automatically merges address
-                        * regions next to each other if they are
-                        * received in incrementing order.
+                        * This function automatically merges address regions
+                        * next to each other if they are received in
+                        * incrementing order
                         */
-                       if (size)
-                               add_memory_region(memory, size, BOOT_MEM_RAM);
+                       if (memory < crashk_base && end >  crashk_end) {
+                               /* region is fully in */
+                               add_memory_region(memory,
+                                                 crashk_base - memory,
+                                                 BOOT_MEM_RAM);
+                               total += crashk_base - memory;
+                               add_memory_region(crashk_end,
+                                                 end - crashk_end,
+                                                 BOOT_MEM_RAM);
+                               total += end - crashk_end;
+                               continue;
+                       }
+
+                       if (memory >= crashk_base && end <= crashk_end)
+                               /*
+                                * Entire memory region is within the new
+                                *  kernel's memory, ignore it.
+                                */
+                               continue;
+
+                       if (memory > crashk_base && memory < crashk_end &&
+                           end > crashk_end) {
+                               /*
+                                * Overlap with the beginning of the region,
+                                * reserve the beginning.
+                                 */
+                               mem_alloc_size -= crashk_end - memory;
+                               memory = crashk_end;
+                       } else if (memory < crashk_base && end > crashk_base &&
+                                  end < crashk_end)
+                               /*
+                                * Overlap with the beginning of the region,
+                                * chop of end.
+                                */
+                               mem_alloc_size -= end - crashk_base;
+#endif
+                       add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM);
                        total += mem_alloc_size;
+                       /* Recovering mem_alloc_size */
+                       mem_alloc_size = 4 << 20;
                } else {
                        break;
                }
        }
        cvmx_bootmem_unlock();
+       /* Add the memory region for the kernel. */
+       kernel_start = (unsigned long) _text;
+       kernel_size = ALIGN(_end - _text, 0x100000);
+
+       /* Adjust for physical offset. */
+       kernel_start &= ~0xffffffff80000000ULL;
+       add_memory_region(kernel_start, kernel_size, BOOT_MEM_RAM);
+#endif /* CONFIG_CRASH_DUMP */
 
 #ifdef CONFIG_CAVIUM_RESERVE32
        /*
@@ -821,3 +1111,51 @@ void __init device_tree_init(void)
        }
        unflatten_device_tree();
 }
+
+static int __initdata disable_octeon_edac_p;
+
+static int __init disable_octeon_edac(char *str)
+{
+       disable_octeon_edac_p = 1;
+       return 0;
+}
+early_param("disable_octeon_edac", disable_octeon_edac);
+
+static char *edac_device_names[] = {
+       "octeon_l2c_edac",
+       "octeon_pc_edac",
+};
+
+static int __init edac_devinit(void)
+{
+       struct platform_device *dev;
+       int i, err = 0;
+       int num_lmc;
+       char *name;
+
+       if (disable_octeon_edac_p)
+               return 0;
+
+       for (i = 0; i < ARRAY_SIZE(edac_device_names); i++) {
+               name = edac_device_names[i];
+               dev = platform_device_register_simple(name, -1, NULL, 0);
+               if (IS_ERR(dev)) {
+                       pr_err("Registation of %s failed!\n", name);
+                       err = PTR_ERR(dev);
+               }
+       }
+
+       num_lmc = OCTEON_IS_MODEL(OCTEON_CN68XX) ? 4 :
+               (OCTEON_IS_MODEL(OCTEON_CN56XX) ? 2 : 1);
+       for (i = 0; i < num_lmc; i++) {
+               dev = platform_device_register_simple("octeon_lmc_edac",
+                                                     i, NULL, 0);
+               if (IS_ERR(dev)) {
+                       pr_err("Registation of octeon_lmc_edac %d failed!\n", i);
+                       err = PTR_ERR(dev);
+               }
+       }
+
+       return err;
+}
+device_initcall(edac_devinit);
diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig
new file mode 100644 (file)
index 0000000..ea87d43
--- /dev/null
@@ -0,0 +1,111 @@
+CONFIG_ATH79=y
+CONFIG_ATH79_MACH_AP121=y
+CONFIG_ATH79_MACH_AP81=y
+CONFIG_ATH79_MACH_DB120=y
+CONFIG_ATH79_MACH_PB44=y
+CONFIG_ATH79_MACH_UBNT_XM=y
+CONFIG_HZ_100=y
+# CONFIG_SECCOMP is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+CONFIG_RD_LZMA=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_PCI=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_PACKET_ENGINE is not set
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_AHB=y
+CONFIG_INPUT=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO_POLLED=m
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_AR933X=y
+CONFIG_SERIAL_AR933X_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATH79=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PCF857X=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ATH79_WDT=y
+# CONFIG_VGA_ARB is not set
+# CONFIG_HID is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_ITU_T=m
index 75165dfa60c10990216691c95c2f25530b0a1fdf..014ba4bbba7d25ff8c2662852955c193da8c7b0d 100644 (file)
@@ -1,7 +1,11 @@
 CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y
+CONFIG_CAVIUM_CN63XXP1=y
 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2
 CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
+CONFIG_HZ_100=y
 CONFIG_PREEMPT=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
@@ -11,16 +15,15 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
-# CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
@@ -42,22 +45,68 @@ CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_OF_PARTS is not set
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_SLRAM=y
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_PATA_OCTEON_CF=y
+CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MARVELL_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_BCM87XX_PHY=y
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -66,24 +115,39 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_OCTEON=y
+CONFIG_SPI=y
+CONFIG_SPI_OCTEON=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_STAGING=y
+CONFIG_OCTEON_ETHERNET=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_NLS=y
+CONFIG_HUGETLBFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_EARLY_PRINTK is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_CRYPTO_CBC=y
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
deleted file mode 100644 (file)
index f72d305..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-CONFIG_PMC_YOSEMITE=y
-CONFIG_HIGHMEM=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_HZ_1000=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PCI=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=m
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETWORK_SECMARK=y
-CONFIG_FW_LOADER=m
-CONFIG_CONNECTOR=m
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_ATA_OVER_ETH=m
-CONFIG_SGI_IOC4=m
-CONFIG_RAID_ATTRS=m
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=m
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_QLA3XXX=m
-CONFIG_CHELSIO_T3=m
-CONFIG_NETXEN_NIC=m
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_FUSE_FS=m
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
index d9740a3788e292db471806472dc1b32863d47d18..3f01dd36e6b7c2040c51b6ca758ee1472f40824a 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for the SNI prom monitor routines under Linux.
 #
 
-lib-$(CONFIG_SNIPROM)  += sniprom.o
+lib-$(CONFIG_FW_SNIPROM)       += sniprom.o
index 52c4e914f95aef97ce72af5fd186678cc7ce9081..90112adb194082a1e41b945d45a7c7091962e3bc 100644 (file)
@@ -243,9 +243,9 @@ enum cpu_type_enum {
         */
        CPU_R4000PC, CPU_R4000SC, CPU_R4000MC, CPU_R4200, CPU_R4300, CPU_R4310,
        CPU_R4400PC, CPU_R4400SC, CPU_R4400MC, CPU_R4600, CPU_R4640, CPU_R4650,
-       CPU_R4700, CPU_R5000, CPU_R5000A, CPU_R5500, CPU_NEVADA, CPU_R5432,
-       CPU_R10000, CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121,
-       CPU_VR4122, CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
+       CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000,
+       CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122,
+       CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
        CPU_SR71000, CPU_RM9000, CPU_TX49XX,
 
        /*
index b9adcd6f0860ecd24dce55c55fab08f441f406d8..2b11f87d6fb3a142f6330f87b8d481c12c7ddad1 100644 (file)
@@ -10,7 +10,7 @@
 #define _ASM_ARC_TYPES_H
 
 
-#ifdef CONFIG_ARC32
+#ifdef CONFIG_FW_ARC32
 
 typedef char           CHAR;
 typedef short          SHORT;
@@ -33,9 +33,9 @@ typedef LONG          _PUSHORT;
 typedef LONG           _PULONG;
 typedef LONG           _PVOID;
 
-#endif /* CONFIG_ARC32 */
+#endif /* CONFIG_FW_ARC32 */
 
-#ifdef CONFIG_ARC64
+#ifdef CONFIG_FW_ARC64
 
 typedef char           CHAR;
 typedef short          SHORT;
@@ -57,7 +57,7 @@ typedef USHORT                *_PUSHORT;
 typedef ULONG          *_PULONG;
 typedef VOID           *_PVOID;
 
-#endif /* CONFIG_ARC64  */
+#endif /* CONFIG_FW_ARC64  */
 
 typedef CHAR           *PCHAR;
 typedef SHORT          *PSHORT;
index b4c20e4f87cd63f0718b785470478fdb74b5f8fd..f0324e92d0896824d593ac1194a96ed7fff182c9 100644 (file)
@@ -161,31 +161,6 @@ ASMMACRO(back_to_back_c0_hazard,
        )
 #define instruction_hazard() do { } while (0)
 
-#elif defined(CONFIG_CPU_RM9000)
-
-/*
- * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
- * use of the JTLB for instructions should not occur for 4 cpu cycles and use
- * for data translations should not occur for 3 cpu cycles.
- */
-
-ASMMACRO(mtc0_tlbw_hazard,
-        _ssnop; _ssnop; _ssnop; _ssnop
-       )
-ASMMACRO(tlbw_use_hazard,
-        _ssnop; _ssnop; _ssnop; _ssnop
-       )
-ASMMACRO(tlb_probe_hazard,
-        _ssnop; _ssnop; _ssnop; _ssnop
-       )
-ASMMACRO(irq_enable_hazard,
-       )
-ASMMACRO(irq_disable_hazard,
-       )
-ASMMACRO(back_to_back_c0_hazard,
-       )
-#define instruction_hazard() do { } while (0)
-
 #elif defined(CONFIG_CPU_SB1)
 
 /*
index 4314892aaebb990572547d371dc5e2febde884ae..ee25ebbf2a28809c73f68311c24284c53fe87907 100644 (file)
@@ -9,22 +9,43 @@
 #ifndef _MIPS_KEXEC
 # define _MIPS_KEXEC
 
+#include <asm/stacktrace.h>
+
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
 /* Maximum address we can reach in physical address mode */
 #define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
  /* Maximum address we can use for the control code buffer */
 #define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
-
-#define KEXEC_CONTROL_PAGE_SIZE 4096
+/* Reserve 3*4096 bytes for board-specific info */
+#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)
 
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_MIPS
+#define MAX_NOTE_BYTES 1024
 
 static inline void crash_setup_regs(struct pt_regs *newregs,
                                    struct pt_regs *oldregs)
 {
-       /* Dummy implementation for now */
+       if (oldregs)
+               memcpy(newregs, oldregs, sizeof(*newregs));
+       else
+               prepare_frametrace(newregs);
 }
 
+#ifdef CONFIG_KEXEC
+struct kimage;
+extern unsigned long kexec_args[4];
+extern int (*_machine_kexec_prepare)(struct kimage *);
+extern void (*_machine_kexec_shutdown)(void);
+extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
+extern void default_machine_crash_shutdown(struct pt_regs *regs);
+#ifdef CONFIG_SMP
+extern const unsigned char kexec_smp_wait[];
+extern unsigned long secondary_kexec_args[4];
+extern void (*relocated_kexec_smp_wait) (void *);
+extern atomic_t kexec_ready_to_reboot;
+#endif
+#endif
+
 #endif /* !_MIPS_KEXEC */
index f4862b563080c2d9f9b9c22e9e0633aa63450b37..99071e50faabdf2cb669a22111837eecb43008ed 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 323d9f1d8c45bc443991251caff5205813804be0..0bb30905fd5b729434a2d82d153bb5765ac51545 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index dd57d03d68ba0d89d33ea723fc5ccc74a6eacaaa..72e260d24e597a42255d61e2a1d70ef0efa29d7c 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 26fdaf40b930fa468e8bfb48656d08a2eeccd3ec..cc7563ba1cbf57e7f2893bc4d2b513bb6548614e 100644 (file)
@@ -44,8 +44,8 @@ union bcm47xx_bus {
 extern union bcm47xx_bus bcm47xx_bus;
 extern enum bcm47xx_bus_type bcm47xx_bus_type;
 
-void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
-void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
+                       bool fallback);
 
 #ifdef CONFIG_BCM47XX_SSB
 void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
index 2ef17e8df40346f07aea6e01431186686214a1f7..90daefa24a4dc58a83e4ca81377aaba2d2ebc82f 100644 (file)
-/*
- * 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) 2007 Aurelien Jarno <aurelien@aurel32.net>
- */
+#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H
+#define __ASM_MIPS_MACH_BCM47XX_GPIO_H
 
-#ifndef __BCM47XX_GPIO_H
-#define __BCM47XX_GPIO_H
+#include <asm-generic/gpio.h>
 
-#include <linux/ssb/ssb_embedded.h>
-#include <linux/bcma/bcma.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
 
-#define BCM47XX_EXTIF_GPIO_LINES       5
-#define BCM47XX_CHIPCO_GPIO_LINES      16
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
 
-extern int gpio_request(unsigned gpio, const char *label);
-extern void gpio_free(unsigned gpio);
-extern int gpio_to_irq(unsigned gpio);
-
-static inline int gpio_get_value(unsigned gpio)
+static inline int irq_to_gpio(unsigned int irq)
 {
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
-                                          1 << gpio);
-#endif
-       }
        return -EINVAL;
 }
 
-#define gpio_get_value_cansleep        gpio_get_value
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
-                            value ? 1 << gpio : 0);
-               return;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-                                    value ? 1 << gpio : 0);
-               return;
 #endif
-       }
-}
-
-#define gpio_set_value_cansleep gpio_set_value
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-       return 0;
-}
-
-static inline int gpio_is_valid(unsigned gpio)
-{
-       return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
-}
-
-
-static inline int gpio_direction_input(unsigned gpio)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
-               return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-                                      0);
-               return 0;
-#endif
-       }
-       return -EINVAL;
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               /* first set the gpio out value */
-               ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
-                            value ? 1 << gpio : 0);
-               /* then set the gpio mode */
-               ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
-               return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               /* first set the gpio out value */
-               bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-                                    value ? 1 << gpio : 0);
-               /* then set the gpio mode */
-               bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-                                      1 << gpio);
-               return 0;
-#endif
-       }
-       return -EINVAL;
-}
-
-static inline int gpio_intmask(unsigned gpio, int value)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
-                                value ? 1 << gpio : 0);
-               return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
-                                        1 << gpio, value ? 1 << gpio : 0);
-               return 0;
-#endif
-       }
-       return -EINVAL;
-}
-
-static inline int gpio_polarity(unsigned gpio, int value)
-{
-       switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-       case BCM47XX_BUS_TYPE_SSB:
-               ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
-                                 value ? 1 << gpio : 0);
-               return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-       case BCM47XX_BUS_TYPE_BCMA:
-               bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
-                                         1 << gpio, value ? 1 << gpio : 0);
-               return 0;
-#endif
-       }
-       return -EINVAL;
-}
-
-
-#endif /* __BCM47XX_GPIO_H */
index 87cd4651dda380a9438564f5b76cbd94dc9767c0..a3d2f448b10e4fbdd37ca91fc1b707b3ee9c7253 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
new file mode 100644 (file)
index 0000000..62d6a3b
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef BCM63XX_NVRAM_H
+#define BCM63XX_NVRAM_H
+
+#include <linux/types.h>
+
+/**
+ * bcm63xx_nvram_init() - initializes nvram
+ * @nvram:     address of the nvram data
+ *
+ * Initialized the local nvram copy from the target address and checks
+ * its checksum.
+ *
+ * Returns 0 on success.
+ */
+int __init bcm63xx_nvram_init(void *nvram);
+
+/**
+ * bcm63xx_nvram_get_name() - returns the board name according to nvram
+ *
+ * Returns the board name field from nvram. Note that it might not be
+ * null terminated if it is exactly 16 bytes long.
+ */
+u8 *bcm63xx_nvram_get_name(void);
+
+/**
+ * bcm63xx_nvram_get_mac_address() - register & return a new mac address
+ * @mac:       pointer to array for allocated mac
+ *
+ * Registers and returns a mac address from the allocated macs from nvram.
+ *
+ * Returns 0 on success.
+ */
+int bcm63xx_nvram_get_mac_address(u8 *mac);
+
+#endif /* BCM63XX_NVRAM_H */
index 12963d05da86c1fa65a63935d5fe63b969cda854..c3eeb90b480a9ede77019b1d06712ae9fb9e1079 100644 (file)
                                        CKCTL_6338_SAR_EN |             \
                                        CKCTL_6338_SPI_EN)
 
-#define CKCTL_6345_CPU_EN              (1 << 0)
-#define CKCTL_6345_BUS_EN              (1 << 1)
-#define CKCTL_6345_EBI_EN              (1 << 2)
-#define CKCTL_6345_UART_EN             (1 << 3)
-#define CKCTL_6345_ADSLPHY_EN          (1 << 4)
-#define CKCTL_6345_ENET_EN             (1 << 7)
-#define CKCTL_6345_USBH_EN             (1 << 8)
+/* BCM6345 clock bits are shifted by 16 on the left, because of the test
+ * control register which is 16-bits wide. That way we do not have any
+ * specific BCM6345 code for handling clocks, and writing 0 to the test
+ * control register is fine.
+ */
+#define CKCTL_6345_CPU_EN              (1 << 16)
+#define CKCTL_6345_BUS_EN              (1 << 17)
+#define CKCTL_6345_EBI_EN              (1 << 18)
+#define CKCTL_6345_UART_EN             (1 << 19)
+#define CKCTL_6345_ADSLPHY_EN          (1 << 20)
+#define CKCTL_6345_ENET_EN             (1 << 23)
+#define CKCTL_6345_USBH_EN             (1 << 24)
 
 #define CKCTL_6345_ALL_SAFE_EN         (CKCTL_6345_ENET_EN |   \
                                        CKCTL_6345_USBH_EN |    \
 /* Soft Reset register */
 #define PERF_SOFTRESET_REG             0x28
 #define PERF_SOFTRESET_6328_REG                0x10
+#define PERF_SOFTRESET_6358_REG                0x34
 #define PERF_SOFTRESET_6368_REG                0x10
 
 #define SOFTRESET_6328_SPI_MASK                (1 << 0)
                                  SOFTRESET_6348_ACLC_MASK |            \
                                  SOFTRESET_6348_ADSLMIPSPLL_MASK)
 
+#define SOFTRESET_6358_SPI_MASK                (1 << 0)
+#define SOFTRESET_6358_ENET_MASK       (1 << 2)
+#define SOFTRESET_6358_MPI_MASK                (1 << 3)
+#define SOFTRESET_6358_EPHY_MASK       (1 << 6)
+#define SOFTRESET_6358_SAR_MASK                (1 << 7)
+#define SOFTRESET_6358_USBH_MASK       (1 << 12)
+#define SOFTRESET_6358_PCM_MASK                (1 << 13)
+#define SOFTRESET_6358_ADSL_MASK       (1 << 14)
+
 #define SOFTRESET_6368_SPI_MASK                (1 << 0)
 #define SOFTRESET_6368_MPI_MASK                (1 << 3)
 #define SOFTRESET_6368_EPHY_MASK       (1 << 6)
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
new file mode 100644 (file)
index 0000000..3a6eb9c
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __BCM63XX_RESET_H
+#define __BCM63XX_RESET_H
+
+enum bcm63xx_core_reset {
+       BCM63XX_RESET_SPI,
+       BCM63XX_RESET_ENET,
+       BCM63XX_RESET_USBH,
+       BCM63XX_RESET_USBD,
+       BCM63XX_RESET_SAR,
+       BCM63XX_RESET_DSL,
+       BCM63XX_RESET_EPHY,
+       BCM63XX_RESET_ENETSW,
+       BCM63XX_RESET_PCM,
+       BCM63XX_RESET_MPI,
+       BCM63XX_RESET_PCIE,
+       BCM63XX_RESET_PCIE_EXT,
+};
+
+void bcm63xx_core_set_reset(enum bcm63xx_core_reset, int reset);
+
+#endif
index b0dd4bb53f7e5b676fab00716c39e80e385e30dc..682bcf3b492ae65cdfa19fd27c6fbb62552dc185 100644 (file)
 #define BCM963XX_CFE_VERSION_OFFSET    0x570
 #define BCM963XX_NVRAM_OFFSET          0x580
 
-/*
- * nvram structure
- */
-struct bcm963xx_nvram {
-       u32     version;
-       u8      reserved1[256];
-       u8      name[16];
-       u32     main_tp_number;
-       u32     psi_size;
-       u32     mac_addr_count;
-       u8      mac_addr_base[6];
-       u8      reserved2[2];
-       u32     checksum_old;
-       u8      reserved3[720];
-       u32     checksum_high;
-};
-
 /*
  * board definition
  */
index 8e3f3fdf3209595a09637f070c4bfc801a00d330..05ee8671bef187cf1b3038b684834336abe4bca2 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index ff0d4909d8480e974b68ce58e31e11da356014f7..502bb1815ae8912c5341fc5826822e91cfdd0a2d 100644 (file)
@@ -42,7 +42,6 @@ enum octeon_irq {
        OCTEON_IRQ_TIMER3,
        OCTEON_IRQ_USB0,
        OCTEON_IRQ_USB1,
-       OCTEON_IRQ_BOOTDMA,
 #ifndef CONFIG_PCI_MSI
        OCTEON_IRQ_LAST = 127
 #endif
index c4712d7cc81df7c11893b4fe33614b8aa4f9d2ea..eb72b35cf04b5bf4f45dc6668b763b05fdce0bdf 100644 (file)
@@ -18,7 +18,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 97884fd18ac04736c670732f301d0f4c6e57dc0f..34ae4046541e76e9f029e4859b7dac8eda6e1ae5 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index ca5e2ef909ad88f1c8298332a28a0f21f280aa27..d29996feb3e793f7e8ff76ef821c704c7c463ea6 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index b660a4c30e6a8a9aea9eb11f9a8eec23abefc1b9..79ae82da3ec7d7d0fa33d6643a8d3d7132f9f9df 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 70d9a25132c5265846febc873c0a90626e7c0f9f..e014264b2be2da8397116475b449024123924030 100644 (file)
 #endif
 #endif
 
-#ifdef CONFIG_IRQ_CPU_RM9K
-#ifndef RM9K_CPU_IRQ_BASE
-#define RM9K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+12)
-#endif
-#endif
-
 #endif /* CONFIG_IRQ_CPU */
 
 #endif /* __ASM_MACH_GENERIC_IRQ_H */
index a44fa9656a82ffa993d0a9f887b784bf01c45d64..fba640517f4faed88047cb74303ff819fd17dc34 100644 (file)
@@ -21,7 +21,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index e2ddcc9b1fff50e7718bdca00d2ee05e6478a1ac..4ee0e4bdf4fb3b80ef7bc01d271475e19d63dc77 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        1
 #define MIPS34K_MISSED_ITLB_WAR                0
index a1baafab486a5d40e0072780f27a99e471dd1bb9..4821c7b7a38cca660f35067bdcfa8e117bfefb8a 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        1
 #define MIPS34K_MISSED_ITLB_WAR                0
index d194056dcd7a94a82e01b50e3330da06bc77252a..7237a935a133c9163585ffa983e9755b9d38a19b 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR   1
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 6158ee861bfd57ff527532d8e7853c434e149efd..5b18b9a3d0ec6bed6051b6f944394e5296c2bad6 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 3a5bc17e28fe3b7f834ca45f0dfb66613d12f9c3..9b511d32383899c52e460f577fbb3d3838c98d48 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 01b08ef368d1678cc05533c509f5776eafce7218..b6c568c280ef038dec56801a6a56bc3304a18187 100644 (file)
@@ -16,7 +16,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR        0
 #define MIPS_CACHE_SYNC_WAR             0
 #define TX49XX_ICACHE_INDEX_INV_WAR     0
-#define RM9000_CDEX_SMP_WAR             0
 #define ICACHE_REFILLS_WORKAROUND_WAR   0
 #define R10000_LLSC_WAR                 0
 #define MIPS34K_MISSED_ITLB_WAR         0
index 6a2df709c576956a4c58541d2fad5c2f9c726917..133336b493b67c4822e79a2965e93300adbab853 100644 (file)
@@ -82,6 +82,9 @@ extern __iomem void *ltq_cgu_membase;
 #define LTQ_MPS_BASE_ADDR      (KSEG1 + 0x1F107000)
 #define LTQ_MPS_CHIPID         ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
+/* allow booting xrx200 phys */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
+
 /* request a non-gpio and set the PIO config */
 #define PMU_PPE                         BIT(13)
 extern void ltq_pmu_enable(unsigned int module);
index bb1e0325c9be212eb1e95c989cba3fbba560e17a..741ae724adc688cf3dfe644747a866ab2426bed6 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 4b971c3ffd8d79dc9c463ed7d903afab0abee5c6..f2570df66bb52bfc2908e22d5bcce729cc4cacf8 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 2f171617badebae054c83c103f46514466d60c2e..718a1228a4f30648e219726b8f42e7e316f047c5 100644 (file)
@@ -18,6 +18,7 @@ extern struct platform_device ls1x_eth0_device;
 extern struct platform_device ls1x_ehci_device;
 extern struct platform_device ls1x_rtc_device;
 
-void ls1x_serial_setup(void);
+extern void __init ls1x_clk_init(void);
+extern void __init ls1x_serial_setup(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
index 8efa7fb9f73a05f952df47a4d669358a149d465f..a81fa3d0dc9157f4bf6c1db273a636043daa8120 100644 (file)
 
 /* Clock PLL Divisor Register Bits */
 #define DIV_DC_EN                      (0x1 << 31)
-#define DIV_DC                         (0x1f << 26)
 #define DIV_CPU_EN                     (0x1 << 25)
-#define DIV_CPU                                (0x1f << 20)
 #define DIV_DDR_EN                     (0x1 << 19)
-#define DIV_DDR                                (0x1f << 14)
 
 #define DIV_DC_SHIFT                   26
 #define DIV_CPU_SHIFT                  20
 #define DIV_DDR_SHIFT                  14
 
+#define DIV_DC_WIDTH                   5
+#define DIV_CPU_WIDTH                  5
+#define DIV_DDR_WIDTH                  5
+
 #endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
index e3680a8fb349b341d4635e54ede57974bdfebc58..8fb50d008131efa5b5bce3cd528b15c09e1cc2e9 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 7c6931d5f45f2a0775844eabbed301a5ad95410a..d068fc411f4787b92299211208a7ac1bde961922 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       1
 #define MIPS_CACHE_SYNC_WAR            1
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  1
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index b5902458e7c1316ee6f10fceac52fc34c24f8631..868ed8a2ed5c025cdf922586b9dfe56e1cd5f29e 100644 (file)
@@ -8,7 +8,9 @@
 #ifndef __ASM_NETLOGIC_IRQ_H
 #define __ASM_NETLOGIC_IRQ_H
 
-#define NR_IRQS                        64
+#include <asm/mach-netlogic/multi-node.h>
+#define NR_IRQS                        (64 * NLM_NR_NODES)
+
 #define MIPS_CPU_IRQ_BASE      0
 
 #endif /* __ASM_NETLOGIC_IRQ_H */
diff --git a/arch/mips/include/asm/mach-netlogic/multi-node.h b/arch/mips/include/asm/mach-netlogic/multi-node.h
new file mode 100644 (file)
index 0000000..d62fc77
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NETLOGIC_MULTI_NODE_H_
+#define _NETLOGIC_MULTI_NODE_H_
+
+#ifndef CONFIG_NLM_MULTINODE
+#define NLM_NR_NODES           1
+#else
+#if defined(CONFIG_NLM_MULTINODE_2)
+#define NLM_NR_NODES           2
+#elif defined(CONFIG_NLM_MULTINODE_4)
+#define NLM_NR_NODES           4
+#else
+#define NLM_NR_NODES           1
+#endif
+#endif
+
+#define NLM_CORES_PER_NODE     8
+#define NLM_THREADS_PER_CORE   4
+#define NLM_CPUS_PER_NODE      (NLM_CORES_PER_NODE * NLM_THREADS_PER_CORE)
+
+#endif
index 22da8932735286a717b10b9cc923598139983666..2c7216840e18a3e9278af1082b18d3b107f80575 100644 (file)
@@ -18,7 +18,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 82cd1e97bc2e4902e318a42abc4b12d328693038..edaa06d9d492171090e10ee08ad370fae79bebe9 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index d0458dd082f91a650b99dea2ceeb55c6658b738e..de8894c46686a16b3336e7d35dd4c8bf7dc1fd93 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 7ac05ecc512be2fd0cb9dea3e7fc2c8800972733..c5651c8e58d1ee3fd086a09edceedafce717c2f3 100644 (file)
@@ -20,7 +20,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       1
 #define MIPS_CACHE_SYNC_WAR            1
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  1
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 3ddf187e98a640d6ad63c40d953ef3c0410885e4..1bfd489a3708147a24c8aa09fc6dd7d98e67e1e4 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       1
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 948d3129a1149ac0e77849344fa72cac720d2a91..a3dde98549bb0ba29f54b7575eae0cdd9fa46607 100644 (file)
@@ -21,7 +21,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 7c6931d5f45f2a0775844eabbed301a5ad95410a..d068fc411f4787b92299211208a7ac1bde961922 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       1
 #define MIPS_CACHE_SYNC_WAR            1
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  1
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 743385d7b5f22b36bcea1f0aa740ad923af41ca4..176f5b32dc69346cfb0d661725e75d29dc599cc9 100644 (file)
@@ -33,7 +33,6 @@ extern int sb1250_m3_workaround_needed(void);
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 4338146163593fa7cff9544117dd577b782bcc0b..6a52e6534776a1ee5f304a9d93d30cb6e3ae24dc 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 39b5d1177c57ef6c08df73e710e61e3336bf00a3..a8e2c586a18c6330ed81fed778f7ca1f06cab021 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    1
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index 56a38926412a4450cca112e472390d571a951424..ffe31e736009e9accd3da51056a41474ecf9d056 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
index ac48629bb1cec7e70a74a9dd75506656ac92fb38..e86084c0bd6b1399c125eb46588bd8f13947232d 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  1
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
diff --git a/arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-yosemite/cpu-feature-overrides.h
deleted file mode 100644 (file)
index 56bdd32..0000000
+++ /dev/null
@@ -1,48 +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) 2003, 04, 07 Ralf Baechle (ralf@linux-mips.org)
- */
-#ifndef __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Jaguar ATX always has the RM9000 processor.
- */
-#define cpu_has_watch          1
-#define cpu_has_mips16         0
-#define cpu_has_divec          0
-#define cpu_has_vce            0
-#define cpu_has_cache_cdex_p   0
-#define cpu_has_cache_cdex_s   0
-#define cpu_has_prefetch       1
-#define cpu_has_mcheck         0
-#define cpu_has_ejtag          0
-
-#define cpu_has_llsc           1
-#define cpu_has_vtag_icache    0
-#define cpu_has_dc_aliases     0
-#define cpu_has_ic_fills_f_dc  0
-#define cpu_has_dsp            0
-#define cpu_has_dsp2           0
-#define cpu_has_mipsmt         0
-#define cpu_has_userlocal      0
-#define cpu_icache_snoops_remote_store 0
-
-#define cpu_has_nofpuex                0
-#define cpu_has_64bits         1
-
-#define cpu_has_inclusive_pcaches      0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 32
-
-#define cpu_has_mips32r1       0
-#define cpu_has_mips32r2       0
-#define cpu_has_mips64r1       0
-#define cpu_has_mips64r2       0
-
-#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-yosemite/war.h b/arch/mips/include/asm/mach-yosemite/war.h
deleted file mode 100644 (file)
index e5c6d53..0000000
+++ /dev/null
@@ -1,25 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
- */
-#ifndef __ASM_MIPS_MACH_YOSEMITE_WAR_H
-#define __ASM_MIPS_MACH_YOSEMITE_WAR_H
-
-#define R4600_V1_INDEX_ICACHEOP_WAR    0
-#define R4600_V1_HIT_CACHEOP_WAR       0
-#define R4600_V2_HIT_CACHEOP_WAR       0
-#define R5432_CP0_INTERRUPT_WAR                0
-#define BCM1250_M3_WAR                 0
-#define SIBYTE_1956_WAR                        0
-#define MIPS4K_ICACHE_REFILL_WAR       0
-#define MIPS_CACHE_SYNC_WAR            0
-#define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            1
-#define ICACHE_REFILLS_WORKAROUND_WAR  1
-#define R10000_LLSC_WAR                        0
-#define MIPS34K_MISSED_ITLB_WAR                0
-
-#endif /* __ASM_MIPS_MACH_YOSEMITE_WAR_H */
index eb742895dcbe97a3e7c81813c76eeec2e41bac02..7e4e6f8fab37b31ab7923f4d1137fafc68b6e1ec 100644 (file)
 #define PM_HUGE_MASK   PM_64M
 #elif defined(CONFIG_PAGE_SIZE_64KB)
 #define PM_HUGE_MASK   PM_256M
-#elif defined(CONFIG_HUGETLB_PAGE)
+#elif defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
 #error Bad page size configuration for hugetlbfs!
 #endif
 
@@ -977,10 +977,6 @@ do {                                                                       \
 #define read_c0_framemask()    __read_32bit_c0_register($21, 0)
 #define write_c0_framemask(val)        __write_32bit_c0_register($21, 0, val)
 
-/* RM9000 PerfControl performance counter control register */
-#define read_c0_perfcontrol()  __read_32bit_c0_register($22, 0)
-#define write_c0_perfcontrol(val) __write_32bit_c0_register($22, 0, val)
-
 #define read_c0_diag()         __read_32bit_c0_register($22, 0)
 #define write_c0_diag(val)     __write_32bit_c0_register($22, 0, val)
 
@@ -1033,10 +1029,6 @@ do {                                                                     \
 #define read_c0_perfcntr3_64() __read_64bit_c0_register($25, 7)
 #define write_c0_perfcntr3_64(val) __write_64bit_c0_register($25, 7, val)
 
-/* RM9000 PerfCount performance counter register */
-#define read_c0_perfcount()    __read_64bit_c0_register($25, 0)
-#define write_c0_perfcount(val)        __write_64bit_c0_register($25, 0, val)
-
 #define read_c0_ecc()          __read_32bit_c0_register($26, 0)
 #define write_c0_ecc(val)      __write_32bit_c0_register($26, 0, val)
 
index 9b02cfba7449ff7ceb2a1b56d4f8876efef38ca5..45cfa1ad86a64f1ec617df998cca6c355687f5e3 100644 (file)
@@ -72,12 +72,6 @@ extern unsigned long pgd_current[];
 #define ASID_INC       0x10
 #define ASID_MASK      0xff0
 
-#elif defined(CONFIG_CPU_RM9000)
-
-#define ASID_INC       0x1
-#define ASID_MASK      0xfff
-
-/* SMTC/34K debug hack - but maybe we'll keep it */
 #elif defined(CONFIG_MIPS_MT_SMTC)
 
 #define ASID_INC       0x1
index 26137da1c713cd95ca0de3bc422fcb8e5fa6f6e8..44b705d0826218a47ac6f78d5b068165b02732b9 100644 (file)
@@ -120,8 +120,6 @@ search_module_dbetables(unsigned long addr)
 #define MODULE_PROC_FAMILY "R10000 "
 #elif defined CONFIG_CPU_RM7000
 #define MODULE_PROC_FAMILY "RM7000 "
-#elif defined CONFIG_CPU_RM9000
-#define MODULE_PROC_FAMILY "RM9000 "
 #elif defined CONFIG_CPU_SB1
 #define MODULE_PROC_FAMILY "SB1 "
 #elif defined CONFIG_CPU_LOONGSON1
index fdd2f44c7b59cafb0486302e9dd66bc2c0c03ea1..42bfd5f1eeec002cda16996aa7ee4c6e83b3b29f 100644 (file)
 #define        BOOT_NMI_HANDLER        8
 
 #ifndef __ASSEMBLY__
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+#include <asm/mach-netlogic/multi-node.h>
+
 struct irq_desc;
-extern struct plat_smp_ops nlm_smp_ops;
-extern char nlm_reset_entry[], nlm_reset_entry_end[];
 void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
 void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
-void nlm_smp_irq_init(void);
+void nlm_smp_irq_init(int hwcpuid);
 void nlm_boot_secondary_cpus(void);
-int nlm_wakeup_secondary_cpus(u32 wakeup_mask);
+int nlm_wakeup_secondary_cpus(void);
 void nlm_rmiboot_preboot(void);
+void nlm_percpu_init(int hwcpuid);
 
 static inline void
 nlm_set_nmi_handler(void *handler)
@@ -68,9 +72,42 @@ nlm_set_nmi_handler(void *handler)
  * Misc.
  */
 unsigned int nlm_get_cpu_frequency(void);
+void nlm_node_init(int node);
+extern struct plat_smp_ops nlm_smp_ops;
+extern char nlm_reset_entry[], nlm_reset_entry_end[];
+
+extern unsigned int nlm_threads_per_core;
+extern cpumask_t nlm_cpumask;
+
+struct nlm_soc_info {
+       unsigned long coremask; /* cores enabled on the soc */
+       unsigned long ebase;
+       uint64_t irqmask;
+       uint64_t sysbase;       /* only for XLP */
+       uint64_t picbase;
+       spinlock_t piclock;
+};
+
+#define        nlm_get_node(i)         (&nlm_nodes[i])
+#ifdef CONFIG_CPU_XLR
+#define        nlm_current_node()      (&nlm_nodes[0])
+#else
+#define nlm_current_node()     (&nlm_nodes[nlm_nodeid()])
+#endif
+
+struct irq_data;
+uint64_t nlm_pci_irqmask(int node);
+void nlm_set_pic_extra_ack(int node, int irq,  void (*xack)(struct irq_data *));
+
+/*
+ * The NR_IRQs is divided between nodes, each of them has a separate irq space
+ */
+static inline int nlm_irq_to_xirq(int node, int irq)
+{
+       return node * NR_IRQS / NLM_NR_NODES + irq;
+}
 
-extern unsigned long nlm_common_ebase;
-extern int nlm_threads_per_core;
-extern uint32_t nlm_cpumask, nlm_coremask;
+extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+extern int nlm_cpu_ready[];
 #endif
 #endif /* _NETLOGIC_COMMON_H_ */
index a85aadb6cfd70ac0c9ccd93e49ede3dcf7ba69d8..ed5993d9b7b886e9e8887fb37d96e1feea163870 100644 (file)
@@ -39,7 +39,7 @@
 
 #define IRQ_IPI_SMP_FUNCTION   3
 #define IRQ_IPI_SMP_RESCHEDULE 4
-#define IRQ_MSGRING            6
+#define IRQ_FMN                        5
 #define IRQ_TIMER              7
 
 #endif
index 8c53d0ba4bf2c744658c298c186a3cab8894d42a..32ba6d95d47cef7768278d56d53757d7d74326d7 100644 (file)
@@ -73,4 +73,146 @@ static inline int hard_smp_processor_id(void)
        return __read_32bit_c0_register($15, 1) & 0x3ff;
 }
 
+static inline int nlm_nodeid(void)
+{
+       return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
+}
+
+static inline unsigned int nlm_core_id(void)
+{
+       return (read_c0_ebase() & 0x1c) >> 2;
+}
+
+static inline unsigned int nlm_thread_id(void)
+{
+       return read_c0_ebase() & 0x3;
+}
+
+#define __read_64bit_c2_split(source, sel)                             \
+({                                                                     \
+       unsigned long long __val;                                       \
+       unsigned long __flags;                                          \
+                                                                       \
+       local_irq_save(__flags);                                        \
+       if (sel == 0)                                                   \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dmfc2\t%M0, " #source "\n\t"                   \
+                       "dsll\t%L0, %M0, 32\n\t"                        \
+                       "dsra\t%M0, %M0, 32\n\t"                        \
+                       "dsra\t%L0, %L0, 32\n\t"                        \
+                       ".set\tmips0\n\t"                               \
+                       : "=r" (__val));                                \
+       else                                                            \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dmfc2\t%M0, " #source ", " #sel "\n\t"         \
+                       "dsll\t%L0, %M0, 32\n\t"                        \
+                       "dsra\t%M0, %M0, 32\n\t"                        \
+                       "dsra\t%L0, %L0, 32\n\t"                        \
+                       ".set\tmips0\n\t"                               \
+                       : "=r" (__val));                                \
+       local_irq_restore(__flags);                                     \
+                                                                       \
+       __val;                                                          \
+})
+
+#define __write_64bit_c2_split(source, sel, val)                       \
+do {                                                                   \
+       unsigned long __flags;                                          \
+                                                                       \
+       local_irq_save(__flags);                                        \
+       if (sel == 0)                                                   \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dsll\t%L0, %L0, 32\n\t"                        \
+                       "dsrl\t%L0, %L0, 32\n\t"                        \
+                       "dsll\t%M0, %M0, 32\n\t"                        \
+                       "or\t%L0, %L0, %M0\n\t"                         \
+                       "dmtc2\t%L0, " #source "\n\t"                   \
+                       ".set\tmips0\n\t"                               \
+                       : : "r" (val));                                 \
+       else                                                            \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dsll\t%L0, %L0, 32\n\t"                        \
+                       "dsrl\t%L0, %L0, 32\n\t"                        \
+                       "dsll\t%M0, %M0, 32\n\t"                        \
+                       "or\t%L0, %L0, %M0\n\t"                         \
+                       "dmtc2\t%L0, " #source ", " #sel "\n\t"         \
+                       ".set\tmips0\n\t"                               \
+                       : : "r" (val));                                 \
+       local_irq_restore(__flags);                                     \
+} while (0)
+
+#define __read_32bit_c2_register(source, sel)                          \
+({ uint32_t __res;                                                     \
+       if (sel == 0)                                                   \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips32\n\t"                              \
+                       "mfc2\t%0, " #source "\n\t"                     \
+                       ".set\tmips0\n\t"                               \
+                       : "=r" (__res));                                \
+       else                                                            \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips32\n\t"                              \
+                       "mfc2\t%0, " #source ", " #sel "\n\t"           \
+                       ".set\tmips0\n\t"                               \
+                       : "=r" (__res));                                \
+       __res;                                                          \
+})
+
+#define __read_64bit_c2_register(source, sel)                          \
+({ unsigned long long __res;                                           \
+       if (sizeof(unsigned long) == 4)                                 \
+               __res = __read_64bit_c2_split(source, sel);             \
+       else if (sel == 0)                                              \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dmfc2\t%0, " #source "\n\t"                    \
+                       ".set\tmips0\n\t"                               \
+                       : "=r" (__res));                                \
+       else                                                            \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dmfc2\t%0, " #source ", " #sel "\n\t"          \
+                       ".set\tmips0\n\t"                               \
+                       : "=r" (__res));                                \
+       __res;                                                          \
+})
+
+#define __write_64bit_c2_register(register, sel, value)                        \
+do {                                                                   \
+       if (sizeof(unsigned long) == 4)                                 \
+               __write_64bit_c2_split(register, sel, value);           \
+       else if (sel == 0)                                              \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dmtc2\t%z0, " #register "\n\t"                 \
+                       ".set\tmips0\n\t"                               \
+                       : : "Jr" (value));                              \
+       else                                                            \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips64\n\t"                              \
+                       "dmtc2\t%z0, " #register ", " #sel "\n\t"       \
+                       ".set\tmips0\n\t"                               \
+                       : : "Jr" (value));                              \
+} while (0)
+
+#define __write_32bit_c2_register(reg, sel, value)                     \
+({                                                                     \
+       if (sel == 0)                                                   \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips32\n\t"                              \
+                       "mtc2\t%z0, " #reg "\n\t"                       \
+                       ".set\tmips0\n\t"                               \
+                       : : "Jr" (value));                              \
+       else                                                            \
+               __asm__ __volatile__(                                   \
+                       ".set\tmips32\n\t"                              \
+                       "mtc2\t%z0, " #reg ", " #sel "\n\t"             \
+                       ".set\tmips0\n\t"                               \
+                       : : "Jr" (value));                              \
+})
+
 #endif /*_ASM_NLM_MIPS_EXTS_H */
index ad8b80233a63b255b12a8227bce551a819711560..b2e53a5383ab155338f593c241a37081d85feae1 100644 (file)
@@ -273,36 +273,16 @@ nlm_pic_read_irt(uint64_t base, int irt_index)
        return nlm_read_pic_reg(base, PIC_IRT(irt_index));
 }
 
-static inline uint64_t
-nlm_pic_read_control(uint64_t base)
-{
-       return nlm_read_pic_reg(base, PIC_CTRL);
-}
-
-static inline void
-nlm_pic_write_control(uint64_t base, uint64_t control)
-{
-       nlm_write_pic_reg(base, PIC_CTRL, control);
-}
-
-static inline void
-nlm_pic_update_control(uint64_t base, uint64_t control)
-{
-       uint64_t val;
-
-       val = nlm_read_pic_reg(base, PIC_CTRL);
-       nlm_write_pic_reg(base, PIC_CTRL, control | val);
-}
-
 static inline void
 nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu)
 {
        uint64_t val;
 
        val = nlm_read_pic_reg(base, PIC_IRT(irt));
-       val |= cpu & 0xf;
-       if (cpu > 15)
-               val |= 1 << 16;
+       /* clear cpuset and mask */
+       val &= ~((0x7ull << 16) | 0xffff);
+       /* set DB, cpuset and cpumask */
+       val |= (1 << 19) | ((cpu >> 4) << 16) | (1 << (cpu & 0xf));
        nlm_write_pic_reg(base, PIC_IRT(irt), val);
 }
 
@@ -369,7 +349,7 @@ nlm_pic_enable_irt(uint64_t base, int irt)
 static inline void
 nlm_pic_disable_irt(uint64_t base, int irt)
 {
-       uint32_t reg;
+       uint64_t reg;
 
        reg = nlm_read_pic_reg(base, PIC_IRT(irt));
        nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31));
@@ -379,15 +359,9 @@ static inline void
 nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi)
 {
        uint64_t ipi;
-       int     node, ncpu;
-
-       node = hwt / 32;
-       ncpu = hwt & 0x1f;
-       ipi = ((uint64_t)nmi << 31) | (irq << 20) | (node << 17) |
-               (1 << (ncpu & 0xf));
-       if (ncpu > 15)
-               ipi |= 0x10000; /* Setting bit 16 to select cpus 16-31 */
 
+       ipi = (nmi << 31) | (irq << 20);
+       ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */
        nlm_write_pic_reg(base, PIC_IPI_CTL, ipi);
 }
 
@@ -404,12 +378,10 @@ nlm_pic_ack(uint64_t base, int irt_num)
 static inline void
 nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
 {
-       nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, 0);
+       nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt);
 }
 
-extern uint64_t nlm_pic_base;
 int nlm_irq_to_irt(int irq);
-int nlm_irt_to_irq(int irt);
 
 #endif /* __ASSEMBLY__ */
 #endif /* _NLM_HAL_PIC_H */
index 21432f7d89b9c107403e1d59858a516a7d6f3d47..258e8cc00e99f12a9c4ff2e843484220e8664344 100644 (file)
 #define        nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
 #define        nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)
 
-extern uint64_t nlm_sys_base;
 #endif
 #endif
diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h
new file mode 100644 (file)
index 0000000..68d5167
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NLM_FMN_H_
+#define _NLM_FMN_H_
+
+#include <asm/netlogic/mips-extns.h> /* for COP2 access */
+
+/* Station IDs */
+#define        FMN_STNID_CPU0                  0x00
+#define        FMN_STNID_CPU1                  0x08
+#define        FMN_STNID_CPU2                  0x10
+#define        FMN_STNID_CPU3                  0x18
+#define        FMN_STNID_CPU4                  0x20
+#define        FMN_STNID_CPU5                  0x28
+#define        FMN_STNID_CPU6                  0x30
+#define        FMN_STNID_CPU7                  0x38
+
+#define        FMN_STNID_XGS0_TX               64
+#define        FMN_STNID_XMAC0_00_TX           64
+#define        FMN_STNID_XMAC0_01_TX           65
+#define        FMN_STNID_XMAC0_02_TX           66
+#define        FMN_STNID_XMAC0_03_TX           67
+#define        FMN_STNID_XMAC0_04_TX           68
+#define        FMN_STNID_XMAC0_05_TX           69
+#define        FMN_STNID_XMAC0_06_TX           70
+#define        FMN_STNID_XMAC0_07_TX           71
+#define        FMN_STNID_XMAC0_08_TX           72
+#define        FMN_STNID_XMAC0_09_TX           73
+#define        FMN_STNID_XMAC0_10_TX           74
+#define        FMN_STNID_XMAC0_11_TX           75
+#define        FMN_STNID_XMAC0_12_TX           76
+#define        FMN_STNID_XMAC0_13_TX           77
+#define        FMN_STNID_XMAC0_14_TX           78
+#define        FMN_STNID_XMAC0_15_TX           79
+
+#define        FMN_STNID_XGS1_TX               80
+#define        FMN_STNID_XMAC1_00_TX           80
+#define        FMN_STNID_XMAC1_01_TX           81
+#define        FMN_STNID_XMAC1_02_TX           82
+#define        FMN_STNID_XMAC1_03_TX           83
+#define        FMN_STNID_XMAC1_04_TX           84
+#define        FMN_STNID_XMAC1_05_TX           85
+#define        FMN_STNID_XMAC1_06_TX           86
+#define        FMN_STNID_XMAC1_07_TX           87
+#define        FMN_STNID_XMAC1_08_TX           88
+#define        FMN_STNID_XMAC1_09_TX           89
+#define        FMN_STNID_XMAC1_10_TX           90
+#define        FMN_STNID_XMAC1_11_TX           91
+#define        FMN_STNID_XMAC1_12_TX           92
+#define        FMN_STNID_XMAC1_13_TX           93
+#define        FMN_STNID_XMAC1_14_TX           94
+#define        FMN_STNID_XMAC1_15_TX           95
+
+#define        FMN_STNID_GMAC                  96
+#define        FMN_STNID_GMACJFR_0             96
+#define        FMN_STNID_GMACRFR_0             97
+#define        FMN_STNID_GMACTX0               98
+#define        FMN_STNID_GMACTX1               99
+#define        FMN_STNID_GMACTX2               100
+#define        FMN_STNID_GMACTX3               101
+#define        FMN_STNID_GMACJFR_1             102
+#define        FMN_STNID_GMACRFR_1             103
+
+#define        FMN_STNID_DMA                   104
+#define        FMN_STNID_DMA_0                 104
+#define        FMN_STNID_DMA_1                 105
+#define        FMN_STNID_DMA_2                 106
+#define        FMN_STNID_DMA_3                 107
+
+#define        FMN_STNID_XGS0FR                112
+#define        FMN_STNID_XMAC0JFR              112
+#define        FMN_STNID_XMAC0RFR              113
+
+#define        FMN_STNID_XGS1FR                114
+#define        FMN_STNID_XMAC1JFR              114
+#define        FMN_STNID_XMAC1RFR              115
+#define        FMN_STNID_SEC                   120
+#define        FMN_STNID_SEC0                  120
+#define        FMN_STNID_SEC1                  121
+#define        FMN_STNID_SEC2                  122
+#define        FMN_STNID_SEC3                  123
+#define        FMN_STNID_PK0                   124
+#define        FMN_STNID_SEC_RSA               124
+#define        FMN_STNID_SEC_RSVD0             125
+#define        FMN_STNID_SEC_RSVD1             126
+#define        FMN_STNID_SEC_RSVD2             127
+
+#define        FMN_STNID_GMAC1                 80
+#define        FMN_STNID_GMAC1_FR_0            81
+#define        FMN_STNID_GMAC1_TX0             82
+#define        FMN_STNID_GMAC1_TX1             83
+#define        FMN_STNID_GMAC1_TX2             84
+#define        FMN_STNID_GMAC1_TX3             85
+#define        FMN_STNID_GMAC1_FR_1            87
+#define        FMN_STNID_GMAC0                 96
+#define        FMN_STNID_GMAC0_FR_0            97
+#define        FMN_STNID_GMAC0_TX0             98
+#define        FMN_STNID_GMAC0_TX1             99
+#define        FMN_STNID_GMAC0_TX2             100
+#define        FMN_STNID_GMAC0_TX3             101
+#define        FMN_STNID_GMAC0_FR_1            103
+#define        FMN_STNID_CMP_0                 108
+#define        FMN_STNID_CMP_1                 109
+#define        FMN_STNID_CMP_2                 110
+#define        FMN_STNID_CMP_3                 111
+#define        FMN_STNID_PCIE_0                116
+#define        FMN_STNID_PCIE_1                117
+#define        FMN_STNID_PCIE_2                118
+#define        FMN_STNID_PCIE_3                119
+#define        FMN_STNID_XLS_PK0               121
+
+#define nlm_read_c2_cc0(s)             __read_32bit_c2_register($16, s)
+#define nlm_read_c2_cc1(s)             __read_32bit_c2_register($17, s)
+#define nlm_read_c2_cc2(s)             __read_32bit_c2_register($18, s)
+#define nlm_read_c2_cc3(s)             __read_32bit_c2_register($19, s)
+#define nlm_read_c2_cc4(s)             __read_32bit_c2_register($20, s)
+#define nlm_read_c2_cc5(s)             __read_32bit_c2_register($21, s)
+#define nlm_read_c2_cc6(s)             __read_32bit_c2_register($22, s)
+#define nlm_read_c2_cc7(s)             __read_32bit_c2_register($23, s)
+#define nlm_read_c2_cc8(s)             __read_32bit_c2_register($24, s)
+#define nlm_read_c2_cc9(s)             __read_32bit_c2_register($25, s)
+#define nlm_read_c2_cc10(s)            __read_32bit_c2_register($26, s)
+#define nlm_read_c2_cc11(s)            __read_32bit_c2_register($27, s)
+#define nlm_read_c2_cc12(s)            __read_32bit_c2_register($28, s)
+#define nlm_read_c2_cc13(s)            __read_32bit_c2_register($29, s)
+#define nlm_read_c2_cc14(s)            __read_32bit_c2_register($30, s)
+#define nlm_read_c2_cc15(s)            __read_32bit_c2_register($31, s)
+
+#define nlm_write_c2_cc0(s, v)         __write_32bit_c2_register($16, s, v)
+#define nlm_write_c2_cc1(s, v)         __write_32bit_c2_register($17, s, v)
+#define nlm_write_c2_cc2(s, v)         __write_32bit_c2_register($18, s, v)
+#define nlm_write_c2_cc3(s, v)         __write_32bit_c2_register($19, s, v)
+#define nlm_write_c2_cc4(s, v)         __write_32bit_c2_register($20, s, v)
+#define nlm_write_c2_cc5(s, v)         __write_32bit_c2_register($21, s, v)
+#define nlm_write_c2_cc6(s, v)         __write_32bit_c2_register($22, s, v)
+#define nlm_write_c2_cc7(s, v)         __write_32bit_c2_register($23, s, v)
+#define nlm_write_c2_cc8(s, v)         __write_32bit_c2_register($24, s, v)
+#define nlm_write_c2_cc9(s, v)         __write_32bit_c2_register($25, s, v)
+#define nlm_write_c2_cc10(s, v)                __write_32bit_c2_register($26, s, v)
+#define nlm_write_c2_cc11(s, v)                __write_32bit_c2_register($27, s, v)
+#define nlm_write_c2_cc12(s, v)                __write_32bit_c2_register($28, s, v)
+#define nlm_write_c2_cc13(s, v)                __write_32bit_c2_register($29, s, v)
+#define nlm_write_c2_cc14(s, v)                __write_32bit_c2_register($30, s, v)
+#define nlm_write_c2_cc15(s, v)                __write_32bit_c2_register($31, s, v)
+
+#define        nlm_read_c2_status(sel)         __read_32bit_c2_register($2, 0)
+#define        nlm_read_c2_config()            __read_32bit_c2_register($3, 0)
+#define        nlm_write_c2_config(v)          __write_32bit_c2_register($3, 0, v)
+#define        nlm_read_c2_bucksize(b)         __read_32bit_c2_register($4, b)
+#define        nlm_write_c2_bucksize(b, v)     __write_32bit_c2_register($4, b, v)
+
+#define        nlm_read_c2_rx_msg0()           __read_64bit_c2_register($1, 0)
+#define        nlm_read_c2_rx_msg1()           __read_64bit_c2_register($1, 1)
+#define        nlm_read_c2_rx_msg2()           __read_64bit_c2_register($1, 2)
+#define        nlm_read_c2_rx_msg3()           __read_64bit_c2_register($1, 3)
+
+#define        nlm_write_c2_tx_msg0(v)         __write_64bit_c2_register($0, 0, v)
+#define        nlm_write_c2_tx_msg1(v)         __write_64bit_c2_register($0, 1, v)
+#define        nlm_write_c2_tx_msg2(v)         __write_64bit_c2_register($0, 2, v)
+#define        nlm_write_c2_tx_msg3(v)         __write_64bit_c2_register($0, 3, v)
+
+#define        FMN_STN_RX_QSIZE                256
+#define        FMN_NSTATIONS                   128
+#define        FMN_CORE_NBUCKETS               8
+
+static inline void nlm_msgsnd(unsigned int stid)
+{
+       __asm__ volatile (
+           ".set       push\n"
+           ".set       noreorder\n"
+           ".set       noat\n"
+           "move       $1, %0\n"
+           "c2         0x10001\n"      /* msgsnd $1 */
+           ".set       pop\n"
+           : : "r" (stid) : "$1"
+       );
+}
+
+static inline void nlm_msgld(unsigned int pri)
+{
+       __asm__ volatile (
+           ".set       push\n"
+           ".set       noreorder\n"
+           ".set       noat\n"
+           "move       $1, %0\n"
+           "c2         0x10002\n"    /* msgld $1 */
+           ".set       pop\n"
+           : : "r" (pri) : "$1"
+       );
+}
+
+static inline void nlm_msgwait(unsigned int mask)
+{
+       __asm__ volatile (
+           ".set       push\n"
+           ".set       noreorder\n"
+           ".set       noat\n"
+           "move       $8, %0\n"
+           "c2         0x10003\n"    /* msgwait $1 */
+           ".set       pop\n"
+           : : "r" (mask) : "$1"
+       );
+}
+
+/*
+ * Disable interrupts and enable COP2 access
+ */
+static inline uint32_t nlm_cop2_enable(void)
+{
+       uint32_t sr = read_c0_status();
+
+       write_c0_status((sr & ~ST0_IE) | ST0_CU2);
+       return sr;
+}
+
+static inline void nlm_cop2_restore(uint32_t sr)
+{
+       write_c0_status(sr);
+}
+
+static inline void nlm_fmn_setup_intr(int irq, unsigned int tmask)
+{
+       uint32_t config;
+
+       config = (1 << 24)      /* interrupt water mark - 1 msg */
+               | (irq << 16)   /* irq */
+               | (tmask << 8)  /* thread mask */
+               | 0x2;          /* enable watermark intr, disable empty intr */
+       nlm_write_c2_config(config);
+}
+
+struct nlm_fmn_msg {
+       uint64_t msg0;
+       uint64_t msg1;
+       uint64_t msg2;
+       uint64_t msg3;
+};
+
+static inline int nlm_fmn_send(unsigned int size, unsigned int code,
+               unsigned int stid, struct nlm_fmn_msg *msg)
+{
+       unsigned int dest;
+       uint32_t status;
+       int i;
+
+       /*
+        * Make sure that all the writes pending at the cpu are flushed.
+        * Any writes pending on CPU will not be see by devices. L1/L2
+        * caches are coherent with IO, so no cache flush needed.
+        */
+       __asm __volatile("sync");
+
+       /* Load TX message buffers */
+       nlm_write_c2_tx_msg0(msg->msg0);
+       nlm_write_c2_tx_msg1(msg->msg1);
+       nlm_write_c2_tx_msg2(msg->msg2);
+       nlm_write_c2_tx_msg3(msg->msg3);
+       dest = ((size - 1) << 16) | (code << 8) | stid;
+
+       /*
+        * Retry a few times on credit fail, this should be a
+        * transient condition, unless there is a configuration
+        * failure, or the receiver is stuck.
+        */
+       for (i = 0; i < 8; i++) {
+               nlm_msgsnd(dest);
+               status = nlm_read_c2_status(0);
+               if ((status & 0x2) == 1)
+                       pr_info("Send pending fail!\n");
+               if ((status & 0x4) == 0)
+                       return 0;
+       }
+
+       /* If there is a credit failure, return error */
+       return status & 0x06;
+}
+
+static inline int nlm_fmn_receive(int bucket, int *size, int *code, int *stid,
+               struct nlm_fmn_msg *msg)
+{
+       uint32_t status, tmp;
+
+       nlm_msgld(bucket);
+
+       /* wait for load pending to clear */
+       do {
+               status = nlm_read_c2_status(1);
+       } while ((status & 0x08) != 0);
+
+       /* receive error bits */
+       tmp = status & 0x30;
+       if (tmp != 0)
+               return tmp;
+
+       *size = ((status & 0xc0) >> 6) + 1;
+       *code = (status & 0xff00) >> 8;
+       *stid = (status & 0x7f0000) >> 16;
+       msg->msg0 = nlm_read_c2_rx_msg0();
+       msg->msg1 = nlm_read_c2_rx_msg1();
+       msg->msg2 = nlm_read_c2_rx_msg2();
+       msg->msg3 = nlm_read_c2_rx_msg3();
+
+       return 0;
+}
+
+struct xlr_fmn_info {
+       int num_buckets;
+       int start_stn_id;
+       int end_stn_id;
+       int credit_config[128];
+};
+
+struct xlr_board_fmn_config {
+       int bucket_size[128];           /* size of buckets for all stations */
+       struct xlr_fmn_info cpu[8];
+       struct xlr_fmn_info gmac[2];
+       struct xlr_fmn_info dma;
+       struct xlr_fmn_info cmp;
+       struct xlr_fmn_info sae;
+       struct xlr_fmn_info xgmac[2];
+};
+
+extern int nlm_register_fmn_handler(int start, int end,
+       void (*fn)(int, int, int, int, struct nlm_fmn_msg *, void *),
+       void *arg);
+extern void xlr_percpu_fmn_init(void);
+extern void nlm_setup_fmn_irq(void);
+extern void xlr_board_info_setup(void);
+
+extern struct xlr_board_fmn_config xlr_board_fmn_config;
+#endif
index 868013e62f3225711ed0033401cc9690a9c200c0..9a691b1f91baf7275dfd6282554cd0ec2a30c8d3 100644 (file)
@@ -258,7 +258,5 @@ nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
        nlm_write_reg(base, PIC_IRT_1(irt),
                (1 << 30) | (1 << 6) | irq);
 }
-
-extern uint64_t nlm_pic_base;
 #endif
 #endif /* _ASM_NLM_XLR_PIC_H */
index ff4a17b0bf78df40462a8b4f71279ebe1cfd3910..c1667e0c272a4d7019efe22ff6d638a73d9fb99c 100644 (file)
@@ -51,10 +51,8 @@ static inline unsigned int nlm_chip_is_xls_b(void)
        return ((prid & 0xf000) == 0x4000);
 }
 
-/*
- *  XLR chip types
- */
- /* The XLS product line has chip versions 0x[48c]? */
+/*  XLR chip types */
+/* The XLS product line has chip versions 0x[48c]? */
 static inline unsigned int nlm_chip_is_xls(void)
 {
        uint32_t prid = read_c0_prid();
index 877845b84b141588e17c23354ff0387cd9a0969c..42db2be663f15a7ea68cdd3ade30083bdc0030cc 100644 (file)
@@ -370,4 +370,6 @@ void cvmx_bootmem_lock(void);
  */
 void cvmx_bootmem_unlock(void);
 
+extern struct cvmx_bootmem_desc *cvmx_bootmem_get_desc(void);
+
 #endif /*   __CVMX_BOOTMEM_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-lmcx-defs.h b/arch/mips/include/asm/octeon/cvmx-lmcx-defs.h
new file mode 100644 (file)
index 0000000..36f5107
--- /dev/null
@@ -0,0 +1,3457 @@
+/***********************license start***************
+ * Author: Cavium Inc.
+ *
+ * Contact: support@cavium.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2012 Cavium Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Inc. for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_LMCX_DEFS_H__
+#define __CVMX_LMCX_DEFS_H__
+
+#define CVMX_LMCX_BIST_CTL(block_id) (CVMX_ADD_IO_SEG(0x00011800880000F0ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_BIST_RESULT(block_id) (CVMX_ADD_IO_SEG(0x00011800880000F8ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_CHAR_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000220ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CHAR_MASK0(block_id) (CVMX_ADD_IO_SEG(0x0001180088000228ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CHAR_MASK1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000230ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CHAR_MASK2(block_id) (CVMX_ADD_IO_SEG(0x0001180088000238ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CHAR_MASK3(block_id) (CVMX_ADD_IO_SEG(0x0001180088000240ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CHAR_MASK4(block_id) (CVMX_ADD_IO_SEG(0x0001180088000318ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_COMP_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000028ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_COMP_CTL2(block_id) (CVMX_ADD_IO_SEG(0x00011800880001B8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CONFIG(block_id) (CVMX_ADD_IO_SEG(0x0001180088000188ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CONTROL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000190ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000010ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_CTL1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000090ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DCLK_CNT(block_id) (CVMX_ADD_IO_SEG(0x00011800880001E0ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_DCLK_CNT_HI(block_id) (CVMX_ADD_IO_SEG(0x0001180088000070ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DCLK_CNT_LO(block_id) (CVMX_ADD_IO_SEG(0x0001180088000068ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DCLK_CTL(block_id) (CVMX_ADD_IO_SEG(0x00011800880000B8ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DDR2_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000018ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DDR_PLL_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000258ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_DELAY_CFG(block_id) (CVMX_ADD_IO_SEG(0x0001180088000088ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DIMMX_PARAMS(offset, block_id) (CVMX_ADD_IO_SEG(0x0001180088000270ull) + (((offset) & 1) + ((block_id) & 3) * 0x200000ull) * 8)
+#define CVMX_LMCX_DIMM_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000310ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_DLL_CTL(block_id) (CVMX_ADD_IO_SEG(0x00011800880000C0ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_DLL_CTL2(block_id) (CVMX_ADD_IO_SEG(0x00011800880001C8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_DLL_CTL3(block_id) (CVMX_ADD_IO_SEG(0x0001180088000218ull) + ((block_id) & 3) * 0x1000000ull)
+static inline uint64_t CVMX_LMCX_DUAL_MEMCFG(unsigned long block_id)
+{
+       switch (cvmx_get_octeon_family()) {
+       case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN50XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN58XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN66XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN52XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN63XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000098ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN56XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000098ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000098ull) + (block_id) * 0x1000000ull;
+       }
+       return CVMX_ADD_IO_SEG(0x0001180088000098ull) + (block_id) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_ECC_SYND(unsigned long block_id)
+{
+       switch (cvmx_get_octeon_family()) {
+       case OCTEON_CN30XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN50XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN38XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN31XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN58XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN66XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN52XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN63XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000038ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN56XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000038ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000038ull) + (block_id) * 0x1000000ull;
+       }
+       return CVMX_ADD_IO_SEG(0x0001180088000038ull) + (block_id) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_FADR(unsigned long block_id)
+{
+       switch (cvmx_get_octeon_family()) {
+       case OCTEON_CN30XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN50XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN38XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN31XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN58XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN66XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN52XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN63XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000020ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN56XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000020ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x0001180088000020ull) + (block_id) * 0x1000000ull;
+       }
+       return CVMX_ADD_IO_SEG(0x0001180088000020ull) + (block_id) * 0x60000000ull;
+}
+
+#define CVMX_LMCX_IFB_CNT(block_id) (CVMX_ADD_IO_SEG(0x00011800880001D0ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_IFB_CNT_HI(block_id) (CVMX_ADD_IO_SEG(0x0001180088000050ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_IFB_CNT_LO(block_id) (CVMX_ADD_IO_SEG(0x0001180088000048ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_INT(block_id) (CVMX_ADD_IO_SEG(0x00011800880001F0ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_INT_EN(block_id) (CVMX_ADD_IO_SEG(0x00011800880001E8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_MEM_CFG0(block_id) (CVMX_ADD_IO_SEG(0x0001180088000000ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_MEM_CFG1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000008ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_MODEREG_PARAMS0(block_id) (CVMX_ADD_IO_SEG(0x00011800880001A8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_MODEREG_PARAMS1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000260ull) + ((block_id) & 3) * 0x1000000ull)
+static inline uint64_t CVMX_LMCX_NXM(unsigned long block_id)
+{
+       switch (cvmx_get_octeon_family()) {
+       case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN66XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN52XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN58XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN63XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x00011800880000C8ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN56XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x00011800880000C8ull) + (block_id) * 0x60000000ull;
+       case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
+               return CVMX_ADD_IO_SEG(0x00011800880000C8ull) + (block_id) * 0x1000000ull;
+       }
+       return CVMX_ADD_IO_SEG(0x00011800880000C8ull) + (block_id) * 0x60000000ull;
+}
+
+#define CVMX_LMCX_OPS_CNT(block_id) (CVMX_ADD_IO_SEG(0x00011800880001D8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_OPS_CNT_HI(block_id) (CVMX_ADD_IO_SEG(0x0001180088000060ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_OPS_CNT_LO(block_id) (CVMX_ADD_IO_SEG(0x0001180088000058ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_PHY_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000210ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_PLL_BWCTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000040ull))
+#define CVMX_LMCX_PLL_CTL(block_id) (CVMX_ADD_IO_SEG(0x00011800880000A8ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_PLL_STATUS(block_id) (CVMX_ADD_IO_SEG(0x00011800880000B0ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_READ_LEVEL_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000140ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_READ_LEVEL_DBG(block_id) (CVMX_ADD_IO_SEG(0x0001180088000148ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_READ_LEVEL_RANKX(offset, block_id) (CVMX_ADD_IO_SEG(0x0001180088000100ull) + (((offset) & 3) + ((block_id) & 1) * 0xC000000ull) * 8)
+#define CVMX_LMCX_RESET_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000180ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_RLEVEL_CTL(block_id) (CVMX_ADD_IO_SEG(0x00011800880002A0ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_RLEVEL_DBG(block_id) (CVMX_ADD_IO_SEG(0x00011800880002A8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_RLEVEL_RANKX(offset, block_id) (CVMX_ADD_IO_SEG(0x0001180088000280ull) + (((offset) & 3) + ((block_id) & 3) * 0x200000ull) * 8)
+#define CVMX_LMCX_RODT_COMP_CTL(block_id) (CVMX_ADD_IO_SEG(0x00011800880000A0ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_RODT_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000078ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_RODT_MASK(block_id) (CVMX_ADD_IO_SEG(0x0001180088000268ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_SCRAMBLED_FADR(block_id) (CVMX_ADD_IO_SEG(0x0001180088000330ull))
+#define CVMX_LMCX_SCRAMBLE_CFG0(block_id) (CVMX_ADD_IO_SEG(0x0001180088000320ull))
+#define CVMX_LMCX_SCRAMBLE_CFG1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000328ull))
+#define CVMX_LMCX_SLOT_CTL0(block_id) (CVMX_ADD_IO_SEG(0x00011800880001F8ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_SLOT_CTL1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000200ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_SLOT_CTL2(block_id) (CVMX_ADD_IO_SEG(0x0001180088000208ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_TIMING_PARAMS0(block_id) (CVMX_ADD_IO_SEG(0x0001180088000198ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_TIMING_PARAMS1(block_id) (CVMX_ADD_IO_SEG(0x00011800880001A0ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_TRO_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000248ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_TRO_STAT(block_id) (CVMX_ADD_IO_SEG(0x0001180088000250ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_WLEVEL_CTL(block_id) (CVMX_ADD_IO_SEG(0x0001180088000300ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_WLEVEL_DBG(block_id) (CVMX_ADD_IO_SEG(0x0001180088000308ull) + ((block_id) & 3) * 0x1000000ull)
+#define CVMX_LMCX_WLEVEL_RANKX(offset, block_id) (CVMX_ADD_IO_SEG(0x00011800880002B0ull) + (((offset) & 3) + ((block_id) & 3) * 0x200000ull) * 8)
+#define CVMX_LMCX_WODT_CTL0(block_id) (CVMX_ADD_IO_SEG(0x0001180088000030ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_WODT_CTL1(block_id) (CVMX_ADD_IO_SEG(0x0001180088000080ull) + ((block_id) & 1) * 0x60000000ull)
+#define CVMX_LMCX_WODT_MASK(block_id) (CVMX_ADD_IO_SEG(0x00011800880001B0ull) + ((block_id) & 3) * 0x1000000ull)
+
+union cvmx_lmcx_bist_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_bist_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_1_63:63;
+               uint64_t start:1;
+#else
+               uint64_t start:1;
+               uint64_t reserved_1_63:63;
+#endif
+       } s;
+       struct cvmx_lmcx_bist_ctl_s cn50xx;
+       struct cvmx_lmcx_bist_ctl_s cn52xx;
+       struct cvmx_lmcx_bist_ctl_s cn52xxp1;
+       struct cvmx_lmcx_bist_ctl_s cn56xx;
+       struct cvmx_lmcx_bist_ctl_s cn56xxp1;
+};
+
+union cvmx_lmcx_bist_result {
+       uint64_t u64;
+       struct cvmx_lmcx_bist_result_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_11_63:53;
+               uint64_t csrd2e:1;
+               uint64_t csre2d:1;
+               uint64_t mwf:1;
+               uint64_t mwd:3;
+               uint64_t mwc:1;
+               uint64_t mrf:1;
+               uint64_t mrd:3;
+#else
+               uint64_t mrd:3;
+               uint64_t mrf:1;
+               uint64_t mwc:1;
+               uint64_t mwd:3;
+               uint64_t mwf:1;
+               uint64_t csre2d:1;
+               uint64_t csrd2e:1;
+               uint64_t reserved_11_63:53;
+#endif
+       } s;
+       struct cvmx_lmcx_bist_result_cn50xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_9_63:55;
+               uint64_t mwf:1;
+               uint64_t mwd:3;
+               uint64_t mwc:1;
+               uint64_t mrf:1;
+               uint64_t mrd:3;
+#else
+               uint64_t mrd:3;
+               uint64_t mrf:1;
+               uint64_t mwc:1;
+               uint64_t mwd:3;
+               uint64_t mwf:1;
+               uint64_t reserved_9_63:55;
+#endif
+       } cn50xx;
+       struct cvmx_lmcx_bist_result_s cn52xx;
+       struct cvmx_lmcx_bist_result_s cn52xxp1;
+       struct cvmx_lmcx_bist_result_s cn56xx;
+       struct cvmx_lmcx_bist_result_s cn56xxp1;
+};
+
+union cvmx_lmcx_char_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_char_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_44_63:20;
+               uint64_t dr:1;
+               uint64_t skew_on:1;
+               uint64_t en:1;
+               uint64_t sel:1;
+               uint64_t prog:8;
+               uint64_t prbs:32;
+#else
+               uint64_t prbs:32;
+               uint64_t prog:8;
+               uint64_t sel:1;
+               uint64_t en:1;
+               uint64_t skew_on:1;
+               uint64_t dr:1;
+               uint64_t reserved_44_63:20;
+#endif
+       } s;
+       struct cvmx_lmcx_char_ctl_s cn61xx;
+       struct cvmx_lmcx_char_ctl_cn63xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_42_63:22;
+               uint64_t en:1;
+               uint64_t sel:1;
+               uint64_t prog:8;
+               uint64_t prbs:32;
+#else
+               uint64_t prbs:32;
+               uint64_t prog:8;
+               uint64_t sel:1;
+               uint64_t en:1;
+               uint64_t reserved_42_63:22;
+#endif
+       } cn63xx;
+       struct cvmx_lmcx_char_ctl_cn63xx cn63xxp1;
+       struct cvmx_lmcx_char_ctl_s cn66xx;
+       struct cvmx_lmcx_char_ctl_s cn68xx;
+       struct cvmx_lmcx_char_ctl_cn63xx cn68xxp1;
+       struct cvmx_lmcx_char_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_char_mask0 {
+       uint64_t u64;
+       struct cvmx_lmcx_char_mask0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t mask:64;
+#else
+               uint64_t mask:64;
+#endif
+       } s;
+       struct cvmx_lmcx_char_mask0_s cn61xx;
+       struct cvmx_lmcx_char_mask0_s cn63xx;
+       struct cvmx_lmcx_char_mask0_s cn63xxp1;
+       struct cvmx_lmcx_char_mask0_s cn66xx;
+       struct cvmx_lmcx_char_mask0_s cn68xx;
+       struct cvmx_lmcx_char_mask0_s cn68xxp1;
+       struct cvmx_lmcx_char_mask0_s cnf71xx;
+};
+
+union cvmx_lmcx_char_mask1 {
+       uint64_t u64;
+       struct cvmx_lmcx_char_mask1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_8_63:56;
+               uint64_t mask:8;
+#else
+               uint64_t mask:8;
+               uint64_t reserved_8_63:56;
+#endif
+       } s;
+       struct cvmx_lmcx_char_mask1_s cn61xx;
+       struct cvmx_lmcx_char_mask1_s cn63xx;
+       struct cvmx_lmcx_char_mask1_s cn63xxp1;
+       struct cvmx_lmcx_char_mask1_s cn66xx;
+       struct cvmx_lmcx_char_mask1_s cn68xx;
+       struct cvmx_lmcx_char_mask1_s cn68xxp1;
+       struct cvmx_lmcx_char_mask1_s cnf71xx;
+};
+
+union cvmx_lmcx_char_mask2 {
+       uint64_t u64;
+       struct cvmx_lmcx_char_mask2_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t mask:64;
+#else
+               uint64_t mask:64;
+#endif
+       } s;
+       struct cvmx_lmcx_char_mask2_s cn61xx;
+       struct cvmx_lmcx_char_mask2_s cn63xx;
+       struct cvmx_lmcx_char_mask2_s cn63xxp1;
+       struct cvmx_lmcx_char_mask2_s cn66xx;
+       struct cvmx_lmcx_char_mask2_s cn68xx;
+       struct cvmx_lmcx_char_mask2_s cn68xxp1;
+       struct cvmx_lmcx_char_mask2_s cnf71xx;
+};
+
+union cvmx_lmcx_char_mask3 {
+       uint64_t u64;
+       struct cvmx_lmcx_char_mask3_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_8_63:56;
+               uint64_t mask:8;
+#else
+               uint64_t mask:8;
+               uint64_t reserved_8_63:56;
+#endif
+       } s;
+       struct cvmx_lmcx_char_mask3_s cn61xx;
+       struct cvmx_lmcx_char_mask3_s cn63xx;
+       struct cvmx_lmcx_char_mask3_s cn63xxp1;
+       struct cvmx_lmcx_char_mask3_s cn66xx;
+       struct cvmx_lmcx_char_mask3_s cn68xx;
+       struct cvmx_lmcx_char_mask3_s cn68xxp1;
+       struct cvmx_lmcx_char_mask3_s cnf71xx;
+};
+
+union cvmx_lmcx_char_mask4 {
+       uint64_t u64;
+       struct cvmx_lmcx_char_mask4_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_33_63:31;
+               uint64_t reset_n_mask:1;
+               uint64_t a_mask:16;
+               uint64_t ba_mask:3;
+               uint64_t we_n_mask:1;
+               uint64_t cas_n_mask:1;
+               uint64_t ras_n_mask:1;
+               uint64_t odt1_mask:2;
+               uint64_t odt0_mask:2;
+               uint64_t cs1_n_mask:2;
+               uint64_t cs0_n_mask:2;
+               uint64_t cke_mask:2;
+#else
+               uint64_t cke_mask:2;
+               uint64_t cs0_n_mask:2;
+               uint64_t cs1_n_mask:2;
+               uint64_t odt0_mask:2;
+               uint64_t odt1_mask:2;
+               uint64_t ras_n_mask:1;
+               uint64_t cas_n_mask:1;
+               uint64_t we_n_mask:1;
+               uint64_t ba_mask:3;
+               uint64_t a_mask:16;
+               uint64_t reset_n_mask:1;
+               uint64_t reserved_33_63:31;
+#endif
+       } s;
+       struct cvmx_lmcx_char_mask4_s cn61xx;
+       struct cvmx_lmcx_char_mask4_s cn63xx;
+       struct cvmx_lmcx_char_mask4_s cn63xxp1;
+       struct cvmx_lmcx_char_mask4_s cn66xx;
+       struct cvmx_lmcx_char_mask4_s cn68xx;
+       struct cvmx_lmcx_char_mask4_s cn68xxp1;
+       struct cvmx_lmcx_char_mask4_s cnf71xx;
+};
+
+union cvmx_lmcx_comp_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_comp_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t nctl_csr:4;
+               uint64_t nctl_clk:4;
+               uint64_t nctl_cmd:4;
+               uint64_t nctl_dat:4;
+               uint64_t pctl_csr:4;
+               uint64_t pctl_clk:4;
+               uint64_t reserved_0_7:8;
+#else
+               uint64_t reserved_0_7:8;
+               uint64_t pctl_clk:4;
+               uint64_t pctl_csr:4;
+               uint64_t nctl_dat:4;
+               uint64_t nctl_cmd:4;
+               uint64_t nctl_clk:4;
+               uint64_t nctl_csr:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_comp_ctl_cn30xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t nctl_csr:4;
+               uint64_t nctl_clk:4;
+               uint64_t nctl_cmd:4;
+               uint64_t nctl_dat:4;
+               uint64_t pctl_csr:4;
+               uint64_t pctl_clk:4;
+               uint64_t pctl_cmd:4;
+               uint64_t pctl_dat:4;
+#else
+               uint64_t pctl_dat:4;
+               uint64_t pctl_cmd:4;
+               uint64_t pctl_clk:4;
+               uint64_t pctl_csr:4;
+               uint64_t nctl_dat:4;
+               uint64_t nctl_cmd:4;
+               uint64_t nctl_clk:4;
+               uint64_t nctl_csr:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn30xx;
+       struct cvmx_lmcx_comp_ctl_cn30xx cn31xx;
+       struct cvmx_lmcx_comp_ctl_cn30xx cn38xx;
+       struct cvmx_lmcx_comp_ctl_cn30xx cn38xxp2;
+       struct cvmx_lmcx_comp_ctl_cn50xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t nctl_csr:4;
+               uint64_t reserved_20_27:8;
+               uint64_t nctl_dat:4;
+               uint64_t pctl_csr:4;
+               uint64_t reserved_5_11:7;
+               uint64_t pctl_dat:5;
+#else
+               uint64_t pctl_dat:5;
+               uint64_t reserved_5_11:7;
+               uint64_t pctl_csr:4;
+               uint64_t nctl_dat:4;
+               uint64_t reserved_20_27:8;
+               uint64_t nctl_csr:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn50xx;
+       struct cvmx_lmcx_comp_ctl_cn50xx cn52xx;
+       struct cvmx_lmcx_comp_ctl_cn50xx cn52xxp1;
+       struct cvmx_lmcx_comp_ctl_cn50xx cn56xx;
+       struct cvmx_lmcx_comp_ctl_cn50xx cn56xxp1;
+       struct cvmx_lmcx_comp_ctl_cn50xx cn58xx;
+       struct cvmx_lmcx_comp_ctl_cn58xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t nctl_csr:4;
+               uint64_t reserved_20_27:8;
+               uint64_t nctl_dat:4;
+               uint64_t pctl_csr:4;
+               uint64_t reserved_4_11:8;
+               uint64_t pctl_dat:4;
+#else
+               uint64_t pctl_dat:4;
+               uint64_t reserved_4_11:8;
+               uint64_t pctl_csr:4;
+               uint64_t nctl_dat:4;
+               uint64_t reserved_20_27:8;
+               uint64_t nctl_csr:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn58xxp1;
+};
+
+union cvmx_lmcx_comp_ctl2 {
+       uint64_t u64;
+       struct cvmx_lmcx_comp_ctl2_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_34_63:30;
+               uint64_t ddr__ptune:4;
+               uint64_t ddr__ntune:4;
+               uint64_t m180:1;
+               uint64_t byp:1;
+               uint64_t ptune:4;
+               uint64_t ntune:4;
+               uint64_t rodt_ctl:4;
+               uint64_t cmd_ctl:4;
+               uint64_t ck_ctl:4;
+               uint64_t dqx_ctl:4;
+#else
+               uint64_t dqx_ctl:4;
+               uint64_t ck_ctl:4;
+               uint64_t cmd_ctl:4;
+               uint64_t rodt_ctl:4;
+               uint64_t ntune:4;
+               uint64_t ptune:4;
+               uint64_t byp:1;
+               uint64_t m180:1;
+               uint64_t ddr__ntune:4;
+               uint64_t ddr__ptune:4;
+               uint64_t reserved_34_63:30;
+#endif
+       } s;
+       struct cvmx_lmcx_comp_ctl2_s cn61xx;
+       struct cvmx_lmcx_comp_ctl2_s cn63xx;
+       struct cvmx_lmcx_comp_ctl2_s cn63xxp1;
+       struct cvmx_lmcx_comp_ctl2_s cn66xx;
+       struct cvmx_lmcx_comp_ctl2_s cn68xx;
+       struct cvmx_lmcx_comp_ctl2_s cn68xxp1;
+       struct cvmx_lmcx_comp_ctl2_s cnf71xx;
+};
+
+union cvmx_lmcx_config {
+       uint64_t u64;
+       struct cvmx_lmcx_config_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_61_63:3;
+               uint64_t mode32b:1;
+               uint64_t scrz:1;
+               uint64_t early_unload_d1_r1:1;
+               uint64_t early_unload_d1_r0:1;
+               uint64_t early_unload_d0_r1:1;
+               uint64_t early_unload_d0_r0:1;
+               uint64_t init_status:4;
+               uint64_t mirrmask:4;
+               uint64_t rankmask:4;
+               uint64_t rank_ena:1;
+               uint64_t sref_with_dll:1;
+               uint64_t early_dqx:1;
+               uint64_t sequence:3;
+               uint64_t ref_zqcs_int:19;
+               uint64_t reset:1;
+               uint64_t ecc_adr:1;
+               uint64_t forcewrite:4;
+               uint64_t idlepower:3;
+               uint64_t pbank_lsb:4;
+               uint64_t row_lsb:3;
+               uint64_t ecc_ena:1;
+               uint64_t init_start:1;
+#else
+               uint64_t init_start:1;
+               uint64_t ecc_ena:1;
+               uint64_t row_lsb:3;
+               uint64_t pbank_lsb:4;
+               uint64_t idlepower:3;
+               uint64_t forcewrite:4;
+               uint64_t ecc_adr:1;
+               uint64_t reset:1;
+               uint64_t ref_zqcs_int:19;
+               uint64_t sequence:3;
+               uint64_t early_dqx:1;
+               uint64_t sref_with_dll:1;
+               uint64_t rank_ena:1;
+               uint64_t rankmask:4;
+               uint64_t mirrmask:4;
+               uint64_t init_status:4;
+               uint64_t early_unload_d0_r0:1;
+               uint64_t early_unload_d0_r1:1;
+               uint64_t early_unload_d1_r0:1;
+               uint64_t early_unload_d1_r1:1;
+               uint64_t scrz:1;
+               uint64_t mode32b:1;
+               uint64_t reserved_61_63:3;
+#endif
+       } s;
+       struct cvmx_lmcx_config_s cn61xx;
+       struct cvmx_lmcx_config_cn63xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_59_63:5;
+               uint64_t early_unload_d1_r1:1;
+               uint64_t early_unload_d1_r0:1;
+               uint64_t early_unload_d0_r1:1;
+               uint64_t early_unload_d0_r0:1;
+               uint64_t init_status:4;
+               uint64_t mirrmask:4;
+               uint64_t rankmask:4;
+               uint64_t rank_ena:1;
+               uint64_t sref_with_dll:1;
+               uint64_t early_dqx:1;
+               uint64_t sequence:3;
+               uint64_t ref_zqcs_int:19;
+               uint64_t reset:1;
+               uint64_t ecc_adr:1;
+               uint64_t forcewrite:4;
+               uint64_t idlepower:3;
+               uint64_t pbank_lsb:4;
+               uint64_t row_lsb:3;
+               uint64_t ecc_ena:1;
+               uint64_t init_start:1;
+#else
+               uint64_t init_start:1;
+               uint64_t ecc_ena:1;
+               uint64_t row_lsb:3;
+               uint64_t pbank_lsb:4;
+               uint64_t idlepower:3;
+               uint64_t forcewrite:4;
+               uint64_t ecc_adr:1;
+               uint64_t reset:1;
+               uint64_t ref_zqcs_int:19;
+               uint64_t sequence:3;
+               uint64_t early_dqx:1;
+               uint64_t sref_with_dll:1;
+               uint64_t rank_ena:1;
+               uint64_t rankmask:4;
+               uint64_t mirrmask:4;
+               uint64_t init_status:4;
+               uint64_t early_unload_d0_r0:1;
+               uint64_t early_unload_d0_r1:1;
+               uint64_t early_unload_d1_r0:1;
+               uint64_t early_unload_d1_r1:1;
+               uint64_t reserved_59_63:5;
+#endif
+       } cn63xx;
+       struct cvmx_lmcx_config_cn63xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_55_63:9;
+               uint64_t init_status:4;
+               uint64_t mirrmask:4;
+               uint64_t rankmask:4;
+               uint64_t rank_ena:1;
+               uint64_t sref_with_dll:1;
+               uint64_t early_dqx:1;
+               uint64_t sequence:3;
+               uint64_t ref_zqcs_int:19;
+               uint64_t reset:1;
+               uint64_t ecc_adr:1;
+               uint64_t forcewrite:4;
+               uint64_t idlepower:3;
+               uint64_t pbank_lsb:4;
+               uint64_t row_lsb:3;
+               uint64_t ecc_ena:1;
+               uint64_t init_start:1;
+#else
+               uint64_t init_start:1;
+               uint64_t ecc_ena:1;
+               uint64_t row_lsb:3;
+               uint64_t pbank_lsb:4;
+               uint64_t idlepower:3;
+               uint64_t forcewrite:4;
+               uint64_t ecc_adr:1;
+               uint64_t reset:1;
+               uint64_t ref_zqcs_int:19;
+               uint64_t sequence:3;
+               uint64_t early_dqx:1;
+               uint64_t sref_with_dll:1;
+               uint64_t rank_ena:1;
+               uint64_t rankmask:4;
+               uint64_t mirrmask:4;
+               uint64_t init_status:4;
+               uint64_t reserved_55_63:9;
+#endif
+       } cn63xxp1;
+       struct cvmx_lmcx_config_cn66xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_60_63:4;
+               uint64_t scrz:1;
+               uint64_t early_unload_d1_r1:1;
+               uint64_t early_unload_d1_r0:1;
+               uint64_t early_unload_d0_r1:1;
+               uint64_t early_unload_d0_r0:1;
+               uint64_t init_status:4;
+               uint64_t mirrmask:4;
+               uint64_t rankmask:4;
+               uint64_t rank_ena:1;
+               uint64_t sref_with_dll:1;
+               uint64_t early_dqx:1;
+               uint64_t sequence:3;
+               uint64_t ref_zqcs_int:19;
+               uint64_t reset:1;
+               uint64_t ecc_adr:1;
+               uint64_t forcewrite:4;
+               uint64_t idlepower:3;
+               uint64_t pbank_lsb:4;
+               uint64_t row_lsb:3;
+               uint64_t ecc_ena:1;
+               uint64_t init_start:1;
+#else
+               uint64_t init_start:1;
+               uint64_t ecc_ena:1;
+               uint64_t row_lsb:3;
+               uint64_t pbank_lsb:4;
+               uint64_t idlepower:3;
+               uint64_t forcewrite:4;
+               uint64_t ecc_adr:1;
+               uint64_t reset:1;
+               uint64_t ref_zqcs_int:19;
+               uint64_t sequence:3;
+               uint64_t early_dqx:1;
+               uint64_t sref_with_dll:1;
+               uint64_t rank_ena:1;
+               uint64_t rankmask:4;
+               uint64_t mirrmask:4;
+               uint64_t init_status:4;
+               uint64_t early_unload_d0_r0:1;
+               uint64_t early_unload_d0_r1:1;
+               uint64_t early_unload_d1_r0:1;
+               uint64_t early_unload_d1_r1:1;
+               uint64_t scrz:1;
+               uint64_t reserved_60_63:4;
+#endif
+       } cn66xx;
+       struct cvmx_lmcx_config_cn63xx cn68xx;
+       struct cvmx_lmcx_config_cn63xx cn68xxp1;
+       struct cvmx_lmcx_config_s cnf71xx;
+};
+
+union cvmx_lmcx_control {
+       uint64_t u64;
+       struct cvmx_lmcx_control_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t scramble_ena:1;
+               uint64_t thrcnt:12;
+               uint64_t persub:8;
+               uint64_t thrmax:4;
+               uint64_t crm_cnt:5;
+               uint64_t crm_thr:5;
+               uint64_t crm_max:5;
+               uint64_t rodt_bprch:1;
+               uint64_t wodt_bprch:1;
+               uint64_t bprch:2;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t nxm_write_en:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t inorder_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t throttle_rd:1;
+               uint64_t fprch2:2;
+               uint64_t pocas:1;
+               uint64_t ddr2t:1;
+               uint64_t bwcnt:1;
+               uint64_t rdimm_ena:1;
+#else
+               uint64_t rdimm_ena:1;
+               uint64_t bwcnt:1;
+               uint64_t ddr2t:1;
+               uint64_t pocas:1;
+               uint64_t fprch2:2;
+               uint64_t throttle_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t inorder_wr:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t nxm_write_en:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t bprch:2;
+               uint64_t wodt_bprch:1;
+               uint64_t rodt_bprch:1;
+               uint64_t crm_max:5;
+               uint64_t crm_thr:5;
+               uint64_t crm_cnt:5;
+               uint64_t thrmax:4;
+               uint64_t persub:8;
+               uint64_t thrcnt:12;
+               uint64_t scramble_ena:1;
+#endif
+       } s;
+       struct cvmx_lmcx_control_s cn61xx;
+       struct cvmx_lmcx_control_cn63xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_24_63:40;
+               uint64_t rodt_bprch:1;
+               uint64_t wodt_bprch:1;
+               uint64_t bprch:2;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t nxm_write_en:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t inorder_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t throttle_rd:1;
+               uint64_t fprch2:2;
+               uint64_t pocas:1;
+               uint64_t ddr2t:1;
+               uint64_t bwcnt:1;
+               uint64_t rdimm_ena:1;
+#else
+               uint64_t rdimm_ena:1;
+               uint64_t bwcnt:1;
+               uint64_t ddr2t:1;
+               uint64_t pocas:1;
+               uint64_t fprch2:2;
+               uint64_t throttle_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t inorder_wr:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t nxm_write_en:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t bprch:2;
+               uint64_t wodt_bprch:1;
+               uint64_t rodt_bprch:1;
+               uint64_t reserved_24_63:40;
+#endif
+       } cn63xx;
+       struct cvmx_lmcx_control_cn63xx cn63xxp1;
+       struct cvmx_lmcx_control_cn66xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t scramble_ena:1;
+               uint64_t reserved_24_62:39;
+               uint64_t rodt_bprch:1;
+               uint64_t wodt_bprch:1;
+               uint64_t bprch:2;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t nxm_write_en:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t inorder_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t throttle_rd:1;
+               uint64_t fprch2:2;
+               uint64_t pocas:1;
+               uint64_t ddr2t:1;
+               uint64_t bwcnt:1;
+               uint64_t rdimm_ena:1;
+#else
+               uint64_t rdimm_ena:1;
+               uint64_t bwcnt:1;
+               uint64_t ddr2t:1;
+               uint64_t pocas:1;
+               uint64_t fprch2:2;
+               uint64_t throttle_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t inorder_wr:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t nxm_write_en:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t bprch:2;
+               uint64_t wodt_bprch:1;
+               uint64_t rodt_bprch:1;
+               uint64_t reserved_24_62:39;
+               uint64_t scramble_ena:1;
+#endif
+       } cn66xx;
+       struct cvmx_lmcx_control_cn68xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_63_63:1;
+               uint64_t thrcnt:12;
+               uint64_t persub:8;
+               uint64_t thrmax:4;
+               uint64_t crm_cnt:5;
+               uint64_t crm_thr:5;
+               uint64_t crm_max:5;
+               uint64_t rodt_bprch:1;
+               uint64_t wodt_bprch:1;
+               uint64_t bprch:2;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t nxm_write_en:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t inorder_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t throttle_rd:1;
+               uint64_t fprch2:2;
+               uint64_t pocas:1;
+               uint64_t ddr2t:1;
+               uint64_t bwcnt:1;
+               uint64_t rdimm_ena:1;
+#else
+               uint64_t rdimm_ena:1;
+               uint64_t bwcnt:1;
+               uint64_t ddr2t:1;
+               uint64_t pocas:1;
+               uint64_t fprch2:2;
+               uint64_t throttle_rd:1;
+               uint64_t throttle_wr:1;
+               uint64_t inorder_rd:1;
+               uint64_t inorder_wr:1;
+               uint64_t elev_prio_dis:1;
+               uint64_t nxm_write_en:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t auto_dclkdis:1;
+               uint64_t int_zqcs_dis:1;
+               uint64_t ext_zqcs_dis:1;
+               uint64_t bprch:2;
+               uint64_t wodt_bprch:1;
+               uint64_t rodt_bprch:1;
+               uint64_t crm_max:5;
+               uint64_t crm_thr:5;
+               uint64_t crm_cnt:5;
+               uint64_t thrmax:4;
+               uint64_t persub:8;
+               uint64_t thrcnt:12;
+               uint64_t reserved_63_63:1;
+#endif
+       } cn68xx;
+       struct cvmx_lmcx_control_cn68xx cn68xxp1;
+       struct cvmx_lmcx_control_cn66xx cnf71xx;
+};
+
+union cvmx_lmcx_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:4;
+               uint64_t ddr__pctl:4;
+               uint64_t slow_scf:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t pll_div2:1;
+               uint64_t pll_bypass:1;
+               uint64_t rdimm_ena:1;
+               uint64_t r2r_slot:1;
+               uint64_t inorder_mwf:1;
+               uint64_t inorder_mrf:1;
+               uint64_t reserved_10_11:2;
+               uint64_t fprch2:1;
+               uint64_t bprch:1;
+               uint64_t sil_lat:2;
+               uint64_t tskw:2;
+               uint64_t qs_dic:2;
+               uint64_t dic:2;
+#else
+               uint64_t dic:2;
+               uint64_t qs_dic:2;
+               uint64_t tskw:2;
+               uint64_t sil_lat:2;
+               uint64_t bprch:1;
+               uint64_t fprch2:1;
+               uint64_t reserved_10_11:2;
+               uint64_t inorder_mrf:1;
+               uint64_t inorder_mwf:1;
+               uint64_t r2r_slot:1;
+               uint64_t rdimm_ena:1;
+               uint64_t pll_bypass:1;
+               uint64_t pll_div2:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t slow_scf:1;
+               uint64_t ddr__pctl:4;
+               uint64_t ddr__nctl:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ctl_cn30xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:4;
+               uint64_t ddr__pctl:4;
+               uint64_t slow_scf:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t pll_div2:1;
+               uint64_t pll_bypass:1;
+               uint64_t rdimm_ena:1;
+               uint64_t r2r_slot:1;
+               uint64_t inorder_mwf:1;
+               uint64_t inorder_mrf:1;
+               uint64_t dreset:1;
+               uint64_t mode32b:1;
+               uint64_t fprch2:1;
+               uint64_t bprch:1;
+               uint64_t sil_lat:2;
+               uint64_t tskw:2;
+               uint64_t qs_dic:2;
+               uint64_t dic:2;
+#else
+               uint64_t dic:2;
+               uint64_t qs_dic:2;
+               uint64_t tskw:2;
+               uint64_t sil_lat:2;
+               uint64_t bprch:1;
+               uint64_t fprch2:1;
+               uint64_t mode32b:1;
+               uint64_t dreset:1;
+               uint64_t inorder_mrf:1;
+               uint64_t inorder_mwf:1;
+               uint64_t r2r_slot:1;
+               uint64_t rdimm_ena:1;
+               uint64_t pll_bypass:1;
+               uint64_t pll_div2:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t slow_scf:1;
+               uint64_t ddr__pctl:4;
+               uint64_t ddr__nctl:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn30xx;
+       struct cvmx_lmcx_ctl_cn30xx cn31xx;
+       struct cvmx_lmcx_ctl_cn38xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:4;
+               uint64_t ddr__pctl:4;
+               uint64_t slow_scf:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t reserved_16_17:2;
+               uint64_t rdimm_ena:1;
+               uint64_t r2r_slot:1;
+               uint64_t inorder_mwf:1;
+               uint64_t inorder_mrf:1;
+               uint64_t set_zero:1;
+               uint64_t mode128b:1;
+               uint64_t fprch2:1;
+               uint64_t bprch:1;
+               uint64_t sil_lat:2;
+               uint64_t tskw:2;
+               uint64_t qs_dic:2;
+               uint64_t dic:2;
+#else
+               uint64_t dic:2;
+               uint64_t qs_dic:2;
+               uint64_t tskw:2;
+               uint64_t sil_lat:2;
+               uint64_t bprch:1;
+               uint64_t fprch2:1;
+               uint64_t mode128b:1;
+               uint64_t set_zero:1;
+               uint64_t inorder_mrf:1;
+               uint64_t inorder_mwf:1;
+               uint64_t r2r_slot:1;
+               uint64_t rdimm_ena:1;
+               uint64_t reserved_16_17:2;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t slow_scf:1;
+               uint64_t ddr__pctl:4;
+               uint64_t ddr__nctl:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn38xx;
+       struct cvmx_lmcx_ctl_cn38xx cn38xxp2;
+       struct cvmx_lmcx_ctl_cn50xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:4;
+               uint64_t ddr__pctl:4;
+               uint64_t slow_scf:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t reserved_17_17:1;
+               uint64_t pll_bypass:1;
+               uint64_t rdimm_ena:1;
+               uint64_t r2r_slot:1;
+               uint64_t inorder_mwf:1;
+               uint64_t inorder_mrf:1;
+               uint64_t dreset:1;
+               uint64_t mode32b:1;
+               uint64_t fprch2:1;
+               uint64_t bprch:1;
+               uint64_t sil_lat:2;
+               uint64_t tskw:2;
+               uint64_t qs_dic:2;
+               uint64_t dic:2;
+#else
+               uint64_t dic:2;
+               uint64_t qs_dic:2;
+               uint64_t tskw:2;
+               uint64_t sil_lat:2;
+               uint64_t bprch:1;
+               uint64_t fprch2:1;
+               uint64_t mode32b:1;
+               uint64_t dreset:1;
+               uint64_t inorder_mrf:1;
+               uint64_t inorder_mwf:1;
+               uint64_t r2r_slot:1;
+               uint64_t rdimm_ena:1;
+               uint64_t pll_bypass:1;
+               uint64_t reserved_17_17:1;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t slow_scf:1;
+               uint64_t ddr__pctl:4;
+               uint64_t ddr__nctl:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn50xx;
+       struct cvmx_lmcx_ctl_cn52xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:4;
+               uint64_t ddr__pctl:4;
+               uint64_t slow_scf:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t reserved_16_17:2;
+               uint64_t rdimm_ena:1;
+               uint64_t r2r_slot:1;
+               uint64_t inorder_mwf:1;
+               uint64_t inorder_mrf:1;
+               uint64_t dreset:1;
+               uint64_t mode32b:1;
+               uint64_t fprch2:1;
+               uint64_t bprch:1;
+               uint64_t sil_lat:2;
+               uint64_t tskw:2;
+               uint64_t qs_dic:2;
+               uint64_t dic:2;
+#else
+               uint64_t dic:2;
+               uint64_t qs_dic:2;
+               uint64_t tskw:2;
+               uint64_t sil_lat:2;
+               uint64_t bprch:1;
+               uint64_t fprch2:1;
+               uint64_t mode32b:1;
+               uint64_t dreset:1;
+               uint64_t inorder_mrf:1;
+               uint64_t inorder_mwf:1;
+               uint64_t r2r_slot:1;
+               uint64_t rdimm_ena:1;
+               uint64_t reserved_16_17:2;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t slow_scf:1;
+               uint64_t ddr__pctl:4;
+               uint64_t ddr__nctl:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn52xx;
+       struct cvmx_lmcx_ctl_cn52xx cn52xxp1;
+       struct cvmx_lmcx_ctl_cn52xx cn56xx;
+       struct cvmx_lmcx_ctl_cn52xx cn56xxp1;
+       struct cvmx_lmcx_ctl_cn58xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:4;
+               uint64_t ddr__pctl:4;
+               uint64_t slow_scf:1;
+               uint64_t xor_bank:1;
+               uint64_t max_write_batch:4;
+               uint64_t reserved_16_17:2;
+               uint64_t rdimm_ena:1;
+               uint64_t r2r_slot:1;
+               uint64_t inorder_mwf:1;
+               uint64_t inorder_mrf:1;
+               uint64_t dreset:1;
+               uint64_t mode128b:1;
+               uint64_t fprch2:1;
+               uint64_t bprch:1;
+               uint64_t sil_lat:2;
+               uint64_t tskw:2;
+               uint64_t qs_dic:2;
+               uint64_t dic:2;
+#else
+               uint64_t dic:2;
+               uint64_t qs_dic:2;
+               uint64_t tskw:2;
+               uint64_t sil_lat:2;
+               uint64_t bprch:1;
+               uint64_t fprch2:1;
+               uint64_t mode128b:1;
+               uint64_t dreset:1;
+               uint64_t inorder_mrf:1;
+               uint64_t inorder_mwf:1;
+               uint64_t r2r_slot:1;
+               uint64_t rdimm_ena:1;
+               uint64_t reserved_16_17:2;
+               uint64_t max_write_batch:4;
+               uint64_t xor_bank:1;
+               uint64_t slow_scf:1;
+               uint64_t ddr__pctl:4;
+               uint64_t ddr__nctl:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn58xx;
+       struct cvmx_lmcx_ctl_cn58xx cn58xxp1;
+};
+
+union cvmx_lmcx_ctl1 {
+       uint64_t u64;
+       struct cvmx_lmcx_ctl1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_21_63:43;
+               uint64_t ecc_adr:1;
+               uint64_t forcewrite:4;
+               uint64_t idlepower:3;
+               uint64_t sequence:3;
+               uint64_t sil_mode:1;
+               uint64_t dcc_enable:1;
+               uint64_t reserved_2_7:6;
+               uint64_t data_layout:2;
+#else
+               uint64_t data_layout:2;
+               uint64_t reserved_2_7:6;
+               uint64_t dcc_enable:1;
+               uint64_t sil_mode:1;
+               uint64_t sequence:3;
+               uint64_t idlepower:3;
+               uint64_t forcewrite:4;
+               uint64_t ecc_adr:1;
+               uint64_t reserved_21_63:43;
+#endif
+       } s;
+       struct cvmx_lmcx_ctl1_cn30xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_2_63:62;
+               uint64_t data_layout:2;
+#else
+               uint64_t data_layout:2;
+               uint64_t reserved_2_63:62;
+#endif
+       } cn30xx;
+       struct cvmx_lmcx_ctl1_cn50xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_10_63:54;
+               uint64_t sil_mode:1;
+               uint64_t dcc_enable:1;
+               uint64_t reserved_2_7:6;
+               uint64_t data_layout:2;
+#else
+               uint64_t data_layout:2;
+               uint64_t reserved_2_7:6;
+               uint64_t dcc_enable:1;
+               uint64_t sil_mode:1;
+               uint64_t reserved_10_63:54;
+#endif
+       } cn50xx;
+       struct cvmx_lmcx_ctl1_cn52xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_21_63:43;
+               uint64_t ecc_adr:1;
+               uint64_t forcewrite:4;
+               uint64_t idlepower:3;
+               uint64_t sequence:3;
+               uint64_t sil_mode:1;
+               uint64_t dcc_enable:1;
+               uint64_t reserved_0_7:8;
+#else
+               uint64_t reserved_0_7:8;
+               uint64_t dcc_enable:1;
+               uint64_t sil_mode:1;
+               uint64_t sequence:3;
+               uint64_t idlepower:3;
+               uint64_t forcewrite:4;
+               uint64_t ecc_adr:1;
+               uint64_t reserved_21_63:43;
+#endif
+       } cn52xx;
+       struct cvmx_lmcx_ctl1_cn52xx cn52xxp1;
+       struct cvmx_lmcx_ctl1_cn52xx cn56xx;
+       struct cvmx_lmcx_ctl1_cn52xx cn56xxp1;
+       struct cvmx_lmcx_ctl1_cn58xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_10_63:54;
+               uint64_t sil_mode:1;
+               uint64_t dcc_enable:1;
+               uint64_t reserved_0_7:8;
+#else
+               uint64_t reserved_0_7:8;
+               uint64_t dcc_enable:1;
+               uint64_t sil_mode:1;
+               uint64_t reserved_10_63:54;
+#endif
+       } cn58xx;
+       struct cvmx_lmcx_ctl1_cn58xx cn58xxp1;
+};
+
+union cvmx_lmcx_dclk_cnt {
+       uint64_t u64;
+       struct cvmx_lmcx_dclk_cnt_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t dclkcnt:64;
+#else
+               uint64_t dclkcnt:64;
+#endif
+       } s;
+       struct cvmx_lmcx_dclk_cnt_s cn61xx;
+       struct cvmx_lmcx_dclk_cnt_s cn63xx;
+       struct cvmx_lmcx_dclk_cnt_s cn63xxp1;
+       struct cvmx_lmcx_dclk_cnt_s cn66xx;
+       struct cvmx_lmcx_dclk_cnt_s cn68xx;
+       struct cvmx_lmcx_dclk_cnt_s cn68xxp1;
+       struct cvmx_lmcx_dclk_cnt_s cnf71xx;
+};
+
+union cvmx_lmcx_dclk_cnt_hi {
+       uint64_t u64;
+       struct cvmx_lmcx_dclk_cnt_hi_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t dclkcnt_hi:32;
+#else
+               uint64_t dclkcnt_hi:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn30xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn31xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn38xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn38xxp2;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn50xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn52xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn52xxp1;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn56xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn56xxp1;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn58xx;
+       struct cvmx_lmcx_dclk_cnt_hi_s cn58xxp1;
+};
+
+union cvmx_lmcx_dclk_cnt_lo {
+       uint64_t u64;
+       struct cvmx_lmcx_dclk_cnt_lo_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t dclkcnt_lo:32;
+#else
+               uint64_t dclkcnt_lo:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn30xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn31xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn38xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn38xxp2;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn50xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn52xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn52xxp1;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn56xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn56xxp1;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn58xx;
+       struct cvmx_lmcx_dclk_cnt_lo_s cn58xxp1;
+};
+
+union cvmx_lmcx_dclk_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_dclk_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_8_63:56;
+               uint64_t off90_ena:1;
+               uint64_t dclk90_byp:1;
+               uint64_t dclk90_ld:1;
+               uint64_t dclk90_vlu:5;
+#else
+               uint64_t dclk90_vlu:5;
+               uint64_t dclk90_ld:1;
+               uint64_t dclk90_byp:1;
+               uint64_t off90_ena:1;
+               uint64_t reserved_8_63:56;
+#endif
+       } s;
+       struct cvmx_lmcx_dclk_ctl_s cn56xx;
+       struct cvmx_lmcx_dclk_ctl_s cn56xxp1;
+};
+
+union cvmx_lmcx_ddr2_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_ddr2_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t bank8:1;
+               uint64_t burst8:1;
+               uint64_t addlat:3;
+               uint64_t pocas:1;
+               uint64_t bwcnt:1;
+               uint64_t twr:3;
+               uint64_t silo_hc:1;
+               uint64_t ddr_eof:4;
+               uint64_t tfaw:5;
+               uint64_t crip_mode:1;
+               uint64_t ddr2t:1;
+               uint64_t odt_ena:1;
+               uint64_t qdll_ena:1;
+               uint64_t dll90_vlu:5;
+               uint64_t dll90_byp:1;
+               uint64_t rdqs:1;
+               uint64_t ddr2:1;
+#else
+               uint64_t ddr2:1;
+               uint64_t rdqs:1;
+               uint64_t dll90_byp:1;
+               uint64_t dll90_vlu:5;
+               uint64_t qdll_ena:1;
+               uint64_t odt_ena:1;
+               uint64_t ddr2t:1;
+               uint64_t crip_mode:1;
+               uint64_t tfaw:5;
+               uint64_t ddr_eof:4;
+               uint64_t silo_hc:1;
+               uint64_t twr:3;
+               uint64_t bwcnt:1;
+               uint64_t pocas:1;
+               uint64_t addlat:3;
+               uint64_t burst8:1;
+               uint64_t bank8:1;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ddr2_ctl_cn30xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t bank8:1;
+               uint64_t burst8:1;
+               uint64_t addlat:3;
+               uint64_t pocas:1;
+               uint64_t bwcnt:1;
+               uint64_t twr:3;
+               uint64_t silo_hc:1;
+               uint64_t ddr_eof:4;
+               uint64_t tfaw:5;
+               uint64_t crip_mode:1;
+               uint64_t ddr2t:1;
+               uint64_t odt_ena:1;
+               uint64_t qdll_ena:1;
+               uint64_t dll90_vlu:5;
+               uint64_t dll90_byp:1;
+               uint64_t reserved_1_1:1;
+               uint64_t ddr2:1;
+#else
+               uint64_t ddr2:1;
+               uint64_t reserved_1_1:1;
+               uint64_t dll90_byp:1;
+               uint64_t dll90_vlu:5;
+               uint64_t qdll_ena:1;
+               uint64_t odt_ena:1;
+               uint64_t ddr2t:1;
+               uint64_t crip_mode:1;
+               uint64_t tfaw:5;
+               uint64_t ddr_eof:4;
+               uint64_t silo_hc:1;
+               uint64_t twr:3;
+               uint64_t bwcnt:1;
+               uint64_t pocas:1;
+               uint64_t addlat:3;
+               uint64_t burst8:1;
+               uint64_t bank8:1;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn30xx;
+       struct cvmx_lmcx_ddr2_ctl_cn30xx cn31xx;
+       struct cvmx_lmcx_ddr2_ctl_s cn38xx;
+       struct cvmx_lmcx_ddr2_ctl_s cn38xxp2;
+       struct cvmx_lmcx_ddr2_ctl_s cn50xx;
+       struct cvmx_lmcx_ddr2_ctl_s cn52xx;
+       struct cvmx_lmcx_ddr2_ctl_s cn52xxp1;
+       struct cvmx_lmcx_ddr2_ctl_s cn56xx;
+       struct cvmx_lmcx_ddr2_ctl_s cn56xxp1;
+       struct cvmx_lmcx_ddr2_ctl_s cn58xx;
+       struct cvmx_lmcx_ddr2_ctl_s cn58xxp1;
+};
+
+union cvmx_lmcx_ddr_pll_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_ddr_pll_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_27_63:37;
+               uint64_t jtg_test_mode:1;
+               uint64_t dfm_div_reset:1;
+               uint64_t dfm_ps_en:3;
+               uint64_t ddr_div_reset:1;
+               uint64_t ddr_ps_en:3;
+               uint64_t diffamp:4;
+               uint64_t cps:3;
+               uint64_t cpb:3;
+               uint64_t reset_n:1;
+               uint64_t clkf:7;
+#else
+               uint64_t clkf:7;
+               uint64_t reset_n:1;
+               uint64_t cpb:3;
+               uint64_t cps:3;
+               uint64_t diffamp:4;
+               uint64_t ddr_ps_en:3;
+               uint64_t ddr_div_reset:1;
+               uint64_t dfm_ps_en:3;
+               uint64_t dfm_div_reset:1;
+               uint64_t jtg_test_mode:1;
+               uint64_t reserved_27_63:37;
+#endif
+       } s;
+       struct cvmx_lmcx_ddr_pll_ctl_s cn61xx;
+       struct cvmx_lmcx_ddr_pll_ctl_s cn63xx;
+       struct cvmx_lmcx_ddr_pll_ctl_s cn63xxp1;
+       struct cvmx_lmcx_ddr_pll_ctl_s cn66xx;
+       struct cvmx_lmcx_ddr_pll_ctl_s cn68xx;
+       struct cvmx_lmcx_ddr_pll_ctl_s cn68xxp1;
+       struct cvmx_lmcx_ddr_pll_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_delay_cfg {
+       uint64_t u64;
+       struct cvmx_lmcx_delay_cfg_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_15_63:49;
+               uint64_t dq:5;
+               uint64_t cmd:5;
+               uint64_t clk:5;
+#else
+               uint64_t clk:5;
+               uint64_t cmd:5;
+               uint64_t dq:5;
+               uint64_t reserved_15_63:49;
+#endif
+       } s;
+       struct cvmx_lmcx_delay_cfg_s cn30xx;
+       struct cvmx_lmcx_delay_cfg_cn38xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_14_63:50;
+               uint64_t dq:4;
+               uint64_t reserved_9_9:1;
+               uint64_t cmd:4;
+               uint64_t reserved_4_4:1;
+               uint64_t clk:4;
+#else
+               uint64_t clk:4;
+               uint64_t reserved_4_4:1;
+               uint64_t cmd:4;
+               uint64_t reserved_9_9:1;
+               uint64_t dq:4;
+               uint64_t reserved_14_63:50;
+#endif
+       } cn38xx;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn50xx;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn52xx;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn52xxp1;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn56xx;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn56xxp1;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn58xx;
+       struct cvmx_lmcx_delay_cfg_cn38xx cn58xxp1;
+};
+
+union cvmx_lmcx_dimmx_params {
+       uint64_t u64;
+       struct cvmx_lmcx_dimmx_params_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t rc15:4;
+               uint64_t rc14:4;
+               uint64_t rc13:4;
+               uint64_t rc12:4;
+               uint64_t rc11:4;
+               uint64_t rc10:4;
+               uint64_t rc9:4;
+               uint64_t rc8:4;
+               uint64_t rc7:4;
+               uint64_t rc6:4;
+               uint64_t rc5:4;
+               uint64_t rc4:4;
+               uint64_t rc3:4;
+               uint64_t rc2:4;
+               uint64_t rc1:4;
+               uint64_t rc0:4;
+#else
+               uint64_t rc0:4;
+               uint64_t rc1:4;
+               uint64_t rc2:4;
+               uint64_t rc3:4;
+               uint64_t rc4:4;
+               uint64_t rc5:4;
+               uint64_t rc6:4;
+               uint64_t rc7:4;
+               uint64_t rc8:4;
+               uint64_t rc9:4;
+               uint64_t rc10:4;
+               uint64_t rc11:4;
+               uint64_t rc12:4;
+               uint64_t rc13:4;
+               uint64_t rc14:4;
+               uint64_t rc15:4;
+#endif
+       } s;
+       struct cvmx_lmcx_dimmx_params_s cn61xx;
+       struct cvmx_lmcx_dimmx_params_s cn63xx;
+       struct cvmx_lmcx_dimmx_params_s cn63xxp1;
+       struct cvmx_lmcx_dimmx_params_s cn66xx;
+       struct cvmx_lmcx_dimmx_params_s cn68xx;
+       struct cvmx_lmcx_dimmx_params_s cn68xxp1;
+       struct cvmx_lmcx_dimmx_params_s cnf71xx;
+};
+
+union cvmx_lmcx_dimm_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_dimm_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_46_63:18;
+               uint64_t parity:1;
+               uint64_t tcws:13;
+               uint64_t dimm1_wmask:16;
+               uint64_t dimm0_wmask:16;
+#else
+               uint64_t dimm0_wmask:16;
+               uint64_t dimm1_wmask:16;
+               uint64_t tcws:13;
+               uint64_t parity:1;
+               uint64_t reserved_46_63:18;
+#endif
+       } s;
+       struct cvmx_lmcx_dimm_ctl_s cn61xx;
+       struct cvmx_lmcx_dimm_ctl_s cn63xx;
+       struct cvmx_lmcx_dimm_ctl_s cn63xxp1;
+       struct cvmx_lmcx_dimm_ctl_s cn66xx;
+       struct cvmx_lmcx_dimm_ctl_s cn68xx;
+       struct cvmx_lmcx_dimm_ctl_s cn68xxp1;
+       struct cvmx_lmcx_dimm_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_dll_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_dll_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_8_63:56;
+               uint64_t dreset:1;
+               uint64_t dll90_byp:1;
+               uint64_t dll90_ena:1;
+               uint64_t dll90_vlu:5;
+#else
+               uint64_t dll90_vlu:5;
+               uint64_t dll90_ena:1;
+               uint64_t dll90_byp:1;
+               uint64_t dreset:1;
+               uint64_t reserved_8_63:56;
+#endif
+       } s;
+       struct cvmx_lmcx_dll_ctl_s cn52xx;
+       struct cvmx_lmcx_dll_ctl_s cn52xxp1;
+       struct cvmx_lmcx_dll_ctl_s cn56xx;
+       struct cvmx_lmcx_dll_ctl_s cn56xxp1;
+};
+
+union cvmx_lmcx_dll_ctl2 {
+       uint64_t u64;
+       struct cvmx_lmcx_dll_ctl2_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_16_63:48;
+               uint64_t intf_en:1;
+               uint64_t dll_bringup:1;
+               uint64_t dreset:1;
+               uint64_t quad_dll_ena:1;
+               uint64_t byp_sel:4;
+               uint64_t byp_setting:8;
+#else
+               uint64_t byp_setting:8;
+               uint64_t byp_sel:4;
+               uint64_t quad_dll_ena:1;
+               uint64_t dreset:1;
+               uint64_t dll_bringup:1;
+               uint64_t intf_en:1;
+               uint64_t reserved_16_63:48;
+#endif
+       } s;
+       struct cvmx_lmcx_dll_ctl2_s cn61xx;
+       struct cvmx_lmcx_dll_ctl2_cn63xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_15_63:49;
+               uint64_t dll_bringup:1;
+               uint64_t dreset:1;
+               uint64_t quad_dll_ena:1;
+               uint64_t byp_sel:4;
+               uint64_t byp_setting:8;
+#else
+               uint64_t byp_setting:8;
+               uint64_t byp_sel:4;
+               uint64_t quad_dll_ena:1;
+               uint64_t dreset:1;
+               uint64_t dll_bringup:1;
+               uint64_t reserved_15_63:49;
+#endif
+       } cn63xx;
+       struct cvmx_lmcx_dll_ctl2_cn63xx cn63xxp1;
+       struct cvmx_lmcx_dll_ctl2_cn63xx cn66xx;
+       struct cvmx_lmcx_dll_ctl2_s cn68xx;
+       struct cvmx_lmcx_dll_ctl2_s cn68xxp1;
+       struct cvmx_lmcx_dll_ctl2_s cnf71xx;
+};
+
+union cvmx_lmcx_dll_ctl3 {
+       uint64_t u64;
+       struct cvmx_lmcx_dll_ctl3_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_41_63:23;
+               uint64_t dclk90_fwd:1;
+               uint64_t ddr_90_dly_byp:1;
+               uint64_t dclk90_recal_dis:1;
+               uint64_t dclk90_byp_sel:1;
+               uint64_t dclk90_byp_setting:8;
+               uint64_t dll_fast:1;
+               uint64_t dll90_setting:8;
+               uint64_t fine_tune_mode:1;
+               uint64_t dll_mode:1;
+               uint64_t dll90_byte_sel:4;
+               uint64_t offset_ena:1;
+               uint64_t load_offset:1;
+               uint64_t mode_sel:2;
+               uint64_t byte_sel:4;
+               uint64_t offset:6;
+#else
+               uint64_t offset:6;
+               uint64_t byte_sel:4;
+               uint64_t mode_sel:2;
+               uint64_t load_offset:1;
+               uint64_t offset_ena:1;
+               uint64_t dll90_byte_sel:4;
+               uint64_t dll_mode:1;
+               uint64_t fine_tune_mode:1;
+               uint64_t dll90_setting:8;
+               uint64_t dll_fast:1;
+               uint64_t dclk90_byp_setting:8;
+               uint64_t dclk90_byp_sel:1;
+               uint64_t dclk90_recal_dis:1;
+               uint64_t ddr_90_dly_byp:1;
+               uint64_t dclk90_fwd:1;
+               uint64_t reserved_41_63:23;
+#endif
+       } s;
+       struct cvmx_lmcx_dll_ctl3_s cn61xx;
+       struct cvmx_lmcx_dll_ctl3_cn63xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_29_63:35;
+               uint64_t dll_fast:1;
+               uint64_t dll90_setting:8;
+               uint64_t fine_tune_mode:1;
+               uint64_t dll_mode:1;
+               uint64_t dll90_byte_sel:4;
+               uint64_t offset_ena:1;
+               uint64_t load_offset:1;
+               uint64_t mode_sel:2;
+               uint64_t byte_sel:4;
+               uint64_t offset:6;
+#else
+               uint64_t offset:6;
+               uint64_t byte_sel:4;
+               uint64_t mode_sel:2;
+               uint64_t load_offset:1;
+               uint64_t offset_ena:1;
+               uint64_t dll90_byte_sel:4;
+               uint64_t dll_mode:1;
+               uint64_t fine_tune_mode:1;
+               uint64_t dll90_setting:8;
+               uint64_t dll_fast:1;
+               uint64_t reserved_29_63:35;
+#endif
+       } cn63xx;
+       struct cvmx_lmcx_dll_ctl3_cn63xx cn63xxp1;
+       struct cvmx_lmcx_dll_ctl3_cn63xx cn66xx;
+       struct cvmx_lmcx_dll_ctl3_s cn68xx;
+       struct cvmx_lmcx_dll_ctl3_s cn68xxp1;
+       struct cvmx_lmcx_dll_ctl3_s cnf71xx;
+};
+
+union cvmx_lmcx_dual_memcfg {
+       uint64_t u64;
+       struct cvmx_lmcx_dual_memcfg_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_20_63:44;
+               uint64_t bank8:1;
+               uint64_t row_lsb:3;
+               uint64_t reserved_8_15:8;
+               uint64_t cs_mask:8;
+#else
+               uint64_t cs_mask:8;
+               uint64_t reserved_8_15:8;
+               uint64_t row_lsb:3;
+               uint64_t bank8:1;
+               uint64_t reserved_20_63:44;
+#endif
+       } s;
+       struct cvmx_lmcx_dual_memcfg_s cn50xx;
+       struct cvmx_lmcx_dual_memcfg_s cn52xx;
+       struct cvmx_lmcx_dual_memcfg_s cn52xxp1;
+       struct cvmx_lmcx_dual_memcfg_s cn56xx;
+       struct cvmx_lmcx_dual_memcfg_s cn56xxp1;
+       struct cvmx_lmcx_dual_memcfg_s cn58xx;
+       struct cvmx_lmcx_dual_memcfg_s cn58xxp1;
+       struct cvmx_lmcx_dual_memcfg_cn61xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_19_63:45;
+               uint64_t row_lsb:3;
+               uint64_t reserved_8_15:8;
+               uint64_t cs_mask:8;
+#else
+               uint64_t cs_mask:8;
+               uint64_t reserved_8_15:8;
+               uint64_t row_lsb:3;
+               uint64_t reserved_19_63:45;
+#endif
+       } cn61xx;
+       struct cvmx_lmcx_dual_memcfg_cn61xx cn63xx;
+       struct cvmx_lmcx_dual_memcfg_cn61xx cn63xxp1;
+       struct cvmx_lmcx_dual_memcfg_cn61xx cn66xx;
+       struct cvmx_lmcx_dual_memcfg_cn61xx cn68xx;
+       struct cvmx_lmcx_dual_memcfg_cn61xx cn68xxp1;
+       struct cvmx_lmcx_dual_memcfg_cn61xx cnf71xx;
+};
+
+union cvmx_lmcx_ecc_synd {
+       uint64_t u64;
+       struct cvmx_lmcx_ecc_synd_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t mrdsyn3:8;
+               uint64_t mrdsyn2:8;
+               uint64_t mrdsyn1:8;
+               uint64_t mrdsyn0:8;
+#else
+               uint64_t mrdsyn0:8;
+               uint64_t mrdsyn1:8;
+               uint64_t mrdsyn2:8;
+               uint64_t mrdsyn3:8;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ecc_synd_s cn30xx;
+       struct cvmx_lmcx_ecc_synd_s cn31xx;
+       struct cvmx_lmcx_ecc_synd_s cn38xx;
+       struct cvmx_lmcx_ecc_synd_s cn38xxp2;
+       struct cvmx_lmcx_ecc_synd_s cn50xx;
+       struct cvmx_lmcx_ecc_synd_s cn52xx;
+       struct cvmx_lmcx_ecc_synd_s cn52xxp1;
+       struct cvmx_lmcx_ecc_synd_s cn56xx;
+       struct cvmx_lmcx_ecc_synd_s cn56xxp1;
+       struct cvmx_lmcx_ecc_synd_s cn58xx;
+       struct cvmx_lmcx_ecc_synd_s cn58xxp1;
+       struct cvmx_lmcx_ecc_synd_s cn61xx;
+       struct cvmx_lmcx_ecc_synd_s cn63xx;
+       struct cvmx_lmcx_ecc_synd_s cn63xxp1;
+       struct cvmx_lmcx_ecc_synd_s cn66xx;
+       struct cvmx_lmcx_ecc_synd_s cn68xx;
+       struct cvmx_lmcx_ecc_synd_s cn68xxp1;
+       struct cvmx_lmcx_ecc_synd_s cnf71xx;
+};
+
+union cvmx_lmcx_fadr {
+       uint64_t u64;
+       struct cvmx_lmcx_fadr_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_0_63:64;
+#else
+               uint64_t reserved_0_63:64;
+#endif
+       } s;
+       struct cvmx_lmcx_fadr_cn30xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t fdimm:2;
+               uint64_t fbunk:1;
+               uint64_t fbank:3;
+               uint64_t frow:14;
+               uint64_t fcol:12;
+#else
+               uint64_t fcol:12;
+               uint64_t frow:14;
+               uint64_t fbank:3;
+               uint64_t fbunk:1;
+               uint64_t fdimm:2;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn30xx;
+       struct cvmx_lmcx_fadr_cn30xx cn31xx;
+       struct cvmx_lmcx_fadr_cn30xx cn38xx;
+       struct cvmx_lmcx_fadr_cn30xx cn38xxp2;
+       struct cvmx_lmcx_fadr_cn30xx cn50xx;
+       struct cvmx_lmcx_fadr_cn30xx cn52xx;
+       struct cvmx_lmcx_fadr_cn30xx cn52xxp1;
+       struct cvmx_lmcx_fadr_cn30xx cn56xx;
+       struct cvmx_lmcx_fadr_cn30xx cn56xxp1;
+       struct cvmx_lmcx_fadr_cn30xx cn58xx;
+       struct cvmx_lmcx_fadr_cn30xx cn58xxp1;
+       struct cvmx_lmcx_fadr_cn61xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_36_63:28;
+               uint64_t fdimm:2;
+               uint64_t fbunk:1;
+               uint64_t fbank:3;
+               uint64_t frow:16;
+               uint64_t fcol:14;
+#else
+               uint64_t fcol:14;
+               uint64_t frow:16;
+               uint64_t fbank:3;
+               uint64_t fbunk:1;
+               uint64_t fdimm:2;
+               uint64_t reserved_36_63:28;
+#endif
+       } cn61xx;
+       struct cvmx_lmcx_fadr_cn61xx cn63xx;
+       struct cvmx_lmcx_fadr_cn61xx cn63xxp1;
+       struct cvmx_lmcx_fadr_cn61xx cn66xx;
+       struct cvmx_lmcx_fadr_cn61xx cn68xx;
+       struct cvmx_lmcx_fadr_cn61xx cn68xxp1;
+       struct cvmx_lmcx_fadr_cn61xx cnf71xx;
+};
+
+union cvmx_lmcx_ifb_cnt {
+       uint64_t u64;
+       struct cvmx_lmcx_ifb_cnt_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t ifbcnt:64;
+#else
+               uint64_t ifbcnt:64;
+#endif
+       } s;
+       struct cvmx_lmcx_ifb_cnt_s cn61xx;
+       struct cvmx_lmcx_ifb_cnt_s cn63xx;
+       struct cvmx_lmcx_ifb_cnt_s cn63xxp1;
+       struct cvmx_lmcx_ifb_cnt_s cn66xx;
+       struct cvmx_lmcx_ifb_cnt_s cn68xx;
+       struct cvmx_lmcx_ifb_cnt_s cn68xxp1;
+       struct cvmx_lmcx_ifb_cnt_s cnf71xx;
+};
+
+union cvmx_lmcx_ifb_cnt_hi {
+       uint64_t u64;
+       struct cvmx_lmcx_ifb_cnt_hi_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ifbcnt_hi:32;
+#else
+               uint64_t ifbcnt_hi:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn30xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn31xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn38xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn38xxp2;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn50xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn52xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn52xxp1;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn56xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn56xxp1;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn58xx;
+       struct cvmx_lmcx_ifb_cnt_hi_s cn58xxp1;
+};
+
+union cvmx_lmcx_ifb_cnt_lo {
+       uint64_t u64;
+       struct cvmx_lmcx_ifb_cnt_lo_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ifbcnt_lo:32;
+#else
+               uint64_t ifbcnt_lo:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn30xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn31xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn38xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn38xxp2;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn50xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn52xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn52xxp1;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn56xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn56xxp1;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn58xx;
+       struct cvmx_lmcx_ifb_cnt_lo_s cn58xxp1;
+};
+
+union cvmx_lmcx_int {
+       uint64_t u64;
+       struct cvmx_lmcx_int_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_9_63:55;
+               uint64_t ded_err:4;
+               uint64_t sec_err:4;
+               uint64_t nxm_wr_err:1;
+#else
+               uint64_t nxm_wr_err:1;
+               uint64_t sec_err:4;
+               uint64_t ded_err:4;
+               uint64_t reserved_9_63:55;
+#endif
+       } s;
+       struct cvmx_lmcx_int_s cn61xx;
+       struct cvmx_lmcx_int_s cn63xx;
+       struct cvmx_lmcx_int_s cn63xxp1;
+       struct cvmx_lmcx_int_s cn66xx;
+       struct cvmx_lmcx_int_s cn68xx;
+       struct cvmx_lmcx_int_s cn68xxp1;
+       struct cvmx_lmcx_int_s cnf71xx;
+};
+
+union cvmx_lmcx_int_en {
+       uint64_t u64;
+       struct cvmx_lmcx_int_en_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_3_63:61;
+               uint64_t intr_ded_ena:1;
+               uint64_t intr_sec_ena:1;
+               uint64_t intr_nxm_wr_ena:1;
+#else
+               uint64_t intr_nxm_wr_ena:1;
+               uint64_t intr_sec_ena:1;
+               uint64_t intr_ded_ena:1;
+               uint64_t reserved_3_63:61;
+#endif
+       } s;
+       struct cvmx_lmcx_int_en_s cn61xx;
+       struct cvmx_lmcx_int_en_s cn63xx;
+       struct cvmx_lmcx_int_en_s cn63xxp1;
+       struct cvmx_lmcx_int_en_s cn66xx;
+       struct cvmx_lmcx_int_en_s cn68xx;
+       struct cvmx_lmcx_int_en_s cn68xxp1;
+       struct cvmx_lmcx_int_en_s cnf71xx;
+};
+
+union cvmx_lmcx_mem_cfg0 {
+       uint64_t u64;
+       struct cvmx_lmcx_mem_cfg0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t reset:1;
+               uint64_t silo_qc:1;
+               uint64_t bunk_ena:1;
+               uint64_t ded_err:4;
+               uint64_t sec_err:4;
+               uint64_t intr_ded_ena:1;
+               uint64_t intr_sec_ena:1;
+               uint64_t tcl:4;
+               uint64_t ref_int:6;
+               uint64_t pbank_lsb:4;
+               uint64_t row_lsb:3;
+               uint64_t ecc_ena:1;
+               uint64_t init_start:1;
+#else
+               uint64_t init_start:1;
+               uint64_t ecc_ena:1;
+               uint64_t row_lsb:3;
+               uint64_t pbank_lsb:4;
+               uint64_t ref_int:6;
+               uint64_t tcl:4;
+               uint64_t intr_sec_ena:1;
+               uint64_t intr_ded_ena:1;
+               uint64_t sec_err:4;
+               uint64_t ded_err:4;
+               uint64_t bunk_ena:1;
+               uint64_t silo_qc:1;
+               uint64_t reset:1;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_mem_cfg0_s cn30xx;
+       struct cvmx_lmcx_mem_cfg0_s cn31xx;
+       struct cvmx_lmcx_mem_cfg0_s cn38xx;
+       struct cvmx_lmcx_mem_cfg0_s cn38xxp2;
+       struct cvmx_lmcx_mem_cfg0_s cn50xx;
+       struct cvmx_lmcx_mem_cfg0_s cn52xx;
+       struct cvmx_lmcx_mem_cfg0_s cn52xxp1;
+       struct cvmx_lmcx_mem_cfg0_s cn56xx;
+       struct cvmx_lmcx_mem_cfg0_s cn56xxp1;
+       struct cvmx_lmcx_mem_cfg0_s cn58xx;
+       struct cvmx_lmcx_mem_cfg0_s cn58xxp1;
+};
+
+union cvmx_lmcx_mem_cfg1 {
+       uint64_t u64;
+       struct cvmx_lmcx_mem_cfg1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t comp_bypass:1;
+               uint64_t trrd:3;
+               uint64_t caslat:3;
+               uint64_t tmrd:3;
+               uint64_t trfc:5;
+               uint64_t trp:4;
+               uint64_t twtr:4;
+               uint64_t trcd:4;
+               uint64_t tras:5;
+#else
+               uint64_t tras:5;
+               uint64_t trcd:4;
+               uint64_t twtr:4;
+               uint64_t trp:4;
+               uint64_t trfc:5;
+               uint64_t tmrd:3;
+               uint64_t caslat:3;
+               uint64_t trrd:3;
+               uint64_t comp_bypass:1;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_mem_cfg1_s cn30xx;
+       struct cvmx_lmcx_mem_cfg1_s cn31xx;
+       struct cvmx_lmcx_mem_cfg1_cn38xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_31_63:33;
+               uint64_t trrd:3;
+               uint64_t caslat:3;
+               uint64_t tmrd:3;
+               uint64_t trfc:5;
+               uint64_t trp:4;
+               uint64_t twtr:4;
+               uint64_t trcd:4;
+               uint64_t tras:5;
+#else
+               uint64_t tras:5;
+               uint64_t trcd:4;
+               uint64_t twtr:4;
+               uint64_t trp:4;
+               uint64_t trfc:5;
+               uint64_t tmrd:3;
+               uint64_t caslat:3;
+               uint64_t trrd:3;
+               uint64_t reserved_31_63:33;
+#endif
+       } cn38xx;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn38xxp2;
+       struct cvmx_lmcx_mem_cfg1_s cn50xx;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn52xx;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn52xxp1;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn56xx;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn56xxp1;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn58xx;
+       struct cvmx_lmcx_mem_cfg1_cn38xx cn58xxp1;
+};
+
+union cvmx_lmcx_modereg_params0 {
+       uint64_t u64;
+       struct cvmx_lmcx_modereg_params0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_25_63:39;
+               uint64_t ppd:1;
+               uint64_t wrp:3;
+               uint64_t dllr:1;
+               uint64_t tm:1;
+               uint64_t rbt:1;
+               uint64_t cl:4;
+               uint64_t bl:2;
+               uint64_t qoff:1;
+               uint64_t tdqs:1;
+               uint64_t wlev:1;
+               uint64_t al:2;
+               uint64_t dll:1;
+               uint64_t mpr:1;
+               uint64_t mprloc:2;
+               uint64_t cwl:3;
+#else
+               uint64_t cwl:3;
+               uint64_t mprloc:2;
+               uint64_t mpr:1;
+               uint64_t dll:1;
+               uint64_t al:2;
+               uint64_t wlev:1;
+               uint64_t tdqs:1;
+               uint64_t qoff:1;
+               uint64_t bl:2;
+               uint64_t cl:4;
+               uint64_t rbt:1;
+               uint64_t tm:1;
+               uint64_t dllr:1;
+               uint64_t wrp:3;
+               uint64_t ppd:1;
+               uint64_t reserved_25_63:39;
+#endif
+       } s;
+       struct cvmx_lmcx_modereg_params0_s cn61xx;
+       struct cvmx_lmcx_modereg_params0_s cn63xx;
+       struct cvmx_lmcx_modereg_params0_s cn63xxp1;
+       struct cvmx_lmcx_modereg_params0_s cn66xx;
+       struct cvmx_lmcx_modereg_params0_s cn68xx;
+       struct cvmx_lmcx_modereg_params0_s cn68xxp1;
+       struct cvmx_lmcx_modereg_params0_s cnf71xx;
+};
+
+union cvmx_lmcx_modereg_params1 {
+       uint64_t u64;
+       struct cvmx_lmcx_modereg_params1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_48_63:16;
+               uint64_t rtt_nom_11:3;
+               uint64_t dic_11:2;
+               uint64_t rtt_wr_11:2;
+               uint64_t srt_11:1;
+               uint64_t asr_11:1;
+               uint64_t pasr_11:3;
+               uint64_t rtt_nom_10:3;
+               uint64_t dic_10:2;
+               uint64_t rtt_wr_10:2;
+               uint64_t srt_10:1;
+               uint64_t asr_10:1;
+               uint64_t pasr_10:3;
+               uint64_t rtt_nom_01:3;
+               uint64_t dic_01:2;
+               uint64_t rtt_wr_01:2;
+               uint64_t srt_01:1;
+               uint64_t asr_01:1;
+               uint64_t pasr_01:3;
+               uint64_t rtt_nom_00:3;
+               uint64_t dic_00:2;
+               uint64_t rtt_wr_00:2;
+               uint64_t srt_00:1;
+               uint64_t asr_00:1;
+               uint64_t pasr_00:3;
+#else
+               uint64_t pasr_00:3;
+               uint64_t asr_00:1;
+               uint64_t srt_00:1;
+               uint64_t rtt_wr_00:2;
+               uint64_t dic_00:2;
+               uint64_t rtt_nom_00:3;
+               uint64_t pasr_01:3;
+               uint64_t asr_01:1;
+               uint64_t srt_01:1;
+               uint64_t rtt_wr_01:2;
+               uint64_t dic_01:2;
+               uint64_t rtt_nom_01:3;
+               uint64_t pasr_10:3;
+               uint64_t asr_10:1;
+               uint64_t srt_10:1;
+               uint64_t rtt_wr_10:2;
+               uint64_t dic_10:2;
+               uint64_t rtt_nom_10:3;
+               uint64_t pasr_11:3;
+               uint64_t asr_11:1;
+               uint64_t srt_11:1;
+               uint64_t rtt_wr_11:2;
+               uint64_t dic_11:2;
+               uint64_t rtt_nom_11:3;
+               uint64_t reserved_48_63:16;
+#endif
+       } s;
+       struct cvmx_lmcx_modereg_params1_s cn61xx;
+       struct cvmx_lmcx_modereg_params1_s cn63xx;
+       struct cvmx_lmcx_modereg_params1_s cn63xxp1;
+       struct cvmx_lmcx_modereg_params1_s cn66xx;
+       struct cvmx_lmcx_modereg_params1_s cn68xx;
+       struct cvmx_lmcx_modereg_params1_s cn68xxp1;
+       struct cvmx_lmcx_modereg_params1_s cnf71xx;
+};
+
+union cvmx_lmcx_nxm {
+       uint64_t u64;
+       struct cvmx_lmcx_nxm_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_40_63:24;
+               uint64_t mem_msb_d3_r1:4;
+               uint64_t mem_msb_d3_r0:4;
+               uint64_t mem_msb_d2_r1:4;
+               uint64_t mem_msb_d2_r0:4;
+               uint64_t mem_msb_d1_r1:4;
+               uint64_t mem_msb_d1_r0:4;
+               uint64_t mem_msb_d0_r1:4;
+               uint64_t mem_msb_d0_r0:4;
+               uint64_t cs_mask:8;
+#else
+               uint64_t cs_mask:8;
+               uint64_t mem_msb_d0_r0:4;
+               uint64_t mem_msb_d0_r1:4;
+               uint64_t mem_msb_d1_r0:4;
+               uint64_t mem_msb_d1_r1:4;
+               uint64_t mem_msb_d2_r0:4;
+               uint64_t mem_msb_d2_r1:4;
+               uint64_t mem_msb_d3_r0:4;
+               uint64_t mem_msb_d3_r1:4;
+               uint64_t reserved_40_63:24;
+#endif
+       } s;
+       struct cvmx_lmcx_nxm_cn52xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_8_63:56;
+               uint64_t cs_mask:8;
+#else
+               uint64_t cs_mask:8;
+               uint64_t reserved_8_63:56;
+#endif
+       } cn52xx;
+       struct cvmx_lmcx_nxm_cn52xx cn56xx;
+       struct cvmx_lmcx_nxm_cn52xx cn58xx;
+       struct cvmx_lmcx_nxm_s cn61xx;
+       struct cvmx_lmcx_nxm_s cn63xx;
+       struct cvmx_lmcx_nxm_s cn63xxp1;
+       struct cvmx_lmcx_nxm_s cn66xx;
+       struct cvmx_lmcx_nxm_s cn68xx;
+       struct cvmx_lmcx_nxm_s cn68xxp1;
+       struct cvmx_lmcx_nxm_s cnf71xx;
+};
+
+union cvmx_lmcx_ops_cnt {
+       uint64_t u64;
+       struct cvmx_lmcx_ops_cnt_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t opscnt:64;
+#else
+               uint64_t opscnt:64;
+#endif
+       } s;
+       struct cvmx_lmcx_ops_cnt_s cn61xx;
+       struct cvmx_lmcx_ops_cnt_s cn63xx;
+       struct cvmx_lmcx_ops_cnt_s cn63xxp1;
+       struct cvmx_lmcx_ops_cnt_s cn66xx;
+       struct cvmx_lmcx_ops_cnt_s cn68xx;
+       struct cvmx_lmcx_ops_cnt_s cn68xxp1;
+       struct cvmx_lmcx_ops_cnt_s cnf71xx;
+};
+
+union cvmx_lmcx_ops_cnt_hi {
+       uint64_t u64;
+       struct cvmx_lmcx_ops_cnt_hi_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t opscnt_hi:32;
+#else
+               uint64_t opscnt_hi:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ops_cnt_hi_s cn30xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn31xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn38xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn38xxp2;
+       struct cvmx_lmcx_ops_cnt_hi_s cn50xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn52xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn52xxp1;
+       struct cvmx_lmcx_ops_cnt_hi_s cn56xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn56xxp1;
+       struct cvmx_lmcx_ops_cnt_hi_s cn58xx;
+       struct cvmx_lmcx_ops_cnt_hi_s cn58xxp1;
+};
+
+union cvmx_lmcx_ops_cnt_lo {
+       uint64_t u64;
+       struct cvmx_lmcx_ops_cnt_lo_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t opscnt_lo:32;
+#else
+               uint64_t opscnt_lo:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_ops_cnt_lo_s cn30xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn31xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn38xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn38xxp2;
+       struct cvmx_lmcx_ops_cnt_lo_s cn50xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn52xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn52xxp1;
+       struct cvmx_lmcx_ops_cnt_lo_s cn56xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn56xxp1;
+       struct cvmx_lmcx_ops_cnt_lo_s cn58xx;
+       struct cvmx_lmcx_ops_cnt_lo_s cn58xxp1;
+};
+
+union cvmx_lmcx_phy_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_phy_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_15_63:49;
+               uint64_t rx_always_on:1;
+               uint64_t lv_mode:1;
+               uint64_t ck_tune1:1;
+               uint64_t ck_dlyout1:4;
+               uint64_t ck_tune0:1;
+               uint64_t ck_dlyout0:4;
+               uint64_t loopback:1;
+               uint64_t loopback_pos:1;
+               uint64_t ts_stagger:1;
+#else
+               uint64_t ts_stagger:1;
+               uint64_t loopback_pos:1;
+               uint64_t loopback:1;
+               uint64_t ck_dlyout0:4;
+               uint64_t ck_tune0:1;
+               uint64_t ck_dlyout1:4;
+               uint64_t ck_tune1:1;
+               uint64_t lv_mode:1;
+               uint64_t rx_always_on:1;
+               uint64_t reserved_15_63:49;
+#endif
+       } s;
+       struct cvmx_lmcx_phy_ctl_s cn61xx;
+       struct cvmx_lmcx_phy_ctl_s cn63xx;
+       struct cvmx_lmcx_phy_ctl_cn63xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_14_63:50;
+               uint64_t lv_mode:1;
+               uint64_t ck_tune1:1;
+               uint64_t ck_dlyout1:4;
+               uint64_t ck_tune0:1;
+               uint64_t ck_dlyout0:4;
+               uint64_t loopback:1;
+               uint64_t loopback_pos:1;
+               uint64_t ts_stagger:1;
+#else
+               uint64_t ts_stagger:1;
+               uint64_t loopback_pos:1;
+               uint64_t loopback:1;
+               uint64_t ck_dlyout0:4;
+               uint64_t ck_tune0:1;
+               uint64_t ck_dlyout1:4;
+               uint64_t ck_tune1:1;
+               uint64_t lv_mode:1;
+               uint64_t reserved_14_63:50;
+#endif
+       } cn63xxp1;
+       struct cvmx_lmcx_phy_ctl_s cn66xx;
+       struct cvmx_lmcx_phy_ctl_s cn68xx;
+       struct cvmx_lmcx_phy_ctl_s cn68xxp1;
+       struct cvmx_lmcx_phy_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_pll_bwctl {
+       uint64_t u64;
+       struct cvmx_lmcx_pll_bwctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_5_63:59;
+               uint64_t bwupd:1;
+               uint64_t bwctl:4;
+#else
+               uint64_t bwctl:4;
+               uint64_t bwupd:1;
+               uint64_t reserved_5_63:59;
+#endif
+       } s;
+       struct cvmx_lmcx_pll_bwctl_s cn30xx;
+       struct cvmx_lmcx_pll_bwctl_s cn31xx;
+       struct cvmx_lmcx_pll_bwctl_s cn38xx;
+       struct cvmx_lmcx_pll_bwctl_s cn38xxp2;
+};
+
+union cvmx_lmcx_pll_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_pll_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_30_63:34;
+               uint64_t bypass:1;
+               uint64_t fasten_n:1;
+               uint64_t div_reset:1;
+               uint64_t reset_n:1;
+               uint64_t clkf:12;
+               uint64_t clkr:6;
+               uint64_t reserved_6_7:2;
+               uint64_t en16:1;
+               uint64_t en12:1;
+               uint64_t en8:1;
+               uint64_t en6:1;
+               uint64_t en4:1;
+               uint64_t en2:1;
+#else
+               uint64_t en2:1;
+               uint64_t en4:1;
+               uint64_t en6:1;
+               uint64_t en8:1;
+               uint64_t en12:1;
+               uint64_t en16:1;
+               uint64_t reserved_6_7:2;
+               uint64_t clkr:6;
+               uint64_t clkf:12;
+               uint64_t reset_n:1;
+               uint64_t div_reset:1;
+               uint64_t fasten_n:1;
+               uint64_t bypass:1;
+               uint64_t reserved_30_63:34;
+#endif
+       } s;
+       struct cvmx_lmcx_pll_ctl_cn50xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_29_63:35;
+               uint64_t fasten_n:1;
+               uint64_t div_reset:1;
+               uint64_t reset_n:1;
+               uint64_t clkf:12;
+               uint64_t clkr:6;
+               uint64_t reserved_6_7:2;
+               uint64_t en16:1;
+               uint64_t en12:1;
+               uint64_t en8:1;
+               uint64_t en6:1;
+               uint64_t en4:1;
+               uint64_t en2:1;
+#else
+               uint64_t en2:1;
+               uint64_t en4:1;
+               uint64_t en6:1;
+               uint64_t en8:1;
+               uint64_t en12:1;
+               uint64_t en16:1;
+               uint64_t reserved_6_7:2;
+               uint64_t clkr:6;
+               uint64_t clkf:12;
+               uint64_t reset_n:1;
+               uint64_t div_reset:1;
+               uint64_t fasten_n:1;
+               uint64_t reserved_29_63:35;
+#endif
+       } cn50xx;
+       struct cvmx_lmcx_pll_ctl_s cn52xx;
+       struct cvmx_lmcx_pll_ctl_s cn52xxp1;
+       struct cvmx_lmcx_pll_ctl_cn50xx cn56xx;
+       struct cvmx_lmcx_pll_ctl_cn56xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_28_63:36;
+               uint64_t div_reset:1;
+               uint64_t reset_n:1;
+               uint64_t clkf:12;
+               uint64_t clkr:6;
+               uint64_t reserved_6_7:2;
+               uint64_t en16:1;
+               uint64_t en12:1;
+               uint64_t en8:1;
+               uint64_t en6:1;
+               uint64_t en4:1;
+               uint64_t en2:1;
+#else
+               uint64_t en2:1;
+               uint64_t en4:1;
+               uint64_t en6:1;
+               uint64_t en8:1;
+               uint64_t en12:1;
+               uint64_t en16:1;
+               uint64_t reserved_6_7:2;
+               uint64_t clkr:6;
+               uint64_t clkf:12;
+               uint64_t reset_n:1;
+               uint64_t div_reset:1;
+               uint64_t reserved_28_63:36;
+#endif
+       } cn56xxp1;
+       struct cvmx_lmcx_pll_ctl_cn56xxp1 cn58xx;
+       struct cvmx_lmcx_pll_ctl_cn56xxp1 cn58xxp1;
+};
+
+union cvmx_lmcx_pll_status {
+       uint64_t u64;
+       struct cvmx_lmcx_pll_status_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ddr__nctl:5;
+               uint64_t ddr__pctl:5;
+               uint64_t reserved_2_21:20;
+               uint64_t rfslip:1;
+               uint64_t fbslip:1;
+#else
+               uint64_t fbslip:1;
+               uint64_t rfslip:1;
+               uint64_t reserved_2_21:20;
+               uint64_t ddr__pctl:5;
+               uint64_t ddr__nctl:5;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_pll_status_s cn50xx;
+       struct cvmx_lmcx_pll_status_s cn52xx;
+       struct cvmx_lmcx_pll_status_s cn52xxp1;
+       struct cvmx_lmcx_pll_status_s cn56xx;
+       struct cvmx_lmcx_pll_status_s cn56xxp1;
+       struct cvmx_lmcx_pll_status_s cn58xx;
+       struct cvmx_lmcx_pll_status_cn58xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_2_63:62;
+               uint64_t rfslip:1;
+               uint64_t fbslip:1;
+#else
+               uint64_t fbslip:1;
+               uint64_t rfslip:1;
+               uint64_t reserved_2_63:62;
+#endif
+       } cn58xxp1;
+};
+
+union cvmx_lmcx_read_level_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_read_level_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_44_63:20;
+               uint64_t rankmask:4;
+               uint64_t pattern:8;
+               uint64_t row:16;
+               uint64_t col:12;
+               uint64_t reserved_3_3:1;
+               uint64_t bnk:3;
+#else
+               uint64_t bnk:3;
+               uint64_t reserved_3_3:1;
+               uint64_t col:12;
+               uint64_t row:16;
+               uint64_t pattern:8;
+               uint64_t rankmask:4;
+               uint64_t reserved_44_63:20;
+#endif
+       } s;
+       struct cvmx_lmcx_read_level_ctl_s cn52xx;
+       struct cvmx_lmcx_read_level_ctl_s cn52xxp1;
+       struct cvmx_lmcx_read_level_ctl_s cn56xx;
+       struct cvmx_lmcx_read_level_ctl_s cn56xxp1;
+};
+
+union cvmx_lmcx_read_level_dbg {
+       uint64_t u64;
+       struct cvmx_lmcx_read_level_dbg_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t bitmask:16;
+               uint64_t reserved_4_15:12;
+               uint64_t byte:4;
+#else
+               uint64_t byte:4;
+               uint64_t reserved_4_15:12;
+               uint64_t bitmask:16;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_read_level_dbg_s cn52xx;
+       struct cvmx_lmcx_read_level_dbg_s cn52xxp1;
+       struct cvmx_lmcx_read_level_dbg_s cn56xx;
+       struct cvmx_lmcx_read_level_dbg_s cn56xxp1;
+};
+
+union cvmx_lmcx_read_level_rankx {
+       uint64_t u64;
+       struct cvmx_lmcx_read_level_rankx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_38_63:26;
+               uint64_t status:2;
+               uint64_t byte8:4;
+               uint64_t byte7:4;
+               uint64_t byte6:4;
+               uint64_t byte5:4;
+               uint64_t byte4:4;
+               uint64_t byte3:4;
+               uint64_t byte2:4;
+               uint64_t byte1:4;
+               uint64_t byte0:4;
+#else
+               uint64_t byte0:4;
+               uint64_t byte1:4;
+               uint64_t byte2:4;
+               uint64_t byte3:4;
+               uint64_t byte4:4;
+               uint64_t byte5:4;
+               uint64_t byte6:4;
+               uint64_t byte7:4;
+               uint64_t byte8:4;
+               uint64_t status:2;
+               uint64_t reserved_38_63:26;
+#endif
+       } s;
+       struct cvmx_lmcx_read_level_rankx_s cn52xx;
+       struct cvmx_lmcx_read_level_rankx_s cn52xxp1;
+       struct cvmx_lmcx_read_level_rankx_s cn56xx;
+       struct cvmx_lmcx_read_level_rankx_s cn56xxp1;
+};
+
+union cvmx_lmcx_reset_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_reset_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_4_63:60;
+               uint64_t ddr3psv:1;
+               uint64_t ddr3psoft:1;
+               uint64_t ddr3pwarm:1;
+               uint64_t ddr3rst:1;
+#else
+               uint64_t ddr3rst:1;
+               uint64_t ddr3pwarm:1;
+               uint64_t ddr3psoft:1;
+               uint64_t ddr3psv:1;
+               uint64_t reserved_4_63:60;
+#endif
+       } s;
+       struct cvmx_lmcx_reset_ctl_s cn61xx;
+       struct cvmx_lmcx_reset_ctl_s cn63xx;
+       struct cvmx_lmcx_reset_ctl_s cn63xxp1;
+       struct cvmx_lmcx_reset_ctl_s cn66xx;
+       struct cvmx_lmcx_reset_ctl_s cn68xx;
+       struct cvmx_lmcx_reset_ctl_s cn68xxp1;
+       struct cvmx_lmcx_reset_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_rlevel_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_rlevel_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_22_63:42;
+               uint64_t delay_unload_3:1;
+               uint64_t delay_unload_2:1;
+               uint64_t delay_unload_1:1;
+               uint64_t delay_unload_0:1;
+               uint64_t bitmask:8;
+               uint64_t or_dis:1;
+               uint64_t offset_en:1;
+               uint64_t offset:4;
+               uint64_t byte:4;
+#else
+               uint64_t byte:4;
+               uint64_t offset:4;
+               uint64_t offset_en:1;
+               uint64_t or_dis:1;
+               uint64_t bitmask:8;
+               uint64_t delay_unload_0:1;
+               uint64_t delay_unload_1:1;
+               uint64_t delay_unload_2:1;
+               uint64_t delay_unload_3:1;
+               uint64_t reserved_22_63:42;
+#endif
+       } s;
+       struct cvmx_lmcx_rlevel_ctl_s cn61xx;
+       struct cvmx_lmcx_rlevel_ctl_s cn63xx;
+       struct cvmx_lmcx_rlevel_ctl_cn63xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_9_63:55;
+               uint64_t offset_en:1;
+               uint64_t offset:4;
+               uint64_t byte:4;
+#else
+               uint64_t byte:4;
+               uint64_t offset:4;
+               uint64_t offset_en:1;
+               uint64_t reserved_9_63:55;
+#endif
+       } cn63xxp1;
+       struct cvmx_lmcx_rlevel_ctl_s cn66xx;
+       struct cvmx_lmcx_rlevel_ctl_s cn68xx;
+       struct cvmx_lmcx_rlevel_ctl_s cn68xxp1;
+       struct cvmx_lmcx_rlevel_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_rlevel_dbg {
+       uint64_t u64;
+       struct cvmx_lmcx_rlevel_dbg_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t bitmask:64;
+#else
+               uint64_t bitmask:64;
+#endif
+       } s;
+       struct cvmx_lmcx_rlevel_dbg_s cn61xx;
+       struct cvmx_lmcx_rlevel_dbg_s cn63xx;
+       struct cvmx_lmcx_rlevel_dbg_s cn63xxp1;
+       struct cvmx_lmcx_rlevel_dbg_s cn66xx;
+       struct cvmx_lmcx_rlevel_dbg_s cn68xx;
+       struct cvmx_lmcx_rlevel_dbg_s cn68xxp1;
+       struct cvmx_lmcx_rlevel_dbg_s cnf71xx;
+};
+
+union cvmx_lmcx_rlevel_rankx {
+       uint64_t u64;
+       struct cvmx_lmcx_rlevel_rankx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_56_63:8;
+               uint64_t status:2;
+               uint64_t byte8:6;
+               uint64_t byte7:6;
+               uint64_t byte6:6;
+               uint64_t byte5:6;
+               uint64_t byte4:6;
+               uint64_t byte3:6;
+               uint64_t byte2:6;
+               uint64_t byte1:6;
+               uint64_t byte0:6;
+#else
+               uint64_t byte0:6;
+               uint64_t byte1:6;
+               uint64_t byte2:6;
+               uint64_t byte3:6;
+               uint64_t byte4:6;
+               uint64_t byte5:6;
+               uint64_t byte6:6;
+               uint64_t byte7:6;
+               uint64_t byte8:6;
+               uint64_t status:2;
+               uint64_t reserved_56_63:8;
+#endif
+       } s;
+       struct cvmx_lmcx_rlevel_rankx_s cn61xx;
+       struct cvmx_lmcx_rlevel_rankx_s cn63xx;
+       struct cvmx_lmcx_rlevel_rankx_s cn63xxp1;
+       struct cvmx_lmcx_rlevel_rankx_s cn66xx;
+       struct cvmx_lmcx_rlevel_rankx_s cn68xx;
+       struct cvmx_lmcx_rlevel_rankx_s cn68xxp1;
+       struct cvmx_lmcx_rlevel_rankx_s cnf71xx;
+};
+
+union cvmx_lmcx_rodt_comp_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_rodt_comp_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_17_63:47;
+               uint64_t enable:1;
+               uint64_t reserved_12_15:4;
+               uint64_t nctl:4;
+               uint64_t reserved_5_7:3;
+               uint64_t pctl:5;
+#else
+               uint64_t pctl:5;
+               uint64_t reserved_5_7:3;
+               uint64_t nctl:4;
+               uint64_t reserved_12_15:4;
+               uint64_t enable:1;
+               uint64_t reserved_17_63:47;
+#endif
+       } s;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn50xx;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn52xx;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn52xxp1;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn56xx;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn56xxp1;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn58xx;
+       struct cvmx_lmcx_rodt_comp_ctl_s cn58xxp1;
+};
+
+union cvmx_lmcx_rodt_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_rodt_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t rodt_hi3:4;
+               uint64_t rodt_hi2:4;
+               uint64_t rodt_hi1:4;
+               uint64_t rodt_hi0:4;
+               uint64_t rodt_lo3:4;
+               uint64_t rodt_lo2:4;
+               uint64_t rodt_lo1:4;
+               uint64_t rodt_lo0:4;
+#else
+               uint64_t rodt_lo0:4;
+               uint64_t rodt_lo1:4;
+               uint64_t rodt_lo2:4;
+               uint64_t rodt_lo3:4;
+               uint64_t rodt_hi0:4;
+               uint64_t rodt_hi1:4;
+               uint64_t rodt_hi2:4;
+               uint64_t rodt_hi3:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_rodt_ctl_s cn30xx;
+       struct cvmx_lmcx_rodt_ctl_s cn31xx;
+       struct cvmx_lmcx_rodt_ctl_s cn38xx;
+       struct cvmx_lmcx_rodt_ctl_s cn38xxp2;
+       struct cvmx_lmcx_rodt_ctl_s cn50xx;
+       struct cvmx_lmcx_rodt_ctl_s cn52xx;
+       struct cvmx_lmcx_rodt_ctl_s cn52xxp1;
+       struct cvmx_lmcx_rodt_ctl_s cn56xx;
+       struct cvmx_lmcx_rodt_ctl_s cn56xxp1;
+       struct cvmx_lmcx_rodt_ctl_s cn58xx;
+       struct cvmx_lmcx_rodt_ctl_s cn58xxp1;
+};
+
+union cvmx_lmcx_rodt_mask {
+       uint64_t u64;
+       struct cvmx_lmcx_rodt_mask_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t rodt_d3_r1:8;
+               uint64_t rodt_d3_r0:8;
+               uint64_t rodt_d2_r1:8;
+               uint64_t rodt_d2_r0:8;
+               uint64_t rodt_d1_r1:8;
+               uint64_t rodt_d1_r0:8;
+               uint64_t rodt_d0_r1:8;
+               uint64_t rodt_d0_r0:8;
+#else
+               uint64_t rodt_d0_r0:8;
+               uint64_t rodt_d0_r1:8;
+               uint64_t rodt_d1_r0:8;
+               uint64_t rodt_d1_r1:8;
+               uint64_t rodt_d2_r0:8;
+               uint64_t rodt_d2_r1:8;
+               uint64_t rodt_d3_r0:8;
+               uint64_t rodt_d3_r1:8;
+#endif
+       } s;
+       struct cvmx_lmcx_rodt_mask_s cn61xx;
+       struct cvmx_lmcx_rodt_mask_s cn63xx;
+       struct cvmx_lmcx_rodt_mask_s cn63xxp1;
+       struct cvmx_lmcx_rodt_mask_s cn66xx;
+       struct cvmx_lmcx_rodt_mask_s cn68xx;
+       struct cvmx_lmcx_rodt_mask_s cn68xxp1;
+       struct cvmx_lmcx_rodt_mask_s cnf71xx;
+};
+
+union cvmx_lmcx_scramble_cfg0 {
+       uint64_t u64;
+       struct cvmx_lmcx_scramble_cfg0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t key:64;
+#else
+               uint64_t key:64;
+#endif
+       } s;
+       struct cvmx_lmcx_scramble_cfg0_s cn61xx;
+       struct cvmx_lmcx_scramble_cfg0_s cn66xx;
+       struct cvmx_lmcx_scramble_cfg0_s cnf71xx;
+};
+
+union cvmx_lmcx_scramble_cfg1 {
+       uint64_t u64;
+       struct cvmx_lmcx_scramble_cfg1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t key:64;
+#else
+               uint64_t key:64;
+#endif
+       } s;
+       struct cvmx_lmcx_scramble_cfg1_s cn61xx;
+       struct cvmx_lmcx_scramble_cfg1_s cn66xx;
+       struct cvmx_lmcx_scramble_cfg1_s cnf71xx;
+};
+
+union cvmx_lmcx_scrambled_fadr {
+       uint64_t u64;
+       struct cvmx_lmcx_scrambled_fadr_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_36_63:28;
+               uint64_t fdimm:2;
+               uint64_t fbunk:1;
+               uint64_t fbank:3;
+               uint64_t frow:16;
+               uint64_t fcol:14;
+#else
+               uint64_t fcol:14;
+               uint64_t frow:16;
+               uint64_t fbank:3;
+               uint64_t fbunk:1;
+               uint64_t fdimm:2;
+               uint64_t reserved_36_63:28;
+#endif
+       } s;
+       struct cvmx_lmcx_scrambled_fadr_s cn61xx;
+       struct cvmx_lmcx_scrambled_fadr_s cn66xx;
+       struct cvmx_lmcx_scrambled_fadr_s cnf71xx;
+};
+
+union cvmx_lmcx_slot_ctl0 {
+       uint64_t u64;
+       struct cvmx_lmcx_slot_ctl0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_24_63:40;
+               uint64_t w2w_init:6;
+               uint64_t w2r_init:6;
+               uint64_t r2w_init:6;
+               uint64_t r2r_init:6;
+#else
+               uint64_t r2r_init:6;
+               uint64_t r2w_init:6;
+               uint64_t w2r_init:6;
+               uint64_t w2w_init:6;
+               uint64_t reserved_24_63:40;
+#endif
+       } s;
+       struct cvmx_lmcx_slot_ctl0_s cn61xx;
+       struct cvmx_lmcx_slot_ctl0_s cn63xx;
+       struct cvmx_lmcx_slot_ctl0_s cn63xxp1;
+       struct cvmx_lmcx_slot_ctl0_s cn66xx;
+       struct cvmx_lmcx_slot_ctl0_s cn68xx;
+       struct cvmx_lmcx_slot_ctl0_s cn68xxp1;
+       struct cvmx_lmcx_slot_ctl0_s cnf71xx;
+};
+
+union cvmx_lmcx_slot_ctl1 {
+       uint64_t u64;
+       struct cvmx_lmcx_slot_ctl1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_24_63:40;
+               uint64_t w2w_xrank_init:6;
+               uint64_t w2r_xrank_init:6;
+               uint64_t r2w_xrank_init:6;
+               uint64_t r2r_xrank_init:6;
+#else
+               uint64_t r2r_xrank_init:6;
+               uint64_t r2w_xrank_init:6;
+               uint64_t w2r_xrank_init:6;
+               uint64_t w2w_xrank_init:6;
+               uint64_t reserved_24_63:40;
+#endif
+       } s;
+       struct cvmx_lmcx_slot_ctl1_s cn61xx;
+       struct cvmx_lmcx_slot_ctl1_s cn63xx;
+       struct cvmx_lmcx_slot_ctl1_s cn63xxp1;
+       struct cvmx_lmcx_slot_ctl1_s cn66xx;
+       struct cvmx_lmcx_slot_ctl1_s cn68xx;
+       struct cvmx_lmcx_slot_ctl1_s cn68xxp1;
+       struct cvmx_lmcx_slot_ctl1_s cnf71xx;
+};
+
+union cvmx_lmcx_slot_ctl2 {
+       uint64_t u64;
+       struct cvmx_lmcx_slot_ctl2_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_24_63:40;
+               uint64_t w2w_xdimm_init:6;
+               uint64_t w2r_xdimm_init:6;
+               uint64_t r2w_xdimm_init:6;
+               uint64_t r2r_xdimm_init:6;
+#else
+               uint64_t r2r_xdimm_init:6;
+               uint64_t r2w_xdimm_init:6;
+               uint64_t w2r_xdimm_init:6;
+               uint64_t w2w_xdimm_init:6;
+               uint64_t reserved_24_63:40;
+#endif
+       } s;
+       struct cvmx_lmcx_slot_ctl2_s cn61xx;
+       struct cvmx_lmcx_slot_ctl2_s cn63xx;
+       struct cvmx_lmcx_slot_ctl2_s cn63xxp1;
+       struct cvmx_lmcx_slot_ctl2_s cn66xx;
+       struct cvmx_lmcx_slot_ctl2_s cn68xx;
+       struct cvmx_lmcx_slot_ctl2_s cn68xxp1;
+       struct cvmx_lmcx_slot_ctl2_s cnf71xx;
+};
+
+union cvmx_lmcx_timing_params0 {
+       uint64_t u64;
+       struct cvmx_lmcx_timing_params0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_47_63:17;
+               uint64_t trp_ext:1;
+               uint64_t tcksre:4;
+               uint64_t trp:4;
+               uint64_t tzqinit:4;
+               uint64_t tdllk:4;
+               uint64_t tmod:4;
+               uint64_t tmrd:4;
+               uint64_t txpr:4;
+               uint64_t tcke:4;
+               uint64_t tzqcs:4;
+               uint64_t tckeon:10;
+#else
+               uint64_t tckeon:10;
+               uint64_t tzqcs:4;
+               uint64_t tcke:4;
+               uint64_t txpr:4;
+               uint64_t tmrd:4;
+               uint64_t tmod:4;
+               uint64_t tdllk:4;
+               uint64_t tzqinit:4;
+               uint64_t trp:4;
+               uint64_t tcksre:4;
+               uint64_t trp_ext:1;
+               uint64_t reserved_47_63:17;
+#endif
+       } s;
+       struct cvmx_lmcx_timing_params0_cn61xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_47_63:17;
+               uint64_t trp_ext:1;
+               uint64_t tcksre:4;
+               uint64_t trp:4;
+               uint64_t tzqinit:4;
+               uint64_t tdllk:4;
+               uint64_t tmod:4;
+               uint64_t tmrd:4;
+               uint64_t txpr:4;
+               uint64_t tcke:4;
+               uint64_t tzqcs:4;
+               uint64_t reserved_0_9:10;
+#else
+               uint64_t reserved_0_9:10;
+               uint64_t tzqcs:4;
+               uint64_t tcke:4;
+               uint64_t txpr:4;
+               uint64_t tmrd:4;
+               uint64_t tmod:4;
+               uint64_t tdllk:4;
+               uint64_t tzqinit:4;
+               uint64_t trp:4;
+               uint64_t tcksre:4;
+               uint64_t trp_ext:1;
+               uint64_t reserved_47_63:17;
+#endif
+       } cn61xx;
+       struct cvmx_lmcx_timing_params0_cn61xx cn63xx;
+       struct cvmx_lmcx_timing_params0_cn63xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_46_63:18;
+               uint64_t tcksre:4;
+               uint64_t trp:4;
+               uint64_t tzqinit:4;
+               uint64_t tdllk:4;
+               uint64_t tmod:4;
+               uint64_t tmrd:4;
+               uint64_t txpr:4;
+               uint64_t tcke:4;
+               uint64_t tzqcs:4;
+               uint64_t tckeon:10;
+#else
+               uint64_t tckeon:10;
+               uint64_t tzqcs:4;
+               uint64_t tcke:4;
+               uint64_t txpr:4;
+               uint64_t tmrd:4;
+               uint64_t tmod:4;
+               uint64_t tdllk:4;
+               uint64_t tzqinit:4;
+               uint64_t trp:4;
+               uint64_t tcksre:4;
+               uint64_t reserved_46_63:18;
+#endif
+       } cn63xxp1;
+       struct cvmx_lmcx_timing_params0_cn61xx cn66xx;
+       struct cvmx_lmcx_timing_params0_cn61xx cn68xx;
+       struct cvmx_lmcx_timing_params0_cn61xx cn68xxp1;
+       struct cvmx_lmcx_timing_params0_cn61xx cnf71xx;
+};
+
+union cvmx_lmcx_timing_params1 {
+       uint64_t u64;
+       struct cvmx_lmcx_timing_params1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_47_63:17;
+               uint64_t tras_ext:1;
+               uint64_t txpdll:5;
+               uint64_t tfaw:5;
+               uint64_t twldqsen:4;
+               uint64_t twlmrd:4;
+               uint64_t txp:3;
+               uint64_t trrd:3;
+               uint64_t trfc:5;
+               uint64_t twtr:4;
+               uint64_t trcd:4;
+               uint64_t tras:5;
+               uint64_t tmprr:4;
+#else
+               uint64_t tmprr:4;
+               uint64_t tras:5;
+               uint64_t trcd:4;
+               uint64_t twtr:4;
+               uint64_t trfc:5;
+               uint64_t trrd:3;
+               uint64_t txp:3;
+               uint64_t twlmrd:4;
+               uint64_t twldqsen:4;
+               uint64_t tfaw:5;
+               uint64_t txpdll:5;
+               uint64_t tras_ext:1;
+               uint64_t reserved_47_63:17;
+#endif
+       } s;
+       struct cvmx_lmcx_timing_params1_s cn61xx;
+       struct cvmx_lmcx_timing_params1_s cn63xx;
+       struct cvmx_lmcx_timing_params1_cn63xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_46_63:18;
+               uint64_t txpdll:5;
+               uint64_t tfaw:5;
+               uint64_t twldqsen:4;
+               uint64_t twlmrd:4;
+               uint64_t txp:3;
+               uint64_t trrd:3;
+               uint64_t trfc:5;
+               uint64_t twtr:4;
+               uint64_t trcd:4;
+               uint64_t tras:5;
+               uint64_t tmprr:4;
+#else
+               uint64_t tmprr:4;
+               uint64_t tras:5;
+               uint64_t trcd:4;
+               uint64_t twtr:4;
+               uint64_t trfc:5;
+               uint64_t trrd:3;
+               uint64_t txp:3;
+               uint64_t twlmrd:4;
+               uint64_t twldqsen:4;
+               uint64_t tfaw:5;
+               uint64_t txpdll:5;
+               uint64_t reserved_46_63:18;
+#endif
+       } cn63xxp1;
+       struct cvmx_lmcx_timing_params1_s cn66xx;
+       struct cvmx_lmcx_timing_params1_s cn68xx;
+       struct cvmx_lmcx_timing_params1_s cn68xxp1;
+       struct cvmx_lmcx_timing_params1_s cnf71xx;
+};
+
+union cvmx_lmcx_tro_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_tro_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_33_63:31;
+               uint64_t rclk_cnt:32;
+               uint64_t treset:1;
+#else
+               uint64_t treset:1;
+               uint64_t rclk_cnt:32;
+               uint64_t reserved_33_63:31;
+#endif
+       } s;
+       struct cvmx_lmcx_tro_ctl_s cn61xx;
+       struct cvmx_lmcx_tro_ctl_s cn63xx;
+       struct cvmx_lmcx_tro_ctl_s cn63xxp1;
+       struct cvmx_lmcx_tro_ctl_s cn66xx;
+       struct cvmx_lmcx_tro_ctl_s cn68xx;
+       struct cvmx_lmcx_tro_ctl_s cn68xxp1;
+       struct cvmx_lmcx_tro_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_tro_stat {
+       uint64_t u64;
+       struct cvmx_lmcx_tro_stat_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t ring_cnt:32;
+#else
+               uint64_t ring_cnt:32;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_tro_stat_s cn61xx;
+       struct cvmx_lmcx_tro_stat_s cn63xx;
+       struct cvmx_lmcx_tro_stat_s cn63xxp1;
+       struct cvmx_lmcx_tro_stat_s cn66xx;
+       struct cvmx_lmcx_tro_stat_s cn68xx;
+       struct cvmx_lmcx_tro_stat_s cn68xxp1;
+       struct cvmx_lmcx_tro_stat_s cnf71xx;
+};
+
+union cvmx_lmcx_wlevel_ctl {
+       uint64_t u64;
+       struct cvmx_lmcx_wlevel_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_22_63:42;
+               uint64_t rtt_nom:3;
+               uint64_t bitmask:8;
+               uint64_t or_dis:1;
+               uint64_t sset:1;
+               uint64_t lanemask:9;
+#else
+               uint64_t lanemask:9;
+               uint64_t sset:1;
+               uint64_t or_dis:1;
+               uint64_t bitmask:8;
+               uint64_t rtt_nom:3;
+               uint64_t reserved_22_63:42;
+#endif
+       } s;
+       struct cvmx_lmcx_wlevel_ctl_s cn61xx;
+       struct cvmx_lmcx_wlevel_ctl_s cn63xx;
+       struct cvmx_lmcx_wlevel_ctl_cn63xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_10_63:54;
+               uint64_t sset:1;
+               uint64_t lanemask:9;
+#else
+               uint64_t lanemask:9;
+               uint64_t sset:1;
+               uint64_t reserved_10_63:54;
+#endif
+       } cn63xxp1;
+       struct cvmx_lmcx_wlevel_ctl_s cn66xx;
+       struct cvmx_lmcx_wlevel_ctl_s cn68xx;
+       struct cvmx_lmcx_wlevel_ctl_s cn68xxp1;
+       struct cvmx_lmcx_wlevel_ctl_s cnf71xx;
+};
+
+union cvmx_lmcx_wlevel_dbg {
+       uint64_t u64;
+       struct cvmx_lmcx_wlevel_dbg_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_12_63:52;
+               uint64_t bitmask:8;
+               uint64_t byte:4;
+#else
+               uint64_t byte:4;
+               uint64_t bitmask:8;
+               uint64_t reserved_12_63:52;
+#endif
+       } s;
+       struct cvmx_lmcx_wlevel_dbg_s cn61xx;
+       struct cvmx_lmcx_wlevel_dbg_s cn63xx;
+       struct cvmx_lmcx_wlevel_dbg_s cn63xxp1;
+       struct cvmx_lmcx_wlevel_dbg_s cn66xx;
+       struct cvmx_lmcx_wlevel_dbg_s cn68xx;
+       struct cvmx_lmcx_wlevel_dbg_s cn68xxp1;
+       struct cvmx_lmcx_wlevel_dbg_s cnf71xx;
+};
+
+union cvmx_lmcx_wlevel_rankx {
+       uint64_t u64;
+       struct cvmx_lmcx_wlevel_rankx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_47_63:17;
+               uint64_t status:2;
+               uint64_t byte8:5;
+               uint64_t byte7:5;
+               uint64_t byte6:5;
+               uint64_t byte5:5;
+               uint64_t byte4:5;
+               uint64_t byte3:5;
+               uint64_t byte2:5;
+               uint64_t byte1:5;
+               uint64_t byte0:5;
+#else
+               uint64_t byte0:5;
+               uint64_t byte1:5;
+               uint64_t byte2:5;
+               uint64_t byte3:5;
+               uint64_t byte4:5;
+               uint64_t byte5:5;
+               uint64_t byte6:5;
+               uint64_t byte7:5;
+               uint64_t byte8:5;
+               uint64_t status:2;
+               uint64_t reserved_47_63:17;
+#endif
+       } s;
+       struct cvmx_lmcx_wlevel_rankx_s cn61xx;
+       struct cvmx_lmcx_wlevel_rankx_s cn63xx;
+       struct cvmx_lmcx_wlevel_rankx_s cn63xxp1;
+       struct cvmx_lmcx_wlevel_rankx_s cn66xx;
+       struct cvmx_lmcx_wlevel_rankx_s cn68xx;
+       struct cvmx_lmcx_wlevel_rankx_s cn68xxp1;
+       struct cvmx_lmcx_wlevel_rankx_s cnf71xx;
+};
+
+union cvmx_lmcx_wodt_ctl0 {
+       uint64_t u64;
+       struct cvmx_lmcx_wodt_ctl0_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_0_63:64;
+#else
+               uint64_t reserved_0_63:64;
+#endif
+       } s;
+       struct cvmx_lmcx_wodt_ctl0_cn30xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t wodt_d1_r1:8;
+               uint64_t wodt_d1_r0:8;
+               uint64_t wodt_d0_r1:8;
+               uint64_t wodt_d0_r0:8;
+#else
+               uint64_t wodt_d0_r0:8;
+               uint64_t wodt_d0_r1:8;
+               uint64_t wodt_d1_r0:8;
+               uint64_t wodt_d1_r1:8;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn30xx;
+       struct cvmx_lmcx_wodt_ctl0_cn30xx cn31xx;
+       struct cvmx_lmcx_wodt_ctl0_cn38xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t wodt_hi3:4;
+               uint64_t wodt_hi2:4;
+               uint64_t wodt_hi1:4;
+               uint64_t wodt_hi0:4;
+               uint64_t wodt_lo3:4;
+               uint64_t wodt_lo2:4;
+               uint64_t wodt_lo1:4;
+               uint64_t wodt_lo0:4;
+#else
+               uint64_t wodt_lo0:4;
+               uint64_t wodt_lo1:4;
+               uint64_t wodt_lo2:4;
+               uint64_t wodt_lo3:4;
+               uint64_t wodt_hi0:4;
+               uint64_t wodt_hi1:4;
+               uint64_t wodt_hi2:4;
+               uint64_t wodt_hi3:4;
+               uint64_t reserved_32_63:32;
+#endif
+       } cn38xx;
+       struct cvmx_lmcx_wodt_ctl0_cn38xx cn38xxp2;
+       struct cvmx_lmcx_wodt_ctl0_cn38xx cn50xx;
+       struct cvmx_lmcx_wodt_ctl0_cn30xx cn52xx;
+       struct cvmx_lmcx_wodt_ctl0_cn30xx cn52xxp1;
+       struct cvmx_lmcx_wodt_ctl0_cn30xx cn56xx;
+       struct cvmx_lmcx_wodt_ctl0_cn30xx cn56xxp1;
+       struct cvmx_lmcx_wodt_ctl0_cn38xx cn58xx;
+       struct cvmx_lmcx_wodt_ctl0_cn38xx cn58xxp1;
+};
+
+union cvmx_lmcx_wodt_ctl1 {
+       uint64_t u64;
+       struct cvmx_lmcx_wodt_ctl1_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_32_63:32;
+               uint64_t wodt_d3_r1:8;
+               uint64_t wodt_d3_r0:8;
+               uint64_t wodt_d2_r1:8;
+               uint64_t wodt_d2_r0:8;
+#else
+               uint64_t wodt_d2_r0:8;
+               uint64_t wodt_d2_r1:8;
+               uint64_t wodt_d3_r0:8;
+               uint64_t wodt_d3_r1:8;
+               uint64_t reserved_32_63:32;
+#endif
+       } s;
+       struct cvmx_lmcx_wodt_ctl1_s cn30xx;
+       struct cvmx_lmcx_wodt_ctl1_s cn31xx;
+       struct cvmx_lmcx_wodt_ctl1_s cn52xx;
+       struct cvmx_lmcx_wodt_ctl1_s cn52xxp1;
+       struct cvmx_lmcx_wodt_ctl1_s cn56xx;
+       struct cvmx_lmcx_wodt_ctl1_s cn56xxp1;
+};
+
+union cvmx_lmcx_wodt_mask {
+       uint64_t u64;
+       struct cvmx_lmcx_wodt_mask_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t wodt_d3_r1:8;
+               uint64_t wodt_d3_r0:8;
+               uint64_t wodt_d2_r1:8;
+               uint64_t wodt_d2_r0:8;
+               uint64_t wodt_d1_r1:8;
+               uint64_t wodt_d1_r0:8;
+               uint64_t wodt_d0_r1:8;
+               uint64_t wodt_d0_r0:8;
+#else
+               uint64_t wodt_d0_r0:8;
+               uint64_t wodt_d0_r1:8;
+               uint64_t wodt_d1_r0:8;
+               uint64_t wodt_d1_r1:8;
+               uint64_t wodt_d2_r0:8;
+               uint64_t wodt_d2_r1:8;
+               uint64_t wodt_d3_r0:8;
+               uint64_t wodt_d3_r1:8;
+#endif
+       } s;
+       struct cvmx_lmcx_wodt_mask_s cn61xx;
+       struct cvmx_lmcx_wodt_mask_s cn63xx;
+       struct cvmx_lmcx_wodt_mask_s cn63xxp1;
+       struct cvmx_lmcx_wodt_mask_s cn66xx;
+       struct cvmx_lmcx_wodt_mask_s cn68xx;
+       struct cvmx_lmcx_wodt_mask_s cn68xxp1;
+       struct cvmx_lmcx_wodt_mask_s cnf71xx;
+};
+
+#endif
index 14dd11f4492afc1959b56643c539c8e3ff089b3f..349bb2ba840cc0260453262c9b080183ee7978f4 100644 (file)
 #define OCTEON_CN5XXX           (OCTEON_CN58XX_PASS1_0 | OM_MATCH_5XXX_FAMILY_MODELS)
 #define OCTEON_CN6XXX           (OCTEON_CN63XX_PASS1_0 | OM_MATCH_6XXX_FAMILY_MODELS)
 
+/* These are used to cover entire families of OCTEON processors */
+#define OCTEON_FAM_1           (OCTEON_CN3XXX)
+#define OCTEON_FAM_PLUS                (OCTEON_CN5XXX)
+#define OCTEON_FAM_1_PLUS      (OCTEON_FAM_PLUS | OM_MATCH_PREVIOUS_MODELS)
+#define OCTEON_FAM_2           (OCTEON_CN6XXX)
+
 /* The revision byte (low byte) has two different encodings.
  * CN3XXX:
  *
index 790939dd8244c6eb9169ba96d1befc0b768ca20d..254e9954ed71ff3a973e44c46425263c0e05eb57 100644 (file)
@@ -209,13 +209,6 @@ union octeon_cvmemctl {
        } s;
 };
 
-struct octeon_cf_data {
-       unsigned long   base_region_bias;
-       unsigned int    base_region;    /* The chip select region used by CF */
-       int             is16bit;        /* 0 - 8bit, !0 - 16bit */
-       int             dma_engine;     /* -1 for no DMA */
-};
-
 extern void octeon_write_lcd(const char *s);
 extern void octeon_check_cpu_bist(void);
 extern int octeon_get_boot_debug_flag(void);
index da9bd7d270d18a761f74f6168653d2eb16da7118..31ab10f02bad555724dffa1e58556bd6508cd79b 100644 (file)
 #define PAGE_SHIFT     16
 #endif
 #define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
+#define PAGE_MASK       (~(PAGE_SIZE - 1))
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 #define HPAGE_SHIFT    (PAGE_SHIFT + PAGE_SHIFT - 3)
 #define HPAGE_SIZE     (_AC(1,UL) << HPAGE_SHIFT)
 #define HPAGE_MASK     (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
-#else /* !CONFIG_HUGETLB_PAGE */
+#else /* !CONFIG_MIPS_HUGE_TLB_SUPPORT */
 #define HPAGE_SHIFT    ({BUILD_BUG(); 0; })
 #define HPAGE_SIZE     ({BUILD_BUG(); 0; })
 #define HPAGE_MASK     ({BUILD_BUG(); 0; })
 #define HUGETLB_PAGE_ORDER     ({BUILD_BUG(); 0; })
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #ifndef __ASSEMBLY__
 
index f5b521d5a67d744e3f250c5a99e5023c77deaee0..c63191055e695c5a49812f3f32ed0c913d941a0a 100644 (file)
@@ -175,7 +175,7 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline int pmd_bad(pmd_t pmd)
 {
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /* pmd_huge(pmd) but inline */
        if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
                return 0;
index da4ba49adcf652fb9522c8c0b171f14aa4ab5247..f6a0439a40858a5b29190825f0ddc820cc8755d7 100644 (file)
  */
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 
-#define _PAGE_PRESENT               (1<<6)  /* implemented in software */
-#define _PAGE_READ                  (1<<7)  /* implemented in software */
-#define _PAGE_WRITE                 (1<<8)  /* implemented in software */
-#define _PAGE_ACCESSED              (1<<9)  /* implemented in software */
-#define _PAGE_MODIFIED              (1<<10) /* implemented in software */
-#define _PAGE_FILE                  (1<<10) /* set:pagecache unset:swap */
-
-#define _PAGE_R4KBUG                (1<<0)  /* workaround for r4k bug  */
-#define _PAGE_GLOBAL                (1<<0)
-#define _PAGE_VALID                 (1<<1)
-#define _PAGE_SILENT_READ           (1<<1)  /* synonym                 */
-#define _PAGE_DIRTY                 (1<<2)  /* The MIPS dirty bit      */
-#define _PAGE_SILENT_WRITE          (1<<2)
-#define _CACHE_SHIFT                3
-#define _CACHE_MASK                 (7<<3)
+/*
+ * The following bits are directly used by the TLB hardware
+ */
+#define _PAGE_R4KBUG           (1 << 0)  /* workaround for r4k bug  */
+#define _PAGE_GLOBAL           (1 << 0)
+#define _PAGE_VALID_SHIFT      1
+#define _PAGE_VALID            (1 << _PAGE_VALID_SHIFT)
+#define _PAGE_SILENT_READ      (1 << 1)  /* synonym                 */
+#define _PAGE_DIRTY_SHIFT      2
+#define _PAGE_DIRTY            (1 << _PAGE_DIRTY_SHIFT)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE     (1 << 2)
+#define _CACHE_SHIFT           3
+#define _CACHE_MASK            (7 << 3)
+
+/*
+ * The following bits are implemented in software
+ *
+ * _PAGE_FILE semantics: set:pagecache unset:swap
+ */ 
+#define _PAGE_PRESENT_SHIFT    6
+#define _PAGE_PRESENT          (1 << _PAGE_PRESENT_SHIFT)
+#define _PAGE_READ_SHIFT       7
+#define _PAGE_READ             (1 << _PAGE_READ_SHIFT)
+#define _PAGE_WRITE_SHIFT      8
+#define _PAGE_WRITE            (1 << _PAGE_WRITE_SHIFT)
+#define _PAGE_ACCESSED_SHIFT   9
+#define _PAGE_ACCESSED         (1 << _PAGE_ACCESSED_SHIFT)
+#define _PAGE_MODIFIED_SHIFT   10
+#define _PAGE_MODIFIED         (1 << _PAGE_MODIFIED_SHIFT)
+
+#define _PAGE_FILE             (1 << 10)
 
 #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
-#define _PAGE_PRESENT               (1<<0)  /* implemented in software */
-#define _PAGE_READ                  (1<<1)  /* implemented in software */
-#define _PAGE_WRITE                 (1<<2)  /* implemented in software */
-#define _PAGE_ACCESSED              (1<<3)  /* implemented in software */
-#define _PAGE_MODIFIED              (1<<4)  /* implemented in software */
-#define _PAGE_FILE                  (1<<4)  /* set:pagecache unset:swap */
-
-#define _PAGE_GLOBAL                (1<<8)
-#define _PAGE_VALID                 (1<<9)
-#define _PAGE_SILENT_READ           (1<<9)  /* synonym                 */
-#define _PAGE_DIRTY                 (1<<10) /* The MIPS dirty bit      */
-#define _PAGE_SILENT_WRITE          (1<<10)
-#define _CACHE_UNCACHED             (1<<11)
-#define _CACHE_MASK                 (1<<11)
+/*
+ * The following are implemented by software
+ *
+ * _PAGE_FILE semantics: set:pagecache unset:swap
+ */
+#define _PAGE_PRESENT_SHIFT    0
+#define _PAGE_PRESENT          (1 <<  _PAGE_PRESENT_SHIFT)
+#define _PAGE_READ_SHIFT       1
+#define _PAGE_READ             (1 <<  _PAGE_READ_SHIFT)
+#define _PAGE_WRITE_SHIFT      2
+#define _PAGE_WRITE            (1 <<  _PAGE_WRITE_SHIFT)
+#define _PAGE_ACCESSED_SHIFT   3
+#define _PAGE_ACCESSED         (1 <<  _PAGE_ACCESSED_SHIFT)
+#define _PAGE_MODIFIED_SHIFT   4
+#define _PAGE_MODIFIED         (1 <<  _PAGE_MODIFIED_SHIFT)
+#define _PAGE_FILE_SHIFT       4
+#define _PAGE_FILE             (1 <<  _PAGE_FILE_SHIFT)
+
+/*
+ * And these are the hardware TLB bits
+ */
+#define _PAGE_GLOBAL_SHIFT     8
+#define _PAGE_GLOBAL           (1 <<  _PAGE_GLOBAL_SHIFT)
+#define _PAGE_VALID_SHIFT      9
+#define _PAGE_VALID            (1 <<  _PAGE_VALID_SHIFT)
+#define _PAGE_SILENT_READ      (1 <<  _PAGE_VALID_SHIFT)       /* synonym  */
+#define _PAGE_DIRTY_SHIFT      10
+#define _PAGE_DIRTY            (1 << _PAGE_DIRTY_SHIFT)
+#define _PAGE_SILENT_WRITE     (1 << _PAGE_DIRTY_SHIFT)
+#define _CACHE_UNCACHED_SHIFT  11
+#define _CACHE_UNCACHED                (1 << _CACHE_UNCACHED_SHIFT)
+#define _CACHE_MASK            (1 << _CACHE_UNCACHED_SHIFT)
 
 #else /* 'Normal' r4K case */
 /*
  * which is more than we need right now.
  */
 
-/* implemented in software */
+/*
+ * The following bits are implemented in software
+ *
+ * _PAGE_READ / _PAGE_READ_SHIFT should be unused if cpu_has_rixi.
+ * _PAGE_FILE semantics: set:pagecache unset:swap
+ */
 #define _PAGE_PRESENT_SHIFT    (0)
 #define _PAGE_PRESENT          (1 << _PAGE_PRESENT_SHIFT)
-/* implemented in software, should be unused if cpu_has_rixi. */
 #define _PAGE_READ_SHIFT       (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1)
 #define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; })
-/* implemented in software */
 #define _PAGE_WRITE_SHIFT      (_PAGE_READ_SHIFT + 1)
 #define _PAGE_WRITE            (1 << _PAGE_WRITE_SHIFT)
-/* implemented in software */
 #define _PAGE_ACCESSED_SHIFT   (_PAGE_WRITE_SHIFT + 1)
 #define _PAGE_ACCESSED         (1 << _PAGE_ACCESSED_SHIFT)
-/* implemented in software */
 #define _PAGE_MODIFIED_SHIFT   (_PAGE_ACCESSED_SHIFT + 1)
 #define _PAGE_MODIFIED         (1 << _PAGE_MODIFIED_SHIFT)
-/* set:pagecache unset:swap */
 #define _PAGE_FILE             (_PAGE_MODIFIED)
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 /* huge tlb page */
 #define _PAGE_HUGE_SHIFT       (_PAGE_MODIFIED_SHIFT + 1)
 #define _PAGE_HUGE             (1 << _PAGE_HUGE_SHIFT)
 #define _PAGE_HUGE             ({BUG(); 1; })  /* Dummy value */
 #endif
 
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+/* huge tlb page */
+#define _PAGE_SPLITTING_SHIFT  (_PAGE_HUGE_SHIFT + 1)
+#define _PAGE_SPLITTING                (1 << _PAGE_SPLITTING_SHIFT)
+#else
+#define _PAGE_SPLITTING_SHIFT  (_PAGE_HUGE_SHIFT)
+#define _PAGE_SPLITTING                ({BUG(); 1; })  /* Dummy value */
+#endif
+
 /* Page cannot be executed */
-#define _PAGE_NO_EXEC_SHIFT    (cpu_has_rixi ? _PAGE_HUGE_SHIFT + 1 : _PAGE_HUGE_SHIFT)
+#define _PAGE_NO_EXEC_SHIFT    (cpu_has_rixi ? _PAGE_SPLITTING_SHIFT + 1 : _PAGE_SPLITTING_SHIFT)
 #define _PAGE_NO_EXEC          ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; })
 
 /* Page cannot be read */
@@ -192,20 +235,6 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 #define _CACHE_CACHABLE_NONCOHERENT (5<<_CACHE_SHIFT)
 #define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)
 
-#elif defined(CONFIG_CPU_RM9000)
-
-#define _CACHE_WT                  (0<<_CACHE_SHIFT)
-#define _CACHE_WTWA                (1<<_CACHE_SHIFT)
-#define _CACHE_UC_B                (2<<_CACHE_SHIFT)
-#define _CACHE_WB                  (3<<_CACHE_SHIFT)
-#define _CACHE_CWBEA               (4<<_CACHE_SHIFT)
-#define _CACHE_CWB                 (5<<_CACHE_SHIFT)
-#define _CACHE_UCNB                (6<<_CACHE_SHIFT)
-#define _CACHE_FPC                 (7<<_CACHE_SHIFT)
-
-#define _CACHE_UNCACHED                    _CACHE_UC_B
-#define _CACHE_CACHABLE_NONCOHERENT _CACHE_WB
-
 #else
 
 #define _CACHE_CACHABLE_NO_WA      (0<<_CACHE_SHIFT)  /* R4600 only      */
index c02158be836cc6793393eb4f3f3c094b3df1043f..ec50d52cfb747a961a161fc98ecfb26f45f6925c 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
+#include <linux/mmzone.h>
 #ifdef CONFIG_32BIT
 #include <asm/pgtable-32.h>
 #endif
@@ -76,16 +77,7 @@ extern unsigned long zero_page_mask;
 
 #define ZERO_PAGE(vaddr) \
        (virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))))
-
-#define is_zero_pfn is_zero_pfn
-static inline int is_zero_pfn(unsigned long pfn)
-{
-       extern unsigned long zero_pfn;
-       unsigned long offset_from_zero_pfn = pfn - zero_pfn;
-       return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
-}
-
-#define my_zero_pfn(addr)      page_to_pfn(ZERO_PAGE(addr))
+#define __HAVE_COLOR_ZERO_PAGE
 
 extern void paging_init(void);
 
@@ -94,7 +86,12 @@ extern void paging_init(void);
  * and a page entry and page directory to the page they refer to.
  */
 #define pmd_phys(pmd)          virt_to_phys((void *)pmd_val(pmd))
-#define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+
+#define __pmd_page(pmd)                (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define pmd_page(pmd)          __pmd_page(pmd)
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
+
 #define pmd_page_vaddr(pmd)    pmd_val(pmd)
 
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
@@ -107,7 +104,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
        ptep->pte_high = pte.pte_high;
        smp_wmb();
        ptep->pte_low = pte.pte_low;
-       //printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
 
        if (pte.pte_low & _PAGE_GLOBAL) {
                pte_t *buddy = ptep_buddy(ptep);
@@ -375,6 +371,14 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
        __update_cache(vma, address, pte);
 }
 
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
+       unsigned long address, pmd_t *pmdp)
+{
+       pte_t pte = *(pte_t *)pmdp;
+
+       __update_tlb(vma, address, pte);
+}
+
 #define kern_addr_valid(addr)  (1)
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
@@ -394,6 +398,157 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
                remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+extern int has_transparent_hugepage(void);
+
+static inline int pmd_trans_huge(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_HUGE);
+}
+
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_HUGE;
+
+       return pmd;
+}
+
+static inline int pmd_trans_splitting(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_SPLITTING);
+}
+
+static inline pmd_t pmd_mksplitting(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_SPLITTING;
+
+       return pmd;
+}
+
+extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+                      pmd_t *pmdp, pmd_t pmd);
+
+#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
+/* Extern to avoid header file madness */
+extern void pmdp_splitting_flush(struct vm_area_struct *vma,
+                                       unsigned long address,
+                                       pmd_t *pmdp);
+
+#define __HAVE_ARCH_PMD_WRITE
+static inline int pmd_write(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_WRITE);
+}
+
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+       return pmd;
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_WRITE;
+       if (pmd_val(pmd) & _PAGE_MODIFIED)
+               pmd_val(pmd) |= _PAGE_SILENT_WRITE;
+
+       return pmd;
+}
+
+static inline int pmd_dirty(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_MODIFIED);
+}
+
+static inline pmd_t pmd_mkclean(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
+       return pmd;
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_MODIFIED;
+       if (pmd_val(pmd) & _PAGE_WRITE)
+               pmd_val(pmd) |= _PAGE_SILENT_WRITE;
+
+       return pmd;
+}
+
+static inline int pmd_young(pmd_t pmd)
+{
+       return !!(pmd_val(pmd) & _PAGE_ACCESSED);
+}
+
+static inline pmd_t pmd_mkold(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+
+       return pmd;
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+       pmd_val(pmd) |= _PAGE_ACCESSED;
+
+       if (cpu_has_rixi) {
+               if (!(pmd_val(pmd) & _PAGE_NO_READ))
+                       pmd_val(pmd) |= _PAGE_SILENT_READ;
+       } else {
+               if (pmd_val(pmd) & _PAGE_READ)
+                       pmd_val(pmd) |= _PAGE_SILENT_READ;
+       }
+
+       return pmd;
+}
+
+/* Extern to avoid header file madness */
+extern pmd_t mk_pmd(struct page *page, pgprot_t prot);
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+       return pmd_val(pmd) >> _PFN_SHIFT;
+}
+
+static inline struct page *pmd_page(pmd_t pmd)
+{
+       if (pmd_trans_huge(pmd))
+               return pfn_to_page(pmd_pfn(pmd));
+
+       return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT);
+}
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+       pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+       return pmd;
+}
+
+static inline pmd_t pmd_mknotpresent(pmd_t pmd)
+{
+       pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY);
+
+       return pmd;
+}
+
+/*
+ * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a
+ * different prototype.
+ */
+#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
+static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
+                                      unsigned long address, pmd_t *pmdp)
+{
+       pmd_t old = *pmdp;
+
+       pmd_clear(pmdp);
+
+       return old;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
 #include <asm-generic/pgtable.h>
 
 /*
index 9e2ee429c52945809ad8bac3ec47f8560508aeb8..c74eb1657f5f51c52f4549cbcfc09cbcc9668c99 100644 (file)
@@ -17,7 +17,6 @@
 #define MIPS4K_ICACHE_REFILL_WAR       0
 #define MIPS_CACHE_SYNC_WAR            0
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            0
 #define ICACHE_REFILLS_WORKAROUND_WAR  0
 #define R10000_LLSC_WAR                        0
 #if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
index d28c41e0887c584a8c869eb266138d3545bad157..bd98b503f04c68fe070366aaa9d1a9d4606c9796 100644 (file)
@@ -226,8 +226,6 @@ struct thread_struct {
        unsigned long cp0_badvaddr;     /* Last user fault */
        unsigned long cp0_baduaddr;     /* Last kernel fault accessing USEG */
        unsigned long error_code;
-       unsigned long irix_trampoline;  /* Wheee... */
-       unsigned long irix_oldctx;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
     struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
     struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
@@ -297,8 +295,6 @@ struct thread_struct {
        .cp0_badvaddr           = 0,                            \
        .cp0_baduaddr           = 0,                            \
        .error_code             = 0,                            \
-       .irix_trampoline        = 0,                            \
-       .irix_oldctx            = 0,                            \
        /*                                                      \
         * Cavium Octeon specifics (null if not Octeon)         \
         */                                                     \
index 149342951436af4d26f650be4acc2df775c63aff..3dce7c788b3e579679c045a937b2f4128cd5f59f 100644 (file)
@@ -366,7 +366,7 @@ struct linux_smonblock {
  * Macros for calling a 32-bit ARC implementation from 64-bit code
  */
 
-#if defined(CONFIG_64BIT) && defined(CONFIG_ARC32)
+#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
 
 #define __arc_clobbers                                                 \
        "$2", "$3" /* ... */, "$8", "$9", "$10", "$11",                         \
@@ -475,10 +475,10 @@ struct linux_smonblock {
        __res;                                                          \
 })
 
-#endif /* defined(CONFIG_64BIT) && defined(CONFIG_ARC32) */
+#endif /* defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32) */
 
-#if (defined(CONFIG_32BIT) && defined(CONFIG_ARC32)) ||                \
-    (defined(CONFIG_64BIT) && defined(CONFIG_ARC64))
+#if (defined(CONFIG_32BIT) && defined(CONFIG_FW_ARC32)) ||             \
+    (defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC64))
 
 #define ARC_CALL0(dest)                                                        \
 ({     long __res;                                                     \
index d4fb4d852a6db5e1778bbc6542807ca2c0919e56..f33b5fd6972b441d3b3a7f342a126b488dfbc12d 100644 (file)
@@ -40,6 +40,8 @@ extern int __cpu_logical_map[NR_CPUS];
 #define SMP_CALL_FUNCTION      0x2
 /* Octeon - Tell another core to flush its icache */
 #define SMP_ICACHE_FLUSH       0x4
+/* Used by kexec crashdump to save all cpu's state */
+#define SMP_DUMP               0x8
 
 extern volatile cpumask_t cpu_callin_map;
 
@@ -91,4 +93,8 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
        mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
 }
 
+#if defined(CONFIG_KEXEC)
+extern void (*dump_ipi_function_ptr)(void *);
+void dump_send_ipi(void (*dump_ipi_callback)(void *));
+#endif
 #endif /* __ASM_SMP_H */
diff --git a/arch/mips/include/asm/smvp.h b/arch/mips/include/asm/smvp.h
deleted file mode 100644 (file)
index 0d0e80a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_SMVP_H
-#define _ASM_SMVP_H
-
-/*
- * Definitions for SMVP multitasking on MIPS MT cores
- */
-struct task_struct;
-
-extern void smvp_smp_setup(void);
-extern void smvp_smp_finish(void);
-extern void smvp_boot_secondary(int cpu, struct task_struct *t);
-extern void smvp_init_secondary(void);
-extern void smvp_smp_finish(void);
-extern void smvp_cpus_done(void);
-extern void smvp_prepare_cpus(unsigned int max_cpus);
-
-/* This is platform specific */
-extern void smvp_send_ipi(int cpu, unsigned int action);
-#endif /*  _ASM_SMVP_H */
index 4461198361c9760fa5afed8a101af0fa89207bc0..65900dab3ad382825143d66d7f206f93d561e34d 100644 (file)
@@ -6,7 +6,7 @@
  * SECTION_SIZE_BITS           2^N: how big each section will be
  * MAX_PHYSMEM_BITS            2^N: how much memory we can have in that space
  */
-#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PAGE_SIZE_64KB)
+#if defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) && defined(CONFIG_PAGE_SIZE_64KB)
 # define SECTION_SIZE_BITS     29
 #else
 # define SECTION_SIZE_BITS     28
index bc14447e69b5999c01db66f9506e3c0e9d7ac8f1..761f2e92119ea5945027ad173476982df2d89329 100644 (file)
@@ -50,10 +50,8 @@ extern int (*perf_irq)(void);
 /*
  * Initialize the calling CPU's compare interrupt as clockevent device
  */
-#ifdef CONFIG_CEVT_R4K_LIB
 extern unsigned int __weak get_c0_compare_int(void);
 extern int r4k_clockevent_init(void);
-#endif
 
 static inline int mips_clockevent_init(void)
 {
@@ -71,7 +69,7 @@ static inline int mips_clockevent_init(void)
 /*
  * Initialize the count register as a clocksource
  */
-#ifdef CONFIG_CSRC_R4K_LIB
+#ifdef CONFIG_CSRC_R4K
 extern int init_r4k_clocksource(void);
 #endif
 
diff --git a/arch/mips/include/asm/titan_dep.h b/arch/mips/include/asm/titan_dep.h
deleted file mode 100644 (file)
index fee1908..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2003 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Board specific definititions for the PMC-Sierra Yosemite
- *
- * 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 __TITAN_DEP_H__
-#define __TITAN_DEP_H__
-
-#include <asm/addrspace.h>              /* for KSEG1ADDR() */
-#include <asm/byteorder.h>              /* for cpu_to_le32() */
-
-#define TITAN_READ(ofs)                                                        \
-       (*(volatile u32 *)(ocd_base+(ofs)))
-#define TITAN_READ_16(ofs)                                             \
-       (*(volatile u16 *)(ocd_base+(ofs)))
-#define TITAN_READ_8(ofs)                                              \
-       (*(volatile u8 *)(ocd_base+(ofs)))
-
-#define TITAN_WRITE(ofs, data)                                         \
-       do { *(volatile u32 *)(ocd_base+(ofs)) = (data); } while (0)
-#define TITAN_WRITE_16(ofs, data)                                      \
-       do { *(volatile u16 *)(ocd_base+(ofs)) = (data); } while (0)
-#define TITAN_WRITE_8(ofs, data)                                       \
-       do { *(volatile u8 *)(ocd_base+(ofs)) = (data); } while (0)
-
-/*
- * PCI specific defines
- */
-#define        TITAN_PCI_0_CONFIG_ADDRESS      0x780
-#define        TITAN_PCI_0_CONFIG_DATA         0x784
-
-/*
- * HT specific defines
- */
-#define RM9000x2_HTLINK_REG            0xbb000644
-#define RM9000x2_BASE_ADDR             0xbb000000
-
-#define OCD_BASE                       0xfb000000UL
-#define OCD_SIZE                       0x3000UL
-
-extern unsigned long ocd_base;
-
-/*
- * OCD Registers
- */
-#define RM9000x2_OCD_LKB5              0x0128          /* Ethernet */
-#define RM9000x2_OCD_LKM5              0x012c
-
-#define RM9000x2_OCD_LKB7              0x0138          /* HT Region 0 */
-#define RM9000x2_OCD_LKM7              0x013c
-#define RM9000x2_OCD_LKB8              0x0140          /* HT Region 1 */
-#define RM9000x2_OCD_LKM8              0x0144
-
-#define RM9000x2_OCD_LKB9              0x0148          /* Local Bus */
-#define RM9000x2_OCD_LKM9              0x014c
-#define RM9000x2_OCD_LKB10             0x0150
-#define RM9000x2_OCD_LKM10             0x0154
-#define RM9000x2_OCD_LKB11             0x0158
-#define RM9000x2_OCD_LKM11             0x015c
-#define RM9000x2_OCD_LKB12             0x0160
-#define RM9000x2_OCD_LKM12             0x0164
-
-#define RM9000x2_OCD_LKB13             0x0168          /* Scratch RAM */
-#define RM9000x2_OCD_LKM13             0x016c
-
-#define RM9000x2_OCD_LPD0              0x0200          /* Local Bus */
-#define RM9000x2_OCD_LPD1              0x0210
-#define RM9000x2_OCD_LPD2              0x0220
-#define RM9000x2_OCD_LPD3              0x0230
-
-#define RM9000x2_OCD_HTDVID            0x0600  /* HT Device Header */
-#define RM9000x2_OCD_HTSC              0x0604
-#define RM9000x2_OCD_HTCCR             0x0608
-#define RM9000x2_OCD_HTBHL             0x060c
-#define RM9000x2_OCD_HTBAR0            0x0610
-#define RM9000x2_OCD_HTBAR1            0x0614
-#define RM9000x2_OCD_HTBAR2            0x0618
-#define RM9000x2_OCD_HTBAR3            0x061c
-#define RM9000x2_OCD_HTBAR4            0x0620
-#define RM9000x2_OCD_HTBAR5            0x0624
-#define RM9000x2_OCD_HTCBCPT           0x0628
-#define RM9000x2_OCD_HTSDVID           0x062c
-#define RM9000x2_OCD_HTXRA             0x0630
-#define RM9000x2_OCD_HTCAP1            0x0634
-#define RM9000x2_OCD_HTIL              0x063c
-
-#define RM9000x2_OCD_HTLCC             0x0640  /* HT Capability Block */
-#define RM9000x2_OCD_HTLINK            0x0644
-#define RM9000x2_OCD_HTFQREV           0x0648
-
-#define RM9000x2_OCD_HTERCTL           0x0668  /* HT Controller */
-#define RM9000x2_OCD_HTRXDB            0x066c
-#define RM9000x2_OCD_HTIMPED           0x0670
-#define RM9000x2_OCD_HTSWIMP           0x0674
-#define RM9000x2_OCD_HTCAL             0x0678
-
-#define RM9000x2_OCD_HTBAA30           0x0680
-#define RM9000x2_OCD_HTBAA54           0x0684
-#define RM9000x2_OCD_HTMASK0           0x0688
-#define RM9000x2_OCD_HTMASK1           0x068c
-#define RM9000x2_OCD_HTMASK2           0x0690
-#define RM9000x2_OCD_HTMASK3           0x0694
-#define RM9000x2_OCD_HTMASK4           0x0698
-#define RM9000x2_OCD_HTMASK5           0x069c
-
-#define RM9000x2_OCD_HTIFCTL           0x06a0
-#define RM9000x2_OCD_HTPLL             0x06a4
-
-#define RM9000x2_OCD_HTSRI             0x06b0
-#define RM9000x2_OCD_HTRXNUM           0x06b4
-#define RM9000x2_OCD_HTTXNUM           0x06b8
-
-#define RM9000x2_OCD_HTTXCNT           0x06c8
-
-#define RM9000x2_OCD_HTERROR           0x06d8
-#define RM9000x2_OCD_HTRCRCE           0x06dc
-#define RM9000x2_OCD_HTEOI             0x06e0
-
-#define RM9000x2_OCD_CRCR              0x06f0
-
-#define RM9000x2_OCD_HTCFGA            0x06f8
-#define RM9000x2_OCD_HTCFGD            0x06fc
-
-#define RM9000x2_OCD_INTMSG            0x0a00
-
-#define RM9000x2_OCD_INTPIN0           0x0a40
-#define RM9000x2_OCD_INTPIN1           0x0a44
-#define RM9000x2_OCD_INTPIN2           0x0a48
-#define RM9000x2_OCD_INTPIN3           0x0a4c
-#define RM9000x2_OCD_INTPIN4           0x0a50
-#define RM9000x2_OCD_INTPIN5           0x0a54
-#define RM9000x2_OCD_INTPIN6           0x0a58
-#define RM9000x2_OCD_INTPIN7           0x0a5c
-#define RM9000x2_OCD_SEM               0x0a60
-#define RM9000x2_OCD_SEMSET            0x0a64
-#define RM9000x2_OCD_SEMCLR            0x0a68
-
-#define RM9000x2_OCD_TKT               0x0a70
-#define RM9000x2_OCD_TKTINC            0x0a74
-
-#define RM9000x2_OCD_NMICONFIG         0x0ac0          /* Interrupts */
-#define RM9000x2_OCD_INTP0PRI          0x1a80
-#define RM9000x2_OCD_INTP1PRI          0x1a80
-#define RM9000x2_OCD_INTP0STATUS0      0x1b00
-#define RM9000x2_OCD_INTP0MASK0                0x1b04
-#define RM9000x2_OCD_INTP0SET0         0x1b08
-#define RM9000x2_OCD_INTP0CLEAR0       0x1b0c
-#define RM9000x2_OCD_INTP0STATUS1      0x1b10
-#define RM9000x2_OCD_INTP0MASK1                0x1b14
-#define RM9000x2_OCD_INTP0SET1         0x1b18
-#define RM9000x2_OCD_INTP0CLEAR1       0x1b1c
-#define RM9000x2_OCD_INTP0STATUS2      0x1b20
-#define RM9000x2_OCD_INTP0MASK2                0x1b24
-#define RM9000x2_OCD_INTP0SET2         0x1b28
-#define RM9000x2_OCD_INTP0CLEAR2       0x1b2c
-#define RM9000x2_OCD_INTP0STATUS3      0x1b30
-#define RM9000x2_OCD_INTP0MASK3                0x1b34
-#define RM9000x2_OCD_INTP0SET3         0x1b38
-#define RM9000x2_OCD_INTP0CLEAR3       0x1b3c
-#define RM9000x2_OCD_INTP0STATUS4      0x1b40
-#define RM9000x2_OCD_INTP0MASK4                0x1b44
-#define RM9000x2_OCD_INTP0SET4         0x1b48
-#define RM9000x2_OCD_INTP0CLEAR4       0x1b4c
-#define RM9000x2_OCD_INTP0STATUS5      0x1b50
-#define RM9000x2_OCD_INTP0MASK5                0x1b54
-#define RM9000x2_OCD_INTP0SET5         0x1b58
-#define RM9000x2_OCD_INTP0CLEAR5       0x1b5c
-#define RM9000x2_OCD_INTP0STATUS6      0x1b60
-#define RM9000x2_OCD_INTP0MASK6                0x1b64
-#define RM9000x2_OCD_INTP0SET6         0x1b68
-#define RM9000x2_OCD_INTP0CLEAR6       0x1b6c
-#define RM9000x2_OCD_INTP0STATUS7      0x1b70
-#define RM9000x2_OCD_INTP0MASK7                0x1b74
-#define RM9000x2_OCD_INTP0SET7         0x1b78
-#define RM9000x2_OCD_INTP0CLEAR7       0x1b7c
-#define RM9000x2_OCD_INTP1STATUS0      0x2b00
-#define RM9000x2_OCD_INTP1MASK0                0x2b04
-#define RM9000x2_OCD_INTP1SET0         0x2b08
-#define RM9000x2_OCD_INTP1CLEAR0       0x2b0c
-#define RM9000x2_OCD_INTP1STATUS1      0x2b10
-#define RM9000x2_OCD_INTP1MASK1                0x2b14
-#define RM9000x2_OCD_INTP1SET1         0x2b18
-#define RM9000x2_OCD_INTP1CLEAR1       0x2b1c
-#define RM9000x2_OCD_INTP1STATUS2      0x2b20
-#define RM9000x2_OCD_INTP1MASK2                0x2b24
-#define RM9000x2_OCD_INTP1SET2         0x2b28
-#define RM9000x2_OCD_INTP1CLEAR2       0x2b2c
-#define RM9000x2_OCD_INTP1STATUS3      0x2b30
-#define RM9000x2_OCD_INTP1MASK3                0x2b34
-#define RM9000x2_OCD_INTP1SET3         0x2b38
-#define RM9000x2_OCD_INTP1CLEAR3       0x2b3c
-#define RM9000x2_OCD_INTP1STATUS4      0x2b40
-#define RM9000x2_OCD_INTP1MASK4                0x2b44
-#define RM9000x2_OCD_INTP1SET4         0x2b48
-#define RM9000x2_OCD_INTP1CLEAR4       0x2b4c
-#define RM9000x2_OCD_INTP1STATUS5      0x2b50
-#define RM9000x2_OCD_INTP1MASK5                0x2b54
-#define RM9000x2_OCD_INTP1SET5         0x2b58
-#define RM9000x2_OCD_INTP1CLEAR5       0x2b5c
-#define RM9000x2_OCD_INTP1STATUS6      0x2b60
-#define RM9000x2_OCD_INTP1MASK6                0x2b64
-#define RM9000x2_OCD_INTP1SET6         0x2b68
-#define RM9000x2_OCD_INTP1CLEAR6       0x2b6c
-#define RM9000x2_OCD_INTP1STATUS7      0x2b70
-#define RM9000x2_OCD_INTP1MASK7                0x2b74
-#define RM9000x2_OCD_INTP1SET7         0x2b78
-#define RM9000x2_OCD_INTP1CLEAR7       0x2b7c
-
-#define OCD_READ(reg)          (*(volatile unsigned int *)(ocd_base + (reg)))
-#define OCD_WRITE(reg, val)                                    \
-       do { *(volatile unsigned int *)(ocd_base + (reg)) = (val); } while (0)
-
-/*
- * Hypertransport specific macros
- */
-#define RM9K_WRITE(ofs, data)   *(volatile u_int32_t *)(RM9000x2_BASE_ADDR+ofs) = data
-#define RM9K_WRITE_8(ofs, data) *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs) = data
-#define RM9K_WRITE_16(ofs, data) *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs) = data
-
-#define RM9K_READ(ofs, val)     *(val) = *(volatile u_int32_t *)(RM9000x2_BASE_ADDR+ofs)
-#define RM9K_READ_8(ofs, val)   *(val) = *(volatile u8 *)(RM9000x2_BASE_ADDR+ofs)
-#define RM9K_READ_16(ofs, val)  *(val) = *(volatile u16 *)(RM9000x2_BASE_ADDR+ofs)
-
-#endif
index fa133c1bc1f962796d88ab99ff695a13a3956303..65e344532dedc1a355176202ae016a44f615874e 100644 (file)
 #error Check setting of TX49XX_ICACHE_INDEX_INV_WAR for your platform
 #endif
 
-/*
- * On the RM9000 there is a problem which makes the CreateDirtyExclusive
- * eache operation unusable on SMP systems.
- */
-#ifndef RM9000_CDEX_SMP_WAR
-#error Check setting of RM9000_CDEX_SMP_WAR for your platform
-#endif
-
 /*
  * The RM7000 processors and the E9000 cores have a bug (though PMC-Sierra
  * opposes it being called that) where invalid instructions in the same
index 8b28bc4e14ea81f409a03c0b33197f20e0924b09..007c33d737154a20c04a8cc2fa109504d77dc151 100644 (file)
@@ -16,7 +16,7 @@ CFLAGS_REMOVE_perf_event_mipsxx.o = -pg
 endif
 
 obj-$(CONFIG_CEVT_BCM1480)     += cevt-bcm1480.o
-obj-$(CONFIG_CEVT_R4K_LIB)     += cevt-r4k.o
+obj-$(CONFIG_CEVT_R4K)         += cevt-r4k.o
 obj-$(CONFIG_MIPS_MT_SMTC)     += cevt-smtc.o
 obj-$(CONFIG_CEVT_DS1287)      += cevt-ds1287.o
 obj-$(CONFIG_CEVT_GT641XX)     += cevt-gt641xx.o
@@ -25,7 +25,7 @@ obj-$(CONFIG_CEVT_TXX9)               += cevt-txx9.o
 obj-$(CONFIG_CSRC_BCM1480)     += csrc-bcm1480.o
 obj-$(CONFIG_CSRC_IOASIC)      += csrc-ioasic.o
 obj-$(CONFIG_CSRC_POWERTV)     += csrc-powertv.o
-obj-$(CONFIG_CSRC_R4K_LIB)     += csrc-r4k.o
+obj-$(CONFIG_CSRC_R4K)         += csrc-r4k.o
 obj-$(CONFIG_CSRC_SB1250)      += csrc-sb1250.o
 obj-$(CONFIG_SYNC_R4K)         += sync-r4k.o
 
@@ -58,7 +58,6 @@ obj-$(CONFIG_MIPS_VPE_APSP_API)       += rtlx.o
 obj-$(CONFIG_I8259)            += i8259.o
 obj-$(CONFIG_IRQ_CPU)          += irq_cpu.o
 obj-$(CONFIG_IRQ_CPU_RM7K)     += irq-rm7000.o
-obj-$(CONFIG_IRQ_CPU_RM9K)     += irq-rm9000.o
 obj-$(CONFIG_MIPS_MSC)         += irq-msc01.o
 obj-$(CONFIG_IRQ_TXX9)         += irq_txx9.o
 obj-$(CONFIG_IRQ_GT641XX)      += irq-gt641xx.o
@@ -80,7 +79,8 @@ obj-$(CONFIG_I8253)           += i8253.o
 
 obj-$(CONFIG_GPIO_TXX9)                += gpio_txx9.o
 
-obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_SPINLOCK_TEST)    += spinlock_test.o
 obj-$(CONFIG_MIPS_MACHINE)     += mips_machine.o
index 0c4bce4882a6621d18ff0450b3f464e3722059b6..9690998d4ef3e9e99b5628cbb4bf297c90158a10 100644 (file)
@@ -125,10 +125,6 @@ void output_thread_defines(void)
               thread.cp0_baduaddr);
        OFFSET(THREAD_ECODE, task_struct, \
               thread.error_code);
-       OFFSET(THREAD_TRAMP, task_struct, \
-              thread.irix_trampoline);
-       OFFSET(THREAD_OLDCTX, task_struct, \
-              thread.irix_oldctx);
        BLANK();
 }
 
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
new file mode 100644 (file)
index 0000000..0f53c39
--- /dev/null
@@ -0,0 +1,71 @@
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu = -1;
+static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+
+#ifdef CONFIG_SMP
+static void crash_shutdown_secondary(void *ignore)
+{
+       struct pt_regs *regs;
+       int cpu = smp_processor_id();
+
+       regs = task_pt_regs(current);
+
+       if (!cpu_online(cpu))
+               return;
+
+       local_irq_disable();
+       if (!cpu_isset(cpu, cpus_in_crash))
+               crash_save_cpu(regs, cpu);
+       cpu_set(cpu, cpus_in_crash);
+
+       while (!atomic_read(&kexec_ready_to_reboot))
+               cpu_relax();
+       relocated_kexec_smp_wait(NULL);
+       /* NOTREACHED */
+}
+
+static void crash_kexec_prepare_cpus(void)
+{
+       unsigned int msecs;
+
+       unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
+
+       dump_send_ipi(crash_shutdown_secondary);
+       smp_wmb();
+
+       /*
+        * The crash CPU sends an IPI and wait for other CPUs to
+        * respond. Delay of at least 10 seconds.
+        */
+       pr_emerg("Sending IPI to other cpus...\n");
+       msecs = 10000;
+       while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+               cpu_relax();
+               mdelay(1);
+       }
+}
+
+#else /* !defined(CONFIG_SMP)  */
+static void crash_kexec_prepare_cpus(void) {}
+#endif /* !defined(CONFIG_SMP)  */
+
+void default_machine_crash_shutdown(struct pt_regs *regs)
+{
+       local_irq_disable();
+       crashing_cpu = smp_processor_id();
+       crash_save_cpu(regs, crashing_cpu);
+       crash_kexec_prepare_cpus();
+       cpu_set(crashing_cpu, cpus_in_crash);
+}
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c
new file mode 100644 (file)
index 0000000..35bed0d
--- /dev/null
@@ -0,0 +1,75 @@
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <asm/uaccess.h>
+
+static int __init parse_savemaxmem(char *p)
+{
+       if (p)
+               saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
+
+       return 1;
+}
+__setup("savemaxmem=", parse_savemaxmem);
+
+
+static void *kdump_buf_page;
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ *     space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ *     otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+                        size_t csize, unsigned long offset, int userbuf)
+{
+       void  *vaddr;
+
+       if (!csize)
+               return 0;
+
+       vaddr = kmap_atomic_pfn(pfn);
+
+       if (!userbuf) {
+               memcpy(buf, (vaddr + offset), csize);
+               kunmap_atomic(vaddr);
+       } else {
+               if (!kdump_buf_page) {
+                       pr_warning("Kdump: Kdump buffer page not allocated\n");
+
+                       return -EFAULT;
+               }
+               copy_page(kdump_buf_page, vaddr);
+               kunmap_atomic(vaddr);
+               if (copy_to_user(buf, (kdump_buf_page + offset), csize))
+                       return -EFAULT;
+       }
+
+       return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+       int ret = 0;
+
+       kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!kdump_buf_page) {
+               pr_warning("Kdump: Failed to allocate kdump buffer page\n");
+               ret = -ENOMEM;
+       }
+
+       return ret;
+}
+arch_initcall(kdump_buf_page_init);
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
deleted file mode 100644 (file)
index 1282b9a..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2003 Ralf Baechle
- *
- * 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.
- *
- * Handler for RM9000 extended interrupts.  These are a non-standard
- * feature so we handle them separately from standard interrupts.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-
-static inline void unmask_rm9k_irq(struct irq_data *d)
-{
-       set_c0_intcontrol(0x1000 << (d->irq - RM9K_CPU_IRQ_BASE));
-}
-
-static inline void mask_rm9k_irq(struct irq_data *d)
-{
-       clear_c0_intcontrol(0x1000 << (d->irq - RM9K_CPU_IRQ_BASE));
-}
-
-static inline void rm9k_cpu_irq_enable(struct irq_data *d)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       unmask_rm9k_irq(d);
-       local_irq_restore(flags);
-}
-
-/*
- * Performance counter interrupts are global on all processors.
- */
-static void local_rm9k_perfcounter_irq_startup(void *args)
-{
-       rm9k_cpu_irq_enable(args);
-}
-
-static unsigned int rm9k_perfcounter_irq_startup(struct irq_data *d)
-{
-       on_each_cpu(local_rm9k_perfcounter_irq_startup, d, 1);
-
-       return 0;
-}
-
-static void local_rm9k_perfcounter_irq_shutdown(void *args)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       mask_rm9k_irq(args);
-       local_irq_restore(flags);
-}
-
-static void rm9k_perfcounter_irq_shutdown(struct irq_data *d)
-{
-       on_each_cpu(local_rm9k_perfcounter_irq_shutdown, d, 1);
-}
-
-static struct irq_chip rm9k_irq_controller = {
-       .name = "RM9000",
-       .irq_ack = mask_rm9k_irq,
-       .irq_mask = mask_rm9k_irq,
-       .irq_mask_ack = mask_rm9k_irq,
-       .irq_unmask = unmask_rm9k_irq,
-       .irq_eoi = unmask_rm9k_irq
-};
-
-static struct irq_chip rm9k_perfcounter_irq = {
-       .name = "RM9000",
-       .irq_startup = rm9k_perfcounter_irq_startup,
-       .irq_shutdown = rm9k_perfcounter_irq_shutdown,
-       .irq_ack = mask_rm9k_irq,
-       .irq_mask = mask_rm9k_irq,
-       .irq_mask_ack = mask_rm9k_irq,
-       .irq_unmask = unmask_rm9k_irq,
-};
-
-unsigned int rm9000_perfcount_irq;
-
-EXPORT_SYMBOL(rm9000_perfcount_irq);
-
-void __init rm9k_cpu_irq_init(void)
-{
-       int base = RM9K_CPU_IRQ_BASE;
-       int i;
-
-       clear_c0_intcontrol(0x0000f000);                /* Mask all */
-
-       for (i = base; i < base + 4; i++)
-               irq_set_chip_and_handler(i, &rm9k_irq_controller,
-                                        handle_level_irq);
-
-       rm9000_perfcount_irq = base + 1;
-       irq_set_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
-                                handle_percpu_irq);
-}
index 85beb9b0b2d0122832017e1d73387f63a8d5d956..992e18474da5da89f1ff4b878dbbc8e8db47e919 100644 (file)
@@ -5,7 +5,7 @@
  * This source code is licensed under the GNU General Public License,
  * Version 2.  See the file COPYING for more details.
  */
-
+#include <linux/compiler.h>
 #include <linux/kexec.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
@@ -19,9 +19,19 @@ extern const size_t relocate_new_kernel_size;
 extern unsigned long kexec_start_address;
 extern unsigned long kexec_indirection_page;
 
+int (*_machine_kexec_prepare)(struct kimage *) = NULL;
+void (*_machine_kexec_shutdown)(void) = NULL;
+void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
+#ifdef CONFIG_SMP
+void (*relocated_kexec_smp_wait) (void *);
+atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
+#endif
+
 int
 machine_kexec_prepare(struct kimage *kimage)
 {
+       if (_machine_kexec_prepare)
+               return _machine_kexec_prepare(kimage);
        return 0;
 }
 
@@ -33,14 +43,20 @@ machine_kexec_cleanup(struct kimage *kimage)
 void
 machine_shutdown(void)
 {
+       if (_machine_kexec_shutdown)
+               _machine_kexec_shutdown();
 }
 
 void
 machine_crash_shutdown(struct pt_regs *regs)
 {
+       if (_machine_crash_shutdown)
+               _machine_crash_shutdown(regs);
+       else
+               default_machine_crash_shutdown(regs);
 }
 
-typedef void (*noretfun_t)(void) __attribute__((noreturn));
+typedef void (*noretfun_t)(void) __noreturn;
 
 void
 machine_kexec(struct kimage *image)
@@ -52,7 +68,9 @@ machine_kexec(struct kimage *image)
        reboot_code_buffer =
          (unsigned long)page_address(image->control_code_page);
 
-       kexec_start_address = image->start;
+       kexec_start_address =
+               (unsigned long) phys_to_virt(image->start);
+
        kexec_indirection_page =
                (unsigned long) phys_to_virt(image->head & PAGE_MASK);
 
@@ -63,7 +81,7 @@ machine_kexec(struct kimage *image)
         * The generic kexec code builds a page list with physical
         * addresses. they are directly accessible through KSEG0 (or
         * CKSEG0 or XPHYS if on 64bit system), hence the
-        * pys_to_virt() call.
+        * phys_to_virt() call.
         */
        for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
             ptr = (entry & IND_INDIRECTION) ?
@@ -81,5 +99,12 @@ machine_kexec(struct kimage *image)
        printk("Will call new kernel at %08lx\n", image->start);
        printk("Bye ...\n");
        __flush_cache_all();
+#ifdef CONFIG_SMP
+       /* All secondary cpus now may jump to kexec_wait cycle */
+       relocated_kexec_smp_wait = reboot_code_buffer +
+               (void *)(kexec_smp_wait - relocate_new_kernel);
+       smp_wmb();
+       atomic_set(&kexec_ready_to_reboot, 1);
+#endif
        ((noretfun_t) reboot_code_buffer)();
 }
index 33f63bab478a7478ad34733eaa861f3aba01e78b..fd814e08c945da41ad10f0582d7ccd7b7a8ab94f 100644 (file)
@@ -50,8 +50,8 @@ static bool check_same_owner(struct task_struct *p)
 
        rcu_read_lock();
        pcred = __task_cred(p);
-       match = (cred->euid == pcred->euid ||
-                cred->euid == pcred->uid);
+       match = (uid_eq(cred->euid, pcred->euid) ||
+                uid_eq(cred->euid, pcred->uid));
        rcu_read_unlock();
        return match;
 }
index 2d9304c2b54cb0e8508e3a9dd397486ac977d1bb..df1e3e455f9a872c70c2c110755cdf1e0b8cfe03 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/export.h>
 #include <asm/checksum.h>
-#include <asm/pgtable.h>
+#include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/ftrace.h>
 
index a9b995dcf69165b39b7dec0ddeefc9ed06b9980f..b14c14d90fc2feedbb25eff71578824a7eff7440 100644 (file)
@@ -840,6 +840,16 @@ static const struct mips_perf_event bmips5000_event_map
        [PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
 };
 
+static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
+       [PERF_COUNT_HW_INSTRUCTIONS] = { 0x18, CNTR_ALL }, /* PAPI_TOT_INS */
+       [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
+       [PERF_COUNT_HW_CACHE_MISSES] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x1b, CNTR_ALL }, /* PAPI_BR_CN */
+       [PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
+       [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
+};
+
 /* 24K/34K/1004K cores can share the same cache event map. */
 static const struct mips_perf_event mipsxxcore_cache_map
                                [PERF_COUNT_HW_CACHE_MAX]
@@ -1092,6 +1102,100 @@ static const struct mips_perf_event octeon_cache_map
 },
 };
 
+static const struct mips_perf_event xlp_cache_map
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x31, CNTR_ALL }, /* PAPI_L1_DCR */
+               [C(RESULT_MISS)]        = { 0x30, CNTR_ALL }, /* PAPI_L1_LDM */
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { 0x2f, CNTR_ALL }, /* PAPI_L1_DCW */
+               [C(RESULT_MISS)]        = { 0x2e, CNTR_ALL }, /* PAPI_L1_STM */
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+},
+[C(L1I)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
+               [C(RESULT_MISS)]        = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+},
+[C(LL)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x35, CNTR_ALL }, /* PAPI_L2_DCR */
+               [C(RESULT_MISS)]        = { 0x37, CNTR_ALL }, /* PAPI_L2_LDM */
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { 0x34, CNTR_ALL }, /* PAPI_L2_DCA */
+               [C(RESULT_MISS)]        = { 0x36, CNTR_ALL }, /* PAPI_L2_DCM */
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+},
+[C(DTLB)] = {
+       /*
+        * Only general DTLB misses are counted use the same event for
+        * read and write.
+        */
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+},
+[C(ITLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+},
+[C(BPU)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { 0x25, CNTR_ALL },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
+               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
+       },
+},
+};
+
 #ifdef CONFIG_MIPS_MT_SMP
 static void check_and_calc_range(struct perf_event *event,
                                 const struct mips_perf_event *pev)
@@ -1444,6 +1548,20 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
        return &raw_event;
 }
 
+static const struct mips_perf_event *xlp_pmu_map_raw_event(u64 config)
+{
+       unsigned int raw_id = config & 0xff;
+
+       /* Only 1-63 are defined */
+       if ((raw_id < 0x01) || (raw_id > 0x3f))
+               return ERR_PTR(-EOPNOTSUPP);
+
+       raw_event.cntr_mask = CNTR_ALL;
+       raw_event.event_id = raw_id;
+
+       return &raw_event;
+}
+
 static int __init
 init_hw_perf_events(void)
 {
@@ -1522,6 +1640,12 @@ init_hw_perf_events(void)
                mipspmu.general_event_map = &bmips5000_event_map;
                mipspmu.cache_event_map = &bmips5000_cache_map;
                break;
+       case CPU_XLP:
+               mipspmu.name = "xlp";
+               mipspmu.general_event_map = &xlp_event_map;
+               mipspmu.cache_event_map = &xlp_cache_map;
+               mipspmu.map_raw_event = xlp_pmu_map_raw_event;
+               break;
        default:
                pr_cont("Either hardware does not support performance "
                        "counters, or not yet implemented.\n");
index 38097652d62d0d6f704f56d93508d50783d848b6..a11c6f9fdd5e0f2e05b306936cb98464f88a130d 100644 (file)
@@ -72,9 +72,7 @@ void __noreturn cpu_idle(void)
                        }
                }
 #ifdef CONFIG_HOTPLUG_CPU
-               if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) &&
-                   (system_state == SYSTEM_RUNNING ||
-                    system_state == SYSTEM_BOOTING))
+               if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map))
                        play_dead();
 #endif
                rcu_idle_exit();
index 87481f916a61bb4ed8743a5d1b2b5b3778639daa..e4142c5f7c2b6f16434275436668f7c17f67c68a 100644 (file)
 #include <asm/addrspace.h>
 
 LEAF(relocate_new_kernel)
+       PTR_L a0,       arg0
+       PTR_L a1,       arg1
+       PTR_L a2,       arg2
+       PTR_L a3,       arg3
+
        PTR_L           s0, kexec_indirection_page
        PTR_L           s1, kexec_start_address
 
@@ -26,7 +31,6 @@ process_entry:
        and             s3, s2, 0x1
        beq             s3, zero, 1f
        and             s4, s2, ~0x1    /* store destination addr in s4 */
-       move            a0, s4
        b               process_entry
 
 1:
@@ -60,10 +64,111 @@ copy_word:
        b               process_entry
 
 done:
+#ifdef CONFIG_SMP
+       /* kexec_flag reset is signal to other CPUs what kernel
+          was moved to it's location. Note - we need relocated address
+          of kexec_flag.  */
+
+       bal             1f
+ 1:    move            t1,ra;
+       PTR_LA          t2,1b
+       PTR_LA          t0,kexec_flag
+       PTR_SUB         t0,t0,t2;
+       PTR_ADD         t0,t1,t0;
+       LONG_S          zero,(t0)
+#endif
+
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       /* We need to flush I-cache before jumping to new kernel.
+        * Unfortunatelly, this code is cpu-specific.
+        */
+       .set push
+       .set noreorder
+       syncw
+       syncw
+       synci           0($0)
+       .set pop
+#else
+       sync
+#endif
        /* jump to kexec_start_address */
        j               s1
        END(relocate_new_kernel)
 
+#ifdef CONFIG_SMP
+/*
+ * Other CPUs should wait until code is relocated and
+ * then start at entry (?) point.
+ */
+LEAF(kexec_smp_wait)
+       PTR_L           a0, s_arg0
+       PTR_L           a1, s_arg1
+       PTR_L           a2, s_arg2
+       PTR_L           a3, s_arg3
+       PTR_L           s1, kexec_start_address
+
+       /* Non-relocated address works for args and kexec_start_address ( old
+        * kernel is not overwritten). But we need relocated address of
+        * kexec_flag.
+        */
+
+       bal             1f
+1:     move            t1,ra;
+       PTR_LA          t2,1b
+       PTR_LA          t0,kexec_flag
+       PTR_SUB         t0,t0,t2;
+       PTR_ADD         t0,t1,t0;
+
+1:     LONG_L          s0, (t0)
+       bne             s0, zero,1b
+
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       .set push
+       .set noreorder
+       synci           0($0)
+       .set pop
+#else
+       sync
+#endif
+       j               s1
+       END(kexec_smp_wait)
+#endif
+
+#ifdef __mips64
+       /* all PTR's must be aligned to 8 byte in 64-bit mode */
+       .align  3
+#endif
+
+/* All parameters to new kernel are passed in registers a0-a3.
+ * kexec_args[0..3] are uses to prepare register values.
+ */
+
+kexec_args:
+       EXPORT(kexec_args)
+arg0:  PTR             0x0
+arg1:  PTR             0x0
+arg2:  PTR             0x0
+arg3:  PTR             0x0
+       .size   kexec_args,PTRSIZE*4
+
+#ifdef CONFIG_SMP
+/*
+ * Secondary CPUs may have different kernel parameters in
+ * their registers a0-a3. secondary_kexec_args[0..3] are used
+ * to prepare register values.
+ */
+secondary_kexec_args:
+       EXPORT(secondary_kexec_args)
+s_arg0:        PTR             0x0
+s_arg1:        PTR             0x0
+s_arg2:        PTR             0x0
+s_arg3:        PTR             0x0
+       .size   secondary_kexec_args,PTRSIZE*4
+kexec_flag:
+       LONG            0x1
+
+#endif
+
 kexec_start_address:
        EXPORT(kexec_start_address)
        PTR             0x0
index 629719143763b081b8afd6ff2631870a02e9fddd..ad3de9668da9974c74d6a002b95a3739207e95b3 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 
-/* This duplicates the definition from <linux/sched.h> */
-#define PT_TRACESYS    0x00000002      /* tracing system calls */
-
-/* This duplicates the definition from <asm/signal.h> */
-#define SIGILL         4               /* Illegal instruction (ANSI).  */
-
 #ifndef CONFIG_MIPS32_O32
 /* No O32, so define handle_sys here */
 #define handle_sysn32 handle_sys
index 290dc6a1d7a344413e36f00fdacfa86e9d1bcbe3..8c41187801ce34d217b953ce7f4a94728fe050bb 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/console.h>
 #include <linux/pfn.h>
 #include <linux/debugfs.h>
+#include <linux/kexec.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -536,12 +537,64 @@ static void __init arch_mem_init(char **cmdline_p)
        }
 
        bootmem_init();
+#ifdef CONFIG_KEXEC
+       if (crashk_res.start != crashk_res.end)
+               reserve_bootmem(crashk_res.start,
+                               crashk_res.end - crashk_res.start + 1,
+                               BOOTMEM_DEFAULT);
+#endif
        device_tree_init();
        sparse_init();
        plat_swiotlb_setup();
        paging_init();
 }
 
+#ifdef CONFIG_KEXEC
+static inline unsigned long long get_total_mem(void)
+{
+       unsigned long long total;
+
+       total = max_pfn - min_low_pfn;
+       return total << PAGE_SHIFT;
+}
+
+static void __init mips_parse_crashkernel(void)
+{
+       unsigned long long total_mem;
+       unsigned long long crash_size, crash_base;
+       int ret;
+
+       total_mem = get_total_mem();
+       ret = parse_crashkernel(boot_command_line, total_mem,
+                               &crash_size, &crash_base);
+       if (ret != 0 || crash_size <= 0)
+               return;
+
+       crashk_res.start = crash_base;
+       crashk_res.end   = crash_base + crash_size - 1;
+}
+
+static void __init request_crashkernel(struct resource *res)
+{
+       int ret;
+
+       ret = request_resource(res, &crashk_res);
+       if (!ret)
+               pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n",
+                       (unsigned long)((crashk_res.end -
+                               crashk_res.start + 1) >> 20),
+                       (unsigned long)(crashk_res.start  >> 20));
+}
+#else /* !defined(CONFIG_KEXEC)  */
+static void __init mips_parse_crashkernel(void)
+{
+}
+
+static void __init request_crashkernel(struct resource *res)
+{
+}
+#endif /* !defined(CONFIG_KEXEC)  */
+
 static void __init resource_init(void)
 {
        int i;
@@ -557,6 +610,8 @@ static void __init resource_init(void)
        /*
         * Request address space for all standard RAM.
         */
+       mips_parse_crashkernel();
+
        for (i = 0; i < boot_mem_map.nr_map; i++) {
                struct resource *res;
                unsigned long start, end;
@@ -593,6 +648,7 @@ static void __init resource_init(void)
                 */
                request_resource(res, &code_resource);
                request_resource(res, &data_resource);
+               request_crashkernel(res);
        }
 }
 
index 0e1a5b8ae817c4c69f417f3aff2d9aade7a5cad0..b6aa77035019bc4913468fbf551f21ef9e9898aa 100644 (file)
@@ -568,17 +568,20 @@ static void do_signal(struct pt_regs *regs)
        }
 
        if (regs->regs[0]) {
-               if (regs->regs[2] == ERESTARTNOHAND ||
-                   regs->regs[2] == ERESTARTSYS ||
-                   regs->regs[2] == ERESTARTNOINTR) {
+               switch (regs->regs[2]) {
+               case ERESTARTNOHAND:
+               case ERESTARTSYS:
+               case ERESTARTNOINTR:
                        regs->regs[2] = regs->regs[0];
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
-               }
-               if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+                       break;
+
+               case ERESTART_RESTARTBLOCK:
                        regs->regs[2] = current->thread.abi->restart;
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
+                       break;
                }
                regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
index 9005bf9fb859552101d7e68638adc73ba4978ee7..2e6374a589ec622a85dde2ad1c9394b93bd05c68 100644 (file)
@@ -386,3 +386,20 @@ void flush_tlb_one(unsigned long vaddr)
 
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_one);
+
+#if defined(CONFIG_KEXEC)
+void (*dump_ipi_function_ptr)(void *) = NULL;
+void dump_send_ipi(void (*dump_ipi_callback)(void *))
+{
+       int i;
+       int cpu = smp_processor_id();
+
+       dump_ipi_function_ptr = dump_ipi_callback;
+       smp_mb();
+       for_each_online_cpu(i)
+               if (i != cpu)
+                       mp_ops->send_ipi_single(i, SMP_DUMP);
+
+}
+EXPORT_SYMBOL(dump_send_ipi);
+#endif
index 9be3df1fa8a461dc4e1e5563582f483e4ed7c103..cf7ac5483f5398e8f91b05c1615a7aab6efa6349 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/bug.h>
 #include <linux/compiler.h>
+#include <linux/kexec.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -409,6 +410,9 @@ void __noreturn die(const char *str, struct pt_regs *regs)
                panic("Fatal exception");
        }
 
+       if (regs && kexec_should_crash(current))
+               crash_kexec(regs);
+
        do_exit(sig);
 }
 
@@ -1021,6 +1025,24 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                return;
 
+       case 3:
+               /*
+                * Old (MIPS I and MIPS II) processors will set this code
+                * for COP1X opcode instructions that replaced the original
+                * COP3 space.  We don't limit COP1 space instructions in
+                * the emulator according to the CPU ISA, so we want to
+                * treat COP1X instructions consistently regardless of which
+                * code the CPU chose.  Therefore we redirect this trap to
+                * the FP emulator too.
+                *
+                * Then some newer FPU-less processors use this code
+                * erroneously too, so they are covered by this choice
+                * as well.
+                */
+               if (raw_cpu_has_fpu)
+                       break;
+               /* Fall through.  */
+
        case 1:
                if (used_math())        /* Using the FPU again.  */
                        own_fpu(1);
@@ -1044,9 +1066,6 @@ asmlinkage void do_cpu(struct pt_regs *regs)
        case 2:
                raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
                return;
-
-       case 3:
-               break;
        }
 
        force_sig(SIGILL, current);
index d84f361f1e4530ec91c591e089b0227dfe9c5f22..c0021912131ebffe825232bada28332e6cd990fb 100644 (file)
@@ -36,4 +36,8 @@ config PCI_LANTIQ
        bool "PCI Support"
        depends on SOC_XWAY && PCI
 
+config XRX200_PHY_FW
+       bool "XRX200 PHY firmware loader"
+       depends on SOC_XWAY
+
 endif
index 6cfd6117fbfdc26f13e403d0241e45a5357aeaf2..9f9e875967aa21244e2d8578a8830096fab27c89 100644 (file)
@@ -87,9 +87,6 @@ void __init device_tree_init(void)
        reserve_bootmem(base, size, BOOTMEM_DEFAULT);
 
        unflatten_device_tree();
-
-       /* free the space reserved for the dt blob */
-       free_bootmem(base, size);
 }
 
 void __init prom_init(void)
@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
                sizeof(of_ids[0].compatible));
        strncpy(of_ids[1].compatible, "simple-bus",
                sizeof(of_ids[1].compatible));
-       return of_platform_bus_probe(NULL, of_ids, NULL);
+       return of_platform_populate(NULL, of_ids, NULL, NULL);
 }
 
 arch_initcall(plat_of_setup);
index 70a58c747bd0227dfa8fd801a6f61be27b968edb..7a13660d630d1303af12f98d53abfcbf51367287 100644 (file)
@@ -1 +1,3 @@
 obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
+
+obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
index 55d2c4fa47140d555d762fadb74b982b7a2f89fd..6453962ac898f86222587ec98184af6244a812a1 100644 (file)
@@ -25,6 +25,7 @@
 #include <lantiq_soc.h>
 #include <xway_dma.h>
 
+#define LTQ_DMA_ID             0x08
 #define LTQ_DMA_CTRL           0x10
 #define LTQ_DMA_CPOLL          0x14
 #define LTQ_DMA_CS             0x18
@@ -48,7 +49,7 @@
 #define DMA_CLK_DIV4           BIT(6)          /* polling clock divider */
 #define DMA_2W_BURST           BIT(1)          /* 2 word burst length */
 #define DMA_MAX_CHANNEL                20              /* the soc has 20 channels */
-#define DMA_ETOP_ENDIANESS     (0xf << 8) /* endianess swap etop channels */
+#define DMA_ETOP_ENDIANNESS    (0xf << 8) /* endianness swap etop channels */
 #define DMA_WEIGHT     (BIT(17) | BIT(16))     /* default channel wheight */
 
 #define ltq_dma_r32(x)                 ltq_r32(ltq_dma_membase + (x))
@@ -191,10 +192,10 @@ ltq_dma_init_port(int p)
        switch (p) {
        case DMA_PORT_ETOP:
                /*
-                * Tell the DMA engine to swap the endianess of data frames and
+                * Tell the DMA engine to swap the endianness of data frames and
                 * drop packets if the channel arbitration fails.
                 */
-               ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN,
+               ltq_dma_w32_mask(0, DMA_ETOP_ENDIANNESS | DMA_PDEN,
                        LTQ_DMA_PCTRL);
                break;
 
@@ -214,6 +215,7 @@ ltq_dma_init(struct platform_device *pdev)
 {
        struct clk *clk;
        struct resource *res;
+       unsigned id;
        int i;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -243,7 +245,12 @@ ltq_dma_init(struct platform_device *pdev)
                ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
                ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
        }
-       dev_info(&pdev->dev, "init done\n");
+
+       id = ltq_dma_r32(LTQ_DMA_ID);
+       dev_info(&pdev->dev,
+               "Init done - hw rev: %X, ports: %d, channels: %d\n",
+               id & 0x1f, (id >> 16) & 0xf, id >> 20);
+
        return 0;
 }
 
index 22c55f73aa9d646c535560a9938e27663970a9d9..544dbb7fb421e03ac01200e226255390f26499f7 100644 (file)
 #define RCU_RST_REQ            0x0010
 /* reset status register */
 #define RCU_RST_STAT           0x0014
+/* vr9 gphy registers */
+#define RCU_GFS_ADD0_XRX200    0x0020
+#define RCU_GFS_ADD1_XRX200    0x0068
 
 /* reboot bit */
+#define RCU_RD_GPHY0_XRX200    BIT(31)
 #define RCU_RD_SRST            BIT(30)
+#define RCU_RD_GPHY1_XRX200    BIT(29)
+
 /* reset cause */
 #define RCU_STAT_SHIFT         26
 /* boot selection */
-#define RCU_BOOT_SEL_SHIFT     26
-#define RCU_BOOT_SEL_MASK      0x7
+#define RCU_BOOT_SEL(x)                ((x >> 18) & 0x7)
+#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
 
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
+static struct device_node *ltq_rcu_np;
 
 /* This function is used by the watchdog driver */
 int ltq_reset_cause(void)
@@ -52,7 +59,41 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
 unsigned char ltq_boot_select(void)
 {
        u32 val = ltq_rcu_r32(RCU_RST_STAT);
-       return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
+
+       if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
+               return RCU_BOOT_SEL_XRX200(val);
+
+       return RCU_BOOT_SEL(val);
+}
+
+/* reset / boot a gphy */
+static struct ltq_xrx200_gphy_reset {
+       u32 rd;
+       u32 addr;
+} xrx200_gphy[] = {
+       {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
+       {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
+};
+
+/* reset and boot a gphy. these phys only exist on xrx200 SoC */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
+{
+       if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
+               dev_err(dev, "this SoC has no GPHY\n");
+               return -EINVAL;
+       }
+       if (id > 1) {
+               dev_err(dev, "%u is an invalid gphy id\n", id);
+               return -EINVAL;
+       }
+       dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
+
+       ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
+                       RCU_RST_REQ);
+       ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
+                       RCU_RST_REQ);
+       return 0;
 }
 
 /* reset a io domain for u micro seconds */
@@ -85,14 +126,17 @@ static void ltq_machine_power_off(void)
 static int __init mips_reboot_setup(void)
 {
        struct resource res;
-       struct device_node *np =
-               of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+
+       ltq_rcu_np = of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+       if (!ltq_rcu_np)
+               ltq_rcu_np = of_find_compatible_node(NULL, NULL,
+                                                       "lantiq,rcu-xrx200");
 
        /* check if all the reset register range is available */
-       if (!np)
+       if (!ltq_rcu_np)
                panic("Failed to load reset resources from devicetree");
 
-       if (of_address_to_resource(np, 0, &res))
+       if (of_address_to_resource(ltq_rcu_np, 0, &res))
                panic("Failed to get rcu memory range");
 
        if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
index 2917b56b6b2572bafc4ded2825ec7fb2feec85da..3925e6609acc5d393a0fe6975c8969c970e54d2e 100644 (file)
@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
                clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
                clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
                clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
+               clkdev_add_pmu("1e108000.eth", NULL, 0,
+                               PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
+                               PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
+                               PMU_PPE_QSB | PMU_PPE_TOP);
        } else if (of_machine_is_compatible("lantiq,ar9")) {
                clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
                                ltq_ar9_fpi_hz());
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
new file mode 100644 (file)
index 0000000..fe808bf
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  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 (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+#define XRX200_GPHY_FW_ALIGN   (16 * 1024)
+
+static dma_addr_t xway_gphy_load(struct platform_device *pdev)
+{
+       const struct firmware *fw;
+       dma_addr_t dev_addr = 0;
+       const char *fw_name;
+       void *fw_addr;
+       size_t size;
+
+       if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
+               dev_err(&pdev->dev, "failed to load firmware filename\n");
+               return 0;
+       }
+
+       dev_info(&pdev->dev, "requesting %s\n", fw_name);
+       if (request_firmware(&fw, fw_name, &pdev->dev)) {
+               dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name);
+               return 0;
+       }
+
+       /*
+        * GPHY cores need the firmware code in a persistent and contiguous
+        * memory area with a 16 kB boundary aligned start address
+        */
+       size = fw->size + XRX200_GPHY_FW_ALIGN;
+
+       fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
+       if (fw_addr) {
+               fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
+               dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN);
+               memcpy(fw_addr, fw->data, fw->size);
+       } else {
+               dev_err(&pdev->dev, "failed to alloc firmware memory\n");
+       }
+
+       release_firmware(fw);
+       return dev_addr;
+}
+
+static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
+{
+       dma_addr_t fw_addr;
+       struct property *pp;
+       unsigned char *phyids;
+       int i, ret = 0;
+
+       fw_addr = xway_gphy_load(pdev);
+       if (!fw_addr)
+               return -EINVAL;
+       pp = of_find_property(pdev->dev.of_node, "phys", NULL);
+       if (!pp)
+               return -ENOENT;
+       phyids = pp->value;
+       for (i = 0; i < pp->length && !ret; i++)
+               ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr);
+       if (!ret)
+               mdelay(100);
+       return ret;
+}
+
+static const struct of_device_id xway_phy_match[] = {
+       { .compatible = "lantiq,phy-xrx200" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, xway_phy_match);
+
+static struct platform_driver xway_phy_driver = {
+       .probe = xway_phy_fw_probe,
+       .driver = {
+               .name = "phy-xrx200",
+               .owner = THIS_MODULE,
+               .of_match_table = xway_phy_match,
+       },
+};
+
+module_platform_driver(xway_phy_driver);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
+MODULE_LICENSE("GPL");
index a9a14d6e81af6c38b9d4510d11b2030d586fa286..fbf75f635798cd99c628e3259df40a52f4293446 100644 (file)
@@ -15,7 +15,7 @@ config LOONGSON1_LS1B
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_HIGHMEM
        select SYS_HAS_EARLY_PRINTK
-       select HAVE_CLK
+       select COMMON_CLK
 
 endchoice
 
index 1bbbbec12085eb5c4264e6cf70d4dc6fbf11437b..07133defa148dbbe2da9216a66fae3b09dabaefd 100644 (file)
  * option) any later version.
  */
 
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <asm/clock.h>
 #include <asm/time.h>
-
-#include <loongson1.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-struct clk *clk_get(struct device *dev, const char *name)
-{
-       struct clk *c;
-       struct clk *ret = NULL;
-
-       mutex_lock(&clocks_mutex);
-       list_for_each_entry(c, &clocks, node) {
-               if (!strcmp(c->name, name)) {
-                       ret = c;
-                       break;
-               }
-       }
-       mutex_unlock(&clocks_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL(clk_get);
-
-int clk_enable(struct clk *clk)
-{
-       return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-static void pll_clk_init(struct clk *clk)
-{
-       u32 pll;
-
-       pll = __raw_readl(LS1X_CLK_PLL_FREQ);
-       clk->rate = (12 + (pll & 0x3f)) * 33 / 2
-                       + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
-       clk->rate *= 1000000;
-}
-
-static void cpu_clk_init(struct clk *clk)
-{
-       u32 pll, ctrl;
-
-       pll = clk_get_rate(clk->parent);
-       ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU;
-       clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
-}
-
-static void ddr_clk_init(struct clk *clk)
-{
-       u32 pll, ctrl;
-
-       pll = clk_get_rate(clk->parent);
-       ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR;
-       clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
-}
-
-static void dc_clk_init(struct clk *clk)
-{
-       u32 pll, ctrl;
-
-       pll = clk_get_rate(clk->parent);
-       ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC;
-       clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
-}
-
-static struct clk_ops pll_clk_ops = {
-       .init   = pll_clk_init,
-};
-
-static struct clk_ops cpu_clk_ops = {
-       .init   = cpu_clk_init,
-};
-
-static struct clk_ops ddr_clk_ops = {
-       .init   = ddr_clk_init,
-};
-
-static struct clk_ops dc_clk_ops = {
-       .init   = dc_clk_init,
-};
-
-static struct clk pll_clk = {
-       .name   = "pll",
-       .ops    = &pll_clk_ops,
-};
-
-static struct clk cpu_clk = {
-       .name   = "cpu",
-       .parent = &pll_clk,
-       .ops    = &cpu_clk_ops,
-};
-
-static struct clk ddr_clk = {
-       .name   = "ddr",
-       .parent = &pll_clk,
-       .ops    = &ddr_clk_ops,
-};
-
-static struct clk dc_clk = {
-       .name   = "dc",
-       .parent = &pll_clk,
-       .ops    = &dc_clk_ops,
-};
-
-int clk_register(struct clk *clk)
-{
-       mutex_lock(&clocks_mutex);
-       list_add(&clk->node, &clocks);
-       if (clk->ops->init)
-               clk->ops->init(clk);
-       mutex_unlock(&clocks_mutex);
-
-       return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-static struct clk *ls1x_clks[] = {
-       &pll_clk,
-       &cpu_clk,
-       &ddr_clk,
-       &dc_clk,
-};
-
-int __init ls1x_clock_init(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++)
-               clk_register(ls1x_clks[i]);
-
-       return 0;
-}
+#include <platform.h>
 
 void __init plat_time_init(void)
 {
        struct clk *clk;
 
        /* Initialize LS1X clocks */
-       ls1x_clock_init();
+       ls1x_clk_init();
 
        /* setup mips r4k timer */
        clk = clk_get(NULL, "cpu");
        if (IS_ERR(clk))
-               panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+               panic("unable to get cpu clock, err=%ld", PTR_ERR(clk));
 
        mips_hpt_frequency = clk_get_rate(clk) / 2;
 }
index 0412ad61e2908fb99552b1d2cd1ac6a27ead90bb..69dad4cfaaf42a9d17b61004fc5805138d1f7a95 100644 (file)
@@ -43,16 +43,17 @@ struct platform_device ls1x_uart_device = {
        },
 };
 
-void __init ls1x_serial_setup(void)
+void __init ls1x_serial_setup(struct platform_device *pdev)
 {
        struct clk *clk;
        struct plat_serial8250_port *p;
 
-       clk = clk_get(NULL, "dc");
+       clk = clk_get(NULL, pdev->name);
        if (IS_ERR(clk))
-               panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+               panic("unable to get %s clock, err=%ld",
+                       pdev->name, PTR_ERR(clk));
 
-       for (p = ls1x_serial8250_port; p->flags != 0; ++p)
+       for (p = pdev->dev.platform_data; p->flags != 0; ++p)
                p->uartclk = clk_get_rate(clk);
 }
 
@@ -71,7 +72,6 @@ static struct resource ls1x_eth0_resources[] = {
 };
 
 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
-       .bus_id         = 0,
        .phy_mask       = 0,
 };
 
index 295b1be893e309a021296110c41a405429ef4c31..1fbd5264f667594efbc923fa2e428213d6bbd242 100644 (file)
@@ -9,9 +9,6 @@
 
 #include <platform.h>
 
-#include <linux/serial_8250.h>
-#include <loongson1.h>
-
 static struct platform_device *ls1b_platform_devices[] __initdata = {
        &ls1x_uart_device,
        &ls1x_eth0_device,
@@ -23,7 +20,7 @@ static int __init ls1b_platform_init(void)
 {
        int err;
 
-       ls1x_serial_setup();
+       ls1x_serial_setup(&ls1x_uart_device);
 
        err = platform_add_devices(ls1b_platform_devices,
                                   ARRAY_SIZE(ls1b_platform_devices));
index a03bf00a1a9cf096226b0ce09a590450018ba62f..47c77e7ffbf89102a07c19e900e29e4dd4cf510b 100644 (file)
@@ -171,16 +171,17 @@ static int isBranchInstr(mips_instruction * i)
  * In the Linux kernel, we support selection of FPR format on the
  * basis of the Status.FR bit.  If an FPU is not present, the FR bit
  * is hardwired to zero, which would imply a 32-bit FPU even for
- * 64-bit CPUs.  For 64-bit kernels with no FPU we use TIF_32BIT_REGS
- * as a proxy for the FR bit so that a 64-bit FPU is emulated.  In any
- * case, for a 32-bit kernel which uses the O32 MIPS ABI, only the
- * even FPRs are used (Status.FR = 0).
+ * 64-bit CPUs so we rather look at TIF_32BIT_REGS.
+ * FPU emu is slow and bulky and optimizing this function offers fairly
+ * sizeable benefits so we try to be clever and make this function return
+ * a constant whenever possible, that is on 64-bit kernels without O32
+ * compatibility enabled and on 32-bit kernels.
  */
 static inline int cop1_64bit(struct pt_regs *xcp)
 {
-       if (cpu_has_fpu)
-               return xcp->cp0_status & ST0_FR;
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32)
+       return 1;
+#elif defined(CONFIG_64BIT) && defined(CONFIG_MIPS32_O32)
        return !test_thread_flag(TIF_32BIT_REGS);
 #else
        return 0;
index 44e69e7a4519110b3efd1e30a755a8ec3e0692ea..6ec04daf423112903669ea98eb7e2b41dfd931c0 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2005-2007 Cavium Networks
  */
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -28,6 +29,7 @@
 #include <asm/octeon/octeon.h>
 
 unsigned long long cache_err_dcache[NR_CPUS];
+EXPORT_SYMBOL_GPL(cache_err_dcache);
 
 /**
  * Octeon automatically flushes the dcache on tlb changes, so
@@ -284,39 +286,59 @@ void __cpuinit octeon_cache_init(void)
        board_cache_error_setup = octeon_cache_error_setup;
 }
 
-/**
+/*
  * Handle a cache error exception
  */
+static RAW_NOTIFIER_HEAD(co_cache_error_chain);
 
-static void  cache_parity_error_octeon(int non_recoverable)
+int register_co_cache_error_notifier(struct notifier_block *nb)
 {
-       unsigned long coreid = cvmx_get_core_num();
-       uint64_t icache_err = read_octeon_c0_icacheerr();
-
-       pr_err("Cache error exception:\n");
-       pr_err("cp0_errorepc == %lx\n", read_c0_errorepc());
-       if (icache_err & 1) {
-               pr_err("CacheErr (Icache) == %llx\n",
-                      (unsigned long long)icache_err);
-               write_octeon_c0_icacheerr(0);
-       }
-       if (cache_err_dcache[coreid] & 1) {
-               pr_err("CacheErr (Dcache) == %llx\n",
-                      (unsigned long long)cache_err_dcache[coreid]);
-               cache_err_dcache[coreid] = 0;
-       }
+       return raw_notifier_chain_register(&co_cache_error_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_co_cache_error_notifier);
+
+int unregister_co_cache_error_notifier(struct notifier_block *nb)
+{
+       return raw_notifier_chain_unregister(&co_cache_error_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier);
 
-       if (non_recoverable)
-               panic("Can't handle cache error: nested exception");
+static void co_cache_error_call_notifiers(unsigned long val)
+{
+       int rv = raw_notifier_call_chain(&co_cache_error_chain, val, NULL);
+       if ((rv & ~NOTIFY_STOP_MASK) != NOTIFY_OK) {
+               u64 dcache_err;
+               unsigned long coreid = cvmx_get_core_num();
+               u64 icache_err = read_octeon_c0_icacheerr();
+
+               if (val) {
+                       dcache_err = cache_err_dcache[coreid];
+                       cache_err_dcache[coreid] = 0;
+               } else {
+                       dcache_err = read_octeon_c0_dcacheerr();
+               }
+
+               pr_err("Core%lu: Cache error exception:\n", coreid);
+               pr_err("cp0_errorepc == %lx\n", read_c0_errorepc());
+               if (icache_err & 1) {
+                       pr_err("CacheErr (Icache) == %llx\n",
+                              (unsigned long long)icache_err);
+                       write_octeon_c0_icacheerr(0);
+               }
+               if (dcache_err & 1) {
+                       pr_err("CacheErr (Dcache) == %llx\n",
+                              (unsigned long long)dcache_err);
+               }
+       }
 }
 
-/**
+/*
  * Called when the the exception is recoverable
  */
 
 asmlinkage void cache_parity_error_octeon_recoverable(void)
 {
-       cache_parity_error_octeon(0);
+       co_cache_error_call_notifiers(0);
 }
 
 /**
@@ -325,5 +347,6 @@ asmlinkage void cache_parity_error_octeon_recoverable(void)
 
 asmlinkage void cache_parity_error_octeon_non_recoverable(void)
 {
-       cache_parity_error_octeon(1);
+       co_cache_error_call_notifiers(1);
+       panic("Can't handle cache error: nested exception");
 }
index 4c32ede464b555defb4c2ecfce4441b54cda39a3..0f7d788e88106fafa98e824d8b6d22f0bdcd2067 100644 (file)
@@ -632,9 +632,6 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
                if (size >= scache_size)
                        r4k_blast_scache();
                else {
-                       unsigned long lsize = cpu_scache_line_size();
-                       unsigned long almask = ~(lsize - 1);
-
                        /*
                         * There is no clearly documented alignment requirement
                         * for the cache instruction on MIPS processors and
@@ -643,9 +640,6 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
                         * hit ops with insufficient alignment.  Solved by
                         * aligning the address to cache line size.
                         */
-                       cache_op(Hit_Writeback_Inv_SD, addr & almask);
-                       cache_op(Hit_Writeback_Inv_SD,
-                                (addr + size - 1) & almask);
                        blast_inv_scache_range(addr, addr + size);
                }
                __sync();
@@ -655,12 +649,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
        if (cpu_has_safe_index_cacheops && size >= dcache_size) {
                r4k_blast_dcache();
        } else {
-               unsigned long lsize = cpu_dcache_line_size();
-               unsigned long almask = ~(lsize - 1);
-
                R4600_HIT_CACHEOP_WAR_IMPL;
-               cache_op(Hit_Writeback_Inv_D, addr & almask);
-               cache_op(Hit_Writeback_Inv_D, (addr + size - 1)  & almask);
                blast_inv_dcache_range(addr, addr + size);
        }
 
@@ -947,7 +936,6 @@ static void __cpuinit probe_pcache(void)
        case CPU_RM7000:
                rm7k_erratum31();
 
-       case CPU_RM9000:
                icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
                c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
                c->icache.ways = 4;
@@ -958,9 +946,7 @@ static void __cpuinit probe_pcache(void)
                c->dcache.ways = 4;
                c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
 
-#if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
                c->options |= MIPS_CPU_CACHE_CDEX_P;
-#endif
                c->options |= MIPS_CPU_PREFETCH;
                break;
 
@@ -1245,7 +1231,6 @@ static void __cpuinit setup_scache(void)
                 return;
 
        case CPU_RM7000:
-       case CPU_RM9000:
 #ifdef CONFIG_RM7000_CPU_SCACHE
                rm7k_sc_init();
 #endif
@@ -1348,10 +1333,10 @@ static int __init cca_setup(char *str)
 {
        get_option(&str, &cca);
 
-       return 1;
+       return 0;
 }
 
-__setup("cca=", cca_setup);
+early_param("cca", cca_setup);
 
 static void __cpuinit coherency_setup(void)
 {
@@ -1401,10 +1386,10 @@ static int __init setcoherentio(char *str)
 {
        coherentio = 1;
 
-       return 1;
+       return 0;
 }
 
-__setup("coherentio", setcoherentio);
+early_param("coherentio", setcoherentio);
 #endif
 
 static void __cpuinit r4k_cache_error_setup(void)
index aff57057a9495f79ff0eec7cc1623ab89ad19e6d..da815d295239baaaf6e1d1069e2255baa8d75358 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/sched.h>
@@ -67,7 +68,7 @@ EXPORT_SYMBOL(kmap_atomic);
 void __kunmap_atomic(void *kvaddr)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       int type;
+       int type __maybe_unused;
 
        if (vaddr < FIXADDR_START) { // FIXME
                pagefault_enable();
index 98f530e182163146ee4bba570edc2c3013236f31..8e666c55f4d47c432a58402ff5b80efa04d81288 100644 (file)
@@ -140,15 +140,6 @@ static void __cpuinit set_prefetch_parameters(void)
                        pref_bias_copy_load = 256;
                        break;
 
-               case CPU_RM9000:
-                       /*
-                        * As a workaround for erratum G105 which make the
-                        * PrepareForStore hint unusable we fall back to
-                        * StoreRetained on the RM9000.  Once it is known which
-                        * versions of the RM9000 we'll be able to condition-
-                        * alize this.
-                        */
-
                case CPU_R10000:
                case CPU_R12000:
                case CPU_R14000:
index 25407794edb4ff875bba1acb9ac5c4fa632ae78c..ee331bbd8f8aa13c263b8aa31c6bfdbab75e1101 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 void pgd_init(unsigned long page)
 {
@@ -61,6 +62,36 @@ void pmd_init(unsigned long addr, unsigned long pagetable)
 }
 #endif
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+void pmdp_splitting_flush(struct vm_area_struct *vma,
+                        unsigned long address,
+                        pmd_t *pmdp)
+{
+       if (!pmd_trans_splitting(*pmdp)) {
+               pmd_t pmd = pmd_mksplitting(*pmdp);
+               set_pmd_at(vma->vm_mm, address, pmdp, pmd);
+       }
+}
+
+#endif
+
+pmd_t mk_pmd(struct page *page, pgprot_t prot)
+{
+       pmd_t pmd;
+
+       pmd_val(pmd) = (page_to_pfn(page) << _PFN_SHIFT) | pgprot_val(prot);
+
+       return pmd;
+}
+
+void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+               pmd_t *pmdp, pmd_t pmd)
+{
+       *pmdp = pmd;
+       flush_tlb_all();
+}
+
 void __init pagetable_init(void)
 {
        unsigned long vaddr;
index 88e79ad6f811e79d07fc45cd51cf2a0580cb20bc..2a7c9725b2a3b704a1028b2ec10a357495357c52 100644 (file)
@@ -295,7 +295,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        pudp = pud_offset(pgdp, address);
        pmdp = pmd_offset(pudp, address);
        idx = read_c0_index();
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /* this could be a huge page  */
        if (pmd_huge(*pmdp)) {
                unsigned long lo;
@@ -367,6 +367,26 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        EXIT_CRITICAL(flags);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+int __init has_transparent_hugepage(void)
+{
+       unsigned int mask;
+       unsigned long flags;
+
+       ENTER_CRITICAL(flags);
+       write_c0_pagemask(PM_HUGE_MASK);
+       back_to_back_c0_hazard();
+       mask = read_c0_pagemask();
+       write_c0_pagemask(PM_DEFAULT_MASK);
+
+       EXIT_CRITICAL(flags);
+
+       return mask == PM_HUGE_MASK;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
+
 static int __cpuinitdata ntlb;
 static int __init set_ntlb(char *str)
 {
index 2833dcb67b5adeaf838536580728176bbc715a77..05613355627b2435faa5efe89b5c0a476dfa9d0f 100644 (file)
@@ -158,7 +158,7 @@ enum label_id {
        label_smp_pgtable_change,
        label_r3000_write_probe_fail,
        label_large_segbits_fault,
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        label_tlb_huge_update,
 #endif
 };
@@ -177,13 +177,15 @@ UASM_L_LA(_nopage_tlbm)
 UASM_L_LA(_smp_pgtable_change)
 UASM_L_LA(_r3000_write_probe_fail)
 UASM_L_LA(_large_segbits_fault)
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 UASM_L_LA(_tlb_huge_update)
 #endif
 
 static int __cpuinitdata hazard_instance;
 
-static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
+static void __cpuinit uasm_bgezl_hazard(u32 **p,
+                                       struct uasm_reloc **r,
+                                       int instance)
 {
        switch (instance) {
        case 0 ... 7:
@@ -194,7 +196,9 @@ static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
        }
 }
 
-static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
+static void __cpuinit uasm_bgezl_label(struct uasm_label **l,
+                                      u32 **p,
+                                      int instance)
 {
        switch (instance) {
        case 0 ... 7:
@@ -206,19 +210,59 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
 }
 
 /*
- * For debug purposes.
+ * pgtable bits are assigned dynamically depending on processor feature
+ * and statically based on kernel configuration.  This spits out the actual
+ * values the kernel is using.  Required to make sense from disassembled
+ * TLB exception handlers.
  */
-static inline void dump_handler(const u32 *handler, int count)
+static void output_pgtable_bits_defines(void)
+{
+#define pr_define(fmt, ...)                                    \
+       pr_debug("#define " fmt, ##__VA_ARGS__)
+
+       pr_debug("#include <asm/asm.h>\n");
+       pr_debug("#include <asm/regdef.h>\n");
+       pr_debug("\n");
+
+       pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
+       pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
+       pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
+       pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
+       pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+       pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
+       pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT);
+#endif
+       if (cpu_has_rixi) {
+#ifdef _PAGE_NO_EXEC_SHIFT
+               pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
+#endif
+#ifdef _PAGE_NO_READ_SHIFT
+               pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
+#endif
+       }
+       pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
+       pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
+       pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT);
+       pr_define("_PFN_SHIFT %d\n", _PFN_SHIFT);
+       pr_debug("\n");
+}
+
+static inline void dump_handler(const char *symbol, const u32 *handler, int count)
 {
        int i;
 
+       pr_debug("LEAF(%s)\n", symbol);
+
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
 
        for (i = 0; i < count; i++)
-               pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]);
+               pr_debug("\t.word\t0x%08x\t\t# %p\n", handler[i], &handler[i]);
+
+       pr_debug("\t.set\tpop\n");
 
-       pr_debug("\t.set pop\n");
+       pr_debug("\tEND(%s)\n", symbol);
 }
 
 /* The only general purpose registers allowed in TLB handlers. */
@@ -401,7 +445,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, tlb_handler, 0x80);
 
-       dump_handler((u32 *)ebase, 32);
+       dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -443,7 +487,6 @@ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p)
        case CPU_R4600:
        case CPU_R4700:
        case CPU_R5000:
-       case CPU_R5000A:
        case CPU_NEVADA:
                uasm_i_nop(p);
                uasm_i_tlbp(p);
@@ -517,7 +560,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                break;
 
        case CPU_R5000:
-       case CPU_R5000A:
        case CPU_NEVADA:
                uasm_i_nop(p); /* QED specifies 2 nops hazard */
                uasm_i_nop(p); /* QED specifies 2 nops hazard */
@@ -565,24 +607,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                tlbw(p);
                break;
 
-       case CPU_RM9000:
-               /*
-                * When the JTLB is updated by tlbwi or tlbwr, a subsequent
-                * use of the JTLB for instructions should not occur for 4
-                * cpu cycles and use for data translations should not occur
-                * for 3 cpu cycles.
-                */
-               uasm_i_ssnop(p);
-               uasm_i_ssnop(p);
-               uasm_i_ssnop(p);
-               uasm_i_ssnop(p);
-               tlbw(p);
-               uasm_i_ssnop(p);
-               uasm_i_ssnop(p);
-               uasm_i_ssnop(p);
-               uasm_i_ssnop(p);
-               break;
-
        case CPU_VR4111:
        case CPU_VR4121:
        case CPU_VR4122:
@@ -629,7 +653,7 @@ static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
        }
 }
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 
 static __cpuinit void build_restore_pagemask(u32 **p,
                                             struct uasm_reloc **r,
@@ -755,7 +779,7 @@ static __cpuinit void build_huge_handler_tail(u32 **p,
        build_huge_update_entries(p, pte, ptr);
        build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
 }
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #ifdef CONFIG_64BIT
 /*
@@ -1200,7 +1224,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
        /* Adjust the context during the load latency. */
        build_adjust_context(p, tmp);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        uasm_il_bbit1(p, r, scratch, ilog2(_PAGE_HUGE), label_tlb_huge_update);
        /*
         * The in the LWX case we don't want to do the load in the
@@ -1209,7 +1233,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
         */
        if (use_lwx_insns())
                uasm_i_nop(p);
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 
        /* build_update_entries */
@@ -1312,7 +1336,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
                build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
 #endif
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
                build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
 #endif
 
@@ -1322,7 +1346,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
                uasm_l_leave(&l, p);
                uasm_i_eret(&p); /* return from trap */
        }
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        uasm_l_tlb_huge_update(&l, p);
        build_huge_update_entries(&p, htlb_info.huge_pte, K1);
        build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
@@ -1367,7 +1391,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
                uasm_copy_handler(relocs, labels, tlb_handler, p, f);
                final_len = p - tlb_handler;
        } else {
-#if defined(CONFIG_HUGETLB_PAGE)
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
                const enum label_id ls = label_tlb_huge_update;
 #else
                const enum label_id ls = label_vmalloc;
@@ -1436,7 +1460,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, final_handler, 0x100);
 
-       dump_handler((u32 *)ebase, 64);
+       dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
 
 /*
@@ -1493,7 +1517,8 @@ static void __cpuinit build_r4000_setup_pgd(void)
        pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
                 (unsigned int)(p - tlbmiss_handler_setup_pgd));
 
-       dump_handler(tlbmiss_handler_setup_pgd,
+       dump_handler("tlbmiss_handler",
+                    tlbmiss_handler_setup_pgd,
                     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
 }
 #endif
@@ -1763,7 +1788,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbl));
 
-       dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
+       dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
 
 static void __cpuinit build_r3000_tlb_store_handler(void)
@@ -1793,7 +1818,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbs));
 
-       dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
+       dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
 
 static void __cpuinit build_r3000_tlb_modify_handler(void)
@@ -1823,7 +1848,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbm));
 
-       dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
+       dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -1842,7 +1867,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
        build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
 #endif
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * For huge tlb entries, pmd doesn't contain an address but
         * instead contains the tlb pte. Check the PAGE_HUGE bit and
@@ -1958,7 +1983,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
        build_make_valid(&p, &r, wr.r1, wr.r2);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * This is the entry point when build_r4000_tlbchange_handler_head
         * spots a huge page.
@@ -2030,7 +2055,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbl));
 
-       dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
+       dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
 
 static void __cpuinit build_r4000_tlb_store_handler(void)
@@ -2051,7 +2076,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
        build_make_write(&p, &r, wr.r1, wr.r2);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * This is the entry point when
         * build_r4000_tlbchange_handler_head spots a huge page.
@@ -2077,7 +2102,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbs));
 
-       dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
+       dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
 
 static void __cpuinit build_r4000_tlb_modify_handler(void)
@@ -2099,7 +2124,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
        build_make_write(&p, &r, wr.r1, wr.r2);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        /*
         * This is the entry point when
         * build_r4000_tlbchange_handler_head spots a huge page.
@@ -2125,7 +2150,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
                 (unsigned int)(p - handle_tlbm));
 
-       dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
+       dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
 
 void __cpuinit build_tlb_refill_handler(void)
@@ -2137,6 +2162,8 @@ void __cpuinit build_tlb_refill_handler(void)
         */
        static int run_once = 0;
 
+       output_pgtable_bits_defines();
+
 #ifdef CONFIG_64BIT
        check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
 #endif
index 8059eb76f8eb7cfdf6273e12131ca9e0566435b8..3c05bf9e280ae5e66ea1e8ae3cfc96179a610d8b 100644 (file)
@@ -9,6 +9,34 @@ config DT_XLP_EVP
          This DTB will be used if the firmware does not pass in a DTB
           pointer to the kernel.  The corresponding DTS file is at
           arch/mips/netlogic/dts/xlp_evp.dts
+
+config NLM_MULTINODE
+       bool "Support for multi-chip boards"
+       depends on NLM_XLP_BOARD
+       default n
+       help
+         Add support for boards with 2 or 4 XLPs connected over ICI.
+
+if NLM_MULTINODE
+choice
+       prompt "Number of XLPs on the board"
+       default NLM_MULTINODE_2
+       help
+         In the multi-node case, specify the number of SoCs on the board.
+
+config NLM_MULTINODE_2
+       bool "Dual-XLP board"
+       help
+         Support boards with upto two XLPs connected over ICI.
+
+config NLM_MULTINODE_4
+       bool "Quad-XLP board"
+       help
+         Support boards with upto four XLPs connected over ICI.
+
+endchoice
+
+endif
 endif
 
 config NLM_COMMON
index e52bfcbce093ff53e38c75dbd4df73089272e514..00dcc7a2bc5a5d912a60274e36958af8a1ba86d9 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/interrupt.h>
-#include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
 #elif defined(CONFIG_CPU_XLR)
 #include <asm/netlogic/xlr/iomap.h>
 #include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/fmn.h>
 #else
 #error "Unknown CPU"
 #endif
-/*
- * These are the routines that handle all the low level interrupt stuff.
- * Actions handled here are: initialization of the interrupt map, requesting of
- * interrupt lines by handlers, dispatching if interrupts to handlers, probing
- * for interrupt lines
- */
 
-/* Globals */
-static uint64_t nlm_irq_mask;
-static DEFINE_SPINLOCK(nlm_pic_lock);
+#ifdef CONFIG_SMP
+#define SMP_IRQ_MASK   ((1ULL << IRQ_IPI_SMP_FUNCTION) | \
+                                (1ULL << IRQ_IPI_SMP_RESCHEDULE))
+#else
+#define SMP_IRQ_MASK   0
+#endif
+#define PERCPU_IRQ_MASK        (SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
+                               (1ull << IRQ_FMN))
+
+struct nlm_pic_irq {
+       void    (*extra_ack)(struct irq_data *);
+       struct  nlm_soc_info *node;
+       int     picirq;
+       int     irt;
+       int     flags;
+};
 
 static void xlp_pic_enable(struct irq_data *d)
 {
        unsigned long flags;
-       int irt;
+       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
 
-       irt = nlm_irq_to_irt(d->irq);
-       if (irt == -1)
-               return;
-       spin_lock_irqsave(&nlm_pic_lock, flags);
-       nlm_pic_enable_irt(nlm_pic_base, irt);
-       spin_unlock_irqrestore(&nlm_pic_lock, flags);
+       BUG_ON(!pd);
+       spin_lock_irqsave(&pd->node->piclock, flags);
+       nlm_pic_enable_irt(pd->node->picbase, pd->irt);
+       spin_unlock_irqrestore(&pd->node->piclock, flags);
 }
 
 static void xlp_pic_disable(struct irq_data *d)
 {
+       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
        unsigned long flags;
-       int irt;
 
-       irt = nlm_irq_to_irt(d->irq);
-       if (irt == -1)
-               return;
-       spin_lock_irqsave(&nlm_pic_lock, flags);
-       nlm_pic_disable_irt(nlm_pic_base, irt);
-       spin_unlock_irqrestore(&nlm_pic_lock, flags);
+       BUG_ON(!pd);
+       spin_lock_irqsave(&pd->node->piclock, flags);
+       nlm_pic_disable_irt(pd->node->picbase, pd->irt);
+       spin_unlock_irqrestore(&pd->node->piclock, flags);
 }
 
 static void xlp_pic_mask_ack(struct irq_data *d)
 {
-       uint64_t mask = 1ull << d->irq;
+       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+       uint64_t mask = 1ull << pd->picirq;
 
        write_c0_eirr(mask);            /* ack by writing EIRR */
 }
 
 static void xlp_pic_unmask(struct irq_data *d)
 {
-       void *hd = irq_data_get_irq_handler_data(d);
-       int irt;
+       struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
 
-       irt = nlm_irq_to_irt(d->irq);
-       if (irt == -1)
+       if (!pd)
                return;
 
-       if (hd) {
-               void (*extra_ack)(void *) = hd;
-               extra_ack(d);
-       }
+       if (pd->extra_ack)
+               pd->extra_ack(d);
+
        /* Ack is a single write, no need to lock */
-       nlm_pic_ack(nlm_pic_base, irt);
+       nlm_pic_ack(pd->node->picbase, pd->irt);
 }
 
 static struct irq_chip xlp_pic = {
@@ -174,64 +175,108 @@ struct irq_chip nlm_cpu_intr = {
        .irq_eoi        = cpuintr_ack,
 };
 
-void __init init_nlm_common_irqs(void)
+static void __init nlm_init_percpu_irqs(void)
 {
-       int i, irq, irt;
+       int i;
 
        for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
                irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
-
-       for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++)
-               irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq);
-
 #ifdef CONFIG_SMP
        irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
                         nlm_smp_function_ipi_handler);
        irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
                         nlm_smp_resched_ipi_handler);
-       nlm_irq_mask |=
-           ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE));
 #endif
+}
+
+void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
+{
+       struct nlm_pic_irq *pic_data;
+       int xirq;
+
+       xirq = nlm_irq_to_xirq(node, irq);
+       pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
+       BUG_ON(pic_data == NULL);
+       pic_data->irt = irt;
+       pic_data->picirq = picirq;
+       pic_data->node = nlm_get_node(node);
+       irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
+       irq_set_handler_data(xirq, pic_data);
+}
+
+void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
+{
+       struct nlm_pic_irq *pic_data;
+       int xirq;
+
+       xirq = nlm_irq_to_xirq(node, irq);
+       pic_data = irq_get_handler_data(xirq);
+       pic_data->extra_ack = xack;
+}
 
-       for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) {
-               irt = nlm_irq_to_irt(irq);
+static void nlm_init_node_irqs(int node)
+{
+       int i, irt;
+       uint64_t irqmask;
+       struct nlm_soc_info *nodep;
+
+       pr_info("Init IRQ for node %d\n", node);
+       nodep = nlm_get_node(node);
+       irqmask = PERCPU_IRQ_MASK;
+       for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
+               irt = nlm_irq_to_irt(i);
                if (irt == -1)
                        continue;
-               nlm_irq_mask |= (1ULL << irq);
-               nlm_pic_init_irt(nlm_pic_base, irt, irq, 0);
+               nlm_setup_pic_irq(node, i, i, irt);
+               /* set interrupts to first cpu in node */
+               nlm_pic_init_irt(nodep->picbase, irt, i,
+                                       node * NLM_CPUS_PER_NODE);
+               irqmask |= (1ull << i);
        }
-
-       nlm_irq_mask |= (1ULL << IRQ_TIMER);
+       nodep->irqmask = irqmask;
 }
 
 void __init arch_init_irq(void)
 {
        /* Initialize the irq descriptors */
-       init_nlm_common_irqs();
-
-       write_c0_eimr(nlm_irq_mask);
+       nlm_init_percpu_irqs();
+       nlm_init_node_irqs(0);
+       write_c0_eimr(nlm_current_node()->irqmask);
+#if defined(CONFIG_CPU_XLR)
+       nlm_setup_fmn_irq();
+#endif
 }
 
-void __cpuinit nlm_smp_irq_init(void)
+void nlm_smp_irq_init(int hwcpuid)
 {
-       /* set interrupt mask for non-zero cpus */
-       write_c0_eimr(nlm_irq_mask);
+       int node, cpu;
+
+       node = hwcpuid / NLM_CPUS_PER_NODE;
+       cpu  = hwcpuid % NLM_CPUS_PER_NODE;
+
+       if (cpu == 0 && node != 0)
+               nlm_init_node_irqs(node);
+       write_c0_eimr(nlm_current_node()->irqmask);
 }
 
 asmlinkage void plat_irq_dispatch(void)
 {
        uint64_t eirr;
-       int i;
+       int i, node;
 
+       node = nlm_nodeid();
        eirr = read_c0_eirr() & read_c0_eimr();
-       if (eirr & (1 << IRQ_TIMER)) {
-               do_IRQ(IRQ_TIMER);
-               return;
-       }
 
        i = __ilog2_u64(eirr);
        if (i == -1)
                return;
 
-       do_IRQ(i);
+       /* per-CPU IRQs don't need translation */
+       if (eirr & PERCPU_IRQ_MASK) {
+               do_IRQ(i);
+               return;
+       }
+
+       /* top level irq handling */
+       do_IRQ(nlm_irq_to_xirq(node, i));
 }
index fab316de57e96718a38abcd1c8434ca54b7ab363..a080d9ee3cd76b5e9c4561cfb4e7c581534e80e0 100644 (file)
 
 void nlm_send_ipi_single(int logical_cpu, unsigned int action)
 {
-       int cpu = cpu_logical_map(logical_cpu);
+       int cpu, node;
+       uint64_t picbase;
+
+       cpu = cpu_logical_map(logical_cpu);
+       node = cpu / NLM_CPUS_PER_NODE;
+       picbase = nlm_get_node(node)->picbase;
 
        if (action & SMP_CALL_FUNCTION)
-               nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_FUNCTION, 0);
+               nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0);
        if (action & SMP_RESCHEDULE_YOURSELF)
-               nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
+               nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
 }
 
 void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
@@ -96,11 +101,12 @@ void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
 void nlm_early_init_secondary(int cpu)
 {
        change_c0_config(CONF_CM_CMASK, 0x3);
-       write_c0_ebase((uint32_t)nlm_common_ebase);
 #ifdef CONFIG_CPU_XLP
-       if (hard_smp_processor_id() % 4 == 0)
+       /* mmu init, once per core */
+       if (cpu % NLM_THREADS_PER_CORE == 0)
                xlp_mmu_init();
 #endif
+       write_c0_ebase(nlm_current_node()->ebase);
 }
 
 /*
@@ -108,8 +114,12 @@ void nlm_early_init_secondary(int cpu)
  */
 static void __cpuinit nlm_init_secondary(void)
 {
-       current_cpu_data.core = hard_smp_processor_id() / 4;
-       nlm_smp_irq_init();
+       int hwtid;
+
+       hwtid = hard_smp_processor_id();
+       current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
+       nlm_percpu_init(hwtid);
+       nlm_smp_irq_init(hwtid);
 }
 
 void nlm_prepare_cpus(unsigned int max_cpus)
@@ -120,9 +130,6 @@ void nlm_prepare_cpus(unsigned int max_cpus)
 
 void nlm_smp_finish(void)
 {
-#ifdef notyet
-       nlm_common_msgring_cpu_init();
-#endif
        local_irq_enable();
 }
 
@@ -142,27 +149,27 @@ cpumask_t phys_cpu_present_map;
 
 void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
 {
-       unsigned long gp = (unsigned long)task_thread_info(idle);
-       unsigned long sp = (unsigned long)__KSTK_TOS(idle);
-       int cpu = cpu_logical_map(logical_cpu);
+       int cpu, node;
 
-       nlm_next_sp = sp;
-       nlm_next_gp = gp;
+       cpu = cpu_logical_map(logical_cpu);
+       node = cpu / NLM_CPUS_PER_NODE;
+       nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
+       nlm_next_gp = (unsigned long)task_thread_info(idle);
 
-       /* barrier */
+       /* barrier for sp/gp store above */
        __sync();
-       nlm_pic_send_ipi(nlm_pic_base, cpu, 1, 1);
+       nlm_pic_send_ipi(nlm_get_node(node)->picbase, cpu, 1, 1);  /* NMI */
 }
 
 void __init nlm_smp_setup(void)
 {
        unsigned int boot_cpu;
-       int num_cpus, i;
+       int num_cpus, i, ncore;
 
        boot_cpu = hard_smp_processor_id();
-       cpus_clear(phys_cpu_present_map);
+       cpumask_clear(&phys_cpu_present_map);
 
-       cpu_set(boot_cpu, phys_cpu_present_map);
+       cpumask_set_cpu(boot_cpu, &phys_cpu_present_map);
        __cpu_number_map[boot_cpu] = 0;
        __cpu_logical_map[0] = boot_cpu;
        set_cpu_possible(0, true);
@@ -174,7 +181,7 @@ void __init nlm_smp_setup(void)
                 * it is only set for ASPs (see smpboot.S)
                 */
                if (nlm_cpu_ready[i]) {
-                       cpu_set(i, phys_cpu_present_map);
+                       cpumask_set_cpu(i, &phys_cpu_present_map);
                        __cpu_number_map[i] = num_cpus;
                        __cpu_logical_map[num_cpus] = i;
                        set_cpu_possible(num_cpus, true);
@@ -182,20 +189,28 @@ void __init nlm_smp_setup(void)
                }
        }
 
+       /* check with the cores we have worken up */
+       for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
+               ncore += hweight32(nlm_get_node(i)->coremask);
+
        pr_info("Phys CPU present map: %lx, possible map %lx\n",
-               (unsigned long)phys_cpu_present_map.bits[0],
+               (unsigned long)cpumask_bits(&phys_cpu_present_map)[0],
                (unsigned long)cpumask_bits(cpu_possible_mask)[0]);
 
-       pr_info("Detected %i Slave CPU(s)\n", num_cpus);
+       pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
+               nlm_threads_per_core, num_cpus);
        nlm_set_nmi_handler(nlm_boot_secondary_cpus);
 }
 
-static int nlm_parse_cpumask(u32 cpu_mask)
+static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 {
        uint32_t core0_thr_mask, core_thr_mask;
-       int threadmode, i;
+       int threadmode, i, j;
 
-       core0_thr_mask = cpu_mask & 0xf;
+       core0_thr_mask = 0;
+       for (i = 0; i < NLM_THREADS_PER_CORE; i++)
+               if (cpumask_test_cpu(i, wakeup_mask))
+                       core0_thr_mask |= (1 << i);
        switch (core0_thr_mask) {
        case 1:
                nlm_threads_per_core = 1;
@@ -214,25 +229,23 @@ static int nlm_parse_cpumask(u32 cpu_mask)
        }
 
        /* Verify other cores CPU masks */
-       nlm_coremask = 1;
-       nlm_cpumask = core0_thr_mask;
-       for (i = 1; i < 8; i++) {
-               core_thr_mask = (cpu_mask >> (i * 4)) & 0xf;
-               if (core_thr_mask) {
-                       if (core_thr_mask != core0_thr_mask)
+       for (i = 0; i < NR_CPUS; i += NLM_THREADS_PER_CORE) {
+               core_thr_mask = 0;
+               for (j = 0; j < NLM_THREADS_PER_CORE; j++)
+                       if (cpumask_test_cpu(i + j, wakeup_mask))
+                               core_thr_mask |= (1 << j);
+               if (core_thr_mask != 0 && core_thr_mask != core0_thr_mask)
                                goto unsupp;
-                       nlm_coremask |= 1 << i;
-                       nlm_cpumask |= core0_thr_mask << (4 * i);
-               }
        }
        return threadmode;
 
 unsupp:
-       panic("Unsupported CPU mask %x\n", cpu_mask);
+       panic("Unsupported CPU mask %lx\n",
+               (unsigned long)cpumask_bits(wakeup_mask)[0]);
        return 0;
 }
 
-int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
+int __cpuinit nlm_wakeup_secondary_cpus(void)
 {
        unsigned long reset_vec;
        char *reset_data;
@@ -244,7 +257,7 @@ int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
                        (nlm_reset_entry_end - nlm_reset_entry));
 
        /* verify the mask and setup core config variables */
-       threadmode = nlm_parse_cpumask(wakeup_mask);
+       threadmode = nlm_parse_cpumask(&nlm_cpumask);
 
        /* Setup CPU init parameters */
        reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS);
index a13355cc97eb4cdcc4df0020007e5ad9c0935e58..a0b74874bebeb2d66f36d21461948ead8f7bf7d6 100644 (file)
@@ -61,7 +61,7 @@
        li      t0, LSU_DEFEATURE
        mfcr    t1, t0
 
-       lui     t2, 0x4080      /* Enable Unaligned Access, L2HPE */
+       lui     t2, 0xc080      /* SUE, Enable Unaligned Access, L2HPE */
        or      t1, t1, t2
 #ifdef XLP_AX_WORKAROUND
        li      t2, ~0xe        /* S1RCM */
@@ -186,7 +186,7 @@ EXPORT(nlm_boot_siblings)
        * jump to the secondary wait function.
        */
        mfc0    v0, CP0_EBASE, 1
-       andi    v0, 0x7f                /* v0 <- node/core */
+       andi    v0, 0x3ff               /* v0 <- node/core */
 
        /* Init MMU in the first thread after changing THREAD_MODE
         * register (Ax Errata?)
@@ -263,6 +263,8 @@ NESTED(nlm_boot_secondary_cpus, 16, sp)
        PTR_L   gp, 0(t1)
 
        /* a0 has the processor id */
+       mfc0    a0, CP0_EBASE, 1
+       andi    a0, 0x3ff               /* a0 <- node/core */
        PTR_LA  t0, nlm_early_init_secondary
        jalr    t0
        nop
index 6c65ac7019125d5cbfedbb72727fcf4c9614dd2f..529e74742d9fc370590f6898c82c79044367cd07 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/time.h>
 
+#include <asm/netlogic/common.h>
 #include <asm/netlogic/haldefs.h>
 #include <asm/netlogic/xlp-hal/iomap.h>
 #include <asm/netlogic/xlp-hal/xlp.h>
 #include <asm/netlogic/xlp-hal/pic.h>
 #include <asm/netlogic/xlp-hal/sys.h>
 
-/* These addresses are computed by the nlm_hal_init() */
-uint64_t nlm_io_base;
-uint64_t nlm_sys_base;
-uint64_t nlm_pic_base;
-
 /* Main initialization */
-void nlm_hal_init(void)
+void nlm_node_init(int node)
 {
-       nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
-       nlm_sys_base = nlm_get_sys_regbase(0);  /* node 0 */
-       nlm_pic_base = nlm_get_pic_regbase(0);  /* node 0 */
+       struct nlm_soc_info *nodep;
+
+       nodep = nlm_get_node(node);
+       nodep->sysbase = nlm_get_sys_regbase(node);
+       nodep->picbase = nlm_get_pic_regbase(node);
+       nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+       spin_lock_init(&nodep->piclock);
 }
 
 int nlm_irq_to_irt(int irq)
@@ -100,52 +100,15 @@ int nlm_irq_to_irt(int irq)
        }
 }
 
-int nlm_irt_to_irq(int irt)
-{
-       switch (irt) {
-       case PIC_IRT_UART_0_INDEX:
-               return PIC_UART_0_IRQ;
-       case PIC_IRT_UART_1_INDEX:
-               return PIC_UART_1_IRQ;
-       case PIC_IRT_PCIE_LINK_0_INDEX:
-              return PIC_PCIE_LINK_0_IRQ;
-       case PIC_IRT_PCIE_LINK_1_INDEX:
-              return PIC_PCIE_LINK_1_IRQ;
-       case PIC_IRT_PCIE_LINK_2_INDEX:
-              return PIC_PCIE_LINK_2_IRQ;
-       case PIC_IRT_PCIE_LINK_3_INDEX:
-              return PIC_PCIE_LINK_3_IRQ;
-       case PIC_IRT_EHCI_0_INDEX:
-               return PIC_EHCI_0_IRQ;
-       case PIC_IRT_EHCI_1_INDEX:
-               return PIC_EHCI_1_IRQ;
-       case PIC_IRT_OHCI_0_INDEX:
-               return PIC_OHCI_0_IRQ;
-       case PIC_IRT_OHCI_1_INDEX:
-               return PIC_OHCI_1_IRQ;
-       case PIC_IRT_OHCI_2_INDEX:
-               return PIC_OHCI_2_IRQ;
-       case PIC_IRT_OHCI_3_INDEX:
-               return PIC_OHCI_3_IRQ;
-       case PIC_IRT_MMC_INDEX:
-              return PIC_MMC_IRQ;
-       case PIC_IRT_I2C_0_INDEX:
-               return PIC_I2C_0_IRQ;
-       case PIC_IRT_I2C_1_INDEX:
-               return PIC_I2C_1_IRQ;
-       default:
-               return -1;
-       }
-}
-
-unsigned int nlm_get_core_frequency(int core)
+unsigned int nlm_get_core_frequency(int node, int core)
 {
        unsigned int pll_divf, pll_divr, dfs_div, ext_div;
        unsigned int rstval, dfsval, denom;
-       uint64_t num;
+       uint64_t num, sysbase;
 
-       rstval = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG);
-       dfsval = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIV_VALUE);
+       sysbase = nlm_get_node(node)->sysbase;
+       rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
+       dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
        pll_divf = ((rstval >> 10) & 0x7f) + 1;
        pll_divr = ((rstval >> 8)  & 0x3) + 1;
        ext_div  = ((rstval >> 30) & 0x3) + 1;
@@ -159,5 +122,5 @@ unsigned int nlm_get_core_frequency(int core)
 
 unsigned int nlm_get_cpu_frequency(void)
 {
-       return nlm_get_core_frequency(0);
+       return nlm_get_core_frequency(0, 0);
 }
index d8997098defda9e265fb7d6adc9be34859669fbc..4894d62043ac3639ce7844069995466ced103ea0 100644 (file)
 #include <asm/netlogic/xlp-hal/xlp.h>
 #include <asm/netlogic/xlp-hal/sys.h>
 
-unsigned long nlm_common_ebase = 0x0;
-
-/* default to uniprocessor */
-uint32_t nlm_coremask = 1, nlm_cpumask  = 1;
-int  nlm_threads_per_core = 1;
+uint64_t nlm_io_base;
+struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+cpumask_t nlm_cpumask = CPU_MASK_CPU0;
+unsigned int nlm_threads_per_core;
 extern u32 __dtb_start[];
 
 static void nlm_linux_exit(void)
 {
-       nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1);
+       uint64_t sysbase = nlm_get_node(0)->sysbase;
+
+       nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
        for ( ; ; )
                cpu_wait();
 }
 
 void __init plat_mem_setup(void)
 {
+       void *fdtp;
+
        panic_timeout   = 5;
        _machine_restart = (void (*)(char *))nlm_linux_exit;
        _machine_halt   = nlm_linux_exit;
        pm_power_off    = nlm_linux_exit;
+
+       /*
+        * If no FDT pointer is passed in, use the built-in FDT.
+        * device_tree_init() does not handle CKSEG0 pointers in
+        * 64-bit, so convert pointer.
+        */
+       fdtp = (void *)(long)fw_arg0;
+       if (!fdtp)
+               fdtp = __dtb_start;
+       fdtp = phys_to_virt(__pa(fdtp));
+       early_init_devtree(fdtp);
 }
 
 const char *get_system_type(void)
@@ -94,27 +108,19 @@ void xlp_mmu_init(void)
                (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
 }
 
-void __init prom_init(void)
+void nlm_percpu_init(int hwcpuid)
 {
-       void *fdtp;
+}
 
+void __init prom_init(void)
+{
+       nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
        xlp_mmu_init();
-       nlm_hal_init();
-
-       /*
-        * If no FDT pointer is passed in, use the built-in FDT.
-        * device_tree_init() does not handle CKSEG0 pointers in
-        * 64-bit, so convert pointer.
-        */
-       fdtp = (void *)(long)fw_arg0;
-       if (!fdtp)
-               fdtp = __dtb_start;
-       fdtp = phys_to_virt(__pa(fdtp));
-       early_init_devtree(fdtp);
+       nlm_node_init(0);
 
-       nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
 #ifdef CONFIG_SMP
-       nlm_wakeup_secondary_cpus(0xffffffff);
+       cpumask_setall(&nlm_cpumask);
+       nlm_wakeup_secondary_cpus();
 
        /* update TLB size after waking up threads */
        current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
index 44d923ff3846fff1ac87482fbc68cdf516041ed3..cb9010642ac33d8002a7b1034644c98574e384af 100644 (file)
 #include <asm/netlogic/xlp-hal/xlp.h>
 #include <asm/netlogic/xlp-hal/sys.h>
 
-static void xlp_enable_secondary_cores(void)
+static int xlp_wakeup_core(uint64_t sysbase, int core)
 {
-       uint32_t core, value, coremask, syscoremask;
+       uint32_t coremask, value;
        int count;
 
-       /* read cores in reset from SYS block */
-       syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
+       coremask = (1 << core);
 
-       /* update user specified */
-       nlm_coremask = nlm_coremask & (syscoremask | 1);
+       /* Enable CPU clock */
+       value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
+       value &= ~coremask;
+       nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
 
-       for (core = 1; core < 8; core++) {
-               coremask = 1 << core;
-               if ((nlm_coremask & coremask) == 0)
-                       continue;
+       /* Remove CPU Reset */
+       value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
+       value &= ~coremask;
+       nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value);
 
-               /* Enable CPU clock */
-               value = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL);
-               value &= ~coremask;
-               nlm_write_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL, value);
+       /* Poll for CPU to mark itself coherent */
+       count = 100000;
+       do {
+               value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
+       } while ((value & coremask) != 0 && --count > 0);
 
-               /* Remove CPU Reset */
-               value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
-               value &= ~coremask;
-               nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value);
+       return count != 0;
+}
+
+static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
+{
+       struct nlm_soc_info *nodep;
+       uint64_t syspcibase;
+       uint32_t syscoremask;
+       int core, n, cpu;
+
+       for (n = 0; n < NLM_NR_NODES; n++) {
+               syspcibase = nlm_get_sys_pcibase(n);
+               if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
+                       break;
+
+               /* read cores in reset from SYS and account for boot cpu */
+               nlm_node_init(n);
+               nodep = nlm_get_node(n);
+               syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
+               if (n == 0)
+                       syscoremask |= 1;
+
+               for (core = 0; core < NLM_CORES_PER_NODE; core++) {
+                       /* see if the core exists */
+                       if ((syscoremask & (1 << core)) == 0)
+                               continue;
 
-               /* Poll for CPU to mark itself coherent */
-               count = 100000;
-               do {
-                       value = nlm_read_sys_reg(nlm_sys_base,
-                           SYS_CPU_NONCOHERENT_MODE);
-               } while ((value & coremask) != 0 && count-- > 0);
+                       /* see if at least the first thread is enabled */
+                       cpu = (n * NLM_CORES_PER_NODE + core)
+                                               * NLM_THREADS_PER_CORE;
+                       if (!cpumask_test_cpu(cpu, wakeup_mask))
+                               continue;
 
-               if (count == 0)
-                       pr_err("Failed to enable core %d\n", core);
+                       /* wake up the core */
+                       if (xlp_wakeup_core(nodep->sysbase, core))
+                               nodep->coremask |= 1u << core;
+                       else
+                               pr_err("Failed to enable core %d\n", core);
+               }
        }
 }
 
-void xlp_wakeup_secondary_cpus(void)
+void xlp_wakeup_secondary_cpus()
 {
        /*
         * In case of u-boot, the secondaries are in reset
@@ -98,5 +125,5 @@ void xlp_wakeup_secondary_cpus(void)
        xlp_boot_core0_siblings();
 
        /* now get other cores out of reset */
-       xlp_enable_secondary_cores();
+       xlp_enable_secondary_cores(&nlm_cpumask);
 }
index c287dea87570922cb1c973b58ae75b5c26d9b8d5..05902bc6f080027f276bfdd39f1ba365df287dd6 100644 (file)
@@ -1,2 +1,2 @@
-obj-y                          += setup.o platform.o platform-flash.o
-obj-$(CONFIG_SMP)              += wakeup.o
+obj-y                  +=  fmn.o fmn-config.o setup.o platform.o platform-flash.o
+obj-$(CONFIG_SMP)      += wakeup.o
diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c
new file mode 100644 (file)
index 0000000..bed2cff
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/cpu-info.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mipsregs.h>
+#include <asm/netlogic/xlr/fmn.h>
+#include <asm/netlogic/xlr/xlr.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+
+struct xlr_board_fmn_config xlr_board_fmn_config;
+
+static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
+{
+       int bkt;
+
+       pr_info("Bucket size :\n");
+       pr_info("Station\t: Size\n");
+       for (bkt = 0; bkt < 16; bkt++)
+               pr_info(" %d  %d  %d  %d  %d  %d  %d %d\n",
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
+                       xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
+       pr_info("\n");
+
+       pr_info("Credits distribution :\n");
+       pr_info("Station\t: Size\n");
+       for (bkt = 0; bkt < 16; bkt++)
+               pr_info(" %d  %d  %d  %d  %d  %d  %d %d\n",
+                       fmn_info->credit_config[(bkt * 8) + 0],
+                       fmn_info->credit_config[(bkt * 8) + 1],
+                       fmn_info->credit_config[(bkt * 8) + 2],
+                       fmn_info->credit_config[(bkt * 8) + 3],
+                       fmn_info->credit_config[(bkt * 8) + 4],
+                       fmn_info->credit_config[(bkt * 8) + 5],
+                       fmn_info->credit_config[(bkt * 8) + 6],
+                       fmn_info->credit_config[(bkt * 8) + 7]);
+       pr_info("\n");
+}
+
+static void check_credit_distribution(void)
+{
+       struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
+       int bkt, n, total_credits, ncores;
+
+       ncores = hweight32(nlm_current_node()->coremask);
+       for (bkt = 0; bkt < 128; bkt++) {
+               total_credits = 0;
+               for (n = 0; n < ncores; n++)
+                       total_credits += cfg->cpu[n].credit_config[bkt];
+               total_credits += cfg->gmac[0].credit_config[bkt];
+               total_credits += cfg->gmac[1].credit_config[bkt];
+               total_credits += cfg->dma.credit_config[bkt];
+               total_credits += cfg->cmp.credit_config[bkt];
+               total_credits += cfg->sae.credit_config[bkt];
+               total_credits += cfg->xgmac[0].credit_config[bkt];
+               total_credits += cfg->xgmac[1].credit_config[bkt];
+               if (total_credits > cfg->bucket_size[bkt])
+                       pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
+                               bkt, total_credits, cfg->bucket_size[bkt]);
+       }
+       pr_info("Credit distribution complete.\n");
+}
+
+/**
+ * Configure bucket size and credits for a device. 'size' is the size of
+ * the buckets for the device. This size is distributed among all the CPUs
+ * so that all of them can send messages to the device.
+ *
+ * The device is also given 'cpu_credits' to send messages to the CPUs
+ *
+ * @dev_info: FMN information structure for each devices
+ * @start_stn_id: Starting station id of dev_info
+ * @end_stn_id: End station id of dev_info
+ * @num_buckets: Total number of buckets for den_info
+ * @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
+ * @size: Size of the each buckets in the device station
+ */
+static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
+               int end_stn_id, int num_buckets, int cpu_credits, int size)
+{
+       int i, j, num_core, n, credits_per_cpu;
+       struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
+
+       num_core = hweight32(nlm_current_node()->coremask);
+       dev_info->num_buckets   = num_buckets;
+       dev_info->start_stn_id  = start_stn_id;
+       dev_info->end_stn_id    = end_stn_id;
+
+       n = num_core;
+       if (num_core == 3)
+               n = 4;
+
+       for (i = start_stn_id; i <= end_stn_id; i++) {
+               xlr_board_fmn_config.bucket_size[i] = size;
+
+               /* Dividing device credits equally to cpus */
+               credits_per_cpu = size / n;
+               for (j = 0; j < num_core; j++)
+                       cpu[j].credit_config[i] = credits_per_cpu;
+
+               /* credits left to distribute */
+               credits_per_cpu = size - (credits_per_cpu * num_core);
+
+               /* distribute the remaining credits (if any), among cores */
+               for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
+                       cpu[j].credit_config[i] += 4;
+                       credits_per_cpu -= 4;
+               }
+       }
+
+       /* Distributing cpu per bucket credits to devices */
+       for (i = 0; i < num_core; i++) {
+               for (j = 0; j < FMN_CORE_NBUCKETS; j++)
+                       dev_info->credit_config[(i * 8) + j] = cpu_credits;
+       }
+}
+
+/*
+ * Each core has 256 slots and 8 buckets,
+ * Configure the 8 buckets each with 32 slots
+ */
+static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
+{
+       int i, j;
+
+       for (i = 0; i < num_core; i++) {
+               cpu[i].start_stn_id     = (8 * i);
+               cpu[i].end_stn_id       = (8 * i + 8);
+
+               for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
+                       xlr_board_fmn_config.bucket_size[j] = 32;
+       }
+}
+
+/**
+ * Setup the FMN details for each devices according to the device available
+ * in each variant of XLR/XLS processor
+ */
+void xlr_board_info_setup(void)
+{
+       struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
+       struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
+       struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
+       struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
+       struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
+       struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
+       int processor_id, num_core;
+
+       num_core = hweight32(nlm_current_node()->coremask);
+       processor_id = read_c0_prid() & 0xff00;
+
+       setup_cpu_fmninfo(cpu, num_core);
+       switch (processor_id) {
+       case PRID_IMP_NETLOGIC_XLS104:
+       case PRID_IMP_NETLOGIC_XLS108:
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 16, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 8, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 8, 128);
+               break;
+
+       case PRID_IMP_NETLOGIC_XLS204:
+       case PRID_IMP_NETLOGIC_XLS208:
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 16, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 8, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 8, 128);
+               break;
+
+       case PRID_IMP_NETLOGIC_XLS404:
+       case PRID_IMP_NETLOGIC_XLS408:
+       case PRID_IMP_NETLOGIC_XLS404B:
+       case PRID_IMP_NETLOGIC_XLS408B:
+       case PRID_IMP_NETLOGIC_XLS416B:
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 8, 32);
+               setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
+                                       FMN_STNID_GMAC1_TX3, 8, 8, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 4, 64);
+               setup_fmn_cc(cmp, FMN_STNID_CMP_0,
+                                       FMN_STNID_CMP_3, 4, 4, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 8, 128);
+               break;
+
+       case PRID_IMP_NETLOGIC_XLS412B:
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 8, 32);
+               setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
+                                       FMN_STNID_GMAC1_TX3, 8, 8, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 4, 64);
+               setup_fmn_cc(cmp, FMN_STNID_CMP_0,
+                                       FMN_STNID_CMP_3, 4, 4, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 8, 128);
+               break;
+
+       case PRID_IMP_NETLOGIC_XLR308:
+       case PRID_IMP_NETLOGIC_XLR308C:
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 16, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 8, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 4, 128);
+               break;
+
+       case PRID_IMP_NETLOGIC_XLR532:
+       case PRID_IMP_NETLOGIC_XLR532C:
+       case PRID_IMP_NETLOGIC_XLR516C:
+       case PRID_IMP_NETLOGIC_XLR508C:
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 16, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 8, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 4, 128);
+               break;
+
+       case PRID_IMP_NETLOGIC_XLR732:
+       case PRID_IMP_NETLOGIC_XLR716:
+               setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
+                                       FMN_STNID_XMAC0_15_TX, 8, 0, 32);
+               setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
+                                       FMN_STNID_XMAC1_15_TX, 8, 0, 32);
+               setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+                                       FMN_STNID_GMAC0_TX3, 8, 24, 32);
+               setup_fmn_cc(dma, FMN_STNID_DMA_0,
+                                       FMN_STNID_DMA_3, 4, 4, 64);
+               setup_fmn_cc(sae, FMN_STNID_SEC0,
+                                       FMN_STNID_SEC1, 2, 4, 128);
+               break;
+       default:
+               pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
+               pr_err("Error: Cannot initialize FMN credits.\n");
+       }
+
+       check_credit_distribution();
+
+#if 0 /* debug */
+       print_credit_config(&cpu[0]);
+       print_credit_config(&gmac[0]);
+#endif
+}
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
new file mode 100644 (file)
index 0000000..4d74f03
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irqreturn.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mipsregs.h>
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/xlr/fmn.h>
+#include <asm/netlogic/common.h>
+
+#define COP2_CC_INIT_CPU_DEST(dest, conf) \
+do { \
+       nlm_write_c2_cc##dest(0, conf[(dest * 8) + 0]); \
+       nlm_write_c2_cc##dest(1, conf[(dest * 8) + 1]); \
+       nlm_write_c2_cc##dest(2, conf[(dest * 8) + 2]); \
+       nlm_write_c2_cc##dest(3, conf[(dest * 8) + 3]); \
+       nlm_write_c2_cc##dest(4, conf[(dest * 8) + 4]); \
+       nlm_write_c2_cc##dest(5, conf[(dest * 8) + 5]); \
+       nlm_write_c2_cc##dest(6, conf[(dest * 8) + 6]); \
+       nlm_write_c2_cc##dest(7, conf[(dest * 8) + 7]); \
+} while (0)
+
+struct fmn_message_handler {
+       void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *);
+       void *arg;
+} msg_handlers[128];
+
+/*
+ * FMN interrupt handler. We configure the FMN so that any messages in
+ * any of the CPU buckets will trigger an interrupt on the CPU.
+ * The message can be from any device on the FMN (like NAE/SAE/DMA).
+ * The source station id is used to figure out which of the registered
+ * handlers have to be called.
+ */
+static irqreturn_t fmn_message_handler(int irq, void *data)
+{
+       struct fmn_message_handler *hndlr;
+       int bucket, rv;
+       int size = 0, code = 0, src_stnid = 0;
+       struct nlm_fmn_msg msg;
+       uint32_t mflags, bkt_status;
+
+       mflags = nlm_cop2_enable();
+       /* Disable message ring interrupt */
+       nlm_fmn_setup_intr(irq, 0);
+       while (1) {
+               /* 8 bkts per core, [24:31] each bit represents one bucket
+                * Bit is Zero if bucket is not empty */
+               bkt_status = (nlm_read_c2_status() >> 24) & 0xff;
+               if (bkt_status == 0xff)
+                       break;
+               for (bucket = 0; bucket < 8; bucket++) {
+                       /* Continue on empty bucket */
+                       if (bkt_status & (1 << bucket))
+                               continue;
+                       rv = nlm_fmn_receive(bucket, &size, &code, &src_stnid,
+                                               &msg);
+                       if (rv != 0)
+                               continue;
+
+                       hndlr = &msg_handlers[src_stnid];
+                       if (hndlr->action == NULL)
+                               pr_warn("No msgring handler for stnid %d\n",
+                                               src_stnid);
+                       else {
+                               nlm_cop2_restore(mflags);
+                               hndlr->action(bucket, src_stnid, size, code,
+                                       &msg, hndlr->arg);
+                               mflags = nlm_cop2_enable();
+                       }
+               }
+       };
+       /* Enable message ring intr, to any thread in core */
+       nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
+       nlm_cop2_restore(mflags);
+       return IRQ_HANDLED;
+}
+
+struct irqaction fmn_irqaction = {
+       .handler = fmn_message_handler,
+       .flags = IRQF_PERCPU,
+       .name = "fmn",
+};
+
+void xlr_percpu_fmn_init(void)
+{
+       struct xlr_fmn_info *cpu_fmn_info;
+       int *bucket_sizes;
+       uint32_t flags;
+       int id;
+
+       BUG_ON(nlm_thread_id() != 0);
+       id = nlm_core_id();
+
+       bucket_sizes = xlr_board_fmn_config.bucket_size;
+       cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
+       flags = nlm_cop2_enable();
+
+       /* Setup bucket sizes for the core. */
+       nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
+       nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
+       nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
+       nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
+       nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
+       nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
+       nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
+       nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
+
+       /*
+        * For sending FMN messages, we need credits on the destination
+        * bucket. Program the credits this core has on the 128 possible
+        * destination buckets.
+        * We cannot use a loop here, because the the first argument has
+        * to be a constant integer value.
+        */
+       COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
+       COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
+
+       /* enable FMN interrupts on this CPU */
+       nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
+       nlm_cop2_restore(flags);
+}
+
+
+/*
+ * Register a FMN message handler with respect to the source station id
+ * @stnid: source station id
+ * @action: Handler function pointer
+ */
+int nlm_register_fmn_handler(int start_stnid, int end_stnid,
+       void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
+       void *arg)
+{
+       int sstnid;
+
+       for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
+               msg_handlers[sstnid].arg = arg;
+               smp_wmb();
+               msg_handlers[sstnid].action = action;
+       }
+       pr_debug("Registered FMN msg handler for stnid %d-%d\n",
+                       start_stnid, end_stnid);
+       return 0;
+}
+
+void nlm_setup_fmn_irq(void)
+{
+       uint32_t flags;
+
+       /* setup irq only once */
+       setup_irq(IRQ_FMN, &fmn_irqaction);
+
+       flags = nlm_cop2_enable();
+       nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
+       nlm_cop2_restore(flags);
+}
index 81b1d311834f521bbd9c1b15d2bf7dbed1568011..4e7f49d3d5a8105c45dd09a6b86999ed0506a7d7 100644 (file)
 #include <asm/netlogic/xlr/iomap.h>
 #include <asm/netlogic/xlr/pic.h>
 #include <asm/netlogic/xlr/gpio.h>
+#include <asm/netlogic/xlr/fmn.h>
 
 uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
-uint64_t nlm_pic_base;
 struct psb_info nlm_prom_info;
 
-unsigned long nlm_common_ebase = 0x0;
-
 /* default to uniprocessor */
-uint32_t nlm_coremask = 1, nlm_cpumask  = 1;
-int  nlm_threads_per_core = 1;
+unsigned int  nlm_threads_per_core = 1;
+struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+cpumask_t nlm_cpumask = CPU_MASK_CPU0;
 
 static void __init nlm_early_serial_setup(void)
 {
@@ -113,6 +112,12 @@ void __init prom_free_prom_memory(void)
        /* Nothing yet */
 }
 
+void nlm_percpu_init(int hwcpuid)
+{
+       if (hwcpuid % 4 == 0)
+               xlr_percpu_fmn_init();
+}
+
 static void __init build_arcs_cmdline(int *argv)
 {
        int i, remain, len;
@@ -176,9 +181,19 @@ static void prom_add_memory(void)
        }
 }
 
+static void nlm_init_node(void)
+{
+       struct nlm_soc_info *nodep;
+
+       nodep = nlm_current_node();
+       nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
+       nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+       spin_lock_init(&nodep->piclock);
+}
+
 void __init prom_init(void)
 {
-       int *argv, *envp;               /* passed as 32 bit ptrs */
+       int i, *argv, *envp;            /* passed as 32 bit ptrs */
        struct psb_info *prom_infop;
 
        /* truncate to 32 bit and sign extend all args */
@@ -187,15 +202,19 @@ void __init prom_init(void)
        prom_infop = (struct psb_info *)(long)(int)fw_arg3;
 
        nlm_prom_info = *prom_infop;
-       nlm_pic_base = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
+       nlm_init_node();
 
        nlm_early_serial_setup();
        build_arcs_cmdline(argv);
-       nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
        prom_add_memory();
 
 #ifdef CONFIG_SMP
-       nlm_wakeup_secondary_cpus(nlm_prom_info.online_cpu_map);
+       for (i = 0; i < 32; i++)
+               if (nlm_prom_info.online_cpu_map & (1 << i))
+                       cpumask_set_cpu(i, &nlm_cpumask);
+       nlm_wakeup_secondary_cpus();
        register_smp_ops(&nlm_smp_ops);
 #endif
+       xlr_board_info_setup();
+       xlr_percpu_fmn_init();
 }
index db5d987d488182cc9964e244e8a4ef1a645aed6a..3ebf7411d67b1280cc77ee857b287f32c92c6612 100644 (file)
@@ -33,6 +33,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/threads.h>
 
 #include <asm/asm.h>
 
 int __cpuinit xlr_wakeup_secondary_cpus(void)
 {
-       unsigned int i, boot_cpu;
+       struct nlm_soc_info *nodep;
+       unsigned int i, j, boot_cpu;
 
        /*
         *  In case of RMI boot, hit with NMI to get the cores
         *  from bootloader to linux code.
         */
+       nodep = nlm_get_node(0);
        boot_cpu = hard_smp_processor_id();
        nlm_set_nmi_handler(nlm_rmiboot_preboot);
        for (i = 0; i < NR_CPUS; i++) {
-               if (i == boot_cpu || (nlm_cpumask & (1u << i)) == 0)
+               if (i == boot_cpu || !cpumask_test_cpu(i, &nlm_cpumask))
                        continue;
-               nlm_pic_send_ipi(nlm_pic_base, i, 1, 1); /* send NMI */
+               nlm_pic_send_ipi(nodep->picbase, i, 1, 1); /* send NMI */
+       }
+
+       /* Fill up the coremask early */
+       nodep->coremask = 1;
+       for (i = 1; i < NLM_CORES_PER_NODE; i++) {
+               for (j = 1000000; j > 0; j--) {
+                       if (nlm_cpu_ready[i * NLM_THREADS_PER_CORE])
+                               break;
+                       udelay(10);
+               }
+               if (j != 0)
+                       nodep->coremask |= (1u << i);
+               else
+                       pr_err("Failed to wakeup core %d\n", i);
        }
 
        return 0;
index 1208c280f77dbb0cc2596890dbccab3f1c45c3e0..9c0a6782c091dcc903f3728b21efc2d712c9c67e 100644 (file)
@@ -12,5 +12,5 @@ oprofile-$(CONFIG_CPU_MIPS32)         += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_MIPS64)          += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_R10000)          += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_SB1)             += op_model_mipsxx.o
-oprofile-$(CONFIG_CPU_RM9000)          += op_model_rm9000.o
+oprofile-$(CONFIG_CPU_XLR)             += op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_LOONGSON2)       += op_model_loongson2.o
index f80480a5a0328b3a79d45950c2679577d0345e4a..e32db1ff02c7ee4020f7d5e1c199f966bfc585ed 100644 (file)
@@ -16,7 +16,6 @@
 #include "op_impl.h"
 
 extern struct op_mips_model op_model_mipsxx_ops __weak;
-extern struct op_mips_model op_model_rm9000_ops __weak;
 extern struct op_mips_model op_model_loongson2_ops __weak;
 
 static struct op_mips_model *model;
@@ -91,12 +90,10 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        case CPU_R10000:
        case CPU_R12000:
        case CPU_R14000:
+       case CPU_XLR:
                lmodel = &op_model_mipsxx_ops;
                break;
 
-       case CPU_RM9000:
-               lmodel = &op_model_rm9000_ops;
-               break;
        case CPU_LOONGSON2:
                lmodel = &op_model_loongson2_ops;
                break;
index 28ea1a4cc576c0bb8e566a63a7d4d0caf9221692..786254630403ab62e02dde6197038f3b976cc9e4 100644 (file)
 
 #define M_COUNTER_OVERFLOW             (1UL      << 31)
 
+/* Netlogic XLR specific, count events in all threads in a core */
+#define M_PERFCTL_COUNT_ALL_THREADS    (1UL      << 13)
+
 static int (*save_perf_irq)(void);
 
+/*
+ * XLR has only one set of counters per core. Designate the
+ * first hardware thread in the core for setup and init.
+ * Skip CPUs with non-zero hardware thread id (4 hwt per core)
+ */
+#ifdef CONFIG_CPU_XLR
+#define oprofile_skip_cpu(c)   ((cpu_logical_map(c) & 0x3) != 0)
+#else
+#define oprofile_skip_cpu(c)   0
+#endif
+
 #ifdef CONFIG_MIPS_MT_SMP
 static int cpu_has_mipsmt_pertccounters;
 #define WHAT           (M_TC_EN_VPE | \
@@ -152,6 +166,8 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
                        reg.control[i] |= M_PERFCTL_USER;
                if (ctr[i].exl)
                        reg.control[i] |= M_PERFCTL_EXL;
+               if (current_cpu_type() == CPU_XLR)
+                       reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
                reg.counter[i] = 0x80000000 - ctr[i].count;
        }
 }
@@ -162,6 +178,9 @@ static void mipsxx_cpu_setup(void *args)
 {
        unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+       if (oprofile_skip_cpu(smp_processor_id()))
+               return;
+
        switch (counters) {
        case 4:
                w_c0_perfctrl3(0);
@@ -183,6 +202,9 @@ static void mipsxx_cpu_start(void *args)
 {
        unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+       if (oprofile_skip_cpu(smp_processor_id()))
+               return;
+
        switch (counters) {
        case 4:
                w_c0_perfctrl3(WHAT | reg.control[3]);
@@ -200,6 +222,9 @@ static void mipsxx_cpu_stop(void *args)
 {
        unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+       if (oprofile_skip_cpu(smp_processor_id()))
+               return;
+
        switch (counters) {
        case 4:
                w_c0_perfctrl3(0);
@@ -372,6 +397,10 @@ static int __init mipsxx_init(void)
                op_model_mipsxx_ops.cpu_type = "mips/loongson1";
                break;
 
+       case CPU_XLR:
+               op_model_mipsxx_ops.cpu_type = "mips/xlr";
+               break;
+
        default:
                printk(KERN_ERR "Profiling unsupported for this CPU\n");
 
diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c
deleted file mode 100644 (file)
index 3aa8138..0000000
+++ /dev/null
@@ -1,138 +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) 2004 by Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/oprofile.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-
-#include "op_impl.h"
-
-#define RM9K_COUNTER1_EVENT(event)     ((event) << 0)
-#define RM9K_COUNTER1_SUPERVISOR       (1ULL    <<  7)
-#define RM9K_COUNTER1_KERNEL           (1ULL    <<  8)
-#define RM9K_COUNTER1_USER             (1ULL    <<  9)
-#define RM9K_COUNTER1_ENABLE           (1ULL    << 10)
-#define RM9K_COUNTER1_OVERFLOW         (1ULL    << 15)
-
-#define RM9K_COUNTER2_EVENT(event)     ((event) << 16)
-#define RM9K_COUNTER2_SUPERVISOR       (1ULL    << 23)
-#define RM9K_COUNTER2_KERNEL           (1ULL    << 24)
-#define RM9K_COUNTER2_USER             (1ULL    << 25)
-#define RM9K_COUNTER2_ENABLE           (1ULL    << 26)
-#define RM9K_COUNTER2_OVERFLOW         (1ULL    << 31)
-
-extern unsigned int rm9000_perfcount_irq;
-
-static struct rm9k_register_config {
-       unsigned int control;
-       unsigned int reset_counter1;
-       unsigned int reset_counter2;
-} reg;
-
-/* Compute all of the registers in preparation for enabling profiling.  */
-
-static void rm9000_reg_setup(struct op_counter_config *ctr)
-{
-       unsigned int control = 0;
-
-       /* Compute the performance counter control word.  */
-       /* For now count kernel and user mode */
-       if (ctr[0].enabled)
-               control |= RM9K_COUNTER1_EVENT(ctr[0].event) |
-                          RM9K_COUNTER1_KERNEL |
-                          RM9K_COUNTER1_USER |
-                          RM9K_COUNTER1_ENABLE;
-       if (ctr[1].enabled)
-               control |= RM9K_COUNTER2_EVENT(ctr[1].event) |
-                          RM9K_COUNTER2_KERNEL |
-                          RM9K_COUNTER2_USER |
-                          RM9K_COUNTER2_ENABLE;
-       reg.control = control;
-
-       reg.reset_counter1 = 0x80000000 - ctr[0].count;
-       reg.reset_counter2 = 0x80000000 - ctr[1].count;
-}
-
-/* Program all of the registers in preparation for enabling profiling.  */
-
-static void rm9000_cpu_setup(void *args)
-{
-       uint64_t perfcount;
-
-       perfcount = ((uint64_t) reg.reset_counter2 << 32) | reg.reset_counter1;
-       write_c0_perfcount(perfcount);
-}
-
-static void rm9000_cpu_start(void *args)
-{
-       /* Start all counters on current CPU */
-       write_c0_perfcontrol(reg.control);
-}
-
-static void rm9000_cpu_stop(void *args)
-{
-       /* Stop all counters on current CPU */
-       write_c0_perfcontrol(0);
-}
-
-static irqreturn_t rm9000_perfcount_handler(int irq, void *dev_id)
-{
-       unsigned int control = read_c0_perfcontrol();
-       struct pt_regs *regs = get_irq_regs();
-       uint32_t counter1, counter2;
-       uint64_t counters;
-
-       /*
-        * RM9000 combines two 32-bit performance counters into a single
-        * 64-bit coprocessor zero register.  To avoid a race updating the
-        * registers we need to stop the counters while we're messing with
-        * them ...
-        */
-       write_c0_perfcontrol(0);
-
-       counters = read_c0_perfcount();
-       counter1 = counters;
-       counter2 = counters >> 32;
-
-       if (control & RM9K_COUNTER1_OVERFLOW) {
-               oprofile_add_sample(regs, 0);
-               counter1 = reg.reset_counter1;
-       }
-       if (control & RM9K_COUNTER2_OVERFLOW) {
-               oprofile_add_sample(regs, 1);
-               counter2 = reg.reset_counter2;
-       }
-
-       counters = ((uint64_t)counter2 << 32) | counter1;
-       write_c0_perfcount(counters);
-       write_c0_perfcontrol(reg.control);
-
-       return IRQ_HANDLED;
-}
-
-static int __init rm9000_init(void)
-{
-       return request_irq(rm9000_perfcount_irq, rm9000_perfcount_handler,
-                          0, "Perfcounter", NULL);
-}
-
-static void rm9000_exit(void)
-{
-       free_irq(rm9000_perfcount_irq, NULL);
-}
-
-struct op_mips_model op_model_rm9000_ops = {
-       .reg_setup      = rm9000_reg_setup,
-       .cpu_setup      = rm9000_cpu_setup,
-       .init           = rm9000_init,
-       .exit           = rm9000_exit,
-       .cpu_start      = rm9000_cpu_start,
-       .cpu_stop       = rm9000_cpu_stop,
-       .cpu_type       = "mips/rm9000",
-       .num_counters   = 2
-};
index e13a71cbc3c7550d5f9980f59ad1afe5d684dd27..ce995d3d94407a8a7894a263ff7a28826b8d3ea9 100644 (file)
@@ -34,8 +34,6 @@ obj-$(CONFIG_MIPS_MALTA)      += fixup-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)   += fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o
-obj-$(CONFIG_PMC_YOSEMITE)     += fixup-yosemite.o ops-titan.o ops-titan-ht.o \
-                                  pci-yosemite.o
 obj-$(CONFIG_SGI_IP27)         += ops-bridge.o pci-ip27.o
 obj-$(CONFIG_SGI_IP32)         += fixup-ip32.o ops-mace.o pci-ip32.o
 obj-$(CONFIG_SIBYTE_SB1250)    += fixup-sb1250.o pci-sb1250.o
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
deleted file mode 100644 (file)
index fdafb13..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-       if (pin == 0)
-               return -1;
-
-       return 3;                       /* Everything goes to one irq bit */
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       return 0;
-}
index b46b3e211775932038d1b82ddf0bb9b3594aaf7b..438319465cb4cb60ca2aaed250f6c5e605e03198 100644 (file)
@@ -56,7 +56,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to look at it for real ...
         */
        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
@@ -76,7 +76,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
 oh_my_gawd:
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to look at the wrong register.
         */
        if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
@@ -85,7 +85,7 @@ oh_my_gawd:
        }
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * IOC3 is fucking fucked beyond belief ...  Don't try to access
         * anything but 32-bit words ...
         */
        addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
@@ -118,7 +118,7 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to look at it for real ...
         */
        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
@@ -139,7 +139,7 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
 oh_my_gawd:
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to look at the wrong register.
         */
        if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
@@ -148,7 +148,7 @@ oh_my_gawd:
        }
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * IOC3 is fucking fucked beyond belief ...  Don't try to access
         * anything but 32-bit words ...
         */
        bridge->b_pci_cfg = (busno << 16) | (slot << 11);
@@ -189,7 +189,7 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to look at it for real ...
         */
        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
@@ -213,14 +213,14 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
 oh_my_gawd:
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to touch the wrong register.
         */
        if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
                return PCIBIOS_SUCCESSFUL;
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * IOC3 is fucking fucked beyond belief ...  Don't try to access
         * anything but 32-bit words ...
         */
        addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
@@ -257,7 +257,7 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to look at it for real ...
         */
        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
@@ -281,14 +281,14 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
 oh_my_gawd:
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * IOC3 is fucking fucked beyond belief ...  Don't even give the
         * generic PCI code a chance to touch the wrong register.
         */
        if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
                return PCIBIOS_SUCCESSFUL;
 
        /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * IOC3 is fucking fucked beyond belief ...  Don't try to access
         * anything but 32-bit words ...
         */
        addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
diff --git a/arch/mips/pci/ops-titan-ht.c b/arch/mips/pci/ops-titan-ht.c
deleted file mode 100644 (file)
index 57d54ad..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2003 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-
-#include <asm/titan_dep.h>
-
-static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn,
-       int offset, u32 *val)
-{
-       volatile uint32_t address;
-       int busno;
-
-       busno = bus->number;
-
-       address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000;
-       if (busno != 0)
-               address |= 1;
-
-       /*
-        * RM9000 HT Errata: Issue back to back HT config
-        * transcations. Issue a BIU sync before and
-        * after the HT cycle
-        */
-
-       *(volatile int32_t *) 0xfb0000f0 |= 0x2;
-
-       udelay(30);
-
-       *(volatile int32_t *) 0xfb0006f8 = address;
-       *(val) = *(volatile int32_t *) 0xfb0006fc;
-
-       udelay(30);
-
-       * (volatile int32_t *) 0xfb0000f0 |= 0x2;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int titan_ht_config_read(struct pci_bus *bus, unsigned int devfn,
-       int offset, int size, u32 *val)
-{
-       uint32_t dword;
-
-       titan_ht_config_read_dword(bus, devfn, offset, &dword);
-
-       dword >>= ((offset & 3) << 3);
-       dword &= (0xffffffffU >> ((4 - size) << 8));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static inline int titan_ht_config_write_dword(struct pci_bus *bus,
-       unsigned int devfn, int offset, u32 val)
-{
-       volatile uint32_t address;
-       int busno;
-
-       busno = bus->number;
-
-       address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000;
-       if (busno != 0)
-               address |= 1;
-
-       *(volatile int32_t *) 0xfb0000f0 |= 0x2;
-
-       udelay(30);
-
-       *(volatile int32_t *) 0xfb0006f8 = address;
-       *(volatile int32_t *) 0xfb0006fc = val;
-
-       udelay(30);
-
-       *(volatile int32_t *) 0xfb0000f0 |= 0x2;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int titan_ht_config_write(struct pci_bus *bus, unsigned int devfn,
-       int offset, int size, u32 val)
-{
-       uint32_t val1, val2, mask;
-
-       titan_ht_config_read_dword(bus, devfn, offset, &val2);
-
-       val1 = val << ((offset & 3) << 3);
-       mask = ~(0xffffffffU >> ((4 - size) << 8));
-       val2 &= ~(mask << ((offset & 3) << 8));
-
-       titan_ht_config_write_dword(bus, devfn, offset, val1 | val2);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops titan_ht_pci_ops = {
-       .read   = titan_ht_config_read,
-       .write  = titan_ht_config_write,
-};
diff --git a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c
deleted file mode 100644 (file)
index ebf8fc4..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2003 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-
-#include <asm/pci.h>
-#include <asm/io.h>
-#include <asm/rm9k-ocd.h>
-
-/*
- * PCI specific defines
- */
-#define        TITAN_PCI_0_CONFIG_ADDRESS      0x780
-#define        TITAN_PCI_0_CONFIG_DATA         0x784
-
-/*
- * Titan PCI Config Read Byte
- */
-static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
-       int size, u32 * val)
-{
-       uint32_t address, tmp;
-       int dev, busno, func;
-
-       busno = bus->number;
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       address = (busno << 16) | (dev << 11) | (func << 8) |
-                 (reg & 0xfc) | 0x80000000;
-
-
-       /* start the configuration cycle */
-       ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS);
-       tmp = ocd_readl(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3);
-
-       switch (size) {
-       case 1:
-               tmp &= 0xff;
-       case 2:
-               tmp &= 0xffff;
-       }
-       *val = tmp;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg,
-       int size, u32 val)
-{
-       uint32_t address;
-       int dev, busno, func;
-
-       busno = bus->number;
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       address = (busno << 16) | (dev << 11) | (func << 8) |
-               (reg & 0xfc) | 0x80000000;
-
-       /* start the configuration cycle */
-       ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS);
-
-       /* write the data */
-       switch (size) {
-       case 1:
-               ocd_writeb(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3));
-               break;
-
-       case 2:
-               ocd_writew(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2));
-               break;
-
-       case 4:
-               ocd_writel(val, TITAN_PCI_0_CONFIG_DATA);
-               break;
-       }
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-/*
- * Titan PCI structure
- */
-struct pci_ops titan_pci_ops = {
-       titan_read_config,
-       titan_write_config,
-};
index 8a48139d219cc2c8918f3f5597333683c3e0ea65..ca179b6ff39b374e0743f76815775972e29e15c0 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <asm/bootinfo.h>
 
+#include <bcm63xx_reset.h>
+
 #include "pci-bcm63xx.h"
 
 /*
@@ -119,41 +122,36 @@ static void __init bcm63xx_reset_pcie(void)
 {
        u32 val;
 
-       /* enable clock */
-       val = bcm_perf_readl(PERF_CKCTL_REG);
-       val |= CKCTL_6328_PCIE_EN;
-       bcm_perf_writel(val, PERF_CKCTL_REG);
-
        /* enable SERDES */
        val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
        val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
        bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
 
        /* reset the PCIe core */
-       val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
-
-       val &= ~SOFTRESET_6328_PCIE_MASK;
-       val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
-       val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
-       val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
-       bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
+       bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
+       bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
        mdelay(10);
 
-       val |= SOFTRESET_6328_PCIE_MASK;
-       val |= SOFTRESET_6328_PCIE_CORE_MASK;
-       val |= SOFTRESET_6328_PCIE_HARD_MASK;
-       bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
+       bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
        mdelay(10);
 
-       val |= SOFTRESET_6328_PCIE_EXT_MASK;
-       bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
+       bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0);
        mdelay(200);
 }
 
+static struct clk *pcie_clk;
+
 static int __init bcm63xx_register_pcie(void)
 {
        u32 val;
 
+       /* enable clock */
+       pcie_clk = clk_get(NULL, "pcie");
+       if (IS_ERR_OR_NULL(pcie_clk))
+               return -ENODEV;
+
+       clk_prepare_enable(pcie_clk);
+
        bcm63xx_reset_pcie();
 
        /* configure the PCIe bridge */
index 4b0c347d7a8241d1279a11efc84c873ee2a85650..5b5ed76c6f47a811676e5026f0c1b2843482005b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 #include <linux/swiotlb.h>
 
 #include <asm/time.h>
@@ -704,6 +705,10 @@ static int __init octeon_pci_setup(void)
         */
        cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1);
 
+       if (IS_ERR(platform_device_register_simple("octeon_pci_edac",
+                                                  -1, NULL, 0)))
+               pr_err("Registation of co_pci_edac failed!\n");
+
        octeon_pci_dma_init();
 
        return 0;
index 18af021d289ac83f5930098d20b9d880ae680780..0c18ccc79623d7d6cefe35b03a7ba36c232d1c8b 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <asm/netlogic/interrupt.h>
 #include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/common.h>
 
 #include <asm/netlogic/xlr/msidef.h>
 #include <asm/netlogic/xlr/iomap.h>
@@ -174,22 +175,9 @@ static struct pci_dev *xls_get_pcie_link(const struct pci_dev *dev)
        return p ? bus->self : NULL;
 }
 
-static int get_irq_vector(const struct pci_dev *dev)
+static int nlm_pci_link_to_irq(int link)
 {
-       struct pci_dev *lnk;
-
-       if (!nlm_chip_is_xls())
-               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ */
-
-       /*
-        * For XLS PCIe, there is an IRQ per Link, find out which
-        * link the device is on to assign interrupts
-        */
-       lnk = xls_get_pcie_link(dev);
-       if (lnk == NULL)
-               return 0;
-
-       switch  (PCI_SLOT(lnk->devfn)) {
+       switch  (link) {
        case 0:
                return PIC_PCIE_LINK0_IRQ;
        case 1:
@@ -205,10 +193,26 @@ static int get_irq_vector(const struct pci_dev *dev)
                else
                        return PIC_PCIE_LINK3_IRQ;
        }
-       WARN(1, "Unexpected devfn %d\n", lnk->devfn);
+       WARN(1, "Unexpected link %d\n", link);
        return 0;
 }
 
+static int get_irq_vector(const struct pci_dev *dev)
+{
+       struct pci_dev *lnk;
+       int link;
+
+       if (!nlm_chip_is_xls())
+               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ */
+
+       lnk = xls_get_pcie_link(dev);
+       if (lnk == NULL)
+               return 0;
+
+       link = PCI_SLOT(lnk->devfn);
+       return nlm_pci_link_to_irq(link);
+}
+
 #ifdef CONFIG_PCI_MSI
 void destroy_irq(unsigned int irq)
 {
@@ -332,6 +336,9 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 
 static int __init pcibios_init(void)
 {
+       void (*extra_ack)(struct irq_data *);
+       int link, irq;
+
        /* PSB assigns PCI resources */
        pci_set_flags(PCI_PROBE_ONLY);
        pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20);
@@ -350,27 +357,19 @@ static int __init pcibios_init(void)
         * For PCI interrupts, we need to ack the PCI controller too, overload
         * irq handler data to do this
         */
-       if (nlm_chip_is_xls()) {
-               if (nlm_chip_is_xls_b()) {
-                       irq_set_handler_data(PIC_PCIE_LINK0_IRQ,
-                                                       xls_pcie_ack_b);
-                       irq_set_handler_data(PIC_PCIE_LINK1_IRQ,
-                                                       xls_pcie_ack_b);
-                       irq_set_handler_data(PIC_PCIE_XLSB0_LINK2_IRQ,
-                                                       xls_pcie_ack_b);
-                       irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ,
-                                                       xls_pcie_ack_b);
-               } else {
-                       irq_set_handler_data(PIC_PCIE_LINK0_IRQ, xls_pcie_ack);
-                       irq_set_handler_data(PIC_PCIE_LINK1_IRQ, xls_pcie_ack);
-                       irq_set_handler_data(PIC_PCIE_LINK2_IRQ, xls_pcie_ack);
-                       irq_set_handler_data(PIC_PCIE_LINK3_IRQ, xls_pcie_ack);
-               }
-       } else {
+       if (!nlm_chip_is_xls()) {
                /* XLR PCI controller ACK */
-               irq_set_handler_data(PIC_PCIX_IRQ, xlr_pci_ack);
+               nlm_set_pic_extra_ack(0, PIC_PCIX_IRQ, xlr_pci_ack);
+       } else {
+               if  (nlm_chip_is_xls_b())
+                       extra_ack = xls_pcie_ack_b;
+               else
+                       extra_ack = xls_pcie_ack;
+               for (link = 0; link < 4; link++) {
+                       irq = nlm_pci_link_to_irq(link);
+                       nlm_set_pic_extra_ack(0, irq, extra_ack);
+               }
        }
-
        return 0;
 }
 
diff --git a/arch/mips/pci/pci-yosemite.c b/arch/mips/pci/pci-yosemite.c
deleted file mode 100644 (file)
index cf5e1a2..0000000
+++ /dev/null
@@ -1,67 +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) 2004 by Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <asm/titan_dep.h>
-
-extern struct pci_ops titan_pci_ops;
-
-static struct resource py_mem_resource = {
-       .start  = 0xe0000000UL,
-       .end    = 0xe3ffffffUL,
-       .name   = "Titan PCI MEM",
-       .flags  = IORESOURCE_MEM
-};
-
-/*
- * PMON really reserves 16MB of I/O port space but that's stupid, nothing
- * needs that much since allocations are limited to 256 bytes per device
- * anyway.  So we just claim 64kB here.
- */
-#define TITAN_IO_SIZE  0x0000ffffUL
-#define TITAN_IO_BASE  0xe8000000UL
-
-static struct resource py_io_resource = {
-       .start  = 0x00001000UL,
-       .end    = TITAN_IO_SIZE - 1,
-       .name   = "Titan IO MEM",
-       .flags  = IORESOURCE_IO,
-};
-
-static struct pci_controller py_controller = {
-       .pci_ops        = &titan_pci_ops,
-       .mem_resource   = &py_mem_resource,
-       .mem_offset     = 0x00000000UL,
-       .io_resource    = &py_io_resource,
-       .io_offset      = 0x00000000UL
-};
-
-static char ioremap_failed[] __initdata = "Could not ioremap I/O port range";
-
-static int __init pmc_yosemite_setup(void)
-{
-       unsigned long io_v_base;
-
-       io_v_base = (unsigned long) ioremap(TITAN_IO_BASE, TITAN_IO_SIZE);
-       if (!io_v_base)
-               panic(ioremap_failed);
-
-       set_io_port_base(io_v_base);
-       py_controller.io_map_base = io_v_base;
-       TITAN_WRITE(RM9000x2_OCD_LKM7, TITAN_READ(RM9000x2_OCD_LKM7) | 1);
-
-       ioport_resource.end = TITAN_IO_SIZE - 1;
-
-       register_pci_controller(&py_controller);
-
-       return 0;
-}
-
-arch_initcall(pmc_yosemite_setup);
index bbd76082fa8c497454193557b56ec195a514b317..3482b8c8640cfa5f5c7dcd8ef7255ad60e240bcd 100644 (file)
@@ -34,10 +34,6 @@ config PMC_MSP7120_FPGA
 
 endchoice
 
-config HYPERTRANSPORT
-       bool "Hypertransport Support for PMC-Sierra Yosemite"
-       depends on PMC_YOSEMITE
-
 config MSP_HAS_USB
        boolean
        depends on PMC_MSP
index f092f2524c5f2b8605d653f854b339adc4b417ad..387fda6c28c69e085851bd4c7566b7be0894e508 100644 (file)
@@ -5,10 +5,3 @@ platform-$(CONFIG_PMC_MSP)     += pmc-sierra/msp71xx/
 cflags-$(CONFIG_PMC_MSP)       += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \
                                        -mno-branch-likely
 load-$(CONFIG_PMC_MSP)         += 0xffffffff80100000
-
-#
-# PMC-Sierra Yosemite
-#
-platform-$(CONFIG_PMC_YOSEMITE)        += pmc-sierra/yosemite/
-cflags-$(CONFIG_PMC_YOSEMITE)  += -I$(srctree)/arch/mips/include/asm/mach-yosemite
-load-$(CONFIG_PMC_YOSEMITE)    += 0xffffffff80100000
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
deleted file mode 100644 (file)
index 5af95ec..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the PMC-Sierra Titan
-#
-
-obj-y    += irq.o prom.o py-console.o setup.o
-
-obj-$(CONFIG_SMP)              += smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
deleted file mode 100644 (file)
index d6f8bdf..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  Copyright (C) 2003 PMC-Sierra Inc.
- *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Description:
- *
- * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
- * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
- * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
- * expected to have a connectivity from the EEPROM to the serial port. This program does
- * __not__ communicate using the I2C protocol
- */
-
-#include "atmel_read_eeprom.h"
-
-static void delay(int delay)
-{
-       while (delay--);
-}
-
-static void send_bit(unsigned char bit)
-{
-       scl_lo;
-       delay(TXX);
-       if (bit)
-               sda_hi;
-       else
-               sda_lo;
-
-       delay(TXX);
-       scl_hi;
-       delay(TXX);
-}
-
-static void send_ack(void)
-{
-       send_bit(0);
-}
-
-static void send_byte(unsigned char byte)
-{
-       int     i = 0;
-
-       for (i = 7; i >= 0; i--)
-               send_bit((byte >> i) & 0x01);
-}
-
-static void send_start(void)
-{
-       sda_hi;
-       delay(TXX);
-       scl_hi;
-       delay(TXX);
-       sda_lo;
-       delay(TXX);
-}
-
-static void send_stop(void)
-{
-       sda_lo;
-       delay(TXX);
-       scl_hi;
-       delay(TXX);
-       sda_hi;
-       delay(TXX);
-}
-
-static void do_idle(void)
-{
-       sda_hi;
-       scl_hi;
-       vcc_off;
-}
-
-static int recv_bit(void)
-{
-       int     status;
-
-       scl_lo;
-       delay(TXX);
-       sda_hi;
-       delay(TXX);
-       scl_hi;
-       delay(TXX);
-
-       return 1;
-}
-
-static unsigned char recv_byte(void) {
-        int i;
-        unsigned char byte=0;
-
-        for (i=7;i>=0;i--)
-                byte |= (recv_bit() << i);
-
-        return byte;
-}
-
-static int recv_ack(void)
-{
-       unsigned int    ack;
-
-       ack = (unsigned int)recv_bit();
-       scl_lo;
-
-       if (ack) {
-               do_idle();
-               printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM\n");
-               return -1;
-       }
-
-       return ack;
-}
-
-/*
- * This function does the actual read of the EEPROM. It needs the buffer into which the
- * read data is copied, the size of the EEPROM being read and the buffer size
- */
-int read_eeprom(char *buffer, int eeprom_size, int size)
-{
-       int     i = 0, err;
-
-       send_start();
-       send_byte(W_HEADER);
-       recv_ack();
-
-       /* EEPROM with size of more than 2K need two byte addressing */
-       if (eeprom_size > 2048) {
-               send_byte(0x00);
-               recv_ack();
-       }
-
-       send_start();
-       send_byte(R_HEADER);
-       err = recv_ack();
-       if (err == -1)
-               return err;
-
-       for (i = 0; i < size; i++) {
-               *buffer++ = recv_byte();
-               send_ack();
-       }
-
-       /* Note : We should do some check if the buffer contains correct information */
-
-       send_stop();
-}
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
deleted file mode 100644 (file)
index d6c7ec4..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
- *
- *  Copyright (C) 2003 PMC-Sierra Inc.
- *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *  Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Header file for atmel_read_eeprom.c
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <asm/pci.h>
-#include <asm/io.h>
-#include <linux/init.h>
-#include <asm/termios.h>
-#include <asm/ioctls.h>
-#include <linux/ioctl.h>
-#include <linux/fcntl.h>
-
-#define        DEFAULT_PORT    "/dev/ttyS0"    /* Port to open */
-#define        TXX             0               /* Dummy loop for spinning */
-
-#define        BLOCK_SEL       0x00
-#define        SLAVE_ADDR      0xa0
-#define        READ_BIT        0x01
-#define        WRITE_BIT       0x00
-#define        R_HEADER        SLAVE_ADDR + BLOCK_SEL + READ_BIT
-#define        W_HEADER        SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
-
-/*
- * Clock, Voltages and Data
- */
-#define        vcc_off         (ioctl(fd, TIOCSBRK, 0))
-#define        vcc_on          (ioctl(fd, TIOCCBRK, 0))
-#define        sda_hi          (ioctl(fd, TIOCMBIS, &dtr))
-#define        sda_lo          (ioctl(fd, TIOCMBIC, &dtr))
-#define        scl_lo          (ioctl(fd, TIOCMBIC, &rts))
-#define        scl_hi          (ioctl(fd, TIOCMBIS, &rts))
-
-const char rts = TIOCM_RTS;
-const char dtr = TIOCM_DTR;
-int fd;
diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c
deleted file mode 100644 (file)
index 62ead66..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/pci.h>
-
-/*
- * HT Bus fixup for the Titan
- * XXX IRQ values need to change based on the board layout
- */
-void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
-{
-       /*
-        * PLX and SPKT related changes go here
-        */
-}
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
deleted file mode 100644 (file)
index 14dc9c8..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright 2003 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <asm/pci.h>
-#include <asm/io.h>
-
-#include <linux/init.h>
-#include <asm/titan_dep.h>
-
-#ifdef CONFIG_HYPERTRANSPORT
-
-
-/*
- * This function check if the Hypertransport Link Initialization completed. If
- * it did, then proceed further with scanning bus #2
- */
-static __inline__ int check_titan_htlink(void)
-{
-        u32 val;
-
-        val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
-        if (val & 0x00000020)
-                /* HT Link Initialization completed */
-                return 1;
-        else
-                return 0;
-}
-
-static int titan_ht_config_read_dword(struct pci_dev *device,
-                                             int offset, u32* val)
-{
-        int dev, bus, func;
-        uint32_t address_reg, data_reg;
-        uint32_t address;
-
-        bus = device->bus->number;
-        dev = PCI_SLOT(device->devfn);
-        func = PCI_FUNC(device->devfn);
-
-       /* XXX Need to change the Bus # */
-        if (bus > 2)
-                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
-                                                        0x80000000 | 0x1;
-        else
-                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
-
-        address_reg = RM9000x2_OCD_HTCFGA;
-        data_reg =  RM9000x2_OCD_HTCFGD;
-
-        RM9K_WRITE(address_reg, address);
-        RM9K_READ(data_reg, val);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int titan_ht_config_read_word(struct pci_dev *device,
-                                             int offset, u16* val)
-{
-        int dev, bus, func;
-        uint32_t address_reg, data_reg;
-        uint32_t address;
-
-        bus = device->bus->number;
-        dev = PCI_SLOT(device->devfn);
-        func = PCI_FUNC(device->devfn);
-
-       /* XXX Need to change the Bus # */
-        if (bus > 2)
-                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
-                                                0x80000000 | 0x1;
-        else
-                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
-
-        address_reg = RM9000x2_OCD_HTCFGA;
-        data_reg =  RM9000x2_OCD_HTCFGD;
-
-        if ((offset & 0x3) == 0)
-                offset = 0x2;
-        else
-                offset = 0x0;
-
-        RM9K_WRITE(address_reg, address);
-        RM9K_READ_16(data_reg + offset, val);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-
-u32 longswap(unsigned long l)
-{
-        unsigned char b1, b2, b3, b4;
-
-        b1 = l&255;
-        b2 = (l>>8)&255;
-        b3 = (l>>16)&255;
-        b4 = (l>>24)&255;
-
-        return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
-}
-
-
-static int titan_ht_config_read_byte(struct pci_dev *device,
-                                             int offset, u8* val)
-{
-        int dev, bus, func;
-        uint32_t address_reg, data_reg;
-        uint32_t address;
-        int offset1;
-
-        bus = device->bus->number;
-        dev = PCI_SLOT(device->devfn);
-        func = PCI_FUNC(device->devfn);
-
-       /* XXX Need to change the Bus # */
-        if (bus > 2)
-                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
-                                                        0x80000000 | 0x1;
-        else
-                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
-
-        address_reg = RM9000x2_OCD_HTCFGA;
-        data_reg =  RM9000x2_OCD_HTCFGD;
-
-        RM9K_WRITE(address_reg, address);
-
-        if ((offset & 0x3) == 0) {
-                offset1 = 0x3;
-        }
-        if ((offset & 0x3) == 1) {
-                offset1 = 0x2;
-        }
-        if ((offset & 0x3) == 2) {
-                offset1 = 0x1;
-        }
-        if ((offset & 0x3) == 3) {
-                offset1 = 0x0;
-        }
-        RM9K_READ_8(data_reg + offset1, val);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int titan_ht_config_write_dword(struct pci_dev *device,
-                                             int offset, u8 val)
-{
-        int dev, bus, func;
-        uint32_t address_reg, data_reg;
-        uint32_t address;
-
-        bus = device->bus->number;
-        dev = PCI_SLOT(device->devfn);
-        func = PCI_FUNC(device->devfn);
-
-       /* XXX Need to change the Bus # */
-        if (bus > 2)
-                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
-                                                        0x80000000 | 0x1;
-        else
-              address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
-
-        address_reg = RM9000x2_OCD_HTCFGA;
-        data_reg =  RM9000x2_OCD_HTCFGD;
-
-        RM9K_WRITE(address_reg, address);
-        RM9K_WRITE(data_reg, val);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-static int titan_ht_config_write_word(struct pci_dev *device,
-                                             int offset, u8 val)
-{
-        int dev, bus, func;
-        uint32_t address_reg, data_reg;
-        uint32_t address;
-
-        bus = device->bus->number;
-        dev = PCI_SLOT(device->devfn);
-        func = PCI_FUNC(device->devfn);
-
-       /* XXX Need to change the Bus # */
-        if (bus > 2)
-                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
-                                0x80000000 | 0x1;
-        else
-                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
-
-        address_reg = RM9000x2_OCD_HTCFGA;
-        data_reg =  RM9000x2_OCD_HTCFGD;
-
-        if ((offset & 0x3) == 0)
-                offset = 0x2;
-        else
-                offset = 0x0;
-
-        RM9K_WRITE(address_reg, address);
-        RM9K_WRITE_16(data_reg + offset, val);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-static int titan_ht_config_write_byte(struct pci_dev *device,
-                                             int offset, u8 val)
-{
-        int dev, bus, func;
-        uint32_t address_reg, data_reg;
-        uint32_t address;
-        int offset1;
-
-        bus = device->bus->number;
-        dev = PCI_SLOT(device->devfn);
-        func = PCI_FUNC(device->devfn);
-
-       /* XXX Need to change the Bus # */
-        if (bus > 2)
-                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
-                                0x80000000 | 0x1;
-        else
-                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
-
-        address_reg = RM9000x2_OCD_HTCFGA;
-        data_reg =  RM9000x2_OCD_HTCFGD;
-
-        RM9K_WRITE(address_reg, address);
-
-        if ((offset & 0x3) == 0) {
-             offset1 = 0x3;
-        }
-        if ((offset & 0x3) == 1) {
-             offset1 = 0x2;
-        }
-        if ((offset & 0x3) == 2) {
-             offset1 = 0x1;
-        }
-        if ((offset & 0x3) == 3) {
-            offset1 = 0x0;
-        }
-
-        RM9K_WRITE_8(data_reg + offset1, val);
-        return PCIBIOS_SUCCESSFUL;
-}
-
-
-static void titan_pcibios_set_master(struct pci_dev *dev)
-{
-        u16 cmd;
-        int bus = dev->bus->number;
-
-       if (check_titan_htlink())
-            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
-
-       cmd |= PCI_COMMAND_MASTER;
-
-       if (check_titan_htlink())
-            titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
-}
-
-
-int pcibios_enable_resources(struct pci_dev *dev)
-{
-        u16 cmd, old_cmd;
-        u8 tmp1;
-        int idx;
-        struct resource *r;
-        int bus = dev->bus->number;
-
-       if (check_titan_htlink())
-            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
-
-       old_cmd = cmd;
-        for (idx = 0; idx < 6; idx++) {
-                r = &dev->resource[idx];
-                if (!r->start && r->end) {
-                        printk(KERN_ERR
-                               "PCI: Device %s not available because of "
-                               "resource collisions\n", pci_name(dev));
-                        return -EINVAL;
-                }
-                if (r->flags & IORESOURCE_IO)
-                        cmd |= PCI_COMMAND_IO;
-                if (r->flags & IORESOURCE_MEM)
-                        cmd |= PCI_COMMAND_MEMORY;
-        }
-        if (cmd != old_cmd) {
-               if (check_titan_htlink())
-                   titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
-       }
-
-       if (check_titan_htlink())
-               titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
-
-       if (tmp1 != 8) {
-                printk(KERN_WARNING "PCI setting cache line size to 8 from "
-                       "%d\n", tmp1);
-       }
-
-       if (check_titan_htlink())
-               titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
-
-       if (check_titan_htlink())
-               titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
-
-       if (tmp1 < 32 || tmp1 == 0xff) {
-                printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
-                       tmp1);
-       }
-
-       if (check_titan_htlink())
-               titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
-
-       return 0;
-}
-
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-        return pcibios_enable_resources(dev);
-}
-
-resource_size_t pcibios_align_resource(void *data, const struct resource *res,
-                               resource_size_t size, resource_size_t align)
-{
-        struct pci_dev *dev = data;
-       resource_size_t start = res->start;
-
-        if (res->flags & IORESOURCE_IO) {
-                /* We need to avoid collisions with `mirrored' VGA ports
-                   and other strange ISA hardware, so we always want the
-                   addresses kilobyte aligned.  */
-                if (size > 0x100) {
-                        printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-                               " (%ld bytes)\n", pci_name(dev),
-                                dev->resource - res, size);
-                }
-
-                start = (start + 1024 - 1) & ~(1024 - 1);
-        }
-
-       return start;
-}
-
-struct pci_ops titan_pci_ops = {
-        titan_ht_config_read_byte,
-        titan_ht_config_read_word,
-        titan_ht_config_read_dword,
-        titan_ht_config_write_byte,
-        titan_ht_config_write_word,
-        titan_ht_config_write_dword
-};
-
-void __init pcibios_fixup_bus(struct pci_bus *c)
-{
-        titan_ht_pcibios_fixup_bus(c);
-}
-
-void __init pcibios_init(void)
-{
-
-        /* Reset PCI I/O and PCI MEM values */
-       /* XXX Need to add the proper values here */
-        ioport_resource.start = 0xe0000000;
-        ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
-        iomem_resource.start  = 0xc0000000;
-        iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
-
-       /* XXX Need to add bus values */
-        pci_scan_bus(2, &titan_pci_ops, NULL);
-        pci_scan_bus(3, &titan_pci_ops, NULL);
-}
-
-unsigned __init int pcibios_assign_all_busses(void)
-{
-        /* We want to use the PCI bus detection done by PMON */
-        return 0;
-}
-
-#endif /* CONFIG_HYPERTRANSPORT */
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
deleted file mode 100644 (file)
index 6590812..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2003 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/timex.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/titan_dep.h>
-
-/* Hypertransport specific */
-#define IRQ_ACK_BITS            0x00000000     /* Ack bits */
-
-#define HYPERTRANSPORT_INTA     0x78           /* INTA# */
-#define HYPERTRANSPORT_INTB     0x79           /* INTB# */
-#define HYPERTRANSPORT_INTC     0x7a           /* INTC# */
-#define HYPERTRANSPORT_INTD     0x7b           /* INTD# */
-
-extern void titan_mailbox_irq(void);
-
-#ifdef CONFIG_HYPERTRANSPORT
-/*
- * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
- * For interprocessor interrupts, the best thing to do is to use the INTMSG
- * register. We use the same external interrupt line, i.e. INTB3 and monitor
- * another status bit
- */
-static void ll_ht_smp_irq_handler(int irq)
-{
-       u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
-
-       /* Ack all the bits that correspond to the interrupt sources */
-       if (status != 0)
-               OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
-
-       status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
-       if (status != 0)
-               OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
-
-#ifdef CONFIG_HT_LEVEL_TRIGGER
-       /*
-        * Level Trigger Mode only. Send the HT EOI message back to the source.
-        */
-       switch (status) {
-       case 0x1000000:
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
-               break;
-       case 0x2000000:
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
-               break;
-       case 0x4000000:
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
-               break;
-       case 0x8000000:
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
-               break;
-       case 0x0000001:
-               /* PLX */
-               OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20);
-               OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS);
-               break;
-       case 0xf000000:
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
-               OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
-               break;
-       }
-#endif /* CONFIG_HT_LEVEL_TRIGGER */
-
-       do_IRQ(irq);
-}
-#endif
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       unsigned int cause = read_c0_cause();
-       unsigned int status = read_c0_status();
-       unsigned int pending = cause & status;
-
-       if (pending & STATUSF_IP7) {
-               do_IRQ(7);
-       } else if (pending & STATUSF_IP2) {
-#ifdef CONFIG_HYPERTRANSPORT
-               ll_ht_smp_irq_handler(2);
-#else
-               do_IRQ(2);
-#endif
-       } else if (pending & STATUSF_IP3) {
-               do_IRQ(3);
-       } else if (pending & STATUSF_IP4) {
-               do_IRQ(4);
-       } else if (pending & STATUSF_IP5) {
-#ifdef CONFIG_SMP
-               titan_mailbox_irq();
-#else
-               do_IRQ(5);
-#endif
-       } else if (pending & STATUSF_IP6) {
-               do_IRQ(4);
-       }
-}
-
-/*
- * Initialize the next level interrupt handler
- */
-void __init arch_init_irq(void)
-{
-       clear_c0_status(ST0_IM);
-
-       mips_cpu_irq_init();
-       rm7k_cpu_irq_init();
-       rm9k_cpu_irq_init();
-}
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
deleted file mode 100644 (file)
index 6a2754c..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2003, 2004 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- * Copyright (C) 2004 Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/smp.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/smp-ops.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#ifdef CONFIG_SMP
-extern void prom_grab_secondary(void);
-#else
-#define prom_grab_secondary() do { } while (0)
-#endif
-
-#include "setup.h"
-
-struct callvectors *debug_vectors;
-
-extern unsigned long yosemite_base;
-extern unsigned long cpu_clock_freq;
-
-const char *get_system_type(void)
-{
-       return "PMC-Sierra Yosemite";
-}
-
-static void prom_cpu0_exit(void *arg)
-{
-       void *nvram = (void *) YOSEMITE_RTC_BASE;
-
-       /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
-       writeb(0x84, nvram + 0xff7);
-
-       /* wait for the watchdog to go off */
-       mdelay(100 + (1000 / 16));
-
-       /* if the watchdog fails for some reason, let people know */
-       printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-/*
- * Reset the NVRAM over the local bus
- */
-static void prom_exit(void)
-{
-#ifdef CONFIG_SMP
-       if (smp_processor_id())
-               /* CPU 1 */
-               smp_call_function(prom_cpu0_exit, NULL, 1);
-#endif
-       prom_cpu0_exit(NULL);
-}
-
-/*
- * Halt the system
- */
-static void prom_halt(void)
-{
-       printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-       while (1)
-               __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
-}
-
-extern struct plat_smp_ops yos_smp_ops;
-
-/*
- * Init routine which accepts the variables from PMON
- */
-void __init prom_init(void)
-{
-       int argc = fw_arg0;
-       char **arg = (char **) fw_arg1;
-       char **env = (char **) fw_arg2;
-       struct callvectors *cv = (struct callvectors *) fw_arg3;
-       int i = 0;
-
-       /* Callbacks for halt, restart */
-       _machine_restart = (void (*)(char *)) prom_exit;
-       _machine_halt = prom_halt;
-       pm_power_off = prom_halt;
-
-       debug_vectors = cv;
-       arcs_cmdline[0] = '\0';
-
-       /* Get the boot parameters */
-       for (i = 1; i < argc; i++) {
-               if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >=
-                   sizeof(arcs_cmdline))
-                       break;
-
-               strcat(arcs_cmdline, arg[i]);
-               strcat(arcs_cmdline, " ");
-       }
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-       if ((strstr(arcs_cmdline, "console=ttyS")) == NULL)
-               strcat(arcs_cmdline, "console=ttyS0,115200");
-#endif
-
-       while (*env) {
-               if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0)
-                       yosemite_base =
-                           simple_strtol(*env + strlen("ocd_base="), NULL,
-                                         16);
-
-               if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0)
-                       cpu_clock_freq =
-                           simple_strtol(*env + strlen("cpuclock="), NULL,
-                                         10);
-
-               env++;
-       }
-
-       prom_grab_secondary();
-
-       register_smp_ops(&yos_smp_ops);
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c
deleted file mode 100644 (file)
index b7f1d9c..0000000
+++ /dev/null
@@ -1,109 +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, 2002, 2004 Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <asm/serial.h>
-#include <asm/io.h>
-
-/* SUPERIO uart register map */
-struct yo_uartregs {
-       union {
-               volatile u8     rbr;    /* read only, DLAB == 0 */
-               volatile u8     thr;    /* write only, DLAB == 0 */
-               volatile u8     dll;    /* DLAB == 1 */
-       } u1;
-       union {
-               volatile u8     ier;    /* DLAB == 0 */
-               volatile u8     dlm;    /* DLAB == 1 */
-       } u2;
-       union {
-               volatile u8     iir;    /* read only */
-               volatile u8     fcr;    /* write only */
-       } u3;
-       volatile u8     iu_lcr;
-       volatile u8     iu_mcr;
-       volatile u8     iu_lsr;
-       volatile u8     iu_msr;
-       volatile u8     iu_scr;
-} yo_uregs_t;
-
-#define iu_rbr u1.rbr
-#define iu_thr u1.thr
-#define iu_dll u1.dll
-#define iu_ier u2.ier
-#define iu_dlm u2.dlm
-#define iu_iir u3.iir
-#define iu_fcr u3.fcr
-
-#define ssnop()                __asm__ __volatile__("sll       $0, $0, 1\n");
-#define ssnop_4()      do { ssnop(); ssnop(); ssnop(); ssnop(); } while (0)
-
-#define IO_BASE_64     0x9000000000000000ULL
-
-static unsigned char readb_outer_space(unsigned long long phys)
-{
-       unsigned long long vaddr = IO_BASE_64 | phys;
-       unsigned char res;
-       unsigned int sr;
-
-       sr = read_c0_status();
-       write_c0_status((sr | ST0_KX) & ~ ST0_IE);
-       ssnop_4();
-
-       __asm__ __volatile__ (
-       "       .set    mips3           \n"
-       "       ld      %0, %1          \n"
-       "       lbu     %0, (%0)        \n"
-       "       .set    mips0           \n"
-       : "=r" (res)
-       : "m" (vaddr));
-
-       write_c0_status(sr);
-       ssnop_4();
-
-       return res;
-}
-
-static void writeb_outer_space(unsigned long long phys, unsigned char c)
-{
-       unsigned long long vaddr = IO_BASE_64 | phys;
-       unsigned long tmp;
-       unsigned int sr;
-
-       sr = read_c0_status();
-       write_c0_status((sr | ST0_KX) & ~ ST0_IE);
-       ssnop_4();
-
-       __asm__ __volatile__ (
-       "       .set    mips3           \n"
-       "       ld      %0, %1          \n"
-       "       sb      %2, (%0)        \n"
-       "       .set    mips0           \n"
-       : "=&r" (tmp)
-       : "m" (vaddr), "r" (c));
-
-       write_c0_status(sr);
-       ssnop_4();
-}
-
-void prom_putchar(char c)
-{
-       unsigned long lsr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_lsr);
-       unsigned long thr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_thr);
-
-       while ((readb_outer_space(lsr) & 0x20) == 0);
-       writeb_outer_space(thr, c);
-}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
deleted file mode 100644 (file)
index b6472fc..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- *  Copyright (C) 2003 PMC-Sierra Inc.
- *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/termios.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/serial.h>
-#include <asm/titan_dep.h>
-#include <asm/m48t37.h>
-
-#include "setup.h"
-
-unsigned char titan_ge_mac_addr_base[6] = {
-       // 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00
-       0x00, 0xe0, 0x04, 0x00, 0x00, 0x21
-};
-
-unsigned long cpu_clock_freq;
-unsigned long yosemite_base;
-
-static struct m48t37_rtc *m48t37_base;
-
-void __init bus_error_init(void)
-{
-       /* Do nothing */
-}
-
-
-void read_persistent_clock(struct timespec *ts)
-{
-       unsigned int year, month, day, hour, min, sec;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       /* Stop the update to the time */
-       m48t37_base->control = 0x40;
-
-       year = bcd2bin(m48t37_base->year);
-       year += bcd2bin(m48t37_base->century) * 100;
-
-       month = bcd2bin(m48t37_base->month);
-       day = bcd2bin(m48t37_base->date);
-       hour = bcd2bin(m48t37_base->hour);
-       min = bcd2bin(m48t37_base->min);
-       sec = bcd2bin(m48t37_base->sec);
-
-       /* Start the update to the time again */
-       m48t37_base->control = 0x00;
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       ts->tv_sec = mktime(year, month, day, hour, min, sec);
-       ts->tv_nsec = 0;
-}
-
-int rtc_mips_set_time(unsigned long tim)
-{
-       struct rtc_time tm;
-       unsigned long flags;
-
-       /*
-        * Convert to a more useful format -- note months count from 0
-        * and years from 1900
-        */
-       rtc_time_to_tm(tim, &tm);
-       tm.tm_year += 1900;
-       tm.tm_mon += 1;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       /* enable writing */
-       m48t37_base->control = 0x80;
-
-       /* year */
-       m48t37_base->year = bin2bcd(tm.tm_year % 100);
-       m48t37_base->century = bin2bcd(tm.tm_year / 100);
-
-       /* month */
-       m48t37_base->month = bin2bcd(tm.tm_mon);
-
-       /* day */
-       m48t37_base->date = bin2bcd(tm.tm_mday);
-
-       /* hour/min/sec */
-       m48t37_base->hour = bin2bcd(tm.tm_hour);
-       m48t37_base->min = bin2bcd(tm.tm_min);
-       m48t37_base->sec = bin2bcd(tm.tm_sec);
-
-       /* day of week -- not really used, but let's keep it up-to-date */
-       m48t37_base->day = bin2bcd(tm.tm_wday + 1);
-
-       /* disable writing */
-       m48t37_base->control = 0x00;
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       return 0;
-}
-
-void __init plat_time_init(void)
-{
-       mips_hpt_frequency = cpu_clock_freq / 2;
-mips_hpt_frequency = 33000000 * 3 * 5;
-}
-
-unsigned long ocd_base;
-
-EXPORT_SYMBOL(ocd_base);
-
-/*
- * Common setup before any secondaries are started
- */
-
-#define TITAN_UART_CLK         3686400
-#define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16)
-#define TITAN_SERIAL_IRQ       4
-#define TITAN_SERIAL_BASE      0xfd000008UL
-
-static void __init py_map_ocd(void)
-{
-       ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE);
-       if (!ocd_base)
-               panic("Mapping OCD failed - game over.  Your score is 0.");
-
-       /* Kludge for PMON bug ... */
-       OCD_WRITE(0x0710, 0x0ffff029);
-}
-
-static void __init py_uart_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
-       struct uart_port up;
-
-       /*
-        * Register to interrupt zero because we share the interrupt with
-        * the serial driver which we don't properly support yet.
-        */
-       memset(&up, 0, sizeof(up));
-       up.membase      = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8);
-       up.irq          = TITAN_SERIAL_IRQ;
-       up.uartclk      = TITAN_UART_CLK;
-       up.regshift     = 0;
-       up.iotype       = UPIO_MEM;
-       up.flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-       up.line         = 0;
-
-       if (early_serial_setup(&up))
-               printk(KERN_ERR "Early serial init of port 0 failed\n");
-#endif /* CONFIG_SERIAL_8250 */
-}
-
-static void __init py_rtc_setup(void)
-{
-       m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
-       if (!m48t37_base)
-               printk(KERN_ERR "Mapping the RTC failed\n");
-}
-
-/* Not only time init but that's what the hook it's called through is named */
-static void __init py_late_time_init(void)
-{
-       py_map_ocd();
-       py_uart_setup();
-       py_rtc_setup();
-}
-
-void __init plat_mem_setup(void)
-{
-       late_time_init = py_late_time_init;
-
-       /* Add memory regions */
-       add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
-
-#if 0 /* XXX Crash ...  */
-       OCD_WRITE(RM9000x2_OCD_HTSC,
-                 OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE);
-
-       /* Set the BAR. Shifted mode */
-       OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
-       OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
-#endif
-}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.h b/arch/mips/pmc-sierra/yosemite/setup.h
deleted file mode 100644 (file)
index 1a01abf..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2003, 04 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
- *
- * Board specific definititions for the PMC-Sierra Yosemite
- *
- * 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 __SETUP_H__
-#define __SETUP_H__
-
-/* M48T37 RTC + NVRAM */
-#define        YOSEMITE_RTC_BASE               0xfc800000
-#define        YOSEMITE_RTC_SIZE               0x00800000
-
-#define HYPERTRANSPORT_BAR0_ADDR        0x00000006
-#define HYPERTRANSPORT_SIZE0            0x0fffffff
-#define HYPERTRANSPORT_BAR0_ATTR        0x00002000
-
-#define HYPERTRANSPORT_ENABLE           0x6
-
-/*
- * EEPROM Size
- */
-#define        TITAN_ATMEL_24C32_SIZE          32768
-#define        TITAN_ATMEL_24C64_SIZE          65536
-
-#endif /* __SETUP_H__ */
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
deleted file mode 100644 (file)
index 5edab2b..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-
-#include <asm/pmon.h>
-#include <asm/titan_dep.h>
-#include <asm/time.h>
-
-#define LAUNCHSTACK_SIZE 256
-
-static __cpuinitdata arch_spinlock_t launch_lock = __ARCH_SPIN_LOCK_UNLOCKED;
-
-static unsigned long secondary_sp __cpuinitdata;
-static unsigned long secondary_gp __cpuinitdata;
-
-static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
-       __attribute__((aligned(2 * sizeof(long))));
-
-static void __init prom_smp_bootstrap(void)
-{
-       local_irq_disable();
-
-       while (arch_spin_is_locked(&launch_lock));
-
-       __asm__ __volatile__(
-       "       move    $sp, %0         \n"
-       "       move    $gp, %1         \n"
-       "       j       smp_bootstrap   \n"
-       :
-       : "r" (secondary_sp), "r" (secondary_gp));
-}
-
-/*
- * PMON is a fragile beast.  It'll blow up once the mappings it's littering
- * right into the middle of KSEG3 are blown away so we have to grab the slave
- * core early and keep it in a waiting loop.
- */
-void __init prom_grab_secondary(void)
-{
-       arch_spin_lock(&launch_lock);
-
-       pmon_cpustart(1, &prom_smp_bootstrap,
-                     launchstack + LAUNCHSTACK_SIZE, 0);
-}
-
-void titan_mailbox_irq(void)
-{
-       int cpu = smp_processor_id();
-       unsigned long status;
-
-       switch (cpu) {
-       case 0:
-               status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
-               OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
-
-               if (status & 0x2)
-                       smp_call_function_interrupt();
-               if (status & 0x4)
-                       scheduler_ipi();
-               break;
-
-       case 1:
-               status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
-               OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
-
-               if (status & 0x2)
-                       smp_call_function_interrupt();
-               if (status & 0x4)
-                       scheduler_ipi();
-               break;
-       }
-}
-
-/*
- * Send inter-processor interrupt
- */
-static void yos_send_ipi_single(int cpu, unsigned int action)
-{
-       /*
-        * Generate an INTMSG so that it can be sent over to the
-        * destination CPU. The INTMSG will put the STATUS bits
-        * based on the action desired. An alternative strategy
-        * is to write to the Interrupt Set register, read the
-        * Interrupt Status register and clear the Interrupt
-        * Clear register. The latter is preffered.
-        */
-       switch (action) {
-       case SMP_RESCHEDULE_YOURSELF:
-               if (cpu == 1)
-                       OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
-               else
-                       OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
-               break;
-
-       case SMP_CALL_FUNCTION:
-               if (cpu == 1)
-                       OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
-               else
-                       OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
-               break;
-       }
-}
-
-static void yos_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
-       unsigned int i;
-
-       for_each_cpu(i, mask)
-               yos_send_ipi_single(i, action);
-}
-
-/*
- *  After we've done initial boot, this function is called to allow the
- *  board code to clean up state, if needed
- */
-static void __cpuinit yos_init_secondary(void)
-{
-}
-
-static void __cpuinit yos_smp_finish(void)
-{
-       set_c0_status(ST0_CO | ST0_IM | ST0_IE);
-}
-
-/* Hook for after all CPUs are online */
-static void yos_cpus_done(void)
-{
-}
-
-/*
- * Firmware CPU startup hook
- * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
- * It launches the next * available CPU and copies some information on the
- * stack so the first thing we do is throw away that stuff and load useful
- * values into the registers ...
- */
-static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
-{
-       unsigned long gp = (unsigned long) task_thread_info(idle);
-       unsigned long sp = __KSTK_TOS(idle);
-
-       secondary_sp = sp;
-       secondary_gp = gp;
-
-       arch_spin_unlock(&launch_lock);
-}
-
-/*
- * Detect available CPUs, populate cpu_possible_mask before smp_init
- *
- * We don't want to start the secondary CPU yet nor do we have a nice probing
- * feature in PMON so we just assume presence of the secondary core.
- */
-static void __init yos_smp_setup(void)
-{
-       int i;
-
-       init_cpu_possible(cpu_none_mask);
-
-       for (i = 0; i < 2; i++) {
-               set_cpu_possible(i, true);
-               __cpu_number_map[i]     = i;
-               __cpu_logical_map[i]    = i;
-       }
-}
-
-static void __init yos_prepare_cpus(unsigned int max_cpus)
-{
-       /*
-        * Be paranoid.  Enable the IPI only if we're really about to go SMP.
-        */
-       if (num_possible_cpus())
-               set_c0_status(STATUSF_IP5);
-}
-
-struct plat_smp_ops yos_smp_ops = {
-       .send_ipi_single        = yos_send_ipi_single,
-       .send_ipi_mask          = yos_send_ipi_mask,
-       .init_secondary         = yos_init_secondary,
-       .smp_finish             = yos_smp_finish,
-       .cpus_done              = yos_cpus_done,
-       .boot_secondary         = yos_boot_secondary,
-       .smp_setup              = yos_smp_setup,
-       .prepare_cpus           = yos_prepare_cpus,
-};
index 1cf5abbef715685f6efba80f1f6d72e6170d9c58..c6979353980bd895be6846687575f6bdca837d33 100644 (file)
@@ -69,40 +69,6 @@ char *prom_getenv(char *envname)
        return result;
 }
 
-/* TODO: Verify on linux-mips mailing list that the following two  */
-/* functions are correct                                           */
-/* TODO: Copy NMI and EJTAG exception vectors to memory from the   */
-/* BootROM exception vectors. Flush their cache entries. test it.  */
-
-static void __init mips_nmi_setup(void)
-{
-       void *base;
-#if defined(CONFIG_CPU_MIPS32_R1)
-       base = cpu_has_veic ?
-               (void *)(CAC_BASE + 0xa80) :
-               (void *)(CAC_BASE + 0x380);
-#elif defined(CONFIG_CPU_MIPS32_R2)
-       base = (void *)0xbfc00000;
-#else
-#error NMI exception handler address not defined
-#endif
-}
-
-static void __init mips_ejtag_setup(void)
-{
-       void *base;
-
-#if defined(CONFIG_CPU_MIPS32_R1)
-       base = cpu_has_veic ?
-               (void *)(CAC_BASE + 0xa00) :
-               (void *)(CAC_BASE + 0x300);
-#elif defined(CONFIG_CPU_MIPS32_R2)
-       base = (void *)0xbfc00480;
-#else
-#error EJTAG exception handler address not defined
-#endif
-}
-
 void __init prom_init(void)
 {
        int prom_argc;
@@ -113,9 +79,6 @@ void __init prom_init(void)
        _prom_envp = (int *) fw_arg2;
        _prom_memsize = (unsigned long) fw_arg3;
 
-       board_nmi_handler_setup = mips_nmi_setup;
-       board_ejtag_handler_setup = mips_ejtag_setup;
-
        if (prom_argc == 1) {
                strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
                strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE);
index d7c26d00cfefe3fdca84fda3fe61bddacc7e799c..a757ded437cdc731e01c82bd003b472cb0295eb7 100644 (file)
@@ -72,12 +72,11 @@ void __init prom_setup_cmdline(void)
        static char cmd_line[COMMAND_LINE_SIZE] __initdata;
        char *cp, *board;
        int prom_argc;
-       char **prom_argv, **prom_envp;
+       char **prom_argv;
        int i;
 
        prom_argc = fw_arg0;
        prom_argv = (char **) fw_arg1;
-       prom_envp = (char **) fw_arg2;
 
        cp = cmd_line;
                /* Note: it is common that parameters start
index da44ccb208299ab73e6774601c2a183e011dc4fa..4a6057b35b9d55765f89d25705d98318ddb6d6a9 100644 (file)
@@ -73,12 +73,10 @@ static char __init *decode_eisa_sig(unsigned long addr)
 
 static irqreturn_t ip22_eisa_intr(int irq, void *dev_id)
 {
-       u8 eisa_irq;
-       u8 dma1, dma2;
+       u8 eisa_irq = inb(EIU_INTRPT_ACK);
 
-       eisa_irq = inb(EIU_INTRPT_ACK);
-       dma1 = inb(EISA_DMA1_STATUS);
-       dma2 = inb(EISA_DMA2_STATUS);
+       inb(EISA_DMA1_STATUS);
+       inb(EISA_DMA2_STATUS);
 
        if (eisa_irq < EISA_MAX_IRQ) {
                do_IRQ(eisa_irq);
index 3cd937e0e9a3c0022e7f3ac626d1ff3a3bf7484b..01cc1a749c73e62e0be4762ee9cd54cc8d9a3221 100644 (file)
@@ -74,7 +74,7 @@ config SIBYTE_SB1xxx_SOC
        select SWAP_IO_SPACE
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
-       select CFE
+       select FW_CFE
        select SYS_HAS_EARLY_PRINTK
 
 choice
index 413f17f8e89289035ce836148c64cc56c31443a5..d6c7bd4b5ab0a5c7980a6a949be8c6597c0f59bb 100644 (file)
 #include <linux/fb.h>
 #include <linux/screen_info.h>
 
-#ifdef CONFIG_ARC
+#ifdef CONFIG_FW_ARC
 #include <asm/fw/arc/types.h>
 #include <asm/sgialib.h>
 #endif
 
-#ifdef CONFIG_SNIPROM
+#ifdef CONFIG_FW_SNIPROM
 #include <asm/mipsprom.h>
 #endif
 
@@ -37,7 +37,7 @@ extern void sni_machine_power_off(void);
 
 static void __init sni_display_setup(void)
 {
-#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC)
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_FW_ARC)
        struct screen_info *si = &screen_info;
        DISPLAY_STATUS *di;
 
@@ -56,7 +56,7 @@ static void __init sni_display_setup(void)
 
 static void __init sni_console_setup(void)
 {
-#ifndef CONFIG_ARC
+#ifndef CONFIG_FW_ARC
        char *ctype;
        char *cdev;
        char *baud;
index 4efd9185f294643d28aefe755c52c9d52e071f84..b14ee53581a9674fc53cbdef9555dbaf0513897e 100644 (file)
@@ -341,7 +341,7 @@ static void __devinit quirk_slc90e66_ide(struct pci_dev *dev)
 
 static void __devinit tc35815_fixup(struct pci_dev *dev)
 {
-       /* This device may have PM registers but not they are not suported. */
+       /* This device may have PM registers but not they are not supported. */
        if (dev->pm_cap) {
                dev_info(&dev->dev, "PM disabled\n");
                dev->pm_cap = 0;
index d06192faeb7ca7038687981726f9ba488f6f489e..8b8a0e1a40caabbc52f5175eefa6866889fde6b9 100644 (file)
@@ -38,10 +38,8 @@ static struct pci_controller hose_0 = {
 
 static int __init gt64120_pci_init(void)
 {
-       u32 tmp;
-
-       tmp = GT_READ(GT_PCI0_CMD_OFS);         /* Huh??? -- Ralf  */
-       tmp = GT_READ(GT_PCI0_BARE_OFS);
+       (void) GT_READ(GT_PCI0_CMD_OFS);        /* Huh??? -- Ralf  */
+       (void) GT_READ(GT_PCI0_BARE_OFS);
 
        /* reset the whole PCI I/O space range */
        ioport_resource.start = GT_PCI_IO_BASE;
index 4ebf117c3285079d7a4ca0d9a4cee8b311b9e16c..bd9ada693f9561ba15b581855d1b80c95f57db4b 100644 (file)
@@ -95,7 +95,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
  * checks at dup_mmap(), exec(), and other mmlist addition points
  * could be used. The locking scheme was chosen on the basis of
  * manfred's recommendations and having no core impact whatsoever.
- * -- wli
+ * -- nyc
  */
 DEFINE_SPINLOCK(pgd_lock);
 struct page *pgd_list;
index e7f1a2993f780ab89795a73c8b2e9bd71bdd2ed6..ec37e185d20d82333c7e4f46cce5d721b99d98c2 100644 (file)
@@ -146,7 +146,7 @@ config DEBUG_STACKOVERFLOW
        help
          Make extra checks for space available on stack in some
           critical functions. This will cause kernel to run a bit slower,
-         but will catch most of kernel stack overruns and exit gracefuly.
+         but will catch most of kernel stack overruns and exit gracefully.
 
          Say Y if you are unsure.
 
index 2d62b484b3fcd0599ca9ed1fcddcdf7c70b26a61..650757c300dbe71ca5e29d127a0c2c923d37ee4f 100644 (file)
@@ -1,5 +1,4 @@
 
-
 generic-y += clkdev.h
 generic-y += rwsem.h
 generic-y += trace_clock.h
index bf2c06c338719e66c20db73bf8bc8d0bb8dabc5d..d3d634274d2c4de6fe63610f872d3eca1eb7738e 100644 (file)
 #ifndef _EPAPR_HCALLS_H
 #define _EPAPR_HCALLS_H
 
+#include <uapi/asm/epapr_hcalls.h>
+
+#ifndef __ASSEMBLY__
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/byteorder.h>
 
-#define EV_BYTE_CHANNEL_SEND           1
-#define EV_BYTE_CHANNEL_RECEIVE                2
-#define EV_BYTE_CHANNEL_POLL           3
-#define EV_INT_SET_CONFIG              4
-#define EV_INT_GET_CONFIG              5
-#define EV_INT_SET_MASK                        6
-#define EV_INT_GET_MASK                        7
-#define EV_INT_IACK                    9
-#define EV_INT_EOI                     10
-#define EV_INT_SEND_IPI                        11
-#define EV_INT_SET_TASK_PRIORITY       12
-#define EV_INT_GET_TASK_PRIORITY       13
-#define EV_DOORBELL_SEND               14
-#define EV_MSGSND                      15
-#define EV_IDLE                                16
-
-/* vendor ID: epapr */
-#define EV_LOCAL_VENDOR_ID             0       /* for private use */
-#define EV_EPAPR_VENDOR_ID             1
-#define EV_FSL_VENDOR_ID               2       /* Freescale Semiconductor */
-#define EV_IBM_VENDOR_ID               3       /* IBM */
-#define EV_GHS_VENDOR_ID               4       /* Green Hills Software */
-#define EV_ENEA_VENDOR_ID              5       /* Enea */
-#define EV_WR_VENDOR_ID                        6       /* Wind River Systems */
-#define EV_AMCC_VENDOR_ID              7       /* Applied Micro Circuits */
-#define EV_KVM_VENDOR_ID               42      /* KVM */
-
-/* The max number of bytes that a byte channel can send or receive per call */
-#define EV_BYTE_CHANNEL_MAX_BYTES      16
-
-
-#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
-#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
-
-/* epapr error codes */
-#define EV_EPERM               1       /* Operation not permitted */
-#define EV_ENOENT              2       /*  Entry Not Found */
-#define EV_EIO                 3       /* I/O error occured */
-#define EV_EAGAIN              4       /* The operation had insufficient
-                                        * resources to complete and should be
-                                        * retried
-                                        */
-#define EV_ENOMEM              5       /* There was insufficient memory to
-                                        * complete the operation */
-#define EV_EFAULT              6       /* Bad guest address */
-#define EV_ENODEV              7       /* No such device */
-#define EV_EINVAL              8       /* An argument supplied to the hcall
-                                          was out of range or invalid */
-#define EV_INTERNAL            9       /* An internal error occured */
-#define EV_CONFIG              10      /* A configuration error was detected */
-#define EV_INVALID_STATE       11      /* The object is in an invalid state */
-#define EV_UNIMPLEMENTED       12      /* Unimplemented hypercall */
-#define EV_BUFFER_OVERFLOW     13      /* Caller-supplied buffer too small */
-
 /*
  * Hypercall register clobber list
  *
@@ -193,7 +142,7 @@ static inline unsigned int ev_int_set_config(unsigned int interrupt,
        r5  = priority;
        r6  = destination;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
                : : EV_HCALL_CLOBBERS4
        );
@@ -222,7 +171,7 @@ static inline unsigned int ev_int_get_config(unsigned int interrupt,
        r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
                : : EV_HCALL_CLOBBERS4
        );
@@ -252,7 +201,7 @@ static inline unsigned int ev_int_set_mask(unsigned int interrupt,
        r3 = interrupt;
        r4 = mask;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -277,7 +226,7 @@ static inline unsigned int ev_int_get_mask(unsigned int interrupt,
        r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -305,7 +254,7 @@ static inline unsigned int ev_int_eoi(unsigned int interrupt)
        r11 = EV_HCALL_TOKEN(EV_INT_EOI);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -344,7 +293,7 @@ static inline unsigned int ev_byte_channel_send(unsigned int handle,
        r7 = be32_to_cpu(p[2]);
        r8 = be32_to_cpu(p[3]);
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3),
                  "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
                : : EV_HCALL_CLOBBERS6
@@ -383,7 +332,7 @@ static inline unsigned int ev_byte_channel_receive(unsigned int handle,
        r3 = handle;
        r4 = *count;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4),
                  "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
                : : EV_HCALL_CLOBBERS6
@@ -421,7 +370,7 @@ static inline unsigned int ev_byte_channel_poll(unsigned int handle,
        r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
                : : EV_HCALL_CLOBBERS3
        );
@@ -454,7 +403,7 @@ static inline unsigned int ev_int_iack(unsigned int handle,
        r11 = EV_HCALL_TOKEN(EV_INT_IACK);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -478,7 +427,7 @@ static inline unsigned int ev_doorbell_send(unsigned int handle)
        r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -498,12 +447,12 @@ static inline unsigned int ev_idle(void)
 
        r11 = EV_HCALL_TOKEN(EV_IDLE);
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "=r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
 
        return r3;
 }
-
-#endif
+#endif /* !__ASSEMBLY__ */
+#endif /* _EPAPR_HCALLS_H */
index 922d9b5fe3d5c9b9863691ffff89c3122f103b21..3abb58394da4830d9d2b61ff6397e5f3090f1c69 100644 (file)
@@ -96,7 +96,7 @@ static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
        r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
        r3 = vcpu_mask;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -151,7 +151,7 @@ static inline unsigned int fh_partition_get_dtprop(int handle,
        r9 = (uint32_t)propvalue_addr;
        r10 = *propvalue_len;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11),
                  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
                  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -205,7 +205,7 @@ static inline unsigned int fh_partition_set_dtprop(int handle,
        r9 = (uint32_t)propvalue_addr;
        r10 = propvalue_len;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11),
                  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
                  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -229,7 +229,7 @@ static inline unsigned int fh_partition_restart(unsigned int partition)
        r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
        r3 = partition;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -262,7 +262,7 @@ static inline unsigned int fh_partition_get_status(unsigned int partition,
        r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
        r3 = partition;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -295,7 +295,7 @@ static inline unsigned int fh_partition_start(unsigned int partition,
        r4 = entry_point;
        r5 = load;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
                : : EV_HCALL_CLOBBERS3
        );
@@ -317,7 +317,7 @@ static inline unsigned int fh_partition_stop(unsigned int partition)
        r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
        r3 = partition;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -376,7 +376,7 @@ static inline unsigned int fh_partition_memcpy(unsigned int source,
 #endif
        r7 = count;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11),
                  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
                : : EV_HCALL_CLOBBERS5
@@ -399,7 +399,7 @@ static inline unsigned int fh_dma_enable(unsigned int liodn)
        r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
        r3 = liodn;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -421,7 +421,7 @@ static inline unsigned int fh_dma_disable(unsigned int liodn)
        r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
        r3 = liodn;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -447,7 +447,7 @@ static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
        r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
        r3 = interrupt;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "=r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -469,7 +469,7 @@ static inline unsigned int fh_system_reset(void)
 
        r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "=r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -506,7 +506,7 @@ static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
        r6 = addr_lo;
        r7 = peek;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
                  "+r" (r7)
                : : EV_HCALL_CLOBBERS5
@@ -542,7 +542,7 @@ static inline unsigned int fh_get_core_state(unsigned int handle,
        r3 = handle;
        r4 = vcpu;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -572,7 +572,7 @@ static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
        r3 = handle;
        r4 = vcpu;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -597,7 +597,7 @@ static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
        r3 = handle;
        r4 = vcpu;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3), "+r" (r4)
                : : EV_HCALL_CLOBBERS2
        );
@@ -618,7 +618,7 @@ static inline unsigned int fh_claim_device(unsigned int handle)
        r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
@@ -645,7 +645,7 @@ static inline unsigned int fh_partition_stop_dma(unsigned int handle)
        r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
        r3 = handle;
 
-       __asm__ __volatile__ ("sc 1"
+       asm volatile("bl        epapr_hypercall_start"
                : "+r" (r11), "+r" (r3)
                : : EV_HCALL_CLOBBERS1
        );
index 76fdcfef088972d1b564d8413c275e1d01261ced..aabcdba8f6b0faedd974d0980041d3e88bc1167f 100644 (file)
 
 #define RESUME_FLAG_NV          (1<<0)  /* Reload guest nonvolatile state? */
 #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
+#define RESUME_FLAG_ARCH1      (1<<2)
 
 #define RESUME_GUEST            0
 #define RESUME_GUEST_NV         RESUME_FLAG_NV
index 7aefdb3e1ce405865beb991934dadfac22036724..5a56e1c5f8517fde0b4005c0c456d14a0b4ce7bc 100644 (file)
@@ -81,6 +81,8 @@ struct kvmppc_vcpu_book3s {
        u64 sdr1;
        u64 hior;
        u64 msr_mask;
+       u64 purr_offset;
+       u64 spurr_offset;
 #ifdef CONFIG_PPC_BOOK3S_32
        u32 vsid_pool[VSID_POOL_SIZE];
        u32 vsid_next;
@@ -157,10 +159,14 @@ extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
 extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr);
 extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
                        long pte_index, unsigned long pteh, unsigned long ptel);
-extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
-                       long pte_index, unsigned long pteh, unsigned long ptel);
+extern long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel,
+                       pgd_t *pgdir, bool realmode, unsigned long *idx_ret);
+extern long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
+                       unsigned long pte_index, unsigned long avpn,
+                       unsigned long *hpret);
 extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
-                       struct kvm_memory_slot *memslot);
+                       struct kvm_memory_slot *memslot, unsigned long *map);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
index 0dd1d86d3e3168303e1e714977dc8439db86cb29..38bec1dc99281f682ddf13209c296be0a8da056b 100644 (file)
@@ -50,6 +50,15 @@ extern int kvm_hpt_order;            /* order of preallocated HPTs */
 #define HPTE_V_HVLOCK  0x40UL
 #define HPTE_V_ABSENT  0x20UL
 
+/*
+ * We use this bit in the guest_rpte field of the revmap entry
+ * to indicate a modified HPTE.
+ */
+#define HPTE_GR_MODIFIED       (1ul << 62)
+
+/* These bits are reserved in the guest view of the HPTE */
+#define HPTE_GR_RESERVED       HPTE_GR_MODIFIED
+
 static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
 {
        unsigned long tmp, old;
@@ -60,7 +69,7 @@ static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
                     "  ori     %0,%0,%4\n"
                     "  stdcx.  %0,0,%2\n"
                     "  beq+    2f\n"
-                    "  li      %1,%3\n"
+                    "  mr      %1,%3\n"
                     "2:        isync"
                     : "=&r" (tmp), "=&r" (old)
                     : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
@@ -237,4 +246,26 @@ static inline bool slot_is_aligned(struct kvm_memory_slot *memslot,
        return !(memslot->base_gfn & mask) && !(memslot->npages & mask);
 }
 
+/*
+ * This works for 4k, 64k and 16M pages on POWER7,
+ * and 4k and 16M pages on PPC970.
+ */
+static inline unsigned long slb_pgsize_encoding(unsigned long psize)
+{
+       unsigned long senc = 0;
+
+       if (psize > 0x1000) {
+               senc = SLB_VSID_L;
+               if (psize == 0x10000)
+                       senc |= SLB_VSID_LP_01;
+       }
+       return senc;
+}
+
+static inline int is_vrma_hpte(unsigned long hpte_v)
+{
+       return (hpte_v & ~0xffffffUL) ==
+               (HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)));
+}
+
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
index 30a600fa1b6a9977a2edc380f763eda4b1ccf5c9..3a79f53257125a4daf05e5546893eb8821606c3d 100644 (file)
@@ -17,6 +17,7 @@
  * there are no exceptions for which we fall through directly to
  * the normal host handler.
  *
+ * 32-bit host
  * Expected inputs (normal exceptions):
  *   SCRATCH0 = saved r10
  *   r10 = thread struct
  *   *(r8 + GPR9) = saved r9
  *   *(r8 + GPR10) = saved r10 (r10 not yet clobbered)
  *   *(r8 + GPR11) = saved r11
+ *
+ * 64-bit host
+ * Expected inputs (GEN/GDBELL/DBG/MC exception types):
+ *  r10 = saved CR
+ *  r13 = PACA_POINTER
+ *  *(r13 + PACA_EX##type + EX_R10) = saved r10
+ *  *(r13 + PACA_EX##type + EX_R11) = saved r11
+ *  SPRN_SPRG_##type##_SCRATCH = saved r13
+ *
+  * Expected inputs (CRIT exception type):
+ *  r10 = saved CR
+ *  r13 = PACA_POINTER
+ *  *(r13 + PACA_EX##type + EX_R10) = saved r10
+ *  *(r13 + PACA_EX##type + EX_R11) = saved r11
+ *  *(r13 + PACA_EX##type + EX_R13) = saved r13
+ *
+ * Expected inputs (TLB exception type):
+ *  r10 = saved CR
+ *  r13 = PACA_POINTER
+ *  *(r13 + PACA_EX##type + EX_TLB_R10) = saved r10
+ *  *(r13 + PACA_EX##type + EX_TLB_R11) = saved r11
+ *  SPRN_SPRG_GEN_SCRATCH = saved r13
+ *
+ * Only the bolted version of TLB miss exception handlers is supported now.
  */
 .macro DO_KVM intno srr1
 #ifdef CONFIG_KVM_BOOKE_HV
 BEGIN_FTR_SECTION
        mtocrf  0x80, r11       /* check MSR[GS] without clobbering reg */
-       bf      3, kvmppc_resume_\intno\()_\srr1
+       bf      3, 1975f
        b       kvmppc_handler_\intno\()_\srr1
-kvmppc_resume_\intno\()_\srr1:
+1975:
 END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
 #endif
 .endm
index 28e8f5e5c63e7e1ac87247edaf2a0052e6c128a8..ca9bf459db6a56e2bb7d1e450a7b5c4d6026a3ae 100644 (file)
@@ -46,7 +46,7 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
-#ifdef CONFIG_KVM_BOOK3S_64_HV
+#if !defined(CONFIG_KVM_440)
 #include <linux/mmu_notifier.h>
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
@@ -204,7 +204,7 @@ struct revmap_entry {
 };
 
 /*
- * We use the top bit of each memslot->rmap entry as a lock bit,
+ * We use the top bit of each memslot->arch.rmap entry as a lock bit,
  * and bit 32 as a present flag.  The bottom 32 bits are the
  * index in the guest HPT of a HPTE that points to the page.
  */
@@ -215,14 +215,17 @@ struct revmap_entry {
 #define KVMPPC_RMAP_PRESENT    0x100000000ul
 #define KVMPPC_RMAP_INDEX      0xfffffffful
 
-/* Low-order bits in kvm->arch.slot_phys[][] */
+/* Low-order bits in memslot->arch.slot_phys[] */
 #define KVMPPC_PAGE_ORDER_MASK 0x1f
 #define KVMPPC_PAGE_NO_CACHE   HPTE_R_I        /* 0x20 */
 #define KVMPPC_PAGE_WRITETHRU  HPTE_R_W        /* 0x40 */
 #define KVMPPC_GOT_PAGE                0x80
 
 struct kvm_arch_memory_slot {
+#ifdef CONFIG_KVM_BOOK3S_64_HV
        unsigned long *rmap;
+       unsigned long *slot_phys;
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
 struct kvm_arch {
@@ -243,12 +246,12 @@ struct kvm_arch {
        int using_mmu_notifiers;
        u32 hpt_order;
        atomic_t vcpus_running;
+       u32 online_vcores;
        unsigned long hpt_npte;
        unsigned long hpt_mask;
+       atomic_t hpte_mod_interest;
        spinlock_t slot_phys_lock;
-       unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
-       int slot_npages[KVM_MEM_SLOTS_NUM];
-       unsigned short last_vcpu[NR_CPUS];
+       cpumask_t need_tlb_flush;
        struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
        struct kvmppc_linear_info *hpt_li;
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
@@ -273,6 +276,7 @@ struct kvmppc_vcore {
        int nap_count;
        int napping_threads;
        u16 pcpu;
+       u16 last_cpu;
        u8 vcore_state;
        u8 in_guest;
        struct list_head runnable_threads;
@@ -288,9 +292,10 @@ struct kvmppc_vcore {
 
 /* Values for vcore_state */
 #define VCORE_INACTIVE 0
-#define VCORE_RUNNING  1
-#define VCORE_EXITING  2
-#define VCORE_SLEEPING 3
+#define VCORE_SLEEPING 1
+#define VCORE_STARTING 2
+#define VCORE_RUNNING  3
+#define VCORE_EXITING  4
 
 /*
  * Struct used to manage memory for a virtual processor area
@@ -346,6 +351,27 @@ struct kvmppc_slb {
        bool class      : 1;
 };
 
+# ifdef CONFIG_PPC_FSL_BOOK3E
+#define KVMPPC_BOOKE_IAC_NUM   2
+#define KVMPPC_BOOKE_DAC_NUM   2
+# else
+#define KVMPPC_BOOKE_IAC_NUM   4
+#define KVMPPC_BOOKE_DAC_NUM   2
+# endif
+#define KVMPPC_BOOKE_MAX_IAC   4
+#define KVMPPC_BOOKE_MAX_DAC   2
+
+struct kvmppc_booke_debug_reg {
+       u32 dbcr0;
+       u32 dbcr1;
+       u32 dbcr2;
+#ifdef CONFIG_KVM_E500MC
+       u32 dbcr4;
+#endif
+       u64 iac[KVMPPC_BOOKE_MAX_IAC];
+       u64 dac[KVMPPC_BOOKE_MAX_DAC];
+};
+
 struct kvm_vcpu_arch {
        ulong host_stack;
        u32 host_pid;
@@ -380,13 +406,18 @@ struct kvm_vcpu_arch {
        u32 host_mas4;
        u32 host_mas6;
        u32 shadow_epcr;
-       u32 epcr;
        u32 shadow_msrp;
        u32 eplc;
        u32 epsc;
        u32 oldpir;
 #endif
 
+#if defined(CONFIG_BOOKE)
+#if defined(CONFIG_KVM_BOOKE_HV) || defined(CONFIG_64BIT)
+       u32 epcr;
+#endif
+#endif
+
 #ifdef CONFIG_PPC_BOOK3S
        /* For Gekko paired singles */
        u32 qpr[32];
@@ -440,8 +471,6 @@ struct kvm_vcpu_arch {
 
        u32 ccr0;
        u32 ccr1;
-       u32 dbcr0;
-       u32 dbcr1;
        u32 dbsr;
 
        u64 mmcr[3];
@@ -471,9 +500,12 @@ struct kvm_vcpu_arch {
        ulong fault_esr;
        ulong queued_dear;
        ulong queued_esr;
+       spinlock_t wdt_lock;
+       struct timer_list wdt_timer;
        u32 tlbcfg[4];
        u32 mmucfg;
        u32 epr;
+       struct kvmppc_booke_debug_reg dbg_reg;
 #endif
        gpa_t paddr_accessed;
        gva_t vaddr_accessed;
@@ -486,6 +518,7 @@ struct kvm_vcpu_arch {
        u8 osi_needed;
        u8 osi_enabled;
        u8 papr_enabled;
+       u8 watchdog_enabled;
        u8 sane;
        u8 cpu_type;
        u8 hcall_needed;
@@ -497,7 +530,6 @@ struct kvm_vcpu_arch {
        u64 dec_jiffies;
        u64 dec_expires;
        unsigned long pending_exceptions;
-       u16 last_cpu;
        u8 ceded;
        u8 prodded;
        u32 last_inst;
@@ -534,13 +566,17 @@ struct kvm_vcpu_arch {
        unsigned long dtl_index;
        u64 stolen_logged;
        struct kvmppc_vpa slb_shadow;
+
+       spinlock_t tbacct_lock;
+       u64 busy_stolen;
+       u64 busy_preempt;
 #endif
 };
 
 /* Values for vcpu->arch.state */
-#define KVMPPC_VCPU_STOPPED            0
-#define KVMPPC_VCPU_BUSY_IN_HOST       1
-#define KVMPPC_VCPU_RUNNABLE           2
+#define KVMPPC_VCPU_NOTREADY           0
+#define KVMPPC_VCPU_RUNNABLE           1
+#define KVMPPC_VCPU_BUSY_IN_HOST       2
 
 /* Values for vcpu->arch.io_gpr */
 #define KVM_MMIO_REG_MASK      0x001f
index 9365860fb7f61676a57233eb14de66db0cc0c65b..2b119654b4c1a5fcd2ce568fd83ad3a64bccdd03 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <uapi/asm/kvm_para.h>
 
-
 #ifdef CONFIG_KVM_GUEST
 
 #include <linux/of.h>
@@ -55,7 +54,7 @@ static unsigned long kvm_hypercall(unsigned long *in,
                                   unsigned long *out,
                                   unsigned long nr)
 {
-       return HC_EV_UNIMPLEMENTED;
+       return EV_UNIMPLEMENTED;
 }
 
 #endif
@@ -66,7 +65,7 @@ static inline long kvm_hypercall0_1(unsigned int nr, unsigned long *r2)
        unsigned long out[8];
        unsigned long r;
 
-       r = kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       r = kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
        *r2 = out[0];
 
        return r;
@@ -77,7 +76,7 @@ static inline long kvm_hypercall0(unsigned int nr)
        unsigned long in[8];
        unsigned long out[8];
 
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
@@ -86,7 +85,7 @@ static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
        unsigned long out[8];
 
        in[0] = p1;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
@@ -97,7 +96,7 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
 
        in[0] = p1;
        in[1] = p2;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
@@ -109,7 +108,7 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
        in[0] = p1;
        in[1] = p2;
        in[2] = p3;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
@@ -123,7 +122,7 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
        in[1] = p2;
        in[2] = p3;
        in[3] = p4;
-       return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+       return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 
index e006f0bdea95f1a9464c688928dc7206690f5c14..572aa75306191272c684a8263a5900cd876352c2 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <linux/kvm_host.h>
+#include <linux/bug.h>
 #ifdef CONFIG_PPC_BOOK3S
 #include <asm/kvm_book3s.h>
 #else
@@ -68,6 +69,8 @@ extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
 extern void kvmppc_decrementer_func(unsigned long data);
 extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
+extern int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
@@ -104,6 +107,7 @@ extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
                                          struct kvm_interrupt *irq);
+extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                   unsigned int op, int *advance);
@@ -111,6 +115,7 @@ extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn,
                                     ulong val);
 extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn,
                                     ulong *val);
+extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_booke_init(void);
 extern void kvmppc_booke_exit(void);
@@ -139,16 +144,28 @@ extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
 extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
+extern void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                                    struct kvm_memory_slot *dont);
+extern int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                                     unsigned long npages);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                               struct kvm_memory_slot *memslot,
                                struct kvm_userspace_memory_region *mem);
 extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem);
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old);
 extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
                                      struct kvm_ppc_smmu_info *info);
+extern void kvmppc_core_flush_memslot(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot);
 
 extern int kvmppc_bookehv_init(void);
 extern void kvmppc_bookehv_exit(void);
 
+extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);
+
+extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *);
+
 /*
  * Cuts out inst bits with ordering according to spec.
  * That means the leftmost bit is zero. All given bits are included.
@@ -182,6 +199,41 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)
        return r;
 }
 
+union kvmppc_one_reg {
+       u32     wval;
+       u64     dval;
+       vector128 vval;
+       u64     vsxval[2];
+       struct {
+               u64     addr;
+               u64     length;
+       }       vpaval;
+};
+
+#define one_reg_size(id)       \
+       (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+
+#define get_reg_val(id, reg)   ({              \
+       union kvmppc_one_reg __u;               \
+       switch (one_reg_size(id)) {             \
+       case 4: __u.wval = (reg); break;        \
+       case 8: __u.dval = (reg); break;        \
+       default: BUG();                         \
+       }                                       \
+       __u;                                    \
+})
+
+
+#define set_reg_val(id, val)   ({              \
+       u64 __v;                                \
+       switch (one_reg_size(id)) {             \
+       case 4: __v = (val).wval; break;        \
+       case 8: __v = (val).dval; break;        \
+       default: BUG();                         \
+       }                                       \
+       __v;                                    \
+})
+
 void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
@@ -190,6 +242,8 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
 
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
@@ -230,5 +284,36 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
        }
 }
 
+/* Please call after prepare_to_enter. This function puts the lazy ee state
+   back to normal mode, without actually enabling interrupts. */
+static inline void kvmppc_lazy_ee_enable(void)
+{
+#ifdef CONFIG_PPC64
+       /* Only need to enable IRQs by hard enabling them after this */
+       local_paca->irq_happened = 0;
+       local_paca->soft_enabled = 1;
+#endif
+}
+
+static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
+{
+       ulong ea;
+       ulong msr_64bit = 0;
+
+       ea = kvmppc_get_gpr(vcpu, rb);
+       if (ra)
+               ea += kvmppc_get_gpr(vcpu, ra);
+
+#if defined(CONFIG_PPC_BOOK3E_64)
+       msr_64bit = MSR_CM;
+#elif defined(CONFIG_PPC_BOOK3S_64)
+       msr_64bit = MSR_SF;
+#endif
+
+       if (!(vcpu->arch.shared->msr & msr_64bit))
+               ea = (uint32_t)ea;
+
+       return ea;
+}
 
 #endif /* __POWERPC_KVM_PPC_H__ */
index eeabcdbc30f7ab00bd7856983e020e70db8a7045..99d43e0c1e4af1198ea4fd07ad3834d0eb4c8f82 100644 (file)
@@ -59,7 +59,7 @@
 #define MAS1_TSIZE_SHIFT       7
 #define MAS1_TSIZE(x)          (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
 
-#define MAS2_EPN               0xFFFFF000
+#define MAS2_EPN               (~0xFFFUL)
 #define MAS2_X0                        0x00000040
 #define MAS2_X1                        0x00000020
 #define MAS2_W                 0x00000010
index 9673f73eb8db2294159a3356266b97c7df6734c2..2fdb47a19efda298b8ddc3749f174be75e1e7a63 100644 (file)
@@ -121,6 +121,16 @@ extern char initial_stab[];
 #define PP_RXRX 3      /* Supervisor read,       User read */
 #define PP_RXXX        (HPTE_R_PP0 | 2)        /* Supervisor read, user none */
 
+/* Fields for tlbiel instruction in architecture 2.06 */
+#define TLBIEL_INVAL_SEL_MASK  0xc00   /* invalidation selector */
+#define  TLBIEL_INVAL_PAGE     0x000   /* invalidate a single page */
+#define  TLBIEL_INVAL_SET_LPID 0x800   /* invalidate a set for current LPID */
+#define  TLBIEL_INVAL_SET      0xc00   /* invalidate a set for all LPIDs */
+#define TLBIEL_INVAL_SET_MASK  0xfff000        /* set number to inval. */
+#define TLBIEL_INVAL_SET_SHIFT 12
+
+#define POWER7_TLB_SETS                128     /* # sets in POWER7 TLB */
+
 #ifndef __ASSEMBLY__
 
 struct hash_pte {
index 639dc96077ab815addab3a43bc894e5654fe6bd9..d697b08994c916dd40e6eabb593fb28e67cd6135 100644 (file)
@@ -34,7 +34,7 @@ struct op_system_config {
        unsigned long mmcra;
 #ifdef CONFIG_OPROFILE_CELL
        /* Register for oprofile user tool to check cell kernel profiling
-        * suport.
+        * support.
         */
        unsigned long cell_support;
 #endif
index eedf427c9124f3c7fc4e13d5dd293b41dafd5f82..3e13e23e4fdf8a4e3fc84e07ef091cffdfc0492f 100644 (file)
@@ -23,7 +23,7 @@
 
 /* Note the full page bits must be in the same location as for normal
  * 4k pages as the same assembly will be used to insert 64K pages
- * wether the kernel has CONFIG_PPC_64K_PAGES or not
+ * whether the kernel has CONFIG_PPC_64K_PAGES or not
  */
 #define _PAGE_F_SECOND  0x00008000 /* full page: hidx bits */
 #define _PAGE_F_GIX     0x00007000 /* full page: hidx bits */
index d24c14163966599ed3a78f559f80191f7cd53693..97d37278ea2da4f978bbf5b5967b5ed22912ee7d 100644 (file)
 #define          SRR1_WS_DEEPER        0x00020000 /* Some resources not maintained */
 #define          SRR1_WS_DEEP          0x00010000 /* All resources maintained */
 #define   SRR1_PROGFPE         0x00100000 /* Floating Point Enabled */
+#define   SRR1_PROGILL         0x00080000 /* Illegal instruction */
 #define   SRR1_PROGPRIV                0x00040000 /* Privileged instruction */
 #define   SRR1_PROGTRAP                0x00020000 /* Trap */
 #define   SRR1_PROGADDR                0x00010000 /* SRR0 contains subsequent addr */
index 2d916c4982c5136a71b10f917606757aa743792f..e07e6af5e1ff9938a00468d49c46aaaee7be8ee9 100644 (file)
 #define TCR_FIE                0x00800000      /* FIT Interrupt Enable */
 #define TCR_ARE                0x00400000      /* Auto Reload Enable */
 
+#ifdef CONFIG_E500
+#define TCR_GET_WP(tcr)  ((((tcr) & 0xC0000000) >> 30) | \
+                             (((tcr) & 0x1E0000) >> 15))
+#else
+#define TCR_GET_WP(tcr)  (((tcr) & 0xC0000000) >> 30)
+#endif
+
 /* Bit definitions for the TSR. */
 #define TSR_ENW                0x80000000      /* Enable Next Watchdog */
 #define TSR_WIS                0x40000000      /* WDT Interrupt Status */
index e807e9d8e3f7ea60b184da83176d54b3bbb40dcd..5a4e437c238d814ad421c4c0c3eff12391cf316f 100644 (file)
@@ -67,6 +67,14 @@ void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
 void generic_set_cpu_up(unsigned int cpu);
 int generic_check_cpu_restart(unsigned int cpu);
+
+extern void inhibit_secondary_onlining(void);
+extern void uninhibit_secondary_onlining(void);
+
+#else /* HOTPLUG_CPU */
+static inline void inhibit_secondary_onlining(void) {}
+static inline void uninhibit_secondary_onlining(void) {}
+
 #endif
 
 #ifdef CONFIG_PPC64
index ae20ce1af4c739e9085f3e53caf421a35f41c529..6e909f3e6a466972285aa2797fd315b898313720 100644 (file)
   *
   * At this point, the OF driver seems to have a limitation on transfer
   * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
-  * wether this is just an OF limit due to some temporary buffer size
+  * whether this is just an OF limit due to some temporary buffer size
   * or if this is an SMU imposed limit. This driver has the same limitation
   * for now as I use a 0x10 bytes temporary buffer as well
   *
  *   3 (optional): enable nmi? [0x00 or 0x01]
  *
  * Returns:
- *   If parameter 2 is 0x00 and parameter 3 is not specified, returns wether
+ *   If parameter 2 is 0x00 and parameter 3 is not specified, returns whether
  *   NMI is enabled. Otherwise unknown.
  */
 #define   SMU_CMD_MISC_df_NMI_OPTION           0x04
index a33c3c03bb2e104693eab939e0ffc3e901508259..f7bca6370745b49133a771d9aff43a742116b229 100644 (file)
@@ -7,6 +7,7 @@ header-y += bootx.h
 header-y += byteorder.h
 header-y += cputable.h
 header-y += elf.h
+header-y += epapr_hcalls.h
 header-y += errno.h
 header-y += fcntl.h
 header-y += ioctl.h
diff --git a/arch/powerpc/include/uapi/asm/epapr_hcalls.h b/arch/powerpc/include/uapi/asm/epapr_hcalls.h
new file mode 100644 (file)
index 0000000..7f9c74b
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UAPI_ASM_POWERPC_EPAPR_HCALLS_H
+#define _UAPI_ASM_POWERPC_EPAPR_HCALLS_H
+
+#define EV_BYTE_CHANNEL_SEND           1
+#define EV_BYTE_CHANNEL_RECEIVE                2
+#define EV_BYTE_CHANNEL_POLL           3
+#define EV_INT_SET_CONFIG              4
+#define EV_INT_GET_CONFIG              5
+#define EV_INT_SET_MASK                        6
+#define EV_INT_GET_MASK                        7
+#define EV_INT_IACK                    9
+#define EV_INT_EOI                     10
+#define EV_INT_SEND_IPI                        11
+#define EV_INT_SET_TASK_PRIORITY       12
+#define EV_INT_GET_TASK_PRIORITY       13
+#define EV_DOORBELL_SEND               14
+#define EV_MSGSND                      15
+#define EV_IDLE                                16
+
+/* vendor ID: epapr */
+#define EV_LOCAL_VENDOR_ID             0       /* for private use */
+#define EV_EPAPR_VENDOR_ID             1
+#define EV_FSL_VENDOR_ID               2       /* Freescale Semiconductor */
+#define EV_IBM_VENDOR_ID               3       /* IBM */
+#define EV_GHS_VENDOR_ID               4       /* Green Hills Software */
+#define EV_ENEA_VENDOR_ID              5       /* Enea */
+#define EV_WR_VENDOR_ID                        6       /* Wind River Systems */
+#define EV_AMCC_VENDOR_ID              7       /* Applied Micro Circuits */
+#define EV_KVM_VENDOR_ID               42      /* KVM */
+
+/* The max number of bytes that a byte channel can send or receive per call */
+#define EV_BYTE_CHANNEL_MAX_BYTES      16
+
+
+#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
+#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
+
+/* epapr return codes */
+#define EV_SUCCESS             0
+#define EV_EPERM               1       /* Operation not permitted */
+#define EV_ENOENT              2       /*  Entry Not Found */
+#define EV_EIO                 3       /* I/O error occured */
+#define EV_EAGAIN              4       /* The operation had insufficient
+                                        * resources to complete and should be
+                                        * retried
+                                        */
+#define EV_ENOMEM              5       /* There was insufficient memory to
+                                        * complete the operation */
+#define EV_EFAULT              6       /* Bad guest address */
+#define EV_ENODEV              7       /* No such device */
+#define EV_EINVAL              8       /* An argument supplied to the hcall
+                                          was out of range or invalid */
+#define EV_INTERNAL            9       /* An internal error occured */
+#define EV_CONFIG              10      /* A configuration error was detected */
+#define EV_INVALID_STATE       11      /* The object is in an invalid state */
+#define EV_UNIMPLEMENTED       12      /* Unimplemented hypercall */
+#define EV_BUFFER_OVERFLOW     13      /* Caller-supplied buffer too small */
+
+#endif /* _UAPI_ASM_POWERPC_EPAPR_HCALLS_H */
index 1bea4d8ea6f432d3e3425752aafa156a8fe7710b..2fba8a66fb10f8a609d2e95e3b97174bbd70a6a6 100644 (file)
@@ -221,6 +221,12 @@ struct kvm_sregs {
 
                        __u32 dbsr;     /* KVM_SREGS_E_UPDATE_DBSR */
                        __u32 dbcr[3];
+                       /*
+                        * iac/dac registers are 64bit wide, while this API
+                        * interface provides only lower 32 bits on 64 bit
+                        * processors. ONE_REG interface is added for 64bit
+                        * iac/dac registers.
+                        */
                        __u32 iac[4];
                        __u32 dac[2];
                        __u32 dvc[2];
@@ -325,6 +331,86 @@ struct kvm_book3e_206_tlb_params {
        __u32 reserved[8];
 };
 
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+       __u64   flags;
+       __u64   start_index;
+       __u64   reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY       ((__u64)0x1)
+#define KVM_GET_HTAB_WRITE             ((__u64)0x2)
+
+/*
+ * Data read on the file descriptor is formatted as a series of
+ * records, each consisting of a header followed by a series of
+ * `n_valid' HPTEs (16 bytes each), which are all valid.  Following
+ * those valid HPTEs there are `n_invalid' invalid HPTEs, which
+ * are not represented explicitly in the stream.  The same format
+ * is used for writing.
+ */
+struct kvm_get_htab_header {
+       __u32   index;
+       __u16   n_valid;
+       __u16   n_invalid;
+};
+
 #define KVM_REG_PPC_HIOR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR                (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR      (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR                (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n)     (KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0                (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n)      (KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31       (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0       (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n)     (KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31      (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB    (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL    (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
+
+#define KVM_REG_PPC_EPCR       (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
 
 #endif /* __LINUX_KVM_POWERPC_H */
index 5e04383a1db5867c9c678b8ad3c6cadf760cab58..ed0e0254b47f2b3ae67940e15d151b58dddc7462 100644 (file)
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
 };
 
 #define KVM_SC_MAGIC_R0                0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM          (42 << 16)
-#define HC_EV_SUCCESS          0
-#define HC_EV_UNIMPLEMENTED    12
+
+#define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <uapi/asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE 1
 
index 7523539cfe9f88e0a49e4b8a5715e8dff7a64fc7..4e23ba2f3ca7622d7f2fe66f6d0925bae26f0cf1 100644 (file)
@@ -441,8 +441,7 @@ int main(void)
        DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
        DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
        DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
-       DEFINE(KVM_ONLINE_CPUS, offsetof(struct kvm, online_vcpus.counter));
-       DEFINE(KVM_LAST_VCPU, offsetof(struct kvm, arch.last_vcpu));
+       DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
        DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
        DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
        DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
@@ -470,7 +469,6 @@ int main(void)
        DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
        DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
        DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
-       DEFINE(VCPU_LAST_CPU, offsetof(struct kvm_vcpu, arch.last_cpu));
        DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
        DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
        DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
index 697b390ebfd8af815075b1764699da52a7402da2..62c0dc2378266653cd97591f095261d2ed5c901a 100644 (file)
@@ -8,13 +8,41 @@
  */
 
 #include <linux/threads.h>
+#include <asm/epapr_hcalls.h>
 #include <asm/reg.h>
 #include <asm/page.h>
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
+#include <asm/asm-compat.h>
 #include <asm/asm-offsets.h>
 
+/* epapr_ev_idle() was derived from e500_idle() */
+_GLOBAL(epapr_ev_idle)
+       CURRENT_THREAD_INFO(r3, r1)
+       PPC_LL  r4, TI_LOCAL_FLAGS(r3)  /* set napping bit */
+       ori     r4, r4,_TLF_NAPPING     /* so when we take an exception */
+       PPC_STL r4, TI_LOCAL_FLAGS(r3)  /* it will return to our caller */
+
+       wrteei  1
+
+idle_loop:
+       LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
+
+.global epapr_ev_idle_start
+epapr_ev_idle_start:
+       li      r3, -1
+       nop
+       nop
+       nop
+
+       /*
+        * Guard against spurious wakeups from a hypervisor --
+        * only interrupt will cause us to return to LR due to
+        * _TLF_NAPPING.
+        */
+       b       idle_loop
+
 /* Hypercall entry point. Will be patched with device tree instructions. */
 .global epapr_hypercall_start
 epapr_hypercall_start:
index 028aeae370b657fb91096be96243efdf0e8bf61f..f3eab8594d9f873432deb94c770db354f20ffc76 100644 (file)
 #include <asm/epapr_hcalls.h>
 #include <asm/cacheflush.h>
 #include <asm/code-patching.h>
+#include <asm/machdep.h>
+
+extern void epapr_ev_idle(void);
+extern u32 epapr_ev_idle_start[];
 
 bool epapr_paravirt_enabled;
 
@@ -41,8 +45,13 @@ static int __init epapr_paravirt_init(void)
        if (len % 4 || len > (4 * 4))
                return -ENODEV;
 
-       for (i = 0; i < (len / 4); i++)
+       for (i = 0; i < (len / 4); i++) {
                patch_instruction(epapr_hypercall_start + i, insts[i]);
+               patch_instruction(epapr_ev_idle_start + i, insts[i]);
+       }
+
+       if (of_get_property(hyper_node, "has-idle", NULL))
+               ppc_md.power_save = epapr_ev_idle;
 
        epapr_paravirt_enabled = true;
 
index 867db1de8949571a152cd9559a5b36bb7c91e090..a61b133c4f99b2a380b274fa7c39c7a5d301761a 100644 (file)
@@ -419,7 +419,7 @@ static void kvm_map_magic_page(void *data)
        in[0] = KVM_MAGIC_PAGE;
        in[1] = KVM_MAGIC_PAGE;
 
-       kvm_hypercall(in, out, HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE);
+       kvm_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE));
 
        *features = out[0];
 }
index bedd12e1cfbcc0b636eea99f1ca18728938ed2f4..0733b05eb856b05476621296b45fbde7661ef6a8 100644 (file)
@@ -387,7 +387,7 @@ void __init find_legacy_serial_ports(void)
                        of_node_put(parent);
                        continue;
                }
-               /* Check for known pciclass, and also check wether we have
+               /* Check for known pciclass, and also check whether we have
                 * a device with child nodes for ports or not
                 */
                if (of_device_is_compatible(np, "pciclass,0700") ||
index 2049f2d00ffef60f0e7b1f9cfa5fc9cbd25a1758..9db8ec07ec94ff4d953bb7277d1698304e39190c 100644 (file)
@@ -82,7 +82,7 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
                return -ENXIO;
 
        /* Claim resources. This might need some rework as well depending
-        * wether we are doing probe-only or not, like assigning unassigned
+        * whether we are doing probe-only or not, like assigning unassigned
         * resources etc...
         */
        pcibios_claim_one_bus(phb->bus);
index 19e4288d84865e7b97f1a22a6fe099037b46aeef..78b8766fd79e4605f96a103c6562ff62caa37c5e 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/dcr.h>
 #include <asm/ftrace.h>
 #include <asm/switch_to.h>
+#include <asm/epapr_hcalls.h>
 
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
@@ -191,3 +192,7 @@ EXPORT_SYMBOL(__arch_hweight64);
 #ifdef CONFIG_PPC_BOOK3S_64
 EXPORT_SYMBOL_GPL(mmu_psize_defs);
 #endif
+
+#ifdef CONFIG_EPAPR_PARAVIRT
+EXPORT_SYMBOL(epapr_hypercall_start);
+#endif
index d183f8719a505ce18e4cc8cb06ee4df3e8fa8674..1ca045d443249ebfa344dd01b15fe8f937f03674 100644 (file)
@@ -83,7 +83,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
         * the context). This is very important because we must ensure we
         * don't lose the VRSAVE content that may have been set prior to
         * the process doing its first vector operation
-        * Userland shall check AT_HWCAP to know wether it can rely on the
+        * Userland shall check AT_HWCAP to know whether it can rely on the
         * v_regs pointer or not
         */
 #ifdef CONFIG_ALTIVEC
index 2b952b5386fd5eae72bcf6a7c8320d1768156277..e5b133ebd8a57820bb65ff0ad5243afb85fa8fdd 100644 (file)
@@ -427,6 +427,45 @@ int generic_check_cpu_restart(unsigned int cpu)
 {
        return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
 }
+
+static atomic_t secondary_inhibit_count;
+
+/*
+ * Don't allow secondary CPU threads to come online
+ */
+void inhibit_secondary_onlining(void)
+{
+       /*
+        * This makes secondary_inhibit_count stable during cpu
+        * online/offline operations.
+        */
+       get_online_cpus();
+
+       atomic_inc(&secondary_inhibit_count);
+       put_online_cpus();
+}
+EXPORT_SYMBOL_GPL(inhibit_secondary_onlining);
+
+/*
+ * Allow secondary CPU threads to come online again
+ */
+void uninhibit_secondary_onlining(void)
+{
+       get_online_cpus();
+       atomic_dec(&secondary_inhibit_count);
+       put_online_cpus();
+}
+EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining);
+
+static int secondaries_inhibited(void)
+{
+       return atomic_read(&secondary_inhibit_count);
+}
+
+#else /* HOTPLUG_CPU */
+
+#define secondaries_inhibited()                0
+
 #endif
 
 static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle)
@@ -445,6 +484,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int rc, c;
 
+       /*
+        * Don't allow secondary threads to come online if inhibited
+        */
+       if (threads_per_core > 1 && secondaries_inhibited() &&
+           cpu % threads_per_core != 0)
+               return -EBUSY;
+
        if (smp_ops == NULL ||
            (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
                return -EINVAL;
index 50e7dbc7356cd0ed574f3ac9fa61ea509fb26439..3d7fd21c65f92eeeb26ce19fc9d7fe07d0cdb36c 100644 (file)
@@ -83,6 +83,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
                vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
        vcpu->arch.cpu_type = KVM_CPU_440;
+       vcpu->arch.pvr = mfspr(SPRN_PVR);
 
        return 0;
 }
index c8c61578fdfc6e8420497854971d8da7b6d74598..35ec0a8547dabb86977f0e24657f8ba710cd4f69 100644 (file)
 #include "booke.h"
 #include "44x_tlb.h"
 
+#define XOP_MFDCRX  259
 #define XOP_MFDCR   323
+#define XOP_MTDCRX  387
 #define XOP_MTDCR   451
 #define XOP_TLBSX   914
 #define XOP_ICCCI   966
 #define XOP_TLBWE   978
 
+static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
+{
+       /* emulate some access in kernel */
+       switch (dcrn) {
+       case DCRN_CPR0_CONFIG_ADDR:
+               vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
+               return EMULATE_DONE;
+       default:
+               vcpu->run->dcr.dcrn = dcrn;
+               vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs);
+               vcpu->run->dcr.is_write = 1;
+               vcpu->arch.dcr_is_write = 1;
+               vcpu->arch.dcr_needed = 1;
+               kvmppc_account_exit(vcpu, DCR_EXITS);
+               return EMULATE_DO_DCR;
+       }
+}
+
+static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
+{
+       /* The guest may access CPR0 registers to determine the timebase
+        * frequency, and it must know the real host frequency because it
+        * can directly access the timebase registers.
+        *
+        * It would be possible to emulate those accesses in userspace,
+        * but userspace can really only figure out the end frequency.
+        * We could decompose that into the factors that compute it, but
+        * that's tricky math, and it's easier to just report the real
+        * CPR0 values.
+        */
+       switch (dcrn) {
+       case DCRN_CPR0_CONFIG_ADDR:
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
+               break;
+       case DCRN_CPR0_CONFIG_DATA:
+               local_irq_disable();
+               mtdcr(DCRN_CPR0_CONFIG_ADDR,
+                         vcpu->arch.cpr0_cfgaddr);
+               kvmppc_set_gpr(vcpu, rt,
+                              mfdcr(DCRN_CPR0_CONFIG_DATA));
+               local_irq_enable();
+               break;
+       default:
+               vcpu->run->dcr.dcrn = dcrn;
+               vcpu->run->dcr.data =  0;
+               vcpu->run->dcr.is_write = 0;
+               vcpu->arch.dcr_is_write = 0;
+               vcpu->arch.io_gpr = rt;
+               vcpu->arch.dcr_needed = 1;
+               kvmppc_account_exit(vcpu, DCR_EXITS);
+               return EMULATE_DO_DCR;
+       }
+
+       return EMULATE_DONE;
+}
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -50,55 +108,21 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                switch (get_xop(inst)) {
 
                case XOP_MFDCR:
-                       /* The guest may access CPR0 registers to determine the timebase
-                        * frequency, and it must know the real host frequency because it
-                        * can directly access the timebase registers.
-                        *
-                        * It would be possible to emulate those accesses in userspace,
-                        * but userspace can really only figure out the end frequency.
-                        * We could decompose that into the factors that compute it, but
-                        * that's tricky math, and it's easier to just report the real
-                        * CPR0 values.
-                        */
-                       switch (dcrn) {
-                       case DCRN_CPR0_CONFIG_ADDR:
-                               kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
-                               break;
-                       case DCRN_CPR0_CONFIG_DATA:
-                               local_irq_disable();
-                               mtdcr(DCRN_CPR0_CONFIG_ADDR,
-                                         vcpu->arch.cpr0_cfgaddr);
-                               kvmppc_set_gpr(vcpu, rt,
-                                              mfdcr(DCRN_CPR0_CONFIG_DATA));
-                               local_irq_enable();
-                               break;
-                       default:
-                               run->dcr.dcrn = dcrn;
-                               run->dcr.data =  0;
-                               run->dcr.is_write = 0;
-                               vcpu->arch.io_gpr = rt;
-                               vcpu->arch.dcr_needed = 1;
-                               kvmppc_account_exit(vcpu, DCR_EXITS);
-                               emulated = EMULATE_DO_DCR;
-                       }
+                       emulated = emulate_mfdcr(vcpu, rt, dcrn);
+                       break;
 
+               case XOP_MFDCRX:
+                       emulated = emulate_mfdcr(vcpu, rt,
+                                       kvmppc_get_gpr(vcpu, ra));
                        break;
 
                case XOP_MTDCR:
-                       /* emulate some access in kernel */
-                       switch (dcrn) {
-                       case DCRN_CPR0_CONFIG_ADDR:
-                               vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
-                               break;
-                       default:
-                               run->dcr.dcrn = dcrn;
-                               run->dcr.data = kvmppc_get_gpr(vcpu, rs);
-                               run->dcr.is_write = 1;
-                               vcpu->arch.dcr_needed = 1;
-                               kvmppc_account_exit(vcpu, DCR_EXITS);
-                               emulated = EMULATE_DO_DCR;
-                       }
+                       emulated = emulate_mtdcr(vcpu, rs, dcrn);
+                       break;
 
+               case XOP_MTDCRX:
+                       emulated = emulate_mtdcr(vcpu, rs,
+                                       kvmppc_get_gpr(vcpu, ra));
                        break;
 
                case XOP_TLBWE:
index f4dacb9c57fac1a275291aedf1357c3070b6f750..4730c953f4357f41df6bf87a8a5a590c53c6f2e1 100644 (file)
@@ -20,6 +20,7 @@ config KVM
        bool
        select PREEMPT_NOTIFIERS
        select ANON_INODES
+       select HAVE_KVM_EVENTFD
 
 config KVM_BOOK3S_HANDLER
        bool
@@ -36,6 +37,7 @@ config KVM_BOOK3S_64_HANDLER
 config KVM_BOOK3S_PR
        bool
        select KVM_MMIO
+       select MMU_NOTIFIER
 
 config KVM_BOOK3S_32
        tristate "KVM support for PowerPC book3s_32 processors"
@@ -123,6 +125,7 @@ config KVM_E500V2
        depends on EXPERIMENTAL && E500 && !PPC_E500MC
        select KVM
        select KVM_MMIO
+       select MMU_NOTIFIER
        ---help---
          Support running unmodified E500 guest kernels in virtual machines on
          E500v2 host processors.
@@ -138,6 +141,7 @@ config KVM_E500MC
        select KVM
        select KVM_MMIO
        select KVM_BOOKE_HV
+       select MMU_NOTIFIER
        ---help---
          Support running unmodified E500MC/E5500 (32-bit) guest kernels in
          virtual machines on E500MC/E5500 host processors.
index c2a08636e6d4294a12e5148fd4a8dd8fe07dbe7d..1e473d46322cd977e5948ec0012ee3563d04ba8b 100644 (file)
@@ -6,7 +6,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
 
-common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
+common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o \
+                                               eventfd.o)
 
 CFLAGS_44x_tlb.o  := -I.
 CFLAGS_e500_tlb.o := -I.
@@ -72,10 +73,12 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
        book3s_hv_rmhandlers.o \
        book3s_hv_rm_mmu.o \
        book3s_64_vio_hv.o \
+       book3s_hv_ras.o \
        book3s_hv_builtin.o
 
 kvm-book3s_64-module-objs := \
        ../../../virt/kvm/kvm_main.o \
+       ../../../virt/kvm/eventfd.o \
        powerpc.o \
        emulate.o \
        book3s.o \
index 3f2a8360c857f1aae94a13631b2eb099a96795a0..a4b64528524098633bcec777404c2fcbf5ac2fe6 100644 (file)
@@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        int i;
@@ -476,6 +485,122 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
        return -ENOTSUPP;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r;
+       union kvmppc_one_reg val;
+       int size;
+       long int i;
+
+       size = one_reg_size(reg->id);
+       if (size > sizeof(val))
+               return -EINVAL;
+
+       r = kvmppc_get_one_reg(vcpu, reg->id, &val);
+
+       if (r == -EINVAL) {
+               r = 0;
+               switch (reg->id) {
+               case KVM_REG_PPC_DAR:
+                       val = get_reg_val(reg->id, vcpu->arch.shared->dar);
+                       break;
+               case KVM_REG_PPC_DSISR:
+                       val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
+                       break;
+               case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+                       i = reg->id - KVM_REG_PPC_FPR0;
+                       val = get_reg_val(reg->id, vcpu->arch.fpr[i]);
+                       break;
+               case KVM_REG_PPC_FPSCR:
+                       val = get_reg_val(reg->id, vcpu->arch.fpscr);
+                       break;
+#ifdef CONFIG_ALTIVEC
+               case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0];
+                       break;
+               case KVM_REG_PPC_VSCR:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]);
+                       break;
+#endif /* CONFIG_ALTIVEC */
+               default:
+                       r = -EINVAL;
+                       break;
+               }
+       }
+       if (r)
+               return r;
+
+       if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
+               r = -EFAULT;
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r;
+       union kvmppc_one_reg val;
+       int size;
+       long int i;
+
+       size = one_reg_size(reg->id);
+       if (size > sizeof(val))
+               return -EINVAL;
+
+       if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
+               return -EFAULT;
+
+       r = kvmppc_set_one_reg(vcpu, reg->id, &val);
+
+       if (r == -EINVAL) {
+               r = 0;
+               switch (reg->id) {
+               case KVM_REG_PPC_DAR:
+                       vcpu->arch.shared->dar = set_reg_val(reg->id, val);
+                       break;
+               case KVM_REG_PPC_DSISR:
+                       vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
+                       break;
+               case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+                       i = reg->id - KVM_REG_PPC_FPR0;
+                       vcpu->arch.fpr[i] = set_reg_val(reg->id, val);
+                       break;
+               case KVM_REG_PPC_FPSCR:
+                       vcpu->arch.fpscr = set_reg_val(reg->id, val);
+                       break;
+#ifdef CONFIG_ALTIVEC
+               case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
+                       break;
+               case KVM_REG_PPC_VSCR:
+                       if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+                               r = -ENXIO;
+                               break;
+                       }
+                       vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
+                       break;
+#endif /* CONFIG_ALTIVEC */
+               default:
+                       r = -EINVAL;
+                       break;
+               }
+       }
+
+       return r;
+}
+
 int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
                                   struct kvm_translation *tr)
 {
index b0f625a33345a6e7cf690d21b041507adae5f61f..00e619bf608ef124c6b348e236afebff258089b5 100644 (file)
@@ -155,7 +155,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 
        /* Get host physical address for gpa */
        hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
-       if (is_error_pfn(hpaddr)) {
+       if (is_error_noslot_pfn(hpaddr)) {
                printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
                                 orig_pte->eaddr);
                r = -EINVAL;
@@ -254,6 +254,7 @@ next_pteg:
 
        kvmppc_mmu_hpte_cache_map(vcpu, pte);
 
+       kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 out:
        return r;
 }
index 4d72f9ebc554bddf331ac9d9201b10cd0d3e484f..ead58e3172945d81e863ba937cc1d88b93922558 100644 (file)
@@ -93,7 +93,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 
        /* Get host physical address for gpa */
        hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
-       if (is_error_pfn(hpaddr)) {
+       if (is_error_noslot_pfn(hpaddr)) {
                printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr);
                r = -EINVAL;
                goto out;
@@ -171,6 +171,7 @@ map_again:
 
                kvmppc_mmu_hpte_cache_map(vcpu, pte);
        }
+       kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 
 out:
        return r;
index d95d11322a159912230832371eefbe74c61c8e62..8cc18abd6dde6b486996bf9f4719fdeb12e0c65e 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
 #include <linux/vmalloc.h>
+#include <linux/srcu.h>
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 /* Power architecture requires HPT is at least 256kB */
 #define PPC_MIN_HPT_ORDER      18
 
+static long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
+                               long pte_index, unsigned long pteh,
+                               unsigned long ptel, unsigned long *pte_idx_ret);
+static void kvmppc_rmap_reset(struct kvm *kvm);
+
 long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
 {
        unsigned long hpt;
@@ -137,10 +145,11 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp)
                /* Set the entire HPT to 0, i.e. invalid HPTEs */
                memset((void *)kvm->arch.hpt_virt, 0, 1ul << order);
                /*
-                * Set the whole last_vcpu array to an invalid vcpu number.
-                * This ensures that each vcpu will flush its TLB on next entry.
+                * Reset all the reverse-mapping chains for all memslots
                 */
-               memset(kvm->arch.last_vcpu, 0xff, sizeof(kvm->arch.last_vcpu));
+               kvmppc_rmap_reset(kvm);
+               /* Ensure that each vcpu will flush its TLB on next entry. */
+               cpumask_setall(&kvm->arch.need_tlb_flush);
                *htab_orderp = order;
                err = 0;
        } else {
@@ -184,6 +193,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
        unsigned long addr, hash;
        unsigned long psize;
        unsigned long hp0, hp1;
+       unsigned long idx_ret;
        long ret;
        struct kvm *kvm = vcpu->kvm;
 
@@ -215,7 +225,8 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
                hash = (hash << 3) + 7;
                hp_v = hp0 | ((addr >> 16) & ~0x7fUL);
                hp_r = hp1 | addr;
-               ret = kvmppc_virtmode_h_enter(vcpu, H_EXACT, hash, hp_v, hp_r);
+               ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, hash, hp_v, hp_r,
+                                                &idx_ret);
                if (ret != H_SUCCESS) {
                        pr_err("KVM: map_vrma at %lx failed, ret=%ld\n",
                               addr, ret);
@@ -260,7 +271,7 @@ static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
 
 /*
  * This is called to get a reference to a guest page if there isn't
- * one already in the kvm->arch.slot_phys[][] arrays.
+ * one already in the memslot->arch.slot_phys[] array.
  */
 static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
                                  struct kvm_memory_slot *memslot,
@@ -275,7 +286,7 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
        struct vm_area_struct *vma;
        unsigned long pfn, i, npages;
 
-       physp = kvm->arch.slot_phys[memslot->id];
+       physp = memslot->arch.slot_phys;
        if (!physp)
                return -EINVAL;
        if (physp[gfn - memslot->base_gfn])
@@ -353,15 +364,10 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
        return err;
 }
 
-/*
- * We come here on a H_ENTER call from the guest when we are not
- * using mmu notifiers and we don't have the requested page pinned
- * already.
- */
-long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
-                       long pte_index, unsigned long pteh, unsigned long ptel)
+long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
+                               long pte_index, unsigned long pteh,
+                               unsigned long ptel, unsigned long *pte_idx_ret)
 {
-       struct kvm *kvm = vcpu->kvm;
        unsigned long psize, gpa, gfn;
        struct kvm_memory_slot *memslot;
        long ret;
@@ -389,8 +395,8 @@ long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
  do_insert:
        /* Protect linux PTE lookup from page table destruction */
        rcu_read_lock_sched();  /* this disables preemption too */
-       vcpu->arch.pgdir = current->mm->pgd;
-       ret = kvmppc_h_enter(vcpu, flags, pte_index, pteh, ptel);
+       ret = kvmppc_do_h_enter(kvm, flags, pte_index, pteh, ptel,
+                               current->mm->pgd, false, pte_idx_ret);
        rcu_read_unlock_sched();
        if (ret == H_TOO_HARD) {
                /* this can't happen */
@@ -401,6 +407,19 @@ long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 
 }
 
+/*
+ * We come here on a H_ENTER call from the guest when we are not
+ * using mmu notifiers and we don't have the requested page pinned
+ * already.
+ */
+long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                            long pte_index, unsigned long pteh,
+                            unsigned long ptel)
+{
+       return kvmppc_virtmode_do_h_enter(vcpu->kvm, flags, pte_index,
+                                         pteh, ptel, &vcpu->arch.gpr[4]);
+}
+
 static struct kvmppc_slb *kvmppc_mmu_book3s_hv_find_slbe(struct kvm_vcpu *vcpu,
                                                         gva_t eaddr)
 {
@@ -570,7 +589,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        struct kvm *kvm = vcpu->kvm;
        unsigned long *hptep, hpte[3], r;
        unsigned long mmu_seq, psize, pte_size;
-       unsigned long gfn, hva, pfn;
+       unsigned long gpa, gfn, hva, pfn;
        struct kvm_memory_slot *memslot;
        unsigned long *rmap;
        struct revmap_entry *rev;
@@ -608,15 +627,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        /* Translate the logical address and get the page */
        psize = hpte_page_size(hpte[0], r);
-       gfn = hpte_rpn(r, psize);
+       gpa = (r & HPTE_R_RPN & ~(psize - 1)) | (ea & (psize - 1));
+       gfn = gpa >> PAGE_SHIFT;
        memslot = gfn_to_memslot(kvm, gfn);
 
        /* No memslot means it's an emulated MMIO region */
-       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
-               unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
                return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
                                              dsisr & DSISR_ISSTORE);
-       }
 
        if (!kvm->arch.using_mmu_notifiers)
                return -EFAULT;         /* should never get here */
@@ -710,7 +728,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        /* Check if we might have been invalidated; let the guest retry if so */
        ret = RESUME_GUEST;
-       if (mmu_notifier_retry(vcpu, mmu_seq)) {
+       if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) {
                unlock_rmap(rmap);
                goto out_unlock;
        }
@@ -756,6 +774,25 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        goto out_put;
 }
 
+static void kvmppc_rmap_reset(struct kvm *kvm)
+{
+       struct kvm_memslots *slots;
+       struct kvm_memory_slot *memslot;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&kvm->srcu);
+       slots = kvm->memslots;
+       kvm_for_each_memslot(memslot, slots) {
+               /*
+                * This assumes it is acceptable to lose reference and
+                * change bits across a reset.
+                */
+               memset(memslot->arch.rmap, 0,
+                      memslot->npages * sizeof(*memslot->arch.rmap));
+       }
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+}
+
 static int kvm_handle_hva_range(struct kvm *kvm,
                                unsigned long start,
                                unsigned long end,
@@ -850,7 +887,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
                psize = hpte_page_size(hptep[0], ptel);
                if ((hptep[0] & HPTE_V_VALID) &&
                    hpte_rpn(ptel, psize) == gfn) {
-                       hptep[0] |= HPTE_V_ABSENT;
+                       if (kvm->arch.using_mmu_notifiers)
+                               hptep[0] |= HPTE_V_ABSENT;
                        kvmppc_invalidate_hpte(kvm, hptep, i);
                        /* Harvest R and C */
                        rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
@@ -877,6 +915,28 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
        return 0;
 }
 
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+       unsigned long *rmapp;
+       unsigned long gfn;
+       unsigned long n;
+
+       rmapp = memslot->arch.rmap;
+       gfn = memslot->base_gfn;
+       for (n = memslot->npages; n; --n) {
+               /*
+                * Testing the present bit without locking is OK because
+                * the memslot has been marked invalid already, and hence
+                * no new HPTEs referencing this page can be created,
+                * thus the present bit can't go from 0 to 1.
+                */
+               if (*rmapp & KVMPPC_RMAP_PRESENT)
+                       kvm_unmap_rmapp(kvm, rmapp, gfn);
+               ++rmapp;
+               ++gfn;
+       }
+}
+
 static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                         unsigned long gfn)
 {
@@ -1030,16 +1090,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
        return ret;
 }
 
-long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
+                            unsigned long *map)
 {
        unsigned long i;
-       unsigned long *rmapp, *map;
+       unsigned long *rmapp;
 
        preempt_disable();
        rmapp = memslot->arch.rmap;
-       map = memslot->dirty_bitmap;
        for (i = 0; i < memslot->npages; ++i) {
-               if (kvm_test_clear_dirty(kvm, rmapp))
+               if (kvm_test_clear_dirty(kvm, rmapp) && map)
                        __set_bit_le(i, map);
                ++rmapp;
        }
@@ -1057,20 +1117,22 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
        unsigned long hva, psize, offset;
        unsigned long pa;
        unsigned long *physp;
+       int srcu_idx;
 
+       srcu_idx = srcu_read_lock(&kvm->srcu);
        memslot = gfn_to_memslot(kvm, gfn);
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-               return NULL;
+               goto err;
        if (!kvm->arch.using_mmu_notifiers) {
-               physp = kvm->arch.slot_phys[memslot->id];
+               physp = memslot->arch.slot_phys;
                if (!physp)
-                       return NULL;
+                       goto err;
                physp += gfn - memslot->base_gfn;
                pa = *physp;
                if (!pa) {
                        if (kvmppc_get_guest_page(kvm, gfn, memslot,
                                                  PAGE_SIZE) < 0)
-                               return NULL;
+                               goto err;
                        pa = *physp;
                }
                page = pfn_to_page(pa >> PAGE_SHIFT);
@@ -1079,9 +1141,11 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
                hva = gfn_to_hva_memslot(memslot, gfn);
                npages = get_user_pages_fast(hva, 1, 1, pages);
                if (npages < 1)
-                       return NULL;
+                       goto err;
                page = pages[0];
        }
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+
        psize = PAGE_SIZE;
        if (PageHuge(page)) {
                page = compound_head(page);
@@ -1091,6 +1155,10 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
        if (nb_ret)
                *nb_ret = psize - offset;
        return page_address(page) + offset;
+
+ err:
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+       return NULL;
 }
 
 void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
@@ -1100,6 +1168,348 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
        put_page(page);
 }
 
+/*
+ * Functions for reading and writing the hash table via reads and
+ * writes on a file descriptor.
+ *
+ * Reads return the guest view of the hash table, which has to be
+ * pieced together from the real hash table and the guest_rpte
+ * values in the revmap array.
+ *
+ * On writes, each HPTE written is considered in turn, and if it
+ * is valid, it is written to the HPT as if an H_ENTER with the
+ * exact flag set was done.  When the invalid count is non-zero
+ * in the header written to the stream, the kernel will make
+ * sure that that many HPTEs are invalid, and invalidate them
+ * if not.
+ */
+
+struct kvm_htab_ctx {
+       unsigned long   index;
+       unsigned long   flags;
+       struct kvm      *kvm;
+       int             first_pass;
+};
+
+#define HPTE_SIZE      (2 * sizeof(unsigned long))
+
+static long record_hpte(unsigned long flags, unsigned long *hptp,
+                       unsigned long *hpte, struct revmap_entry *revp,
+                       int want_valid, int first_pass)
+{
+       unsigned long v, r;
+       int ok = 1;
+       int valid, dirty;
+
+       /* Unmodified entries are uninteresting except on the first pass */
+       dirty = !!(revp->guest_rpte & HPTE_GR_MODIFIED);
+       if (!first_pass && !dirty)
+               return 0;
+
+       valid = 0;
+       if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+               valid = 1;
+               if ((flags & KVM_GET_HTAB_BOLTED_ONLY) &&
+                   !(hptp[0] & HPTE_V_BOLTED))
+                       valid = 0;
+       }
+       if (valid != want_valid)
+               return 0;
+
+       v = r = 0;
+       if (valid || dirty) {
+               /* lock the HPTE so it's stable and read it */
+               preempt_disable();
+               while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
+                       cpu_relax();
+               v = hptp[0];
+               if (v & HPTE_V_ABSENT) {
+                       v &= ~HPTE_V_ABSENT;
+                       v |= HPTE_V_VALID;
+               }
+               /* re-evaluate valid and dirty from synchronized HPTE value */
+               valid = !!(v & HPTE_V_VALID);
+               if ((flags & KVM_GET_HTAB_BOLTED_ONLY) && !(v & HPTE_V_BOLTED))
+                       valid = 0;
+               r = revp->guest_rpte | (hptp[1] & (HPTE_R_R | HPTE_R_C));
+               dirty = !!(revp->guest_rpte & HPTE_GR_MODIFIED);
+               /* only clear modified if this is the right sort of entry */
+               if (valid == want_valid && dirty) {
+                       r &= ~HPTE_GR_MODIFIED;
+                       revp->guest_rpte = r;
+               }
+               asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
+               hptp[0] &= ~HPTE_V_HVLOCK;
+               preempt_enable();
+               if (!(valid == want_valid && (first_pass || dirty)))
+                       ok = 0;
+       }
+       hpte[0] = v;
+       hpte[1] = r;
+       return ok;
+}
+
+static ssize_t kvm_htab_read(struct file *file, char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+       struct kvm_htab_ctx *ctx = file->private_data;
+       struct kvm *kvm = ctx->kvm;
+       struct kvm_get_htab_header hdr;
+       unsigned long *hptp;
+       struct revmap_entry *revp;
+       unsigned long i, nb, nw;
+       unsigned long __user *lbuf;
+       struct kvm_get_htab_header __user *hptr;
+       unsigned long flags;
+       int first_pass;
+       unsigned long hpte[2];
+
+       if (!access_ok(VERIFY_WRITE, buf, count))
+               return -EFAULT;
+
+       first_pass = ctx->first_pass;
+       flags = ctx->flags;
+
+       i = ctx->index;
+       hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+       revp = kvm->arch.revmap + i;
+       lbuf = (unsigned long __user *)buf;
+
+       nb = 0;
+       while (nb + sizeof(hdr) + HPTE_SIZE < count) {
+               /* Initialize header */
+               hptr = (struct kvm_get_htab_header __user *)buf;
+               hdr.n_valid = 0;
+               hdr.n_invalid = 0;
+               nw = nb;
+               nb += sizeof(hdr);
+               lbuf = (unsigned long __user *)(buf + sizeof(hdr));
+
+               /* Skip uninteresting entries, i.e. clean on not-first pass */
+               if (!first_pass) {
+                       while (i < kvm->arch.hpt_npte &&
+                              !(revp->guest_rpte & HPTE_GR_MODIFIED)) {
+                               ++i;
+                               hptp += 2;
+                               ++revp;
+                       }
+               }
+               hdr.index = i;
+
+               /* Grab a series of valid entries */
+               while (i < kvm->arch.hpt_npte &&
+                      hdr.n_valid < 0xffff &&
+                      nb + HPTE_SIZE < count &&
+                      record_hpte(flags, hptp, hpte, revp, 1, first_pass)) {
+                       /* valid entry, write it out */
+                       ++hdr.n_valid;
+                       if (__put_user(hpte[0], lbuf) ||
+                           __put_user(hpte[1], lbuf + 1))
+                               return -EFAULT;
+                       nb += HPTE_SIZE;
+                       lbuf += 2;
+                       ++i;
+                       hptp += 2;
+                       ++revp;
+               }
+               /* Now skip invalid entries while we can */
+               while (i < kvm->arch.hpt_npte &&
+                      hdr.n_invalid < 0xffff &&
+                      record_hpte(flags, hptp, hpte, revp, 0, first_pass)) {
+                       /* found an invalid entry */
+                       ++hdr.n_invalid;
+                       ++i;
+                       hptp += 2;
+                       ++revp;
+               }
+
+               if (hdr.n_valid || hdr.n_invalid) {
+                       /* write back the header */
+                       if (__copy_to_user(hptr, &hdr, sizeof(hdr)))
+                               return -EFAULT;
+                       nw = nb;
+                       buf = (char __user *)lbuf;
+               } else {
+                       nb = nw;
+               }
+
+               /* Check if we've wrapped around the hash table */
+               if (i >= kvm->arch.hpt_npte) {
+                       i = 0;
+                       ctx->first_pass = 0;
+                       break;
+               }
+       }
+
+       ctx->index = i;
+
+       return nb;
+}
+
+static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
+                             size_t count, loff_t *ppos)
+{
+       struct kvm_htab_ctx *ctx = file->private_data;
+       struct kvm *kvm = ctx->kvm;
+       struct kvm_get_htab_header hdr;
+       unsigned long i, j;
+       unsigned long v, r;
+       unsigned long __user *lbuf;
+       unsigned long *hptp;
+       unsigned long tmp[2];
+       ssize_t nb;
+       long int err, ret;
+       int rma_setup;
+
+       if (!access_ok(VERIFY_READ, buf, count))
+               return -EFAULT;
+
+       /* lock out vcpus from running while we're doing this */
+       mutex_lock(&kvm->lock);
+       rma_setup = kvm->arch.rma_setup_done;
+       if (rma_setup) {
+               kvm->arch.rma_setup_done = 0;   /* temporarily */
+               /* order rma_setup_done vs. vcpus_running */
+               smp_mb();
+               if (atomic_read(&kvm->arch.vcpus_running)) {
+                       kvm->arch.rma_setup_done = 1;
+                       mutex_unlock(&kvm->lock);
+                       return -EBUSY;
+               }
+       }
+
+       err = 0;
+       for (nb = 0; nb + sizeof(hdr) <= count; ) {
+               err = -EFAULT;
+               if (__copy_from_user(&hdr, buf, sizeof(hdr)))
+                       break;
+
+               err = 0;
+               if (nb + hdr.n_valid * HPTE_SIZE > count)
+                       break;
+
+               nb += sizeof(hdr);
+               buf += sizeof(hdr);
+
+               err = -EINVAL;
+               i = hdr.index;
+               if (i >= kvm->arch.hpt_npte ||
+                   i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte)
+                       break;
+
+               hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+               lbuf = (unsigned long __user *)buf;
+               for (j = 0; j < hdr.n_valid; ++j) {
+                       err = -EFAULT;
+                       if (__get_user(v, lbuf) || __get_user(r, lbuf + 1))
+                               goto out;
+                       err = -EINVAL;
+                       if (!(v & HPTE_V_VALID))
+                               goto out;
+                       lbuf += 2;
+                       nb += HPTE_SIZE;
+
+                       if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+                               kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
+                       err = -EIO;
+                       ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r,
+                                                        tmp);
+                       if (ret != H_SUCCESS) {
+                               pr_err("kvm_htab_write ret %ld i=%ld v=%lx "
+                                      "r=%lx\n", ret, i, v, r);
+                               goto out;
+                       }
+                       if (!rma_setup && is_vrma_hpte(v)) {
+                               unsigned long psize = hpte_page_size(v, r);
+                               unsigned long senc = slb_pgsize_encoding(psize);
+                               unsigned long lpcr;
+
+                               kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
+                                       (VRMA_VSID << SLB_VSID_SHIFT_1T);
+                               lpcr = kvm->arch.lpcr & ~LPCR_VRMASD;
+                               lpcr |= senc << (LPCR_VRMASD_SH - 4);
+                               kvm->arch.lpcr = lpcr;
+                               rma_setup = 1;
+                       }
+                       ++i;
+                       hptp += 2;
+               }
+
+               for (j = 0; j < hdr.n_invalid; ++j) {
+                       if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+                               kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
+                       ++i;
+                       hptp += 2;
+               }
+               err = 0;
+       }
+
+ out:
+       /* Order HPTE updates vs. rma_setup_done */
+       smp_wmb();
+       kvm->arch.rma_setup_done = rma_setup;
+       mutex_unlock(&kvm->lock);
+
+       if (err)
+               return err;
+       return nb;
+}
+
+static int kvm_htab_release(struct inode *inode, struct file *filp)
+{
+       struct kvm_htab_ctx *ctx = filp->private_data;
+
+       filp->private_data = NULL;
+       if (!(ctx->flags & KVM_GET_HTAB_WRITE))
+               atomic_dec(&ctx->kvm->arch.hpte_mod_interest);
+       kvm_put_kvm(ctx->kvm);
+       kfree(ctx);
+       return 0;
+}
+
+static struct file_operations kvm_htab_fops = {
+       .read           = kvm_htab_read,
+       .write          = kvm_htab_write,
+       .llseek         = default_llseek,
+       .release        = kvm_htab_release,
+};
+
+int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *ghf)
+{
+       int ret;
+       struct kvm_htab_ctx *ctx;
+       int rwflag;
+
+       /* reject flags we don't recognize */
+       if (ghf->flags & ~(KVM_GET_HTAB_BOLTED_ONLY | KVM_GET_HTAB_WRITE))
+               return -EINVAL;
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+       kvm_get_kvm(kvm);
+       ctx->kvm = kvm;
+       ctx->index = ghf->start_index;
+       ctx->flags = ghf->flags;
+       ctx->first_pass = 1;
+
+       rwflag = (ghf->flags & KVM_GET_HTAB_WRITE) ? O_WRONLY : O_RDONLY;
+       ret = anon_inode_getfd("kvm-htab", &kvm_htab_fops, ctx, rwflag);
+       if (ret < 0) {
+               kvm_put_kvm(kvm);
+               return ret;
+       }
+
+       if (rwflag == O_RDONLY) {
+               mutex_lock(&kvm->slots_lock);
+               atomic_inc(&kvm->arch.hpte_mod_interest);
+               /* make sure kvmppc_do_h_enter etc. see the increment */
+               synchronize_srcu_expedited(&kvm->srcu);
+               mutex_unlock(&kvm->slots_lock);
+       }
+
+       return ret;
+}
+
 void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
index b9a989dc76ccff5cd739f22910c4201c0dafb4e2..d31a716f7f2bc1d06b0a2021a422b1f69e8257e5 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/kvm_book3s.h>
 #include <asm/reg.h>
 #include <asm/switch_to.h>
+#include <asm/time.h>
 
 #define OP_19_XOP_RFID         18
 #define OP_19_XOP_RFI          50
@@ -395,6 +396,12 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                    (mfmsr() & MSR_HV))
                        vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
                break;
+       case SPRN_PURR:
+               to_book3s(vcpu)->purr_offset = spr_val - get_tb();
+               break;
+       case SPRN_SPURR:
+               to_book3s(vcpu)->spurr_offset = spr_val - get_tb();
+               break;
        case SPRN_GQR0:
        case SPRN_GQR1:
        case SPRN_GQR2:
@@ -412,6 +419,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
        case SPRN_CTRLF:
        case SPRN_CTRLT:
        case SPRN_L2CR:
+       case SPRN_DSCR:
        case SPRN_MMCR0_GEKKO:
        case SPRN_MMCR1_GEKKO:
        case SPRN_PMC1_GEKKO:
@@ -483,9 +491,15 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
                *spr_val = to_book3s(vcpu)->hid[5];
                break;
        case SPRN_CFAR:
-       case SPRN_PURR:
+       case SPRN_DSCR:
                *spr_val = 0;
                break;
+       case SPRN_PURR:
+               *spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+               break;
+       case SPRN_SPURR:
+               *spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+               break;
        case SPRN_GQR0:
        case SPRN_GQR1:
        case SPRN_GQR2:
index a150817d6d4c7f9d03763542dacad5cf45ada096..7057a02f0906b2545540d92bef5ae2f45b6c527a 100644 (file)
@@ -28,8 +28,5 @@ EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
 #endif
-#ifdef CONFIG_VSX
-EXPORT_SYMBOL_GPL(kvmppc_load_up_vsx);
-#endif
 #endif
 
index 721d4603a23587bf692c887a7c10c9aca73c2ccb..71d0c90b62bf6dfe5c2a512bdda80ed60963b3f2 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/cpumask.h>
 #include <linux/spinlock.h>
 #include <linux/page-flags.h>
+#include <linux/srcu.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -46,6 +47,7 @@
 #include <asm/page.h>
 #include <asm/hvcall.h>
 #include <asm/switch_to.h>
+#include <asm/smp.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 /* #define EXIT_DEBUG_SIMPLE */
 /* #define EXIT_DEBUG_INT */
 
+/* Used to indicate that a guest page fault needs to be handled */
+#define RESUME_PAGE_FAULT      (RESUME_GUEST | RESUME_FLAG_ARCH1)
+
+/* Used as a "null" value for timebase values */
+#define TB_NIL (~(u64)0)
+
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
+/*
+ * We use the vcpu_load/put functions to measure stolen time.
+ * Stolen time is counted as time when either the vcpu is able to
+ * run as part of a virtual core, but the task running the vcore
+ * is preempted or sleeping, or when the vcpu needs something done
+ * in the kernel by the task running the vcpu, but that task is
+ * preempted or sleeping.  Those two things have to be counted
+ * separately, since one of the vcpu tasks will take on the job
+ * of running the core, and the other vcpu tasks in the vcore will
+ * sleep waiting for it to do that, but that sleep shouldn't count
+ * as stolen time.
+ *
+ * Hence we accumulate stolen time when the vcpu can run as part of
+ * a vcore using vc->stolen_tb, and the stolen time when the vcpu
+ * needs its task to do other things in the kernel (for example,
+ * service a page fault) in busy_stolen.  We don't accumulate
+ * stolen time for a vcore when it is inactive, or for a vcpu
+ * when it is in state RUNNING or NOTREADY.  NOTREADY is a bit of
+ * a misnomer; it means that the vcpu task is not executing in
+ * the KVM_VCPU_RUN ioctl, i.e. it is in userspace or elsewhere in
+ * the kernel.  We don't have any way of dividing up that time
+ * between time that the vcpu is genuinely stopped, time that
+ * the task is actively working on behalf of the vcpu, and time
+ * that the task is preempted, so we don't count any of it as
+ * stolen.
+ *
+ * Updates to busy_stolen are protected by arch.tbacct_lock;
+ * updates to vc->stolen_tb are protected by the arch.tbacct_lock
+ * of the vcpu that has taken responsibility for running the vcore
+ * (i.e. vc->runner).  The stolen times are measured in units of
+ * timebase ticks.  (Note that the != TB_NIL checks below are
+ * purely defensive; they should never fail.)
+ */
+
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
-       local_paca->kvm_hstate.kvm_vcpu = vcpu;
-       local_paca->kvm_hstate.kvm_vcore = vc;
-       if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
+       spin_lock(&vcpu->arch.tbacct_lock);
+       if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE &&
+           vc->preempt_tb != TB_NIL) {
                vc->stolen_tb += mftb() - vc->preempt_tb;
+               vc->preempt_tb = TB_NIL;
+       }
+       if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST &&
+           vcpu->arch.busy_preempt != TB_NIL) {
+               vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt;
+               vcpu->arch.busy_preempt = TB_NIL;
+       }
+       spin_unlock(&vcpu->arch.tbacct_lock);
 }
 
 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
+       spin_lock(&vcpu->arch.tbacct_lock);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
                vc->preempt_tb = mftb();
+       if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
+               vcpu->arch.busy_preempt = mftb();
+       spin_unlock(&vcpu->arch.tbacct_lock);
 }
 
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
@@ -142,6 +196,22 @@ static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
        vpa->yield_count = 1;
 }
 
+static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
+                  unsigned long addr, unsigned long len)
+{
+       /* check address is cacheline aligned */
+       if (addr & (L1_CACHE_BYTES - 1))
+               return -EINVAL;
+       spin_lock(&vcpu->arch.vpa_update_lock);
+       if (v->next_gpa != addr || v->len != len) {
+               v->next_gpa = addr;
+               v->len = addr ? len : 0;
+               v->update_pending = 1;
+       }
+       spin_unlock(&vcpu->arch.vpa_update_lock);
+       return 0;
+}
+
 /* Length for a per-processor buffer is passed in at offset 4 in the buffer */
 struct reg_vpa {
        u32 dummy;
@@ -317,10 +387,16 @@ static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap)
 
 static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
 {
+       if (!(vcpu->arch.vpa.update_pending ||
+             vcpu->arch.slb_shadow.update_pending ||
+             vcpu->arch.dtl.update_pending))
+               return;
+
        spin_lock(&vcpu->arch.vpa_update_lock);
        if (vcpu->arch.vpa.update_pending) {
                kvmppc_update_vpa(vcpu, &vcpu->arch.vpa);
-               init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
+               if (vcpu->arch.vpa.pinned_addr)
+                       init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
        }
        if (vcpu->arch.dtl.update_pending) {
                kvmppc_update_vpa(vcpu, &vcpu->arch.dtl);
@@ -332,24 +408,61 @@ static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
        spin_unlock(&vcpu->arch.vpa_update_lock);
 }
 
+/*
+ * Return the accumulated stolen time for the vcore up until `now'.
+ * The caller should hold the vcore lock.
+ */
+static u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now)
+{
+       u64 p;
+
+       /*
+        * If we are the task running the vcore, then since we hold
+        * the vcore lock, we can't be preempted, so stolen_tb/preempt_tb
+        * can't be updated, so we don't need the tbacct_lock.
+        * If the vcore is inactive, it can't become active (since we
+        * hold the vcore lock), so the vcpu load/put functions won't
+        * update stolen_tb/preempt_tb, and we don't need tbacct_lock.
+        */
+       if (vc->vcore_state != VCORE_INACTIVE &&
+           vc->runner->arch.run_task != current) {
+               spin_lock(&vc->runner->arch.tbacct_lock);
+               p = vc->stolen_tb;
+               if (vc->preempt_tb != TB_NIL)
+                       p += now - vc->preempt_tb;
+               spin_unlock(&vc->runner->arch.tbacct_lock);
+       } else {
+               p = vc->stolen_tb;
+       }
+       return p;
+}
+
 static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
                                    struct kvmppc_vcore *vc)
 {
        struct dtl_entry *dt;
        struct lppaca *vpa;
-       unsigned long old_stolen;
+       unsigned long stolen;
+       unsigned long core_stolen;
+       u64 now;
 
        dt = vcpu->arch.dtl_ptr;
        vpa = vcpu->arch.vpa.pinned_addr;
-       old_stolen = vcpu->arch.stolen_logged;
-       vcpu->arch.stolen_logged = vc->stolen_tb;
+       now = mftb();
+       core_stolen = vcore_stolen_time(vc, now);
+       stolen = core_stolen - vcpu->arch.stolen_logged;
+       vcpu->arch.stolen_logged = core_stolen;
+       spin_lock(&vcpu->arch.tbacct_lock);
+       stolen += vcpu->arch.busy_stolen;
+       vcpu->arch.busy_stolen = 0;
+       spin_unlock(&vcpu->arch.tbacct_lock);
        if (!dt || !vpa)
                return;
        memset(dt, 0, sizeof(struct dtl_entry));
        dt->dispatch_reason = 7;
        dt->processor_id = vc->pcpu + vcpu->arch.ptid;
-       dt->timebase = mftb();
-       dt->enqueue_to_dispatch_time = vc->stolen_tb - old_stolen;
+       dt->timebase = now;
+       dt->enqueue_to_dispatch_time = stolen;
        dt->srr0 = kvmppc_get_pc(vcpu);
        dt->srr1 = vcpu->arch.shregs.msr;
        ++dt;
@@ -366,13 +479,16 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        unsigned long req = kvmppc_get_gpr(vcpu, 3);
        unsigned long target, ret = H_SUCCESS;
        struct kvm_vcpu *tvcpu;
+       int idx;
 
        switch (req) {
        case H_ENTER:
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
                ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
                                              kvmppc_get_gpr(vcpu, 5),
                                              kvmppc_get_gpr(vcpu, 6),
                                              kvmppc_get_gpr(vcpu, 7));
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
        case H_CEDE:
                break;
@@ -429,6 +545,17 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
        case BOOK3S_INTERRUPT_PERFMON:
                r = RESUME_GUEST;
                break;
+       case BOOK3S_INTERRUPT_MACHINE_CHECK:
+               /*
+                * Deliver a machine check interrupt to the guest.
+                * We have to do this, even if the host has handled the
+                * machine check, because machine checks use SRR0/1 and
+                * the interrupt might have trashed guest state in them.
+                */
+               kvmppc_book3s_queue_irqprio(vcpu,
+                                           BOOK3S_INTERRUPT_MACHINE_CHECK);
+               r = RESUME_GUEST;
+               break;
        case BOOK3S_INTERRUPT_PROGRAM:
        {
                ulong flags;
@@ -470,12 +597,12 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
         * have been handled already.
         */
        case BOOK3S_INTERRUPT_H_DATA_STORAGE:
-               r = kvmppc_book3s_hv_page_fault(run, vcpu,
-                               vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+               r = RESUME_PAGE_FAULT;
                break;
        case BOOK3S_INTERRUPT_H_INST_STORAGE:
-               r = kvmppc_book3s_hv_page_fault(run, vcpu,
-                               kvmppc_get_pc(vcpu), 0);
+               vcpu->arch.fault_dar = kvmppc_get_pc(vcpu);
+               vcpu->arch.fault_dsisr = 0;
+               r = RESUME_PAGE_FAULT;
                break;
        /*
         * This occurs if the guest executes an illegal instruction.
@@ -535,36 +662,174 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
+       long int i;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-               r = put_user(0, (u64 __user *)reg->addr);
+               *val = get_reg_val(id, 0);
+               break;
+       case KVM_REG_PPC_DABR:
+               *val = get_reg_val(id, vcpu->arch.dabr);
+               break;
+       case KVM_REG_PPC_DSCR:
+               *val = get_reg_val(id, vcpu->arch.dscr);
+               break;
+       case KVM_REG_PPC_PURR:
+               *val = get_reg_val(id, vcpu->arch.purr);
+               break;
+       case KVM_REG_PPC_SPURR:
+               *val = get_reg_val(id, vcpu->arch.spurr);
+               break;
+       case KVM_REG_PPC_AMR:
+               *val = get_reg_val(id, vcpu->arch.amr);
+               break;
+       case KVM_REG_PPC_UAMOR:
+               *val = get_reg_val(id, vcpu->arch.uamor);
+               break;
+       case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
+               i = id - KVM_REG_PPC_MMCR0;
+               *val = get_reg_val(id, vcpu->arch.mmcr[i]);
+               break;
+       case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
+               i = id - KVM_REG_PPC_PMC1;
+               *val = get_reg_val(id, vcpu->arch.pmc[i]);
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       /* VSX => FP reg i is stored in arch.vsr[2*i] */
+                       long int i = id - KVM_REG_PPC_FPR0;
+                       *val = get_reg_val(id, vcpu->arch.vsr[2 * i]);
+               } else {
+                       /* let generic code handle it */
+                       r = -EINVAL;
+               }
+               break;
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       long int i = id - KVM_REG_PPC_VSR0;
+                       val->vsxval[0] = vcpu->arch.vsr[2 * i];
+                       val->vsxval[1] = vcpu->arch.vsr[2 * i + 1];
+               } else {
+                       r = -ENXIO;
+               }
+               break;
+#endif /* CONFIG_VSX */
+       case KVM_REG_PPC_VPA_ADDR:
+               spin_lock(&vcpu->arch.vpa_update_lock);
+               *val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
+               spin_unlock(&vcpu->arch.vpa_update_lock);
+               break;
+       case KVM_REG_PPC_VPA_SLB:
+               spin_lock(&vcpu->arch.vpa_update_lock);
+               val->vpaval.addr = vcpu->arch.slb_shadow.next_gpa;
+               val->vpaval.length = vcpu->arch.slb_shadow.len;
+               spin_unlock(&vcpu->arch.vpa_update_lock);
+               break;
+       case KVM_REG_PPC_VPA_DTL:
+               spin_lock(&vcpu->arch.vpa_update_lock);
+               val->vpaval.addr = vcpu->arch.dtl.next_gpa;
+               val->vpaval.length = vcpu->arch.dtl.len;
+               spin_unlock(&vcpu->arch.vpa_update_lock);
                break;
        default:
+               r = -EINVAL;
                break;
        }
 
        return r;
 }
 
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
+       long int i;
+       unsigned long addr, len;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-       {
-               u64 hior;
                /* Only allow this to be set to zero */
-               r = get_user(hior, (u64 __user *)reg->addr);
-               if (!r && (hior != 0))
+               if (set_reg_val(id, *val))
                        r = -EINVAL;
                break;
-       }
+       case KVM_REG_PPC_DABR:
+               vcpu->arch.dabr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_DSCR:
+               vcpu->arch.dscr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_PURR:
+               vcpu->arch.purr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_SPURR:
+               vcpu->arch.spurr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_AMR:
+               vcpu->arch.amr = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_UAMOR:
+               vcpu->arch.uamor = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
+               i = id - KVM_REG_PPC_MMCR0;
+               vcpu->arch.mmcr[i] = set_reg_val(id, *val);
+               break;
+       case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
+               i = id - KVM_REG_PPC_PMC1;
+               vcpu->arch.pmc[i] = set_reg_val(id, *val);
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       /* VSX => FP reg i is stored in arch.vsr[2*i] */
+                       long int i = id - KVM_REG_PPC_FPR0;
+                       vcpu->arch.vsr[2 * i] = set_reg_val(id, *val);
+               } else {
+                       /* let generic code handle it */
+                       r = -EINVAL;
+               }
+               break;
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
+               if (cpu_has_feature(CPU_FTR_VSX)) {
+                       long int i = id - KVM_REG_PPC_VSR0;
+                       vcpu->arch.vsr[2 * i] = val->vsxval[0];
+                       vcpu->arch.vsr[2 * i + 1] = val->vsxval[1];
+               } else {
+                       r = -ENXIO;
+               }
+               break;
+#endif /* CONFIG_VSX */
+       case KVM_REG_PPC_VPA_ADDR:
+               addr = set_reg_val(id, *val);
+               r = -EINVAL;
+               if (!addr && (vcpu->arch.slb_shadow.next_gpa ||
+                             vcpu->arch.dtl.next_gpa))
+                       break;
+               r = set_vpa(vcpu, &vcpu->arch.vpa, addr, sizeof(struct lppaca));
+               break;
+       case KVM_REG_PPC_VPA_SLB:
+               addr = val->vpaval.addr;
+               len = val->vpaval.length;
+               r = -EINVAL;
+               if (addr && !vcpu->arch.vpa.next_gpa)
+                       break;
+               r = set_vpa(vcpu, &vcpu->arch.slb_shadow, addr, len);
+               break;
+       case KVM_REG_PPC_VPA_DTL:
+               addr = val->vpaval.addr;
+               len = val->vpaval.length;
+               r = -EINVAL;
+               if (addr && (len < sizeof(struct dtl_entry) ||
+                            !vcpu->arch.vpa.next_gpa))
+                       break;
+               len -= len % sizeof(struct dtl_entry);
+               r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len);
+               break;
        default:
+               r = -EINVAL;
                break;
        }
 
@@ -599,20 +864,18 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
                goto free_vcpu;
 
        vcpu->arch.shared = &vcpu->arch.shregs;
-       vcpu->arch.last_cpu = -1;
        vcpu->arch.mmcr[0] = MMCR0_FC;
        vcpu->arch.ctrl = CTRL_RUNLATCH;
        /* default to host PVR, since we can't spoof it */
        vcpu->arch.pvr = mfspr(SPRN_PVR);
        kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
        spin_lock_init(&vcpu->arch.vpa_update_lock);
+       spin_lock_init(&vcpu->arch.tbacct_lock);
+       vcpu->arch.busy_preempt = TB_NIL;
 
        kvmppc_mmu_book3s_hv_init(vcpu);
 
-       /*
-        * We consider the vcpu stopped until we see the first run ioctl for it.
-        */
-       vcpu->arch.state = KVMPPC_VCPU_STOPPED;
+       vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
 
        init_waitqueue_head(&vcpu->arch.cpu_run);
 
@@ -624,9 +887,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
                        INIT_LIST_HEAD(&vcore->runnable_threads);
                        spin_lock_init(&vcore->lock);
                        init_waitqueue_head(&vcore->wq);
-                       vcore->preempt_tb = mftb();
+                       vcore->preempt_tb = TB_NIL;
                }
                kvm->arch.vcores[core] = vcore;
+               kvm->arch.online_vcores++;
        }
        mutex_unlock(&kvm->lock);
 
@@ -637,7 +901,6 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
        ++vcore->num_threads;
        spin_unlock(&vcore->lock);
        vcpu->arch.vcore = vcore;
-       vcpu->arch.stolen_logged = vcore->stolen_tb;
 
        vcpu->arch.cpu_type = KVM_CPU_3S_64;
        kvmppc_sanity_check(vcpu);
@@ -697,17 +960,18 @@ extern void xics_wake_cpu(int cpu);
 static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
                                   struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu *v;
+       u64 now;
 
        if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                return;
+       spin_lock(&vcpu->arch.tbacct_lock);
+       now = mftb();
+       vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) -
+               vcpu->arch.stolen_logged;
+       vcpu->arch.busy_preempt = now;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
+       spin_unlock(&vcpu->arch.tbacct_lock);
        --vc->n_runnable;
-       ++vc->n_busy;
-       /* decrement the physical thread id of each following vcpu */
-       v = vcpu;
-       list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
-               --v->arch.ptid;
        list_del(&vcpu->arch.run_list);
 }
 
@@ -720,6 +984,7 @@ static int kvmppc_grab_hwthread(int cpu)
 
        /* Ensure the thread won't go into the kernel if it wakes */
        tpaca->kvm_hstate.hwthread_req = 1;
+       tpaca->kvm_hstate.kvm_vcpu = NULL;
 
        /*
         * If the thread is already executing in the kernel (e.g. handling
@@ -769,7 +1034,6 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
        smp_wmb();
 #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
        if (vcpu->arch.ptid) {
-               kvmppc_grab_hwthread(cpu);
                xics_wake_cpu(cpu);
                ++vc->n_woken;
        }
@@ -795,7 +1059,8 @@ static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc)
 
 /*
  * Check that we are on thread 0 and that any other threads in
- * this core are off-line.
+ * this core are off-line.  Then grab the threads so they can't
+ * enter the kernel.
  */
 static int on_primary_thread(void)
 {
@@ -807,6 +1072,17 @@ static int on_primary_thread(void)
        while (++thr < threads_per_core)
                if (cpu_online(cpu + thr))
                        return 0;
+
+       /* Grab all hw threads so they can't go into the kernel */
+       for (thr = 1; thr < threads_per_core; ++thr) {
+               if (kvmppc_grab_hwthread(cpu + thr)) {
+                       /* Couldn't grab one; let the others go */
+                       do {
+                               kvmppc_release_hwthread(cpu + thr);
+                       } while (--thr > 0);
+                       return 0;
+               }
+       }
        return 1;
 }
 
@@ -814,21 +1090,24 @@ static int on_primary_thread(void)
  * Run a set of guest threads on a physical core.
  * Called with vc->lock held.
  */
-static int kvmppc_run_core(struct kvmppc_vcore *vc)
+static void kvmppc_run_core(struct kvmppc_vcore *vc)
 {
        struct kvm_vcpu *vcpu, *vcpu0, *vnext;
        long ret;
        u64 now;
        int ptid, i, need_vpa_update;
+       int srcu_idx;
+       struct kvm_vcpu *vcpus_to_update[threads_per_core];
 
        /* don't start if any threads have a signal pending */
        need_vpa_update = 0;
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
                if (signal_pending(vcpu->arch.run_task))
-                       return 0;
-               need_vpa_update |= vcpu->arch.vpa.update_pending |
-                       vcpu->arch.slb_shadow.update_pending |
-                       vcpu->arch.dtl.update_pending;
+                       return;
+               if (vcpu->arch.vpa.update_pending ||
+                   vcpu->arch.slb_shadow.update_pending ||
+                   vcpu->arch.dtl.update_pending)
+                       vcpus_to_update[need_vpa_update++] = vcpu;
        }
 
        /*
@@ -838,7 +1117,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
        vc->n_woken = 0;
        vc->nap_count = 0;
        vc->entry_exit_count = 0;
-       vc->vcore_state = VCORE_RUNNING;
+       vc->vcore_state = VCORE_STARTING;
        vc->in_guest = 0;
        vc->napping_threads = 0;
 
@@ -848,23 +1127,11 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
         */
        if (need_vpa_update) {
                spin_unlock(&vc->lock);
-               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
-                       kvmppc_update_vpas(vcpu);
+               for (i = 0; i < need_vpa_update; ++i)
+                       kvmppc_update_vpas(vcpus_to_update[i]);
                spin_lock(&vc->lock);
        }
 
-       /*
-        * Make sure we are running on thread 0, and that
-        * secondary threads are offline.
-        * XXX we should also block attempts to bring any
-        * secondary threads online.
-        */
-       if (threads_per_core > 1 && !on_primary_thread()) {
-               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
-                       vcpu->arch.ret = -EBUSY;
-               goto out;
-       }
-
        /*
         * Assign physical thread IDs, first to non-ceded vcpus
         * and then to ceded ones.
@@ -879,28 +1146,36 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
                }
        }
        if (!vcpu0)
-               return 0;               /* nothing to run */
+               goto out;       /* nothing to run; should never happen */
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
                if (vcpu->arch.ceded)
                        vcpu->arch.ptid = ptid++;
 
-       vc->stolen_tb += mftb() - vc->preempt_tb;
+       /*
+        * Make sure we are running on thread 0, and that
+        * secondary threads are offline.
+        */
+       if (threads_per_core > 1 && !on_primary_thread()) {
+               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+                       vcpu->arch.ret = -EBUSY;
+               goto out;
+       }
+
        vc->pcpu = smp_processor_id();
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
                kvmppc_start_thread(vcpu);
                kvmppc_create_dtl_entry(vcpu, vc);
        }
-       /* Grab any remaining hw threads so they can't go into the kernel */
-       for (i = ptid; i < threads_per_core; ++i)
-               kvmppc_grab_hwthread(vc->pcpu + i);
 
+       vc->vcore_state = VCORE_RUNNING;
        preempt_disable();
        spin_unlock(&vc->lock);
 
        kvm_guest_enter();
+
+       srcu_idx = srcu_read_lock(&vcpu0->kvm->srcu);
+
        __kvmppc_vcore_entry(NULL, vcpu0);
-       for (i = 0; i < threads_per_core; ++i)
-               kvmppc_release_hwthread(vc->pcpu + i);
 
        spin_lock(&vc->lock);
        /* disable sending of IPIs on virtual external irqs */
@@ -909,10 +1184,14 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
        /* wait for secondary threads to finish writing their state to memory */
        if (vc->nap_count < vc->n_woken)
                kvmppc_wait_for_nap(vc);
+       for (i = 0; i < threads_per_core; ++i)
+               kvmppc_release_hwthread(vc->pcpu + i);
        /* prevent other vcpu threads from doing kvmppc_start_thread() now */
        vc->vcore_state = VCORE_EXITING;
        spin_unlock(&vc->lock);
 
+       srcu_read_unlock(&vcpu0->kvm->srcu, srcu_idx);
+
        /* make sure updates to secondary vcpu structs are visible now */
        smp_mb();
        kvm_guest_exit();
@@ -920,6 +1199,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
        preempt_enable();
        kvm_resched(vcpu);
 
+       spin_lock(&vc->lock);
        now = get_tb();
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
                /* cancel pending dec exception if dec is positive */
@@ -943,10 +1223,8 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
                }
        }
 
-       spin_lock(&vc->lock);
  out:
        vc->vcore_state = VCORE_INACTIVE;
-       vc->preempt_tb = mftb();
        list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
                                 arch.run_list) {
                if (vcpu->arch.ret != RESUME_GUEST) {
@@ -954,8 +1232,6 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
                        wake_up(&vcpu->arch.cpu_run);
                }
        }
-
-       return 1;
 }
 
 /*
@@ -979,20 +1255,11 @@ static void kvmppc_wait_for_exec(struct kvm_vcpu *vcpu, int wait_state)
 static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 {
        DEFINE_WAIT(wait);
-       struct kvm_vcpu *v;
-       int all_idle = 1;
 
        prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
        vc->vcore_state = VCORE_SLEEPING;
        spin_unlock(&vc->lock);
-       list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
-               if (!v->arch.ceded || v->arch.pending_exceptions) {
-                       all_idle = 0;
-                       break;
-               }
-       }
-       if (all_idle)
-               schedule();
+       schedule();
        finish_wait(&vc->wq, &wait);
        spin_lock(&vc->lock);
        vc->vcore_state = VCORE_INACTIVE;
@@ -1001,13 +1268,13 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        int n_ceded;
-       int prev_state;
        struct kvmppc_vcore *vc;
        struct kvm_vcpu *v, *vn;
 
        kvm_run->exit_reason = 0;
        vcpu->arch.ret = RESUME_GUEST;
        vcpu->arch.trap = 0;
+       kvmppc_update_vpas(vcpu);
 
        /*
         * Synchronize with other threads in this virtual core
@@ -1017,8 +1284,9 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        vcpu->arch.ceded = 0;
        vcpu->arch.run_task = current;
        vcpu->arch.kvm_run = kvm_run;
-       prev_state = vcpu->arch.state;
+       vcpu->arch.stolen_logged = vcore_stolen_time(vc, mftb());
        vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
+       vcpu->arch.busy_preempt = TB_NIL;
        list_add_tail(&vcpu->arch.run_list, &vc->runnable_threads);
        ++vc->n_runnable;
 
@@ -1027,33 +1295,26 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
         * If the vcore is already running, we may be able to start
         * this thread straight away and have it join in.
         */
-       if (prev_state == KVMPPC_VCPU_STOPPED) {
+       if (!signal_pending(current)) {
                if (vc->vcore_state == VCORE_RUNNING &&
                    VCORE_EXIT_COUNT(vc) == 0) {
                        vcpu->arch.ptid = vc->n_runnable - 1;
+                       kvmppc_create_dtl_entry(vcpu, vc);
                        kvmppc_start_thread(vcpu);
+               } else if (vc->vcore_state == VCORE_SLEEPING) {
+                       wake_up(&vc->wq);
                }
 
-       } else if (prev_state == KVMPPC_VCPU_BUSY_IN_HOST)
-               --vc->n_busy;
+       }
 
        while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
               !signal_pending(current)) {
-               if (vc->n_busy || vc->vcore_state != VCORE_INACTIVE) {
+               if (vc->vcore_state != VCORE_INACTIVE) {
                        spin_unlock(&vc->lock);
                        kvmppc_wait_for_exec(vcpu, TASK_INTERRUPTIBLE);
                        spin_lock(&vc->lock);
                        continue;
                }
-               vc->runner = vcpu;
-               n_ceded = 0;
-               list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
-                       n_ceded += v->arch.ceded;
-               if (n_ceded == vc->n_runnable)
-                       kvmppc_vcore_blocked(vc);
-               else
-                       kvmppc_run_core(vc);
-
                list_for_each_entry_safe(v, vn, &vc->runnable_threads,
                                         arch.run_list) {
                        kvmppc_core_prepare_to_enter(v);
@@ -1065,22 +1326,40 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                                wake_up(&v->arch.cpu_run);
                        }
                }
+               if (!vc->n_runnable || vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
+                       break;
+               vc->runner = vcpu;
+               n_ceded = 0;
+               list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
+                       if (!v->arch.pending_exceptions)
+                               n_ceded += v->arch.ceded;
+               if (n_ceded == vc->n_runnable)
+                       kvmppc_vcore_blocked(vc);
+               else
+                       kvmppc_run_core(vc);
                vc->runner = NULL;
        }
 
-       if (signal_pending(current)) {
-               if (vc->vcore_state == VCORE_RUNNING ||
-                   vc->vcore_state == VCORE_EXITING) {
-                       spin_unlock(&vc->lock);
-                       kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
-                       spin_lock(&vc->lock);
-               }
-               if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
-                       kvmppc_remove_runnable(vc, vcpu);
-                       vcpu->stat.signal_exits++;
-                       kvm_run->exit_reason = KVM_EXIT_INTR;
-                       vcpu->arch.ret = -EINTR;
-               }
+       while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
+              (vc->vcore_state == VCORE_RUNNING ||
+               vc->vcore_state == VCORE_EXITING)) {
+               spin_unlock(&vc->lock);
+               kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
+               spin_lock(&vc->lock);
+       }
+
+       if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+               kvmppc_remove_runnable(vc, vcpu);
+               vcpu->stat.signal_exits++;
+               kvm_run->exit_reason = KVM_EXIT_INTR;
+               vcpu->arch.ret = -EINTR;
+       }
+
+       if (vc->n_runnable && vc->vcore_state == VCORE_INACTIVE) {
+               /* Wake up some vcpu to run the core */
+               v = list_first_entry(&vc->runnable_threads,
+                                    struct kvm_vcpu, arch.run_list);
+               wake_up(&v->arch.cpu_run);
        }
 
        spin_unlock(&vc->lock);
@@ -1090,6 +1369,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
        int r;
+       int srcu_idx;
 
        if (!vcpu->arch.sane) {
                run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -1120,6 +1400,7 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
        flush_vsx_to_thread(current);
        vcpu->arch.wqp = &vcpu->arch.vcore->wq;
        vcpu->arch.pgdir = current->mm->pgd;
+       vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
 
        do {
                r = kvmppc_run_vcpu(run, vcpu);
@@ -1128,10 +1409,16 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
                    !(vcpu->arch.shregs.msr & MSR_PR)) {
                        r = kvmppc_pseries_do_hcall(vcpu);
                        kvmppc_core_prepare_to_enter(vcpu);
+               } else if (r == RESUME_PAGE_FAULT) {
+                       srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+                       r = kvmppc_book3s_hv_page_fault(run, vcpu,
+                               vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+                       srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
                }
        } while (r == RESUME_GUEST);
 
  out:
+       vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
        atomic_dec(&vcpu->kvm->arch.vcpus_running);
        return r;
 }
@@ -1273,7 +1560,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
        n = kvm_dirty_bitmap_bytes(memslot);
        memset(memslot->dirty_bitmap, 0, n);
 
-       r = kvmppc_hv_get_dirty_log(kvm, memslot);
+       r = kvmppc_hv_get_dirty_log(kvm, memslot, memslot->dirty_bitmap);
        if (r)
                goto out;
 
@@ -1287,67 +1574,88 @@ out:
        return r;
 }
 
-static unsigned long slb_pgsize_encoding(unsigned long psize)
+static void unpin_slot(struct kvm_memory_slot *memslot)
 {
-       unsigned long senc = 0;
+       unsigned long *physp;
+       unsigned long j, npages, pfn;
+       struct page *page;
 
-       if (psize > 0x1000) {
-               senc = SLB_VSID_L;
-               if (psize == 0x10000)
-                       senc |= SLB_VSID_LP_01;
+       physp = memslot->arch.slot_phys;
+       npages = memslot->npages;
+       if (!physp)
+               return;
+       for (j = 0; j < npages; j++) {
+               if (!(physp[j] & KVMPPC_GOT_PAGE))
+                       continue;
+               pfn = physp[j] >> PAGE_SHIFT;
+               page = pfn_to_page(pfn);
+               SetPageDirty(page);
+               put_page(page);
+       }
+}
+
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                             struct kvm_memory_slot *dont)
+{
+       if (!dont || free->arch.rmap != dont->arch.rmap) {
+               vfree(free->arch.rmap);
+               free->arch.rmap = NULL;
+       }
+       if (!dont || free->arch.slot_phys != dont->arch.slot_phys) {
+               unpin_slot(free);
+               vfree(free->arch.slot_phys);
+               free->arch.slot_phys = NULL;
        }
-       return senc;
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                              unsigned long npages)
+{
+       slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
+       if (!slot->arch.rmap)
+               return -ENOMEM;
+       slot->arch.slot_phys = NULL;
+
+       return 0;
 }
 
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+                                     struct kvm_memory_slot *memslot,
+                                     struct kvm_userspace_memory_region *mem)
 {
-       unsigned long npages;
        unsigned long *phys;
 
-       /* Allocate a slot_phys array */
-       phys = kvm->arch.slot_phys[mem->slot];
-       if (!kvm->arch.using_mmu_notifiers && !phys) {
-               npages = mem->memory_size >> PAGE_SHIFT;
-               phys = vzalloc(npages * sizeof(unsigned long));
+       /* Allocate a slot_phys array if needed */
+       phys = memslot->arch.slot_phys;
+       if (!kvm->arch.using_mmu_notifiers && !phys && memslot->npages) {
+               phys = vzalloc(memslot->npages * sizeof(unsigned long));
                if (!phys)
                        return -ENOMEM;
-               kvm->arch.slot_phys[mem->slot] = phys;
-               kvm->arch.slot_npages[mem->slot] = npages;
+               memslot->arch.slot_phys = phys;
        }
 
        return 0;
 }
 
-static void unpin_slot(struct kvm *kvm, int slot_id)
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+                                     struct kvm_userspace_memory_region *mem,
+                                     struct kvm_memory_slot old)
 {
-       unsigned long *physp;
-       unsigned long j, npages, pfn;
-       struct page *page;
+       unsigned long npages = mem->memory_size >> PAGE_SHIFT;
+       struct kvm_memory_slot *memslot;
 
-       physp = kvm->arch.slot_phys[slot_id];
-       npages = kvm->arch.slot_npages[slot_id];
-       if (physp) {
-               spin_lock(&kvm->arch.slot_phys_lock);
-               for (j = 0; j < npages; j++) {
-                       if (!(physp[j] & KVMPPC_GOT_PAGE))
-                               continue;
-                       pfn = physp[j] >> PAGE_SHIFT;
-                       page = pfn_to_page(pfn);
-                       SetPageDirty(page);
-                       put_page(page);
-               }
-               kvm->arch.slot_phys[slot_id] = NULL;
-               spin_unlock(&kvm->arch.slot_phys_lock);
-               vfree(physp);
+       if (npages && old.npages) {
+               /*
+                * If modifying a memslot, reset all the rmap dirty bits.
+                * If this is a new memslot, we don't need to do anything
+                * since the rmap array starts out as all zeroes,
+                * i.e. no pages are dirty.
+                */
+               memslot = id_to_memslot(kvm->memslots, mem->slot);
+               kvmppc_hv_get_dirty_log(kvm, memslot, NULL);
        }
 }
 
-void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
-{
-}
-
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 {
        int err = 0;
@@ -1362,6 +1670,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
        unsigned long rmls;
        unsigned long *physp;
        unsigned long i, npages;
+       int srcu_idx;
 
        mutex_lock(&kvm->lock);
        if (kvm->arch.rma_setup_done)
@@ -1377,12 +1686,13 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
        }
 
        /* Look up the memslot for guest physical address 0 */
+       srcu_idx = srcu_read_lock(&kvm->srcu);
        memslot = gfn_to_memslot(kvm, 0);
 
        /* We must have some memory at 0 by now */
        err = -EINVAL;
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-               goto out;
+               goto out_srcu;
 
        /* Look up the VMA for the start of this memory slot */
        hva = memslot->userspace_addr;
@@ -1406,14 +1716,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
                err = -EPERM;
                if (cpu_has_feature(CPU_FTR_ARCH_201)) {
                        pr_err("KVM: CPU requires an RMO\n");
-                       goto out;
+                       goto out_srcu;
                }
 
                /* We can handle 4k, 64k or 16M pages in the VRMA */
                err = -EINVAL;
                if (!(psize == 0x1000 || psize == 0x10000 ||
                      psize == 0x1000000))
-                       goto out;
+                       goto out_srcu;
 
                /* Update VRMASD field in the LPCR */
                senc = slb_pgsize_encoding(psize);
@@ -1436,7 +1746,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
                err = -EINVAL;
                if (rmls < 0) {
                        pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
-                       goto out;
+                       goto out_srcu;
                }
                atomic_inc(&ri->use_count);
                kvm->arch.rma = ri;
@@ -1465,17 +1775,24 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
                /* Initialize phys addrs of pages in RMO */
                npages = ri->npages;
                porder = __ilog2(npages);
-               physp = kvm->arch.slot_phys[memslot->id];
-               spin_lock(&kvm->arch.slot_phys_lock);
-               for (i = 0; i < npages; ++i)
-                       physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) + porder;
-               spin_unlock(&kvm->arch.slot_phys_lock);
+               physp = memslot->arch.slot_phys;
+               if (physp) {
+                       if (npages > memslot->npages)
+                               npages = memslot->npages;
+                       spin_lock(&kvm->arch.slot_phys_lock);
+                       for (i = 0; i < npages; ++i)
+                               physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) +
+                                       porder;
+                       spin_unlock(&kvm->arch.slot_phys_lock);
+               }
        }
 
        /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
        smp_wmb();
        kvm->arch.rma_setup_done = 1;
        err = 0;
+ out_srcu:
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
  out:
        mutex_unlock(&kvm->lock);
        return err;
@@ -1496,6 +1813,13 @@ int kvmppc_core_init_vm(struct kvm *kvm)
                return -ENOMEM;
        kvm->arch.lpid = lpid;
 
+       /*
+        * Since we don't flush the TLB when tearing down a VM,
+        * and this lpid might have previously been used,
+        * make sure we flush on each core before running the new VM.
+        */
+       cpumask_setall(&kvm->arch.need_tlb_flush);
+
        INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
 
        kvm->arch.rma = NULL;
@@ -1523,16 +1847,19 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 
        kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206);
        spin_lock_init(&kvm->arch.slot_phys_lock);
+
+       /*
+        * Don't allow secondary CPU threads to come online
+        * while any KVM VMs exist.
+        */
+       inhibit_secondary_onlining();
+
        return 0;
 }
 
 void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
-       unsigned long i;
-
-       if (!kvm->arch.using_mmu_notifiers)
-               for (i = 0; i < KVM_MEM_SLOTS_NUM; i++)
-                       unpin_slot(kvm, i);
+       uninhibit_secondary_onlining();
 
        if (kvm->arch.rma) {
                kvm_release_rma(kvm->arch.rma);
index fb4eac290fefc1c438b46a1cc5865c0b3200ce57..ec0a9e5de1005331e7372a5c76d3a153d2a4dfd5 100644 (file)
@@ -157,8 +157,8 @@ static void __init kvm_linear_init_one(ulong size, int count, int type)
        linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
        for (i = 0; i < count; ++i) {
                linear = alloc_bootmem_align(size, size);
-               pr_info("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
-                       size >> 20);
+               pr_debug("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
+                        size >> 20);
                linear_info[i].base_virt = linear;
                linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
                linear_info[i].npages = npages;
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
new file mode 100644 (file)
index 0000000..35f3cf0
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/kernel.h>
+#include <asm/opal.h>
+
+/* SRR1 bits for machine check on POWER7 */
+#define SRR1_MC_LDSTERR                (1ul << (63-42))
+#define SRR1_MC_IFETCH_SH      (63-45)
+#define SRR1_MC_IFETCH_MASK    0x7
+#define SRR1_MC_IFETCH_SLBPAR          2       /* SLB parity error */
+#define SRR1_MC_IFETCH_SLBMULTI                3       /* SLB multi-hit */
+#define SRR1_MC_IFETCH_SLBPARMULTI     4       /* SLB parity + multi-hit */
+#define SRR1_MC_IFETCH_TLBMULTI                5       /* I-TLB multi-hit */
+
+/* DSISR bits for machine check on POWER7 */
+#define DSISR_MC_DERAT_MULTI   0x800           /* D-ERAT multi-hit */
+#define DSISR_MC_TLB_MULTI     0x400           /* D-TLB multi-hit */
+#define DSISR_MC_SLB_PARITY    0x100           /* SLB parity error */
+#define DSISR_MC_SLB_MULTI     0x080           /* SLB multi-hit */
+#define DSISR_MC_SLB_PARMULTI  0x040           /* SLB parity + multi-hit */
+
+/* POWER7 SLB flush and reload */
+static void reload_slb(struct kvm_vcpu *vcpu)
+{
+       struct slb_shadow *slb;
+       unsigned long i, n;
+
+       /* First clear out SLB */
+       asm volatile("slbmte %0,%0; slbia" : : "r" (0));
+
+       /* Do they have an SLB shadow buffer registered? */
+       slb = vcpu->arch.slb_shadow.pinned_addr;
+       if (!slb)
+               return;
+
+       /* Sanity check */
+       n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
+       if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end)
+               return;
+
+       /* Load up the SLB from that */
+       for (i = 0; i < n; ++i) {
+               unsigned long rb = slb->save_area[i].esid;
+               unsigned long rs = slb->save_area[i].vsid;
+
+               rb = (rb & ~0xFFFul) | i;       /* insert entry number */
+               asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
+       }
+}
+
+/* POWER7 TLB flush */
+static void flush_tlb_power7(struct kvm_vcpu *vcpu)
+{
+       unsigned long i, rb;
+
+       rb = TLBIEL_INVAL_SET_LPID;
+       for (i = 0; i < POWER7_TLB_SETS; ++i) {
+               asm volatile("tlbiel %0" : : "r" (rb));
+               rb += 1 << TLBIEL_INVAL_SET_SHIFT;
+       }
+}
+
+/*
+ * On POWER7, see if we can handle a machine check that occurred inside
+ * the guest in real mode, without switching to the host partition.
+ *
+ * Returns: 0 => exit guest, 1 => deliver machine check to guest
+ */
+static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
+{
+       unsigned long srr1 = vcpu->arch.shregs.msr;
+       struct opal_machine_check_event *opal_evt;
+       long handled = 1;
+
+       if (srr1 & SRR1_MC_LDSTERR) {
+               /* error on load/store */
+               unsigned long dsisr = vcpu->arch.shregs.dsisr;
+
+               if (dsisr & (DSISR_MC_SLB_PARMULTI | DSISR_MC_SLB_MULTI |
+                            DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI)) {
+                       /* flush and reload SLB; flushes D-ERAT too */
+                       reload_slb(vcpu);
+                       dsisr &= ~(DSISR_MC_SLB_PARMULTI | DSISR_MC_SLB_MULTI |
+                                  DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
+               }
+               if (dsisr & DSISR_MC_TLB_MULTI) {
+                       flush_tlb_power7(vcpu);
+                       dsisr &= ~DSISR_MC_TLB_MULTI;
+               }
+               /* Any other errors we don't understand? */
+               if (dsisr & 0xffffffffUL)
+                       handled = 0;
+       }
+
+       switch ((srr1 >> SRR1_MC_IFETCH_SH) & SRR1_MC_IFETCH_MASK) {
+       case 0:
+               break;
+       case SRR1_MC_IFETCH_SLBPAR:
+       case SRR1_MC_IFETCH_SLBMULTI:
+       case SRR1_MC_IFETCH_SLBPARMULTI:
+               reload_slb(vcpu);
+               break;
+       case SRR1_MC_IFETCH_TLBMULTI:
+               flush_tlb_power7(vcpu);
+               break;
+       default:
+               handled = 0;
+       }
+
+       /*
+        * See if OPAL has already handled the condition.
+        * We assume that if the condition is recovered then OPAL
+        * will have generated an error log event that we will pick
+        * up and log later.
+        */
+       opal_evt = local_paca->opal_mc_evt;
+       if (opal_evt->version == OpalMCE_V1 &&
+           (opal_evt->severity == OpalMCE_SEV_NO_ERROR ||
+            opal_evt->disposition == OpalMCE_DISPOSITION_RECOVERED))
+               handled = 1;
+
+       if (handled)
+               opal_evt->in_use = 0;
+
+       return handled;
+}
+
+long kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_206))
+               return kvmppc_realmode_mc_power7(vcpu);
+
+       return 0;
+}
index fb0e821622d4fc97465288cd57f6c12978bdc381..19c93bae1aea5781a421957c3ff941d39427f7f5 100644 (file)
@@ -35,6 +35,37 @@ static void *real_vmalloc_addr(void *x)
        return __va(addr);
 }
 
+/* Return 1 if we need to do a global tlbie, 0 if we can use tlbiel */
+static int global_invalidates(struct kvm *kvm, unsigned long flags)
+{
+       int global;
+
+       /*
+        * If there is only one vcore, and it's currently running,
+        * we can use tlbiel as long as we mark all other physical
+        * cores as potentially having stale TLB entries for this lpid.
+        * If we're not using MMU notifiers, we never take pages away
+        * from the guest, so we can use tlbiel if requested.
+        * Otherwise, don't use tlbiel.
+        */
+       if (kvm->arch.online_vcores == 1 && local_paca->kvm_hstate.kvm_vcore)
+               global = 0;
+       else if (kvm->arch.using_mmu_notifiers)
+               global = 1;
+       else
+               global = !(flags & H_LOCAL);
+
+       if (!global) {
+               /* any other core might now have stale TLB entries... */
+               smp_wmb();
+               cpumask_setall(&kvm->arch.need_tlb_flush);
+               cpumask_clear_cpu(local_paca->kvm_hstate.kvm_vcore->pcpu,
+                                 &kvm->arch.need_tlb_flush);
+       }
+
+       return global;
+}
+
 /*
  * Add this HPTE into the chain for the real page.
  * Must be called with the chain locked; it unlocks the chain.
@@ -59,13 +90,24 @@ void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
                head->back = pte_index;
        } else {
                rev->forw = rev->back = pte_index;
-               i = pte_index;
+               *rmap = (*rmap & ~KVMPPC_RMAP_INDEX) |
+                       pte_index | KVMPPC_RMAP_PRESENT;
        }
-       smp_wmb();
-       *rmap = i | KVMPPC_RMAP_REFERENCED | KVMPPC_RMAP_PRESENT; /* unlock */
+       unlock_rmap(rmap);
 }
 EXPORT_SYMBOL_GPL(kvmppc_add_revmap_chain);
 
+/*
+ * Note modification of an HPTE; set the HPTE modified bit
+ * if anyone is interested.
+ */
+static inline void note_hpte_modification(struct kvm *kvm,
+                                         struct revmap_entry *rev)
+{
+       if (atomic_read(&kvm->arch.hpte_mod_interest))
+               rev->guest_rpte |= HPTE_GR_MODIFIED;
+}
+
 /* Remove this HPTE from the chain for a real page */
 static void remove_revmap_chain(struct kvm *kvm, long pte_index,
                                struct revmap_entry *rev,
@@ -81,7 +123,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
        ptel = rev->guest_rpte |= rcbits;
        gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
        memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
-       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+       if (!memslot)
                return;
 
        rmap = real_vmalloc_addr(&memslot->arch.rmap[gfn - memslot->base_gfn]);
@@ -103,14 +145,14 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
        unlock_rmap(rmap);
 }
 
-static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
+static pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
                              int writing, unsigned long *pte_sizep)
 {
        pte_t *ptep;
        unsigned long ps = *pte_sizep;
        unsigned int shift;
 
-       ptep = find_linux_pte_or_hugepte(vcpu->arch.pgdir, hva, &shift);
+       ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
        if (!ptep)
                return __pte(0);
        if (shift)
@@ -130,15 +172,15 @@ static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
        hpte[0] = hpte_v;
 }
 
-long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
-                   long pte_index, unsigned long pteh, unsigned long ptel)
+long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
+                      long pte_index, unsigned long pteh, unsigned long ptel,
+                      pgd_t *pgdir, bool realmode, unsigned long *pte_idx_ret)
 {
-       struct kvm *kvm = vcpu->kvm;
        unsigned long i, pa, gpa, gfn, psize;
        unsigned long slot_fn, hva;
        unsigned long *hpte;
        struct revmap_entry *rev;
-       unsigned long g_ptel = ptel;
+       unsigned long g_ptel;
        struct kvm_memory_slot *memslot;
        unsigned long *physp, pte_size;
        unsigned long is_io;
@@ -147,13 +189,14 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
        unsigned int writing;
        unsigned long mmu_seq;
        unsigned long rcbits;
-       bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
 
        psize = hpte_page_size(pteh, ptel);
        if (!psize)
                return H_PARAMETER;
        writing = hpte_is_writable(ptel);
        pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
+       ptel &= ~HPTE_GR_RESERVED;
+       g_ptel = ptel;
 
        /* used later to detect if we might have been invalidated */
        mmu_seq = kvm->mmu_notifier_seq;
@@ -183,7 +226,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
        rmap = &memslot->arch.rmap[slot_fn];
 
        if (!kvm->arch.using_mmu_notifiers) {
-               physp = kvm->arch.slot_phys[memslot->id];
+               physp = memslot->arch.slot_phys;
                if (!physp)
                        return H_PARAMETER;
                physp += slot_fn;
@@ -201,7 +244,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 
                /* Look up the Linux PTE for the backing page */
                pte_size = psize;
-               pte = lookup_linux_pte(vcpu, hva, writing, &pte_size);
+               pte = lookup_linux_pte(pgdir, hva, writing, &pte_size);
                if (pte_present(pte)) {
                        if (writing && !pte_write(pte))
                                /* make the actual HPTE be read-only */
@@ -210,6 +253,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
                        pa = pte_pfn(pte) << PAGE_SHIFT;
                }
        }
+
        if (pte_size < psize)
                return H_PARAMETER;
        if (pa && pte_size > psize)
@@ -287,8 +331,10 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
        rev = &kvm->arch.revmap[pte_index];
        if (realmode)
                rev = real_vmalloc_addr(rev);
-       if (rev)
+       if (rev) {
                rev->guest_rpte = g_ptel;
+               note_hpte_modification(kvm, rev);
+       }
 
        /* Link HPTE into reverse-map chain */
        if (pteh & HPTE_V_VALID) {
@@ -297,7 +343,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
                lock_rmap(rmap);
                /* Check for pending invalidations under the rmap chain lock */
                if (kvm->arch.using_mmu_notifiers &&
-                   mmu_notifier_retry(vcpu, mmu_seq)) {
+                   mmu_notifier_retry(kvm, mmu_seq)) {
                        /* inval in progress, write a non-present HPTE */
                        pteh |= HPTE_V_ABSENT;
                        pteh &= ~HPTE_V_VALID;
@@ -318,10 +364,17 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
        hpte[0] = pteh;
        asm volatile("ptesync" : : : "memory");
 
-       vcpu->arch.gpr[4] = pte_index;
+       *pte_idx_ret = pte_index;
        return H_SUCCESS;
 }
-EXPORT_SYMBOL_GPL(kvmppc_h_enter);
+EXPORT_SYMBOL_GPL(kvmppc_do_h_enter);
+
+long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                   long pte_index, unsigned long pteh, unsigned long ptel)
+{
+       return kvmppc_do_h_enter(vcpu->kvm, flags, pte_index, pteh, ptel,
+                                vcpu->arch.pgdir, true, &vcpu->arch.gpr[4]);
+}
 
 #define LOCK_TOKEN     (*(u32 *)(&get_paca()->lock_token))
 
@@ -343,11 +396,10 @@ static inline int try_lock_tlbie(unsigned int *lock)
        return old == 0;
 }
 
-long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
-                    unsigned long pte_index, unsigned long avpn,
-                    unsigned long va)
+long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
+                       unsigned long pte_index, unsigned long avpn,
+                       unsigned long *hpret)
 {
-       struct kvm *kvm = vcpu->kvm;
        unsigned long *hpte;
        unsigned long v, r, rb;
        struct revmap_entry *rev;
@@ -369,7 +421,7 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
        if (v & HPTE_V_VALID) {
                hpte[0] &= ~HPTE_V_VALID;
                rb = compute_tlbie_rb(v, hpte[1], pte_index);
-               if (!(flags & H_LOCAL) && atomic_read(&kvm->online_vcpus) > 1) {
+               if (global_invalidates(kvm, flags)) {
                        while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
                                cpu_relax();
                        asm volatile("ptesync" : : : "memory");
@@ -385,13 +437,22 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
                /* Read PTE low word after tlbie to get final R/C values */
                remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
        }
-       r = rev->guest_rpte;
+       r = rev->guest_rpte & ~HPTE_GR_RESERVED;
+       note_hpte_modification(kvm, rev);
        unlock_hpte(hpte, 0);
 
-       vcpu->arch.gpr[4] = v;
-       vcpu->arch.gpr[5] = r;
+       hpret[0] = v;
+       hpret[1] = r;
        return H_SUCCESS;
 }
+EXPORT_SYMBOL_GPL(kvmppc_do_h_remove);
+
+long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
+                    unsigned long pte_index, unsigned long avpn)
+{
+       return kvmppc_do_h_remove(vcpu->kvm, flags, pte_index, avpn,
+                                 &vcpu->arch.gpr[4]);
+}
 
 long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 {
@@ -459,6 +520,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 
                        args[j] = ((0x80 | flags) << 56) + pte_index;
                        rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+                       note_hpte_modification(kvm, rev);
 
                        if (!(hp[0] & HPTE_V_VALID)) {
                                /* insert R and C bits from PTE */
@@ -534,8 +596,6 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
                return H_NOT_FOUND;
        }
 
-       if (atomic_read(&kvm->online_vcpus) == 1)
-               flags |= H_LOCAL;
        v = hpte[0];
        bits = (flags << 55) & HPTE_R_PP0;
        bits |= (flags << 48) & HPTE_R_KEY_HI;
@@ -548,6 +608,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
        if (rev) {
                r = (rev->guest_rpte & ~mask) | bits;
                rev->guest_rpte = r;
+               note_hpte_modification(kvm, rev);
        }
        r = (hpte[1] & ~mask) | bits;
 
@@ -555,7 +616,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
        if (v & HPTE_V_VALID) {
                rb = compute_tlbie_rb(v, r, pte_index);
                hpte[0] = v & ~HPTE_V_VALID;
-               if (!(flags & H_LOCAL)) {
+               if (global_invalidates(kvm, flags)) {
                        while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
                                cpu_relax();
                        asm volatile("ptesync" : : : "memory");
@@ -568,6 +629,28 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
                        asm volatile("tlbiel %0" : : "r" (rb));
                        asm volatile("ptesync" : : : "memory");
                }
+               /*
+                * If the host has this page as readonly but the guest
+                * wants to make it read/write, reduce the permissions.
+                * Checking the host permissions involves finding the
+                * memslot and then the Linux PTE for the page.
+                */
+               if (hpte_is_writable(r) && kvm->arch.using_mmu_notifiers) {
+                       unsigned long psize, gfn, hva;
+                       struct kvm_memory_slot *memslot;
+                       pgd_t *pgdir = vcpu->arch.pgdir;
+                       pte_t pte;
+
+                       psize = hpte_page_size(v, r);
+                       gfn = ((r & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
+                       memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
+                       if (memslot) {
+                               hva = __gfn_to_hva_memslot(memslot, gfn);
+                               pte = lookup_linux_pte(pgdir, hva, 1, &psize);
+                               if (pte_present(pte) && !pte_write(pte))
+                                       r = hpte_make_readonly(r);
+                       }
+               }
        }
        hpte[1] = r;
        eieio();
@@ -599,8 +682,10 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
                        v &= ~HPTE_V_ABSENT;
                        v |= HPTE_V_VALID;
                }
-               if (v & HPTE_V_VALID)
+               if (v & HPTE_V_VALID) {
                        r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
+                       r &= ~HPTE_GR_RESERVED;
+               }
                vcpu->arch.gpr[4 + i * 2] = v;
                vcpu->arch.gpr[5 + i * 2] = r;
        }
index 74a24bbb963762cdb89eac53e9a302c184084c35..10b6c358dd770cf7c3c0083aebfdecc321631985 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/exception-64s.h>
 #include <asm/kvm_book3s_asm.h>
+#include <asm/mmu-hash64.h>
 
 /*****************************************************************************
  *                                                                           *
@@ -134,8 +135,11 @@ kvm_start_guest:
 
 27:    /* XXX should handle hypervisor maintenance interrupts etc. here */
 
+       /* reload vcpu pointer after clearing the IPI */
+       ld      r4,HSTATE_KVM_VCPU(r13)
+       cmpdi   r4,0
        /* if we have no vcpu to run, go back to sleep */
-       beq     cr1,kvm_no_guest
+       beq     kvm_no_guest
 
        /* were we napping due to cede? */
        lbz     r0,HSTATE_NAPPING(r13)
@@ -310,7 +314,33 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        mtspr   SPRN_SDR1,r6            /* switch to partition page table */
        mtspr   SPRN_LPID,r7
        isync
+
+       /* See if we need to flush the TLB */
+       lhz     r6,PACAPACAINDEX(r13)   /* test_bit(cpu, need_tlb_flush) */
+       clrldi  r7,r6,64-6              /* extract bit number (6 bits) */
+       srdi    r6,r6,6                 /* doubleword number */
+       sldi    r6,r6,3                 /* address offset */
+       add     r6,r6,r9
+       addi    r6,r6,KVM_NEED_FLUSH    /* dword in kvm->arch.need_tlb_flush */
        li      r0,1
+       sld     r0,r0,r7
+       ld      r7,0(r6)
+       and.    r7,r7,r0
+       beq     22f
+23:    ldarx   r7,0,r6                 /* if set, clear the bit */
+       andc    r7,r7,r0
+       stdcx.  r7,0,r6
+       bne     23b
+       li      r6,128                  /* and flush the TLB */
+       mtctr   r6
+       li      r7,0x800                /* IS field = 0b10 */
+       ptesync
+28:    tlbiel  r7
+       addi    r7,r7,0x1000
+       bdnz    28b
+       ptesync
+
+22:    li      r0,1
        stb     r0,VCORE_IN_GUEST(r5)   /* signal secondaries to continue */
        b       10f
 
@@ -333,36 +363,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        mr      r9,r4
        blt     hdec_soon
 
-       /*
-        * Invalidate the TLB if we could possibly have stale TLB
-        * entries for this partition on this core due to the use
-        * of tlbiel.
-        * XXX maybe only need this on primary thread?
-        */
-       ld      r9,VCPU_KVM(r4)         /* pointer to struct kvm */
-       lwz     r5,VCPU_VCPUID(r4)
-       lhz     r6,PACAPACAINDEX(r13)
-       rldimi  r6,r5,0,62              /* XXX map as if threads 1:1 p:v */
-       lhz     r8,VCPU_LAST_CPU(r4)
-       sldi    r7,r6,1                 /* see if this is the same vcpu */
-       add     r7,r7,r9                /* as last ran on this pcpu */
-       lhz     r0,KVM_LAST_VCPU(r7)
-       cmpw    r6,r8                   /* on the same cpu core as last time? */
-       bne     3f
-       cmpw    r0,r5                   /* same vcpu as this core last ran? */
-       beq     1f
-3:     sth     r6,VCPU_LAST_CPU(r4)    /* if not, invalidate partition TLB */
-       sth     r5,KVM_LAST_VCPU(r7)
-       li      r6,128
-       mtctr   r6
-       li      r7,0x800                /* IS field = 0b10 */
-       ptesync
-2:     tlbiel  r7
-       addi    r7,r7,0x1000
-       bdnz    2b
-       ptesync
-1:
-
        /* Save purr/spurr */
        mfspr   r5,SPRN_PURR
        mfspr   r6,SPRN_SPURR
@@ -679,8 +679,7 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
-nohpte_cont:
-hcall_real_cont:               /* r9 = vcpu, r12 = trap, r13 = paca */
+guest_exit_cont:               /* r9 = vcpu, r12 = trap, r13 = paca */
        /* Save DEC */
        mfspr   r5,SPRN_DEC
        mftb    r6
@@ -701,6 +700,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
        std     r6, VCPU_FAULT_DAR(r9)
        stw     r7, VCPU_FAULT_DSISR(r9)
 
+       /* See if it is a machine check */
+       cmpwi   r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+       beq     machine_check_realmode
+mc_cont:
+
        /* Save guest CTRL register, set runlatch to 1 */
 6:     mfspr   r6,SPRN_CTRLF
        stw     r6,VCPU_CTRL(r9)
@@ -1113,38 +1117,41 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        /*
         * For external and machine check interrupts, we need
         * to call the Linux handler to process the interrupt.
-        * We do that by jumping to the interrupt vector address
-        * which we have in r12.  The [h]rfid at the end of the
+        * We do that by jumping to absolute address 0x500 for
+        * external interrupts, or the machine_check_fwnmi label
+        * for machine checks (since firmware might have patched
+        * the vector area at 0x200).  The [h]rfid at the end of the
         * handler will return to the book3s_hv_interrupts.S code.
         * For other interrupts we do the rfid to get back
-        * to the book3s_interrupts.S code here.
+        * to the book3s_hv_interrupts.S code here.
         */
        ld      r8, HSTATE_VMHANDLER(r13)
        ld      r7, HSTATE_HOST_MSR(r13)
 
+       cmpwi   cr1, r12, BOOK3S_INTERRUPT_MACHINE_CHECK
        cmpwi   r12, BOOK3S_INTERRUPT_EXTERNAL
+BEGIN_FTR_SECTION
        beq     11f
-       cmpwi   r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
        /* RFI into the highmem handler, or branch to interrupt handler */
-12:    mfmsr   r6
-       mtctr   r12
+       mfmsr   r6
        li      r0, MSR_RI
        andc    r6, r6, r0
        mtmsrd  r6, 1                   /* Clear RI in MSR */
        mtsrr0  r8
        mtsrr1  r7
-       beqctr
+       beqa    0x500                   /* external interrupt (PPC970) */
+       beq     cr1, 13f                /* machine check */
        RFI
 
-11:
-BEGIN_FTR_SECTION
-       b       12b
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
-       mtspr   SPRN_HSRR0, r8
+       /* On POWER7, we have external interrupts set to use HSRR0/1 */
+11:    mtspr   SPRN_HSRR0, r8
        mtspr   SPRN_HSRR1, r7
        ba      0x500
 
+13:    b       machine_check_fwnmi
+
 /*
  * Check whether an HDSI is an HPTE not found fault or something else.
  * If it is an HPTE not found fault that is due to the guest accessing
@@ -1177,7 +1184,7 @@ kvmppc_hdsi:
        cmpdi   r3, 0                   /* retry the instruction */
        beq     6f
        cmpdi   r3, -1                  /* handle in kernel mode */
-       beq     nohpte_cont
+       beq     guest_exit_cont
        cmpdi   r3, -2                  /* MMIO emulation; need instr word */
        beq     2f
 
@@ -1191,6 +1198,7 @@ kvmppc_hdsi:
        li      r10, BOOK3S_INTERRUPT_DATA_STORAGE
        li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
        rotldi  r11, r11, 63
+fast_interrupt_c_return:
 6:     ld      r7, VCPU_CTR(r9)
        lwz     r8, VCPU_XER(r9)
        mtctr   r7
@@ -1223,7 +1231,7 @@ kvmppc_hdsi:
        /* Unset guest mode. */
        li      r0, KVM_GUEST_MODE_NONE
        stb     r0, HSTATE_IN_GUEST(r13)
-       b       nohpte_cont
+       b       guest_exit_cont
 
 /*
  * Similarly for an HISI, reflect it to the guest as an ISI unless
@@ -1249,9 +1257,9 @@ kvmppc_hisi:
        ld      r11, VCPU_MSR(r9)
        li      r12, BOOK3S_INTERRUPT_H_INST_STORAGE
        cmpdi   r3, 0                   /* retry the instruction */
-       beq     6f
+       beq     fast_interrupt_c_return
        cmpdi   r3, -1                  /* handle in kernel mode */
-       beq     nohpte_cont
+       beq     guest_exit_cont
 
        /* Synthesize an ISI for the guest */
        mr      r11, r3
@@ -1260,12 +1268,7 @@ kvmppc_hisi:
        li      r10, BOOK3S_INTERRUPT_INST_STORAGE
        li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
        rotldi  r11, r11, 63
-6:     ld      r7, VCPU_CTR(r9)
-       lwz     r8, VCPU_XER(r9)
-       mtctr   r7
-       mtxer   r8
-       mr      r4, r9
-       b       fast_guest_return
+       b       fast_interrupt_c_return
 
 3:     ld      r6, VCPU_KVM(r9)        /* not relocated, use VRMA */
        ld      r5, KVM_VRMA_SLB_V(r6)
@@ -1281,14 +1284,14 @@ kvmppc_hisi:
 hcall_try_real_mode:
        ld      r3,VCPU_GPR(R3)(r9)
        andi.   r0,r11,MSR_PR
-       bne     hcall_real_cont
+       bne     guest_exit_cont
        clrrdi  r3,r3,2
        cmpldi  r3,hcall_real_table_end - hcall_real_table
-       bge     hcall_real_cont
+       bge     guest_exit_cont
        LOAD_REG_ADDR(r4, hcall_real_table)
        lwzx    r3,r3,r4
        cmpwi   r3,0
-       beq     hcall_real_cont
+       beq     guest_exit_cont
        add     r3,r3,r4
        mtctr   r3
        mr      r3,r9           /* get vcpu pointer */
@@ -1309,7 +1312,7 @@ hcall_real_fallback:
        li      r12,BOOK3S_INTERRUPT_SYSCALL
        ld      r9, HSTATE_KVM_VCPU(r13)
 
-       b       hcall_real_cont
+       b       guest_exit_cont
 
        .globl  hcall_real_table
 hcall_real_table:
@@ -1568,6 +1571,21 @@ kvm_cede_exit:
        li      r3,H_TOO_HARD
        blr
 
+       /* Try to handle a machine check in real mode */
+machine_check_realmode:
+       mr      r3, r9          /* get vcpu pointer */
+       bl      .kvmppc_realmode_machine_check
+       nop
+       cmpdi   r3, 0           /* continue exiting from guest? */
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       li      r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+       beq     mc_cont
+       /* If not, deliver a machine check.  SRR0/1 are already set */
+       li      r10, BOOK3S_INTERRUPT_MACHINE_CHECK
+       li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
+       rotldi  r11, r11, 63
+       b       fast_interrupt_c_return
+
 secondary_too_late:
        ld      r5,HSTATE_KVM_VCORE(r13)
        HMT_LOW
@@ -1587,6 +1605,10 @@ secondary_too_late:
        .endr
 
 secondary_nap:
+       /* Clear our vcpu pointer so we don't come back in early */
+       li      r0, 0
+       std     r0, HSTATE_KVM_VCPU(r13)
+       lwsync
        /* Clear any pending IPI - assume we're a secondary thread */
        ld      r5, HSTATE_XICS_PHYS(r13)
        li      r7, XICS_XIRR
@@ -1612,8 +1634,6 @@ secondary_nap:
 kvm_no_guest:
        li      r0, KVM_HWTHREAD_IN_NAP
        stb     r0, HSTATE_HWTHREAD_STATE(r13)
-       li      r0, 0
-       std     r0, HSTATE_KVM_VCPU(r13)
 
        li      r3, LPCR_PECE0
        mfspr   r4, SPRN_LPCR
index 41cb0017e757a1d8ccd83360624d9f1a40189426..2c86b0d6371494d4417b3e7e8d796c25a4b21a48 100644 (file)
@@ -114,11 +114,6 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
        hlist_del_init_rcu(&pte->list_vpte);
        hlist_del_init_rcu(&pte->list_vpte_long);
 
-       if (pte->pte.may_write)
-               kvm_release_pfn_dirty(pte->pfn);
-       else
-               kvm_release_pfn_clean(pte->pfn);
-
        spin_unlock(&vcpu3s->mmu_lock);
 
        vcpu3s->hpte_cache_count--;
index 05c28f59f77f4a4bc46c196addf12747cbb97e4f..28d38adeca73af0658785a79f94da7a7865ec854 100644 (file)
@@ -52,8 +52,6 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 #define MSR_USER32 MSR_USER
 #define MSR_USER64 MSR_USER
 #define HW_PAGE_SIZE PAGE_SIZE
-#define __hard_irq_disable local_irq_disable
-#define __hard_irq_enable local_irq_enable
 #endif
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -66,7 +64,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
        svcpu_put(svcpu);
 #endif
-
+       vcpu->cpu = smp_processor_id();
 #ifdef CONFIG_PPC_BOOK3S_32
        current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
 #endif
@@ -83,17 +81,71 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
        svcpu_put(svcpu);
 #endif
 
-       kvmppc_giveup_ext(vcpu, MSR_FP);
-       kvmppc_giveup_ext(vcpu, MSR_VEC);
-       kvmppc_giveup_ext(vcpu, MSR_VSX);
+       kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
+       vcpu->cpu = -1;
+}
+
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
+{
+       int r = 1; /* Indicate we want to get back into the guest */
+
+       /* We misuse TLB_FLUSH to indicate that we want to clear
+          all shadow cache entries */
+       if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+               kvmppc_mmu_pte_flush(vcpu, 0, 0);
+
+       return r;
+}
+
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       trace_kvm_unmap_hva(hva);
+
+       /*
+        * Flush all shadow tlb entries everywhere. This is slow, but
+        * we are 100% sure that we catch the to be unmapped page
+        */
+       kvm_flush_remote_tlbs(kvm);
+
+       return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+       /* kvm_unmap_hva flushes everything anyways */
+       kvm_unmap_hva(kvm, start);
+
+       return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
 }
 
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+       /* The page will get remapped properly on its next fault */
+       kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 {
        ulong smsr = vcpu->arch.shared->msr;
 
        /* Guest MSR values */
-       smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
+       smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE;
        /* Process MSR values */
        smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
        /* External providers the guest reserved */
@@ -379,10 +431,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 static inline int get_fpr_index(int i)
 {
-#ifdef CONFIG_VSX
-       i *= 2;
-#endif
-       return i;
+       return i * TS_FPRWIDTH;
 }
 
 /* Give up external provider (FPU, Altivec, VSX) */
@@ -396,41 +445,49 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
        u64 *thread_fpr = (u64*)t->fpr;
        int i;
 
-       if (!(vcpu->arch.guest_owned_ext & msr))
+       /*
+        * VSX instructions can access FP and vector registers, so if
+        * we are giving up VSX, make sure we give up FP and VMX as well.
+        */
+       if (msr & MSR_VSX)
+               msr |= MSR_FP | MSR_VEC;
+
+       msr &= vcpu->arch.guest_owned_ext;
+       if (!msr)
                return;
 
 #ifdef DEBUG_EXT
        printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
 #endif
 
-       switch (msr) {
-       case MSR_FP:
+       if (msr & MSR_FP) {
+               /*
+                * Note that on CPUs with VSX, giveup_fpu stores
+                * both the traditional FP registers and the added VSX
+                * registers into thread.fpr[].
+                */
                giveup_fpu(current);
                for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
                        vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
 
                vcpu->arch.fpscr = t->fpscr.val;
-               break;
-       case MSR_VEC:
+
+#ifdef CONFIG_VSX
+               if (cpu_has_feature(CPU_FTR_VSX))
+                       for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++)
+                               vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
+#endif
+       }
+
 #ifdef CONFIG_ALTIVEC
+       if (msr & MSR_VEC) {
                giveup_altivec(current);
                memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
                vcpu->arch.vscr = t->vscr;
-#endif
-               break;
-       case MSR_VSX:
-#ifdef CONFIG_VSX
-               __giveup_vsx(current);
-               for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
-                       vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
-#endif
-               break;
-       default:
-               BUG();
        }
+#endif
 
-       vcpu->arch.guest_owned_ext &= ~msr;
-       current->thread.regs->msr &= ~msr;
+       vcpu->arch.guest_owned_ext &= ~(msr | MSR_VSX);
        kvmppc_recalc_shadow_msr(vcpu);
 }
 
@@ -490,47 +547,56 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
                return RESUME_GUEST;
        }
 
-       /* We already own the ext */
-       if (vcpu->arch.guest_owned_ext & msr) {
-               return RESUME_GUEST;
+       if (msr == MSR_VSX) {
+               /* No VSX?  Give an illegal instruction interrupt */
+#ifdef CONFIG_VSX
+               if (!cpu_has_feature(CPU_FTR_VSX))
+#endif
+               {
+                       kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
+                       return RESUME_GUEST;
+               }
+
+               /*
+                * We have to load up all the FP and VMX registers before
+                * we can let the guest use VSX instructions.
+                */
+               msr = MSR_FP | MSR_VEC | MSR_VSX;
        }
 
+       /* See if we already own all the ext(s) needed */
+       msr &= ~vcpu->arch.guest_owned_ext;
+       if (!msr)
+               return RESUME_GUEST;
+
 #ifdef DEBUG_EXT
        printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
 #endif
 
        current->thread.regs->msr |= msr;
 
-       switch (msr) {
-       case MSR_FP:
+       if (msr & MSR_FP) {
                for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
                        thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
-
+#ifdef CONFIG_VSX
+               for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++)
+                       thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
+#endif
                t->fpscr.val = vcpu->arch.fpscr;
                t->fpexc_mode = 0;
                kvmppc_load_up_fpu();
-               break;
-       case MSR_VEC:
+       }
+
+       if (msr & MSR_VEC) {
 #ifdef CONFIG_ALTIVEC
                memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
                t->vscr = vcpu->arch.vscr;
                t->vrsave = -1;
                kvmppc_load_up_altivec();
 #endif
-               break;
-       case MSR_VSX:
-#ifdef CONFIG_VSX
-               for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
-                       thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
-               kvmppc_load_up_vsx();
-#endif
-               break;
-       default:
-               BUG();
        }
 
        vcpu->arch.guest_owned_ext |= msr;
-
        kvmppc_recalc_shadow_msr(vcpu);
 
        return RESUME_GUEST;
@@ -540,18 +606,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
        int r = RESUME_HOST;
+       int s;
 
        vcpu->stat.sum_exits++;
 
        run->exit_reason = KVM_EXIT_UNKNOWN;
        run->ready_for_interrupt_injection = 1;
 
-       /* We get here with MSR.EE=0, so enable it to be a nice citizen */
-       __hard_irq_enable();
+       /* We get here with MSR.EE=1 */
+
+       trace_kvm_exit(exit_nr, vcpu);
+       kvm_guest_exit();
 
-       trace_kvm_book3s_exit(exit_nr, vcpu);
-       preempt_enable();
-       kvm_resched(vcpu);
        switch (exit_nr) {
        case BOOK3S_INTERRUPT_INST_STORAGE:
        {
@@ -802,7 +868,6 @@ program_interrupt:
        }
        }
 
-       preempt_disable();
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
                 * we aren't already exiting to userspace for some other
@@ -814,20 +879,13 @@ program_interrupt:
                 * and if we really did time things so badly, then we just exit
                 * again due to a host external interrupt.
                 */
-               __hard_irq_disable();
-               if (signal_pending(current)) {
-                       __hard_irq_enable();
-#ifdef EXIT_DEBUG
-                       printk(KERN_EMERG "KVM: Going back to host\n");
-#endif
-                       vcpu->stat.signal_exits++;
-                       run->exit_reason = KVM_EXIT_INTR;
-                       r = -EINTR;
+               local_irq_disable();
+               s = kvmppc_prepare_to_enter(vcpu);
+               if (s <= 0) {
+                       local_irq_enable();
+                       r = s;
                } else {
-                       /* In case an interrupt came in that was triggered
-                        * from userspace (like DEC), we need to check what
-                        * to inject now! */
-                       kvmppc_core_prepare_to_enter(vcpu);
+                       kvmppc_lazy_ee_enable();
                }
        }
 
@@ -899,34 +957,59 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-               r = copy_to_user((u64 __user *)(long)reg->addr,
-                               &to_book3s(vcpu)->hior, sizeof(u64));
+               *val = get_reg_val(id, to_book3s(vcpu)->hior);
                break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
+               long int i = id - KVM_REG_PPC_VSR0;
+
+               if (!cpu_has_feature(CPU_FTR_VSX)) {
+                       r = -ENXIO;
+                       break;
+               }
+               val->vsxval[0] = vcpu->arch.fpr[i];
+               val->vsxval[1] = vcpu->arch.vsr[i];
+               break;
+       }
+#endif /* CONFIG_VSX */
        default:
+               r = -EINVAL;
                break;
        }
 
        return r;
 }
 
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-       int r = -EINVAL;
+       int r = 0;
 
-       switch (reg->id) {
+       switch (id) {
        case KVM_REG_PPC_HIOR:
-               r = copy_from_user(&to_book3s(vcpu)->hior,
-                                  (u64 __user *)(long)reg->addr, sizeof(u64));
-               if (!r)
-                       to_book3s(vcpu)->hior_explicit = true;
+               to_book3s(vcpu)->hior = set_reg_val(id, *val);
+               to_book3s(vcpu)->hior_explicit = true;
+               break;
+#ifdef CONFIG_VSX
+       case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
+               long int i = id - KVM_REG_PPC_VSR0;
+
+               if (!cpu_has_feature(CPU_FTR_VSX)) {
+                       r = -ENXIO;
+                       break;
+               }
+               vcpu->arch.fpr[i] = val->vsxval[0];
+               vcpu->arch.vsr[i] = val->vsxval[1];
                break;
+       }
+#endif /* CONFIG_VSX */
        default:
+               r = -EINVAL;
                break;
        }
 
@@ -1020,8 +1103,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
        ulong ext_msr;
 
-       preempt_disable();
-
        /* Check if we can run the vcpu at all */
        if (!vcpu->arch.sane) {
                kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -1029,21 +1110,16 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                goto out;
        }
 
-       kvmppc_core_prepare_to_enter(vcpu);
-
        /*
         * Interrupts could be timers for the guest which we have to inject
         * again, so let's postpone them until we're in the guest and if we
         * really did time things so badly, then we just exit again due to
         * a host external interrupt.
         */
-       __hard_irq_disable();
-
-       /* No need to go into the guest when all we do is going out */
-       if (signal_pending(current)) {
-               __hard_irq_enable();
-               kvm_run->exit_reason = KVM_EXIT_INTR;
-               ret = -EINTR;
+       local_irq_disable();
+       ret = kvmppc_prepare_to_enter(vcpu);
+       if (ret <= 0) {
+               local_irq_enable();
                goto out;
        }
 
@@ -1070,7 +1146,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        /* Save VSX state in stack */
        used_vsr = current->thread.used_vsr;
        if (used_vsr && (current->thread.regs->msr & MSR_VSX))
-                       __giveup_vsx(current);
+               __giveup_vsx(current);
 #endif
 
        /* Remember the MSR with disabled extensions */
@@ -1080,20 +1156,19 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        if (vcpu->arch.shared->msr & MSR_FP)
                kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
 
-       kvm_guest_enter();
+       kvmppc_lazy_ee_enable();
 
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
-       kvm_guest_exit();
-
-       current->thread.regs->msr = ext_msr;
+       /* No need for kvm_guest_exit. It's done in handle_exit.
+          We also get here with interrupts enabled. */
 
        /* Make sure we save the guest FPU/Altivec/VSX state */
-       kvmppc_giveup_ext(vcpu, MSR_FP);
-       kvmppc_giveup_ext(vcpu, MSR_VEC);
-       kvmppc_giveup_ext(vcpu, MSR_VSX);
+       kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
+
+       current->thread.regs->msr = ext_msr;
 
-       /* Restore FPU state from stack */
+       /* Restore FPU/VSX state from stack */
        memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
        current->thread.fpscr.val = fpscr;
        current->thread.fpexc_mode = fpexc_mode;
@@ -1113,7 +1188,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
 out:
-       preempt_enable();
+       vcpu->mode = OUTSIDE_GUEST_MODE;
        return ret;
 }
 
@@ -1181,14 +1256,31 @@ int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info)
 }
 #endif /* CONFIG_PPC64 */
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                             struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                              unsigned long npages)
+{
+       return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot,
                                      struct kvm_userspace_memory_region *mem)
 {
        return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
index 9ecf6e35cd8de0de4fe148a7527524a46256c900..8f7633e3afb8112b0123a298211a31c82240dcf0 100644 (file)
@@ -170,20 +170,21 @@ kvmppc_handler_skip_ins:
  * Call kvmppc_handler_trampoline_enter in real mode
  *
  * On entry, r4 contains the guest shadow MSR
+ * MSR.EE has to be 0 when calling this function
  */
 _GLOBAL(kvmppc_entry_trampoline)
        mfmsr   r5
        LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
        toreal(r7)
 
-       li      r9, MSR_RI
-       ori     r9, r9, MSR_EE
-       andc    r9, r5, r9      /* Clear EE and RI in MSR value */
        li      r6, MSR_IR | MSR_DR
-       ori     r6, r6, MSR_EE
-       andc    r6, r5, r6      /* Clear EE, DR and IR in MSR value */
-       MTMSR_EERI(r9)          /* Clear EE and RI in MSR */
-       mtsrr0  r7              /* before we set srr0/1 */
+       andc    r6, r5, r6      /* Clear DR and IR in MSR value */
+       /*
+        * Set EE in HOST_MSR so that it's enabled when we get into our
+        * C exit handler function
+        */
+       ori     r5, r5, MSR_EE
+       mtsrr0  r7
        mtsrr1  r6
        RFI
 
@@ -233,8 +234,5 @@ define_load_up(fpu)
 #ifdef CONFIG_ALTIVEC
 define_load_up(altivec)
 #endif
-#ifdef CONFIG_VSX
-define_load_up(vsx)
-#endif
 
 #include "book3s_segment.S"
index d25a097c852b75469785578cde71daef2043c65b..69f1140157807c7df83c33541975e799563ed865 100644 (file)
 #include <asm/dbell.h>
 #include <asm/hw_irq.h>
 #include <asm/irq.h>
+#include <asm/time.h>
 
 #include "timing.h"
 #include "booke.h"
+#include "trace.h"
 
 unsigned long kvmppc_booke_handlers;
 
@@ -62,6 +64,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "doorbell", VCPU_STAT(dbell_exits) },
        { "guest doorbell", VCPU_STAT(gdbell_exits) },
+       { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
        { NULL }
 };
 
@@ -120,6 +123,16 @@ static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
 }
 #endif
 
+static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_PPC_FPU) && !defined(CONFIG_KVM_BOOKE_HV)
+       /* We always treat the FP bit as enabled from the host
+          perspective, so only need to adjust the shadow MSR */
+       vcpu->arch.shadow_msr &= ~MSR_FP;
+       vcpu->arch.shadow_msr |= vcpu->arch.shared->msr & MSR_FP;
+#endif
+}
+
 /*
  * Helper function for "full" MSR writes.  No need to call this if only
  * EE/CE/ME/DE/RI are changing.
@@ -136,11 +149,13 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
 
        kvmppc_mmu_msr_notify(vcpu, old_msr);
        kvmppc_vcpu_sync_spe(vcpu);
+       kvmppc_vcpu_sync_fpu(vcpu);
 }
 
 static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
                                        unsigned int priority)
 {
+       trace_kvm_booke_queue_irqprio(vcpu, priority);
        set_bit(priority, &vcpu->arch.pending_exceptions);
 }
 
@@ -206,6 +221,16 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
        clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
 }
 
+static void kvmppc_core_queue_watchdog(struct kvm_vcpu *vcpu)
+{
+       kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_WATCHDOG);
+}
+
+static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu)
+{
+       clear_bit(BOOKE_IRQPRIO_WATCHDOG, &vcpu->arch.pending_exceptions);
+}
+
 static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
@@ -287,6 +312,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
        bool crit;
        bool keep_irq = false;
        enum int_class int_class;
+       ulong new_msr = vcpu->arch.shared->msr;
 
        /* Truncate crit indicators in 32 bit mode */
        if (!(vcpu->arch.shared->msr & MSR_SF)) {
@@ -325,6 +351,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                msr_mask = MSR_CE | MSR_ME | MSR_DE;
                int_class = INT_CLASS_NONCRIT;
                break;
+       case BOOKE_IRQPRIO_WATCHDOG:
        case BOOKE_IRQPRIO_CRITICAL:
        case BOOKE_IRQPRIO_DBELL_CRIT:
                allowed = vcpu->arch.shared->msr & MSR_CE;
@@ -381,7 +408,13 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                        set_guest_esr(vcpu, vcpu->arch.queued_esr);
                if (update_dear == true)
                        set_guest_dear(vcpu, vcpu->arch.queued_dear);
-               kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
+
+               new_msr &= msr_mask;
+#if defined(CONFIG_64BIT)
+               if (vcpu->arch.epcr & SPRN_EPCR_ICM)
+                       new_msr |= MSR_CM;
+#endif
+               kvmppc_set_msr(vcpu, new_msr);
 
                if (!keep_irq)
                        clear_bit(priority, &vcpu->arch.pending_exceptions);
@@ -404,12 +437,121 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
        return allowed;
 }
 
+/*
+ * Return the number of jiffies until the next timeout.  If the timeout is
+ * longer than the NEXT_TIMER_MAX_DELTA, then return NEXT_TIMER_MAX_DELTA
+ * because the larger value can break the timer APIs.
+ */
+static unsigned long watchdog_next_timeout(struct kvm_vcpu *vcpu)
+{
+       u64 tb, wdt_tb, wdt_ticks = 0;
+       u64 nr_jiffies = 0;
+       u32 period = TCR_GET_WP(vcpu->arch.tcr);
+
+       wdt_tb = 1ULL << (63 - period);
+       tb = get_tb();
+       /*
+        * The watchdog timeout will hapeen when TB bit corresponding
+        * to watchdog will toggle from 0 to 1.
+        */
+       if (tb & wdt_tb)
+               wdt_ticks = wdt_tb;
+
+       wdt_ticks += wdt_tb - (tb & (wdt_tb - 1));
+
+       /* Convert timebase ticks to jiffies */
+       nr_jiffies = wdt_ticks;
+
+       if (do_div(nr_jiffies, tb_ticks_per_jiffy))
+               nr_jiffies++;
+
+       return min_t(unsigned long long, nr_jiffies, NEXT_TIMER_MAX_DELTA);
+}
+
+static void arm_next_watchdog(struct kvm_vcpu *vcpu)
+{
+       unsigned long nr_jiffies;
+       unsigned long flags;
+
+       /*
+        * If TSR_ENW and TSR_WIS are not set then no need to exit to
+        * userspace, so clear the KVM_REQ_WATCHDOG request.
+        */
+       if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS))
+               clear_bit(KVM_REQ_WATCHDOG, &vcpu->requests);
+
+       spin_lock_irqsave(&vcpu->arch.wdt_lock, flags);
+       nr_jiffies = watchdog_next_timeout(vcpu);
+       /*
+        * If the number of jiffies of watchdog timer >= NEXT_TIMER_MAX_DELTA
+        * then do not run the watchdog timer as this can break timer APIs.
+        */
+       if (nr_jiffies < NEXT_TIMER_MAX_DELTA)
+               mod_timer(&vcpu->arch.wdt_timer, jiffies + nr_jiffies);
+       else
+               del_timer(&vcpu->arch.wdt_timer);
+       spin_unlock_irqrestore(&vcpu->arch.wdt_lock, flags);
+}
+
+void kvmppc_watchdog_func(unsigned long data)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+       u32 tsr, new_tsr;
+       int final;
+
+       do {
+               new_tsr = tsr = vcpu->arch.tsr;
+               final = 0;
+
+               /* Time out event */
+               if (tsr & TSR_ENW) {
+                       if (tsr & TSR_WIS)
+                               final = 1;
+                       else
+                               new_tsr = tsr | TSR_WIS;
+               } else {
+                       new_tsr = tsr | TSR_ENW;
+               }
+       } while (cmpxchg(&vcpu->arch.tsr, tsr, new_tsr) != tsr);
+
+       if (new_tsr & TSR_WIS) {
+               smp_wmb();
+               kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+               kvm_vcpu_kick(vcpu);
+       }
+
+       /*
+        * If this is final watchdog expiry and some action is required
+        * then exit to userspace.
+        */
+       if (final && (vcpu->arch.tcr & TCR_WRC_MASK) &&
+           vcpu->arch.watchdog_enabled) {
+               smp_wmb();
+               kvm_make_request(KVM_REQ_WATCHDOG, vcpu);
+               kvm_vcpu_kick(vcpu);
+       }
+
+       /*
+        * Stop running the watchdog timer after final expiration to
+        * prevent the host from being flooded with timers if the
+        * guest sets a short period.
+        * Timers will resume when TSR/TCR is updated next time.
+        */
+       if (!final)
+               arm_next_watchdog(vcpu);
+}
+
 static void update_timer_ints(struct kvm_vcpu *vcpu)
 {
        if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
                kvmppc_core_queue_dec(vcpu);
        else
                kvmppc_core_dequeue_dec(vcpu);
+
+       if ((vcpu->arch.tcr & TCR_WIE) && (vcpu->arch.tsr & TSR_WIS))
+               kvmppc_core_queue_watchdog(vcpu);
+       else
+               kvmppc_core_dequeue_watchdog(vcpu);
 }
 
 static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
@@ -417,13 +559,6 @@ static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
        unsigned long *pending = &vcpu->arch.pending_exceptions;
        unsigned int priority;
 
-       if (vcpu->requests) {
-               if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
-                       smp_mb();
-                       update_timer_ints(vcpu);
-               }
-       }
-
        priority = __ffs(*pending);
        while (priority < BOOKE_IRQPRIO_MAX) {
                if (kvmppc_booke_irqprio_deliver(vcpu, priority))
@@ -459,37 +594,20 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
        return r;
 }
 
-/*
- * Common checks before entering the guest world.  Call with interrupts
- * disabled.
- *
- * returns !0 if a signal is pending and check_signal is true
- */
-static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 {
-       int r = 0;
+       int r = 1; /* Indicate we want to get back into the guest */
 
-       WARN_ON_ONCE(!irqs_disabled());
-       while (true) {
-               if (need_resched()) {
-                       local_irq_enable();
-                       cond_resched();
-                       local_irq_disable();
-                       continue;
-               }
-
-               if (signal_pending(current)) {
-                       r = 1;
-                       break;
-               }
-
-               if (kvmppc_core_prepare_to_enter(vcpu)) {
-                       /* interrupts got enabled in between, so we
-                          are back at square 1 */
-                       continue;
-               }
+       if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu))
+               update_timer_ints(vcpu);
+#if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
+       if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+               kvmppc_core_flush_tlb(vcpu);
+#endif
 
-               break;
+       if (kvm_check_request(KVM_REQ_WATCHDOG, vcpu)) {
+               vcpu->run->exit_reason = KVM_EXIT_WATCHDOG;
+               r = 0;
        }
 
        return r;
@@ -497,7 +615,7 @@ static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
-       int ret;
+       int ret, s;
 #ifdef CONFIG_PPC_FPU
        unsigned int fpscr;
        int fpexc_mode;
@@ -510,11 +628,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        }
 
        local_irq_disable();
-       if (kvmppc_prepare_to_enter(vcpu)) {
-               kvm_run->exit_reason = KVM_EXIT_INTR;
-               ret = -EINTR;
+       s = kvmppc_prepare_to_enter(vcpu);
+       if (s <= 0) {
+               local_irq_enable();
+               ret = s;
                goto out;
        }
+       kvmppc_lazy_ee_enable();
 
        kvm_guest_enter();
 
@@ -542,6 +662,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
+       /* No need for kvm_guest_exit. It's done in handle_exit.
+          We also get here with interrupts enabled. */
+
 #ifdef CONFIG_PPC_FPU
        kvmppc_save_guest_fp(vcpu);
 
@@ -557,10 +680,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        current->thread.fpexc_mode = fpexc_mode;
 #endif
 
-       kvm_guest_exit();
-
 out:
-       local_irq_enable();
+       vcpu->mode = OUTSIDE_GUEST_MODE;
        return ret;
 }
 
@@ -668,6 +789,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
        int r = RESUME_HOST;
+       int s;
 
        /* update before a new last_exit_type is rewritten */
        kvmppc_update_timing_stats(vcpu);
@@ -677,6 +799,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        local_irq_enable();
 
+       trace_kvm_exit(exit_nr, vcpu);
+       kvm_guest_exit();
+
        run->exit_reason = KVM_EXIT_UNKNOWN;
        run->ready_for_interrupt_injection = 1;
 
@@ -971,10 +1096,12 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
         */
        if (!(r & RESUME_HOST)) {
                local_irq_disable();
-               if (kvmppc_prepare_to_enter(vcpu)) {
-                       run->exit_reason = KVM_EXIT_INTR;
-                       r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
-                       kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+               s = kvmppc_prepare_to_enter(vcpu);
+               if (s <= 0) {
+                       local_irq_enable();
+                       r = (s << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
+               } else {
+                       kvmppc_lazy_ee_enable();
                }
        }
 
@@ -1011,6 +1138,21 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return r;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       /* setup watchdog timer once */
+       spin_lock_init(&vcpu->arch.wdt_lock);
+       setup_timer(&vcpu->arch.wdt_timer, kvmppc_watchdog_func,
+                   (unsigned long)vcpu);
+
+       return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+       del_timer_sync(&vcpu->arch.wdt_timer);
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        int i;
@@ -1106,7 +1248,13 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
        }
 
        if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
+               u32 old_tsr = vcpu->arch.tsr;
+
                vcpu->arch.tsr = sregs->u.e.tsr;
+
+               if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
+                       arm_next_watchdog(vcpu);
+
                update_timer_ints(vcpu);
        }
 
@@ -1221,12 +1369,70 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-       return -EINVAL;
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_IAC1:
+       case KVM_REG_PPC_IAC2:
+       case KVM_REG_PPC_IAC3:
+       case KVM_REG_PPC_IAC4: {
+               int iac = reg->id - KVM_REG_PPC_IAC1;
+               r = copy_to_user((u64 __user *)(long)reg->addr,
+                                &vcpu->arch.dbg_reg.iac[iac], sizeof(u64));
+               break;
+       }
+       case KVM_REG_PPC_DAC1:
+       case KVM_REG_PPC_DAC2: {
+               int dac = reg->id - KVM_REG_PPC_DAC1;
+               r = copy_to_user((u64 __user *)(long)reg->addr,
+                                &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
+               break;
+       }
+#if defined(CONFIG_64BIT)
+       case KVM_REG_PPC_EPCR:
+               r = put_user(vcpu->arch.epcr, (u32 __user *)(long)reg->addr);
+               break;
+#endif
+       default:
+               break;
+       }
+       return r;
 }
 
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-       return -EINVAL;
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_IAC1:
+       case KVM_REG_PPC_IAC2:
+       case KVM_REG_PPC_IAC3:
+       case KVM_REG_PPC_IAC4: {
+               int iac = reg->id - KVM_REG_PPC_IAC1;
+               r = copy_from_user(&vcpu->arch.dbg_reg.iac[iac],
+                            (u64 __user *)(long)reg->addr, sizeof(u64));
+               break;
+       }
+       case KVM_REG_PPC_DAC1:
+       case KVM_REG_PPC_DAC2: {
+               int dac = reg->id - KVM_REG_PPC_DAC1;
+               r = copy_from_user(&vcpu->arch.dbg_reg.dac[dac],
+                            (u64 __user *)(long)reg->addr, sizeof(u64));
+               break;
+       }
+#if defined(CONFIG_64BIT)
+       case KVM_REG_PPC_EPCR: {
+               u32 new_epcr;
+               r = get_user(new_epcr, (u32 __user *)(long)reg->addr);
+               if (r == 0)
+                       kvmppc_set_epcr(vcpu, new_epcr);
+               break;
+       }
+#endif
+       default:
+               break;
+       }
+       return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
@@ -1253,20 +1459,50 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
        return -ENOTSUPP;
 }
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+                             struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+                              unsigned long npages)
+{
+       return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+                                     struct kvm_memory_slot *memslot,
                                      struct kvm_userspace_memory_region *mem)
 {
        return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
+                               struct kvm_userspace_memory_region *mem,
+                               struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+}
+
+void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr)
 {
+#if defined(CONFIG_64BIT)
+       vcpu->arch.epcr = new_epcr;
+#ifdef CONFIG_KVM_BOOKE_HV
+       vcpu->arch.shadow_epcr &= ~SPRN_EPCR_GICM;
+       if (vcpu->arch.epcr  & SPRN_EPCR_ICM)
+               vcpu->arch.shadow_epcr |= SPRN_EPCR_GICM;
+#endif
+#endif
 }
 
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
 {
        vcpu->arch.tcr = new_tcr;
+       arm_next_watchdog(vcpu);
        update_timer_ints(vcpu);
 }
 
@@ -1281,6 +1517,14 @@ void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 {
        clear_bits(tsr_bits, &vcpu->arch.tsr);
+
+       /*
+        * We may have stopped the watchdog due to
+        * being stuck on final expiration.
+        */
+       if (tsr_bits & (TSR_ENW | TSR_WIS))
+               arm_next_watchdog(vcpu);
+
        update_timer_ints(vcpu);
 }
 
@@ -1298,12 +1542,14 @@ void kvmppc_decrementer_func(unsigned long data)
 
 void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+       vcpu->cpu = smp_processor_id();
        current->thread.kvm_vcpu = vcpu;
 }
 
 void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu)
 {
        current->thread.kvm_vcpu = NULL;
+       vcpu->cpu = -1;
 }
 
 int __init kvmppc_booke_init(void)
index ba61974c1e20839f454ebb9e33cc8f46e4949d9e..e9b88e433f64a3d835d8b8970ab6ff6a6d0ebf56 100644 (file)
@@ -69,6 +69,7 @@ extern unsigned long kvmppc_booke_handlers;
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
 void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
 
+void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr);
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr);
 void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
 void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
index 12834bb608aba1e41653fa6aaa96f0735d587b80..4685b8cf224959a29d1c6e774109e31f47f5c2e6 100644 (file)
@@ -133,10 +133,10 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                vcpu->arch.csrr1 = spr_val;
                break;
        case SPRN_DBCR0:
-               vcpu->arch.dbcr0 = spr_val;
+               vcpu->arch.dbg_reg.dbcr0 = spr_val;
                break;
        case SPRN_DBCR1:
-               vcpu->arch.dbcr1 = spr_val;
+               vcpu->arch.dbg_reg.dbcr1 = spr_val;
                break;
        case SPRN_DBSR:
                vcpu->arch.dbsr &= ~spr_val;
@@ -145,6 +145,14 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                kvmppc_clr_tsr_bits(vcpu, spr_val);
                break;
        case SPRN_TCR:
+               /*
+                * WRC is a 2-bit field that is supposed to preserve its
+                * value once written to non-zero.
+                */
+               if (vcpu->arch.tcr & TCR_WRC_MASK) {
+                       spr_val &= ~TCR_WRC_MASK;
+                       spr_val |= vcpu->arch.tcr & TCR_WRC_MASK;
+               }
                kvmppc_set_tcr(vcpu, spr_val);
                break;
 
@@ -229,7 +237,17 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
        case SPRN_IVOR15:
                vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
                break;
-
+       case SPRN_MCSR:
+               vcpu->arch.mcsr &= ~spr_val;
+               break;
+#if defined(CONFIG_64BIT)
+       case SPRN_EPCR:
+               kvmppc_set_epcr(vcpu, spr_val);
+#ifdef CONFIG_KVM_BOOKE_HV
+               mtspr(SPRN_EPCR, vcpu->arch.shadow_epcr);
+#endif
+               break;
+#endif
        default:
                emulated = EMULATE_FAIL;
        }
@@ -258,10 +276,10 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
                *spr_val = vcpu->arch.csrr1;
                break;
        case SPRN_DBCR0:
-               *spr_val = vcpu->arch.dbcr0;
+               *spr_val = vcpu->arch.dbg_reg.dbcr0;
                break;
        case SPRN_DBCR1:
-               *spr_val = vcpu->arch.dbcr1;
+               *spr_val = vcpu->arch.dbg_reg.dbcr1;
                break;
        case SPRN_DBSR:
                *spr_val = vcpu->arch.dbsr;
@@ -321,6 +339,14 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
        case SPRN_IVOR15:
                *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
                break;
+       case SPRN_MCSR:
+               *spr_val = vcpu->arch.mcsr;
+               break;
+#if defined(CONFIG_64BIT)
+       case SPRN_EPCR:
+               *spr_val = vcpu->arch.epcr;
+               break;
+#endif
 
        default:
                emulated = EMULATE_FAIL;
index 099fe8272b57fdd7fdfb9de56ff1beb53dd36e53..e8ed7d659c55f8cbcdc341c07ea58a8bc26b744d 100644 (file)
@@ -16,6 +16,7 @@
  *
  * Author: Varun Sethi <varun.sethi@freescale.com>
  * Author: Scott Wood <scotwood@freescale.com>
+ * Author: Mihai Caraman <mihai.caraman@freescale.com>
  *
  * This file is derived from arch/powerpc/kvm/booke_interrupts.S
  */
 #include <asm/bitsperlong.h>
 #include <asm/thread_info.h>
 
+#ifdef CONFIG_64BIT
+#include <asm/exception-64e.h>
+#else
 #include "../kernel/head_booke.h" /* for THREAD_NORMSAVE() */
-
-#define GET_VCPU(vcpu, thread) \
-       PPC_LL  vcpu, THREAD_KVM_VCPU(thread)
+#endif
 
 #define LONGBYTES              (BITS_PER_LONG / 8)
 
 #define VCPU_GUEST_SPRG(n)     (VCPU_GUEST_SPRGS + (n * LONGBYTES))
 
 /* The host stack layout: */
-#define HOST_R1         (0 * LONGBYTES) /* Implied by stwu. */
-#define HOST_CALLEE_LR  (1 * LONGBYTES)
-#define HOST_RUN        (2 * LONGBYTES) /* struct kvm_run */
+#define HOST_R1         0 /* Implied by stwu. */
+#define HOST_CALLEE_LR  PPC_LR_STKOFF
+#define HOST_RUN        (HOST_CALLEE_LR + LONGBYTES)
 /*
  * r2 is special: it holds 'current', and it made nonvolatile in the
  * kernel with the -ffixed-r2 gcc option.
  */
-#define HOST_R2         (3 * LONGBYTES)
-#define HOST_CR         (4 * LONGBYTES)
-#define HOST_NV_GPRS    (5 * LONGBYTES)
+#define HOST_R2         (HOST_RUN + LONGBYTES)
+#define HOST_CR         (HOST_R2 + LONGBYTES)
+#define HOST_NV_GPRS    (HOST_CR + LONGBYTES)
 #define __HOST_NV_GPR(n)  (HOST_NV_GPRS + ((n - 14) * LONGBYTES))
 #define HOST_NV_GPR(n)  __HOST_NV_GPR(__REG_##n)
 #define HOST_MIN_STACK_SIZE (HOST_NV_GPR(R31) + LONGBYTES)
 #define HOST_STACK_SIZE ((HOST_MIN_STACK_SIZE + 15) & ~15) /* Align. */
-#define HOST_STACK_LR   (HOST_STACK_SIZE + LONGBYTES) /* In caller stack frame. */
+/* LR in caller stack frame. */
+#define HOST_STACK_LR  (HOST_STACK_SIZE + PPC_LR_STKOFF)
 
 #define NEED_EMU               0x00000001 /* emulation -- save nv regs */
 #define NEED_DEAR              0x00000002 /* save faulting DEAR */
        b       kvmppc_resume_host
 .endm
 
+#ifdef CONFIG_64BIT
+/* Exception types */
+#define EX_GEN                 1
+#define EX_GDBELL              2
+#define EX_DBG                 3
+#define EX_MC                  4
+#define EX_CRIT                        5
+#define EX_TLB                 6
+
+/*
+ * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
+ */
+.macro kvm_handler intno type scratch, paca_ex, ex_r10, ex_r11, srr0, srr1, flags
+ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
+       mr      r11, r4
+       /*
+        * Get vcpu from Paca: paca->__current.thread->kvm_vcpu
+        */
+       PPC_LL  r4, PACACURRENT(r13)
+       PPC_LL  r4, (THREAD + THREAD_KVM_VCPU)(r4)
+       stw     r10, VCPU_CR(r4)
+       PPC_STL r11, VCPU_GPR(R4)(r4)
+       PPC_STL r5, VCPU_GPR(R5)(r4)
+       .if \type == EX_CRIT
+       PPC_LL  r5, (\paca_ex + EX_R13)(r13)
+       .else
+       mfspr   r5, \scratch
+       .endif
+       PPC_STL r6, VCPU_GPR(R6)(r4)
+       PPC_STL r8, VCPU_GPR(R8)(r4)
+       PPC_STL r9, VCPU_GPR(R9)(r4)
+       PPC_STL r5, VCPU_GPR(R13)(r4)
+       PPC_LL  r6, (\paca_ex + \ex_r10)(r13)
+       PPC_LL  r8, (\paca_ex + \ex_r11)(r13)
+       PPC_STL r3, VCPU_GPR(R3)(r4)
+       PPC_STL r7, VCPU_GPR(R7)(r4)
+       PPC_STL r12, VCPU_GPR(R12)(r4)
+       PPC_STL r6, VCPU_GPR(R10)(r4)
+       PPC_STL r8, VCPU_GPR(R11)(r4)
+       mfctr   r5
+       PPC_STL r5, VCPU_CTR(r4)
+       mfspr   r5, \srr0
+       mfspr   r6, \srr1
+       kvm_handler_common \intno, \srr0, \flags
+.endm
+
+#define EX_PARAMS(type) \
+       EX_##type, \
+       SPRN_SPRG_##type##_SCRATCH, \
+       PACA_EX##type, \
+       EX_R10, \
+       EX_R11
+
+#define EX_PARAMS_TLB \
+       EX_TLB, \
+       SPRN_SPRG_GEN_SCRATCH, \
+       PACA_EXTLB, \
+       EX_TLB_R10, \
+       EX_TLB_R11
+
+kvm_handler BOOKE_INTERRUPT_CRITICAL, EX_PARAMS(CRIT), \
+       SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_MACHINE_CHECK, EX_PARAMS(MC), \
+       SPRN_MCSRR0, SPRN_MCSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DATA_STORAGE, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1,(NEED_EMU | NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_INST_STORAGE, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, NEED_ESR
+kvm_handler BOOKE_INTERRUPT_EXTERNAL, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_ALIGNMENT, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1,(NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_PROGRAM, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1,NEED_ESR
+kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DECREMENTER, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_FIT, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_WATCHDOG, EX_PARAMS(CRIT),\
+       SPRN_CSRR0, SPRN_CSRR1, 0
+/*
+ * Only bolted TLB miss exception handlers are supported for now
+ */
+kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS_TLB, \
+       SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS_TLB, \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DOORBELL, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DOORBELL_CRITICAL, EX_PARAMS(CRIT), \
+       SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_HV_PRIV, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, NEED_EMU
+kvm_handler BOOKE_INTERRUPT_HV_SYSCALL, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_GUEST_DBELL, EX_PARAMS(GDBELL), \
+       SPRN_GSRR0, SPRN_GSRR1, 0
+kvm_handler BOOKE_INTERRUPT_GUEST_DBELL_CRIT, EX_PARAMS(CRIT), \
+       SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \
+       SPRN_DSRR0, SPRN_DSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \
+       SPRN_CSRR0, SPRN_CSRR1, 0
+#else
 /*
  * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
  */
 .macro kvm_handler intno srr0, srr1, flags
 _GLOBAL(kvmppc_handler_\intno\()_\srr1)
-       GET_VCPU(r11, r10)
+       PPC_LL  r11, THREAD_KVM_VCPU(r10)
        PPC_STL r3, VCPU_GPR(R3)(r11)
        mfspr   r3, SPRN_SPRG_RSCRATCH0
        PPC_STL r4, VCPU_GPR(R4)(r11)
@@ -233,7 +352,7 @@ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
 .macro kvm_lvl_handler intno scratch srr0, srr1, flags
 _GLOBAL(kvmppc_handler_\intno\()_\srr1)
        mfspr   r10, SPRN_SPRG_THREAD
-       GET_VCPU(r11, r10)
+       PPC_LL  r11, THREAD_KVM_VCPU(r10)
        PPC_STL r3, VCPU_GPR(R3)(r11)
        mfspr   r3, \scratch
        PPC_STL r4, VCPU_GPR(R4)(r11)
@@ -295,7 +414,7 @@ kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
        SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
 kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
        SPRN_SPRG_RSCRATCH_DBG, SPRN_DSRR0, SPRN_DSRR1, 0
-
+#endif
 
 /* Registers:
  *  SPRG_SCRATCH0: guest r10
index aa8b81428bf4afd168a1a2e8fa40da83f180b860..c70d37ed770a33c4d844ccbaca59f7c3e8e413e6 100644 (file)
@@ -27,8 +27,7 @@
 #define E500_TLB_NUM   2
 
 #define E500_TLB_VALID 1
-#define E500_TLB_DIRTY 2
-#define E500_TLB_BITMAP 4
+#define E500_TLB_BITMAP 2
 
 struct tlbe_ref {
        pfn_t pfn;
@@ -130,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
                                ulong value);
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
 int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
 int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
 
@@ -155,7 +154,7 @@ get_tlb_size(const struct kvm_book3e_206_tlb_entry *tlbe)
 
 static inline gva_t get_tlb_eaddr(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
-       return tlbe->mas2 & 0xfffff000;
+       return tlbe->mas2 & MAS2_EPN;
 }
 
 static inline u64 get_tlb_bytes(const struct kvm_book3e_206_tlb_entry *tlbe)
index e04b0ef55ce0e131df45cdadd06d95d004129bbb..e78f353a836a0731d96217546598a93b2ae22dfd 100644 (file)
@@ -89,6 +89,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
        int ra = get_ra(inst);
        int rb = get_rb(inst);
        int rt = get_rt(inst);
+       gva_t ea;
 
        switch (get_op(inst)) {
        case 31:
@@ -113,15 +114,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        break;
 
                case XOP_TLBSX:
-                       emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
+                       ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+                       emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
                        break;
 
-               case XOP_TLBILX:
-                       emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
+               case XOP_TLBILX: {
+                       int type = rt & 0x3;
+                       ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+                       emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea);
                        break;
+               }
 
                case XOP_TLBIVAX:
-                       emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
+                       ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+                       emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
                        break;
 
                default:
index ff38b664195d6dcac44f1e24b6e15c6a431abd7b..cf3f180123717cb8e7439f6460c537ec24d0523b 100644 (file)
@@ -304,17 +304,13 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
        ref->flags = E500_TLB_VALID;
 
        if (tlbe_is_writable(gtlbe))
-               ref->flags |= E500_TLB_DIRTY;
+               kvm_set_pfn_dirty(pfn);
 }
 
 static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
        if (ref->flags & E500_TLB_VALID) {
-               if (ref->flags & E500_TLB_DIRTY)
-                       kvm_release_pfn_dirty(ref->pfn);
-               else
-                       kvm_release_pfn_clean(ref->pfn);
-
+               trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
                ref->flags = 0;
        }
 }
@@ -357,6 +353,13 @@ static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
        clear_tlb_privs(vcpu_e500);
 }
 
+void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+       clear_tlb_refs(vcpu_e500);
+       clear_tlb1_bitmap(vcpu_e500);
+}
+
 static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
                unsigned int eaddr, int as)
 {
@@ -412,7 +415,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
        struct tlbe_ref *ref)
 {
        struct kvm_memory_slot *slot;
-       unsigned long pfn, hva;
+       unsigned long pfn = 0; /* silence GCC warning */
+       unsigned long hva;
        int pfnmap = 0;
        int tsize = BOOK3E_PAGESZ_4K;
 
@@ -521,7 +525,7 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
        if (likely(!pfnmap)) {
                unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
                pfn = gfn_to_pfn_memslot(slot, gfn);
-               if (is_error_pfn(pfn)) {
+               if (is_error_noslot_pfn(pfn)) {
                        printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
                                        (long)gfn);
                        return;
@@ -541,6 +545,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
        /* Clear i-cache for new pages */
        kvmppc_mmu_flush_icache(pfn);
+
+       /* Drop refcount on page, so that mmu notifiers can clear it */
+       kvm_release_pfn_clean(pfn);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
@@ -682,14 +689,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
        return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        unsigned int ia;
        int esel, tlbsel;
-       gva_t ea;
-
-       ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
 
        ia = (ea >> 2) & 0x1;
 
@@ -716,7 +720,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 }
 
 static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
-                      int pid, int rt)
+                      int pid, int type)
 {
        struct kvm_book3e_206_tlb_entry *tlbe;
        int tid, esel;
@@ -725,7 +729,7 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
        for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
                tlbe = get_entry(vcpu_e500, tlbsel, esel);
                tid = get_tlb_tid(tlbe);
-               if (rt == 0 || tid == pid) {
+               if (type == 0 || tid == pid) {
                        inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
                }
@@ -733,14 +737,9 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 }
 
 static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
-                      int ra, int rb)
+                      gva_t ea)
 {
        int tlbsel, esel;
-       gva_t ea;
-
-       ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
-       if (ra)
-               ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);
 
        for (tlbsel = 0; tlbsel < 2; tlbsel++) {
                esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
@@ -752,16 +751,16 @@ static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
        }
 }
 
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int pid = get_cur_spid(vcpu);
 
-       if (rt == 0 || rt == 1) {
-               tlbilx_all(vcpu_e500, 0, pid, rt);
-               tlbilx_all(vcpu_e500, 1, pid, rt);
-       } else if (rt == 3) {
-               tlbilx_one(vcpu_e500, pid, ra, rb);
+       if (type == 0 || type == 1) {
+               tlbilx_all(vcpu_e500, 0, pid, type);
+               tlbilx_all(vcpu_e500, 1, pid, type);
+       } else if (type == 3) {
+               tlbilx_one(vcpu_e500, pid, ea);
        }
 
        return EMULATE_DONE;
@@ -786,16 +785,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int as = !!get_cur_sas(vcpu);
        unsigned int pid = get_cur_spid(vcpu);
        int esel, tlbsel;
        struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
-       gva_t ea;
-
-       ea = kvmppc_get_gpr(vcpu, rb);
 
        for (tlbsel = 0; tlbsel < 2; tlbsel++) {
                esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
@@ -875,6 +871,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 
        gtlbe->mas1 = vcpu->arch.shared->mas1;
        gtlbe->mas2 = vcpu->arch.shared->mas2;
+       if (!(vcpu->arch.shared->msr & MSR_CM))
+               gtlbe->mas2 &= 0xffffffffUL;
        gtlbe->mas7_3 = vcpu->arch.shared->mas7_3;
 
        trace_kvm_booke206_gtlb_write(vcpu->arch.shared->mas0, gtlbe->mas1,
@@ -1039,8 +1037,12 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
                sesel = 0; /* unused */
                priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
-               kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
-                                       &priv->ref, eaddr, &stlbe);
+               /* Only triggers after clear_tlb_refs */
+               if (unlikely(!(priv->ref.flags & E500_TLB_VALID)))
+                       kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+               else
+                       kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
+                                               &priv->ref, eaddr, &stlbe);
                break;
 
        case 1: {
@@ -1060,6 +1062,49 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
        write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
 }
 
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       trace_kvm_unmap_hva(hva);
+
+       /*
+        * Flush all shadow tlb entries everywhere. This is slow, but
+        * we are 100% sure that we catch the to be unmapped page
+        */
+       kvm_flush_remote_tlbs(kvm);
+
+       return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+       /* kvm_unmap_hva flushes everything anyways */
+       kvm_unmap_hva(kvm, start);
+
+       return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       /* XXX could be more clever ;) */
+       return 0;
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+       /* The page will get remapped properly on its next fault */
+       kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
        int i;
@@ -1081,6 +1126,8 @@ static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
                }
 
                vcpu_e500->num_shared_tlb_pages = 0;
+
+               kfree(vcpu_e500->shared_tlb_pages);
                vcpu_e500->shared_tlb_pages = NULL;
        } else {
                kfree(vcpu_e500->gtlb_arch);
@@ -1178,21 +1225,27 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
        }
 
        virt = vmap(pages, num_pages, VM_MAP, PAGE_KERNEL);
-       if (!virt)
+       if (!virt) {
+               ret = -ENOMEM;
                goto err_put_page;
+       }
 
        privs[0] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[0],
                           GFP_KERNEL);
        privs[1] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[1],
                           GFP_KERNEL);
 
-       if (!privs[0] || !privs[1])
-               goto err_put_page;
+       if (!privs[0] || !privs[1]) {
+               ret = -ENOMEM;
+               goto err_privs;
+       }
 
        g2h_bitmap = kzalloc(sizeof(u64) * params.tlb_sizes[1],
                             GFP_KERNEL);
-       if (!g2h_bitmap)
-               goto err_put_page;
+       if (!g2h_bitmap) {
+               ret = -ENOMEM;
+               goto err_privs;
+       }
 
        free_gtlb(vcpu_e500);
 
@@ -1232,10 +1285,11 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
        kvmppc_recalc_tlb1map_range(vcpu_e500);
        return 0;
 
-err_put_page:
+err_privs:
        kfree(privs[0]);
        kfree(privs[1]);
 
+err_put_page:
        for (i = 0; i < num_pages; i++)
                put_page(pages[i]);
 
@@ -1332,7 +1386,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
        if (!vcpu_e500->gtlb_priv[1])
                goto err;
 
-       vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) *
+       vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) *
                                          vcpu_e500->gtlb_params[1].entries,
                                          GFP_KERNEL);
        if (!vcpu_e500->g2h_tlb1_map)
index ee04abaefe233c89e692a9e1a84e4686d4da8030..b0855e5d8905ee50e6422ca9edfc37aa952f6b21 100644 (file)
@@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
        return vcpu->arch.dec - jd;
 }
 
+static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+       enum emulation_result emulated = EMULATE_DONE;
+       ulong spr_val = kvmppc_get_gpr(vcpu, rs);
+
+       switch (sprn) {
+       case SPRN_SRR0:
+               vcpu->arch.shared->srr0 = spr_val;
+               break;
+       case SPRN_SRR1:
+               vcpu->arch.shared->srr1 = spr_val;
+               break;
+
+       /* XXX We need to context-switch the timebase for
+        * watchdog and FIT. */
+       case SPRN_TBWL: break;
+       case SPRN_TBWU: break;
+
+       case SPRN_MSSSR0: break;
+
+       case SPRN_DEC:
+               vcpu->arch.dec = spr_val;
+               kvmppc_emulate_dec(vcpu);
+               break;
+
+       case SPRN_SPRG0:
+               vcpu->arch.shared->sprg0 = spr_val;
+               break;
+       case SPRN_SPRG1:
+               vcpu->arch.shared->sprg1 = spr_val;
+               break;
+       case SPRN_SPRG2:
+               vcpu->arch.shared->sprg2 = spr_val;
+               break;
+       case SPRN_SPRG3:
+               vcpu->arch.shared->sprg3 = spr_val;
+               break;
+
+       default:
+               emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
+                                                    spr_val);
+               if (emulated == EMULATE_FAIL)
+                       printk(KERN_INFO "mtspr: unknown spr "
+                               "0x%x\n", sprn);
+               break;
+       }
+
+       kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+
+       return emulated;
+}
+
+static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+       enum emulation_result emulated = EMULATE_DONE;
+       ulong spr_val = 0;
+
+       switch (sprn) {
+       case SPRN_SRR0:
+               spr_val = vcpu->arch.shared->srr0;
+               break;
+       case SPRN_SRR1:
+               spr_val = vcpu->arch.shared->srr1;
+               break;
+       case SPRN_PVR:
+               spr_val = vcpu->arch.pvr;
+               break;
+       case SPRN_PIR:
+               spr_val = vcpu->vcpu_id;
+               break;
+       case SPRN_MSSSR0:
+               spr_val = 0;
+               break;
+
+       /* Note: mftb and TBRL/TBWL are user-accessible, so
+        * the guest can always access the real TB anyways.
+        * In fact, we probably will never see these traps. */
+       case SPRN_TBWL:
+               spr_val = get_tb() >> 32;
+               break;
+       case SPRN_TBWU:
+               spr_val = get_tb();
+               break;
+
+       case SPRN_SPRG0:
+               spr_val = vcpu->arch.shared->sprg0;
+               break;
+       case SPRN_SPRG1:
+               spr_val = vcpu->arch.shared->sprg1;
+               break;
+       case SPRN_SPRG2:
+               spr_val = vcpu->arch.shared->sprg2;
+               break;
+       case SPRN_SPRG3:
+               spr_val = vcpu->arch.shared->sprg3;
+               break;
+       /* Note: SPRG4-7 are user-readable, so we don't get
+        * a trap. */
+
+       case SPRN_DEC:
+               spr_val = kvmppc_get_dec(vcpu, get_tb());
+               break;
+       default:
+               emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
+                                                    &spr_val);
+               if (unlikely(emulated == EMULATE_FAIL)) {
+                       printk(KERN_INFO "mfspr: unknown spr "
+                               "0x%x\n", sprn);
+               }
+               break;
+       }
+
+       if (emulated == EMULATE_DONE)
+               kvmppc_set_gpr(vcpu, rt, spr_val);
+       kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+
+       return emulated;
+}
+
 /* XXX to do:
  * lhax
  * lhaux
@@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
        int sprn = get_sprn(inst);
        enum emulation_result emulated = EMULATE_DONE;
        int advance = 1;
-       ulong spr_val = 0;
 
        /* this default type might be overwritten by subcategories */
        kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        break;
 
                case OP_31_XOP_MFSPR:
-                       switch (sprn) {
-                       case SPRN_SRR0:
-                               spr_val = vcpu->arch.shared->srr0;
-                               break;
-                       case SPRN_SRR1:
-                               spr_val = vcpu->arch.shared->srr1;
-                               break;
-                       case SPRN_PVR:
-                               spr_val = vcpu->arch.pvr;
-                               break;
-                       case SPRN_PIR:
-                               spr_val = vcpu->vcpu_id;
-                               break;
-                       case SPRN_MSSSR0:
-                               spr_val = 0;
-                               break;
-
-                       /* Note: mftb and TBRL/TBWL are user-accessible, so
-                        * the guest can always access the real TB anyways.
-                        * In fact, we probably will never see these traps. */
-                       case SPRN_TBWL:
-                               spr_val = get_tb() >> 32;
-                               break;
-                       case SPRN_TBWU:
-                               spr_val = get_tb();
-                               break;
-
-                       case SPRN_SPRG0:
-                               spr_val = vcpu->arch.shared->sprg0;
-                               break;
-                       case SPRN_SPRG1:
-                               spr_val = vcpu->arch.shared->sprg1;
-                               break;
-                       case SPRN_SPRG2:
-                               spr_val = vcpu->arch.shared->sprg2;
-                               break;
-                       case SPRN_SPRG3:
-                               spr_val = vcpu->arch.shared->sprg3;
-                               break;
-                       /* Note: SPRG4-7 are user-readable, so we don't get
-                        * a trap. */
-
-                       case SPRN_DEC:
-                               spr_val = kvmppc_get_dec(vcpu, get_tb());
-                               break;
-                       default:
-                               emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
-                                                                    &spr_val);
-                               if (unlikely(emulated == EMULATE_FAIL)) {
-                                       printk(KERN_INFO "mfspr: unknown spr "
-                                               "0x%x\n", sprn);
-                               }
-                               break;
-                       }
-                       kvmppc_set_gpr(vcpu, rt, spr_val);
-                       kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+                       emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
                        break;
 
                case OP_31_XOP_STHX:
@@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        break;
 
                case OP_31_XOP_MTSPR:
-                       spr_val = kvmppc_get_gpr(vcpu, rs);
-                       switch (sprn) {
-                       case SPRN_SRR0:
-                               vcpu->arch.shared->srr0 = spr_val;
-                               break;
-                       case SPRN_SRR1:
-                               vcpu->arch.shared->srr1 = spr_val;
-                               break;
-
-                       /* XXX We need to context-switch the timebase for
-                        * watchdog and FIT. */
-                       case SPRN_TBWL: break;
-                       case SPRN_TBWU: break;
-
-                       case SPRN_MSSSR0: break;
-
-                       case SPRN_DEC:
-                               vcpu->arch.dec = spr_val;
-                               kvmppc_emulate_dec(vcpu);
-                               break;
-
-                       case SPRN_SPRG0:
-                               vcpu->arch.shared->sprg0 = spr_val;
-                               break;
-                       case SPRN_SPRG1:
-                               vcpu->arch.shared->sprg1 = spr_val;
-                               break;
-                       case SPRN_SPRG2:
-                               vcpu->arch.shared->sprg2 = spr_val;
-                               break;
-                       case SPRN_SPRG3:
-                               vcpu->arch.shared->sprg3 = spr_val;
-                               break;
-
-                       default:
-                               emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
-                                                                    spr_val);
-                               if (emulated == EMULATE_FAIL)
-                                       printk(KERN_INFO "mtspr: unknown spr "
-                                               "0x%x\n", sprn);
-                               break;
-                       }
-                       kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+                       emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
                        break;
 
                case OP_31_XOP_DCBI:
index 4d213b8b0fb55eeb1eff3ae1ab591ab91d00dba9..70739a08956044b875d4c98cbbeec27d74643c75 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
 #include <asm/cputhreads.h>
+#include <asm/irqflags.h>
 #include "timing.h"
 #include "../mm/mmu_decl.h"
 
@@ -38,8 +39,7 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-       return !(v->arch.shared->msr & MSR_WE) ||
-              !!(v->arch.pending_exceptions) ||
+       return !!(v->arch.pending_exceptions) ||
               v->requests;
 }
 
@@ -48,6 +48,85 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+#ifndef CONFIG_KVM_BOOK3S_64_HV
+/*
+ * Common checks before entering the guest world.  Call with interrupts
+ * disabled.
+ *
+ * returns:
+ *
+ * == 1 if we're ready to go into guest state
+ * <= 0 if we need to go back to the host with return value
+ */
+int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+{
+       int r = 1;
+
+       WARN_ON_ONCE(!irqs_disabled());
+       while (true) {
+               if (need_resched()) {
+                       local_irq_enable();
+                       cond_resched();
+                       local_irq_disable();
+                       continue;
+               }
+
+               if (signal_pending(current)) {
+                       kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+                       vcpu->run->exit_reason = KVM_EXIT_INTR;
+                       r = -EINTR;
+                       break;
+               }
+
+               vcpu->mode = IN_GUEST_MODE;
+
+               /*
+                * Reading vcpu->requests must happen after setting vcpu->mode,
+                * so we don't miss a request because the requester sees
+                * OUTSIDE_GUEST_MODE and assumes we'll be checking requests
+                * before next entering the guest (and thus doesn't IPI).
+                */
+               smp_mb();
+
+               if (vcpu->requests) {
+                       /* Make sure we process requests preemptable */
+                       local_irq_enable();
+                       trace_kvm_check_requests(vcpu);
+                       r = kvmppc_core_check_requests(vcpu);
+                       local_irq_disable();
+                       if (r > 0)
+                               continue;
+                       break;
+               }
+
+               if (kvmppc_core_prepare_to_enter(vcpu)) {
+                       /* interrupts got enabled in between, so we
+                          are back at square 1 */
+                       continue;
+               }
+
+#ifdef CONFIG_PPC64
+               /* lazy EE magic */
+               hard_irq_disable();
+               if (lazy_irq_pending()) {
+                       /* Got an interrupt in between, try again */
+                       local_irq_enable();
+                       local_irq_disable();
+                       kvm_guest_exit();
+                       continue;
+               }
+
+               trace_hardirqs_on();
+#endif
+
+               kvm_guest_enter();
+               break;
+       }
+
+       return r;
+}
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
        int nr = kvmppc_get_gpr(vcpu, 11);
@@ -67,18 +146,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
        }
 
        switch (nr) {
-       case HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE:
+       case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
        {
                vcpu->arch.magic_page_pa = param1;
                vcpu->arch.magic_page_ea = param2;
 
                r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
-               r = HC_EV_SUCCESS;
+               r = EV_SUCCESS;
                break;
        }
-       case HC_VENDOR_KVM | KVM_HC_FEATURES:
-               r = HC_EV_SUCCESS;
+       case KVM_HCALL_TOKEN(KVM_HC_FEATURES):
+               r = EV_SUCCESS;
 #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2)
                /* XXX Missing magic page on 44x */
                r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
@@ -86,8 +165,13 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 
                /* Second return value is in r4 */
                break;
+       case EV_HCALL_TOKEN(EV_IDLE):
+               r = EV_SUCCESS;
+               kvm_vcpu_block(vcpu);
+               clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+               break;
        default:
-               r = HC_EV_UNIMPLEMENTED;
+               r = EV_UNIMPLEMENTED;
                break;
        }
 
@@ -220,6 +304,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        switch (ext) {
 #ifdef CONFIG_BOOKE
        case KVM_CAP_PPC_BOOKE_SREGS:
+       case KVM_CAP_PPC_BOOKE_WATCHDOG:
 #else
        case KVM_CAP_PPC_SEGSTATE:
        case KVM_CAP_PPC_HIOR:
@@ -229,6 +314,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_PPC_IRQ_LEVEL:
        case KVM_CAP_ENABLE_CAP:
        case KVM_CAP_ONE_REG:
+       case KVM_CAP_IOEVENTFD:
                r = 1;
                break;
 #ifndef CONFIG_KVM_BOOK3S_64_HV
@@ -260,10 +346,22 @@ int kvm_dev_ioctl_check_extension(long ext)
                if (cpu_has_feature(CPU_FTR_ARCH_201))
                        r = 2;
                break;
+#endif
        case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_BOOK3S_64_HV
                r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+#elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
+               r = 1;
+#else
+               r = 0;
+               break;
+#endif
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+       case KVM_CAP_PPC_HTAB_FD:
+               r = 1;
                break;
 #endif
+               break;
        case KVM_CAP_NR_VCPUS:
                /*
                 * Recommending a number of CPUs is somewhat arbitrary; we
@@ -302,19 +400,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
                           struct kvm_memory_slot *dont)
 {
-       if (!dont || free->arch.rmap != dont->arch.rmap) {
-               vfree(free->arch.rmap);
-               free->arch.rmap = NULL;
-       }
+       kvmppc_core_free_memslot(free, dont);
 }
 
 int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 {
-       slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
-       if (!slot->arch.rmap)
-               return -ENOMEM;
-
-       return 0;
+       return kvmppc_core_create_memslot(slot, npages);
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -323,7 +414,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_userspace_memory_region *mem,
                                    int user_alloc)
 {
-       return kvmppc_core_prepare_memory_region(kvm, mem);
+       return kvmppc_core_prepare_memory_region(kvm, memslot, mem);
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
@@ -331,7 +422,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                struct kvm_memory_slot old,
                int user_alloc)
 {
-       kvmppc_core_commit_memory_region(kvm, mem);
+       kvmppc_core_commit_memory_region(kvm, mem, old);
 }
 
 void kvm_arch_flush_shadow_all(struct kvm *kvm)
@@ -341,6 +432,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
 void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
                                   struct kvm_memory_slot *slot)
 {
+       kvmppc_core_flush_memslot(kvm, slot);
 }
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
@@ -354,6 +446,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
        return vcpu;
 }
 
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
        /* Make sure we're not using the vcpu anymore */
@@ -390,6 +487,8 @@ enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+       int ret;
+
        hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
        tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
        vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
@@ -398,13 +497,14 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_KVM_EXIT_TIMING
        mutex_init(&vcpu->arch.exit_timing_lock);
 #endif
-
-       return 0;
+       ret = kvmppc_subarch_vcpu_init(vcpu);
+       return ret;
 }
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
        kvmppc_mmu_destroy(vcpu);
+       kvmppc_subarch_vcpu_uninit(vcpu);
 }
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -420,7 +520,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        mtspr(SPRN_VRSAVE, vcpu->arch.vrsave);
 #endif
        kvmppc_core_vcpu_load(vcpu, cpu);
-       vcpu->cpu = smp_processor_id();
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -429,7 +528,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_BOOKE
        vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
 #endif
-       vcpu->cpu = -1;
 }
 
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
@@ -527,6 +625,13 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
        vcpu->mmio_is_write = 0;
        vcpu->arch.mmio_sign_extend = 0;
 
+       if (!kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+                            bytes, &run->mmio.data)) {
+               kvmppc_complete_mmio_load(vcpu, run);
+               vcpu->mmio_needed = 0;
+               return EMULATE_DONE;
+       }
+
        return EMULATE_DO_MMIO;
 }
 
@@ -536,8 +641,8 @@ int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
 {
        int r;
 
-       r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian);
        vcpu->arch.mmio_sign_extend = 1;
+       r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian);
 
        return r;
 }
@@ -575,6 +680,13 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
                }
        }
 
+       if (!kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+                             bytes, &run->mmio.data)) {
+               kvmppc_complete_mmio_load(vcpu, run);
+               vcpu->mmio_needed = 0;
+               return EMULATE_DONE;
+       }
+
        return EMULATE_DO_MMIO;
 }
 
@@ -649,6 +761,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
                r = 0;
                vcpu->arch.papr_enabled = true;
                break;
+#ifdef CONFIG_BOOKE
+       case KVM_CAP_PPC_BOOKE_WATCHDOG:
+               r = 0;
+               vcpu->arch.watchdog_enabled = true;
+               break;
+#endif
 #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
        case KVM_CAP_SW_TLB: {
                struct kvm_config_tlb cfg;
@@ -751,9 +869,16 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
 
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
+       u32 inst_nop = 0x60000000;
+#ifdef CONFIG_KVM_BOOKE_HV
+       u32 inst_sc1 = 0x44000022;
+       pvinfo->hcall[0] = inst_sc1;
+       pvinfo->hcall[1] = inst_nop;
+       pvinfo->hcall[2] = inst_nop;
+       pvinfo->hcall[3] = inst_nop;
+#else
        u32 inst_lis = 0x3c000000;
        u32 inst_ori = 0x60000000;
-       u32 inst_nop = 0x60000000;
        u32 inst_sc = 0x44000002;
        u32 inst_imm_mask = 0xffff;
 
@@ -770,6 +895,9 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
        pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask);
        pvinfo->hcall[2] = inst_sc;
        pvinfo->hcall[3] = inst_nop;
+#endif
+
+       pvinfo->flags = KVM_PPC_PVINFO_FLAGS_EV_IDLE;
 
        return 0;
 }
@@ -832,6 +960,17 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = 0;
                break;
        }
+
+       case KVM_PPC_GET_HTAB_FD: {
+               struct kvm *kvm = filp->private_data;
+               struct kvm_get_htab_fd ghf;
+
+               r = -EFAULT;
+               if (copy_from_user(&ghf, argp, sizeof(ghf)))
+                       break;
+               r = kvm_vm_ioctl_get_htab_fd(kvm, &ghf);
+               break;
+       }
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 
 #ifdef CONFIG_PPC_BOOK3S_64
index ddb6a2149d4460c067da161de4672f3cbaf4a97a..e326489a54205b30bc8c111c442ca19ab6d5c831 100644 (file)
@@ -31,6 +31,126 @@ TRACE_EVENT(kvm_ppc_instr,
                  __entry->inst, __entry->pc, __entry->emulate)
 );
 
+#ifdef CONFIG_PPC_BOOK3S
+#define kvm_trace_symbol_exit \
+       {0x100, "SYSTEM_RESET"}, \
+       {0x200, "MACHINE_CHECK"}, \
+       {0x300, "DATA_STORAGE"}, \
+       {0x380, "DATA_SEGMENT"}, \
+       {0x400, "INST_STORAGE"}, \
+       {0x480, "INST_SEGMENT"}, \
+       {0x500, "EXTERNAL"}, \
+       {0x501, "EXTERNAL_LEVEL"}, \
+       {0x502, "EXTERNAL_HV"}, \
+       {0x600, "ALIGNMENT"}, \
+       {0x700, "PROGRAM"}, \
+       {0x800, "FP_UNAVAIL"}, \
+       {0x900, "DECREMENTER"}, \
+       {0x980, "HV_DECREMENTER"}, \
+       {0xc00, "SYSCALL"}, \
+       {0xd00, "TRACE"}, \
+       {0xe00, "H_DATA_STORAGE"}, \
+       {0xe20, "H_INST_STORAGE"}, \
+       {0xe40, "H_EMUL_ASSIST"}, \
+       {0xf00, "PERFMON"}, \
+       {0xf20, "ALTIVEC"}, \
+       {0xf40, "VSX"}
+#else
+#define kvm_trace_symbol_exit \
+       {0, "CRITICAL"}, \
+       {1, "MACHINE_CHECK"}, \
+       {2, "DATA_STORAGE"}, \
+       {3, "INST_STORAGE"}, \
+       {4, "EXTERNAL"}, \
+       {5, "ALIGNMENT"}, \
+       {6, "PROGRAM"}, \
+       {7, "FP_UNAVAIL"}, \
+       {8, "SYSCALL"}, \
+       {9, "AP_UNAVAIL"}, \
+       {10, "DECREMENTER"}, \
+       {11, "FIT"}, \
+       {12, "WATCHDOG"}, \
+       {13, "DTLB_MISS"}, \
+       {14, "ITLB_MISS"}, \
+       {15, "DEBUG"}, \
+       {32, "SPE_UNAVAIL"}, \
+       {33, "SPE_FP_DATA"}, \
+       {34, "SPE_FP_ROUND"}, \
+       {35, "PERFORMANCE_MONITOR"}, \
+       {36, "DOORBELL"}, \
+       {37, "DOORBELL_CRITICAL"}, \
+       {38, "GUEST_DBELL"}, \
+       {39, "GUEST_DBELL_CRIT"}, \
+       {40, "HV_SYSCALL"}, \
+       {41, "HV_PRIV"}
+#endif
+
+TRACE_EVENT(kvm_exit,
+       TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
+       TP_ARGS(exit_nr, vcpu),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   exit_nr         )
+               __field(        unsigned long,  pc              )
+               __field(        unsigned long,  msr             )
+               __field(        unsigned long,  dar             )
+#ifdef CONFIG_KVM_BOOK3S_PR
+               __field(        unsigned long,  srr1            )
+#endif
+               __field(        unsigned long,  last_inst       )
+       ),
+
+       TP_fast_assign(
+#ifdef CONFIG_KVM_BOOK3S_PR
+               struct kvmppc_book3s_shadow_vcpu *svcpu;
+#endif
+               __entry->exit_nr        = exit_nr;
+               __entry->pc             = kvmppc_get_pc(vcpu);
+               __entry->dar            = kvmppc_get_fault_dar(vcpu);
+               __entry->msr            = vcpu->arch.shared->msr;
+#ifdef CONFIG_KVM_BOOK3S_PR
+               svcpu = svcpu_get(vcpu);
+               __entry->srr1           = svcpu->shadow_srr1;
+               svcpu_put(svcpu);
+#endif
+               __entry->last_inst      = vcpu->arch.last_inst;
+       ),
+
+       TP_printk("exit=%s"
+               " | pc=0x%lx"
+               " | msr=0x%lx"
+               " | dar=0x%lx"
+#ifdef CONFIG_KVM_BOOK3S_PR
+               " | srr1=0x%lx"
+#endif
+               " | last_inst=0x%lx"
+               ,
+               __print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit),
+               __entry->pc,
+               __entry->msr,
+               __entry->dar,
+#ifdef CONFIG_KVM_BOOK3S_PR
+               __entry->srr1,
+#endif
+               __entry->last_inst
+               )
+);
+
+TRACE_EVENT(kvm_unmap_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("unmap hva 0x%lx\n", __entry->hva)
+);
+
 TRACE_EVENT(kvm_stlb_inval,
        TP_PROTO(unsigned int stlb_index),
        TP_ARGS(stlb_index),
@@ -98,41 +218,31 @@ TRACE_EVENT(kvm_gtlb_write,
                __entry->word1, __entry->word2)
 );
 
-
-/*************************************************************************
- *                         Book3S trace points                           *
- *************************************************************************/
-
-#ifdef CONFIG_KVM_BOOK3S_PR
-
-TRACE_EVENT(kvm_book3s_exit,
-       TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
-       TP_ARGS(exit_nr, vcpu),
+TRACE_EVENT(kvm_check_requests,
+       TP_PROTO(struct kvm_vcpu *vcpu),
+       TP_ARGS(vcpu),
 
        TP_STRUCT__entry(
-               __field(        unsigned int,   exit_nr         )
-               __field(        unsigned long,  pc              )
-               __field(        unsigned long,  msr             )
-               __field(        unsigned long,  dar             )
-               __field(        unsigned long,  srr1            )
+               __field(        __u32,  cpu_nr          )
+               __field(        __u32,  requests        )
        ),
 
        TP_fast_assign(
-               struct kvmppc_book3s_shadow_vcpu *svcpu;
-               __entry->exit_nr        = exit_nr;
-               __entry->pc             = kvmppc_get_pc(vcpu);
-               __entry->dar            = kvmppc_get_fault_dar(vcpu);
-               __entry->msr            = vcpu->arch.shared->msr;
-               svcpu = svcpu_get(vcpu);
-               __entry->srr1           = svcpu->shadow_srr1;
-               svcpu_put(svcpu);
+               __entry->cpu_nr         = vcpu->vcpu_id;
+               __entry->requests       = vcpu->requests;
        ),
 
-       TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx",
-                 __entry->exit_nr, __entry->pc, __entry->msr, __entry->dar,
-                 __entry->srr1)
+       TP_printk("vcpu=%x requests=%x",
+               __entry->cpu_nr, __entry->requests)
 );
 
+
+/*************************************************************************
+ *                         Book3S trace points                           *
+ *************************************************************************/
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+
 TRACE_EVENT(kvm_book3s_reenter,
        TP_PROTO(int r, struct kvm_vcpu *vcpu),
        TP_ARGS(r, vcpu),
@@ -395,6 +505,44 @@ TRACE_EVENT(kvm_booke206_gtlb_write,
                __entry->mas2, __entry->mas7_3)
 );
 
+TRACE_EVENT(kvm_booke206_ref_release,
+       TP_PROTO(__u64 pfn, __u32 flags),
+       TP_ARGS(pfn, flags),
+
+       TP_STRUCT__entry(
+               __field(        __u64,  pfn             )
+               __field(        __u32,  flags           )
+       ),
+
+       TP_fast_assign(
+               __entry->pfn            = pfn;
+               __entry->flags          = flags;
+       ),
+
+       TP_printk("pfn=%llx flags=%x",
+               __entry->pfn, __entry->flags)
+);
+
+TRACE_EVENT(kvm_booke_queue_irqprio,
+       TP_PROTO(struct kvm_vcpu *vcpu, unsigned int priority),
+       TP_ARGS(vcpu, priority),
+
+       TP_STRUCT__entry(
+               __field(        __u32,  cpu_nr          )
+               __field(        __u32,  priority                )
+               __field(        unsigned long,  pending         )
+       ),
+
+       TP_fast_assign(
+               __entry->cpu_nr         = vcpu->vcpu_id;
+               __entry->priority       = priority;
+               __entry->pending        = vcpu->arch.pending_exceptions;
+       ),
+
+       TP_printk("vcpu=%x prio=%x pending=%lx",
+               __entry->cpu_nr, __entry->priority, __entry->pending)
+);
+
 #endif
 
 #endif /* _TRACE_KVM_H */
index 0a6b28336eb0791354c1dc4439ddddcc4e2b35d7..3a8489a354e94d16cb6d0ad6f165fbc1870f53c1 100644 (file)
@@ -113,19 +113,6 @@ static int store_updates_sp(struct pt_regs *regs)
 #define MM_FAULT_CONTINUE      -1
 #define MM_FAULT_ERR(sig)      (sig)
 
-static int out_of_memory(struct pt_regs *regs)
-{
-       /*
-        * We ran out of memory, or some other thing happened to us that made
-        * us unable to handle the page fault gracefully.
-        */
-       up_read(&current->mm->mmap_sem);
-       if (!user_mode(regs))
-               return MM_FAULT_ERR(SIGKILL);
-       pagefault_out_of_memory();
-       return MM_FAULT_RETURN;
-}
-
 static int do_sigbus(struct pt_regs *regs, unsigned long address)
 {
        siginfo_t info;
@@ -169,8 +156,18 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
                return MM_FAULT_CONTINUE;
 
        /* Out of memory */
-       if (fault & VM_FAULT_OOM)
-               return out_of_memory(regs);
+       if (fault & VM_FAULT_OOM) {
+               up_read(&current->mm->mmap_sem);
+
+               /*
+                * We ran out of memory, or some other thing happened to us that
+                * made us unable to handle the page fault gracefully.
+                */
+               if (!user_mode(regs))
+                       return MM_FAULT_ERR(SIGKILL);
+               pagefault_out_of_memory();
+               return MM_FAULT_RETURN;
+       }
 
        /* Bus error. x86 handles HWPOISON here, we'll add this if/when
         * we support the feature in HW
index 5829d2a950d48e4150b9c51510835c983a8854ad..cf9dada734b65ca2506444c6b00ea46b13b0314e 100644 (file)
@@ -722,7 +722,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 }
 
 /*
- * is_hugepage_only_range() is used by generic code to verify wether
+ * is_hugepage_only_range() is used by generic code to verify whether
  * a normal mmap mapping (non hugetlbfs) is valid on a given area.
  *
  * until the generic code provides a more generic hook and/or starts
index 028470b95886d0085a21416b4c64e6e179e4ec8b..a51cb07bd663debc0b9f9fb17211e0a57cbed1f1 100644 (file)
@@ -526,7 +526,7 @@ EXPORT_SYMBOL(mpc52xx_gpt_timer_period);
 
 #define WDT_IDENTITY       "mpc52xx watchdog on GPT0"
 
-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
+/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
 static unsigned long wdt_is_active;
 
 /* wdt-capable gpt */
index e7a896acd982798d20650bd9b0bd9df9aa202bff..48a920d514892b2e238a9bcfc60050cb25f95f00 100644 (file)
@@ -90,6 +90,7 @@ config MPIC
 config PPC_EPAPR_HV_PIC
        bool
        default n
+       select EPAPR_PARAVIRT
 
 config MPIC_WEIRD
        bool
index dca213666747fecdc6d261f33adf5fbfbe294b05..e56bb651da1a1e4929c6047a196e6878d537581d 100644 (file)
@@ -728,7 +728,7 @@ static struct cbe_iommu * __init cell_iommu_alloc(struct device_node *np)
                 nid, np->full_name);
 
        /* XXX todo: If we can have multiple windows on the same IOMMU, which
-        * isn't the case today, we probably want here to check wether the
+        * isn't the case today, we probably want here to check whether the
         * iommu for that node is already setup.
         * However, there might be issue with getting the size right so let's
         * ignore that for now. We might want to completely get rid of the
index d8b7cc8a66cad141e4c9d58b23540427a4771167..8e299447127e108a7d0b8179fa085a8b245f8dbb 100644 (file)
@@ -148,7 +148,7 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
 
        /* Configure the source. One gross hack that was there before and
         * that I've kept around is the priority to the BE which I set to
-        * be the same as the interrupt source number. I don't know wether
+        * be the same as the interrupt source number. I don't know whether
         * that's supposed to make any kind of sense however, we'll have to
         * decide that, but for now, I'm not changing the behaviour.
         */
@@ -220,7 +220,7 @@ static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 /* For hooking up the cascace we have a problem. Our device-tree is
  * crap and we don't know on which BE iic interrupt we are hooked on at
  * least not the "standard" way. We can reconstitute it based on two
- * informations though: which BE node we are connected to and wether
+ * informations though: which BE node we are connected to and whether
  * we are connected to IOIF0 or IOIF1. Right now, we really only care
  * about the IBM cell blade and we know that its firmware gives us an
  * interrupt-map property which is pretty strange.
@@ -232,7 +232,7 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
        int imaplen, intsize, unit;
        struct device_node *iic;
 
-       /* First, we check wether we have a real "interrupts" in the device
+       /* First, we check whether we have a real "interrupts" in the device
         * tree in case the device-tree is ever fixed
         */
        struct of_irq oirq;
index c4e630576ff283666f74c37ee985cf4f1b22b105..31036b56670e6dc18e21a976e7632ccc57d78d4e 100644 (file)
@@ -529,7 +529,7 @@ static int __init pmac_pic_probe_mpic(void)
 void __init pmac_pic_init(void)
 {
        /* We configure the OF parsing based on our oldworld vs. newworld
-        * platform type and wether we were booted by BootX.
+        * platform type and whether we were booted by BootX.
         */
 #ifdef CONFIG_PPC32
        if (!pmac_newworld)
index 51ffafae561ea5a4a12da1f401c76da164811fff..63c5f04ea580177649aba38d101cb3f86b40cb35 100644 (file)
@@ -236,7 +236,6 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        u32 intr_index;
        u32 have_shift = 0;
        struct fsl_msi_cascade_data *cascade_data;
-       unsigned int ret;
 
        cascade_data = irq_get_handler_data(irq);
        msi_data = cascade_data->msi_data;
@@ -268,7 +267,9 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
        case FSL_PIC_IP_IPIC:
                msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4);
                break;
-       case FSL_PIC_IP_VMPIC:
+#ifdef CONFIG_EPAPR_PARAVIRT
+       case FSL_PIC_IP_VMPIC: {
+               unsigned int ret;
                ret = fh_vmpic_get_msir(virq_to_hw(irq), &msir_value);
                if (ret) {
                        pr_err("fsl-msi: fh_vmpic_get_msir() failed for "
@@ -277,6 +278,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
                }
                break;
        }
+#endif
+       }
 
        while (msir_value) {
                intr_index = ffs(msir_value) - 1;
@@ -508,10 +511,12 @@ static const struct of_device_id fsl_of_msi_ids[] = {
                .compatible = "fsl,ipic-msi",
                .data = &ipic_msi_feature,
        },
+#ifdef CONFIG_EPAPR_PARAVIRT
        {
                .compatible = "fsl,vmpic-msi",
                .data = &vmpic_msi_feature,
        },
+#endif
        {}
 };
 
index c449dbd1c938f749447bf04944dde0e6ca1450e1..97118dc3d2851b7a33ce46a4aec162ff1cc4bba5 100644 (file)
@@ -253,6 +253,7 @@ struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
 #endif
 
+#ifdef CONFIG_EPAPR_PARAVIRT
 /*
  * Restart the current partition
  *
@@ -278,3 +279,4 @@ void fsl_hv_halt(void)
        pr_info("hv exit\n");
        fh_partition_stop(-1);
 }
+#endif
index cc45d25487b0ae945087000d7a347fa0ee6e0852..647c3eccc3d0758f9284dcc5530c0b877c7fce2a 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_S390_HYPFS_FS)     += hypfs/
 obj-$(CONFIG_APPLDATA_BASE)    += appldata/
 obj-$(CONFIG_MATHEMU)          += math-emu/
 obj-y                          += net/
+obj-$(CONFIG_PCI)              += pci/
index 3cbb8757704ef6d2617328db099164406dfc1af3..32425af9d68d7b6379c7bba2da62cb335c8ad7be 100644 (file)
@@ -34,12 +34,6 @@ config GENERIC_BUG
 config GENERIC_BUG_RELATIVE_POINTERS
        def_bool y
 
-config NO_IOMEM
-       def_bool y
-
-config NO_DMA
-       def_bool y
-
 config ARCH_DMA_ADDR_T_64BIT
        def_bool 64BIT
 
@@ -58,6 +52,12 @@ config KEXEC
 config AUDIT_ARCH
        def_bool y
 
+config NO_IOPORT
+       def_bool y
+
+config PCI_QUIRKS
+       def_bool n
+
 config S390
        def_bool y
        select USE_GENERIC_SMP_HELPERS if SMP
@@ -171,6 +171,10 @@ config HAVE_MARCH_Z196_FEATURES
        def_bool n
        select HAVE_MARCH_Z10_FEATURES
 
+config HAVE_MARCH_ZEC12_FEATURES
+       def_bool n
+       select HAVE_MARCH_Z196_FEATURES
+
 choice
        prompt "Processor type"
        default MARCH_G5
@@ -222,6 +226,13 @@ config MARCH_Z196
          (2818 and 2817 series). The kernel will be slightly faster but will
          not work on older machines.
 
+config MARCH_ZEC12
+       bool "IBM zEC12"
+       select HAVE_MARCH_ZEC12_FEATURES if 64BIT
+       help
+         Select this to enable optimizations for IBM zEC12 (2827 series). The
+         kernel will be slightly faster but will not work on older machines.
+
 endchoice
 
 config 64BIT
@@ -426,6 +437,53 @@ config QDIO
 
          If unsure, say Y.
 
+menuconfig PCI
+       bool "PCI support"
+       default n
+       depends on 64BIT
+       select ARCH_SUPPORTS_MSI
+       select PCI_MSI
+       help
+         Enable PCI support.
+
+if PCI
+
+config PCI_NR_FUNCTIONS
+       int "Maximum number of PCI functions (1-4096)"
+       range 1 4096
+       default "64"
+       help
+         This allows you to specify the maximum number of PCI functions which
+         this kernel will support.
+
+source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+source "drivers/pci/hotplug/Kconfig"
+
+endif  # PCI
+
+config PCI_DOMAINS
+       def_bool PCI
+
+config HAS_IOMEM
+       def_bool PCI
+
+config IOMMU_HELPER
+       def_bool PCI
+
+config HAS_DMA
+       def_bool PCI
+       select HAVE_DMA_API_DEBUG
+
+config NEED_SG_DMA_LENGTH
+       def_bool PCI
+
+config HAVE_DMA_ATTRS
+       def_bool PCI
+
+config NEED_DMA_MAP_STATE
+       def_bool PCI
+
 config CHSC_SCH
        def_tristate m
        prompt "Support for CHSC subchannels"
index 49e76e8b477d43444c98e20c6ef9f4cf868e3a2f..4b8e08b56f49679b40bd4ee098bae0bb01945292 100644 (file)
@@ -41,6 +41,7 @@ cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
 cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
 cflags-$(CONFIG_MARCH_Z10) += $(call cc-option,-march=z10)
 cflags-$(CONFIG_MARCH_Z196) += $(call cc-option,-march=z196)
+cflags-$(CONFIG_MARCH_ZEC12) += $(call cc-option,-march=zEC12)
 
 #KBUILD_IMAGE is necessary for make rpm
 KBUILD_IMAGE   :=arch/s390/boot/image
index da3c1a7dcd8e4ddb7dc76f16e95a38e232ef6c5c..b4dbade8ca247c52106ecd72036983c850369431 100644 (file)
@@ -325,7 +325,8 @@ static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
                u8 *in = walk->src.virt.addr;
 
                ret = crypt_s390_km(func, param, out, in, n);
-               BUG_ON((ret < 0) || (ret != n));
+               if (ret < 0 || ret != n)
+                       return -EIO;
 
                nbytes &= AES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -457,7 +458,8 @@ static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
                u8 *in = walk->src.virt.addr;
 
                ret = crypt_s390_kmc(func, param, out, in, n);
-               BUG_ON((ret < 0) || (ret != n));
+               if (ret < 0 || ret != n)
+                       return -EIO;
 
                nbytes &= AES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -625,7 +627,8 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
        memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
        param = xts_ctx->pcc.key + offset;
        ret = crypt_s390_pcc(func, param);
-       BUG_ON(ret < 0);
+       if (ret < 0)
+               return -EIO;
 
        memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
        param = xts_ctx->key + offset;
@@ -636,7 +639,8 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
                in = walk->src.virt.addr;
 
                ret = crypt_s390_km(func, param, out, in, n);
-               BUG_ON(ret < 0 || ret != n);
+               if (ret < 0 || ret != n)
+                       return -EIO;
 
                nbytes &= AES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -769,7 +773,8 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                                crypto_inc(ctrblk + i, AES_BLOCK_SIZE);
                        }
                        ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk);
-                       BUG_ON(ret < 0 || ret != n);
+                       if (ret < 0 || ret != n)
+                               return -EIO;
                        if (n > AES_BLOCK_SIZE)
                                memcpy(ctrblk, ctrblk + n - AES_BLOCK_SIZE,
                                       AES_BLOCK_SIZE);
@@ -788,7 +793,8 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                in = walk->src.virt.addr;
                ret = crypt_s390_kmctr(func, sctx->key, buf, in,
                                       AES_BLOCK_SIZE, ctrblk);
-               BUG_ON(ret < 0 || ret != AES_BLOCK_SIZE);
+               if (ret < 0 || ret != AES_BLOCK_SIZE)
+                       return -EIO;
                memcpy(out, buf, nbytes);
                crypto_inc(ctrblk, AES_BLOCK_SIZE);
                ret = blkcipher_walk_done(desc, walk, 0);
index b49fb96f42070623a1645db10ebee3457eb0a98a..bcca01c9989daf57b963db9168d64ec09c7ee5af 100644 (file)
@@ -94,7 +94,8 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
                u8 *in = walk->src.virt.addr;
 
                ret = crypt_s390_km(func, key, out, in, n);
-               BUG_ON((ret < 0) || (ret != n));
+               if (ret < 0 || ret != n)
+                       return -EIO;
 
                nbytes &= DES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -120,7 +121,8 @@ static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
                u8 *in = walk->src.virt.addr;
 
                ret = crypt_s390_kmc(func, iv, out, in, n);
-               BUG_ON((ret < 0) || (ret != n));
+               if (ret < 0 || ret != n)
+                       return -EIO;
 
                nbytes &= DES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -386,7 +388,8 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
                                crypto_inc(ctrblk + i, DES_BLOCK_SIZE);
                        }
                        ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk);
-                       BUG_ON((ret < 0) || (ret != n));
+                       if (ret < 0 || ret != n)
+                               return -EIO;
                        if (n > DES_BLOCK_SIZE)
                                memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE,
                                       DES_BLOCK_SIZE);
@@ -404,7 +407,8 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
                in = walk->src.virt.addr;
                ret = crypt_s390_kmctr(func, ctx->key, buf, in,
                                       DES_BLOCK_SIZE, ctrblk);
-               BUG_ON(ret < 0 || ret != DES_BLOCK_SIZE);
+               if (ret < 0 || ret != DES_BLOCK_SIZE)
+                       return -EIO;
                memcpy(out, buf, nbytes);
                crypto_inc(ctrblk, DES_BLOCK_SIZE);
                ret = blkcipher_walk_done(desc, walk, 0);
index 1ebd3a15cca47d499e3d3855b3f3b1e5bad0082a..d43485d142e911623d30d5abb5bd80d957f752d4 100644 (file)
@@ -72,14 +72,16 @@ static int ghash_update(struct shash_desc *desc,
                if (!dctx->bytes) {
                        ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf,
                                              GHASH_BLOCK_SIZE);
-                       BUG_ON(ret != GHASH_BLOCK_SIZE);
+                       if (ret != GHASH_BLOCK_SIZE)
+                               return -EIO;
                }
        }
 
        n = srclen & ~(GHASH_BLOCK_SIZE - 1);
        if (n) {
                ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n);
-               BUG_ON(ret != n);
+               if (ret != n)
+                       return -EIO;
                src += n;
                srclen -= n;
        }
@@ -92,7 +94,7 @@ static int ghash_update(struct shash_desc *desc,
        return 0;
 }
 
-static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
+static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
 {
        u8 *buf = dctx->buffer;
        int ret;
@@ -103,21 +105,24 @@ static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
                memset(pos, 0, dctx->bytes);
 
                ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE);
-               BUG_ON(ret != GHASH_BLOCK_SIZE);
+               if (ret != GHASH_BLOCK_SIZE)
+                       return -EIO;
        }
 
        dctx->bytes = 0;
+       return 0;
 }
 
 static int ghash_final(struct shash_desc *desc, u8 *dst)
 {
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
        struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
+       int ret;
 
-       ghash_flush(ctx, dctx);
-       memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
-
-       return 0;
+       ret = ghash_flush(ctx, dctx);
+       if (!ret)
+               memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
+       return ret;
 }
 
 static struct shash_alg ghash_alg = {
index bd37d09b9d3c8cfacbc39f512ed8eb354d3049e0..8620b0ec9c42611f8a8093f0150e301d8241ccdd 100644 (file)
@@ -36,7 +36,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
        if (index) {
                memcpy(ctx->buf + index, data, bsize - index);
                ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize);
-               BUG_ON(ret != bsize);
+               if (ret != bsize)
+                       return -EIO;
                data += bsize - index;
                len -= bsize - index;
                index = 0;
@@ -46,7 +47,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
        if (len >= bsize) {
                ret = crypt_s390_kimd(ctx->func, ctx->state, data,
                                      len & ~(bsize - 1));
-               BUG_ON(ret != (len & ~(bsize - 1)));
+               if (ret != (len & ~(bsize - 1)))
+                       return -EIO;
                data += ret;
                len -= ret;
        }
@@ -88,7 +90,8 @@ int s390_sha_final(struct shash_desc *desc, u8 *out)
        memcpy(ctx->buf + end - 8, &bits, sizeof(bits));
 
        ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end);
-       BUG_ON(ret != end);
+       if (ret != end)
+               return -EIO;
 
        /* copy digest to out */
        memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
index 6f573890fb2853602271d2a16b0b39b792ff9cfe..15422933c60ba4b4d9ca12e2187d3154bff4656f 100644 (file)
@@ -640,6 +640,87 @@ static inline unsigned long find_first_bit(const unsigned long * addr,
 }
 #define find_first_bit find_first_bit
 
+/*
+ * Big endian variant whichs starts bit counting from left using
+ * the flogr (find leftmost one) instruction.
+ */
+static inline unsigned long __flo_word(unsigned long nr, unsigned long val)
+{
+       register unsigned long bit asm("2") = val;
+       register unsigned long out asm("3");
+
+       asm volatile (
+               "       .insn   rre,0xb9830000,%[bit],%[bit]\n"
+               : [bit] "+d" (bit), [out] "=d" (out) : : "cc");
+       return nr + bit;
+}
+
+/*
+ * 64 bit special left bitops format:
+ * order in memory:
+ *    00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+ *    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
+ *    20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+ *    30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+ * after that follows the next long with bit numbers
+ *    40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+ *    50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+ *    60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+ *    70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
+ * The reason for this bit ordering is the fact that
+ * the hardware sets bits in a bitmap starting at bit 0
+ * and we don't want to scan the bitmap from the 'wrong
+ * end'.
+ */
+static inline unsigned long find_first_bit_left(const unsigned long *addr,
+                                               unsigned long size)
+{
+       unsigned long bytes, bits;
+
+       if (!size)
+               return 0;
+       bytes = __ffs_word_loop(addr, size);
+       bits = __flo_word(bytes * 8, __load_ulong_be(addr, bytes));
+       return (bits < size) ? bits : size;
+}
+
+static inline int find_next_bit_left(const unsigned long *addr,
+                                    unsigned long size,
+                                    unsigned long offset)
+{
+       const unsigned long *p;
+       unsigned long bit, set;
+
+       if (offset >= size)
+               return size;
+       bit = offset & (__BITOPS_WORDSIZE - 1);
+       offset -= bit;
+       size -= offset;
+       p = addr + offset / __BITOPS_WORDSIZE;
+       if (bit) {
+               set = __flo_word(0, *p & (~0UL << bit));
+               if (set >= size)
+                       return size + offset;
+               if (set < __BITOPS_WORDSIZE)
+                       return set + offset;
+               offset += __BITOPS_WORDSIZE;
+               size -= __BITOPS_WORDSIZE;
+               p++;
+       }
+       return offset + find_first_bit_left(p, size);
+}
+
+#define for_each_set_bit_left(bit, addr, size)                         \
+       for ((bit) = find_first_bit_left((addr), (size));               \
+            (bit) < (size);                                            \
+            (bit) = find_next_bit_left((addr), (size), (bit) + 1))
+
+/* same as for_each_set_bit() but use bit as value to start with */
+#define for_each_set_bit_left_cont(bit, addr, size)                    \
+       for ((bit) = find_next_bit_left((addr), (size), (bit));         \
+            (bit) < (size);                                            \
+            (bit) = find_next_bit_left((addr), (size), (bit) + 1))
+
 /**
  * find_next_zero_bit - find the first zero bit in a memory region
  * @addr: The address to base the search on
index 1cb4bb3f32d92709d11cee7f96c198d2689d3a77..6d1f3573f0df020cd6f23904357f3ccedf2ecc0e 100644 (file)
@@ -18,6 +18,9 @@ struct irb;
 struct ccw1;
 struct ccw_dev_id;
 
+/* from asm/schid.h */
+struct subchannel_id;
+
 /* simplified initializers for struct ccw_device:
  * CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one
  * entry in your MODULE_DEVICE_TABLE and set the match_flag correctly */
@@ -223,8 +226,7 @@ extern int ccw_device_force_console(void);
 
 int ccw_device_siosl(struct ccw_device *);
 
-// FIXME: these have to go
-extern int _ccw_device_get_subchannel_number(struct ccw_device *);
+extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *);
 
 extern void *ccw_device_get_chp_desc(struct ccw_device *, int);
 #endif /* _S390_CCWDEV_H_ */
index 01a905eb11e036e2601580053af149ec1ef89da2..23723ce5ca7a9b0b68585eb2faa2f4cdcd6cabc9 100644 (file)
@@ -59,6 +59,9 @@ extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
 int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv,
                        int num_devices, const char *buf);
 
+extern int ccwgroup_set_online(struct ccwgroup_device *gdev);
+extern int ccwgroup_set_offline(struct ccwgroup_device *gdev);
+
 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
 
diff --git a/arch/s390/include/asm/clp.h b/arch/s390/include/asm/clp.h
new file mode 100644 (file)
index 0000000..6c3aecc
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _ASM_S390_CLP_H
+#define _ASM_S390_CLP_H
+
+/* CLP common request & response block size */
+#define CLP_BLK_SIZE                   (PAGE_SIZE * 2)
+
+struct clp_req_hdr {
+       u16 len;
+       u16 cmd;
+} __packed;
+
+struct clp_rsp_hdr {
+       u16 len;
+       u16 rsp;
+} __packed;
+
+/* CLP Response Codes */
+#define CLP_RC_OK                      0x0010  /* Command request successfully */
+#define CLP_RC_CMD                     0x0020  /* Command code not recognized */
+#define CLP_RC_PERM                    0x0030  /* Command not authorized */
+#define CLP_RC_FMT                     0x0040  /* Invalid command request format */
+#define CLP_RC_LEN                     0x0050  /* Invalid command request length */
+#define CLP_RC_8K                      0x0060  /* Command requires 8K LPCB */
+#define CLP_RC_RESNOT0                 0x0070  /* Reserved field not zero */
+#define CLP_RC_NODATA                  0x0080  /* No data available */
+#define CLP_RC_FC_UNKNOWN              0x0100  /* Function code not recognized */
+
+#endif
diff --git a/arch/s390/include/asm/dma-mapping.h b/arch/s390/include/asm/dma-mapping.h
new file mode 100644 (file)
index 0000000..8a32f7d
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef _ASM_S390_DMA_MAPPING_H
+#define _ASM_S390_DMA_MAPPING_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-debug.h>
+#include <linux/io.h>
+
+#define DMA_ERROR_CODE         (~(dma_addr_t) 0x0)
+
+extern struct dma_map_ops s390_dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+       return &s390_dma_ops;
+}
+
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                          enum dma_data_direction direction);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       if (dma_ops->dma_supported == NULL)
+               return 1;
+       return dma_ops->dma_supported(dev, mask);
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+       if (!dev->dma_mask)
+               return 0;
+       return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       if (dma_ops->mapping_error)
+               return dma_ops->mapping_error(dev, dma_addr);
+       return (dma_addr == 0UL);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+                                      dma_addr_t *dma_handle, gfp_t flag)
+{
+       struct dma_map_ops *ops = get_dma_ops(dev);
+       void *ret;
+
+       ret = ops->alloc(dev, size, dma_handle, flag, NULL);
+       debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+       return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+                                    void *cpu_addr, dma_addr_t dma_handle)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       dma_ops->free(dev, size, cpu_addr, dma_handle, NULL);
+       debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif /* _ASM_S390_DMA_MAPPING_H */
index 6fb6de4f15b0d987f377ddb3fbeabef949929ab2..de015d85e3e5f9ce7f3f308e3bb5175d7bfcd2c0 100644 (file)
@@ -1,14 +1,13 @@
-/*
- *  S390 version
- */
-
-#ifndef _ASM_DMA_H
-#define _ASM_DMA_H
+#ifndef _ASM_S390_DMA_H
+#define _ASM_S390_DMA_H
 
-#include <asm/io.h>            /* need byte IO */
+#include <asm/io.h>
 
+/*
+ * MAX_DMA_ADDRESS is ambiguous because on s390 its completely unrelated
+ * to DMA. It _is_ used for the s390 memory zone split at 2GB caused
+ * by the 31 bit heritage.
+ */
 #define MAX_DMA_ADDRESS         0x80000000
 
-#define free_dma(x)    do { } while (0)
-
-#endif /* _ASM_DMA_H */
+#endif /* _ASM_S390_DMA_H */
diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h
new file mode 100644 (file)
index 0000000..7e3d258
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _HW_IRQ_H
+#define _HW_IRQ_H
+
+#include <linux/msi.h>
+#include <linux/pci.h>
+
+static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
+{
+       return __irq_get_msi_desc(irq);
+}
+
+/* Must be called with msi map lock held */
+static inline int irq_set_msi_desc(unsigned int irq, struct msi_desc *msi)
+{
+       if (!msi)
+               return -EINVAL;
+
+       msi->irq = irq;
+       return 0;
+}
+
+#endif
index 559e921a6bbafa082df673fa9989ea44d4a23427..16c3eb164f4fe0cdb44b91eb3be271743b8beeb8 100644 (file)
@@ -9,9 +9,9 @@
 #ifndef _S390_IO_H
 #define _S390_IO_H
 
+#include <linux/kernel.h>
 #include <asm/page.h>
-
-#define IO_SPACE_LIMIT 0xffffffff
+#include <asm/pci_io.h>
 
 /*
  * Change virtual addresses to physical addresses and vv.
@@ -24,10 +24,11 @@ static inline unsigned long virt_to_phys(volatile void * address)
                 "      lra     %0,0(%1)\n"
                 "      jz      0f\n"
                 "      la      %0,0\n"
-                 "0:"
+                "0:"
                 : "=a" (real_address) : "a" (address) : "cc");
-        return real_address;
+       return real_address;
 }
+#define virt_to_phys virt_to_phys
 
 static inline void * phys_to_virt(unsigned long address)
 {
@@ -42,4 +43,50 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
  */
 #define xlate_dev_kmem_ptr(p)  p
 
+#define IO_SPACE_LIMIT 0
+
+#ifdef CONFIG_PCI
+
+#define ioremap_nocache(addr, size)    ioremap(addr, size)
+#define ioremap_wc                     ioremap_nocache
+
+/* TODO: s390 cannot support io_remap_pfn_range... */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
+       remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
+{
+       return (void __iomem *) offset;
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+}
+
+/*
+ * s390 needs a private implementation of pci_iomap since ioremap with its
+ * offset parameter isn't sufficient. That's because BAR spaces are not
+ * disjunctive on s390 so we need the bar parameter of pci_iomap to find
+ * the corresponding device and create the mapping cookie.
+ */
+#define pci_iomap pci_iomap
+#define pci_iounmap pci_iounmap
+
+#define memcpy_fromio(dst, src, count) zpci_memcpy_fromio(dst, src, count)
+#define memcpy_toio(dst, src, count)   zpci_memcpy_toio(dst, src, count)
+#define memset_io(dst, val, count)     zpci_memset_io(dst, val, count)
+
+#define __raw_readb    zpci_read_u8
+#define __raw_readw    zpci_read_u16
+#define __raw_readl    zpci_read_u32
+#define __raw_readq    zpci_read_u64
+#define __raw_writeb   zpci_write_u8
+#define __raw_writew   zpci_write_u16
+#define __raw_writel   zpci_write_u32
+#define __raw_writeq   zpci_write_u64
+
+#endif /* CONFIG_PCI */
+
+#include <asm-generic/io.h>
+
 #endif
index 6703dd986fd4cad1963a79111d5c18dd9badd658..e6972f85d2b0926e58832e955cefb538e58618e7 100644 (file)
@@ -33,6 +33,8 @@ enum interruption_class {
        IOINT_APB,
        IOINT_ADM,
        IOINT_CSC,
+       IOINT_PCI,
+       IOINT_MSI,
        NMI_NMI,
        NR_IRQS,
 };
@@ -51,4 +53,14 @@ void service_subclass_irq_unregister(void);
 void measurement_alert_subclass_register(void);
 void measurement_alert_subclass_unregister(void);
 
+#ifdef CONFIG_LOCKDEP
+#  define disable_irq_nosync_lockdep(irq)      disable_irq_nosync(irq)
+#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
+                                               disable_irq_nosync(irq)
+#  define disable_irq_lockdep(irq)             disable_irq(irq)
+#  define enable_irq_lockdep(irq)              enable_irq(irq)
+#  define enable_irq_lockdep_irqrestore(irq, flags) \
+                                               enable_irq(irq)
+#endif
+
 #endif /* _ASM_IRQ_H */
index 5ae606456b0a25fa4a84b373aaa3020fb7aec710..68d7d68300f2e81b171f633ab56b86f7d6864e41 100644 (file)
@@ -18,6 +18,7 @@
 #define CHSC_SCH_ISC 7                 /* CHSC subchannels */
 /* Adapter interrupts. */
 #define QDIO_AIRQ_ISC IO_SCH_ISC       /* I/O subchannel in qdio mode */
+#define PCI_ISC 2                      /* PCI I/O subchannels */
 #define AP_ISC 6                       /* adjunct processor (crypto) devices */
 
 /* Functions for registration of I/O interruption subclasses */
index 39faa4ac966075298ea1d6fb1843d9c85cf792a5..a86ad4084073c85b2f6307f780d07336e470db5b 100644 (file)
@@ -30,6 +30,8 @@
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
+void storage_key_init_range(unsigned long start, unsigned long end);
+
 static unsigned long pfmf(unsigned long function, unsigned long address)
 {
        asm volatile(
index 42a145c9ddd62f2c05ea20172d0ef9a8995e20ee..a6175ad0c42fa6761fb543d5175e81b0b198a81a 100644 (file)
 #ifndef __ASM_S390_PCI_H
 #define __ASM_S390_PCI_H
 
-/* S/390 systems don't have a PCI bus. This file is just here because some stupid .c code
- * includes it even if CONFIG_PCI is not set.
- */
+/* must be set before including asm-generic/pci.h */
 #define PCI_DMA_BUS_IS_PHYS (0)
+/* must be set before including pci_clp.h */
+#define PCI_BAR_COUNT  6
 
-#endif /* __ASM_S390_PCI_H */
+#include <asm-generic/pci.h>
+#include <asm-generic/pci-dma-compat.h>
+#include <asm/pci_clp.h>
 
+#define PCIBIOS_MIN_IO         0x1000
+#define PCIBIOS_MIN_MEM                0x10000000
+
+#define pcibios_assign_all_busses()    (0)
+
+void __iomem *pci_iomap(struct pci_dev *, int, unsigned long);
+void pci_iounmap(struct pci_dev *, void __iomem *);
+int pci_domain_nr(struct pci_bus *);
+int pci_proc_domain(struct pci_bus *);
+
+/* MSI arch hooks */
+#define arch_setup_msi_irqs    arch_setup_msi_irqs
+#define arch_teardown_msi_irqs arch_teardown_msi_irqs
+
+#define ZPCI_BUS_NR                    0       /* default bus number */
+#define ZPCI_DEVFN                     0       /* default device number */
+
+/* PCI Function Controls */
+#define ZPCI_FC_FN_ENABLED             0x80
+#define ZPCI_FC_ERROR                  0x40
+#define ZPCI_FC_BLOCKED                        0x20
+#define ZPCI_FC_DMA_ENABLED            0x10
+
+struct msi_map {
+       unsigned long irq;
+       struct msi_desc *msi;
+       struct hlist_node msi_chain;
+};
+
+#define ZPCI_NR_MSI_VECS       64
+#define ZPCI_MSI_MASK          (ZPCI_NR_MSI_VECS - 1)
+
+enum zpci_state {
+       ZPCI_FN_STATE_RESERVED,
+       ZPCI_FN_STATE_STANDBY,
+       ZPCI_FN_STATE_CONFIGURED,
+       ZPCI_FN_STATE_ONLINE,
+       NR_ZPCI_FN_STATES,
+};
+
+struct zpci_bar_struct {
+       u32             val;            /* bar start & 3 flag bits */
+       u8              size;           /* order 2 exponent */
+       u16             map_idx;        /* index into bar mapping array */
+};
+
+/* Private data per function */
+struct zpci_dev {
+       struct pci_dev  *pdev;
+       struct pci_bus  *bus;
+       struct list_head entry;         /* list of all zpci_devices, needed for hotplug, etc. */
+
+       enum zpci_state state;
+       u32             fid;            /* function ID, used by sclp */
+       u32             fh;             /* function handle, used by insn's */
+       u16             pchid;          /* physical channel ID */
+       u8              pfgid;          /* function group ID */
+       u16             domain;
+
+       /* IRQ stuff */
+       u64             msi_addr;       /* MSI address */
+       struct zdev_irq_map *irq_map;
+       struct msi_map *msi_map[ZPCI_NR_MSI_VECS];
+       unsigned int    aisb;           /* number of the summary bit */
+
+       /* DMA stuff */
+       unsigned long   *dma_table;
+       spinlock_t      dma_table_lock;
+       int             tlb_refresh;
+
+       spinlock_t      iommu_bitmap_lock;
+       unsigned long   *iommu_bitmap;
+       unsigned long   iommu_size;
+       unsigned long   iommu_pages;
+       unsigned int    next_bit;
+
+       struct zpci_bar_struct bars[PCI_BAR_COUNT];
+
+       u64             start_dma;      /* Start of available DMA addresses */
+       u64             end_dma;        /* End of available DMA addresses */
+       u64             dma_mask;       /* DMA address space mask */
+
+       enum pci_bus_speed max_bus_speed;
+};
+
+struct pci_hp_callback_ops {
+       int (*create_slot)      (struct zpci_dev *zdev);
+       void (*remove_slot)     (struct zpci_dev *zdev);
+};
+
+static inline bool zdev_enabled(struct zpci_dev *zdev)
+{
+       return (zdev->fh & (1UL << 31)) ? true : false;
+}
+
+/* -----------------------------------------------------------------------------
+  Prototypes
+----------------------------------------------------------------------------- */
+/* Base stuff */
+struct zpci_dev *zpci_alloc_device(void);
+int zpci_create_device(struct zpci_dev *);
+int zpci_enable_device(struct zpci_dev *);
+void zpci_stop_device(struct zpci_dev *);
+void zpci_free_device(struct zpci_dev *);
+int zpci_scan_device(struct zpci_dev *);
+int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
+int zpci_unregister_ioat(struct zpci_dev *, u8);
+
+/* CLP */
+int clp_find_pci_devices(void);
+int clp_add_pci_device(u32, u32, int);
+int clp_enable_fh(struct zpci_dev *, u8);
+int clp_disable_fh(struct zpci_dev *);
+
+/* MSI */
+struct msi_desc *__irq_get_msi_desc(unsigned int);
+int zpci_msi_set_mask_bits(struct msi_desc *, u32, u32);
+int zpci_setup_msi_irq(struct zpci_dev *, struct msi_desc *, unsigned int, int);
+void zpci_teardown_msi_irq(struct zpci_dev *, struct msi_desc *);
+int zpci_msihash_init(void);
+void zpci_msihash_exit(void);
+
+/* Error handling and recovery */
+void zpci_event_error(void *);
+void zpci_event_availability(void *);
+
+/* Helpers */
+struct zpci_dev *get_zdev(struct pci_dev *);
+struct zpci_dev *get_zdev_by_fid(u32);
+bool zpci_fid_present(u32);
+
+/* sysfs */
+int zpci_sysfs_add_device(struct device *);
+void zpci_sysfs_remove_device(struct device *);
+
+/* DMA */
+int zpci_dma_init(void);
+void zpci_dma_exit(void);
+
+/* Hotplug */
+extern struct mutex zpci_list_lock;
+extern struct list_head zpci_list;
+extern struct pci_hp_callback_ops hotplug_ops;
+extern unsigned int pci_probe;
+
+#endif
diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h
new file mode 100644 (file)
index 0000000..d31d739
--- /dev/null
@@ -0,0 +1,182 @@
+#ifndef _ASM_S390_PCI_CLP_H
+#define _ASM_S390_PCI_CLP_H
+
+#include <asm/clp.h>
+
+/*
+ * Call Logical Processor - Command Codes
+ */
+#define CLP_LIST_PCI           0x0002
+#define CLP_QUERY_PCI_FN       0x0003
+#define CLP_QUERY_PCI_FNGRP    0x0004
+#define CLP_SET_PCI_FN         0x0005
+
+/* PCI function handle list entry */
+struct clp_fh_list_entry {
+       u16 device_id;
+       u16 vendor_id;
+       u32 config_state :  1;
+       u32              : 31;
+       u32 fid;                /* PCI function id */
+       u32 fh;                 /* PCI function handle */
+} __packed;
+
+#define CLP_RC_SETPCIFN_FH     0x0101  /* Invalid PCI fn handle */
+#define CLP_RC_SETPCIFN_FHOP   0x0102  /* Fn handle not valid for op */
+#define CLP_RC_SETPCIFN_DMAAS  0x0103  /* Invalid DMA addr space */
+#define CLP_RC_SETPCIFN_RES    0x0104  /* Insufficient resources */
+#define CLP_RC_SETPCIFN_ALRDY  0x0105  /* Fn already in requested state */
+#define CLP_RC_SETPCIFN_ERR    0x0106  /* Fn in permanent error state */
+#define CLP_RC_SETPCIFN_RECPND 0x0107  /* Error recovery pending */
+#define CLP_RC_SETPCIFN_BUSY   0x0108  /* Fn busy */
+#define CLP_RC_LISTPCI_BADRT   0x010a  /* Resume token not recognized */
+#define CLP_RC_QUERYPCIFG_PFGID        0x010b  /* Unrecognized PFGID */
+
+/* request or response block header length */
+#define LIST_PCI_HDR_LEN       32
+
+/* Number of function handles fitting in response block */
+#define CLP_FH_LIST_NR_ENTRIES                         \
+       ((CLP_BLK_SIZE - 2 * LIST_PCI_HDR_LEN)          \
+               / sizeof(struct clp_fh_list_entry))
+
+#define CLP_SET_ENABLE_PCI_FN  0       /* Yes, 0 enables it */
+#define CLP_SET_DISABLE_PCI_FN 1       /* Yes, 1 disables it */
+
+#define CLP_UTIL_STR_LEN       64
+
+/* List PCI functions request */
+struct clp_req_list_pci {
+       struct clp_req_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u64 resume_token;
+       u64 reserved2;
+} __packed;
+
+/* List PCI functions response */
+struct clp_rsp_list_pci {
+       struct clp_rsp_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u64 resume_token;
+       u32 reserved2;
+       u16 max_fn;
+       u8 reserved3;
+       u8 entry_size;
+       struct clp_fh_list_entry fh_list[CLP_FH_LIST_NR_ENTRIES];
+} __packed;
+
+/* Query PCI function request */
+struct clp_req_query_pci {
+       struct clp_req_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u32 fh;                         /* function handle */
+       u32 reserved2;
+       u64 reserved3;
+} __packed;
+
+/* Query PCI function response */
+struct clp_rsp_query_pci {
+       struct clp_rsp_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u16 vfn;                        /* virtual fn number */
+       u16                     :  7;
+       u16 util_str_avail      :  1;   /* utility string available? */
+       u16 pfgid               :  8;   /* pci function group id */
+       u32 fid;                        /* pci function id */
+       u8 bar_size[PCI_BAR_COUNT];
+       u16 pchid;
+       u32 bar[PCI_BAR_COUNT];
+       u64 reserved2;
+       u64 sdma;                       /* start dma as */
+       u64 edma;                       /* end dma as */
+       u64 reserved3[6];
+       u8 util_str[CLP_UTIL_STR_LEN];  /* utility string */
+} __packed;
+
+/* Query PCI function group request */
+struct clp_req_query_pci_grp {
+       struct clp_req_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u32                     : 24;
+       u32 pfgid               :  8;   /* function group id */
+       u32 reserved2;
+       u64 reserved3;
+} __packed;
+
+/* Query PCI function group response */
+struct clp_rsp_query_pci_grp {
+       struct clp_rsp_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u16                     :  4;
+       u16 noi                 : 12;   /* number of interrupts */
+       u8 version;
+       u8                      :  6;
+       u8 frame                :  1;
+       u8 refresh              :  1;   /* TLB refresh mode */
+       u16 reserved2;
+       u16 mui;
+       u64 reserved3;
+       u64 dasm;                       /* dma address space mask */
+       u64 msia;                       /* MSI address */
+       u64 reserved4;
+       u64 reserved5;
+} __packed;
+
+/* Set PCI function request */
+struct clp_req_set_pci {
+       struct clp_req_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u32 fh;                         /* function handle */
+       u16 reserved2;
+       u8 oc;                          /* operation controls */
+       u8 ndas;                        /* number of dma spaces */
+       u64 reserved3;
+} __packed;
+
+/* Set PCI function response */
+struct clp_rsp_set_pci {
+       struct clp_rsp_hdr hdr;
+       u32 fmt                 :  4;   /* cmd request block format */
+       u32                     : 28;
+       u64 reserved1;
+       u32 fh;                         /* function handle */
+       u32 reserved3;
+       u64 reserved4;
+} __packed;
+
+/* Combined request/response block structures used by clp insn */
+struct clp_req_rsp_list_pci {
+       struct clp_req_list_pci request;
+       struct clp_rsp_list_pci response;
+} __packed;
+
+struct clp_req_rsp_set_pci {
+       struct clp_req_set_pci request;
+       struct clp_rsp_set_pci response;
+} __packed;
+
+struct clp_req_rsp_query_pci {
+       struct clp_req_query_pci request;
+       struct clp_rsp_query_pci response;
+} __packed;
+
+struct clp_req_rsp_query_pci_grp {
+       struct clp_req_query_pci_grp request;
+       struct clp_rsp_query_pci_grp response;
+} __packed;
+
+#endif
diff --git a/arch/s390/include/asm/pci_dma.h b/arch/s390/include/asm/pci_dma.h
new file mode 100644 (file)
index 0000000..30b4c17
--- /dev/null
@@ -0,0 +1,196 @@
+#ifndef _ASM_S390_PCI_DMA_H
+#define _ASM_S390_PCI_DMA_H
+
+/* I/O Translation Anchor (IOTA) */
+enum zpci_ioat_dtype {
+       ZPCI_IOTA_STO = 0,
+       ZPCI_IOTA_RTTO = 1,
+       ZPCI_IOTA_RSTO = 2,
+       ZPCI_IOTA_RFTO = 3,
+       ZPCI_IOTA_PFAA = 4,
+       ZPCI_IOTA_IOPFAA = 5,
+       ZPCI_IOTA_IOPTO = 7
+};
+
+#define ZPCI_IOTA_IOT_ENABLED          0x800UL
+#define ZPCI_IOTA_DT_ST                        (ZPCI_IOTA_STO  << 2)
+#define ZPCI_IOTA_DT_RT                        (ZPCI_IOTA_RTTO << 2)
+#define ZPCI_IOTA_DT_RS                        (ZPCI_IOTA_RSTO << 2)
+#define ZPCI_IOTA_DT_RF                        (ZPCI_IOTA_RFTO << 2)
+#define ZPCI_IOTA_DT_PF                        (ZPCI_IOTA_PFAA << 2)
+#define ZPCI_IOTA_FS_4K                        0
+#define ZPCI_IOTA_FS_1M                        1
+#define ZPCI_IOTA_FS_2G                        2
+#define ZPCI_KEY                       (PAGE_DEFAULT_KEY << 5)
+
+#define ZPCI_IOTA_STO_FLAG     (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST)
+#define ZPCI_IOTA_RTTO_FLAG    (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT)
+#define ZPCI_IOTA_RSTO_FLAG    (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RS)
+#define ZPCI_IOTA_RFTO_FLAG    (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RF)
+#define ZPCI_IOTA_RFAA_FLAG    (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_PF | ZPCI_IOTA_FS_2G)
+
+/* I/O Region and segment tables */
+#define ZPCI_INDEX_MASK                        0x7ffUL
+
+#define ZPCI_TABLE_TYPE_MASK           0xc
+#define ZPCI_TABLE_TYPE_RFX            0xc
+#define ZPCI_TABLE_TYPE_RSX            0x8
+#define ZPCI_TABLE_TYPE_RTX            0x4
+#define ZPCI_TABLE_TYPE_SX             0x0
+
+#define ZPCI_TABLE_LEN_RFX             0x3
+#define ZPCI_TABLE_LEN_RSX             0x3
+#define ZPCI_TABLE_LEN_RTX             0x3
+
+#define ZPCI_TABLE_OFFSET_MASK         0xc0
+#define ZPCI_TABLE_SIZE                        0x4000
+#define ZPCI_TABLE_ALIGN               ZPCI_TABLE_SIZE
+#define ZPCI_TABLE_ENTRY_SIZE          (sizeof(unsigned long))
+#define ZPCI_TABLE_ENTRIES             (ZPCI_TABLE_SIZE / ZPCI_TABLE_ENTRY_SIZE)
+
+#define ZPCI_TABLE_BITS                        11
+#define ZPCI_PT_BITS                   8
+#define ZPCI_ST_SHIFT                  (ZPCI_PT_BITS + PAGE_SHIFT)
+#define ZPCI_RT_SHIFT                  (ZPCI_ST_SHIFT + ZPCI_TABLE_BITS)
+
+#define ZPCI_RTE_FLAG_MASK             0x3fffUL
+#define ZPCI_RTE_ADDR_MASK             (~ZPCI_RTE_FLAG_MASK)
+#define ZPCI_STE_FLAG_MASK             0x7ffUL
+#define ZPCI_STE_ADDR_MASK             (~ZPCI_STE_FLAG_MASK)
+
+/* I/O Page tables */
+#define ZPCI_PTE_VALID_MASK            0x400
+#define ZPCI_PTE_INVALID               0x400
+#define ZPCI_PTE_VALID                 0x000
+#define ZPCI_PT_SIZE                   0x800
+#define ZPCI_PT_ALIGN                  ZPCI_PT_SIZE
+#define ZPCI_PT_ENTRIES                        (ZPCI_PT_SIZE / ZPCI_TABLE_ENTRY_SIZE)
+#define ZPCI_PT_MASK                   (ZPCI_PT_ENTRIES - 1)
+
+#define ZPCI_PTE_FLAG_MASK             0xfffUL
+#define ZPCI_PTE_ADDR_MASK             (~ZPCI_PTE_FLAG_MASK)
+
+/* Shared bits */
+#define ZPCI_TABLE_VALID               0x00
+#define ZPCI_TABLE_INVALID             0x20
+#define ZPCI_TABLE_PROTECTED           0x200
+#define ZPCI_TABLE_UNPROTECTED         0x000
+
+#define ZPCI_TABLE_VALID_MASK          0x20
+#define ZPCI_TABLE_PROT_MASK           0x200
+
+static inline unsigned int calc_rtx(dma_addr_t ptr)
+{
+       return ((unsigned long) ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK;
+}
+
+static inline unsigned int calc_sx(dma_addr_t ptr)
+{
+       return ((unsigned long) ptr >> ZPCI_ST_SHIFT) & ZPCI_INDEX_MASK;
+}
+
+static inline unsigned int calc_px(dma_addr_t ptr)
+{
+       return ((unsigned long) ptr >> PAGE_SHIFT) & ZPCI_PT_MASK;
+}
+
+static inline void set_pt_pfaa(unsigned long *entry, void *pfaa)
+{
+       *entry &= ZPCI_PTE_FLAG_MASK;
+       *entry |= ((unsigned long) pfaa & ZPCI_PTE_ADDR_MASK);
+}
+
+static inline void set_rt_sto(unsigned long *entry, void *sto)
+{
+       *entry &= ZPCI_RTE_FLAG_MASK;
+       *entry |= ((unsigned long) sto & ZPCI_RTE_ADDR_MASK);
+       *entry |= ZPCI_TABLE_TYPE_RTX;
+}
+
+static inline void set_st_pto(unsigned long *entry, void *pto)
+{
+       *entry &= ZPCI_STE_FLAG_MASK;
+       *entry |= ((unsigned long) pto & ZPCI_STE_ADDR_MASK);
+       *entry |= ZPCI_TABLE_TYPE_SX;
+}
+
+static inline void validate_rt_entry(unsigned long *entry)
+{
+       *entry &= ~ZPCI_TABLE_VALID_MASK;
+       *entry &= ~ZPCI_TABLE_OFFSET_MASK;
+       *entry |= ZPCI_TABLE_VALID;
+       *entry |= ZPCI_TABLE_LEN_RTX;
+}
+
+static inline void validate_st_entry(unsigned long *entry)
+{
+       *entry &= ~ZPCI_TABLE_VALID_MASK;
+       *entry |= ZPCI_TABLE_VALID;
+}
+
+static inline void invalidate_table_entry(unsigned long *entry)
+{
+       *entry &= ~ZPCI_TABLE_VALID_MASK;
+       *entry |= ZPCI_TABLE_INVALID;
+}
+
+static inline void invalidate_pt_entry(unsigned long *entry)
+{
+       WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_INVALID);
+       *entry &= ~ZPCI_PTE_VALID_MASK;
+       *entry |= ZPCI_PTE_INVALID;
+}
+
+static inline void validate_pt_entry(unsigned long *entry)
+{
+       WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID);
+       *entry &= ~ZPCI_PTE_VALID_MASK;
+       *entry |= ZPCI_PTE_VALID;
+}
+
+static inline void entry_set_protected(unsigned long *entry)
+{
+       *entry &= ~ZPCI_TABLE_PROT_MASK;
+       *entry |= ZPCI_TABLE_PROTECTED;
+}
+
+static inline void entry_clr_protected(unsigned long *entry)
+{
+       *entry &= ~ZPCI_TABLE_PROT_MASK;
+       *entry |= ZPCI_TABLE_UNPROTECTED;
+}
+
+static inline int reg_entry_isvalid(unsigned long entry)
+{
+       return (entry & ZPCI_TABLE_VALID_MASK) == ZPCI_TABLE_VALID;
+}
+
+static inline int pt_entry_isvalid(unsigned long entry)
+{
+       return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID;
+}
+
+static inline int entry_isprotected(unsigned long entry)
+{
+       return (entry & ZPCI_TABLE_PROT_MASK) == ZPCI_TABLE_PROTECTED;
+}
+
+static inline unsigned long *get_rt_sto(unsigned long entry)
+{
+       return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX)
+               ? (unsigned long *) (entry & ZPCI_RTE_ADDR_MASK)
+               : NULL;
+}
+
+static inline unsigned long *get_st_pto(unsigned long entry)
+{
+       return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_SX)
+               ? (unsigned long *) (entry & ZPCI_STE_ADDR_MASK)
+               : NULL;
+}
+
+/* Prototypes */
+int zpci_dma_init_device(struct zpci_dev *);
+void zpci_dma_exit_device(struct zpci_dev *);
+
+#endif
diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
new file mode 100644 (file)
index 0000000..1486a98
--- /dev/null
@@ -0,0 +1,280 @@
+#ifndef _ASM_S390_PCI_INSN_H
+#define _ASM_S390_PCI_INSN_H
+
+#include <linux/delay.h>
+
+#define ZPCI_INSN_BUSY_DELAY   1       /* 1 microsecond */
+
+/* Load/Store status codes */
+#define ZPCI_PCI_ST_FUNC_NOT_ENABLED           4
+#define ZPCI_PCI_ST_FUNC_IN_ERR                        8
+#define ZPCI_PCI_ST_BLOCKED                    12
+#define ZPCI_PCI_ST_INSUF_RES                  16
+#define ZPCI_PCI_ST_INVAL_AS                   20
+#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED       24
+#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED         28
+#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS           36
+#define ZPCI_PCI_ST_FUNC_NOT_AVAIL             40
+#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE                44
+
+/* Load/Store return codes */
+#define ZPCI_PCI_LS_OK                         0
+#define ZPCI_PCI_LS_ERR                                1
+#define ZPCI_PCI_LS_BUSY                       2
+#define ZPCI_PCI_LS_INVAL_HANDLE               3
+
+/* Load/Store address space identifiers */
+#define ZPCI_PCIAS_MEMIO_0                     0
+#define ZPCI_PCIAS_MEMIO_1                     1
+#define ZPCI_PCIAS_MEMIO_2                     2
+#define ZPCI_PCIAS_MEMIO_3                     3
+#define ZPCI_PCIAS_MEMIO_4                     4
+#define ZPCI_PCIAS_MEMIO_5                     5
+#define ZPCI_PCIAS_CFGSPC                      15
+
+/* Modify PCI Function Controls */
+#define ZPCI_MOD_FC_REG_INT    2
+#define ZPCI_MOD_FC_DEREG_INT  3
+#define ZPCI_MOD_FC_REG_IOAT   4
+#define ZPCI_MOD_FC_DEREG_IOAT 5
+#define ZPCI_MOD_FC_REREG_IOAT 6
+#define ZPCI_MOD_FC_RESET_ERROR        7
+#define ZPCI_MOD_FC_RESET_BLOCK        9
+#define ZPCI_MOD_FC_SET_MEASURE        10
+
+/* FIB function controls */
+#define ZPCI_FIB_FC_ENABLED    0x80
+#define ZPCI_FIB_FC_ERROR      0x40
+#define ZPCI_FIB_FC_LS_BLOCKED 0x20
+#define ZPCI_FIB_FC_DMAAS_REG  0x10
+
+/* FIB function controls */
+#define ZPCI_FIB_FC_ENABLED    0x80
+#define ZPCI_FIB_FC_ERROR      0x40
+#define ZPCI_FIB_FC_LS_BLOCKED 0x20
+#define ZPCI_FIB_FC_DMAAS_REG  0x10
+
+/* Function Information Block */
+struct zpci_fib {
+       u32 fmt         :  8;   /* format */
+       u32             : 24;
+       u32 reserved1;
+       u8 fc;                  /* function controls */
+       u8 reserved2;
+       u16 reserved3;
+       u32 reserved4;
+       u64 pba;                /* PCI base address */
+       u64 pal;                /* PCI address limit */
+       u64 iota;               /* I/O Translation Anchor */
+       u32             :  1;
+       u32 isc         :  3;   /* Interrupt subclass */
+       u32 noi         : 12;   /* Number of interrupts */
+       u32             :  2;
+       u32 aibvo       :  6;   /* Adapter interrupt bit vector offset */
+       u32 sum         :  1;   /* Adapter int summary bit enabled */
+       u32             :  1;
+       u32 aisbo       :  6;   /* Adapter int summary bit offset */
+       u32 reserved5;
+       u64 aibv;               /* Adapter int bit vector address */
+       u64 aisb;               /* Adapter int summary bit address */
+       u64 fmb_addr;           /* Function measurement block address and key */
+       u64 reserved6;
+       u64 reserved7;
+} __packed;
+
+/* Modify PCI Function Controls */
+static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
+{
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rxy,0xe300000000d0,%[req],%[fib]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
+               : : "cc");
+       *status = req >> 24 & 0xff;
+       return cc;
+}
+
+static inline int mpcifc_instr(u64 req, struct zpci_fib *fib)
+{
+       u8 cc, status;
+
+       do {
+               cc = __mpcifc(req, fib, &status);
+               if (cc == 2)
+                       msleep(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d\n",
+                            __func__, cc, status);
+       return (cc) ? -EIO : 0;
+}
+
+/* Refresh PCI Translations */
+static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
+{
+       register u64 __addr asm("2") = addr;
+       register u64 __range asm("3") = range;
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rre,0xb9d30000,%[fn],%[addr]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [fn] "+d" (fn)
+               : [addr] "d" (__addr), "d" (__range)
+               : "cc");
+       *status = fn >> 24 & 0xff;
+       return cc;
+}
+
+static inline int rpcit_instr(u64 fn, u64 addr, u64 range)
+{
+       u8 cc, status;
+
+       do {
+               cc = __rpcit(fn, addr, range, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  dma_addr: %Lx  size: %Lx\n",
+                           __func__, cc, status, addr, range);
+       return (cc) ? -EIO : 0;
+}
+
+/* Store PCI function controls */
+static inline u8 __stpcifc(u32 handle, u8 space, struct zpci_fib *fib, u8 *status)
+{
+       u64 fn = (u64) handle << 32 | space << 16;
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rxy,0xe300000000d4,%[fn],%[fib]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [fn] "+d" (fn), [fib] "=m" (*fib)
+               : : "cc");
+       *status = fn >> 24 & 0xff;
+       return cc;
+}
+
+/* Set Interruption Controls */
+static inline void sic_instr(u16 ctl, char *unused, u8 isc)
+{
+       asm volatile (
+               "       .insn   rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
+               : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
+}
+
+/* PCI Load */
+static inline u8 __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
+{
+       register u64 __req asm("2") = req;
+       register u64 __offset asm("3") = offset;
+       u64 __data;
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rre,0xb9d20000,%[data],%[req]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [data] "=d" (__data), [req] "+d" (__req)
+               :  "d" (__offset)
+               : "cc");
+       *status = __req >> 24 & 0xff;
+       *data = __data;
+       return cc;
+}
+
+static inline int pcilg_instr(u64 *data, u64 req, u64 offset)
+{
+       u8 cc, status;
+
+       do {
+               cc = __pcilg(data, req, offset, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc) {
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
+                           __func__, cc, status, req, offset);
+               /* TODO: on IO errors set data to 0xff...
+                * here or in users of pcilg (le conversion)?
+                */
+       }
+       return (cc) ? -EIO : 0;
+}
+
+/* PCI Store */
+static inline u8 __pcistg(u64 data, u64 req, u64 offset, u8 *status)
+{
+       register u64 __req asm("2") = req;
+       register u64 __offset asm("3") = offset;
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rre,0xb9d00000,%[data],%[req]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [req] "+d" (__req)
+               : "d" (__offset), [data] "d" (data)
+               : "cc");
+       *status = __req >> 24 & 0xff;
+       return cc;
+}
+
+static inline int pcistg_instr(u64 data, u64 req, u64 offset)
+{
+       u8 cc, status;
+
+       do {
+               cc = __pcistg(data, req, offset, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
+                       __func__, cc, status, req, offset);
+       return (cc) ? -EIO : 0;
+}
+
+/* PCI Store Block */
+static inline u8 __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
+{
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [req] "+d" (req)
+               : [offset] "d" (offset), [data] "Q" (*data)
+               : "cc");
+       *status = req >> 24 & 0xff;
+       return cc;
+}
+
+static inline int pcistb_instr(const u64 *data, u64 req, u64 offset)
+{
+       u8 cc, status;
+
+       do {
+               cc = __pcistb(data, req, offset, &status);
+               if (cc == 2)
+                       udelay(ZPCI_INSN_BUSY_DELAY);
+       } while (cc == 2);
+
+       if (cc)
+               printk_once(KERN_ERR "%s: error cc: %d  status: %d  req: %Lx  offset: %Lx\n",
+                           __func__, cc, status, req, offset);
+       return (cc) ? -EIO : 0;
+}
+
+#endif
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h
new file mode 100644 (file)
index 0000000..5fd81f3
--- /dev/null
@@ -0,0 +1,194 @@
+#ifndef _ASM_S390_PCI_IO_H
+#define _ASM_S390_PCI_IO_H
+
+#ifdef CONFIG_PCI
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/pci_insn.h>
+
+/* I/O Map */
+#define ZPCI_IOMAP_MAX_ENTRIES         0x7fff
+#define ZPCI_IOMAP_ADDR_BASE           0x8000000000000000ULL
+#define ZPCI_IOMAP_ADDR_IDX_MASK       0x7fff000000000000ULL
+#define ZPCI_IOMAP_ADDR_OFF_MASK       0x0000ffffffffffffULL
+
+struct zpci_iomap_entry {
+       u32 fh;
+       u8 bar;
+};
+
+extern struct zpci_iomap_entry *zpci_iomap_start;
+
+#define ZPCI_IDX(addr)                                                         \
+       (((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> 48)
+#define ZPCI_OFFSET(addr)                                                      \
+       ((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK)
+
+#define ZPCI_CREATE_REQ(handle, space, len)                                    \
+       ((u64) handle << 32 | space << 16 | len)
+
+#define zpci_read(LENGTH, RETTYPE)                                             \
+static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)   \
+{                                                                              \
+       struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(addr)];     \
+       u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH);               \
+       u64 data;                                                               \
+       int rc;                                                                 \
+                                                                               \
+       rc = pcilg_instr(&data, req, ZPCI_OFFSET(addr));                        \
+       if (rc)                                                                 \
+               data = -1ULL;                                                   \
+       return (RETTYPE) data;                                                  \
+}
+
+#define zpci_write(LENGTH, VALTYPE)                                            \
+static inline void zpci_write_##VALTYPE(VALTYPE val,                           \
+                                       const volatile void __iomem *addr)      \
+{                                                                              \
+       struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(addr)];     \
+       u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH);               \
+       u64 data = (VALTYPE) val;                                               \
+                                                                               \
+       pcistg_instr(data, req, ZPCI_OFFSET(addr));                             \
+}
+
+zpci_read(8, u64)
+zpci_read(4, u32)
+zpci_read(2, u16)
+zpci_read(1, u8)
+zpci_write(8, u64)
+zpci_write(4, u32)
+zpci_write(2, u16)
+zpci_write(1, u8)
+
+static inline int zpci_write_single(u64 req, const u64 *data, u64 offset, u8 len)
+{
+       u64 val;
+
+       switch (len) {
+       case 1:
+               val = (u64) *((u8 *) data);
+               break;
+       case 2:
+               val = (u64) *((u16 *) data);
+               break;
+       case 4:
+               val = (u64) *((u32 *) data);
+               break;
+       case 8:
+               val = (u64) *((u64 *) data);
+               break;
+       default:
+               val = 0;                /* let FW report error */
+               break;
+       }
+       return pcistg_instr(val, req, offset);
+}
+
+static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
+{
+       u64 data;
+       u8 cc;
+
+       cc = pcilg_instr(&data,  req, offset);
+       switch (len) {
+       case 1:
+               *((u8 *) dst) = (u8) data;
+               break;
+       case 2:
+               *((u16 *) dst) = (u16) data;
+               break;
+       case 4:
+               *((u32 *) dst) = (u32) data;
+               break;
+       case 8:
+               *((u64 *) dst) = (u64) data;
+               break;
+       }
+       return cc;
+}
+
+static inline int zpci_write_block(u64 req, const u64 *data, u64 offset)
+{
+       return pcistb_instr(data, req, offset);
+}
+
+static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
+{
+       int count = len > max ? max : len, size = 1;
+
+       while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) {
+               dst = dst >> 1;
+               src = src >> 1;
+               size = size << 1;
+       }
+       return size;
+}
+
+static inline int zpci_memcpy_fromio(void *dst,
+                                    const volatile void __iomem *src,
+                                    unsigned long n)
+{
+       struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(src)];
+       u64 req, offset = ZPCI_OFFSET(src);
+       int size, rc = 0;
+
+       while (n > 0) {
+               size = zpci_get_max_write_size((u64) src, (u64) dst, n, 8);
+               req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size);
+               rc = zpci_read_single(req, dst, offset, size);
+               if (rc)
+                       break;
+               offset += size;
+               dst += size;
+               n -= size;
+       }
+       return rc;
+}
+
+static inline int zpci_memcpy_toio(volatile void __iomem *dst,
+                                  const void *src, unsigned long n)
+{
+       struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(dst)];
+       u64 req, offset = ZPCI_OFFSET(dst);
+       int size, rc = 0;
+
+       if (!src)
+               return -EINVAL;
+
+       while (n > 0) {
+               size = zpci_get_max_write_size((u64) dst, (u64) src, n, 128);
+               req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size);
+
+               if (size > 8) /* main path */
+                       rc = zpci_write_block(req, src, offset);
+               else
+                       rc = zpci_write_single(req, src, offset, size);
+               if (rc)
+                       break;
+               offset += size;
+               src += size;
+               n -= size;
+       }
+       return rc;
+}
+
+static inline int zpci_memset_io(volatile void __iomem *dst,
+                                unsigned char val, size_t count)
+{
+       u8 *src = kmalloc(count, GFP_KERNEL);
+       int rc;
+
+       if (src == NULL)
+               return -ENOMEM;
+       memset(src, val, count);
+
+       rc = zpci_memcpy_toio(dst, src, count);
+       kfree(src);
+       return rc;
+}
+
+#endif /* CONFIG_PCI */
+
+#endif /* _ASM_S390_PCI_IO_H */
index 2d3b7cb2600593f102b23dc8094fe384aa151b28..c928dc1938f23c8a90134c972147c9bbfecb005e 100644 (file)
@@ -35,7 +35,6 @@
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
 extern void paging_init(void);
 extern void vmem_map_init(void);
-extern void fault_init(void);
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
@@ -55,16 +54,7 @@ extern unsigned long zero_page_mask;
 #define ZERO_PAGE(vaddr) \
        (virt_to_page((void *)(empty_zero_page + \
         (((unsigned long)(vaddr)) &zero_page_mask))))
-
-#define is_zero_pfn is_zero_pfn
-static inline int is_zero_pfn(unsigned long pfn)
-{
-       extern unsigned long zero_pfn;
-       unsigned long offset_from_zero_pfn = pfn - zero_pfn;
-       return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
-}
-
-#define my_zero_pfn(addr)      page_to_pfn(ZERO_PAGE(addr))
+#define __HAVE_COLOR_ZERO_PAGE
 
 #endif /* !__ASSEMBLY__ */
 
@@ -345,6 +335,8 @@ extern unsigned long MODULES_END;
 #define _REGION3_ENTRY         (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
 #define _REGION3_ENTRY_EMPTY   (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
 
+#define _REGION3_ENTRY_LARGE   0x400   /* RTTE-format control, large page  */
+
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN  ~0x7ffUL/* segment table origin             */
 #define _SEGMENT_ENTRY_RO      0x200   /* page protection bit              */
@@ -444,6 +436,7 @@ static inline int pgd_bad(pgd_t pgd)     { return 0; }
 
 static inline int pud_present(pud_t pud) { return 1; }
 static inline int pud_none(pud_t pud)   { return 0; }
+static inline int pud_large(pud_t pud)  { return 0; }
 static inline int pud_bad(pud_t pud)    { return 0; }
 
 #else /* CONFIG_64BIT */
@@ -489,6 +482,13 @@ static inline int pud_none(pud_t pud)
        return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL;
 }
 
+static inline int pud_large(pud_t pud)
+{
+       if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
+               return 0;
+       return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
+}
+
 static inline int pud_bad(pud_t pud)
 {
        /*
index e62a555557ee459df20a4b370bce690a75158820..833788693f09b99a9cb18eda3f4b05f118778e3b 100644 (file)
@@ -55,5 +55,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info);
 void sclp_get_ipl_info(struct sclp_ipl_info *info);
 bool sclp_has_linemode(void);
 bool sclp_has_vt220(void);
+int sclp_pci_configure(u32 fid);
+int sclp_pci_deconfigure(u32 fid);
 
 #endif /* _ASM_S390_SCLP_H */
index 9935cbd6a46fdee89e8cdfd65c7f9acc0de474b9..05425b18c0aab7af89205a716f2ba05cec89cd0a 100644 (file)
@@ -8,32 +8,34 @@ struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
 
-extern unsigned char cpu_socket_id[NR_CPUS];
-#define topology_physical_package_id(cpu) (cpu_socket_id[cpu])
+struct cpu_topology_s390 {
+       unsigned short core_id;
+       unsigned short socket_id;
+       unsigned short book_id;
+       cpumask_t core_mask;
+       cpumask_t book_mask;
+};
+
+extern struct cpu_topology_s390 cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu)      (cpu_topology[cpu].socket_id)
+#define topology_core_id(cpu)                  (cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu)             (&cpu_topology[cpu].core_mask)
+#define topology_book_id(cpu)                  (cpu_topology[cpu].book_id)
+#define topology_book_cpumask(cpu)             (&cpu_topology[cpu].book_mask)
 
-extern unsigned char cpu_core_id[NR_CPUS];
-extern cpumask_t cpu_core_map[NR_CPUS];
+#define mc_capable() 1
 
 static inline const struct cpumask *cpu_coregroup_mask(int cpu)
 {
-       return &cpu_core_map[cpu];
+       return &cpu_topology[cpu].core_mask;
 }
 
-#define topology_core_id(cpu)          (cpu_core_id[cpu])
-#define topology_core_cpumask(cpu)     (&cpu_core_map[cpu])
-#define mc_capable()                   (1)
-
-extern unsigned char cpu_book_id[NR_CPUS];
-extern cpumask_t cpu_book_map[NR_CPUS];
-
 static inline const struct cpumask *cpu_book_mask(int cpu)
 {
-       return &cpu_book_map[cpu];
+       return &cpu_topology[cpu].book_mask;
 }
 
-#define topology_book_id(cpu)          (cpu_book_id[cpu])
-#define topology_book_cpumask(cpu)     (&cpu_book_map[cpu])
-
 int topology_cpu_init(struct cpu *);
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
diff --git a/arch/s390/include/asm/vga.h b/arch/s390/include/asm/vga.h
new file mode 100644 (file)
index 0000000..d375526
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_S390_VGA_H
+#define _ASM_S390_VGA_H
+
+/* Avoid compile errors due to missing asm/vga.h */
+
+#endif /* _ASM_S390_VGA_H */
index 4da52fe317437e312e509b05d28a5d92ed681d5d..2ac311ef5c9b11a3b37aa4f5586a240aa14679a6 100644 (file)
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
            processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
            debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o
+           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
index f00286bd2ef9050ad0cb166415272915eb7c5f5f..a7f9abd98cf23f5a014526206ca9b6827424c818 100644 (file)
@@ -83,22 +83,29 @@ enum {
        U4_12,  /* 4 bit unsigned value starting at 12 */
        U4_16,  /* 4 bit unsigned value starting at 16 */
        U4_20,  /* 4 bit unsigned value starting at 20 */
+       U4_24,  /* 4 bit unsigned value starting at 24 */
+       U4_28,  /* 4 bit unsigned value starting at 28 */
        U4_32,  /* 4 bit unsigned value starting at 32 */
+       U4_36,  /* 4 bit unsigned value starting at 36 */
        U8_8,   /* 8 bit unsigned value starting at 8 */
        U8_16,  /* 8 bit unsigned value starting at 16 */
        U8_24,  /* 8 bit unsigned value starting at 24 */
        U8_32,  /* 8 bit unsigned value starting at 32 */
        I8_8,   /* 8 bit signed value starting at 8 */
        I8_32,  /* 8 bit signed value starting at 32 */
+       J12_12, /* PC relative offset at 12 */
        I16_16, /* 16 bit signed value starting at 16 */
        I16_32, /* 32 bit signed value starting at 16 */
        U16_16, /* 16 bit unsigned value starting at 16 */
        U16_32, /* 32 bit unsigned value starting at 16 */
        J16_16, /* PC relative jump offset at 16 */
+       J16_32, /* PC relative offset at 16 */
+       I24_24, /* 24 bit signed value starting at 24 */
        J32_16, /* PC relative long offset at 16 */
        I32_16, /* 32 bit signed value starting at 16 */
        U32_16, /* 32 bit unsigned value starting at 16 */
        M_16,   /* 4 bit optional mask starting at 16 */
+       M_20,   /* 4 bit optional mask starting at 20 */
        RO_28,  /* optional GPR starting at position 28 */
 };
 
@@ -109,6 +116,8 @@ enum {
 enum {
        INSTR_INVALID,
        INSTR_E,
+       INSTR_IE_UU,
+       INSTR_MII_UPI,
        INSTR_RIE_R0IU, INSTR_RIE_R0UU, INSTR_RIE_RRP, INSTR_RIE_RRPU,
        INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU, INSTR_RIE_RRI0,
        INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, INSTR_RIL_UP,
@@ -118,13 +127,15 @@ enum {
        INSTR_RRE_FF, INSTR_RRE_FR, INSTR_RRE_R0, INSTR_RRE_RA, INSTR_RRE_RF,
        INSTR_RRE_RR, INSTR_RRE_RR_OPT,
        INSTR_RRF_0UFF, INSTR_RRF_F0FF, INSTR_RRF_F0FF2, INSTR_RRF_F0FR,
-       INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_M0RR, INSTR_RRF_R0RR,
-       INSTR_RRF_R0RR2, INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF,
-       INSTR_RRF_U0RR, INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
+       INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_FUFF2, INSTR_RRF_M0RR,
+       INSTR_RRF_R0RR, INSTR_RRF_R0RR2, INSTR_RRF_RMRR, INSTR_RRF_RURR,
+       INSTR_RRF_U0FF, INSTR_RRF_U0RF, INSTR_RRF_U0RR, INSTR_RRF_UUFF,
+       INSTR_RRF_UUFR, INSTR_RRF_UURF,
+       INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
        INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR,
        INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD,
        INSTR_RSI_RRP,
-       INSTR_RSL_R0RD,
+       INSTR_RSL_LRDFU, INSTR_RSL_R0RD,
        INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, INSTR_RSY_RURD,
        INSTR_RSY_RDRM,
        INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, INSTR_RS_RRRD,
@@ -136,6 +147,7 @@ enum {
        INSTR_SIL_RDI, INSTR_SIL_RDU,
        INSTR_SIY_IRD, INSTR_SIY_URD,
        INSTR_SI_URD,
+       INSTR_SMI_U0RDP,
        INSTR_SSE_RDRD,
        INSTR_SSF_RRDRD, INSTR_SSF_RRDRD2,
        INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, INSTR_SS_LLRDRD, INSTR_SS_RRRDRD,
@@ -191,31 +203,42 @@ static const struct operand operands[] =
        [U4_12]  = {  4, 12, 0 },
        [U4_16]  = {  4, 16, 0 },
        [U4_20]  = {  4, 20, 0 },
+       [U4_24]  = {  4, 24, 0 },
+       [U4_28]  = {  4, 28, 0 },
        [U4_32]  = {  4, 32, 0 },
+       [U4_36]  = {  4, 36, 0 },
        [U8_8]   = {  8,  8, 0 },
        [U8_16]  = {  8, 16, 0 },
        [U8_24]  = {  8, 24, 0 },
        [U8_32]  = {  8, 32, 0 },
+       [J12_12] = { 12, 12, OPERAND_PCREL },
        [I16_16] = { 16, 16, OPERAND_SIGNED },
        [U16_16] = { 16, 16, 0 },
        [U16_32] = { 16, 32, 0 },
        [J16_16] = { 16, 16, OPERAND_PCREL },
+       [J16_32] = { 16, 32, OPERAND_PCREL },
        [I16_32] = { 16, 32, OPERAND_SIGNED },
+       [I24_24] = { 24, 24, OPERAND_SIGNED },
        [J32_16] = { 32, 16, OPERAND_PCREL },
        [I32_16] = { 32, 16, OPERAND_SIGNED },
        [U32_16] = { 32, 16, 0 },
        [M_16]   = {  4, 16, 0 },
+       [M_20]   = {  4, 20, 0 },
        [RO_28]  = {  4, 28, OPERAND_GPR }
 };
 
 static const unsigned char formats[][7] = {
        [INSTR_E]         = { 0xff, 0,0,0,0,0,0 },
+       [INSTR_IE_UU]     = { 0xff, U4_24,U4_28,0,0,0,0 },
+       [INSTR_MII_UPI]   = { 0xff, U4_8,J12_12,I24_24 },
+       [INSTR_RIE_R0IU]  = { 0xff, R_8,I16_16,U4_32,0,0,0 },
        [INSTR_RIE_R0UU]  = { 0xff, R_8,U16_16,U4_32,0,0,0 },
+       [INSTR_RIE_RRI0]  = { 0xff, R_8,R_12,I16_16,0,0,0 },
        [INSTR_RIE_RRPU]  = { 0xff, R_8,R_12,U4_32,J16_16,0,0 },
        [INSTR_RIE_RRP]   = { 0xff, R_8,R_12,J16_16,0,0,0 },
        [INSTR_RIE_RRUUU] = { 0xff, R_8,R_12,U8_16,U8_24,U8_32,0 },
        [INSTR_RIE_RUPI]  = { 0xff, R_8,I8_32,U4_12,J16_16,0,0 },
-       [INSTR_RIE_RRI0]  = { 0xff, R_8,R_12,I16_16,0,0,0 },
+       [INSTR_RIE_RUPU]  = { 0xff, R_8,U8_32,U4_12,J16_16,0,0 },
        [INSTR_RIL_RI]    = { 0x0f, R_8,I32_16,0,0,0,0 },
        [INSTR_RIL_RP]    = { 0x0f, R_8,J32_16,0,0,0,0 },
        [INSTR_RIL_RU]    = { 0x0f, R_8,U32_16,0,0,0,0 },
@@ -245,14 +268,18 @@ static const unsigned char formats[][7] = {
        [INSTR_RRF_F0FR]  = { 0xff, F_24,F_16,R_28,0,0,0 },
        [INSTR_RRF_FFRU]  = { 0xff, F_24,F_16,R_28,U4_20,0,0 },
        [INSTR_RRF_FUFF]  = { 0xff, F_24,F_16,F_28,U4_20,0,0 },
+       [INSTR_RRF_FUFF2] = { 0xff, F_24,F_28,F_16,U4_20,0,0 },
        [INSTR_RRF_M0RR]  = { 0xff, R_24,R_28,M_16,0,0,0 },
        [INSTR_RRF_R0RR]  = { 0xff, R_24,R_16,R_28,0,0,0 },
        [INSTR_RRF_R0RR2] = { 0xff, R_24,R_28,R_16,0,0,0 },
+       [INSTR_RRF_RMRR]  = { 0xff, R_24,R_16,R_28,M_20,0,0 },
        [INSTR_RRF_RURR]  = { 0xff, R_24,R_28,R_16,U4_20,0,0 },
        [INSTR_RRF_U0FF]  = { 0xff, F_24,U4_16,F_28,0,0,0 },
        [INSTR_RRF_U0RF]  = { 0xff, R_24,U4_16,F_28,0,0,0 },
        [INSTR_RRF_U0RR]  = { 0xff, R_24,R_28,U4_16,0,0,0 },
        [INSTR_RRF_UUFF]  = { 0xff, F_24,U4_16,F_28,U4_20,0,0 },
+       [INSTR_RRF_UUFR]  = { 0xff, F_24,U4_16,R_28,U4_20,0,0 },
+       [INSTR_RRF_UURF]  = { 0xff, R_24,U4_16,F_28,U4_20,0,0 },
        [INSTR_RRR_F0FF]  = { 0xff, F_24,F_28,F_16,0,0,0 },
        [INSTR_RRS_RRRDU] = { 0xff, R_8,R_12,U4_32,D_20,B_16,0 },
        [INSTR_RR_FF]     = { 0xff, F_8,F_12,0,0,0,0 },
@@ -264,12 +291,13 @@ static const unsigned char formats[][7] = {
        [INSTR_RSE_RRRD]  = { 0xff, R_8,R_12,D_20,B_16,0,0 },
        [INSTR_RSE_RURD]  = { 0xff, R_8,U4_12,D_20,B_16,0,0 },
        [INSTR_RSI_RRP]   = { 0xff, R_8,R_12,J16_16,0,0,0 },
+       [INSTR_RSL_LRDFU] = { 0xff, F_32,D_20,L4_8,B_16,U4_36,0 },
        [INSTR_RSL_R0RD]  = { 0xff, D_20,L4_8,B_16,0,0,0 },
        [INSTR_RSY_AARD]  = { 0xff, A_8,A_12,D20_20,B_16,0,0 },
        [INSTR_RSY_CCRD]  = { 0xff, C_8,C_12,D20_20,B_16,0,0 },
+       [INSTR_RSY_RDRM]  = { 0xff, R_8,D20_20,B_16,U4_12,0,0 },
        [INSTR_RSY_RRRD]  = { 0xff, R_8,R_12,D20_20,B_16,0,0 },
        [INSTR_RSY_RURD]  = { 0xff, R_8,U4_12,D20_20,B_16,0,0 },
-       [INSTR_RSY_RDRM]  = { 0xff, R_8,D20_20,B_16,U4_12,0,0 },
        [INSTR_RS_AARD]   = { 0xff, A_8,A_12,D_20,B_16,0,0 },
        [INSTR_RS_CCRD]   = { 0xff, C_8,C_12,D_20,B_16,0,0 },
        [INSTR_RS_R0RD]   = { 0xff, R_8,D_20,B_16,0,0,0 },
@@ -289,9 +317,10 @@ static const unsigned char formats[][7] = {
        [INSTR_SIY_IRD]   = { 0xff, D20_20,B_16,I8_8,0,0,0 },
        [INSTR_SIY_URD]   = { 0xff, D20_20,B_16,U8_8,0,0,0 },
        [INSTR_SI_URD]    = { 0xff, D_20,B_16,U8_8,0,0,0 },
+       [INSTR_SMI_U0RDP] = { 0xff, U4_8,J16_32,D_20,B_16,0,0 },
        [INSTR_SSE_RDRD]  = { 0xff, D_20,B_16,D_36,B_32,0,0 },
-       [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 },
-       [INSTR_SSF_RRDRD2]= { 0x00, R_8,D_20,B_16,D_36,B_32,0 },
+       [INSTR_SSF_RRDRD] = { 0x0f, D_20,B_16,D_36,B_32,R_8,0 },
+       [INSTR_SSF_RRDRD2]= { 0x0f, R_8,D_20,B_16,D_36,B_32,0 },
        [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 },
        [INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 },
        [INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 },
@@ -304,46 +333,157 @@ static const unsigned char formats[][7] = {
 
 enum {
        LONG_INSN_ALGHSIK,
+       LONG_INSN_ALHHHR,
+       LONG_INSN_ALHHLR,
        LONG_INSN_ALHSIK,
+       LONG_INSN_ALSIHN,
+       LONG_INSN_CDFBRA,
+       LONG_INSN_CDGBRA,
+       LONG_INSN_CDGTRA,
+       LONG_INSN_CDLFBR,
+       LONG_INSN_CDLFTR,
+       LONG_INSN_CDLGBR,
+       LONG_INSN_CDLGTR,
+       LONG_INSN_CEFBRA,
+       LONG_INSN_CEGBRA,
+       LONG_INSN_CELFBR,
+       LONG_INSN_CELGBR,
+       LONG_INSN_CFDBRA,
+       LONG_INSN_CFEBRA,
+       LONG_INSN_CFXBRA,
+       LONG_INSN_CGDBRA,
+       LONG_INSN_CGDTRA,
+       LONG_INSN_CGEBRA,
+       LONG_INSN_CGXBRA,
+       LONG_INSN_CGXTRA,
+       LONG_INSN_CLFDBR,
+       LONG_INSN_CLFDTR,
+       LONG_INSN_CLFEBR,
        LONG_INSN_CLFHSI,
+       LONG_INSN_CLFXBR,
+       LONG_INSN_CLFXTR,
+       LONG_INSN_CLGDBR,
+       LONG_INSN_CLGDTR,
+       LONG_INSN_CLGEBR,
        LONG_INSN_CLGFRL,
        LONG_INSN_CLGHRL,
        LONG_INSN_CLGHSI,
+       LONG_INSN_CLGXBR,
+       LONG_INSN_CLGXTR,
        LONG_INSN_CLHHSI,
+       LONG_INSN_CXFBRA,
+       LONG_INSN_CXGBRA,
+       LONG_INSN_CXGTRA,
+       LONG_INSN_CXLFBR,
+       LONG_INSN_CXLFTR,
+       LONG_INSN_CXLGBR,
+       LONG_INSN_CXLGTR,
+       LONG_INSN_FIDBRA,
+       LONG_INSN_FIEBRA,
+       LONG_INSN_FIXBRA,
+       LONG_INSN_LDXBRA,
+       LONG_INSN_LEDBRA,
+       LONG_INSN_LEXBRA,
+       LONG_INSN_LLGFAT,
        LONG_INSN_LLGFRL,
        LONG_INSN_LLGHRL,
+       LONG_INSN_LLGTAT,
        LONG_INSN_POPCNT,
+       LONG_INSN_RIEMIT,
+       LONG_INSN_RINEXT,
+       LONG_INSN_RISBGN,
        LONG_INSN_RISBHG,
        LONG_INSN_RISBLG,
-       LONG_INSN_RINEXT,
-       LONG_INSN_RIEMIT,
+       LONG_INSN_SLHHHR,
+       LONG_INSN_SLHHLR,
        LONG_INSN_TABORT,
        LONG_INSN_TBEGIN,
        LONG_INSN_TBEGINC,
+       LONG_INSN_PCISTG,
+       LONG_INSN_MPCIFC,
+       LONG_INSN_STPCIFC,
+       LONG_INSN_PCISTB,
 };
 
 static char *long_insn_name[] = {
        [LONG_INSN_ALGHSIK] = "alghsik",
+       [LONG_INSN_ALHHHR] = "alhhhr",
+       [LONG_INSN_ALHHLR] = "alhhlr",
        [LONG_INSN_ALHSIK] = "alhsik",
+       [LONG_INSN_ALSIHN] = "alsihn",
+       [LONG_INSN_CDFBRA] = "cdfbra",
+       [LONG_INSN_CDGBRA] = "cdgbra",
+       [LONG_INSN_CDGTRA] = "cdgtra",
+       [LONG_INSN_CDLFBR] = "cdlfbr",
+       [LONG_INSN_CDLFTR] = "cdlftr",
+       [LONG_INSN_CDLGBR] = "cdlgbr",
+       [LONG_INSN_CDLGTR] = "cdlgtr",
+       [LONG_INSN_CEFBRA] = "cefbra",
+       [LONG_INSN_CEGBRA] = "cegbra",
+       [LONG_INSN_CELFBR] = "celfbr",
+       [LONG_INSN_CELGBR] = "celgbr",
+       [LONG_INSN_CFDBRA] = "cfdbra",
+       [LONG_INSN_CFEBRA] = "cfebra",
+       [LONG_INSN_CFXBRA] = "cfxbra",
+       [LONG_INSN_CGDBRA] = "cgdbra",
+       [LONG_INSN_CGDTRA] = "cgdtra",
+       [LONG_INSN_CGEBRA] = "cgebra",
+       [LONG_INSN_CGXBRA] = "cgxbra",
+       [LONG_INSN_CGXTRA] = "cgxtra",
+       [LONG_INSN_CLFDBR] = "clfdbr",
+       [LONG_INSN_CLFDTR] = "clfdtr",
+       [LONG_INSN_CLFEBR] = "clfebr",
        [LONG_INSN_CLFHSI] = "clfhsi",
+       [LONG_INSN_CLFXBR] = "clfxbr",
+       [LONG_INSN_CLFXTR] = "clfxtr",
+       [LONG_INSN_CLGDBR] = "clgdbr",
+       [LONG_INSN_CLGDTR] = "clgdtr",
+       [LONG_INSN_CLGEBR] = "clgebr",
        [LONG_INSN_CLGFRL] = "clgfrl",
        [LONG_INSN_CLGHRL] = "clghrl",
        [LONG_INSN_CLGHSI] = "clghsi",
+       [LONG_INSN_CLGXBR] = "clgxbr",
+       [LONG_INSN_CLGXTR] = "clgxtr",
        [LONG_INSN_CLHHSI] = "clhhsi",
+       [LONG_INSN_CXFBRA] = "cxfbra",
+       [LONG_INSN_CXGBRA] = "cxgbra",
+       [LONG_INSN_CXGTRA] = "cxgtra",
+       [LONG_INSN_CXLFBR] = "cxlfbr",
+       [LONG_INSN_CXLFTR] = "cxlftr",
+       [LONG_INSN_CXLGBR] = "cxlgbr",
+       [LONG_INSN_CXLGTR] = "cxlgtr",
+       [LONG_INSN_FIDBRA] = "fidbra",
+       [LONG_INSN_FIEBRA] = "fiebra",
+       [LONG_INSN_FIXBRA] = "fixbra",
+       [LONG_INSN_LDXBRA] = "ldxbra",
+       [LONG_INSN_LEDBRA] = "ledbra",
+       [LONG_INSN_LEXBRA] = "lexbra",
+       [LONG_INSN_LLGFAT] = "llgfat",
        [LONG_INSN_LLGFRL] = "llgfrl",
        [LONG_INSN_LLGHRL] = "llghrl",
+       [LONG_INSN_LLGTAT] = "llgtat",
        [LONG_INSN_POPCNT] = "popcnt",
+       [LONG_INSN_RIEMIT] = "riemit",
+       [LONG_INSN_RINEXT] = "rinext",
+       [LONG_INSN_RISBGN] = "risbgn",
        [LONG_INSN_RISBHG] = "risbhg",
        [LONG_INSN_RISBLG] = "risblg",
-       [LONG_INSN_RINEXT] = "rinext",
-       [LONG_INSN_RIEMIT] = "riemit",
+       [LONG_INSN_SLHHHR] = "slhhhr",
+       [LONG_INSN_SLHHLR] = "slhhlr",
        [LONG_INSN_TABORT] = "tabort",
        [LONG_INSN_TBEGIN] = "tbegin",
        [LONG_INSN_TBEGINC] = "tbeginc",
+       [LONG_INSN_PCISTG] = "pcistg",
+       [LONG_INSN_MPCIFC] = "mpcifc",
+       [LONG_INSN_STPCIFC] = "stpcifc",
+       [LONG_INSN_PCISTB] = "pcistb",
 };
 
 static struct insn opcode[] = {
 #ifdef CONFIG_64BIT
+       { "bprp", 0xc5, INSTR_MII_UPI },
+       { "bpp", 0xc7, INSTR_SMI_U0RDP },
+       { "trtr", 0xd0, INSTR_SS_L0RDRD },
        { "lmd", 0xef, INSTR_SS_RRRDRD3 },
 #endif
        { "spm", 0x04, INSTR_RR_R0 },
@@ -378,7 +518,6 @@ static struct insn opcode[] = {
        { "lcdr", 0x23, INSTR_RR_FF },
        { "hdr", 0x24, INSTR_RR_FF },
        { "ldxr", 0x25, INSTR_RR_FF },
-       { "lrdr", 0x25, INSTR_RR_FF },
        { "mxr", 0x26, INSTR_RR_FF },
        { "mxdr", 0x27, INSTR_RR_FF },
        { "ldr", 0x28, INSTR_RR_FF },
@@ -395,7 +534,6 @@ static struct insn opcode[] = {
        { "lcer", 0x33, INSTR_RR_FF },
        { "her", 0x34, INSTR_RR_FF },
        { "ledr", 0x35, INSTR_RR_FF },
-       { "lrer", 0x35, INSTR_RR_FF },
        { "axr", 0x36, INSTR_RR_FF },
        { "sxr", 0x37, INSTR_RR_FF },
        { "ler", 0x38, INSTR_RR_FF },
@@ -403,7 +541,6 @@ static struct insn opcode[] = {
        { "aer", 0x3a, INSTR_RR_FF },
        { "ser", 0x3b, INSTR_RR_FF },
        { "mder", 0x3c, INSTR_RR_FF },
-       { "mer", 0x3c, INSTR_RR_FF },
        { "der", 0x3d, INSTR_RR_FF },
        { "aur", 0x3e, INSTR_RR_FF },
        { "sur", 0x3f, INSTR_RR_FF },
@@ -454,7 +591,6 @@ static struct insn opcode[] = {
        { "ae", 0x7a, INSTR_RX_FRRD },
        { "se", 0x7b, INSTR_RX_FRRD },
        { "mde", 0x7c, INSTR_RX_FRRD },
-       { "me", 0x7c, INSTR_RX_FRRD },
        { "de", 0x7d, INSTR_RX_FRRD },
        { "au", 0x7e, INSTR_RX_FRRD },
        { "su", 0x7f, INSTR_RX_FRRD },
@@ -534,9 +670,9 @@ static struct insn opcode[] = {
 
 static struct insn opcode_01[] = {
 #ifdef CONFIG_64BIT
-       { "sam64", 0x0e, INSTR_E },
-       { "pfpo", 0x0a, INSTR_E },
        { "ptff", 0x04, INSTR_E },
+       { "pfpo", 0x0a, INSTR_E },
+       { "sam64", 0x0e, INSTR_E },
 #endif
        { "pr", 0x01, INSTR_E },
        { "upt", 0x02, INSTR_E },
@@ -605,19 +741,28 @@ static struct insn opcode_aa[] = {
 
 static struct insn opcode_b2[] = {
 #ifdef CONFIG_64BIT
-       { "sske", 0x2b, INSTR_RRF_M0RR },
        { "stckf", 0x7c, INSTR_S_RD },
-       { "cu21", 0xa6, INSTR_RRF_M0RR },
-       { "cuutf", 0xa6, INSTR_RRF_M0RR },
-       { "cu12", 0xa7, INSTR_RRF_M0RR },
-       { "cutfu", 0xa7, INSTR_RRF_M0RR },
+       { "lpp", 0x80, INSTR_S_RD },
+       { "lcctl", 0x84, INSTR_S_RD },
+       { "lpctl", 0x85, INSTR_S_RD },
+       { "qsi", 0x86, INSTR_S_RD },
+       { "lsctl", 0x87, INSTR_S_RD },
+       { "qctri", 0x8e, INSTR_S_RD },
        { "stfle", 0xb0, INSTR_S_RD },
        { "lpswe", 0xb2, INSTR_S_RD },
+       { "srnmb", 0xb8, INSTR_S_RD },
        { "srnmt", 0xb9, INSTR_S_RD },
        { "lfas", 0xbd, INSTR_S_RD },
-       { "etndg", 0xec, INSTR_RRE_R0 },
+       { "scctr", 0xe0, INSTR_RRE_RR },
+       { "spctr", 0xe1, INSTR_RRE_RR },
+       { "ecctr", 0xe4, INSTR_RRE_RR },
+       { "epctr", 0xe5, INSTR_RRE_RR },
+       { "ppa", 0xe8, INSTR_RRF_U0RR },
+       { "etnd", 0xec, INSTR_RRE_R0 },
+       { "ecpga", 0xed, INSTR_RRE_RR },
+       { "tend", 0xf8, INSTR_S_00 },
+       { "niai", 0xfa, INSTR_IE_UU },
        { { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD },
-       { "tend", 0xf8, INSTR_S_RD },
 #endif
        { "stidp", 0x02, INSTR_S_RD },
        { "sck", 0x04, INSTR_S_RD },
@@ -635,8 +780,8 @@ static struct insn opcode_b2[] = {
        { "sie", 0x14, INSTR_S_RD },
        { "pc", 0x18, INSTR_S_RD },
        { "sac", 0x19, INSTR_S_RD },
-       { "servc", 0x20, INSTR_RRE_RR },
        { "cfc", 0x1a, INSTR_S_RD },
+       { "servc", 0x20, INSTR_RRE_RR },
        { "ipte", 0x21, INSTR_RRE_RR },
        { "ipm", 0x22, INSTR_RRE_R0 },
        { "ivsk", 0x23, INSTR_RRE_RR },
@@ -647,9 +792,9 @@ static struct insn opcode_b2[] = {
        { "pt", 0x28, INSTR_RRE_RR },
        { "iske", 0x29, INSTR_RRE_RR },
        { "rrbe", 0x2a, INSTR_RRE_RR },
-       { "sske", 0x2b, INSTR_RRE_RR },
+       { "sske", 0x2b, INSTR_RRF_M0RR },
        { "tb", 0x2c, INSTR_RRE_0R },
-       { "dxr", 0x2d, INSTR_RRE_F0 },
+       { "dxr", 0x2d, INSTR_RRE_FF },
        { "pgin", 0x2e, INSTR_RRE_RR },
        { "pgout", 0x2f, INSTR_RRE_RR },
        { "csch", 0x30, INSTR_S_00 },
@@ -667,8 +812,8 @@ static struct insn opcode_b2[] = {
        { "schm", 0x3c, INSTR_S_00 },
        { "bakr", 0x40, INSTR_RRE_RR },
        { "cksm", 0x41, INSTR_RRE_RR },
-       { "sqdr", 0x44, INSTR_RRE_F0 },
-       { "sqer", 0x45, INSTR_RRE_F0 },
+       { "sqdr", 0x44, INSTR_RRE_FF },
+       { "sqer", 0x45, INSTR_RRE_FF },
        { "stura", 0x46, INSTR_RRE_RR },
        { "msta", 0x47, INSTR_RRE_R0 },
        { "palb", 0x48, INSTR_RRE_00 },
@@ -694,14 +839,14 @@ static struct insn opcode_b2[] = {
        { "rp", 0x77, INSTR_S_RD },
        { "stcke", 0x78, INSTR_S_RD },
        { "sacf", 0x79, INSTR_S_RD },
-       { "spp", 0x80, INSTR_S_RD },
        { "stsi", 0x7d, INSTR_S_RD },
+       { "spp", 0x80, INSTR_S_RD },
        { "srnm", 0x99, INSTR_S_RD },
        { "stfpc", 0x9c, INSTR_S_RD },
        { "lfpc", 0x9d, INSTR_S_RD },
        { "tre", 0xa5, INSTR_RRE_RR },
-       { "cuutf", 0xa6, INSTR_RRE_RR },
-       { "cutfu", 0xa7, INSTR_RRE_RR },
+       { "cuutf", 0xa6, INSTR_RRF_M0RR },
+       { "cutfu", 0xa7, INSTR_RRF_M0RR },
        { "stfl", 0xb1, INSTR_S_RD },
        { "trap4", 0xff, INSTR_S_RD },
        { "", 0, INSTR_INVALID }
@@ -715,72 +860,87 @@ static struct insn opcode_b3[] = {
        { "myr", 0x3b, INSTR_RRF_F0FF },
        { "mayhr", 0x3c, INSTR_RRF_F0FF },
        { "myhr", 0x3d, INSTR_RRF_F0FF },
-       { "cegbr", 0xa4, INSTR_RRE_RR },
-       { "cdgbr", 0xa5, INSTR_RRE_RR },
-       { "cxgbr", 0xa6, INSTR_RRE_RR },
-       { "cgebr", 0xa8, INSTR_RRF_U0RF },
-       { "cgdbr", 0xa9, INSTR_RRF_U0RF },
-       { "cgxbr", 0xaa, INSTR_RRF_U0RF },
-       { "cfer", 0xb8, INSTR_RRF_U0RF },
-       { "cfdr", 0xb9, INSTR_RRF_U0RF },
-       { "cfxr", 0xba, INSTR_RRF_U0RF },
-       { "cegr", 0xc4, INSTR_RRE_RR },
-       { "cdgr", 0xc5, INSTR_RRE_RR },
-       { "cxgr", 0xc6, INSTR_RRE_RR },
-       { "cger", 0xc8, INSTR_RRF_U0RF },
-       { "cgdr", 0xc9, INSTR_RRF_U0RF },
-       { "cgxr", 0xca, INSTR_RRF_U0RF },
        { "lpdfr", 0x70, INSTR_RRE_FF },
        { "lndfr", 0x71, INSTR_RRE_FF },
        { "cpsdr", 0x72, INSTR_RRF_F0FF2 },
        { "lcdfr", 0x73, INSTR_RRE_FF },
+       { "sfasr", 0x85, INSTR_RRE_R0 },
+       { { 0, LONG_INSN_CELFBR }, 0x90, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CDLFBR }, 0x91, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CXLFBR }, 0x92, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CEFBRA }, 0x94, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CDFBRA }, 0x95, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CXFBRA }, 0x96, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CFEBRA }, 0x98, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CFDBRA }, 0x99, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CFXBRA }, 0x9a, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CLFEBR }, 0x9c, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLFDBR }, 0x9d, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLFXBR }, 0x9e, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CELGBR }, 0xa0, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CDLGBR }, 0xa1, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CXLGBR }, 0xa2, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CEGBRA }, 0xa4, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CDGBRA }, 0xa5, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CXGBRA }, 0xa6, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CGEBRA }, 0xa8, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CGDBRA }, 0xa9, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CGXBRA }, 0xaa, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CLGEBR }, 0xac, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLGDBR }, 0xad, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLGXBR }, 0xae, INSTR_RRF_UUFR },
        { "ldgr", 0xc1, INSTR_RRE_FR },
+       { "cegr", 0xc4, INSTR_RRE_FR },
+       { "cdgr", 0xc5, INSTR_RRE_FR },
+       { "cxgr", 0xc6, INSTR_RRE_FR },
+       { "cger", 0xc8, INSTR_RRF_U0RF },
+       { "cgdr", 0xc9, INSTR_RRF_U0RF },
+       { "cgxr", 0xca, INSTR_RRF_U0RF },
        { "lgdr", 0xcd, INSTR_RRE_RF },
-       { "adtr", 0xd2, INSTR_RRR_F0FF },
-       { "axtr", 0xda, INSTR_RRR_F0FF },
-       { "cdtr", 0xe4, INSTR_RRE_FF },
-       { "cxtr", 0xec, INSTR_RRE_FF },
+       { "mdtra", 0xd0, INSTR_RRF_FUFF2 },
+       { "ddtra", 0xd1, INSTR_RRF_FUFF2 },
+       { "adtra", 0xd2, INSTR_RRF_FUFF2 },
+       { "sdtra", 0xd3, INSTR_RRF_FUFF2 },
+       { "ldetr", 0xd4, INSTR_RRF_0UFF },
+       { "ledtr", 0xd5, INSTR_RRF_UUFF },
+       { "ltdtr", 0xd6, INSTR_RRE_FF },
+       { "fidtr", 0xd7, INSTR_RRF_UUFF },
+       { "mxtra", 0xd8, INSTR_RRF_FUFF2 },
+       { "dxtra", 0xd9, INSTR_RRF_FUFF2 },
+       { "axtra", 0xda, INSTR_RRF_FUFF2 },
+       { "sxtra", 0xdb, INSTR_RRF_FUFF2 },
+       { "lxdtr", 0xdc, INSTR_RRF_0UFF },
+       { "ldxtr", 0xdd, INSTR_RRF_UUFF },
+       { "ltxtr", 0xde, INSTR_RRE_FF },
+       { "fixtr", 0xdf, INSTR_RRF_UUFF },
        { "kdtr", 0xe0, INSTR_RRE_FF },
-       { "kxtr", 0xe8, INSTR_RRE_FF },
-       { "cedtr", 0xf4, INSTR_RRE_FF },
-       { "cextr", 0xfc, INSTR_RRE_FF },
-       { "cdgtr", 0xf1, INSTR_RRE_FR },
-       { "cxgtr", 0xf9, INSTR_RRE_FR },
-       { "cdstr", 0xf3, INSTR_RRE_FR },
-       { "cxstr", 0xfb, INSTR_RRE_FR },
-       { "cdutr", 0xf2, INSTR_RRE_FR },
-       { "cxutr", 0xfa, INSTR_RRE_FR },
-       { "cgdtr", 0xe1, INSTR_RRF_U0RF },
-       { "cgxtr", 0xe9, INSTR_RRF_U0RF },
-       { "csdtr", 0xe3, INSTR_RRE_RF },
-       { "csxtr", 0xeb, INSTR_RRE_RF },
+       { { 0, LONG_INSN_CGDTRA }, 0xe1, INSTR_RRF_UURF },
        { "cudtr", 0xe2, INSTR_RRE_RF },
-       { "cuxtr", 0xea, INSTR_RRE_RF },
-       { "ddtr", 0xd1, INSTR_RRR_F0FF },
-       { "dxtr", 0xd9, INSTR_RRR_F0FF },
+       { "csdtr", 0xe3, INSTR_RRE_RF },
+       { "cdtr", 0xe4, INSTR_RRE_FF },
        { "eedtr", 0xe5, INSTR_RRE_RF },
-       { "eextr", 0xed, INSTR_RRE_RF },
        { "esdtr", 0xe7, INSTR_RRE_RF },
+       { "kxtr", 0xe8, INSTR_RRE_FF },
+       { { 0, LONG_INSN_CGXTRA }, 0xe9, INSTR_RRF_UUFR },
+       { "cuxtr", 0xea, INSTR_RRE_RF },
+       { "csxtr", 0xeb, INSTR_RRE_RF },
+       { "cxtr", 0xec, INSTR_RRE_FF },
+       { "eextr", 0xed, INSTR_RRE_RF },
        { "esxtr", 0xef, INSTR_RRE_RF },
-       { "iedtr", 0xf6, INSTR_RRF_F0FR },
-       { "iextr", 0xfe, INSTR_RRF_F0FR },
-       { "ltdtr", 0xd6, INSTR_RRE_FF },
-       { "ltxtr", 0xde, INSTR_RRE_FF },
-       { "fidtr", 0xd7, INSTR_RRF_UUFF },
-       { "fixtr", 0xdf, INSTR_RRF_UUFF },
-       { "ldetr", 0xd4, INSTR_RRF_0UFF },
-       { "lxdtr", 0xdc, INSTR_RRF_0UFF },
-       { "ledtr", 0xd5, INSTR_RRF_UUFF },
-       { "ldxtr", 0xdd, INSTR_RRF_UUFF },
-       { "mdtr", 0xd0, INSTR_RRR_F0FF },
-       { "mxtr", 0xd8, INSTR_RRR_F0FF },
+       { { 0, LONG_INSN_CDGTRA }, 0xf1, INSTR_RRF_UUFR },
+       { "cdutr", 0xf2, INSTR_RRE_FR },
+       { "cdstr", 0xf3, INSTR_RRE_FR },
+       { "cedtr", 0xf4, INSTR_RRE_FF },
        { "qadtr", 0xf5, INSTR_RRF_FUFF },
-       { "qaxtr", 0xfd, INSTR_RRF_FUFF },
+       { "iedtr", 0xf6, INSTR_RRF_F0FR },
        { "rrdtr", 0xf7, INSTR_RRF_FFRU },
+       { { 0, LONG_INSN_CXGTRA }, 0xf9, INSTR_RRF_UURF },
+       { "cxutr", 0xfa, INSTR_RRE_FR },
+       { "cxstr", 0xfb, INSTR_RRE_FR },
+       { "cextr", 0xfc, INSTR_RRE_FF },
+       { "qaxtr", 0xfd, INSTR_RRF_FUFF },
+       { "iextr", 0xfe, INSTR_RRF_F0FR },
        { "rrxtr", 0xff, INSTR_RRF_FFRU },
-       { "sfasr", 0x85, INSTR_RRE_R0 },
-       { "sdtr", 0xd3, INSTR_RRR_F0FF },
-       { "sxtr", 0xdb, INSTR_RRR_F0FF },
 #endif
        { "lpebr", 0x00, INSTR_RRE_FF },
        { "lnebr", 0x01, INSTR_RRE_FF },
@@ -827,10 +987,10 @@ static struct insn opcode_b3[] = {
        { "lnxbr", 0x41, INSTR_RRE_FF },
        { "ltxbr", 0x42, INSTR_RRE_FF },
        { "lcxbr", 0x43, INSTR_RRE_FF },
-       { "ledbr", 0x44, INSTR_RRE_FF },
-       { "ldxbr", 0x45, INSTR_RRE_FF },
-       { "lexbr", 0x46, INSTR_RRE_FF },
-       { "fixbr", 0x47, INSTR_RRF_U0FF },
+       { { 0, LONG_INSN_LEDBRA }, 0x44, INSTR_RRF_UUFF },
+       { { 0, LONG_INSN_LDXBRA }, 0x45, INSTR_RRF_UUFF },
+       { { 0, LONG_INSN_LEXBRA }, 0x46, INSTR_RRF_UUFF },
+       { { 0, LONG_INSN_FIXBRA }, 0x47, INSTR_RRF_UUFF },
        { "kxbr", 0x48, INSTR_RRE_FF },
        { "cxbr", 0x49, INSTR_RRE_FF },
        { "axbr", 0x4a, INSTR_RRE_FF },
@@ -840,24 +1000,24 @@ static struct insn opcode_b3[] = {
        { "tbedr", 0x50, INSTR_RRF_U0FF },
        { "tbdr", 0x51, INSTR_RRF_U0FF },
        { "diebr", 0x53, INSTR_RRF_FUFF },
-       { "fiebr", 0x57, INSTR_RRF_U0FF },
-       { "thder", 0x58, INSTR_RRE_RR },
-       { "thdr", 0x59, INSTR_RRE_RR },
+       { { 0, LONG_INSN_FIEBRA }, 0x57, INSTR_RRF_UUFF },
+       { "thder", 0x58, INSTR_RRE_FF },
+       { "thdr", 0x59, INSTR_RRE_FF },
        { "didbr", 0x5b, INSTR_RRF_FUFF },
-       { "fidbr", 0x5f, INSTR_RRF_U0FF },
+       { { 0, LONG_INSN_FIDBRA }, 0x5f, INSTR_RRF_UUFF },
        { "lpxr", 0x60, INSTR_RRE_FF },
        { "lnxr", 0x61, INSTR_RRE_FF },
        { "ltxr", 0x62, INSTR_RRE_FF },
        { "lcxr", 0x63, INSTR_RRE_FF },
-       { "lxr", 0x65, INSTR_RRE_RR },
+       { "lxr", 0x65, INSTR_RRE_FF },
        { "lexr", 0x66, INSTR_RRE_FF },
-       { "fixr", 0x67, INSTR_RRF_U0FF },
+       { "fixr", 0x67, INSTR_RRE_FF },
        { "cxr", 0x69, INSTR_RRE_FF },
-       { "lzer", 0x74, INSTR_RRE_R0 },
-       { "lzdr", 0x75, INSTR_RRE_R0 },
-       { "lzxr", 0x76, INSTR_RRE_R0 },
-       { "fier", 0x77, INSTR_RRF_U0FF },
-       { "fidr", 0x7f, INSTR_RRF_U0FF },
+       { "lzer", 0x74, INSTR_RRE_F0 },
+       { "lzdr", 0x75, INSTR_RRE_F0 },
+       { "lzxr", 0x76, INSTR_RRE_F0 },
+       { "fier", 0x77, INSTR_RRE_FF },
+       { "fidr", 0x7f, INSTR_RRE_FF },
        { "sfpc", 0x84, INSTR_RRE_RR_OPT },
        { "efpc", 0x8c, INSTR_RRE_RR_OPT },
        { "cefbr", 0x94, INSTR_RRE_RF },
@@ -866,9 +1026,12 @@ static struct insn opcode_b3[] = {
        { "cfebr", 0x98, INSTR_RRF_U0RF },
        { "cfdbr", 0x99, INSTR_RRF_U0RF },
        { "cfxbr", 0x9a, INSTR_RRF_U0RF },
-       { "cefr", 0xb4, INSTR_RRE_RF },
-       { "cdfr", 0xb5, INSTR_RRE_RF },
-       { "cxfr", 0xb6, INSTR_RRE_RF },
+       { "cefr", 0xb4, INSTR_RRE_FR },
+       { "cdfr", 0xb5, INSTR_RRE_FR },
+       { "cxfr", 0xb6, INSTR_RRE_FR },
+       { "cfer", 0xb8, INSTR_RRF_U0RF },
+       { "cfdr", 0xb9, INSTR_RRF_U0RF },
+       { "cfxr", 0xba, INSTR_RRF_U0RF },
        { "", 0, INSTR_INVALID }
 };
 
@@ -910,7 +1073,23 @@ static struct insn opcode_b9[] = {
        { "lhr", 0x27, INSTR_RRE_RR },
        { "cgfr", 0x30, INSTR_RRE_RR },
        { "clgfr", 0x31, INSTR_RRE_RR },
+       { "cfdtr", 0x41, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLGDTR }, 0x42, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLFDTR }, 0x43, INSTR_RRF_UURF },
        { "bctgr", 0x46, INSTR_RRE_RR },
+       { "cfxtr", 0x49, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CLGXTR }, 0x4a, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CLFXTR }, 0x4b, INSTR_RRF_UUFR },
+       { "cdftr", 0x51, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CDLGTR }, 0x52, INSTR_RRF_UUFR },
+       { { 0, LONG_INSN_CDLFTR }, 0x53, INSTR_RRF_UUFR },
+       { "cxftr", 0x59, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CXLGTR }, 0x5a, INSTR_RRF_UURF },
+       { { 0, LONG_INSN_CXLFTR }, 0x5b, INSTR_RRF_UUFR },
+       { "cgrt", 0x60, INSTR_RRF_U0RR },
+       { "clgrt", 0x61, INSTR_RRF_U0RR },
+       { "crt", 0x72, INSTR_RRF_U0RR },
+       { "clrt", 0x73, INSTR_RRF_U0RR },
        { "ngr", 0x80, INSTR_RRE_RR },
        { "ogr", 0x81, INSTR_RRE_RR },
        { "xgr", 0x82, INSTR_RRE_RR },
@@ -923,32 +1102,34 @@ static struct insn opcode_b9[] = {
        { "slbgr", 0x89, INSTR_RRE_RR },
        { "cspg", 0x8a, INSTR_RRE_RR },
        { "idte", 0x8e, INSTR_RRF_R0RR },
+       { "crdte", 0x8f, INSTR_RRF_RMRR },
        { "llcr", 0x94, INSTR_RRE_RR },
        { "llhr", 0x95, INSTR_RRE_RR },
        { "esea", 0x9d, INSTR_RRE_R0 },
+       { "ptf", 0xa2, INSTR_RRE_R0 },
        { "lptea", 0xaa, INSTR_RRF_RURR },
+       { "rrbm", 0xae, INSTR_RRE_RR },
+       { "pfmf", 0xaf, INSTR_RRE_RR },
        { "cu14", 0xb0, INSTR_RRF_M0RR },
        { "cu24", 0xb1, INSTR_RRF_M0RR },
-       { "cu41", 0xb2, INSTR_RRF_M0RR },
-       { "cu42", 0xb3, INSTR_RRF_M0RR },
-       { "crt", 0x72, INSTR_RRF_U0RR },
-       { "cgrt", 0x60, INSTR_RRF_U0RR },
-       { "clrt", 0x73, INSTR_RRF_U0RR },
-       { "clgrt", 0x61, INSTR_RRF_U0RR },
-       { "ptf", 0xa2, INSTR_RRE_R0 },
-       { "pfmf", 0xaf, INSTR_RRE_RR },
-       { "trte", 0xbf, INSTR_RRF_M0RR },
+       { "cu41", 0xb2, INSTR_RRE_RR },
+       { "cu42", 0xb3, INSTR_RRE_RR },
        { "trtre", 0xbd, INSTR_RRF_M0RR },
+       { "srstu", 0xbe, INSTR_RRE_RR },
+       { "trte", 0xbf, INSTR_RRF_M0RR },
        { "ahhhr", 0xc8, INSTR_RRF_R0RR2 },
        { "shhhr", 0xc9, INSTR_RRF_R0RR2 },
-       { "alhhh", 0xca, INSTR_RRF_R0RR2 },
-       { "alhhl", 0xca, INSTR_RRF_R0RR2 },
-       { "slhhh", 0xcb, INSTR_RRF_R0RR2 },
-       { "chhr ", 0xcd, INSTR_RRE_RR },
+       { { 0, LONG_INSN_ALHHHR }, 0xca, INSTR_RRF_R0RR2 },
+       { { 0, LONG_INSN_SLHHHR }, 0xcb, INSTR_RRF_R0RR2 },
+       { "chhr", 0xcd, INSTR_RRE_RR },
        { "clhhr", 0xcf, INSTR_RRE_RR },
+       { { 0, LONG_INSN_PCISTG }, 0xd0, INSTR_RRE_RR },
+       { "pcilg", 0xd2, INSTR_RRE_RR },
+       { "rpcit", 0xd3, INSTR_RRE_RR },
        { "ahhlr", 0xd8, INSTR_RRF_R0RR2 },
        { "shhlr", 0xd9, INSTR_RRF_R0RR2 },
-       { "slhhl", 0xdb, INSTR_RRF_R0RR2 },
+       { { 0, LONG_INSN_ALHHLR }, 0xda, INSTR_RRF_R0RR2 },
+       { { 0, LONG_INSN_SLHHLR }, 0xdb, INSTR_RRF_R0RR2 },
        { "chlr", 0xdd, INSTR_RRE_RR },
        { "clhlr", 0xdf, INSTR_RRE_RR },
        { { 0, LONG_INSN_POPCNT }, 0xe1, INSTR_RRE_RR },
@@ -976,13 +1157,9 @@ static struct insn opcode_b9[] = {
        { "kimd", 0x3e, INSTR_RRE_RR },
        { "klmd", 0x3f, INSTR_RRE_RR },
        { "epsw", 0x8d, INSTR_RRE_RR },
-       { "trtt", 0x90, INSTR_RRE_RR },
        { "trtt", 0x90, INSTR_RRF_M0RR },
-       { "trto", 0x91, INSTR_RRE_RR },
        { "trto", 0x91, INSTR_RRF_M0RR },
-       { "trot", 0x92, INSTR_RRE_RR },
        { "trot", 0x92, INSTR_RRF_M0RR },
-       { "troo", 0x93, INSTR_RRE_RR },
        { "troo", 0x93, INSTR_RRF_M0RR },
        { "mlr", 0x96, INSTR_RRE_RR },
        { "dlr", 0x97, INSTR_RRE_RR },
@@ -1013,6 +1190,8 @@ static struct insn opcode_c0[] = {
 
 static struct insn opcode_c2[] = {
 #ifdef CONFIG_64BIT
+       { "msgfi", 0x00, INSTR_RIL_RI },
+       { "msfi", 0x01, INSTR_RIL_RI },
        { "slgfi", 0x04, INSTR_RIL_RU },
        { "slfi", 0x05, INSTR_RIL_RU },
        { "agfi", 0x08, INSTR_RIL_RI },
@@ -1023,43 +1202,41 @@ static struct insn opcode_c2[] = {
        { "cfi", 0x0d, INSTR_RIL_RI },
        { "clgfi", 0x0e, INSTR_RIL_RU },
        { "clfi", 0x0f, INSTR_RIL_RU },
-       { "msfi", 0x01, INSTR_RIL_RI },
-       { "msgfi", 0x00, INSTR_RIL_RI },
 #endif
        { "", 0, INSTR_INVALID }
 };
 
 static struct insn opcode_c4[] = {
 #ifdef CONFIG_64BIT
-       { "lrl", 0x0d, INSTR_RIL_RP },
+       { "llhrl", 0x02, INSTR_RIL_RP },
+       { "lghrl", 0x04, INSTR_RIL_RP },
+       { "lhrl", 0x05, INSTR_RIL_RP },
+       { { 0, LONG_INSN_LLGHRL }, 0x06, INSTR_RIL_RP },
+       { "sthrl", 0x07, INSTR_RIL_RP },
        { "lgrl", 0x08, INSTR_RIL_RP },
+       { "stgrl", 0x0b, INSTR_RIL_RP },
        { "lgfrl", 0x0c, INSTR_RIL_RP },
-       { "lhrl", 0x05, INSTR_RIL_RP },
-       { "lghrl", 0x04, INSTR_RIL_RP },
+       { "lrl", 0x0d, INSTR_RIL_RP },
        { { 0, LONG_INSN_LLGFRL }, 0x0e, INSTR_RIL_RP },
-       { "llhrl", 0x02, INSTR_RIL_RP },
-       { { 0, LONG_INSN_LLGHRL }, 0x06, INSTR_RIL_RP },
        { "strl", 0x0f, INSTR_RIL_RP },
-       { "stgrl", 0x0b, INSTR_RIL_RP },
-       { "sthrl", 0x07, INSTR_RIL_RP },
 #endif
        { "", 0, INSTR_INVALID }
 };
 
 static struct insn opcode_c6[] = {
 #ifdef CONFIG_64BIT
-       { "crl", 0x0d, INSTR_RIL_RP },
-       { "cgrl", 0x08, INSTR_RIL_RP },
-       { "cgfrl", 0x0c, INSTR_RIL_RP },
-       { "chrl", 0x05, INSTR_RIL_RP },
+       { "exrl", 0x00, INSTR_RIL_RP },
+       { "pfdrl", 0x02, INSTR_RIL_UP },
        { "cghrl", 0x04, INSTR_RIL_RP },
-       { "clrl", 0x0f, INSTR_RIL_RP },
+       { "chrl", 0x05, INSTR_RIL_RP },
+       { { 0, LONG_INSN_CLGHRL }, 0x06, INSTR_RIL_RP },
+       { "clhrl", 0x07, INSTR_RIL_RP },
+       { "cgrl", 0x08, INSTR_RIL_RP },
        { "clgrl", 0x0a, INSTR_RIL_RP },
+       { "cgfrl", 0x0c, INSTR_RIL_RP },
+       { "crl", 0x0d, INSTR_RIL_RP },
        { { 0, LONG_INSN_CLGFRL }, 0x0e, INSTR_RIL_RP },
-       { "clhrl", 0x07, INSTR_RIL_RP },
-       { { 0, LONG_INSN_CLGHRL }, 0x06, INSTR_RIL_RP },
-       { "pfdrl", 0x02, INSTR_RIL_UP },
-       { "exrl", 0x00, INSTR_RIL_RP },
+       { "clrl", 0x0f, INSTR_RIL_RP },
 #endif
        { "", 0, INSTR_INVALID }
 };
@@ -1070,7 +1247,7 @@ static struct insn opcode_c8[] = {
        { "ectg", 0x01, INSTR_SSF_RRDRD },
        { "csst", 0x02, INSTR_SSF_RRDRD },
        { "lpd", 0x04, INSTR_SSF_RRDRD2 },
-       { "lpdg ", 0x05, INSTR_SSF_RRDRD2 },
+       { "lpdg", 0x05, INSTR_SSF_RRDRD2 },
 #endif
        { "", 0, INSTR_INVALID }
 };
@@ -1080,9 +1257,9 @@ static struct insn opcode_cc[] = {
        { "brcth", 0x06, INSTR_RIL_RP },
        { "aih", 0x08, INSTR_RIL_RI },
        { "alsih", 0x0a, INSTR_RIL_RI },
-       { "alsih", 0x0b, INSTR_RIL_RI },
+       { { 0, LONG_INSN_ALSIHN }, 0x0b, INSTR_RIL_RI },
        { "cih", 0x0d, INSTR_RIL_RI },
-       { "clih ", 0x0f, INSTR_RIL_RI },
+       { "clih", 0x0f, INSTR_RIL_RI },
 #endif
        { "", 0, INSTR_INVALID }
 };
@@ -1116,11 +1293,15 @@ static struct insn opcode_e3[] = {
        { "cg", 0x20, INSTR_RXY_RRRD },
        { "clg", 0x21, INSTR_RXY_RRRD },
        { "stg", 0x24, INSTR_RXY_RRRD },
+       { "ntstg", 0x25, INSTR_RXY_RRRD },
        { "cvdy", 0x26, INSTR_RXY_RRRD },
        { "cvdg", 0x2e, INSTR_RXY_RRRD },
        { "strvg", 0x2f, INSTR_RXY_RRRD },
        { "cgf", 0x30, INSTR_RXY_RRRD },
        { "clgf", 0x31, INSTR_RXY_RRRD },
+       { "ltgf", 0x32, INSTR_RXY_RRRD },
+       { "cgh", 0x34, INSTR_RXY_RRRD },
+       { "pfd", 0x36, INSTR_RXY_URRD },
        { "strvh", 0x3f, INSTR_RXY_RRRD },
        { "bctg", 0x46, INSTR_RXY_RRRD },
        { "sty", 0x50, INSTR_RXY_RRRD },
@@ -1133,21 +1314,25 @@ static struct insn opcode_e3[] = {
        { "cy", 0x59, INSTR_RXY_RRRD },
        { "ay", 0x5a, INSTR_RXY_RRRD },
        { "sy", 0x5b, INSTR_RXY_RRRD },
+       { "mfy", 0x5c, INSTR_RXY_RRRD },
        { "aly", 0x5e, INSTR_RXY_RRRD },
        { "sly", 0x5f, INSTR_RXY_RRRD },
        { "sthy", 0x70, INSTR_RXY_RRRD },
        { "lay", 0x71, INSTR_RXY_RRRD },
        { "stcy", 0x72, INSTR_RXY_RRRD },
        { "icy", 0x73, INSTR_RXY_RRRD },
+       { "laey", 0x75, INSTR_RXY_RRRD },
        { "lb", 0x76, INSTR_RXY_RRRD },
        { "lgb", 0x77, INSTR_RXY_RRRD },
        { "lhy", 0x78, INSTR_RXY_RRRD },
        { "chy", 0x79, INSTR_RXY_RRRD },
        { "ahy", 0x7a, INSTR_RXY_RRRD },
        { "shy", 0x7b, INSTR_RXY_RRRD },
+       { "mhy", 0x7c, INSTR_RXY_RRRD },
        { "ng", 0x80, INSTR_RXY_RRRD },
        { "og", 0x81, INSTR_RXY_RRRD },
        { "xg", 0x82, INSTR_RXY_RRRD },
+       { "lgat", 0x85, INSTR_RXY_RRRD },
        { "mlg", 0x86, INSTR_RXY_RRRD },
        { "dlg", 0x87, INSTR_RXY_RRRD },
        { "alcg", 0x88, INSTR_RXY_RRRD },
@@ -1158,23 +1343,22 @@ static struct insn opcode_e3[] = {
        { "llgh", 0x91, INSTR_RXY_RRRD },
        { "llc", 0x94, INSTR_RXY_RRRD },
        { "llh", 0x95, INSTR_RXY_RRRD },
-       { "cgh", 0x34, INSTR_RXY_RRRD },
-       { "laey", 0x75, INSTR_RXY_RRRD },
-       { "ltgf", 0x32, INSTR_RXY_RRRD },
-       { "mfy", 0x5c, INSTR_RXY_RRRD },
-       { "mhy", 0x7c, INSTR_RXY_RRRD },
-       { "pfd", 0x36, INSTR_RXY_URRD },
+       { { 0, LONG_INSN_LLGTAT }, 0x9c, INSTR_RXY_RRRD },
+       { { 0, LONG_INSN_LLGFAT }, 0x9d, INSTR_RXY_RRRD },
+       { "lat", 0x9f, INSTR_RXY_RRRD },
        { "lbh", 0xc0, INSTR_RXY_RRRD },
        { "llch", 0xc2, INSTR_RXY_RRRD },
        { "stch", 0xc3, INSTR_RXY_RRRD },
        { "lhh", 0xc4, INSTR_RXY_RRRD },
        { "llhh", 0xc6, INSTR_RXY_RRRD },
        { "sthh", 0xc7, INSTR_RXY_RRRD },
+       { "lfhat", 0xc8, INSTR_RXY_RRRD },
        { "lfh", 0xca, INSTR_RXY_RRRD },
        { "stfh", 0xcb, INSTR_RXY_RRRD },
        { "chf", 0xcd, INSTR_RXY_RRRD },
        { "clhf", 0xcf, INSTR_RXY_RRRD },
-       { "ntstg", 0x25, INSTR_RXY_RRRD },
+       { { 0, LONG_INSN_MPCIFC }, 0xd0, INSTR_RXY_RRRD },
+       { { 0, LONG_INSN_STPCIFC }, 0xd4, INSTR_RXY_RRRD },
 #endif
        { "lrv", 0x1e, INSTR_RXY_RRRD },
        { "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -1189,15 +1373,15 @@ static struct insn opcode_e3[] = {
 static struct insn opcode_e5[] = {
 #ifdef CONFIG_64BIT
        { "strag", 0x02, INSTR_SSE_RDRD },
+       { "mvhhi", 0x44, INSTR_SIL_RDI },
+       { "mvghi", 0x48, INSTR_SIL_RDI },
+       { "mvhi", 0x4c, INSTR_SIL_RDI },
        { "chhsi", 0x54, INSTR_SIL_RDI },
-       { "chsi", 0x5c, INSTR_SIL_RDI },
-       { "cghsi", 0x58, INSTR_SIL_RDI },
        { { 0, LONG_INSN_CLHHSI }, 0x55, INSTR_SIL_RDU },
-       { { 0, LONG_INSN_CLFHSI }, 0x5d, INSTR_SIL_RDU },
+       { "cghsi", 0x58, INSTR_SIL_RDI },
        { { 0, LONG_INSN_CLGHSI }, 0x59, INSTR_SIL_RDU },
-       { "mvhhi", 0x44, INSTR_SIL_RDI },
-       { "mvhi", 0x4c, INSTR_SIL_RDI },
-       { "mvghi", 0x48, INSTR_SIL_RDI },
+       { "chsi", 0x5c, INSTR_SIL_RDI },
+       { { 0, LONG_INSN_CLFHSI }, 0x5d, INSTR_SIL_RDU },
        { { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU },
        { { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU },
 #endif
@@ -1220,9 +1404,11 @@ static struct insn opcode_eb[] = {
        { "rllg", 0x1c, INSTR_RSY_RRRD },
        { "clmh", 0x20, INSTR_RSY_RURD },
        { "clmy", 0x21, INSTR_RSY_RURD },
+       { "clt", 0x23, INSTR_RSY_RURD },
        { "stmg", 0x24, INSTR_RSY_RRRD },
        { "stctg", 0x25, INSTR_RSY_CCRD },
        { "stmh", 0x26, INSTR_RSY_RRRD },
+       { "clgt", 0x2b, INSTR_RSY_RURD },
        { "stcmh", 0x2c, INSTR_RSY_RURD },
        { "stcmy", 0x2d, INSTR_RSY_RURD },
        { "lctlg", 0x2f, INSTR_RSY_CCRD },
@@ -1231,16 +1417,17 @@ static struct insn opcode_eb[] = {
        { "cdsg", 0x3e, INSTR_RSY_RRRD },
        { "bxhg", 0x44, INSTR_RSY_RRRD },
        { "bxleg", 0x45, INSTR_RSY_RRRD },
+       { "ecag", 0x4c, INSTR_RSY_RRRD },
        { "tmy", 0x51, INSTR_SIY_URD },
        { "mviy", 0x52, INSTR_SIY_URD },
        { "niy", 0x54, INSTR_SIY_URD },
        { "cliy", 0x55, INSTR_SIY_URD },
        { "oiy", 0x56, INSTR_SIY_URD },
        { "xiy", 0x57, INSTR_SIY_URD },
-       { "lric", 0x60, INSTR_RSY_RDRM },
-       { "stric", 0x61, INSTR_RSY_RDRM },
-       { "mric", 0x62, INSTR_RSY_RDRM },
-       { "icmh", 0x80, INSTR_RSE_RURD },
+       { "asi", 0x6a, INSTR_SIY_IRD },
+       { "alsi", 0x6e, INSTR_SIY_IRD },
+       { "agsi", 0x7a, INSTR_SIY_IRD },
+       { "algsi", 0x7e, INSTR_SIY_IRD },
        { "icmh", 0x80, INSTR_RSY_RURD },
        { "icmy", 0x81, INSTR_RSY_RURD },
        { "clclu", 0x8f, INSTR_RSY_RRRD },
@@ -1249,11 +1436,8 @@ static struct insn opcode_eb[] = {
        { "lmy", 0x98, INSTR_RSY_RRRD },
        { "lamy", 0x9a, INSTR_RSY_AARD },
        { "stamy", 0x9b, INSTR_RSY_AARD },
-       { "asi", 0x6a, INSTR_SIY_IRD },
-       { "agsi", 0x7a, INSTR_SIY_IRD },
-       { "alsi", 0x6e, INSTR_SIY_IRD },
-       { "algsi", 0x7e, INSTR_SIY_IRD },
-       { "ecag", 0x4c, INSTR_RSY_RRRD },
+       { { 0, LONG_INSN_PCISTB }, 0xd0, INSTR_RSY_RRRD },
+       { "sic", 0xd1, INSTR_RSY_RRRD },
        { "srak", 0xdc, INSTR_RSY_RRRD },
        { "slak", 0xdd, INSTR_RSY_RRRD },
        { "srlk", 0xde, INSTR_RSY_RRRD },
@@ -1272,6 +1456,9 @@ static struct insn opcode_eb[] = {
        { "lax", 0xf7, INSTR_RSY_RRRD },
        { "laa", 0xf8, INSTR_RSY_RRRD },
        { "laal", 0xfa, INSTR_RSY_RRRD },
+       { "lric", 0x60, INSTR_RSY_RDRM },
+       { "stric", 0x61, INSTR_RSY_RDRM },
+       { "mric", 0x62, INSTR_RSY_RDRM },
 #endif
        { "rll", 0x1d, INSTR_RSY_RRRD },
        { "mvclu", 0x8e, INSTR_RSY_RRRD },
@@ -1283,36 +1470,37 @@ static struct insn opcode_ec[] = {
 #ifdef CONFIG_64BIT
        { "brxhg", 0x44, INSTR_RIE_RRP },
        { "brxlg", 0x45, INSTR_RIE_RRP },
-       { "crb", 0xf6, INSTR_RRS_RRRDU },
-       { "cgrb", 0xe4, INSTR_RRS_RRRDU },
-       { "crj", 0x76, INSTR_RIE_RRPU },
+       { { 0, LONG_INSN_RISBLG }, 0x51, INSTR_RIE_RRUUU },
+       { "rnsbg", 0x54, INSTR_RIE_RRUUU },
+       { "risbg", 0x55, INSTR_RIE_RRUUU },
+       { "rosbg", 0x56, INSTR_RIE_RRUUU },
+       { "rxsbg", 0x57, INSTR_RIE_RRUUU },
+       { { 0, LONG_INSN_RISBGN }, 0x59, INSTR_RIE_RRUUU },
+       { { 0, LONG_INSN_RISBHG }, 0x5D, INSTR_RIE_RRUUU },
        { "cgrj", 0x64, INSTR_RIE_RRPU },
-       { "cib", 0xfe, INSTR_RIS_RURDI },
-       { "cgib", 0xfc, INSTR_RIS_RURDI },
-       { "cij", 0x7e, INSTR_RIE_RUPI },
-       { "cgij", 0x7c, INSTR_RIE_RUPI },
-       { "cit", 0x72, INSTR_RIE_R0IU },
+       { "clgrj", 0x65, INSTR_RIE_RRPU },
        { "cgit", 0x70, INSTR_RIE_R0IU },
-       { "clrb", 0xf7, INSTR_RRS_RRRDU },
-       { "clgrb", 0xe5, INSTR_RRS_RRRDU },
+       { "clgit", 0x71, INSTR_RIE_R0UU },
+       { "cit", 0x72, INSTR_RIE_R0IU },
+       { "clfit", 0x73, INSTR_RIE_R0UU },
+       { "crj", 0x76, INSTR_RIE_RRPU },
        { "clrj", 0x77, INSTR_RIE_RRPU },
-       { "clgrj", 0x65, INSTR_RIE_RRPU },
-       { "clib", 0xff, INSTR_RIS_RURDU },
-       { "clgib", 0xfd, INSTR_RIS_RURDU },
-       { "clij", 0x7f, INSTR_RIE_RUPU },
+       { "cgij", 0x7c, INSTR_RIE_RUPI },
        { "clgij", 0x7d, INSTR_RIE_RUPU },
-       { "clfit", 0x73, INSTR_RIE_R0UU },
-       { "clgit", 0x71, INSTR_RIE_R0UU },
-       { "rnsbg", 0x54, INSTR_RIE_RRUUU },
-       { "rxsbg", 0x57, INSTR_RIE_RRUUU },
-       { "rosbg", 0x56, INSTR_RIE_RRUUU },
-       { "risbg", 0x55, INSTR_RIE_RRUUU },
-       { { 0, LONG_INSN_RISBLG }, 0x51, INSTR_RIE_RRUUU },
-       { { 0, LONG_INSN_RISBHG }, 0x5D, INSTR_RIE_RRUUU },
+       { "cij", 0x7e, INSTR_RIE_RUPI },
+       { "clij", 0x7f, INSTR_RIE_RUPU },
        { "ahik", 0xd8, INSTR_RIE_RRI0 },
        { "aghik", 0xd9, INSTR_RIE_RRI0 },
        { { 0, LONG_INSN_ALHSIK }, 0xda, INSTR_RIE_RRI0 },
        { { 0, LONG_INSN_ALGHSIK }, 0xdb, INSTR_RIE_RRI0 },
+       { "cgrb", 0xe4, INSTR_RRS_RRRDU },
+       { "clgrb", 0xe5, INSTR_RRS_RRRDU },
+       { "crb", 0xf6, INSTR_RRS_RRRDU },
+       { "clrb", 0xf7, INSTR_RRS_RRRDU },
+       { "cgib", 0xfc, INSTR_RIS_RURDI },
+       { "clgib", 0xfd, INSTR_RIS_RURDU },
+       { "cib", 0xfe, INSTR_RIS_RURDI },
+       { "clib", 0xff, INSTR_RIS_RURDU },
 #endif
        { "", 0, INSTR_INVALID }
 };
@@ -1325,20 +1513,24 @@ static struct insn opcode_ed[] = {
        { "my", 0x3b, INSTR_RXF_FRRDF },
        { "mayh", 0x3c, INSTR_RXF_FRRDF },
        { "myh", 0x3d, INSTR_RXF_FRRDF },
-       { "ley", 0x64, INSTR_RXY_FRRD },
-       { "ldy", 0x65, INSTR_RXY_FRRD },
-       { "stey", 0x66, INSTR_RXY_FRRD },
-       { "stdy", 0x67, INSTR_RXY_FRRD },
        { "sldt", 0x40, INSTR_RXF_FRRDF },
-       { "slxt", 0x48, INSTR_RXF_FRRDF },
        { "srdt", 0x41, INSTR_RXF_FRRDF },
+       { "slxt", 0x48, INSTR_RXF_FRRDF },
        { "srxt", 0x49, INSTR_RXF_FRRDF },
        { "tdcet", 0x50, INSTR_RXE_FRRD },
-       { "tdcdt", 0x54, INSTR_RXE_FRRD },
-       { "tdcxt", 0x58, INSTR_RXE_FRRD },
        { "tdget", 0x51, INSTR_RXE_FRRD },
+       { "tdcdt", 0x54, INSTR_RXE_FRRD },
        { "tdgdt", 0x55, INSTR_RXE_FRRD },
+       { "tdcxt", 0x58, INSTR_RXE_FRRD },
        { "tdgxt", 0x59, INSTR_RXE_FRRD },
+       { "ley", 0x64, INSTR_RXY_FRRD },
+       { "ldy", 0x65, INSTR_RXY_FRRD },
+       { "stey", 0x66, INSTR_RXY_FRRD },
+       { "stdy", 0x67, INSTR_RXY_FRRD },
+       { "czdt", 0xa8, INSTR_RSL_LRDFU },
+       { "czxt", 0xa9, INSTR_RSL_LRDFU },
+       { "cdzt", 0xaa, INSTR_RSL_LRDFU },
+       { "cxzt", 0xab, INSTR_RSL_LRDFU },
 #endif
        { "ldeb", 0x04, INSTR_RXE_FRRD },
        { "lxdb", 0x05, INSTR_RXE_FRRD },
index aa8f2ba6289b2da57b409cbaec0a3a596206001a..55022852326748599c4a8f4a74e77468e3d1f5a3 100644 (file)
@@ -231,12 +231,12 @@ sysc_work:
        jo      sysc_mcck_pending
        tm      __TI_flags+3(%r12),_TIF_NEED_RESCHED
        jo      sysc_reschedule
+       tm      __TI_flags+3(%r12),_TIF_PER_TRAP
+       jo      sysc_singlestep
        tm      __TI_flags+3(%r12),_TIF_SIGPENDING
        jo      sysc_sigpending
        tm      __TI_flags+3(%r12),_TIF_NOTIFY_RESUME
        jo      sysc_notify_resume
-       tm      __TI_flags+3(%r12),_TIF_PER_TRAP
-       jo      sysc_singlestep
        j       sysc_return             # beware of critical section cleanup
 
 #
@@ -259,7 +259,6 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-       ni      __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
        lr      %r2,%r11                # pass pointer to pt_regs
        l       %r1,BASED(.Ldo_signal)
        basr    %r14,%r1                # call do_signal
@@ -286,7 +285,7 @@ sysc_notify_resume:
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-       ni      __TI_flags+3(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
+       ni      __TI_flags+3(%r12),255-_TIF_PER_TRAP
        lr      %r2,%r11                # pass pointer to pt_regs
        l       %r1,BASED(.Ldo_per_trap)
        la      %r14,BASED(sysc_return)
index d8251b98f17a4ef3d925e0eb6bd8495be4d24eac..2711936fe70624e9a4f7be2e7980e4a8745a013d 100644 (file)
@@ -6,7 +6,6 @@
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
 
-extern void (*pgm_check_table[128])(struct pt_regs *);
 extern void *restart_stack;
 
 void system_call(void);
@@ -25,6 +24,26 @@ void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
 void do_asce_exception(struct pt_regs *regs);
 
+void addressing_exception(struct pt_regs *regs);
+void data_exception(struct pt_regs *regs);
+void default_trap_handler(struct pt_regs *regs);
+void divide_exception(struct pt_regs *regs);
+void execute_exception(struct pt_regs *regs);
+void hfp_divide_exception(struct pt_regs *regs);
+void hfp_overflow_exception(struct pt_regs *regs);
+void hfp_significance_exception(struct pt_regs *regs);
+void hfp_sqrt_exception(struct pt_regs *regs);
+void hfp_underflow_exception(struct pt_regs *regs);
+void illegal_op(struct pt_regs *regs);
+void operand_exception(struct pt_regs *regs);
+void overflow_exception(struct pt_regs *regs);
+void privileged_op(struct pt_regs *regs);
+void space_switch_exception(struct pt_regs *regs);
+void special_op_exception(struct pt_regs *regs);
+void specification_exception(struct pt_regs *regs);
+void transaction_exception(struct pt_regs *regs);
+void translation_exception(struct pt_regs *regs);
+
 void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
index 499e95e90f38d9d785609a3c0ed2d1e41a5c8f15..6d34e0c97a3948fde034acedabfec98af203e64b 100644 (file)
@@ -80,14 +80,21 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 #endif
        .endm
 
-       .macro  HANDLE_SIE_INTERCEPT scratch
+       .macro  HANDLE_SIE_INTERCEPT scratch,pgmcheck
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
        tmhh    %r8,0x0001              # interrupting from user ?
        jnz     .+42
        lgr     \scratch,%r9
        slg     \scratch,BASED(.Lsie_loop)
        clg     \scratch,BASED(.Lsie_length)
+       .if     \pgmcheck
+       # Some program interrupts are suppressing (e.g. protection).
+       # We must also check the instruction after SIE in that case.
+       # do_protection_exception will rewind to rewind_pad
+       jh      .+22
+       .else
        jhe     .+22
+       .endif
        lg      %r9,BASED(.Lsie_loop)
        SPP     BASED(.Lhost_id)        # set host id
 #endif
@@ -262,12 +269,12 @@ sysc_work:
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r12),_TIF_NEED_RESCHED
        jo      sysc_reschedule
+       tm      __TI_flags+7(%r12),_TIF_PER_TRAP
+       jo      sysc_singlestep
        tm      __TI_flags+7(%r12),_TIF_SIGPENDING
        jo      sysc_sigpending
        tm      __TI_flags+7(%r12),_TIF_NOTIFY_RESUME
        jo      sysc_notify_resume
-       tm      __TI_flags+7(%r12),_TIF_PER_TRAP
-       jo      sysc_singlestep
        j       sysc_return             # beware of critical section cleanup
 
 #
@@ -288,7 +295,6 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-       ni      __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
        lgr     %r2,%r11                # pass pointer to pt_regs
        brasl   %r14,do_signal
        tm      __TI_flags+7(%r12),_TIF_SYSCALL
@@ -313,7 +319,7 @@ sysc_notify_resume:
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-       ni      __TI_flags+7(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
+       ni      __TI_flags+7(%r12),255-_TIF_PER_TRAP
        lgr     %r2,%r11                # pass pointer to pt_regs
        larl    %r14,sysc_return
        jg      do_per_trap
@@ -375,7 +381,7 @@ ENTRY(pgm_check_handler)
        lg      %r12,__LC_THREAD_INFO
        larl    %r13,system_call
        lmg     %r8,%r9,__LC_PGM_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14
+       HANDLE_SIE_INTERCEPT %r14,1
        tmhh    %r8,0x0001              # test problem state bit
        jnz     1f                      # -> fault in user space
        tmhh    %r8,0x4000              # PER bit set in old PSW ?
@@ -413,9 +419,9 @@ ENTRY(pgm_check_handler)
        larl    %r1,pgm_check_table
        llgh    %r10,__PT_INT_CODE+2(%r11)
        nill    %r10,0x007f
-       sll     %r10,3
+       sll     %r10,2
        je      sysc_return
-       lg      %r1,0(%r10,%r1)         # load address of handler routine
+       lgf     %r1,0(%r10,%r1)         # load address of handler routine
        lgr     %r2,%r11                # pass pointer to pt_regs
        basr    %r14,%r1                # branch to interrupt-handler
        j       sysc_return
@@ -451,7 +457,7 @@ ENTRY(io_int_handler)
        lg      %r12,__LC_THREAD_INFO
        larl    %r13,system_call
        lmg     %r8,%r9,__LC_IO_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14
+       HANDLE_SIE_INTERCEPT %r14,0
        SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
        tmhh    %r8,0x0001              # interrupting from user?
        jz      io_skip
@@ -597,7 +603,7 @@ ENTRY(ext_int_handler)
        lg      %r12,__LC_THREAD_INFO
        larl    %r13,system_call
        lmg     %r8,%r9,__LC_EXT_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14
+       HANDLE_SIE_INTERCEPT %r14,0
        SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
        tmhh    %r8,0x0001              # interrupting from user ?
        jz      ext_skip
@@ -645,7 +651,7 @@ ENTRY(mcck_int_handler)
        lg      %r12,__LC_THREAD_INFO
        larl    %r13,system_call
        lmg     %r8,%r9,__LC_MCK_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14
+       HANDLE_SIE_INTERCEPT %r14,0
        tm      __LC_MCCK_CODE,0x80     # system damage?
        jo      mcck_panic              # yes -> rest of mcck code invalid
        lghi    %r14,__LC_CPU_TIMER_SAVE_AREA
@@ -944,6 +950,13 @@ ENTRY(sie64a)
        stg     %r3,__SF_EMPTY+8(%r15)          # save guest register save area
        xc      __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
        lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
+# some program checks are suppressing. C code (e.g. do_protection_exception)
+# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
+# instructions in the sie_loop should not cause program interrupts. So
+# lets use a nop (47 00 00 00) as a landing pad.
+# See also HANDLE_SIE_INTERCEPT
+rewind_pad:
+       nop     0
 sie_loop:
        lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
        tm      __TI_flags+7(%r14),_TIF_EXIT_SIE
@@ -983,6 +996,7 @@ sie_fault:
 .Lhost_id:
        .quad   0
 
+       EX_TABLE(rewind_pad,sie_fault)
        EX_TABLE(sie_loop,sie_fault)
 #endif
 
index 984726cbce1607855672dbb6210d7b38b56ea122..fd8db63dfc942a211d9dfe95b8c2bff88b90ed8d 100644 (file)
@@ -393,30 +393,35 @@ ENTRY(startup_kdump)
        xc      0x300(256),0x300
        xc      0xe00(256),0xe00
        stck    __LC_LAST_UPDATE_CLOCK
-       spt     5f-.LPG0(%r13)
-       mvc     __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
+       spt     6f-.LPG0(%r13)
+       mvc     __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
        xc      __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
 #ifndef CONFIG_MARCH_G5
        # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
        .insn   s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list
        tm      __LC_STFL_FAC_LIST,0x01 # stfle available ?
        jz      0f
-       la      %r0,0
+       la      %r0,1
        .insn   s,0xb2b00000,__LC_STFL_FAC_LIST # store facility list extended
-0:     l       %r0,__LC_STFL_FAC_LIST
-       n       %r0,2f+8-.LPG0(%r13)
-       cl      %r0,2f+8-.LPG0(%r13)
-       jne     1f
-       l       %r0,__LC_STFL_FAC_LIST+4
-       n       %r0,2f+12-.LPG0(%r13)
-       cl      %r0,2f+12-.LPG0(%r13)
-       je      3f
-1:     l       %r15,.Lstack-.LPG0(%r13)
+       # verify if all required facilities are supported by the machine
+0:     la      %r1,__LC_STFL_FAC_LIST
+       la      %r2,3f+8-.LPG0(%r13)
+       l       %r3,0(%r2)
+1:     l       %r0,0(%r1)
+       n       %r0,4(%r2)
+       cl      %r0,4(%r2)
+       jne     2f
+       la      %r1,4(%r1)
+       la      %r2,4(%r2)
+       ahi     %r3,-1
+       jnz     1b
+       j       4f
+2:     l       %r15,.Lstack-.LPG0(%r13)
        ahi     %r15,-96
        la      %r2,.Lals_string-.LPG0(%r13)
        l       %r3,.Lsclp_print-.LPG0(%r13)
        basr    %r14,%r3
-       lpsw    2f-.LPG0(%r13)          # machine type not good enough, crash
+       lpsw    3f-.LPG0(%r13)          # machine type not good enough, crash
 .Lals_string:
        .asciz  "The Linux kernel requires more recent processor hardware"
 .Lsclp_print:
@@ -424,33 +429,42 @@ ENTRY(startup_kdump)
 .Lstack:
        .long   0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
        .align 16
-2:     .long   0x000a0000,0x8badcccc
+3:     .long   0x000a0000,0x8badcccc
+
+# List of facilities that are required. If not all facilities are present
+# the kernel will crash. Format is number of facility words with bits set,
+# followed by the facility words.
+
 #if defined(CONFIG_64BIT)
-#if defined(CONFIG_MARCH_Z196)
-       .long 0xc100efe3, 0xf46c0000
+#if defined(CONFIG_MARCH_ZEC12)
+       .long 3, 0xc100efe3, 0xf46ce000, 0x00400000
+#elif defined(CONFIG_MARCH_Z196)
+       .long 2, 0xc100efe3, 0xf46c0000
 #elif defined(CONFIG_MARCH_Z10)
-       .long 0xc100efe3, 0xf0680000
+       .long 2, 0xc100efe3, 0xf0680000
 #elif defined(CONFIG_MARCH_Z9_109)
-       .long 0xc100efc3, 0x00000000
+       .long 1, 0xc100efc3
 #elif defined(CONFIG_MARCH_Z990)
-       .long 0xc0002000, 0x00000000
+       .long 1, 0xc0002000
 #elif defined(CONFIG_MARCH_Z900)
-       .long 0xc0000000, 0x00000000
+       .long 1, 0xc0000000
 #endif
 #else
-#if defined(CONFIG_MARCH_Z196)
-       .long 0x8100c880, 0x00000000
+#if defined(CONFIG_MARCH_ZEC12)
+       .long 1, 0x8100c880
+#elif defined(CONFIG_MARCH_Z196)
+       .long 1, 0x8100c880
 #elif defined(CONFIG_MARCH_Z10)
-       .long 0x8100c880, 0x00000000
+       .long 1, 0x8100c880
 #elif defined(CONFIG_MARCH_Z9_109)
-       .long 0x8100c880, 0x00000000
+       .long 1, 0x8100c880
 #elif defined(CONFIG_MARCH_Z990)
-       .long 0x80002000, 0x00000000
+       .long 1, 0x80002000
 #elif defined(CONFIG_MARCH_Z900)
-       .long 0x80000000, 0x00000000
+       .long 1, 0x80000000
 #endif
 #endif
-3:
+4:
 #endif
 
 #ifdef CONFIG_64BIT
@@ -459,14 +473,14 @@ ENTRY(startup_kdump)
        jg      startup_continue
 #else
        /* Continue with 31bit startup code in head31.S */
-       l       %r13,4f-.LPG0(%r13)
+       l       %r13,5f-.LPG0(%r13)
        b       0(%r13)
        .align  8
-4:     .long   startup_continue
+5:     .long   startup_continue
 #endif
 
        .align  8
-5:     .long   0x7fffffff,0xffffffff
+6:     .long   0x7fffffff,0xffffffff
 
 #include "head_kdump.S"
 
index 6cdc55b26d68e5d94819f66aaebdc1ebc00fe959..bf24293970ce544b358f9bb3f4d4c7daa9bde88f 100644 (file)
@@ -58,6 +58,8 @@ static const struct irq_class intrclass_names[] = {
        [IOINT_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
        [IOINT_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
        [IOINT_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
+       [IOINT_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
+       [IOINT_MSI] =  {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
        [NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"},
 };
 
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
new file mode 100644 (file)
index 0000000..14bdecb
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *    Program check table.
+ *
+ *    Copyright IBM Corp. 2012
+ */
+
+#include <linux/linkage.h>
+
+#ifdef CONFIG_32BIT
+#define PGM_CHECK_64BIT(handler) .long default_trap_handler
+#else
+#define PGM_CHECK_64BIT(handler) .long handler
+#endif
+
+#define PGM_CHECK(handler)     .long handler
+#define PGM_CHECK_DEFAULT      PGM_CHECK(default_trap_handler)
+
+/*
+ * The program check table contains exactly 128 (0x00-0x7f) entries. Each
+ * line defines the 31 and/or 64 bit function to be called corresponding
+ * to the program check interruption code.
+ */
+.section .rodata, "a"
+ENTRY(pgm_check_table)
+PGM_CHECK_DEFAULT                      /* 00 */
+PGM_CHECK(illegal_op)                  /* 01 */
+PGM_CHECK(privileged_op)               /* 02 */
+PGM_CHECK(execute_exception)           /* 03 */
+PGM_CHECK(do_protection_exception)     /* 04 */
+PGM_CHECK(addressing_exception)                /* 05 */
+PGM_CHECK(specification_exception)     /* 06 */
+PGM_CHECK(data_exception)              /* 07 */
+PGM_CHECK(overflow_exception)          /* 08 */
+PGM_CHECK(divide_exception)            /* 09 */
+PGM_CHECK(overflow_exception)          /* 0a */
+PGM_CHECK(divide_exception)            /* 0b */
+PGM_CHECK(hfp_overflow_exception)      /* 0c */
+PGM_CHECK(hfp_underflow_exception)     /* 0d */
+PGM_CHECK(hfp_significance_exception)  /* 0e */
+PGM_CHECK(hfp_divide_exception)                /* 0f */
+PGM_CHECK(do_dat_exception)            /* 10 */
+PGM_CHECK(do_dat_exception)            /* 11 */
+PGM_CHECK(translation_exception)       /* 12 */
+PGM_CHECK(special_op_exception)                /* 13 */
+PGM_CHECK_DEFAULT                      /* 14 */
+PGM_CHECK(operand_exception)           /* 15 */
+PGM_CHECK_DEFAULT                      /* 16 */
+PGM_CHECK_DEFAULT                      /* 17 */
+PGM_CHECK_64BIT(transaction_exception) /* 18 */
+PGM_CHECK_DEFAULT                      /* 19 */
+PGM_CHECK_DEFAULT                      /* 1a */
+PGM_CHECK_DEFAULT                      /* 1b */
+PGM_CHECK(space_switch_exception)      /* 1c */
+PGM_CHECK(hfp_sqrt_exception)          /* 1d */
+PGM_CHECK_DEFAULT                      /* 1e */
+PGM_CHECK_DEFAULT                      /* 1f */
+PGM_CHECK_DEFAULT                      /* 20 */
+PGM_CHECK_DEFAULT                      /* 21 */
+PGM_CHECK_DEFAULT                      /* 22 */
+PGM_CHECK_DEFAULT                      /* 23 */
+PGM_CHECK_DEFAULT                      /* 24 */
+PGM_CHECK_DEFAULT                      /* 25 */
+PGM_CHECK_DEFAULT                      /* 26 */
+PGM_CHECK_DEFAULT                      /* 27 */
+PGM_CHECK_DEFAULT                      /* 28 */
+PGM_CHECK_DEFAULT                      /* 29 */
+PGM_CHECK_DEFAULT                      /* 2a */
+PGM_CHECK_DEFAULT                      /* 2b */
+PGM_CHECK_DEFAULT                      /* 2c */
+PGM_CHECK_DEFAULT                      /* 2d */
+PGM_CHECK_DEFAULT                      /* 2e */
+PGM_CHECK_DEFAULT                      /* 2f */
+PGM_CHECK_DEFAULT                      /* 30 */
+PGM_CHECK_DEFAULT                      /* 31 */
+PGM_CHECK_DEFAULT                      /* 32 */
+PGM_CHECK_DEFAULT                      /* 33 */
+PGM_CHECK_DEFAULT                      /* 34 */
+PGM_CHECK_DEFAULT                      /* 35 */
+PGM_CHECK_DEFAULT                      /* 36 */
+PGM_CHECK_DEFAULT                      /* 37 */
+PGM_CHECK_64BIT(do_asce_exception)     /* 38 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 39 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 3a */
+PGM_CHECK_64BIT(do_dat_exception)      /* 3b */
+PGM_CHECK_DEFAULT                      /* 3c */
+PGM_CHECK_DEFAULT                      /* 3d */
+PGM_CHECK_DEFAULT                      /* 3e */
+PGM_CHECK_DEFAULT                      /* 3f */
+PGM_CHECK_DEFAULT                      /* 40 */
+PGM_CHECK_DEFAULT                      /* 41 */
+PGM_CHECK_DEFAULT                      /* 42 */
+PGM_CHECK_DEFAULT                      /* 43 */
+PGM_CHECK_DEFAULT                      /* 44 */
+PGM_CHECK_DEFAULT                      /* 45 */
+PGM_CHECK_DEFAULT                      /* 46 */
+PGM_CHECK_DEFAULT                      /* 47 */
+PGM_CHECK_DEFAULT                      /* 48 */
+PGM_CHECK_DEFAULT                      /* 49 */
+PGM_CHECK_DEFAULT                      /* 4a */
+PGM_CHECK_DEFAULT                      /* 4b */
+PGM_CHECK_DEFAULT                      /* 4c */
+PGM_CHECK_DEFAULT                      /* 4d */
+PGM_CHECK_DEFAULT                      /* 4e */
+PGM_CHECK_DEFAULT                      /* 4f */
+PGM_CHECK_DEFAULT                      /* 50 */
+PGM_CHECK_DEFAULT                      /* 51 */
+PGM_CHECK_DEFAULT                      /* 52 */
+PGM_CHECK_DEFAULT                      /* 53 */
+PGM_CHECK_DEFAULT                      /* 54 */
+PGM_CHECK_DEFAULT                      /* 55 */
+PGM_CHECK_DEFAULT                      /* 56 */
+PGM_CHECK_DEFAULT                      /* 57 */
+PGM_CHECK_DEFAULT                      /* 58 */
+PGM_CHECK_DEFAULT                      /* 59 */
+PGM_CHECK_DEFAULT                      /* 5a */
+PGM_CHECK_DEFAULT                      /* 5b */
+PGM_CHECK_DEFAULT                      /* 5c */
+PGM_CHECK_DEFAULT                      /* 5d */
+PGM_CHECK_DEFAULT                      /* 5e */
+PGM_CHECK_DEFAULT                      /* 5f */
+PGM_CHECK_DEFAULT                      /* 60 */
+PGM_CHECK_DEFAULT                      /* 61 */
+PGM_CHECK_DEFAULT                      /* 62 */
+PGM_CHECK_DEFAULT                      /* 63 */
+PGM_CHECK_DEFAULT                      /* 64 */
+PGM_CHECK_DEFAULT                      /* 65 */
+PGM_CHECK_DEFAULT                      /* 66 */
+PGM_CHECK_DEFAULT                      /* 67 */
+PGM_CHECK_DEFAULT                      /* 68 */
+PGM_CHECK_DEFAULT                      /* 69 */
+PGM_CHECK_DEFAULT                      /* 6a */
+PGM_CHECK_DEFAULT                      /* 6b */
+PGM_CHECK_DEFAULT                      /* 6c */
+PGM_CHECK_DEFAULT                      /* 6d */
+PGM_CHECK_DEFAULT                      /* 6e */
+PGM_CHECK_DEFAULT                      /* 6f */
+PGM_CHECK_DEFAULT                      /* 70 */
+PGM_CHECK_DEFAULT                      /* 71 */
+PGM_CHECK_DEFAULT                      /* 72 */
+PGM_CHECK_DEFAULT                      /* 73 */
+PGM_CHECK_DEFAULT                      /* 74 */
+PGM_CHECK_DEFAULT                      /* 75 */
+PGM_CHECK_DEFAULT                      /* 76 */
+PGM_CHECK_DEFAULT                      /* 77 */
+PGM_CHECK_DEFAULT                      /* 78 */
+PGM_CHECK_DEFAULT                      /* 79 */
+PGM_CHECK_DEFAULT                      /* 7a */
+PGM_CHECK_DEFAULT                      /* 7b */
+PGM_CHECK_DEFAULT                      /* 7c */
+PGM_CHECK_DEFAULT                      /* 7d */
+PGM_CHECK_DEFAULT                      /* 7e */
+PGM_CHECK_DEFAULT                      /* 7f */
index b1f2be9aaaad7459b339af793e6e95d754543723..2568590973ad2e429f394ce4f6147211e7169b11 100644 (file)
@@ -777,40 +777,6 @@ 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;
@@ -889,7 +855,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);
-               init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
+               storage_key_init_range(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
        }
 
        psw_set_key(PAGE_DEFAULT_KEY);
@@ -1040,6 +1006,9 @@ static void __init setup_hwcaps(void)
        case 0x2818:
                strcpy(elf_platform, "z196");
                break;
+       case 0x2827:
+               strcpy(elf_platform, "zEC12");
+               break;
        }
 }
 
index d1259d875074179ff11b232258fcc36ef98b90c3..c3ff70a7b2472b5e91626d9aea6f366e217ace46 100644 (file)
@@ -461,6 +461,8 @@ void do_signal(struct pt_regs *regs)
                        /* Restart system call with magic TIF bit. */
                        regs->gprs[2] = regs->orig_gpr2;
                        set_thread_flag(TIF_SYSCALL);
+                       if (test_thread_flag(TIF_SINGLE_STEP))
+                               set_thread_flag(TIF_PER_TRAP);
                        break;
                }
        }
index dd55f7c2010448a5b842c741ac6d93fc673591da..f1aba87cceb8acfd7d47df98ad3cb0854e3db288 100644 (file)
@@ -29,48 +29,38 @@ struct mask_info {
        cpumask_t mask;
 };
 
-static int topology_enabled = 1;
+static void set_topology_timer(void);
 static void topology_work_fn(struct work_struct *work);
 static struct sysinfo_15_1_x *tl_info;
-static void set_topology_timer(void);
-static DECLARE_WORK(topology_work, topology_work_fn);
-/* topology_lock protects the core linked list */
-static DEFINE_SPINLOCK(topology_lock);
 
-static struct mask_info core_info;
-cpumask_t cpu_core_map[NR_CPUS];
-unsigned char cpu_core_id[NR_CPUS];
-unsigned char cpu_socket_id[NR_CPUS];
+static int topology_enabled = 1;
+static DECLARE_WORK(topology_work, topology_work_fn);
 
+/* topology_lock protects the socket and book linked lists */
+static DEFINE_SPINLOCK(topology_lock);
+static struct mask_info socket_info;
 static struct mask_info book_info;
-cpumask_t cpu_book_map[NR_CPUS];
-unsigned char cpu_book_id[NR_CPUS];
+
+struct cpu_topology_s390 cpu_topology[NR_CPUS];
 
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
        cpumask_t mask;
 
-       cpumask_clear(&mask);
-       if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) {
-               cpumask_copy(&mask, cpumask_of(cpu));
+       cpumask_copy(&mask, cpumask_of(cpu));
+       if (!topology_enabled || !MACHINE_HAS_TOPOLOGY)
                return mask;
+       for (; info; info = info->next) {
+               if (cpumask_test_cpu(cpu, &info->mask))
+                       return info->mask;
        }
-       while (info) {
-               if (cpumask_test_cpu(cpu, &info->mask)) {
-                       mask = info->mask;
-                       break;
-               }
-               info = info->next;
-       }
-       if (cpumask_empty(&mask))
-               cpumask_copy(&mask, cpumask_of(cpu));
        return mask;
 }
 
 static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
                                          struct mask_info *book,
-                                         struct mask_info *core,
-                                         int one_core_per_cpu)
+                                         struct mask_info *socket,
+                                         int one_socket_per_cpu)
 {
        unsigned int cpu;
 
@@ -80,28 +70,28 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
 
                rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
                lcpu = smp_find_processor_id(rcpu);
-               if (lcpu >= 0) {
-                       cpumask_set_cpu(lcpu, &book->mask);
-                       cpu_book_id[lcpu] = book->id;
-                       cpumask_set_cpu(lcpu, &core->mask);
-                       cpu_core_id[lcpu] = rcpu;
-                       if (one_core_per_cpu) {
-                               cpu_socket_id[lcpu] = rcpu;
-                               core = core->next;
-                       } else {
-                               cpu_socket_id[lcpu] = core->id;
-                       }
-                       smp_cpu_set_polarization(lcpu, tl_cpu->pp);
+               if (lcpu < 0)
+                       continue;
+               cpumask_set_cpu(lcpu, &book->mask);
+               cpu_topology[lcpu].book_id = book->id;
+               cpumask_set_cpu(lcpu, &socket->mask);
+               cpu_topology[lcpu].core_id = rcpu;
+               if (one_socket_per_cpu) {
+                       cpu_topology[lcpu].socket_id = rcpu;
+                       socket = socket->next;
+               } else {
+                       cpu_topology[lcpu].socket_id = socket->id;
                }
+               smp_cpu_set_polarization(lcpu, tl_cpu->pp);
        }
-       return core;
+       return socket;
 }
 
 static void clear_masks(void)
 {
        struct mask_info *info;
 
-       info = &core_info;
+       info = &socket_info;
        while (info) {
                cpumask_clear(&info->mask);
                info = info->next;
@@ -120,9 +110,9 @@ static union topology_entry *next_tle(union topology_entry *tle)
        return (union topology_entry *)((struct topology_container *)tle + 1);
 }
 
-static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
+static void __tl_to_masks_generic(struct sysinfo_15_1_x *info)
 {
-       struct mask_info *core = &core_info;
+       struct mask_info *socket = &socket_info;
        struct mask_info *book = &book_info;
        union topology_entry *tle, *end;
 
@@ -135,11 +125,11 @@ static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
                        book->id = tle->container.id;
                        break;
                case 1:
-                       core = core->next;
-                       core->id = tle->container.id;
+                       socket = socket->next;
+                       socket->id = tle->container.id;
                        break;
                case 0:
-                       add_cpus_to_mask(&tle->cpu, book, core, 0);
+                       add_cpus_to_mask(&tle->cpu, book, socket, 0);
                        break;
                default:
                        clear_masks();
@@ -149,9 +139,9 @@ static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
        }
 }
 
-static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
+static void __tl_to_masks_z10(struct sysinfo_15_1_x *info)
 {
-       struct mask_info *core = &core_info;
+       struct mask_info *socket = &socket_info;
        struct mask_info *book = &book_info;
        union topology_entry *tle, *end;
 
@@ -164,7 +154,7 @@ static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
                        book->id = tle->container.id;
                        break;
                case 0:
-                       core = add_cpus_to_mask(&tle->cpu, book, core, 1);
+                       socket = add_cpus_to_mask(&tle->cpu, book, socket, 1);
                        break;
                default:
                        clear_masks();
@@ -174,20 +164,20 @@ static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
        }
 }
 
-static void tl_to_cores(struct sysinfo_15_1_x *info)
+static void tl_to_masks(struct sysinfo_15_1_x *info)
 {
        struct cpuid cpu_id;
 
-       get_cpu_id(&cpu_id);
        spin_lock_irq(&topology_lock);
+       get_cpu_id(&cpu_id);
        clear_masks();
        switch (cpu_id.machine) {
        case 0x2097:
        case 0x2098:
-               __tl_to_cores_z10(info);
+               __tl_to_masks_z10(info);
                break;
        default:
-               __tl_to_cores_generic(info);
+               __tl_to_masks_generic(info);
        }
        spin_unlock_irq(&topology_lock);
 }
@@ -232,15 +222,20 @@ int topology_set_cpu_management(int fc)
        return rc;
 }
 
-static void update_cpu_core_map(void)
+static void update_cpu_masks(void)
 {
        unsigned long flags;
        int cpu;
 
        spin_lock_irqsave(&topology_lock, flags);
        for_each_possible_cpu(cpu) {
-               cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
-               cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
+               cpu_topology[cpu].core_mask = cpu_group_map(&socket_info, cpu);
+               cpu_topology[cpu].book_mask = cpu_group_map(&book_info, cpu);
+               if (!MACHINE_HAS_TOPOLOGY) {
+                       cpu_topology[cpu].core_id = cpu;
+                       cpu_topology[cpu].socket_id = cpu;
+                       cpu_topology[cpu].book_id = cpu;
+               }
        }
        spin_unlock_irqrestore(&topology_lock, flags);
 }
@@ -260,13 +255,13 @@ int arch_update_cpu_topology(void)
        int cpu;
 
        if (!MACHINE_HAS_TOPOLOGY) {
-               update_cpu_core_map();
+               update_cpu_masks();
                topology_update_polarization_simple();
                return 0;
        }
        store_topology(info);
-       tl_to_cores(info);
-       update_cpu_core_map();
+       tl_to_masks(info);
+       update_cpu_masks();
        for_each_online_cpu(cpu) {
                dev = get_cpu_device(cpu);
                kobject_uevent(&dev->kobj, KOBJ_CHANGE);
@@ -355,7 +350,7 @@ void __init s390_init_cpu_topology(void)
        for (i = 0; i < TOPOLOGY_NR_MAG; i++)
                printk(KERN_CONT " %d", info->mag[i]);
        printk(KERN_CONT " / %d\n", info->mnest);
-       alloc_masks(info, &core_info, 1);
+       alloc_masks(info, &socket_info, 1);
        alloc_masks(info, &book_info, 2);
 }
 
@@ -454,7 +449,7 @@ static int __init topology_init(void)
        }
        set_topology_timer();
 out:
-       update_cpu_core_map();
+       update_cpu_masks();
        return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
 }
 device_initcall(topology_init);
index 3d2b0fa37db09649f6bcf0861de452144c22b0da..70ecfc5fe8f0acc87b7fe0036df511f283b22dbe 100644 (file)
@@ -41,8 +41,6 @@
 #include <asm/ipl.h>
 #include "entry.h"
 
-void (*pgm_check_table[128])(struct pt_regs *regs);
-
 int show_unhandled_signals = 1;
 
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -350,7 +348,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
        force_sig_info(SIGTRAP, &info, current);
 }
 
-static void default_trap_handler(struct pt_regs *regs)
+void default_trap_handler(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
                report_user_fault(regs, SIGSEGV);
@@ -360,9 +358,9 @@ static void default_trap_handler(struct pt_regs *regs)
 }
 
 #define DO_ERROR_INFO(name, signr, sicode, str) \
-static void name(struct pt_regs *regs) \
-{ \
-       do_trap(regs, signr, sicode, str); \
+void name(struct pt_regs *regs)                        \
+{                                              \
+       do_trap(regs, signr, sicode, str);      \
 }
 
 DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
@@ -417,7 +415,7 @@ static inline void do_fp_trap(struct pt_regs *regs, int fpc)
        do_trap(regs, SIGFPE, si_code, "floating point exception");
 }
 
-static void __kprobes illegal_op(struct pt_regs *regs)
+void __kprobes illegal_op(struct pt_regs *regs)
 {
        siginfo_t info;
         __u8 opcode[6];
@@ -536,7 +534,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
              "specification exception");
 #endif
 
-static void data_exception(struct pt_regs *regs)
+void data_exception(struct pt_regs *regs)
 {
        __u16 __user *location;
        int signal = 0;
@@ -611,7 +609,7 @@ static void data_exception(struct pt_regs *regs)
                do_trap(regs, signal, ILL_ILLOPN, "data exception");
 }
 
-static void space_switch_exception(struct pt_regs *regs)
+void space_switch_exception(struct pt_regs *regs)
 {
        /* Set user psw back to home space mode. */
        if (user_mode(regs))
@@ -629,43 +627,7 @@ void __kprobes kernel_stack_overflow(struct pt_regs * regs)
        panic("Corrupt kernel stack, can't continue.");
 }
 
-/* init is done in lowcore.S and head.S */
-
 void __init trap_init(void)
 {
-        int i;
-
-        for (i = 0; i < 128; i++)
-          pgm_check_table[i] = &default_trap_handler;
-        pgm_check_table[1] = &illegal_op;
-        pgm_check_table[2] = &privileged_op;
-        pgm_check_table[3] = &execute_exception;
-        pgm_check_table[4] = &do_protection_exception;
-        pgm_check_table[5] = &addressing_exception;
-        pgm_check_table[6] = &specification_exception;
-        pgm_check_table[7] = &data_exception;
-        pgm_check_table[8] = &overflow_exception;
-        pgm_check_table[9] = &divide_exception;
-        pgm_check_table[0x0A] = &overflow_exception;
-        pgm_check_table[0x0B] = &divide_exception;
-        pgm_check_table[0x0C] = &hfp_overflow_exception;
-        pgm_check_table[0x0D] = &hfp_underflow_exception;
-        pgm_check_table[0x0E] = &hfp_significance_exception;
-        pgm_check_table[0x0F] = &hfp_divide_exception;
-        pgm_check_table[0x10] = &do_dat_exception;
-        pgm_check_table[0x11] = &do_dat_exception;
-        pgm_check_table[0x12] = &translation_exception;
-        pgm_check_table[0x13] = &special_op_exception;
-#ifdef CONFIG_64BIT
-       pgm_check_table[0x18] = &transaction_exception;
-       pgm_check_table[0x38] = &do_asce_exception;
-       pgm_check_table[0x39] = &do_dat_exception;
-       pgm_check_table[0x3A] = &do_dat_exception;
-        pgm_check_table[0x3B] = &do_dat_exception;
-#endif /* CONFIG_64BIT */
-        pgm_check_table[0x15] = &operand_exception;
-        pgm_check_table[0x1C] = &space_switch_exception;
-        pgm_check_table[0x1D] = &hfp_sqrt_exception;
-       /* Enable machine checks early. */
        local_mcck_enable();
 }
index ff1e2f8ef94a02146e9b90e56c7105f9e9b140f3..c30615e605ac6716a1f93ee8dc377f9691ee99e0 100644 (file)
@@ -629,10 +629,27 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
                break;
        case KVM_S390_SIGP_STOP:
        case KVM_S390_RESTART:
+               VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+               inti->type = s390int->type;
+               break;
        case KVM_S390_INT_EXTERNAL_CALL:
+               if (s390int->parm & 0xffff0000) {
+                       kfree(inti);
+                       return -EINVAL;
+               }
+               VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
+                          s390int->parm);
+               inti->type = s390int->type;
+               inti->extcall.code = s390int->parm;
+               break;
        case KVM_S390_INT_EMERGENCY:
-               VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+               if (s390int->parm & 0xffff0000) {
+                       kfree(inti);
+                       return -EINVAL;
+               }
+               VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
                inti->type = s390int->type;
+               inti->emerg.code = s390int->parm;
                break;
        case KVM_S390_INT_VIRTIO:
        case KVM_S390_INT_SERVICE:
index d91a95568002ce5353f2d1162b1eb057f3d4a6c7..c9011bfaabbe8594bdd6d3c63ce242a55897cff3 100644 (file)
@@ -355,6 +355,11 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
        atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 }
 
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
        atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
@@ -993,7 +998,7 @@ static int __init kvm_s390_init(void)
        }
        memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
        facilities[0] &= 0xff00fff3f47c0000ULL;
-       facilities[1] &= 0x201c000000000000ULL;
+       facilities[1] &= 0x001c000000000000ULL;
        return 0;
 }
 
index 1bea6d1f55ab334b86db2042d84c84e5f01231df..640bea12303c0a659bcbb235bf191aaee8da4c62 100644 (file)
@@ -2,9 +2,9 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y   := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
-           page-states.o gup.o extable.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
+obj-y          := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
+obj-y          += page-states.o gup.o extable.o pageattr.o
+
+obj-$(CONFIG_CMM)              += cmm.o
+obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
+obj-$(CONFIG_S390_PTDUMP)      += dump_pagetables.o
index cbc6668acb85e8dd5b6100410a1fcd887e97df1d..04e4892247d2081f1087897613d0028149133a72 100644 (file)
@@ -150,6 +150,7 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
 static void walk_pud_level(struct seq_file *m, struct pg_state *st,
                           pgd_t *pgd, unsigned long addr)
 {
+       unsigned int prot;
        pud_t *pud;
        int i;
 
@@ -157,7 +158,11 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
                st->current_address = addr;
                pud = pud_offset(pgd, addr);
                if (!pud_none(*pud))
-                       walk_pmd_level(m, st, pud, addr);
+                       if (pud_large(*pud)) {
+                               prot = pud_val(*pud) & _PAGE_RO;
+                               note_page(m, st, prot, 2);
+                       } else
+                               walk_pmd_level(m, st, pud, addr);
                else
                        note_page(m, st, _PAGE_INVALID, 2);
                addr += PUD_SIZE;
index 04ad4001a289e05c89d30b5d6aaad9573b2ca388..42601d6e166fe73db1e6e97382df8158212dd5d7 100644 (file)
 #define VM_FAULT_BADCONTEXT    0x010000
 #define VM_FAULT_BADMAP                0x020000
 #define VM_FAULT_BADACCESS     0x040000
-#define VM_FAULT_SIGNAL        0x080000
+#define VM_FAULT_SIGNAL                0x080000
 
-static unsigned long store_indication;
+static unsigned long store_indication __read_mostly;
 
-void fault_init(void)
+#ifdef CONFIG_64BIT
+static int __init fault_init(void)
 {
-       if (test_facility(2) && test_facility(75))
+       if (test_facility(75))
                store_indication = 0xc00;
+       return 0;
 }
+early_initcall(fault_init);
+#endif
 
 static inline int notify_page_fault(struct pt_regs *regs)
 {
@@ -273,10 +277,16 @@ static inline int do_exception(struct pt_regs *regs, int access)
        unsigned int flags;
        int fault;
 
+       tsk = current;
+       /*
+        * The instruction that caused the program check has
+        * been nullified. Don't signal single step via SIGTRAP.
+        */
+       clear_tsk_thread_flag(tsk, TIF_PER_TRAP);
+
        if (notify_page_fault(regs))
                return 0;
 
-       tsk = current;
        mm = tsk->mm;
        trans_exc_code = regs->int_parm_long;
 
@@ -372,11 +382,6 @@ retry:
                        goto retry;
                }
        }
-       /*
-        * The instruction that caused the program check will
-        * be repeated. Don't signal single step via SIGTRAP.
-        */
-       clear_tsk_thread_flag(tsk, TIF_PER_TRAP);
        fault = 0;
 out_up:
        up_read(&mm->mmap_sem);
@@ -423,6 +428,12 @@ void __kprobes do_asce_exception(struct pt_regs *regs)
        struct vm_area_struct *vma;
        unsigned long trans_exc_code;
 
+       /*
+        * The instruction that caused the program check has
+        * been nullified. Don't signal single step via SIGTRAP.
+        */
+       clear_tsk_thread_flag(current, TIF_PER_TRAP);
+
        trans_exc_code = regs->int_parm_long;
        if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
                goto no_context;
index 81e596c65dee089dac921691c6b3ecec9beff4e1..ae672f41c464101a6d39727209441481d7775eff 100644 (file)
@@ -125,7 +125,6 @@ void __init paging_init(void)
        max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
        free_area_init_nodes(max_zone_pfns);
-       fault_init();
 }
 
 void __init mem_init(void)
@@ -159,34 +158,6 @@ void __init mem_init(void)
               PFN_ALIGN((unsigned long)&_eshared) - 1);
 }
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-void kernel_map_pages(struct page *page, int numpages, int enable)
-{
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       unsigned long address;
-       int i;
-
-       for (i = 0; i < numpages; i++) {
-               address = page_to_phys(page + i);
-               pgd = pgd_offset_k(address);
-               pud = pud_offset(pgd, address);
-               pmd = pmd_offset(pud, address);
-               pte = pte_offset_kernel(pmd, address);
-               if (!enable) {
-                       __ptep_ipte(address, pte);
-                       pte_val(*pte) = _PAGE_TYPE_EMPTY;
-                       continue;
-               }
-               *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
-               /* Flush cpu write queue. */
-               mb();
-       }
-}
-#endif
-
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
        unsigned long addr = begin;
index 00be01c4b4f3fc3ee8242ea1e7b6921bfc6afc2a..29ccee3651f410b670f71e51deb4a6757e148b19 100644 (file)
@@ -2,11 +2,46 @@
  * Copyright IBM Corp. 2011
  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
  */
+#include <linux/hugetlb.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/hugetlb.h>
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
+#include <asm/page.h>
+
+void storage_key_init_range(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 pte_t *walk_page_table(unsigned long addr)
 {
@@ -19,7 +54,7 @@ static pte_t *walk_page_table(unsigned long addr)
        if (pgd_none(*pgdp))
                return NULL;
        pudp = pud_offset(pgdp, addr);
-       if (pud_none(*pudp))
+       if (pud_none(*pudp) || pud_large(*pudp))
                return NULL;
        pmdp = pmd_offset(pudp, addr);
        if (pmd_none(*pmdp) || pmd_large(*pmdp))
@@ -70,3 +105,46 @@ int set_memory_x(unsigned long addr, int numpages)
 {
        return 0;
 }
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+       unsigned long address;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       int i;
+
+       for (i = 0; i < numpages; i++) {
+               address = page_to_phys(page + i);
+               pgd = pgd_offset_k(address);
+               pud = pud_offset(pgd, address);
+               pmd = pmd_offset(pud, address);
+               pte = pte_offset_kernel(pmd, address);
+               if (!enable) {
+                       __ptep_ipte(address, pte);
+                       pte_val(*pte) = _PAGE_TYPE_EMPTY;
+                       continue;
+               }
+               *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
+       }
+}
+
+#ifdef CONFIG_HIBERNATION
+bool kernel_page_present(struct page *page)
+{
+       unsigned long addr;
+       int cc;
+
+       addr = page_to_phys(page);
+       asm volatile(
+               "       lra     %1,0(%1)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (cc), "+a" (addr) : : "cc");
+       return cc == 0;
+}
+#endif /* CONFIG_HIBERNATION */
+
+#endif /* CONFIG_DEBUG_PAGEALLOC */
index c8188a18af05b565e57304b02e153ed4629940d5..ae44d2a34313258b7a570a25cab979c24c4f5a20 100644 (file)
@@ -881,22 +881,6 @@ int s390_enable_sie(void)
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
 
-#if defined(CONFIG_DEBUG_PAGEALLOC) && defined(CONFIG_HIBERNATION)
-bool kernel_page_present(struct page *page)
-{
-       unsigned long addr;
-       int cc;
-
-       addr = page_to_phys(page);
-       asm volatile(
-               "       lra     %1,0(%1)\n"
-               "       ipm     %0\n"
-               "       srl     %0,28"
-               : "=d" (cc), "+a" (addr) : : "cc");
-       return cc == 0;
-}
-#endif /* CONFIG_HIBERNATION && CONFIG_DEBUG_PAGEALLOC */
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 int pmdp_clear_flush_young(struct vm_area_struct *vma, unsigned long address,
                           pmd_t *pmdp)
index 387c7c60b5b8d65a50bec087a54288a1cc913519..6ed1426d27c55ff893b22a9ae2d2876c8bccb3c5 100644 (file)
@@ -89,6 +89,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
        int ret = -ENOMEM;
 
        while (address < end) {
+               pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
                pg_dir = pgd_offset_k(address);
                if (pgd_none(*pg_dir)) {
                        pu_dir = vmem_pud_alloc();
@@ -96,18 +97,24 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                                goto out;
                        pgd_populate(&init_mm, pg_dir, pu_dir);
                }
-
                pu_dir = pud_offset(pg_dir, address);
+#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
+               if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
+                   !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) {
+                       pte_val(pte) |= _REGION3_ENTRY_LARGE;
+                       pte_val(pte) |= _REGION_ENTRY_TYPE_R3;
+                       pud_val(*pu_dir) = pte_val(pte);
+                       address += PUD_SIZE;
+                       continue;
+               }
+#endif
                if (pud_none(*pu_dir)) {
                        pm_dir = vmem_pmd_alloc();
                        if (!pm_dir)
                                goto out;
                        pud_populate(&init_mm, pu_dir, pm_dir);
                }
-
-               pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
                pm_dir = pmd_offset(pu_dir, address);
-
 #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
                if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
                    !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
@@ -160,6 +167,11 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
                        address += PUD_SIZE;
                        continue;
                }
+               if (pud_large(*pu_dir)) {
+                       pud_clear(pu_dir);
+                       address += PUD_SIZE;
+                       continue;
+               }
                pm_dir = pmd_offset(pu_dir, address);
                if (pmd_none(*pm_dir)) {
                        address += PMD_SIZE;
@@ -193,7 +205,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
        start_addr = (unsigned long) start;
        end_addr = (unsigned long) (start + nr);
 
-       for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
+       for (address = start_addr; address < end_addr;) {
                pg_dir = pgd_offset_k(address);
                if (pgd_none(*pg_dir)) {
                        pu_dir = vmem_pud_alloc();
@@ -212,10 +224,33 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 
                pm_dir = pmd_offset(pu_dir, address);
                if (pmd_none(*pm_dir)) {
+#ifdef CONFIG_64BIT
+                       /* Use 1MB frames for vmemmap if available. We always
+                        * use large frames even if they are only partially
+                        * used.
+                        * Otherwise we would have also page tables since
+                        * vmemmap_populate gets called for each section
+                        * separately. */
+                       if (MACHINE_HAS_EDAT1) {
+                               void *new_page;
+
+                               new_page = vmemmap_alloc_block(PMD_SIZE, node);
+                               if (!new_page)
+                                       goto out;
+                               pte = mk_pte_phys(__pa(new_page), PAGE_RW);
+                               pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
+                               pmd_val(*pm_dir) = pte_val(pte);
+                               address = (address + PMD_SIZE) & PMD_MASK;
+                               continue;
+                       }
+#endif
                        pt_dir = vmem_pte_alloc(address);
                        if (!pt_dir)
                                goto out;
                        pmd_populate(&init_mm, pm_dir, pt_dir);
+               } else if (pmd_large(*pm_dir)) {
+                       address = (address + PMD_SIZE) & PMD_MASK;
+                       continue;
                }
 
                pt_dir = pte_offset_kernel(pm_dir, address);
@@ -228,6 +263,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
                        pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
                        *pt_dir = pte;
                }
+               address += PAGE_SIZE;
        }
        memset(start, 0, nr * sizeof(struct page));
        ret = 0;
index 9b355b406afaafb924d52f9e8c853f0338a292a0..bb284419b0fd95a651348701516cf53a56ca2935 100644 (file)
@@ -341,6 +341,27 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
                /* lr %r5,%r4 */
                EMIT2(0x1854);
                break;
+       case BPF_S_ALU_MOD_X: /* A %= X */
+               jit->seen |= SEEN_XREG | SEEN_RET0;
+               /* ltr %r12,%r12 */
+               EMIT2(0x12cc);
+               /* jz <ret0> */
+               EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
+               /* lhi %r4,0 */
+               EMIT4(0xa7480000);
+               /* dr %r4,%r12 */
+               EMIT2(0x1d4c);
+               /* lr %r5,%r4 */
+               EMIT2(0x1854);
+               break;
+       case BPF_S_ALU_MOD_K: /* A %= K */
+               /* lhi %r4,0 */
+               EMIT4(0xa7480000);
+               /* d %r4,<d(K)>(%r13) */
+               EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
+               /* lr %r5,%r4 */
+               EMIT2(0x1854);
+               break;
        case BPF_S_ALU_AND_X: /* A &= X */
                jit->seen |= SEEN_XREG;
                /* nr %r5,%r12 */
@@ -368,10 +389,17 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
                        EMIT4_DISP(0x5650d000, EMIT_CONST(K));
                break;
        case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */
+       case BPF_S_ALU_XOR_X:
                jit->seen |= SEEN_XREG;
                /* xr %r5,%r12 */
                EMIT2(0x175c);
                break;
+       case BPF_S_ALU_XOR_K: /* A ^= K */
+               if (!K)
+                       break;
+               /* x %r5,<d(K)>(%r13) */
+               EMIT4_DISP(0x5750d000, EMIT_CONST(K));
+               break;
        case BPF_S_ALU_LSH_X: /* A <<= X; */
                jit->seen |= SEEN_XREG;
                /* sll %r5,0(%r12) */
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
new file mode 100644 (file)
index 0000000..ab0827b
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the s390 PCI subsystem.
+#
+
+obj-$(CONFIG_PCI)      += pci.o pci_dma.o pci_clp.o pci_msi.o \
+                          pci_sysfs.o pci_event.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
new file mode 100644 (file)
index 0000000..7ed38e5
--- /dev/null
@@ -0,0 +1,1103 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s):
+ *   Jan Glauber <jang@linux.vnet.ibm.com>
+ *
+ * The System z PCI code is a rewrite from a prototype by
+ * the following people (Kudoz!):
+ *   Alexander Schmidt
+ *   Christoph Raisch
+ *   Hannes Hering
+ *   Hoang-Nam Nguyen
+ *   Jan-Bernd Themann
+ *   Stefan Roscher
+ *   Thomas Klein
+ */
+
+#define COMPONENT "zPCI"
+#define pr_fmt(fmt) COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+
+#include <asm/isc.h>
+#include <asm/airq.h>
+#include <asm/facility.h>
+#include <asm/pci_insn.h>
+#include <asm/pci_clp.h>
+#include <asm/pci_dma.h>
+
+#define DEBUG                          /* enable pr_debug */
+
+#define        SIC_IRQ_MODE_ALL                0
+#define        SIC_IRQ_MODE_SINGLE             1
+
+#define ZPCI_NR_DMA_SPACES             1
+#define ZPCI_MSI_VEC_BITS              6
+#define ZPCI_NR_DEVICES                        CONFIG_PCI_NR_FUNCTIONS
+
+/* list of all detected zpci devices */
+LIST_HEAD(zpci_list);
+EXPORT_SYMBOL_GPL(zpci_list);
+DEFINE_MUTEX(zpci_list_lock);
+EXPORT_SYMBOL_GPL(zpci_list_lock);
+
+struct pci_hp_callback_ops hotplug_ops;
+EXPORT_SYMBOL_GPL(hotplug_ops);
+
+static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
+static DEFINE_SPINLOCK(zpci_domain_lock);
+
+struct callback {
+       irq_handler_t   handler;
+       void            *data;
+};
+
+struct zdev_irq_map {
+       unsigned long   aibv;           /* AI bit vector */
+       int             msi_vecs;       /* consecutive MSI-vectors used */
+       int             __unused;
+       struct callback cb[ZPCI_NR_MSI_VECS]; /* callback handler array */
+       spinlock_t      lock;           /* protect callbacks against de-reg */
+};
+
+struct intr_bucket {
+       /* amap of adapters, one bit per dev, corresponds to one irq nr */
+       unsigned long   *alloc;
+       /* AI summary bit, global page for all devices */
+       unsigned long   *aisb;
+       /* pointer to aibv and callback data in zdev */
+       struct zdev_irq_map *imap[ZPCI_NR_DEVICES];
+       /* protects the whole bucket struct */
+       spinlock_t      lock;
+};
+
+static struct intr_bucket *bucket;
+
+/* Adapter local summary indicator */
+static u8 *zpci_irq_si;
+
+static atomic_t irq_retries = ATOMIC_INIT(0);
+
+/* I/O Map */
+static DEFINE_SPINLOCK(zpci_iomap_lock);
+static DECLARE_BITMAP(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES);
+struct zpci_iomap_entry *zpci_iomap_start;
+EXPORT_SYMBOL_GPL(zpci_iomap_start);
+
+/* highest irq summary bit */
+static int __read_mostly aisb_max;
+
+static struct kmem_cache *zdev_irq_cache;
+
+static inline int irq_to_msi_nr(unsigned int irq)
+{
+       return irq & ZPCI_MSI_MASK;
+}
+
+static inline int irq_to_dev_nr(unsigned int irq)
+{
+       return irq >> ZPCI_MSI_VEC_BITS;
+}
+
+static inline struct zdev_irq_map *get_imap(unsigned int irq)
+{
+       return bucket->imap[irq_to_dev_nr(irq)];
+}
+
+struct zpci_dev *get_zdev(struct pci_dev *pdev)
+{
+       return (struct zpci_dev *) pdev->sysdata;
+}
+
+struct zpci_dev *get_zdev_by_fid(u32 fid)
+{
+       struct zpci_dev *tmp, *zdev = NULL;
+
+       mutex_lock(&zpci_list_lock);
+       list_for_each_entry(tmp, &zpci_list, entry) {
+               if (tmp->fid == fid) {
+                       zdev = tmp;
+                       break;
+               }
+       }
+       mutex_unlock(&zpci_list_lock);
+       return zdev;
+}
+
+bool zpci_fid_present(u32 fid)
+{
+       return (get_zdev_by_fid(fid) != NULL) ? true : false;
+}
+
+static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
+{
+       return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
+}
+
+int pci_domain_nr(struct pci_bus *bus)
+{
+       return ((struct zpci_dev *) bus->sysdata)->domain;
+}
+EXPORT_SYMBOL_GPL(pci_domain_nr);
+
+int pci_proc_domain(struct pci_bus *bus)
+{
+       return pci_domain_nr(bus);
+}
+EXPORT_SYMBOL_GPL(pci_proc_domain);
+
+/* Store PCI function information block */
+static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc)
+{
+       struct zpci_fib *fib;
+       u8 status, cc;
+
+       fib = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!fib)
+               return -ENOMEM;
+
+       do {
+               cc = __stpcifc(zdev->fh, 0, fib, &status);
+               if (cc == 2) {
+                       msleep(ZPCI_INSN_BUSY_DELAY);
+                       memset(fib, 0, PAGE_SIZE);
+               }
+       } while (cc == 2);
+
+       if (cc)
+               pr_err_once("%s: cc: %u  status: %u\n",
+                           __func__, cc, status);
+
+       /* Return PCI function controls */
+       *fc = fib->fc;
+
+       free_page((unsigned long) fib);
+       return (cc) ? -EIO : 0;
+}
+
+/* Modify PCI: Register adapter interruptions */
+static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb,
+                             u64 aibv)
+{
+       u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT);
+       struct zpci_fib *fib;
+       int rc;
+
+       fib = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!fib)
+               return -ENOMEM;
+
+       fib->isc = PCI_ISC;
+       fib->noi = zdev->irq_map->msi_vecs;
+       fib->sum = 1;           /* enable summary notifications */
+       fib->aibv = aibv;
+       fib->aibvo = 0;         /* every function has its own page */
+       fib->aisb = (u64) bucket->aisb + aisb / 8;
+       fib->aisbo = aisb & ZPCI_MSI_MASK;
+
+       rc = mpcifc_instr(req, fib);
+       pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi);
+
+       free_page((unsigned long) fib);
+       return rc;
+}
+
+struct mod_pci_args {
+       u64 base;
+       u64 limit;
+       u64 iota;
+};
+
+static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args)
+{
+       u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, fn);
+       struct zpci_fib *fib;
+       int rc;
+
+       /* The FIB must be available even if it's not used */
+       fib = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!fib)
+               return -ENOMEM;
+
+       fib->pba = args->base;
+       fib->pal = args->limit;
+       fib->iota = args->iota;
+
+       rc = mpcifc_instr(req, fib);
+       free_page((unsigned long) fib);
+       return rc;
+}
+
+/* Modify PCI: Register I/O address translation parameters */
+int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
+                      u64 base, u64 limit, u64 iota)
+{
+       struct mod_pci_args args = { base, limit, iota };
+
+       WARN_ON_ONCE(iota & 0x3fff);
+       args.iota |= ZPCI_IOTA_RTTO_FLAG;
+       return mod_pci(zdev, ZPCI_MOD_FC_REG_IOAT, dmaas, &args);
+}
+
+/* Modify PCI: Unregister I/O address translation parameters */
+int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
+{
+       struct mod_pci_args args = { 0, 0, 0 };
+
+       return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args);
+}
+
+/* Modify PCI: Unregister adapter interruptions */
+static int zpci_unregister_airq(struct zpci_dev *zdev)
+{
+       struct mod_pci_args args = { 0, 0, 0 };
+
+       return mod_pci(zdev, ZPCI_MOD_FC_DEREG_INT, 0, &args);
+}
+
+#define ZPCI_PCIAS_CFGSPC      15
+
+static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)
+{
+       u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len);
+       u64 data;
+       int rc;
+
+       rc = pcilg_instr(&data, req, offset);
+       data = data << ((8 - len) * 8);
+       data = le64_to_cpu(data);
+       if (!rc)
+               *val = (u32) data;
+       else
+               *val = 0xffffffff;
+       return rc;
+}
+
+static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
+{
+       u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len);
+       u64 data = val;
+       int rc;
+
+       data = cpu_to_le64(data);
+       data = data >> ((8 - len) * 8);
+       rc = pcistg_instr(data, req, offset);
+       return rc;
+}
+
+void synchronize_irq(unsigned int irq)
+{
+       /*
+        * Not needed, the handler is protected by a lock and IRQs that occur
+        * after the handler is deleted are just NOPs.
+        */
+}
+EXPORT_SYMBOL_GPL(synchronize_irq);
+
+void enable_irq(unsigned int irq)
+{
+       struct msi_desc *msi = irq_get_msi_desc(irq);
+
+       zpci_msi_set_mask_bits(msi, 1, 0);
+}
+EXPORT_SYMBOL_GPL(enable_irq);
+
+void disable_irq(unsigned int irq)
+{
+       struct msi_desc *msi = irq_get_msi_desc(irq);
+
+       zpci_msi_set_mask_bits(msi, 1, 1);
+}
+EXPORT_SYMBOL_GPL(disable_irq);
+
+void disable_irq_nosync(unsigned int irq)
+{
+       disable_irq(irq);
+}
+EXPORT_SYMBOL_GPL(disable_irq_nosync);
+
+unsigned long probe_irq_on(void)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(probe_irq_on);
+
+int probe_irq_off(unsigned long val)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(probe_irq_off);
+
+unsigned int probe_irq_mask(unsigned long val)
+{
+       return val;
+}
+EXPORT_SYMBOL_GPL(probe_irq_mask);
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
+
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+                                      resource_size_t size,
+                                      resource_size_t align)
+{
+       return 0;
+}
+
+/* combine single writes by using store-block insn */
+void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
+{
+       zpci_memcpy_toio(to, from, count);
+}
+
+/* Create a virtual mapping cookie for a PCI BAR */
+void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max)
+{
+       struct zpci_dev *zdev = get_zdev(pdev);
+       u64 addr;
+       int idx;
+
+       if ((bar & 7) != bar)
+               return NULL;
+
+       idx = zdev->bars[bar].map_idx;
+       spin_lock(&zpci_iomap_lock);
+       zpci_iomap_start[idx].fh = zdev->fh;
+       zpci_iomap_start[idx].bar = bar;
+       spin_unlock(&zpci_iomap_lock);
+
+       addr = ZPCI_IOMAP_ADDR_BASE | ((u64) idx << 48);
+       return (void __iomem *) addr;
+}
+EXPORT_SYMBOL_GPL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *pdev, void __iomem *addr)
+{
+       unsigned int idx;
+
+       idx = (((__force u64) addr) & ~ZPCI_IOMAP_ADDR_BASE) >> 48;
+       spin_lock(&zpci_iomap_lock);
+       zpci_iomap_start[idx].fh = 0;
+       zpci_iomap_start[idx].bar = 0;
+       spin_unlock(&zpci_iomap_lock);
+}
+EXPORT_SYMBOL_GPL(pci_iounmap);
+
+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+                   int size, u32 *val)
+{
+       struct zpci_dev *zdev = get_zdev_by_bus(bus);
+
+       if (!zdev || devfn != ZPCI_DEVFN)
+               return 0;
+       return zpci_cfg_load(zdev, where, val, size);
+}
+
+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+                    int size, u32 val)
+{
+       struct zpci_dev *zdev = get_zdev_by_bus(bus);
+
+       if (!zdev || devfn != ZPCI_DEVFN)
+               return 0;
+       return zpci_cfg_store(zdev, where, val, size);
+}
+
+static struct pci_ops pci_root_ops = {
+       .read = pci_read,
+       .write = pci_write,
+};
+
+/* store the last handled bit to implement fair scheduling of devices */
+static DEFINE_PER_CPU(unsigned long, next_sbit);
+
+static void zpci_irq_handler(void *dont, void *need)
+{
+       unsigned long sbit, mbit, last = 0, start = __get_cpu_var(next_sbit);
+       int rescan = 0, max = aisb_max;
+       struct zdev_irq_map *imap;
+
+       kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++;
+       sbit = start;
+
+scan:
+       /* find summary_bit */
+       for_each_set_bit_left_cont(sbit, bucket->aisb, max) {
+               clear_bit(63 - (sbit & 63), bucket->aisb + (sbit >> 6));
+               last = sbit;
+
+               /* find vector bit */
+               imap = bucket->imap[sbit];
+               for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) {
+                       kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++;
+                       clear_bit(63 - mbit, &imap->aibv);
+
+                       spin_lock(&imap->lock);
+                       if (imap->cb[mbit].handler)
+                               imap->cb[mbit].handler(mbit,
+                                       imap->cb[mbit].data);
+                       spin_unlock(&imap->lock);
+               }
+       }
+
+       if (rescan)
+               goto out;
+
+       /* scan the skipped bits */
+       if (start > 0) {
+               sbit = 0;
+               max = start;
+               start = 0;
+               goto scan;
+       }
+
+       /* enable interrupts again */
+       sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+
+       /* check again to not lose initiative */
+       rmb();
+       max = aisb_max;
+       sbit = find_first_bit_left(bucket->aisb, max);
+       if (sbit != max) {
+               atomic_inc(&irq_retries);
+               rescan++;
+               goto scan;
+       }
+out:
+       /* store next device bit to scan */
+       __get_cpu_var(next_sbit) = (++last >= aisb_max) ? 0 : last;
+}
+
+/* msi_vecs - number of requested interrupts, 0 place function to error state */
+static int zpci_setup_msi(struct pci_dev *pdev, int msi_vecs)
+{
+       struct zpci_dev *zdev = get_zdev(pdev);
+       unsigned int aisb, msi_nr;
+       struct msi_desc *msi;
+       int rc;
+
+       /* store the number of used MSI vectors */
+       zdev->irq_map->msi_vecs = min(msi_vecs, ZPCI_NR_MSI_VECS);
+
+       spin_lock(&bucket->lock);
+       aisb = find_first_zero_bit(bucket->alloc, PAGE_SIZE);
+       /* alloc map exhausted? */
+       if (aisb == PAGE_SIZE) {
+               spin_unlock(&bucket->lock);
+               return -EIO;
+       }
+       set_bit(aisb, bucket->alloc);
+       spin_unlock(&bucket->lock);
+
+       zdev->aisb = aisb;
+       if (aisb + 1 > aisb_max)
+               aisb_max = aisb + 1;
+
+       /* wire up IRQ shortcut pointer */
+       bucket->imap[zdev->aisb] = zdev->irq_map;
+       pr_debug("%s: imap[%u] linked to %p\n", __func__, zdev->aisb, zdev->irq_map);
+
+       /* TODO: irq number 0 wont be found if we return less than requested MSIs.
+        * ignore it for now and fix in common code.
+        */
+       msi_nr = aisb << ZPCI_MSI_VEC_BITS;
+
+       list_for_each_entry(msi, &pdev->msi_list, list) {
+               rc = zpci_setup_msi_irq(zdev, msi, msi_nr,
+                                         aisb << ZPCI_MSI_VEC_BITS);
+               if (rc)
+                       return rc;
+               msi_nr++;
+       }
+
+       rc = zpci_register_airq(zdev, aisb, (u64) &zdev->irq_map->aibv);
+       if (rc) {
+               clear_bit(aisb, bucket->alloc);
+               dev_err(&pdev->dev, "register MSI failed with: %d\n", rc);
+               return rc;
+       }
+       return (zdev->irq_map->msi_vecs == msi_vecs) ?
+               0 : zdev->irq_map->msi_vecs;
+}
+
+static void zpci_teardown_msi(struct pci_dev *pdev)
+{
+       struct zpci_dev *zdev = get_zdev(pdev);
+       struct msi_desc *msi;
+       int aisb, rc;
+
+       rc = zpci_unregister_airq(zdev);
+       if (rc) {
+               dev_err(&pdev->dev, "deregister MSI failed with: %d\n", rc);
+               return;
+       }
+
+       msi = list_first_entry(&pdev->msi_list, struct msi_desc, list);
+       aisb = irq_to_dev_nr(msi->irq);
+
+       list_for_each_entry(msi, &pdev->msi_list, list)
+               zpci_teardown_msi_irq(zdev, msi);
+
+       clear_bit(aisb, bucket->alloc);
+       if (aisb + 1 == aisb_max)
+               aisb_max--;
+}
+
+int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+       pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
+       if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
+               return -EINVAL;
+       return zpci_setup_msi(pdev, nvec);
+}
+
+void arch_teardown_msi_irqs(struct pci_dev *pdev)
+{
+       pr_info("%s: on pdev: %p\n", __func__, pdev);
+       zpci_teardown_msi(pdev);
+}
+
+static void zpci_map_resources(struct zpci_dev *zdev)
+{
+       struct pci_dev *pdev = zdev->pdev;
+       resource_size_t len;
+       int i;
+
+       for (i = 0; i < PCI_BAR_COUNT; i++) {
+               len = pci_resource_len(pdev, i);
+               if (!len)
+                       continue;
+               pdev->resource[i].start = (resource_size_t) pci_iomap(pdev, i, 0);
+               pdev->resource[i].end = pdev->resource[i].start + len - 1;
+               pr_debug("BAR%i: -> start: %Lx  end: %Lx\n",
+                       i, pdev->resource[i].start, pdev->resource[i].end);
+       }
+};
+
+static void zpci_unmap_resources(struct pci_dev *pdev)
+{
+       resource_size_t len;
+       int i;
+
+       for (i = 0; i < PCI_BAR_COUNT; i++) {
+               len = pci_resource_len(pdev, i);
+               if (!len)
+                       continue;
+               pci_iounmap(pdev, (void *) pdev->resource[i].start);
+       }
+};
+
+struct zpci_dev *zpci_alloc_device(void)
+{
+       struct zpci_dev *zdev;
+
+       /* Alloc memory for our private pci device data */
+       zdev = kzalloc(sizeof(*zdev), GFP_KERNEL);
+       if (!zdev)
+               return ERR_PTR(-ENOMEM);
+
+       /* Alloc aibv & callback space */
+       zdev->irq_map = kmem_cache_zalloc(zdev_irq_cache, GFP_KERNEL);
+       if (!zdev->irq_map)
+               goto error;
+       WARN_ON((u64) zdev->irq_map & 0xff);
+       return zdev;
+
+error:
+       kfree(zdev);
+       return ERR_PTR(-ENOMEM);
+}
+
+void zpci_free_device(struct zpci_dev *zdev)
+{
+       kmem_cache_free(zdev_irq_cache, zdev->irq_map);
+       kfree(zdev);
+}
+
+/* Called on removal of pci_dev, leaves zpci and bus device */
+static void zpci_remove_device(struct pci_dev *pdev)
+{
+       struct zpci_dev *zdev = get_zdev(pdev);
+
+       dev_info(&pdev->dev, "Removing device %u\n", zdev->domain);
+       zdev->state = ZPCI_FN_STATE_CONFIGURED;
+       zpci_dma_exit_device(zdev);
+       zpci_sysfs_remove_device(&pdev->dev);
+       zpci_unmap_resources(pdev);
+       list_del(&zdev->entry);         /* can be called from init */
+       zdev->pdev = NULL;
+}
+
+static void zpci_scan_devices(void)
+{
+       struct zpci_dev *zdev;
+
+       mutex_lock(&zpci_list_lock);
+       list_for_each_entry(zdev, &zpci_list, entry)
+               if (zdev->state == ZPCI_FN_STATE_CONFIGURED)
+                       zpci_scan_device(zdev);
+       mutex_unlock(&zpci_list_lock);
+}
+
+/*
+ * Too late for any s390 specific setup, since interrupts must be set up
+ * already which requires DMA setup too and the pci scan will access the
+ * config space, which only works if the function handle is enabled.
+ */
+int pcibios_enable_device(struct pci_dev *pdev, int mask)
+{
+       struct resource *res;
+       u16 cmd;
+       int i;
+
+       pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+
+       for (i = 0; i < PCI_BAR_COUNT; i++) {
+               res = &pdev->resource[i];
+
+               if (res->flags & IORESOURCE_IO)
+                       return -EINVAL;
+
+               if (res->flags & IORESOURCE_MEM)
+                       cmd |= PCI_COMMAND_MEMORY;
+       }
+       pci_write_config_word(pdev, PCI_COMMAND, cmd);
+       return 0;
+}
+
+void pcibios_disable_device(struct pci_dev *pdev)
+{
+       zpci_remove_device(pdev);
+       pdev->sysdata = NULL;
+}
+
+int pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+       return zpci_sysfs_add_device(&pdev->dev);
+}
+
+int zpci_request_irq(unsigned int irq, irq_handler_t handler, void *data)
+{
+       int msi_nr = irq_to_msi_nr(irq);
+       struct zdev_irq_map *imap;
+       struct msi_desc *msi;
+
+       msi = irq_get_msi_desc(irq);
+       if (!msi)
+               return -EIO;
+
+       imap = get_imap(irq);
+       spin_lock_init(&imap->lock);
+
+       pr_debug("%s: register handler for IRQ:MSI %d:%d\n", __func__, irq >> 6, msi_nr);
+       imap->cb[msi_nr].handler = handler;
+       imap->cb[msi_nr].data = data;
+
+       /*
+        * The generic MSI code returns with the interrupt disabled on the
+        * card, using the MSI mask bits. Firmware doesn't appear to unmask
+        * at that level, so we do it here by hand.
+        */
+       zpci_msi_set_mask_bits(msi, 1, 0);
+       return 0;
+}
+
+void zpci_free_irq(unsigned int irq)
+{
+       struct zdev_irq_map *imap = get_imap(irq);
+       int msi_nr = irq_to_msi_nr(irq);
+       unsigned long flags;
+
+       pr_debug("%s: for irq: %d\n", __func__, irq);
+
+       spin_lock_irqsave(&imap->lock, flags);
+       imap->cb[msi_nr].handler = NULL;
+       imap->cb[msi_nr].data = NULL;
+       spin_unlock_irqrestore(&imap->lock, flags);
+}
+
+int request_irq(unsigned int irq, irq_handler_t handler,
+               unsigned long irqflags, const char *devname, void *dev_id)
+{
+       pr_debug("%s: irq: %d  handler: %p  flags: %lx  dev: %s\n",
+               __func__, irq, handler, irqflags, devname);
+
+       return zpci_request_irq(irq, handler, dev_id);
+}
+EXPORT_SYMBOL_GPL(request_irq);
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+       zpci_free_irq(irq);
+}
+EXPORT_SYMBOL_GPL(free_irq);
+
+static int __init zpci_irq_init(void)
+{
+       int cpu, rc;
+
+       bucket = kzalloc(sizeof(*bucket), GFP_KERNEL);
+       if (!bucket)
+               return -ENOMEM;
+
+       bucket->aisb = (unsigned long *) get_zeroed_page(GFP_KERNEL);
+       if (!bucket->aisb) {
+               rc = -ENOMEM;
+               goto out_aisb;
+       }
+
+       bucket->alloc = (unsigned long *) get_zeroed_page(GFP_KERNEL);
+       if (!bucket->alloc) {
+               rc = -ENOMEM;
+               goto out_alloc;
+       }
+
+       isc_register(PCI_ISC);
+       zpci_irq_si = s390_register_adapter_interrupt(&zpci_irq_handler, NULL, PCI_ISC);
+       if (IS_ERR(zpci_irq_si)) {
+               rc = PTR_ERR(zpci_irq_si);
+               zpci_irq_si = NULL;
+               goto out_ai;
+       }
+
+       for_each_online_cpu(cpu)
+               per_cpu(next_sbit, cpu) = 0;
+
+       spin_lock_init(&bucket->lock);
+       /* set summary to 1 to be called every time for the ISC */
+       *zpci_irq_si = 1;
+       sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+       return 0;
+
+out_ai:
+       isc_unregister(PCI_ISC);
+       free_page((unsigned long) bucket->alloc);
+out_alloc:
+       free_page((unsigned long) bucket->aisb);
+out_aisb:
+       kfree(bucket);
+       return rc;
+}
+
+static void zpci_irq_exit(void)
+{
+       free_page((unsigned long) bucket->alloc);
+       free_page((unsigned long) bucket->aisb);
+       s390_unregister_adapter_interrupt(zpci_irq_si, PCI_ISC);
+       isc_unregister(PCI_ISC);
+       kfree(bucket);
+}
+
+static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size,
+                                               unsigned long flags, int domain)
+{
+       struct resource *r;
+       char *name;
+       int rc;
+
+       r = kzalloc(sizeof(*r), GFP_KERNEL);
+       if (!r)
+               return ERR_PTR(-ENOMEM);
+       r->start = start;
+       r->end = r->start + size - 1;
+       r->flags = flags;
+       r->parent = &iomem_resource;
+       name = kmalloc(18, GFP_KERNEL);
+       if (!name) {
+               kfree(r);
+               return ERR_PTR(-ENOMEM);
+       }
+       sprintf(name, "PCI Bus: %04x:%02x", domain, ZPCI_BUS_NR);
+       r->name = name;
+
+       rc = request_resource(&iomem_resource, r);
+       if (rc)
+               pr_debug("request resource %pR failed\n", r);
+       return r;
+}
+
+static int zpci_alloc_iomap(struct zpci_dev *zdev)
+{
+       int entry;
+
+       spin_lock(&zpci_iomap_lock);
+       entry = find_first_zero_bit(zpci_iomap, ZPCI_IOMAP_MAX_ENTRIES);
+       if (entry == ZPCI_IOMAP_MAX_ENTRIES) {
+               spin_unlock(&zpci_iomap_lock);
+               return -ENOSPC;
+       }
+       set_bit(entry, zpci_iomap);
+       spin_unlock(&zpci_iomap_lock);
+       return entry;
+}
+
+static void zpci_free_iomap(struct zpci_dev *zdev, int entry)
+{
+       spin_lock(&zpci_iomap_lock);
+       memset(&zpci_iomap_start[entry], 0, sizeof(struct zpci_iomap_entry));
+       clear_bit(entry, zpci_iomap);
+       spin_unlock(&zpci_iomap_lock);
+}
+
+static int zpci_create_device_bus(struct zpci_dev *zdev)
+{
+       struct resource *res;
+       LIST_HEAD(resources);
+       int i;
+
+       /* allocate mapping entry for each used bar */
+       for (i = 0; i < PCI_BAR_COUNT; i++) {
+               unsigned long addr, size, flags;
+               int entry;
+
+               if (!zdev->bars[i].size)
+                       continue;
+               entry = zpci_alloc_iomap(zdev);
+               if (entry < 0)
+                       return entry;
+               zdev->bars[i].map_idx = entry;
+
+               /* only MMIO is supported */
+               flags = IORESOURCE_MEM;
+               if (zdev->bars[i].val & 8)
+                       flags |= IORESOURCE_PREFETCH;
+               if (zdev->bars[i].val & 4)
+                       flags |= IORESOURCE_MEM_64;
+
+               addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48);
+
+               size = 1UL << zdev->bars[i].size;
+
+               res = zpci_alloc_bus_resource(addr, size, flags, zdev->domain);
+               if (IS_ERR(res)) {
+                       zpci_free_iomap(zdev, entry);
+                       return PTR_ERR(res);
+               }
+               pci_add_resource(&resources, res);
+       }
+
+       zdev->bus = pci_create_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
+                                       zdev, &resources);
+       if (!zdev->bus)
+               return -EIO;
+
+       zdev->bus->max_bus_speed = zdev->max_bus_speed;
+       return 0;
+}
+
+static int zpci_alloc_domain(struct zpci_dev *zdev)
+{
+       spin_lock(&zpci_domain_lock);
+       zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES);
+       if (zdev->domain == ZPCI_NR_DEVICES) {
+               spin_unlock(&zpci_domain_lock);
+               return -ENOSPC;
+       }
+       set_bit(zdev->domain, zpci_domain);
+       spin_unlock(&zpci_domain_lock);
+       return 0;
+}
+
+static void zpci_free_domain(struct zpci_dev *zdev)
+{
+       spin_lock(&zpci_domain_lock);
+       clear_bit(zdev->domain, zpci_domain);
+       spin_unlock(&zpci_domain_lock);
+}
+
+int zpci_enable_device(struct zpci_dev *zdev)
+{
+       int rc;
+
+       rc = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES);
+       if (rc)
+               goto out;
+       pr_info("Enabled fh: 0x%x fid: 0x%x\n", zdev->fh, zdev->fid);
+
+       rc = zpci_dma_init_device(zdev);
+       if (rc)
+               goto out_dma;
+       return 0;
+
+out_dma:
+       clp_disable_fh(zdev);
+out:
+       return rc;
+}
+EXPORT_SYMBOL_GPL(zpci_enable_device);
+
+int zpci_create_device(struct zpci_dev *zdev)
+{
+       int rc;
+
+       rc = zpci_alloc_domain(zdev);
+       if (rc)
+               goto out;
+
+       rc = zpci_create_device_bus(zdev);
+       if (rc)
+               goto out_bus;
+
+       mutex_lock(&zpci_list_lock);
+       list_add_tail(&zdev->entry, &zpci_list);
+       if (hotplug_ops.create_slot)
+               hotplug_ops.create_slot(zdev);
+       mutex_unlock(&zpci_list_lock);
+
+       if (zdev->state == ZPCI_FN_STATE_STANDBY)
+               return 0;
+
+       rc = zpci_enable_device(zdev);
+       if (rc)
+               goto out_start;
+       return 0;
+
+out_start:
+       mutex_lock(&zpci_list_lock);
+       list_del(&zdev->entry);
+       if (hotplug_ops.remove_slot)
+               hotplug_ops.remove_slot(zdev);
+       mutex_unlock(&zpci_list_lock);
+out_bus:
+       zpci_free_domain(zdev);
+out:
+       return rc;
+}
+
+void zpci_stop_device(struct zpci_dev *zdev)
+{
+       zpci_dma_exit_device(zdev);
+       /*
+        * Note: SCLP disables fh via set-pci-fn so don't
+        * do that here.
+        */
+}
+EXPORT_SYMBOL_GPL(zpci_stop_device);
+
+int zpci_scan_device(struct zpci_dev *zdev)
+{
+       zdev->pdev = pci_scan_single_device(zdev->bus, ZPCI_DEVFN);
+       if (!zdev->pdev) {
+               pr_err("pci_scan_single_device failed for fid: 0x%x\n",
+                       zdev->fid);
+               goto out;
+       }
+
+       zpci_map_resources(zdev);
+       pci_bus_add_devices(zdev->bus);
+
+       /* now that pdev was added to the bus mark it as used */
+       zdev->state = ZPCI_FN_STATE_ONLINE;
+       return 0;
+
+out:
+       zpci_dma_exit_device(zdev);
+       clp_disable_fh(zdev);
+       return -EIO;
+}
+EXPORT_SYMBOL_GPL(zpci_scan_device);
+
+static inline int barsize(u8 size)
+{
+       return (size) ? (1 << size) >> 10 : 0;
+}
+
+static int zpci_mem_init(void)
+{
+       zdev_irq_cache = kmem_cache_create("PCI_IRQ_cache", sizeof(struct zdev_irq_map),
+                               L1_CACHE_BYTES, SLAB_HWCACHE_ALIGN, NULL);
+       if (!zdev_irq_cache)
+               goto error_zdev;
+
+       /* TODO: use realloc */
+       zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start),
+                                  GFP_KERNEL);
+       if (!zpci_iomap_start)
+               goto error_iomap;
+       return 0;
+
+error_iomap:
+       kmem_cache_destroy(zdev_irq_cache);
+error_zdev:
+       return -ENOMEM;
+}
+
+static void zpci_mem_exit(void)
+{
+       kfree(zpci_iomap_start);
+       kmem_cache_destroy(zdev_irq_cache);
+}
+
+unsigned int pci_probe = 1;
+EXPORT_SYMBOL_GPL(pci_probe);
+
+char * __init pcibios_setup(char *str)
+{
+       if (!strcmp(str, "off")) {
+               pci_probe = 0;
+               return NULL;
+       }
+       return str;
+}
+
+static int __init pci_base_init(void)
+{
+       int rc;
+
+       if (!pci_probe)
+               return 0;
+
+       if (!test_facility(2) || !test_facility(69)
+           || !test_facility(71) || !test_facility(72))
+               return 0;
+
+       pr_info("Probing PCI hardware: PCI:%d  SID:%d  AEN:%d\n",
+               test_facility(69), test_facility(70),
+               test_facility(71));
+
+       rc = zpci_mem_init();
+       if (rc)
+               goto out_mem;
+
+       rc = zpci_msihash_init();
+       if (rc)
+               goto out_hash;
+
+       rc = zpci_irq_init();
+       if (rc)
+               goto out_irq;
+
+       rc = zpci_dma_init();
+       if (rc)
+               goto out_dma;
+
+       rc = clp_find_pci_devices();
+       if (rc)
+               goto out_find;
+
+       zpci_scan_devices();
+       return 0;
+
+out_find:
+       zpci_dma_exit();
+out_dma:
+       zpci_irq_exit();
+out_irq:
+       zpci_msihash_exit();
+out_hash:
+       zpci_mem_exit();
+out_mem:
+       return rc;
+}
+subsys_initcall(pci_base_init);
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
new file mode 100644 (file)
index 0000000..7f4ce8d
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s):
+ *   Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#define COMPONENT "zPCI"
+#define pr_fmt(fmt) COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm/pci_clp.h>
+
+/*
+ * Call Logical Processor
+ * Retry logic is handled by the caller.
+ */
+static inline u8 clp_instr(void *req)
+{
+       u64 ilpm;
+       u8 cc;
+
+       asm volatile (
+               "       .insn   rrf,0xb9a00000,%[ilpm],%[req],0x0,0x2\n"
+               "       ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               : [cc] "=d" (cc), [ilpm] "=d" (ilpm)
+               : [req] "a" (req)
+               : "cc", "memory");
+       return cc;
+}
+
+static void *clp_alloc_block(void)
+{
+       struct page *page = alloc_pages(GFP_KERNEL, get_order(CLP_BLK_SIZE));
+       return (page) ? page_address(page) : NULL;
+}
+
+static void clp_free_block(void *ptr)
+{
+       free_pages((unsigned long) ptr, get_order(CLP_BLK_SIZE));
+}
+
+static void clp_store_query_pci_fngrp(struct zpci_dev *zdev,
+                                     struct clp_rsp_query_pci_grp *response)
+{
+       zdev->tlb_refresh = response->refresh;
+       zdev->dma_mask = response->dasm;
+       zdev->msi_addr = response->msia;
+
+       pr_debug("Supported number of MSI vectors: %u\n", response->noi);
+       switch (response->version) {
+       case 1:
+               zdev->max_bus_speed = PCIE_SPEED_5_0GT;
+               break;
+       default:
+               zdev->max_bus_speed = PCI_SPEED_UNKNOWN;
+               break;
+       }
+}
+
+static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
+{
+       struct clp_req_rsp_query_pci_grp *rrb;
+       int rc;
+
+       rrb = clp_alloc_block();
+       if (!rrb)
+               return -ENOMEM;
+
+       memset(rrb, 0, sizeof(*rrb));
+       rrb->request.hdr.len = sizeof(rrb->request);
+       rrb->request.hdr.cmd = CLP_QUERY_PCI_FNGRP;
+       rrb->response.hdr.len = sizeof(rrb->response);
+       rrb->request.pfgid = pfgid;
+
+       rc = clp_instr(rrb);
+       if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
+               clp_store_query_pci_fngrp(zdev, &rrb->response);
+       else {
+               pr_err("Query PCI FNGRP failed with response: %x  cc: %d\n",
+                       rrb->response.hdr.rsp, rc);
+               rc = -EIO;
+       }
+       clp_free_block(rrb);
+       return rc;
+}
+
+static int clp_store_query_pci_fn(struct zpci_dev *zdev,
+                                 struct clp_rsp_query_pci *response)
+{
+       int i;
+
+       for (i = 0; i < PCI_BAR_COUNT; i++) {
+               zdev->bars[i].val = le32_to_cpu(response->bar[i]);
+               zdev->bars[i].size = response->bar_size[i];
+       }
+       zdev->start_dma = response->sdma;
+       zdev->end_dma = response->edma;
+       zdev->pchid = response->pchid;
+       zdev->pfgid = response->pfgid;
+       return 0;
+}
+
+static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh)
+{
+       struct clp_req_rsp_query_pci *rrb;
+       int rc;
+
+       rrb = clp_alloc_block();
+       if (!rrb)
+               return -ENOMEM;
+
+       memset(rrb, 0, sizeof(*rrb));
+       rrb->request.hdr.len = sizeof(rrb->request);
+       rrb->request.hdr.cmd = CLP_QUERY_PCI_FN;
+       rrb->response.hdr.len = sizeof(rrb->response);
+       rrb->request.fh = fh;
+
+       rc = clp_instr(rrb);
+       if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
+               rc = clp_store_query_pci_fn(zdev, &rrb->response);
+               if (rc)
+                       goto out;
+               if (rrb->response.pfgid)
+                       rc = clp_query_pci_fngrp(zdev, rrb->response.pfgid);
+       } else {
+               pr_err("Query PCI failed with response: %x  cc: %d\n",
+                        rrb->response.hdr.rsp, rc);
+               rc = -EIO;
+       }
+out:
+       clp_free_block(rrb);
+       return rc;
+}
+
+int clp_add_pci_device(u32 fid, u32 fh, int configured)
+{
+       struct zpci_dev *zdev;
+       int rc;
+
+       zdev = zpci_alloc_device();
+       if (IS_ERR(zdev))
+               return PTR_ERR(zdev);
+
+       zdev->fh = fh;
+       zdev->fid = fid;
+
+       /* Query function properties and update zdev */
+       rc = clp_query_pci_fn(zdev, fh);
+       if (rc)
+               goto error;
+
+       if (configured)
+               zdev->state = ZPCI_FN_STATE_CONFIGURED;
+       else
+               zdev->state = ZPCI_FN_STATE_STANDBY;
+
+       rc = zpci_create_device(zdev);
+       if (rc)
+               goto error;
+       return 0;
+
+error:
+       zpci_free_device(zdev);
+       return rc;
+}
+
+/*
+ * Enable/Disable a given PCI function defined by its function handle.
+ */
+static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
+{
+       struct clp_req_rsp_set_pci *rrb;
+       int rc, retries = 1000;
+
+       rrb = clp_alloc_block();
+       if (!rrb)
+               return -ENOMEM;
+
+       do {
+               memset(rrb, 0, sizeof(*rrb));
+               rrb->request.hdr.len = sizeof(rrb->request);
+               rrb->request.hdr.cmd = CLP_SET_PCI_FN;
+               rrb->response.hdr.len = sizeof(rrb->response);
+               rrb->request.fh = *fh;
+               rrb->request.oc = command;
+               rrb->request.ndas = nr_dma_as;
+
+               rc = clp_instr(rrb);
+               if (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY) {
+                       retries--;
+                       if (retries < 0)
+                               break;
+                       msleep(1);
+               }
+       } while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);
+
+       if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
+               *fh = rrb->response.fh;
+       else {
+               pr_err("Set PCI FN failed with response: %x  cc: %d\n",
+                       rrb->response.hdr.rsp, rc);
+               rc = -EIO;
+       }
+       clp_free_block(rrb);
+       return rc;
+}
+
+int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
+{
+       u32 fh = zdev->fh;
+       int rc;
+
+       rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
+       if (!rc)
+               /* Success -> store enabled handle in zdev */
+               zdev->fh = fh;
+       return rc;
+}
+
+int clp_disable_fh(struct zpci_dev *zdev)
+{
+       u32 fh = zdev->fh;
+       int rc;
+
+       if (!zdev_enabled(zdev))
+               return 0;
+
+       dev_info(&zdev->pdev->dev, "disabling fn handle: 0x%x\n", fh);
+       rc = clp_set_pci_fn(&fh, 0, CLP_SET_DISABLE_PCI_FN);
+       if (!rc)
+               /* Success -> store disabled handle in zdev */
+               zdev->fh = fh;
+       else
+               dev_err(&zdev->pdev->dev,
+                       "Failed to disable fn handle: 0x%x\n", fh);
+       return rc;
+}
+
+static void clp_check_pcifn_entry(struct clp_fh_list_entry *entry)
+{
+       int present, rc;
+
+       if (!entry->vendor_id)
+               return;
+
+       /* TODO: be a little bit more scalable */
+       present = zpci_fid_present(entry->fid);
+
+       if (present)
+               pr_debug("%s: device %x already present\n", __func__, entry->fid);
+
+       /* skip already used functions */
+       if (present && entry->config_state)
+               return;
+
+       /* aev 306: function moved to stand-by state */
+       if (present && !entry->config_state) {
+               /*
+                * The handle is already disabled, that means no iota/irq freeing via
+                * the firmware interfaces anymore. Need to free resources manually
+                * (DMA memory, debug, sysfs)...
+                */
+               zpci_stop_device(get_zdev_by_fid(entry->fid));
+               return;
+       }
+
+       rc = clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
+       if (rc)
+               pr_err("Failed to add fid: 0x%x\n", entry->fid);
+}
+
+int clp_find_pci_devices(void)
+{
+       struct clp_req_rsp_list_pci *rrb;
+       u64 resume_token = 0;
+       int entries, i, rc;
+
+       rrb = clp_alloc_block();
+       if (!rrb)
+               return -ENOMEM;
+
+       do {
+               memset(rrb, 0, sizeof(*rrb));
+               rrb->request.hdr.len = sizeof(rrb->request);
+               rrb->request.hdr.cmd = CLP_LIST_PCI;
+               /* store as many entries as possible */
+               rrb->response.hdr.len = CLP_BLK_SIZE - LIST_PCI_HDR_LEN;
+               rrb->request.resume_token = resume_token;
+
+               /* Get PCI function handle list */
+               rc = clp_instr(rrb);
+               if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
+                       pr_err("List PCI failed with response: 0x%x  cc: %d\n",
+                               rrb->response.hdr.rsp, rc);
+                       rc = -EIO;
+                       goto out;
+               }
+
+               WARN_ON_ONCE(rrb->response.entry_size !=
+                       sizeof(struct clp_fh_list_entry));
+
+               entries = (rrb->response.hdr.len - LIST_PCI_HDR_LEN) /
+                       rrb->response.entry_size;
+               pr_info("Detected number of PCI functions: %u\n", entries);
+
+               /* Store the returned resume token as input for the next call */
+               resume_token = rrb->response.resume_token;
+
+               for (i = 0; i < entries; i++)
+                       clp_check_pcifn_entry(&rrb->response.fh_list[i]);
+       } while (resume_token);
+
+       pr_debug("Maximum number of supported PCI functions: %u\n",
+               rrb->response.max_fn);
+out:
+       clp_free_block(rrb);
+       return rc;
+}
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
new file mode 100644 (file)
index 0000000..c64b4b2
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s):
+ *   Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/iommu-helper.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <asm/pci_dma.h>
+
+static enum zpci_ioat_dtype zpci_ioat_dt = ZPCI_IOTA_RTTO;
+
+static struct kmem_cache *dma_region_table_cache;
+static struct kmem_cache *dma_page_table_cache;
+
+static unsigned long *dma_alloc_cpu_table(void)
+{
+       unsigned long *table, *entry;
+
+       table = kmem_cache_alloc(dma_region_table_cache, GFP_ATOMIC);
+       if (!table)
+               return NULL;
+
+       for (entry = table; entry < table + ZPCI_TABLE_ENTRIES; entry++)
+               *entry = ZPCI_TABLE_INVALID | ZPCI_TABLE_PROTECTED;
+       return table;
+}
+
+static void dma_free_cpu_table(void *table)
+{
+       kmem_cache_free(dma_region_table_cache, table);
+}
+
+static unsigned long *dma_alloc_page_table(void)
+{
+       unsigned long *table, *entry;
+
+       table = kmem_cache_alloc(dma_page_table_cache, GFP_ATOMIC);
+       if (!table)
+               return NULL;
+
+       for (entry = table; entry < table + ZPCI_PT_ENTRIES; entry++)
+               *entry = ZPCI_PTE_INVALID | ZPCI_TABLE_PROTECTED;
+       return table;
+}
+
+static void dma_free_page_table(void *table)
+{
+       kmem_cache_free(dma_page_table_cache, table);
+}
+
+static unsigned long *dma_get_seg_table_origin(unsigned long *entry)
+{
+       unsigned long *sto;
+
+       if (reg_entry_isvalid(*entry))
+               sto = get_rt_sto(*entry);
+       else {
+               sto = dma_alloc_cpu_table();
+               if (!sto)
+                       return NULL;
+
+               set_rt_sto(entry, sto);
+               validate_rt_entry(entry);
+               entry_clr_protected(entry);
+       }
+       return sto;
+}
+
+static unsigned long *dma_get_page_table_origin(unsigned long *entry)
+{
+       unsigned long *pto;
+
+       if (reg_entry_isvalid(*entry))
+               pto = get_st_pto(*entry);
+       else {
+               pto = dma_alloc_page_table();
+               if (!pto)
+                       return NULL;
+               set_st_pto(entry, pto);
+               validate_st_entry(entry);
+               entry_clr_protected(entry);
+       }
+       return pto;
+}
+
+static unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr)
+{
+       unsigned long *sto, *pto;
+       unsigned int rtx, sx, px;
+
+       rtx = calc_rtx(dma_addr);
+       sto = dma_get_seg_table_origin(&rto[rtx]);
+       if (!sto)
+               return NULL;
+
+       sx = calc_sx(dma_addr);
+       pto = dma_get_page_table_origin(&sto[sx]);
+       if (!pto)
+               return NULL;
+
+       px = calc_px(dma_addr);
+       return &pto[px];
+}
+
+static void dma_update_cpu_trans(struct zpci_dev *zdev, void *page_addr,
+                                dma_addr_t dma_addr, int flags)
+{
+       unsigned long *entry;
+
+       entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr);
+       if (!entry) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
+       if (flags & ZPCI_PTE_INVALID) {
+               invalidate_pt_entry(entry);
+               return;
+       } else {
+               set_pt_pfaa(entry, page_addr);
+               validate_pt_entry(entry);
+       }
+
+       if (flags & ZPCI_TABLE_PROTECTED)
+               entry_set_protected(entry);
+       else
+               entry_clr_protected(entry);
+}
+
+static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
+                           dma_addr_t dma_addr, size_t size, int flags)
+{
+       unsigned int nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+       u8 *page_addr = (u8 *) (pa & PAGE_MASK);
+       dma_addr_t start_dma_addr = dma_addr;
+       unsigned long irq_flags;
+       int i, rc = 0;
+
+       if (!nr_pages)
+               return -EINVAL;
+
+       spin_lock_irqsave(&zdev->dma_table_lock, irq_flags);
+       if (!zdev->dma_table) {
+               dev_err(&zdev->pdev->dev, "Missing DMA table\n");
+               goto no_refresh;
+       }
+
+       for (i = 0; i < nr_pages; i++) {
+               dma_update_cpu_trans(zdev, page_addr, dma_addr, flags);
+               page_addr += PAGE_SIZE;
+               dma_addr += PAGE_SIZE;
+       }
+
+       /*
+        * rpcit is not required to establish new translations when previously
+        * invalid translation-table entries are validated, however it is
+        * required when altering previously valid entries.
+        */
+       if (!zdev->tlb_refresh &&
+           ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID))
+               /*
+                * TODO: also need to check that the old entry is indeed INVALID
+                * and not only for one page but for the whole range...
+                * -> now we WARN_ON in that case but with lazy unmap that
+                * needs to be redone!
+                */
+               goto no_refresh;
+       rc = rpcit_instr((u64) zdev->fh << 32, start_dma_addr,
+                         nr_pages * PAGE_SIZE);
+
+no_refresh:
+       spin_unlock_irqrestore(&zdev->dma_table_lock, irq_flags);
+       return rc;
+}
+
+static void dma_free_seg_table(unsigned long entry)
+{
+       unsigned long *sto = get_rt_sto(entry);
+       int sx;
+
+       for (sx = 0; sx < ZPCI_TABLE_ENTRIES; sx++)
+               if (reg_entry_isvalid(sto[sx]))
+                       dma_free_page_table(get_st_pto(sto[sx]));
+
+       dma_free_cpu_table(sto);
+}
+
+static void dma_cleanup_tables(struct zpci_dev *zdev)
+{
+       unsigned long *table;
+       int rtx;
+
+       if (!zdev || !zdev->dma_table)
+               return;
+
+       table = zdev->dma_table;
+       for (rtx = 0; rtx < ZPCI_TABLE_ENTRIES; rtx++)
+               if (reg_entry_isvalid(table[rtx]))
+                       dma_free_seg_table(table[rtx]);
+
+       dma_free_cpu_table(table);
+       zdev->dma_table = NULL;
+}
+
+static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, unsigned long start,
+                                  int size)
+{
+       unsigned long boundary_size = 0x1000000;
+
+       return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
+                               start, size, 0, boundary_size, 0);
+}
+
+static unsigned long dma_alloc_iommu(struct zpci_dev *zdev, int size)
+{
+       unsigned long offset, flags;
+
+       spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
+       offset = __dma_alloc_iommu(zdev, zdev->next_bit, size);
+       if (offset == -1)
+               offset = __dma_alloc_iommu(zdev, 0, size);
+
+       if (offset != -1) {
+               zdev->next_bit = offset + size;
+               if (zdev->next_bit >= zdev->iommu_pages)
+                       zdev->next_bit = 0;
+       }
+       spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
+       return offset;
+}
+
+static void dma_free_iommu(struct zpci_dev *zdev, unsigned long offset, int size)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
+       if (!zdev->iommu_bitmap)
+               goto out;
+       bitmap_clear(zdev->iommu_bitmap, offset, size);
+       if (offset >= zdev->next_bit)
+               zdev->next_bit = offset + size;
+out:
+       spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
+}
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+       if (!dev->dma_mask || !dma_supported(dev, mask))
+               return -EIO;
+
+       *dev->dma_mask = mask;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dma_set_mask);
+
+static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
+                                    unsigned long offset, size_t size,
+                                    enum dma_data_direction direction,
+                                    struct dma_attrs *attrs)
+{
+       struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev));
+       unsigned long nr_pages, iommu_page_index;
+       unsigned long pa = page_to_phys(page) + offset;
+       int flags = ZPCI_PTE_VALID;
+       dma_addr_t dma_addr;
+
+       WARN_ON_ONCE(offset > PAGE_SIZE);
+
+       /* This rounds up number of pages based on size and offset */
+       nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
+       iommu_page_index = dma_alloc_iommu(zdev, nr_pages);
+       if (iommu_page_index == -1)
+               goto out_err;
+
+       /* Use rounded up size */
+       size = nr_pages * PAGE_SIZE;
+
+       dma_addr = zdev->start_dma + iommu_page_index * PAGE_SIZE;
+       if (dma_addr + size > zdev->end_dma) {
+               dev_err(dev, "(dma_addr: 0x%16.16LX + size: 0x%16.16lx) > end_dma: 0x%16.16Lx\n",
+                        dma_addr, size, zdev->end_dma);
+               goto out_free;
+       }
+
+       if (direction == DMA_NONE || direction == DMA_TO_DEVICE)
+               flags |= ZPCI_TABLE_PROTECTED;
+
+       if (!dma_update_trans(zdev, pa, dma_addr, size, flags))
+               return dma_addr + offset;
+
+out_free:
+       dma_free_iommu(zdev, iommu_page_index, nr_pages);
+out_err:
+       dev_err(dev, "Failed to map addr: %lx\n", pa);
+       return DMA_ERROR_CODE;
+}
+
+static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
+                                size_t size, enum dma_data_direction direction,
+                                struct dma_attrs *attrs)
+{
+       struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev));
+       unsigned long iommu_page_index;
+       int npages;
+
+       npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
+       dma_addr = dma_addr & PAGE_MASK;
+       if (dma_update_trans(zdev, 0, dma_addr, npages * PAGE_SIZE,
+                            ZPCI_TABLE_PROTECTED | ZPCI_PTE_INVALID))
+               dev_err(dev, "Failed to unmap addr: %Lx\n", dma_addr);
+
+       iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT;
+       dma_free_iommu(zdev, iommu_page_index, npages);
+}
+
+static void *s390_dma_alloc(struct device *dev, size_t size,
+                           dma_addr_t *dma_handle, gfp_t flag,
+                           struct dma_attrs *attrs)
+{
+       struct page *page;
+       unsigned long pa;
+       dma_addr_t map;
+
+       size = PAGE_ALIGN(size);
+       page = alloc_pages(flag, get_order(size));
+       if (!page)
+               return NULL;
+       pa = page_to_phys(page);
+       memset((void *) pa, 0, size);
+
+       map = s390_dma_map_pages(dev, page, pa % PAGE_SIZE,
+                                size, DMA_BIDIRECTIONAL, NULL);
+       if (dma_mapping_error(dev, map)) {
+               free_pages(pa, get_order(size));
+               return NULL;
+       }
+
+       if (dma_handle)
+               *dma_handle = map;
+       return (void *) pa;
+}
+
+static void s390_dma_free(struct device *dev, size_t size,
+                         void *pa, dma_addr_t dma_handle,
+                         struct dma_attrs *attrs)
+{
+       s390_dma_unmap_pages(dev, dma_handle, PAGE_ALIGN(size),
+                            DMA_BIDIRECTIONAL, NULL);
+       free_pages((unsigned long) pa, get_order(size));
+}
+
+static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
+                          int nr_elements, enum dma_data_direction dir,
+                          struct dma_attrs *attrs)
+{
+       int mapped_elements = 0;
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nr_elements, i) {
+               struct page *page = sg_page(s);
+               s->dma_address = s390_dma_map_pages(dev, page, s->offset,
+                                                   s->length, dir, NULL);
+               if (!dma_mapping_error(dev, s->dma_address)) {
+                       s->dma_length = s->length;
+                       mapped_elements++;
+               } else
+                       goto unmap;
+       }
+out:
+       return mapped_elements;
+
+unmap:
+       for_each_sg(sg, s, mapped_elements, i) {
+               if (s->dma_address)
+                       s390_dma_unmap_pages(dev, s->dma_address, s->dma_length,
+                                            dir, NULL);
+               s->dma_address = 0;
+               s->dma_length = 0;
+       }
+       mapped_elements = 0;
+       goto out;
+}
+
+static void s390_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+                             int nr_elements, enum dma_data_direction dir,
+                             struct dma_attrs *attrs)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nr_elements, i) {
+               s390_dma_unmap_pages(dev, s->dma_address, s->dma_length, dir, NULL);
+               s->dma_address = 0;
+               s->dma_length = 0;
+       }
+}
+
+int zpci_dma_init_device(struct zpci_dev *zdev)
+{
+       unsigned int bitmap_order;
+       int rc;
+
+       spin_lock_init(&zdev->iommu_bitmap_lock);
+       spin_lock_init(&zdev->dma_table_lock);
+
+       zdev->dma_table = dma_alloc_cpu_table();
+       if (!zdev->dma_table) {
+               rc = -ENOMEM;
+               goto out_clean;
+       }
+
+       zdev->iommu_size = (unsigned long) high_memory - PAGE_OFFSET;
+       zdev->iommu_pages = zdev->iommu_size >> PAGE_SHIFT;
+       bitmap_order = get_order(zdev->iommu_pages / 8);
+       pr_info("iommu_size: 0x%lx  iommu_pages: 0x%lx  bitmap_order: %i\n",
+                zdev->iommu_size, zdev->iommu_pages, bitmap_order);
+
+       zdev->iommu_bitmap = (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+                                                      bitmap_order);
+       if (!zdev->iommu_bitmap) {
+               rc = -ENOMEM;
+               goto out_reg;
+       }
+
+       rc = zpci_register_ioat(zdev,
+                               0,
+                               zdev->start_dma + PAGE_OFFSET,
+                               zdev->start_dma + zdev->iommu_size - 1,
+                               (u64) zdev->dma_table);
+       if (rc)
+               goto out_reg;
+       return 0;
+
+out_reg:
+       dma_free_cpu_table(zdev->dma_table);
+out_clean:
+       return rc;
+}
+
+void zpci_dma_exit_device(struct zpci_dev *zdev)
+{
+       zpci_unregister_ioat(zdev, 0);
+       dma_cleanup_tables(zdev);
+       free_pages((unsigned long) zdev->iommu_bitmap,
+                  get_order(zdev->iommu_pages / 8));
+       zdev->iommu_bitmap = NULL;
+       zdev->next_bit = 0;
+}
+
+static int __init dma_alloc_cpu_table_caches(void)
+{
+       dma_region_table_cache = kmem_cache_create("PCI_DMA_region_tables",
+                                       ZPCI_TABLE_SIZE, ZPCI_TABLE_ALIGN,
+                                       0, NULL);
+       if (!dma_region_table_cache)
+               return -ENOMEM;
+
+       dma_page_table_cache = kmem_cache_create("PCI_DMA_page_tables",
+                                       ZPCI_PT_SIZE, ZPCI_PT_ALIGN,
+                                       0, NULL);
+       if (!dma_page_table_cache) {
+               kmem_cache_destroy(dma_region_table_cache);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+int __init zpci_dma_init(void)
+{
+       return dma_alloc_cpu_table_caches();
+}
+
+void zpci_dma_exit(void)
+{
+       kmem_cache_destroy(dma_page_table_cache);
+       kmem_cache_destroy(dma_region_table_cache);
+}
+
+#define PREALLOC_DMA_DEBUG_ENTRIES     (1 << 16)
+
+static int __init dma_debug_do_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+       return 0;
+}
+fs_initcall(dma_debug_do_init);
+
+struct dma_map_ops s390_dma_ops = {
+       .alloc          = s390_dma_alloc,
+       .free           = s390_dma_free,
+       .map_sg         = s390_dma_map_sg,
+       .unmap_sg       = s390_dma_unmap_sg,
+       .map_page       = s390_dma_map_pages,
+       .unmap_page     = s390_dma_unmap_pages,
+       /* if we support direct DMA this must be conditional */
+       .is_phys        = 0,
+       /* dma_supported is unconditionally true without a callback */
+};
+EXPORT_SYMBOL_GPL(s390_dma_ops);
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
new file mode 100644 (file)
index 0000000..dbed8cd
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  Copyright IBM Corp. 2012
+ *
+ *  Author(s):
+ *    Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#define COMPONENT "zPCI"
+#define pr_fmt(fmt) COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+/* Content Code Description for PCI Function Error */
+struct zpci_ccdf_err {
+       u32 reserved1;
+       u32 fh;                         /* function handle */
+       u32 fid;                        /* function id */
+       u32 ett         :  4;           /* expected table type */
+       u32 mvn         : 12;           /* MSI vector number */
+       u32 dmaas       :  8;           /* DMA address space */
+       u32             :  6;
+       u32 q           :  1;           /* event qualifier */
+       u32 rw          :  1;           /* read/write */
+       u64 faddr;                      /* failing address */
+       u32 reserved3;
+       u16 reserved4;
+       u16 pec;                        /* PCI event code */
+} __packed;
+
+/* Content Code Description for PCI Function Availability */
+struct zpci_ccdf_avail {
+       u32 reserved1;
+       u32 fh;                         /* function handle */
+       u32 fid;                        /* function id */
+       u32 reserved2;
+       u32 reserved3;
+       u32 reserved4;
+       u32 reserved5;
+       u16 reserved6;
+       u16 pec;                        /* PCI event code */
+} __packed;
+
+static void zpci_event_log_err(struct zpci_ccdf_err *ccdf)
+{
+       struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
+
+       dev_err(&zdev->pdev->dev, "event code: 0x%x\n", ccdf->pec);
+}
+
+static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf)
+{
+       struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
+
+       pr_err("%s%s: availability event: fh: 0x%x  fid: 0x%x  event code: 0x%x  reason:",
+               (zdev) ? dev_driver_string(&zdev->pdev->dev) : "?",
+               (zdev) ? dev_name(&zdev->pdev->dev) : "?",
+               ccdf->fh, ccdf->fid, ccdf->pec);
+       print_hex_dump(KERN_CONT, "ccdf", DUMP_PREFIX_OFFSET,
+                      16, 1, ccdf, sizeof(*ccdf), false);
+
+       switch (ccdf->pec) {
+       case 0x0301:
+               zpci_enable_device(zdev);
+               break;
+       case 0x0302:
+               clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
+               break;
+       case 0x0306:
+               clp_find_pci_devices();
+               break;
+       default:
+               break;
+       }
+}
+
+void zpci_event_error(void *data)
+{
+       struct zpci_ccdf_err *ccdf = data;
+       struct zpci_dev *zdev;
+
+       zpci_event_log_err(ccdf);
+       zdev = get_zdev_by_fid(ccdf->fid);
+       if (!zdev) {
+               pr_err("Error event for unknown fid: %x", ccdf->fid);
+               return;
+       }
+}
+
+void zpci_event_availability(void *data)
+{
+       zpci_event_log_avail(data);
+}
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c
new file mode 100644 (file)
index 0000000..90fd348
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s):
+ *   Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#define COMPONENT "zPCI"
+#define pr_fmt(fmt) COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/rculist.h>
+#include <linux/hash.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <asm/hw_irq.h>
+
+/* mapping of irq numbers to msi_desc */
+static struct hlist_head *msi_hash;
+static unsigned int msihash_shift = 6;
+#define msi_hashfn(nr) hash_long(nr, msihash_shift)
+
+static DEFINE_SPINLOCK(msi_map_lock);
+
+struct msi_desc *__irq_get_msi_desc(unsigned int irq)
+{
+       struct hlist_node *entry;
+       struct msi_map *map;
+
+       hlist_for_each_entry_rcu(map, entry,
+                       &msi_hash[msi_hashfn(irq)], msi_chain)
+               if (map->irq == irq)
+                       return map->msi;
+       return NULL;
+}
+
+int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
+{
+       if (msi->msi_attrib.is_msix) {
+               int offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+                       PCI_MSIX_ENTRY_VECTOR_CTRL;
+               msi->masked = readl(msi->mask_base + offset);
+               writel(flag, msi->mask_base + offset);
+       } else {
+               if (msi->msi_attrib.maskbit) {
+                       int pos;
+                       u32 mask_bits;
+
+                       pos = (long) msi->mask_base;
+                       pci_read_config_dword(msi->dev, pos, &mask_bits);
+                       mask_bits &= ~(mask);
+                       mask_bits |= flag & mask;
+                       pci_write_config_dword(msi->dev, pos, mask_bits);
+               } else {
+                       return 0;
+               }
+       }
+
+       msi->msi_attrib.maskbit = !!flag;
+       return 1;
+}
+
+int zpci_setup_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi,
+                       unsigned int nr, int offset)
+{
+       struct msi_map *map;
+       struct msi_msg msg;
+       int rc;
+
+       map = kmalloc(sizeof(*map), GFP_KERNEL);
+       if (map == NULL)
+               return -ENOMEM;
+
+       map->irq = nr;
+       map->msi = msi;
+       zdev->msi_map[nr & ZPCI_MSI_MASK] = map;
+
+       pr_debug("%s hashing irq: %u  to bucket nr: %llu\n",
+               __func__, nr, msi_hashfn(nr));
+       hlist_add_head_rcu(&map->msi_chain, &msi_hash[msi_hashfn(nr)]);
+
+       spin_lock(&msi_map_lock);
+       rc = irq_set_msi_desc(nr, msi);
+       if (rc) {
+               spin_unlock(&msi_map_lock);
+               hlist_del_rcu(&map->msi_chain);
+               kfree(map);
+               zdev->msi_map[nr & ZPCI_MSI_MASK] = NULL;
+               return rc;
+       }
+       spin_unlock(&msi_map_lock);
+
+       msg.data = nr - offset;
+       msg.address_lo = zdev->msi_addr & 0xffffffff;
+       msg.address_hi = zdev->msi_addr >> 32;
+       write_msi_msg(nr, &msg);
+       return 0;
+}
+
+void zpci_teardown_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi)
+{
+       int irq = msi->irq & ZPCI_MSI_MASK;
+       struct msi_map *map;
+
+       msi->msg.address_lo = 0;
+       msi->msg.address_hi = 0;
+       msi->msg.data = 0;
+       msi->irq = 0;
+       zpci_msi_set_mask_bits(msi, 1, 1);
+
+       spin_lock(&msi_map_lock);
+       map = zdev->msi_map[irq];
+       hlist_del_rcu(&map->msi_chain);
+       kfree(map);
+       zdev->msi_map[irq] = NULL;
+       spin_unlock(&msi_map_lock);
+}
+
+/*
+ * The msi hash table has 256 entries which is good for 4..20
+ * devices (a typical device allocates 10 + CPUs MSI's). Maybe make
+ * the hash table size adjustable later.
+ */
+int __init zpci_msihash_init(void)
+{
+       unsigned int i;
+
+       msi_hash = kmalloc(256 * sizeof(*msi_hash), GFP_KERNEL);
+       if (!msi_hash)
+               return -ENOMEM;
+
+       for (i = 0; i < (1U << msihash_shift); i++)
+               INIT_HLIST_HEAD(&msi_hash[i]);
+       return 0;
+}
+
+void __init zpci_msihash_exit(void)
+{
+       kfree(msi_hash);
+}
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c
new file mode 100644 (file)
index 0000000..a42cce6
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s):
+ *   Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#define COMPONENT "zPCI"
+#define pr_fmt(fmt) COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/stat.h>
+#include <linux/pci.h>
+
+static ssize_t show_fid(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev));
+
+       sprintf(buf, "0x%08x\n", zdev->fid);
+       return strlen(buf);
+}
+static DEVICE_ATTR(function_id, S_IRUGO, show_fid, NULL);
+
+static ssize_t show_fh(struct device *dev, struct device_attribute *attr,
+                      char *buf)
+{
+       struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev));
+
+       sprintf(buf, "0x%08x\n", zdev->fh);
+       return strlen(buf);
+}
+static DEVICE_ATTR(function_handle, S_IRUGO, show_fh, NULL);
+
+static ssize_t show_pchid(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev));
+
+       sprintf(buf, "0x%04x\n", zdev->pchid);
+       return strlen(buf);
+}
+static DEVICE_ATTR(pchid, S_IRUGO, show_pchid, NULL);
+
+static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev));
+
+       sprintf(buf, "0x%02x\n", zdev->pfgid);
+       return strlen(buf);
+}
+static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL);
+
+static struct device_attribute *zpci_dev_attrs[] = {
+       &dev_attr_function_id,
+       &dev_attr_function_handle,
+       &dev_attr_pchid,
+       &dev_attr_pfgid,
+       NULL,
+};
+
+int zpci_sysfs_add_device(struct device *dev)
+{
+       int i, rc = 0;
+
+       for (i = 0; zpci_dev_attrs[i]; i++) {
+               rc = device_create_file(dev, zpci_dev_attrs[i]);
+               if (rc)
+                       goto error;
+       }
+       return 0;
+
+error:
+       while (--i >= 0)
+               device_remove_file(dev, zpci_dev_attrs[i]);
+       return rc;
+}
+
+void zpci_sysfs_remove_device(struct device *dev)
+{
+       int i;
+
+       for (i = 0; zpci_dev_attrs[i]; i++)
+               device_remove_file(dev, zpci_dev_attrs[i]);
+}
index 6cba0a7068bcf9f713a1ca79a233211a928c771a..d71a0bcf8145d529208ff9d053e8b6cb497eb45b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Data Technology Inc. ESPT-GIGA board suport
+ * Data Technology Inc. ESPT-GIGA board support
  *
  * Copyright (C) 2008, 2009 Renesas Solutions Corp.
  * Copyright (C) 2008, 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
index 9e963c1d14474c0e819358145b1c0f832315d79a..5620e33c18a0bef4f2874eead2bd4d175e8d4821 100644 (file)
@@ -179,11 +179,6 @@ static int ap320_wvga_set_brightness(int brightness)
        return 0;
 }
 
-static int ap320_wvga_get_brightness(void)
-{
-       return gpio_get_value(GPIO_PTS3);
-}
-
 static void ap320_wvga_power_on(void)
 {
        msleep(100);
@@ -232,7 +227,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                        .name = "sh_mobile_lcdc_bl",
                        .max_brightness = 1,
                        .set_brightness = ap320_wvga_set_brightness,
-                       .get_brightness = ap320_wvga_get_brightness,
                },
        }
 };
index 64559e8af14b3e7aa3dad26d0f2dc3e07e1edf2c..3fede4556c91eee6ae7e5aa7a449675710254150 100644 (file)
@@ -329,11 +329,6 @@ static int ecovec24_set_brightness(int brightness)
        return 0;
 }
 
-static int ecovec24_get_brightness(void)
-{
-       return gpio_get_value(GPIO_PTR1);
-}
-
 static struct sh_mobile_lcdc_info lcdc_info = {
        .ch[0] = {
                .interface_type = RGB18,
@@ -347,7 +342,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                        .name = "sh_mobile_lcdc_bl",
                        .max_brightness = 1,
                        .set_brightness = ecovec24_set_brightness,
-                       .get_brightness = ecovec24_get_brightness,
                },
        }
 };
index c148b36ecb65c04dbfccdd95685b5dd6cc3bc846..c620503326295f0d7bc30b58b71e58b0c5f5175c 100644 (file)
@@ -283,7 +283,7 @@ void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
 #define MAIN_MLED4      0x40
 #define MAIN_MSW        0x80
 
-static int kfr2r09_lcd_backlight(int on)
+int kfr2r09_lcd_set_brightness(int brightness)
 {
        struct i2c_adapter *a;
        struct i2c_msg msg;
@@ -295,7 +295,7 @@ static int kfr2r09_lcd_backlight(int on)
                return -ENODEV;
 
        buf[0] = 0x00;
-       if (on)
+       if (brightness)
                buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
        else
                buf[1] = 0;
@@ -309,7 +309,7 @@ static int kfr2r09_lcd_backlight(int on)
                return -ENODEV;
 
        buf[0] = 0x01;
-       if (on)
+       if (brightness)
                buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
        else
                buf[1] = 0;
@@ -324,13 +324,3 @@ static int kfr2r09_lcd_backlight(int on)
 
        return 0;
 }
-
-void kfr2r09_lcd_on(void)
-{
-       kfr2r09_lcd_backlight(1);
-}
-
-void kfr2r09_lcd_off(void)
-{
-       kfr2r09_lcd_backlight(0);
-}
index f2a4304fbe2321996fb875b75d2bd570feda8ae6..ab502f12ef57ad1025b504645608447a2e115840 100644 (file)
@@ -158,8 +158,11 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
                        .height = 58,
                        .setup_sys = kfr2r09_lcd_setup,
                        .start_transfer = kfr2r09_lcd_start,
-                       .display_on = kfr2r09_lcd_on,
-                       .display_off = kfr2r09_lcd_off,
+               },
+               .bl_info = {
+                       .name = "sh_mobile_lcdc_bl",
+                       .max_brightness = 1,
+                       .set_brightness = kfr2r09_lcd_set_brightness,
                },
                .sys_bus_cfg = {
                        .ldmt2r = 0x07010904,
index ba3d93d333f8e292a20d53246ab4d90b5a96b6f9..c20c9e5f5eabe9279c1738d85354ba1a636a6207 100644 (file)
@@ -4,15 +4,13 @@
 #include <video/sh_mobile_lcdc.h>
 
 #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
-void kfr2r09_lcd_on(void);
-void kfr2r09_lcd_off(void);
+int kfr2r09_lcd_set_brightness(int brightness);
 int kfr2r09_lcd_setup(void *sys_ops_handle,
                      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 void kfr2r09_lcd_start(void *sys_ops_handle,
                       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 #else
-static void kfr2r09_lcd_on(void) {}
-static void kfr2r09_lcd_off(void) {}
+static int kfr2r09_lcd_set_brightness(int brightness) {}
 static int kfr2r09_lcd_setup(void *sys_ops_handle,
                                struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
 {
index cbbdcad8fcb357cc7fc383820a6f0c7dc1537be9..1f49c28affa90495047c6b82577b2d5221bc089b 100644 (file)
@@ -301,17 +301,6 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
        __bad_area(regs, error_code, address, SEGV_ACCERR);
 }
 
-static void out_of_memory(void)
-{
-       /*
-        * We ran out of memory, call the OOM killer, and return the userspace
-        * (which will retry the fault, or kill us if we got oom-killed):
-        */
-       up_read(&current->mm->mmap_sem);
-
-       pagefault_out_of_memory();
-}
-
 static void
 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
 {
@@ -353,8 +342,14 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
                        no_context(regs, error_code, address);
                        return 1;
                }
+               up_read(&current->mm->mmap_sem);
 
-               out_of_memory();
+               /*
+                * We ran out of memory, call the OOM killer, and return the
+                * userspace (which will retry the fault, or kill us if we got
+                * oom-killed):
+                */
+               pagefault_out_of_memory();
        } else {
                if (fault & VM_FAULT_SIGBUS)
                        do_sigbus(regs, error_code, address);
index 9195fd80e11ed7efa2e030704eab0b22e161c7cc..65a872bf72f9c693039540519b69f9c8238b7214 100644 (file)
@@ -370,6 +370,7 @@ config X86_NUMACHIP
        depends on NUMA
        depends on SMP
        depends on X86_X2APIC
+       depends on PCI_MMCONFIG
        ---help---
          Adds support for Numascale NumaChip large-SMP systems. Needed to
          enable more than ~168 cores.
index 851fe936d2421a14d7a558e2946321503d73a5b6..e3cf9f682be55e5d07617a7ba921bead05a218e1 100644 (file)
@@ -2,7 +2,6 @@ bootsect
 bzImage
 cpustr.h
 mkcpustr
-offsets.h
 voffset.h
 zoffset.h
 setup
index e87b0cac14b5e5d735ab21f9f3b163db52349938..b1942e222768e7c9c2707c14dbdbd9643a51a8b9 100644 (file)
@@ -8,6 +8,7 @@
  * ----------------------------------------------------------------------- */
 
 #include <linux/efi.h>
+#include <linux/pci.h>
 #include <asm/efi.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
@@ -245,6 +246,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
        *size = len;
 }
 
+static efi_status_t setup_efi_pci(struct boot_params *params)
+{
+       efi_pci_io_protocol *pci;
+       efi_status_t status;
+       void **pci_handle;
+       efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+       unsigned long nr_pci, size = 0;
+       int i;
+       struct setup_data *data;
+
+       data = (struct setup_data *)params->hdr.setup_data;
+
+       while (data && data->next)
+               data = (struct setup_data *)data->next;
+
+       status = efi_call_phys5(sys_table->boottime->locate_handle,
+                               EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+                               NULL, &size, pci_handle);
+
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               status = efi_call_phys3(sys_table->boottime->allocate_pool,
+                                       EFI_LOADER_DATA, size, &pci_handle);
+
+               if (status != EFI_SUCCESS)
+                       return status;
+
+               status = efi_call_phys5(sys_table->boottime->locate_handle,
+                                       EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+                                       NULL, &size, pci_handle);
+       }
+
+       if (status != EFI_SUCCESS)
+               goto free_handle;
+
+       nr_pci = size / sizeof(void *);
+       for (i = 0; i < nr_pci; i++) {
+               void *h = pci_handle[i];
+               uint64_t attributes;
+               struct pci_setup_rom *rom;
+
+               status = efi_call_phys3(sys_table->boottime->handle_protocol,
+                                       h, &pci_proto, &pci);
+
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               if (!pci)
+                       continue;
+
+               status = efi_call_phys4(pci->attributes, pci,
+                                       EfiPciIoAttributeOperationGet, 0,
+                                       &attributes);
+
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+                       continue;
+
+               if (!pci->romimage || !pci->romsize)
+                       continue;
+
+               size = pci->romsize + sizeof(*rom);
+
+               status = efi_call_phys3(sys_table->boottime->allocate_pool,
+                               EFI_LOADER_DATA, size, &rom);
+
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               rom->data.type = SETUP_PCI;
+               rom->data.len = size - sizeof(struct setup_data);
+               rom->data.next = 0;
+               rom->pcilen = pci->romsize;
+
+               status = efi_call_phys5(pci->pci.read, pci,
+                                       EfiPciIoWidthUint16, PCI_VENDOR_ID,
+                                       1, &(rom->vendor));
+
+               if (status != EFI_SUCCESS)
+                       goto free_struct;
+
+               status = efi_call_phys5(pci->pci.read, pci,
+                                       EfiPciIoWidthUint16, PCI_DEVICE_ID,
+                                       1, &(rom->devid));
+
+               if (status != EFI_SUCCESS)
+                       goto free_struct;
+
+               status = efi_call_phys5(pci->get_location, pci,
+                                       &(rom->segment), &(rom->bus),
+                                       &(rom->device), &(rom->function));
+
+               if (status != EFI_SUCCESS)
+                       goto free_struct;
+
+               memcpy(rom->romdata, pci->romimage, pci->romsize);
+
+               if (data)
+                       data->next = (uint64_t)rom;
+               else
+                       params->hdr.setup_data = (uint64_t)rom;
+
+               data = (struct setup_data *)rom;
+
+               continue;
+       free_struct:
+               efi_call_phys1(sys_table->boottime->free_pool, rom);
+       }
+
+free_handle:
+       efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
+       return status;
+}
+
 /*
  * See if we have Graphics Output Protocol
  */
@@ -1028,6 +1144,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
 
        setup_graphics(boot_params);
 
+       setup_efi_pci(boot_params);
+
        status = efi_call_phys3(sys_table->boottime->allocate_pool,
                                EFI_LOADER_DATA, sizeof(*gdt),
                                (void **)&gdt);
index 5bacb4a226ac8e4ff88562b60e96f04f2e0cc8e4..e0ca7c9ac383ead8afe04654454ad8809df8d8fe 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
 obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o
+obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64) += camellia-aesni-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_CAST5_AVX_X86_64) += cast5-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_CAST6_AVX_X86_64) += cast6-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
@@ -34,6 +35,8 @@ serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
 camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
+camellia-aesni-avx-x86_64-y := camellia-aesni-avx-asm_64.o \
+                              camellia_aesni_avx_glue.o
 cast5-avx-x86_64-y := cast5-avx-x86_64-asm_64.o cast5_avx_glue.o
 cast6-avx-x86_64-y := cast6-avx-x86_64-asm_64.o cast6_avx_glue.o
 blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
@@ -47,3 +50,5 @@ serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o serpent_avx_glue.o
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
 sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
+crc32c-intel-y := crc32c-intel_glue.o
+crc32c-intel-$(CONFIG_CRYPTO_CRC32C_X86_64) += crc32c-pcl-intel-asm_64.o
diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
new file mode 100644 (file)
index 0000000..2306d2e
--- /dev/null
@@ -0,0 +1,1102 @@
+/*
+ * x86_64/AVX/AES-NI assembler implementation of Camellia
+ *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Version licensed under 2-clause BSD License is available at:
+ *     http://koti.mbnet.fi/axh/crypto/camellia-BSD-1.2.0-aesni1.tar.xz
+ */
+
+#define CAMELLIA_TABLE_BYTE_LEN 272
+
+/* struct camellia_ctx: */
+#define key_table 0
+#define key_length CAMELLIA_TABLE_BYTE_LEN
+
+/* register macros */
+#define CTX %rdi
+
+/**********************************************************************
+  16-way camellia
+ **********************************************************************/
+#define filter_8bit(x, lo_t, hi_t, mask4bit, tmp0) \
+       vpand x, mask4bit, tmp0; \
+       vpandn x, mask4bit, x; \
+       vpsrld $4, x, x; \
+       \
+       vpshufb tmp0, lo_t, tmp0; \
+       vpshufb x, hi_t, x; \
+       vpxor tmp0, x, x;
+
+/*
+ * IN:
+ *   x0..x7: byte-sliced AB state
+ *   mem_cd: register pointer storing CD state
+ *   key: index for key material
+ * OUT:
+ *   x0..x7: new byte-sliced CD state
+ */
+#define roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2, t3, t4, t5, t6, \
+                 t7, mem_cd, key) \
+       /* \
+        * S-function with AES subbytes \
+        */ \
+       vmovdqa .Linv_shift_row, t4; \
+       vbroadcastss .L0f0f0f0f, t7; \
+       vmovdqa .Lpre_tf_lo_s1, t0; \
+       vmovdqa .Lpre_tf_hi_s1, t1; \
+       \
+       /* AES inverse shift rows */ \
+       vpshufb t4, x0, x0; \
+       vpshufb t4, x7, x7; \
+       vpshufb t4, x1, x1; \
+       vpshufb t4, x4, x4; \
+       vpshufb t4, x2, x2; \
+       vpshufb t4, x5, x5; \
+       vpshufb t4, x3, x3; \
+       vpshufb t4, x6, x6; \
+       \
+       /* prefilter sboxes 1, 2 and 3 */ \
+       vmovdqa .Lpre_tf_lo_s4, t2; \
+       vmovdqa .Lpre_tf_hi_s4, t3; \
+       filter_8bit(x0, t0, t1, t7, t6); \
+       filter_8bit(x7, t0, t1, t7, t6); \
+       filter_8bit(x1, t0, t1, t7, t6); \
+       filter_8bit(x4, t0, t1, t7, t6); \
+       filter_8bit(x2, t0, t1, t7, t6); \
+       filter_8bit(x5, t0, t1, t7, t6); \
+       \
+       /* prefilter sbox 4 */ \
+       vpxor t4, t4, t4; \
+       filter_8bit(x3, t2, t3, t7, t6); \
+       filter_8bit(x6, t2, t3, t7, t6); \
+       \
+       /* AES subbytes + AES shift rows */ \
+       vmovdqa .Lpost_tf_lo_s1, t0; \
+       vmovdqa .Lpost_tf_hi_s1, t1; \
+       vaesenclast t4, x0, x0; \
+       vaesenclast t4, x7, x7; \
+       vaesenclast t4, x1, x1; \
+       vaesenclast t4, x4, x4; \
+       vaesenclast t4, x2, x2; \
+       vaesenclast t4, x5, x5; \
+       vaesenclast t4, x3, x3; \
+       vaesenclast t4, x6, x6; \
+       \
+       /* postfilter sboxes 1 and 4 */ \
+       vmovdqa .Lpost_tf_lo_s3, t2; \
+       vmovdqa .Lpost_tf_hi_s3, t3; \
+       filter_8bit(x0, t0, t1, t7, t6); \
+       filter_8bit(x7, t0, t1, t7, t6); \
+       filter_8bit(x3, t0, t1, t7, t6); \
+       filter_8bit(x6, t0, t1, t7, t6); \
+       \
+       /* postfilter sbox 3 */ \
+       vmovdqa .Lpost_tf_lo_s2, t4; \
+       vmovdqa .Lpost_tf_hi_s2, t5; \
+       filter_8bit(x2, t2, t3, t7, t6); \
+       filter_8bit(x5, t2, t3, t7, t6); \
+       \
+       vpxor t6, t6, t6; \
+       vmovq key, t0; \
+       \
+       /* postfilter sbox 2 */ \
+       filter_8bit(x1, t4, t5, t7, t2); \
+       filter_8bit(x4, t4, t5, t7, t2); \
+       \
+       vpsrldq $5, t0, t5; \
+       vpsrldq $1, t0, t1; \
+       vpsrldq $2, t0, t2; \
+       vpsrldq $3, t0, t3; \
+       vpsrldq $4, t0, t4; \
+       vpshufb t6, t0, t0; \
+       vpshufb t6, t1, t1; \
+       vpshufb t6, t2, t2; \
+       vpshufb t6, t3, t3; \
+       vpshufb t6, t4, t4; \
+       vpsrldq $2, t5, t7; \
+       vpshufb t6, t7, t7; \
+       \
+       /* \
+        * P-function \
+        */ \
+       vpxor x5, x0, x0; \
+       vpxor x6, x1, x1; \
+       vpxor x7, x2, x2; \
+       vpxor x4, x3, x3; \
+       \
+       vpxor x2, x4, x4; \
+       vpxor x3, x5, x5; \
+       vpxor x0, x6, x6; \
+       vpxor x1, x7, x7; \
+       \
+       vpxor x7, x0, x0; \
+       vpxor x4, x1, x1; \
+       vpxor x5, x2, x2; \
+       vpxor x6, x3, x3; \
+       \
+       vpxor x3, x4, x4; \
+       vpxor x0, x5, x5; \
+       vpxor x1, x6, x6; \
+       vpxor x2, x7, x7; /* note: high and low parts swapped */ \
+       \
+       /* \
+        * Add key material and result to CD (x becomes new CD) \
+        */ \
+       \
+       vpxor t3, x4, x4; \
+       vpxor 0 * 16(mem_cd), x4, x4; \
+       \
+       vpxor t2, x5, x5; \
+       vpxor 1 * 16(mem_cd), x5, x5; \
+       \
+       vpsrldq $1, t5, t3; \
+       vpshufb t6, t5, t5; \
+       vpshufb t6, t3, t6; \
+       \
+       vpxor t1, x6, x6; \
+       vpxor 2 * 16(mem_cd), x6, x6; \
+       \
+       vpxor t0, x7, x7; \
+       vpxor 3 * 16(mem_cd), x7, x7; \
+       \
+       vpxor t7, x0, x0; \
+       vpxor 4 * 16(mem_cd), x0, x0; \
+       \
+       vpxor t6, x1, x1; \
+       vpxor 5 * 16(mem_cd), x1, x1; \
+       \
+       vpxor t5, x2, x2; \
+       vpxor 6 * 16(mem_cd), x2, x2; \
+       \
+       vpxor t4, x3, x3; \
+       vpxor 7 * 16(mem_cd), x3, x3;
+
+/*
+ * Size optimization... with inlined roundsm16, binary would be over 5 times
+ * larger and would only be 0.5% faster (on sandy-bridge).
+ */
+.align 8
+roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd:
+       roundsm16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                 %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15,
+                 %rcx, (%r9));
+       ret;
+
+.align 8
+roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab:
+       roundsm16(%xmm4, %xmm5, %xmm6, %xmm7, %xmm0, %xmm1, %xmm2, %xmm3,
+                 %xmm12, %xmm13, %xmm14, %xmm15, %xmm8, %xmm9, %xmm10, %xmm11,
+                 %rax, (%r9));
+       ret;
+
+/*
+ * IN/OUT:
+ *  x0..x7: byte-sliced AB state preloaded
+ *  mem_ab: byte-sliced AB state in memory
+ *  mem_cb: byte-sliced CD state in memory
+ */
+#define two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, i, dir, store_ab) \
+       leaq (key_table + (i) * 8)(CTX), %r9; \
+       call roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd; \
+       \
+       vmovdqu x4, 0 * 16(mem_cd); \
+       vmovdqu x5, 1 * 16(mem_cd); \
+       vmovdqu x6, 2 * 16(mem_cd); \
+       vmovdqu x7, 3 * 16(mem_cd); \
+       vmovdqu x0, 4 * 16(mem_cd); \
+       vmovdqu x1, 5 * 16(mem_cd); \
+       vmovdqu x2, 6 * 16(mem_cd); \
+       vmovdqu x3, 7 * 16(mem_cd); \
+       \
+       leaq (key_table + ((i) + (dir)) * 8)(CTX), %r9; \
+       call roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab; \
+       \
+       store_ab(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab);
+
+#define dummy_store(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) /* do nothing */
+
+#define store_ab_state(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) \
+       /* Store new AB state */ \
+       vmovdqu x0, 0 * 16(mem_ab); \
+       vmovdqu x1, 1 * 16(mem_ab); \
+       vmovdqu x2, 2 * 16(mem_ab); \
+       vmovdqu x3, 3 * 16(mem_ab); \
+       vmovdqu x4, 4 * 16(mem_ab); \
+       vmovdqu x5, 5 * 16(mem_ab); \
+       vmovdqu x6, 6 * 16(mem_ab); \
+       vmovdqu x7, 7 * 16(mem_ab);
+
+#define enc_rounds16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, i) \
+       two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 2, 1, store_ab_state); \
+       two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 4, 1, store_ab_state); \
+       two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 6, 1, dummy_store);
+
+#define dec_rounds16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, i) \
+       two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 7, -1, store_ab_state); \
+       two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 5, -1, store_ab_state); \
+       two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 3, -1, dummy_store);
+
+/*
+ * IN:
+ *  v0..3: byte-sliced 32-bit integers
+ * OUT:
+ *  v0..3: (IN <<< 1)
+ */
+#define rol32_1_16(v0, v1, v2, v3, t0, t1, t2, zero) \
+       vpcmpgtb v0, zero, t0; \
+       vpaddb v0, v0, v0; \
+       vpabsb t0, t0; \
+       \
+       vpcmpgtb v1, zero, t1; \
+       vpaddb v1, v1, v1; \
+       vpabsb t1, t1; \
+       \
+       vpcmpgtb v2, zero, t2; \
+       vpaddb v2, v2, v2; \
+       vpabsb t2, t2; \
+       \
+       vpor t0, v1, v1; \
+       \
+       vpcmpgtb v3, zero, t0; \
+       vpaddb v3, v3, v3; \
+       vpabsb t0, t0; \
+       \
+       vpor t1, v2, v2; \
+       vpor t2, v3, v3; \
+       vpor t0, v0, v0;
+
+/*
+ * IN:
+ *   r: byte-sliced AB state in memory
+ *   l: byte-sliced CD state in memory
+ * OUT:
+ *   x0..x7: new byte-sliced CD state
+ */
+#define fls16(l, l0, l1, l2, l3, l4, l5, l6, l7, r, t0, t1, t2, t3, tt0, \
+             tt1, tt2, tt3, kll, klr, krl, krr) \
+       /* \
+        * t0 = kll; \
+        * t0 &= ll; \
+        * lr ^= rol32(t0, 1); \
+        */ \
+       vpxor tt0, tt0, tt0; \
+       vmovd kll, t0; \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpand l0, t0, t0; \
+       vpand l1, t1, t1; \
+       vpand l2, t2, t2; \
+       vpand l3, t3, t3; \
+       \
+       rol32_1_16(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
+       \
+       vpxor l4, t0, l4; \
+       vmovdqu l4, 4 * 16(l); \
+       vpxor l5, t1, l5; \
+       vmovdqu l5, 5 * 16(l); \
+       vpxor l6, t2, l6; \
+       vmovdqu l6, 6 * 16(l); \
+       vpxor l7, t3, l7; \
+       vmovdqu l7, 7 * 16(l); \
+       \
+       /* \
+        * t2 = krr; \
+        * t2 |= rr; \
+        * rl ^= t2; \
+        */ \
+       \
+       vmovd krr, t0; \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpor 4 * 16(r), t0, t0; \
+       vpor 5 * 16(r), t1, t1; \
+       vpor 6 * 16(r), t2, t2; \
+       vpor 7 * 16(r), t3, t3; \
+       \
+       vpxor 0 * 16(r), t0, t0; \
+       vpxor 1 * 16(r), t1, t1; \
+       vpxor 2 * 16(r), t2, t2; \
+       vpxor 3 * 16(r), t3, t3; \
+       vmovdqu t0, 0 * 16(r); \
+       vmovdqu t1, 1 * 16(r); \
+       vmovdqu t2, 2 * 16(r); \
+       vmovdqu t3, 3 * 16(r); \
+       \
+       /* \
+        * t2 = krl; \
+        * t2 &= rl; \
+        * rr ^= rol32(t2, 1); \
+        */ \
+       vmovd krl, t0; \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpand 0 * 16(r), t0, t0; \
+       vpand 1 * 16(r), t1, t1; \
+       vpand 2 * 16(r), t2, t2; \
+       vpand 3 * 16(r), t3, t3; \
+       \
+       rol32_1_16(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
+       \
+       vpxor 4 * 16(r), t0, t0; \
+       vpxor 5 * 16(r), t1, t1; \
+       vpxor 6 * 16(r), t2, t2; \
+       vpxor 7 * 16(r), t3, t3; \
+       vmovdqu t0, 4 * 16(r); \
+       vmovdqu t1, 5 * 16(r); \
+       vmovdqu t2, 6 * 16(r); \
+       vmovdqu t3, 7 * 16(r); \
+       \
+       /* \
+        * t0 = klr; \
+        * t0 |= lr; \
+        * ll ^= t0; \
+        */ \
+       \
+       vmovd klr, t0; \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpor l4, t0, t0; \
+       vpor l5, t1, t1; \
+       vpor l6, t2, t2; \
+       vpor l7, t3, t3; \
+       \
+       vpxor l0, t0, l0; \
+       vmovdqu l0, 0 * 16(l); \
+       vpxor l1, t1, l1; \
+       vmovdqu l1, 1 * 16(l); \
+       vpxor l2, t2, l2; \
+       vmovdqu l2, 2 * 16(l); \
+       vpxor l3, t3, l3; \
+       vmovdqu l3, 3 * 16(l);
+
+#define transpose_4x4(x0, x1, x2, x3, t1, t2) \
+       vpunpckhdq x1, x0, t2; \
+       vpunpckldq x1, x0, x0; \
+       \
+       vpunpckldq x3, x2, t1; \
+       vpunpckhdq x3, x2, x2; \
+       \
+       vpunpckhqdq t1, x0, x1; \
+       vpunpcklqdq t1, x0, x0; \
+       \
+       vpunpckhqdq x2, t2, x3; \
+       vpunpcklqdq x2, t2, x2;
+
+#define byteslice_16x16b(a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, a3, \
+                        b3, c3, d3, st0, st1) \
+       vmovdqu d2, st0; \
+       vmovdqu d3, st1; \
+       transpose_4x4(a0, a1, a2, a3, d2, d3); \
+       transpose_4x4(b0, b1, b2, b3, d2, d3); \
+       vmovdqu st0, d2; \
+       vmovdqu st1, d3; \
+       \
+       vmovdqu a0, st0; \
+       vmovdqu a1, st1; \
+       transpose_4x4(c0, c1, c2, c3, a0, a1); \
+       transpose_4x4(d0, d1, d2, d3, a0, a1); \
+       \
+       vmovdqu .Lshufb_16x16b, a0; \
+       vmovdqu st1, a1; \
+       vpshufb a0, a2, a2; \
+       vpshufb a0, a3, a3; \
+       vpshufb a0, b0, b0; \
+       vpshufb a0, b1, b1; \
+       vpshufb a0, b2, b2; \
+       vpshufb a0, b3, b3; \
+       vpshufb a0, a1, a1; \
+       vpshufb a0, c0, c0; \
+       vpshufb a0, c1, c1; \
+       vpshufb a0, c2, c2; \
+       vpshufb a0, c3, c3; \
+       vpshufb a0, d0, d0; \
+       vpshufb a0, d1, d1; \
+       vpshufb a0, d2, d2; \
+       vpshufb a0, d3, d3; \
+       vmovdqu d3, st1; \
+       vmovdqu st0, d3; \
+       vpshufb a0, d3, a0; \
+       vmovdqu d2, st0; \
+       \
+       transpose_4x4(a0, b0, c0, d0, d2, d3); \
+       transpose_4x4(a1, b1, c1, d1, d2, d3); \
+       vmovdqu st0, d2; \
+       vmovdqu st1, d3; \
+       \
+       vmovdqu b0, st0; \
+       vmovdqu b1, st1; \
+       transpose_4x4(a2, b2, c2, d2, b0, b1); \
+       transpose_4x4(a3, b3, c3, d3, b0, b1); \
+       vmovdqu st0, b0; \
+       vmovdqu st1, b1; \
+       /* does not adjust output bytes inside vectors */
+
+/* load blocks to registers and apply pre-whitening */
+#define inpack16_pre(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                    y6, y7, rio, key) \
+       vmovq key, x0; \
+       vpshufb .Lpack_bswap, x0, x0; \
+       \
+       vpxor 0 * 16(rio), x0, y7; \
+       vpxor 1 * 16(rio), x0, y6; \
+       vpxor 2 * 16(rio), x0, y5; \
+       vpxor 3 * 16(rio), x0, y4; \
+       vpxor 4 * 16(rio), x0, y3; \
+       vpxor 5 * 16(rio), x0, y2; \
+       vpxor 6 * 16(rio), x0, y1; \
+       vpxor 7 * 16(rio), x0, y0; \
+       vpxor 8 * 16(rio), x0, x7; \
+       vpxor 9 * 16(rio), x0, x6; \
+       vpxor 10 * 16(rio), x0, x5; \
+       vpxor 11 * 16(rio), x0, x4; \
+       vpxor 12 * 16(rio), x0, x3; \
+       vpxor 13 * 16(rio), x0, x2; \
+       vpxor 14 * 16(rio), x0, x1; \
+       vpxor 15 * 16(rio), x0, x0;
+
+/* byteslice pre-whitened blocks and store to temporary memory */
+#define inpack16_post(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd) \
+       byteslice_16x16b(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \
+                        y5, y6, y7, (mem_ab), (mem_cd)); \
+       \
+       vmovdqu x0, 0 * 16(mem_ab); \
+       vmovdqu x1, 1 * 16(mem_ab); \
+       vmovdqu x2, 2 * 16(mem_ab); \
+       vmovdqu x3, 3 * 16(mem_ab); \
+       vmovdqu x4, 4 * 16(mem_ab); \
+       vmovdqu x5, 5 * 16(mem_ab); \
+       vmovdqu x6, 6 * 16(mem_ab); \
+       vmovdqu x7, 7 * 16(mem_ab); \
+       vmovdqu y0, 0 * 16(mem_cd); \
+       vmovdqu y1, 1 * 16(mem_cd); \
+       vmovdqu y2, 2 * 16(mem_cd); \
+       vmovdqu y3, 3 * 16(mem_cd); \
+       vmovdqu y4, 4 * 16(mem_cd); \
+       vmovdqu y5, 5 * 16(mem_cd); \
+       vmovdqu y6, 6 * 16(mem_cd); \
+       vmovdqu y7, 7 * 16(mem_cd);
+
+/* de-byteslice, apply post-whitening and store blocks */
+#define outunpack16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \
+                   y5, y6, y7, key, stack_tmp0, stack_tmp1) \
+       byteslice_16x16b(y0, y4, x0, x4, y1, y5, x1, x5, y2, y6, x2, x6, y3, \
+                        y7, x3, x7, stack_tmp0, stack_tmp1); \
+       \
+       vmovdqu x0, stack_tmp0; \
+       \
+       vmovq key, x0; \
+       vpshufb .Lpack_bswap, x0, x0; \
+       \
+       vpxor x0, y7, y7; \
+       vpxor x0, y6, y6; \
+       vpxor x0, y5, y5; \
+       vpxor x0, y4, y4; \
+       vpxor x0, y3, y3; \
+       vpxor x0, y2, y2; \
+       vpxor x0, y1, y1; \
+       vpxor x0, y0, y0; \
+       vpxor x0, x7, x7; \
+       vpxor x0, x6, x6; \
+       vpxor x0, x5, x5; \
+       vpxor x0, x4, x4; \
+       vpxor x0, x3, x3; \
+       vpxor x0, x2, x2; \
+       vpxor x0, x1, x1; \
+       vpxor stack_tmp0, x0, x0;
+
+#define write_output(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                    y6, y7, rio) \
+       vmovdqu x0, 0 * 16(rio); \
+       vmovdqu x1, 1 * 16(rio); \
+       vmovdqu x2, 2 * 16(rio); \
+       vmovdqu x3, 3 * 16(rio); \
+       vmovdqu x4, 4 * 16(rio); \
+       vmovdqu x5, 5 * 16(rio); \
+       vmovdqu x6, 6 * 16(rio); \
+       vmovdqu x7, 7 * 16(rio); \
+       vmovdqu y0, 8 * 16(rio); \
+       vmovdqu y1, 9 * 16(rio); \
+       vmovdqu y2, 10 * 16(rio); \
+       vmovdqu y3, 11 * 16(rio); \
+       vmovdqu y4, 12 * 16(rio); \
+       vmovdqu y5, 13 * 16(rio); \
+       vmovdqu y6, 14 * 16(rio); \
+       vmovdqu y7, 15 * 16(rio);
+
+.data
+.align 16
+
+#define SHUFB_BYTES(idx) \
+       0 + (idx), 4 + (idx), 8 + (idx), 12 + (idx)
+
+.Lshufb_16x16b:
+       .byte SHUFB_BYTES(0), SHUFB_BYTES(1), SHUFB_BYTES(2), SHUFB_BYTES(3);
+
+.Lpack_bswap:
+       .long 0x00010203
+       .long 0x04050607
+       .long 0x80808080
+       .long 0x80808080
+
+/* For CTR-mode IV byteswap */
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+/*
+ * pre-SubByte transform
+ *
+ * pre-lookup for sbox1, sbox2, sbox3:
+ *   swap_bitendianness(
+ *       isom_map_camellia_to_aes(
+ *           camellia_f(
+ *               swap_bitendianess(in)
+ *           )
+ *       )
+ *   )
+ *
+ * (note: '⊕ 0xc5' inside camellia_f())
+ */
+.Lpre_tf_lo_s1:
+       .byte 0x45, 0xe8, 0x40, 0xed, 0x2e, 0x83, 0x2b, 0x86
+       .byte 0x4b, 0xe6, 0x4e, 0xe3, 0x20, 0x8d, 0x25, 0x88
+.Lpre_tf_hi_s1:
+       .byte 0x00, 0x51, 0xf1, 0xa0, 0x8a, 0xdb, 0x7b, 0x2a
+       .byte 0x09, 0x58, 0xf8, 0xa9, 0x83, 0xd2, 0x72, 0x23
+
+/*
+ * pre-SubByte transform
+ *
+ * pre-lookup for sbox4:
+ *   swap_bitendianness(
+ *       isom_map_camellia_to_aes(
+ *           camellia_f(
+ *               swap_bitendianess(in <<< 1)
+ *           )
+ *       )
+ *   )
+ *
+ * (note: '⊕ 0xc5' inside camellia_f())
+ */
+.Lpre_tf_lo_s4:
+       .byte 0x45, 0x40, 0x2e, 0x2b, 0x4b, 0x4e, 0x20, 0x25
+       .byte 0x14, 0x11, 0x7f, 0x7a, 0x1a, 0x1f, 0x71, 0x74
+.Lpre_tf_hi_s4:
+       .byte 0x00, 0xf1, 0x8a, 0x7b, 0x09, 0xf8, 0x83, 0x72
+       .byte 0xad, 0x5c, 0x27, 0xd6, 0xa4, 0x55, 0x2e, 0xdf
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox1, sbox4:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  )
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s1:
+       .byte 0x3c, 0xcc, 0xcf, 0x3f, 0x32, 0xc2, 0xc1, 0x31
+       .byte 0xdc, 0x2c, 0x2f, 0xdf, 0xd2, 0x22, 0x21, 0xd1
+.Lpost_tf_hi_s1:
+       .byte 0x00, 0xf9, 0x86, 0x7f, 0xd7, 0x2e, 0x51, 0xa8
+       .byte 0xa4, 0x5d, 0x22, 0xdb, 0x73, 0x8a, 0xf5, 0x0c
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox2:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  ) <<< 1
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s2:
+       .byte 0x78, 0x99, 0x9f, 0x7e, 0x64, 0x85, 0x83, 0x62
+       .byte 0xb9, 0x58, 0x5e, 0xbf, 0xa5, 0x44, 0x42, 0xa3
+.Lpost_tf_hi_s2:
+       .byte 0x00, 0xf3, 0x0d, 0xfe, 0xaf, 0x5c, 0xa2, 0x51
+       .byte 0x49, 0xba, 0x44, 0xb7, 0xe6, 0x15, 0xeb, 0x18
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox3:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  ) >>> 1
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s3:
+       .byte 0x1e, 0x66, 0xe7, 0x9f, 0x19, 0x61, 0xe0, 0x98
+       .byte 0x6e, 0x16, 0x97, 0xef, 0x69, 0x11, 0x90, 0xe8
+.Lpost_tf_hi_s3:
+       .byte 0x00, 0xfc, 0x43, 0xbf, 0xeb, 0x17, 0xa8, 0x54
+       .byte 0x52, 0xae, 0x11, 0xed, 0xb9, 0x45, 0xfa, 0x06
+
+/* For isolating SubBytes from AESENCLAST, inverse shift row */
+.Linv_shift_row:
+       .byte 0x00, 0x0d, 0x0a, 0x07, 0x04, 0x01, 0x0e, 0x0b
+       .byte 0x08, 0x05, 0x02, 0x0f, 0x0c, 0x09, 0x06, 0x03
+
+/* 4-bit mask */
+.align 4
+.L0f0f0f0f:
+       .long 0x0f0f0f0f
+
+.text
+
+.align 8
+.type   __camellia_enc_blk16,@function;
+
+__camellia_enc_blk16:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rax: temporary storage, 256 bytes
+        *      %xmm0..%xmm15: 16 plaintext blocks
+        * output:
+        *      %xmm0..%xmm15: 16 encrypted blocks, order swapped:
+        *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
+        */
+
+       leaq 8 * 16(%rax), %rcx;
+
+       inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                     %xmm15, %rax, %rcx);
+
+       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 0);
+
+       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+             %xmm15,
+             ((key_table + (8) * 8) + 0)(CTX),
+             ((key_table + (8) * 8) + 4)(CTX),
+             ((key_table + (8) * 8) + 8)(CTX),
+             ((key_table + (8) * 8) + 12)(CTX));
+
+       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 8);
+
+       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+             %xmm15,
+             ((key_table + (16) * 8) + 0)(CTX),
+             ((key_table + (16) * 8) + 4)(CTX),
+             ((key_table + (16) * 8) + 8)(CTX),
+             ((key_table + (16) * 8) + 12)(CTX));
+
+       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 16);
+
+       movl $24, %r8d;
+       cmpl $16, key_length(CTX);
+       jne .Lenc_max32;
+
+.Lenc_done:
+       /* load CD for output */
+       vmovdqu 0 * 16(%rcx), %xmm8;
+       vmovdqu 1 * 16(%rcx), %xmm9;
+       vmovdqu 2 * 16(%rcx), %xmm10;
+       vmovdqu 3 * 16(%rcx), %xmm11;
+       vmovdqu 4 * 16(%rcx), %xmm12;
+       vmovdqu 5 * 16(%rcx), %xmm13;
+       vmovdqu 6 * 16(%rcx), %xmm14;
+       vmovdqu 7 * 16(%rcx), %xmm15;
+
+       outunpack16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                   %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                   %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
+
+       ret;
+
+.align 8
+.Lenc_max32:
+       movl $32, %r8d;
+
+       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+             %xmm15,
+             ((key_table + (24) * 8) + 0)(CTX),
+             ((key_table + (24) * 8) + 4)(CTX),
+             ((key_table + (24) * 8) + 8)(CTX),
+             ((key_table + (24) * 8) + 12)(CTX));
+
+       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 24);
+
+       jmp .Lenc_done;
+
+.align 8
+.type   __camellia_dec_blk16,@function;
+
+__camellia_dec_blk16:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rax: temporary storage, 256 bytes
+        *      %r8d: 24 for 16 byte key, 32 for larger
+        *      %xmm0..%xmm15: 16 encrypted blocks
+        * output:
+        *      %xmm0..%xmm15: 16 plaintext blocks, order swapped:
+        *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
+        */
+
+       leaq 8 * 16(%rax), %rcx;
+
+       inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                     %xmm15, %rax, %rcx);
+
+       cmpl $32, %r8d;
+       je .Ldec_max32;
+
+.Ldec_max24:
+       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 16);
+
+       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+             %xmm15,
+             ((key_table + (16) * 8) + 8)(CTX),
+             ((key_table + (16) * 8) + 12)(CTX),
+             ((key_table + (16) * 8) + 0)(CTX),
+             ((key_table + (16) * 8) + 4)(CTX));
+
+       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 8);
+
+       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+             %xmm15,
+             ((key_table + (8) * 8) + 8)(CTX),
+             ((key_table + (8) * 8) + 12)(CTX),
+             ((key_table + (8) * 8) + 0)(CTX),
+             ((key_table + (8) * 8) + 4)(CTX));
+
+       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 0);
+
+       /* load CD for output */
+       vmovdqu 0 * 16(%rcx), %xmm8;
+       vmovdqu 1 * 16(%rcx), %xmm9;
+       vmovdqu 2 * 16(%rcx), %xmm10;
+       vmovdqu 3 * 16(%rcx), %xmm11;
+       vmovdqu 4 * 16(%rcx), %xmm12;
+       vmovdqu 5 * 16(%rcx), %xmm13;
+       vmovdqu 6 * 16(%rcx), %xmm14;
+       vmovdqu 7 * 16(%rcx), %xmm15;
+
+       outunpack16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                   %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                   %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
+
+       ret;
+
+.align 8
+.Ldec_max32:
+       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rax, %rcx, 24);
+
+       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+             %xmm15,
+             ((key_table + (24) * 8) + 8)(CTX),
+             ((key_table + (24) * 8) + 12)(CTX),
+             ((key_table + (24) * 8) + 0)(CTX),
+             ((key_table + (24) * 8) + 4)(CTX));
+
+       jmp .Ldec_max24;
+
+.align 8
+.global camellia_ecb_enc_16way
+.type   camellia_ecb_enc_16way,@function;
+
+camellia_ecb_enc_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        */
+
+       inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rdx, (key_table)(CTX));
+
+       /* now dst can be used as temporary buffer (even in src == dst case) */
+       movq    %rsi, %rax;
+
+       call __camellia_enc_blk16;
+
+       write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+                    %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+                    %xmm8, %rsi);
+
+       ret;
+
+.align 8
+.global camellia_ecb_dec_16way
+.type   camellia_ecb_dec_16way,@function;
+
+camellia_ecb_dec_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        */
+
+       cmpl $16, key_length(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
+       inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rdx, (key_table)(CTX, %r8, 8));
+
+       /* now dst can be used as temporary buffer (even in src == dst case) */
+       movq    %rsi, %rax;
+
+       call __camellia_dec_blk16;
+
+       write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+                    %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+                    %xmm8, %rsi);
+
+       ret;
+
+.align 8
+.global camellia_cbc_dec_16way
+.type   camellia_cbc_dec_16way,@function;
+
+camellia_cbc_dec_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        */
+
+       cmpl $16, key_length(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
+       inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+                    %xmm15, %rdx, (key_table)(CTX, %r8, 8));
+
+       /*
+        * dst might still be in-use (in case dst == src), so use stack for
+        * temporary storage.
+        */
+       subq $(16 * 16), %rsp;
+       movq %rsp, %rax;
+
+       call __camellia_dec_blk16;
+
+       addq $(16 * 16), %rsp;
+
+       vpxor (0 * 16)(%rdx), %xmm6, %xmm6;
+       vpxor (1 * 16)(%rdx), %xmm5, %xmm5;
+       vpxor (2 * 16)(%rdx), %xmm4, %xmm4;
+       vpxor (3 * 16)(%rdx), %xmm3, %xmm3;
+       vpxor (4 * 16)(%rdx), %xmm2, %xmm2;
+       vpxor (5 * 16)(%rdx), %xmm1, %xmm1;
+       vpxor (6 * 16)(%rdx), %xmm0, %xmm0;
+       vpxor (7 * 16)(%rdx), %xmm15, %xmm15;
+       vpxor (8 * 16)(%rdx), %xmm14, %xmm14;
+       vpxor (9 * 16)(%rdx), %xmm13, %xmm13;
+       vpxor (10 * 16)(%rdx), %xmm12, %xmm12;
+       vpxor (11 * 16)(%rdx), %xmm11, %xmm11;
+       vpxor (12 * 16)(%rdx), %xmm10, %xmm10;
+       vpxor (13 * 16)(%rdx), %xmm9, %xmm9;
+       vpxor (14 * 16)(%rdx), %xmm8, %xmm8;
+       write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+                    %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+                    %xmm8, %rsi);
+
+       ret;
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+.align 8
+.global camellia_ctr_16way
+.type   camellia_ctr_16way,@function;
+
+camellia_ctr_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       subq $(16 * 16), %rsp;
+       movq %rsp, %rax;
+
+       vmovdqa .Lbswap128_mask, %xmm14;
+
+       /* load IV and byteswap */
+       vmovdqu (%rcx), %xmm0;
+       vpshufb %xmm14, %xmm0, %xmm15;
+       vmovdqu %xmm15, 15 * 16(%rax);
+
+       vpcmpeqd %xmm15, %xmm15, %xmm15;
+       vpsrldq $8, %xmm15, %xmm15; /* low: -1, high: 0 */
+
+       /* construct IVs */
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm13;
+       vmovdqu %xmm13, 14 * 16(%rax);
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm13;
+       vmovdqu %xmm13, 13 * 16(%rax);
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm12;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm11;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm10;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm9;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm8;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm7;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm6;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm5;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm4;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm3;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm2;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vpshufb %xmm14, %xmm0, %xmm1;
+       inc_le128(%xmm0, %xmm15, %xmm13);
+       vmovdqa %xmm0, %xmm13;
+       vpshufb %xmm14, %xmm0, %xmm0;
+       inc_le128(%xmm13, %xmm15, %xmm14);
+       vmovdqu %xmm13, (%rcx);
+
+       /* inpack16_pre: */
+       vmovq (key_table)(CTX), %xmm15;
+       vpshufb .Lpack_bswap, %xmm15, %xmm15;
+       vpxor %xmm0, %xmm15, %xmm0;
+       vpxor %xmm1, %xmm15, %xmm1;
+       vpxor %xmm2, %xmm15, %xmm2;
+       vpxor %xmm3, %xmm15, %xmm3;
+       vpxor %xmm4, %xmm15, %xmm4;
+       vpxor %xmm5, %xmm15, %xmm5;
+       vpxor %xmm6, %xmm15, %xmm6;
+       vpxor %xmm7, %xmm15, %xmm7;
+       vpxor %xmm8, %xmm15, %xmm8;
+       vpxor %xmm9, %xmm15, %xmm9;
+       vpxor %xmm10, %xmm15, %xmm10;
+       vpxor %xmm11, %xmm15, %xmm11;
+       vpxor %xmm12, %xmm15, %xmm12;
+       vpxor 13 * 16(%rax), %xmm15, %xmm13;
+       vpxor 14 * 16(%rax), %xmm15, %xmm14;
+       vpxor 15 * 16(%rax), %xmm15, %xmm15;
+
+       call __camellia_enc_blk16;
+
+       addq $(16 * 16), %rsp;
+
+       vpxor 0 * 16(%rdx), %xmm7, %xmm7;
+       vpxor 1 * 16(%rdx), %xmm6, %xmm6;
+       vpxor 2 * 16(%rdx), %xmm5, %xmm5;
+       vpxor 3 * 16(%rdx), %xmm4, %xmm4;
+       vpxor 4 * 16(%rdx), %xmm3, %xmm3;
+       vpxor 5 * 16(%rdx), %xmm2, %xmm2;
+       vpxor 6 * 16(%rdx), %xmm1, %xmm1;
+       vpxor 7 * 16(%rdx), %xmm0, %xmm0;
+       vpxor 8 * 16(%rdx), %xmm15, %xmm15;
+       vpxor 9 * 16(%rdx), %xmm14, %xmm14;
+       vpxor 10 * 16(%rdx), %xmm13, %xmm13;
+       vpxor 11 * 16(%rdx), %xmm12, %xmm12;
+       vpxor 12 * 16(%rdx), %xmm11, %xmm11;
+       vpxor 13 * 16(%rdx), %xmm10, %xmm10;
+       vpxor 14 * 16(%rdx), %xmm9, %xmm9;
+       vpxor 15 * 16(%rdx), %xmm8, %xmm8;
+       write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+                    %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+                    %xmm8, %rsi);
+
+       ret;
diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c
new file mode 100644 (file)
index 0000000..96cbb60
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * Glue Code for x86_64/AVX/AES-NI assembler optimized version of Camellia
+ *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * 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/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/algapi.h>
+#include <crypto/ctr.h>
+#include <crypto/lrw.h>
+#include <crypto/xts.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+#include <asm/crypto/camellia.h>
+#include <asm/crypto/ablk_helper.h>
+#include <asm/crypto/glue_helper.h>
+
+#define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
+
+/* 16-way AES-NI parallel cipher functions */
+asmlinkage void camellia_ecb_enc_16way(struct camellia_ctx *ctx, u8 *dst,
+                                      const u8 *src);
+asmlinkage void camellia_ecb_dec_16way(struct camellia_ctx *ctx, u8 *dst,
+                                      const u8 *src);
+
+asmlinkage void camellia_cbc_dec_16way(struct camellia_ctx *ctx, u8 *dst,
+                                      const u8 *src);
+asmlinkage void camellia_ctr_16way(struct camellia_ctx *ctx, u8 *dst,
+                                  const u8 *src, le128 *iv);
+
+static const struct common_glue_ctx camellia_enc = {
+       .num_funcs = 3,
+       .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+       .funcs = { {
+               .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+               .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_enc_16way) }
+       }, {
+               .num_blocks = 2,
+               .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk_2way) }
+       }, {
+               .num_blocks = 1,
+               .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk) }
+       } }
+};
+
+static const struct common_glue_ctx camellia_ctr = {
+       .num_funcs = 3,
+       .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+       .funcs = { {
+               .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_ctr_16way) }
+       }, {
+               .num_blocks = 2,
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way) }
+       }, {
+               .num_blocks = 1,
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr) }
+       } }
+};
+
+static const struct common_glue_ctx camellia_dec = {
+       .num_funcs = 3,
+       .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+       .funcs = { {
+               .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+               .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_dec_16way) }
+       }, {
+               .num_blocks = 2,
+               .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk_2way) }
+       }, {
+               .num_blocks = 1,
+               .fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk) }
+       } }
+};
+
+static const struct common_glue_ctx camellia_dec_cbc = {
+       .num_funcs = 3,
+       .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+       .funcs = { {
+               .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_cbc_dec_16way) }
+       }, {
+               .num_blocks = 2,
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way) }
+       }, {
+               .num_blocks = 1,
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_dec_blk) }
+       } }
+};
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       return glue_ecb_crypt_128bit(&camellia_enc, desc, dst, src, nbytes);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       return glue_ecb_crypt_128bit(&camellia_dec, desc, dst, src, nbytes);
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(camellia_enc_blk), desc,
+                                      dst, src, nbytes);
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       return glue_cbc_decrypt_128bit(&camellia_dec_cbc, desc, dst, src,
+                                      nbytes);
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                    struct scatterlist *src, unsigned int nbytes)
+{
+       return glue_ctr_crypt_128bit(&camellia_ctr, desc, dst, src, nbytes);
+}
+
+static inline bool camellia_fpu_begin(bool fpu_enabled, unsigned int nbytes)
+{
+       return glue_fpu_begin(CAMELLIA_BLOCK_SIZE,
+                             CAMELLIA_AESNI_PARALLEL_BLOCKS, NULL, fpu_enabled,
+                             nbytes);
+}
+
+static inline void camellia_fpu_end(bool fpu_enabled)
+{
+       glue_fpu_end(fpu_enabled);
+}
+
+static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+                          unsigned int key_len)
+{
+       return __camellia_setkey(crypto_tfm_ctx(tfm), in_key, key_len,
+                                &tfm->crt_flags);
+}
+
+struct crypt_priv {
+       struct camellia_ctx *ctx;
+       bool fpu_enabled;
+};
+
+static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
+{
+       const unsigned int bsize = CAMELLIA_BLOCK_SIZE;
+       struct crypt_priv *ctx = priv;
+       int i;
+
+       ctx->fpu_enabled = camellia_fpu_begin(ctx->fpu_enabled, nbytes);
+
+       if (nbytes >= CAMELLIA_AESNI_PARALLEL_BLOCKS * bsize) {
+               camellia_ecb_enc_16way(ctx->ctx, srcdst, srcdst);
+               srcdst += bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+               nbytes -= bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+       }
+
+       while (nbytes >= CAMELLIA_PARALLEL_BLOCKS * bsize) {
+               camellia_enc_blk_2way(ctx->ctx, srcdst, srcdst);
+               srcdst += bsize * CAMELLIA_PARALLEL_BLOCKS;
+               nbytes -= bsize * CAMELLIA_PARALLEL_BLOCKS;
+       }
+
+       for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
+               camellia_enc_blk(ctx->ctx, srcdst, srcdst);
+}
+
+static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
+{
+       const unsigned int bsize = CAMELLIA_BLOCK_SIZE;
+       struct crypt_priv *ctx = priv;
+       int i;
+
+       ctx->fpu_enabled = camellia_fpu_begin(ctx->fpu_enabled, nbytes);
+
+       if (nbytes >= CAMELLIA_AESNI_PARALLEL_BLOCKS * bsize) {
+               camellia_ecb_dec_16way(ctx->ctx, srcdst, srcdst);
+               srcdst += bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+               nbytes -= bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+       }
+
+       while (nbytes >= CAMELLIA_PARALLEL_BLOCKS * bsize) {
+               camellia_dec_blk_2way(ctx->ctx, srcdst, srcdst);
+               srcdst += bsize * CAMELLIA_PARALLEL_BLOCKS;
+               nbytes -= bsize * CAMELLIA_PARALLEL_BLOCKS;
+       }
+
+       for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
+               camellia_dec_blk(ctx->ctx, srcdst, srcdst);
+}
+
+static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       struct camellia_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+       struct crypt_priv crypt_ctx = {
+               .ctx = &ctx->camellia_ctx,
+               .fpu_enabled = false,
+       };
+       struct lrw_crypt_req req = {
+               .tbuf = buf,
+               .tbuflen = sizeof(buf),
+
+               .table_ctx = &ctx->lrw_table,
+               .crypt_ctx = &crypt_ctx,
+               .crypt_fn = encrypt_callback,
+       };
+       int ret;
+
+       desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+       ret = lrw_crypt(desc, dst, src, nbytes, &req);
+       camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+       return ret;
+}
+
+static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       struct camellia_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+       struct crypt_priv crypt_ctx = {
+               .ctx = &ctx->camellia_ctx,
+               .fpu_enabled = false,
+       };
+       struct lrw_crypt_req req = {
+               .tbuf = buf,
+               .tbuflen = sizeof(buf),
+
+               .table_ctx = &ctx->lrw_table,
+               .crypt_ctx = &crypt_ctx,
+               .crypt_fn = decrypt_callback,
+       };
+       int ret;
+
+       desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+       ret = lrw_crypt(desc, dst, src, nbytes, &req);
+       camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+       return ret;
+}
+
+static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       struct camellia_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+       struct crypt_priv crypt_ctx = {
+               .ctx = &ctx->crypt_ctx,
+               .fpu_enabled = false,
+       };
+       struct xts_crypt_req req = {
+               .tbuf = buf,
+               .tbuflen = sizeof(buf),
+
+               .tweak_ctx = &ctx->tweak_ctx,
+               .tweak_fn = XTS_TWEAK_CAST(camellia_enc_blk),
+               .crypt_ctx = &crypt_ctx,
+               .crypt_fn = encrypt_callback,
+       };
+       int ret;
+
+       desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+       ret = xts_crypt(desc, dst, src, nbytes, &req);
+       camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+       return ret;
+}
+
+static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                      struct scatterlist *src, unsigned int nbytes)
+{
+       struct camellia_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+       struct crypt_priv crypt_ctx = {
+               .ctx = &ctx->crypt_ctx,
+               .fpu_enabled = false,
+       };
+       struct xts_crypt_req req = {
+               .tbuf = buf,
+               .tbuflen = sizeof(buf),
+
+               .tweak_ctx = &ctx->tweak_ctx,
+               .tweak_fn = XTS_TWEAK_CAST(camellia_enc_blk),
+               .crypt_ctx = &crypt_ctx,
+               .crypt_fn = decrypt_callback,
+       };
+       int ret;
+
+       desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+       ret = xts_crypt(desc, dst, src, nbytes, &req);
+       camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+       return ret;
+}
+
+static struct crypto_alg cmll_algs[10] = { {
+       .cra_name               = "__ecb-camellia-aesni",
+       .cra_driver_name        = "__driver-ecb-camellia-aesni",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct camellia_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_u = {
+               .blkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .setkey         = camellia_setkey,
+                       .encrypt        = ecb_encrypt,
+                       .decrypt        = ecb_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "__cbc-camellia-aesni",
+       .cra_driver_name        = "__driver-cbc-camellia-aesni",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct camellia_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_u = {
+               .blkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .setkey         = camellia_setkey,
+                       .encrypt        = cbc_encrypt,
+                       .decrypt        = cbc_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "__ctr-camellia-aesni",
+       .cra_driver_name        = "__driver-ctr-camellia-aesni",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = 1,
+       .cra_ctxsize            = sizeof(struct camellia_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_u = {
+               .blkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = camellia_setkey,
+                       .encrypt        = ctr_crypt,
+                       .decrypt        = ctr_crypt,
+               },
+       },
+}, {
+       .cra_name               = "__lrw-camellia-aesni",
+       .cra_driver_name        = "__driver-lrw-camellia-aesni",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct camellia_lrw_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_exit               = lrw_camellia_exit_tfm,
+       .cra_u = {
+               .blkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE +
+                                         CAMELLIA_BLOCK_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE +
+                                         CAMELLIA_BLOCK_SIZE,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = lrw_camellia_setkey,
+                       .encrypt        = lrw_encrypt,
+                       .decrypt        = lrw_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "__xts-camellia-aesni",
+       .cra_driver_name        = "__driver-xts-camellia-aesni",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct camellia_xts_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_u = {
+               .blkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE * 2,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE * 2,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = xts_camellia_setkey,
+                       .encrypt        = xts_encrypt,
+                       .decrypt        = xts_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "ecb(camellia)",
+       .cra_driver_name        = "ecb-camellia-aesni",
+       .cra_priority           = 400,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_u = {
+               .ablkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .setkey         = ablk_set_key,
+                       .encrypt        = ablk_encrypt,
+                       .decrypt        = ablk_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "cbc(camellia)",
+       .cra_driver_name        = "cbc-camellia-aesni",
+       .cra_priority           = 400,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_u = {
+               .ablkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = ablk_set_key,
+                       .encrypt        = __ablk_encrypt,
+                       .decrypt        = ablk_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "ctr(camellia)",
+       .cra_driver_name        = "ctr-camellia-aesni",
+       .cra_priority           = 400,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = 1,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_u = {
+               .ablkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = ablk_set_key,
+                       .encrypt        = ablk_encrypt,
+                       .decrypt        = ablk_encrypt,
+                       .geniv          = "chainiv",
+               },
+       },
+}, {
+       .cra_name               = "lrw(camellia)",
+       .cra_driver_name        = "lrw-camellia-aesni",
+       .cra_priority           = 400,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_u = {
+               .ablkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE +
+                                         CAMELLIA_BLOCK_SIZE,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE +
+                                         CAMELLIA_BLOCK_SIZE,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = ablk_set_key,
+                       .encrypt        = ablk_encrypt,
+                       .decrypt        = ablk_decrypt,
+               },
+       },
+}, {
+       .cra_name               = "xts(camellia)",
+       .cra_driver_name        = "xts-camellia-aesni",
+       .cra_priority           = 400,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = CAMELLIA_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 0,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_u = {
+               .ablkcipher = {
+                       .min_keysize    = CAMELLIA_MIN_KEY_SIZE * 2,
+                       .max_keysize    = CAMELLIA_MAX_KEY_SIZE * 2,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
+                       .setkey         = ablk_set_key,
+                       .encrypt        = ablk_encrypt,
+                       .decrypt        = ablk_decrypt,
+               },
+       },
+} };
+
+static int __init camellia_aesni_init(void)
+{
+       u64 xcr0;
+
+       if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+               pr_info("AVX or AES-NI instructions are not detected.\n");
+               return -ENODEV;
+       }
+
+       xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+       if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+               pr_info("AVX detected but unusable.\n");
+               return -ENODEV;
+       }
+
+       return crypto_register_algs(cmll_algs, ARRAY_SIZE(cmll_algs));
+}
+
+static void __exit camellia_aesni_fini(void)
+{
+       crypto_unregister_algs(cmll_algs, ARRAY_SIZE(cmll_algs));
+}
+
+module_init(camellia_aesni_init);
+module_exit(camellia_aesni_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX optimized");
+MODULE_ALIAS("camellia");
+MODULE_ALIAS("camellia-asm");
index 42ffd2bbab5bb9e18de2695d1f5814e4c5b43958..5cb86ccd4acb9e6e105098525cb8fd7592a0cbd6 100644 (file)
 #include <crypto/algapi.h>
 #include <crypto/lrw.h>
 #include <crypto/xts.h>
+#include <asm/crypto/camellia.h>
 #include <asm/crypto/glue_helper.h>
 
-#define CAMELLIA_MIN_KEY_SIZE  16
-#define CAMELLIA_MAX_KEY_SIZE  32
-#define CAMELLIA_BLOCK_SIZE    16
-#define CAMELLIA_TABLE_BYTE_LEN        272
-
-struct camellia_ctx {
-       u64 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
-       u32 key_length;
-};
-
 /* regular block cipher functions */
 asmlinkage void __camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
                                   const u8 *src, bool xor);
+EXPORT_SYMBOL_GPL(__camellia_enc_blk);
 asmlinkage void camellia_dec_blk(struct camellia_ctx *ctx, u8 *dst,
                                 const u8 *src);
+EXPORT_SYMBOL_GPL(camellia_dec_blk);
 
 /* 2-way parallel cipher functions */
 asmlinkage void __camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
                                        const u8 *src, bool xor);
+EXPORT_SYMBOL_GPL(__camellia_enc_blk_2way);
 asmlinkage void camellia_dec_blk_2way(struct camellia_ctx *ctx, u8 *dst,
                                      const u8 *src);
-
-static inline void camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
-                                   const u8 *src)
-{
-       __camellia_enc_blk(ctx, dst, src, false);
-}
-
-static inline void camellia_enc_blk_xor(struct camellia_ctx *ctx, u8 *dst,
-                                       const u8 *src)
-{
-       __camellia_enc_blk(ctx, dst, src, true);
-}
-
-static inline void camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
-                                        const u8 *src)
-{
-       __camellia_enc_blk_2way(ctx, dst, src, false);
-}
-
-static inline void camellia_enc_blk_xor_2way(struct camellia_ctx *ctx, u8 *dst,
-                                            const u8 *src)
-{
-       __camellia_enc_blk_2way(ctx, dst, src, true);
-}
+EXPORT_SYMBOL_GPL(camellia_dec_blk_2way);
 
 static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
@@ -1275,9 +1246,8 @@ static void camellia_setup192(const unsigned char *key, u64 *subkey)
        camellia_setup256(kk, subkey);
 }
 
-static int __camellia_setkey(struct camellia_ctx *cctx,
-                            const unsigned char *key,
-                            unsigned int key_len, u32 *flags)
+int __camellia_setkey(struct camellia_ctx *cctx, const unsigned char *key,
+                     unsigned int key_len, u32 *flags)
 {
        if (key_len != 16 && key_len != 24 && key_len != 32) {
                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -1300,6 +1270,7 @@ static int __camellia_setkey(struct camellia_ctx *cctx,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(__camellia_setkey);
 
 static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key,
                           unsigned int key_len)
@@ -1308,7 +1279,7 @@ static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key,
                                 &tfm->crt_flags);
 }
 
-static void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
+void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
 {
        u128 iv = *src;
 
@@ -1316,22 +1287,23 @@ static void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
 
        u128_xor(&dst[1], &dst[1], &iv);
 }
+EXPORT_SYMBOL_GPL(camellia_decrypt_cbc_2way);
 
-static void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
        if (dst != src)
                *dst = *src;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        camellia_enc_blk_xor(ctx, (u8 *)dst, (u8 *)&ctrblk);
 }
+EXPORT_SYMBOL_GPL(camellia_crypt_ctr);
 
-static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
-                                   u128 *iv)
+void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblks[2];
 
@@ -1340,13 +1312,14 @@ static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
                dst[1] = src[1];
        }
 
-       u128_to_be128(&ctrblks[0], iv);
-       u128_inc(iv);
-       u128_to_be128(&ctrblks[1], iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblks[0], iv);
+       le128_inc(iv);
+       le128_to_be128(&ctrblks[1], iv);
+       le128_inc(iv);
 
        camellia_enc_blk_xor_2way(ctx, (u8 *)dst, (u8 *)ctrblks);
 }
+EXPORT_SYMBOL_GPL(camellia_crypt_ctr_2way);
 
 static const struct common_glue_ctx camellia_enc = {
        .num_funcs = 2,
@@ -1464,13 +1437,8 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
                camellia_dec_blk(ctx, srcdst, srcdst);
 }
 
-struct camellia_lrw_ctx {
-       struct lrw_table_ctx lrw_table;
-       struct camellia_ctx camellia_ctx;
-};
-
-static int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
-                             unsigned int keylen)
+int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+                       unsigned int keylen)
 {
        struct camellia_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
        int err;
@@ -1484,6 +1452,7 @@ static int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
        return lrw_init_table(&ctx->lrw_table,
                              key + keylen - CAMELLIA_BLOCK_SIZE);
 }
+EXPORT_SYMBOL_GPL(lrw_camellia_setkey);
 
 static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                       struct scatterlist *src, unsigned int nbytes)
@@ -1519,20 +1488,16 @@ static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
        return lrw_crypt(desc, dst, src, nbytes, &req);
 }
 
-static void lrw_exit_tfm(struct crypto_tfm *tfm)
+void lrw_camellia_exit_tfm(struct crypto_tfm *tfm)
 {
        struct camellia_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
 
        lrw_free_table(&ctx->lrw_table);
 }
+EXPORT_SYMBOL_GPL(lrw_camellia_exit_tfm);
 
-struct camellia_xts_ctx {
-       struct camellia_ctx tweak_ctx;
-       struct camellia_ctx crypt_ctx;
-};
-
-static int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
-                             unsigned int keylen)
+int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+                       unsigned int keylen)
 {
        struct camellia_xts_ctx *ctx = crypto_tfm_ctx(tfm);
        u32 *flags = &tfm->crt_flags;
@@ -1555,6 +1520,7 @@ static int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
        return __camellia_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2,
                                flags);
 }
+EXPORT_SYMBOL_GPL(xts_camellia_setkey);
 
 static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                       struct scatterlist *src, unsigned int nbytes)
@@ -1679,7 +1645,7 @@ static struct crypto_alg camellia_algs[6] = { {
        .cra_alignmask          = 0,
        .cra_type               = &crypto_blkcipher_type,
        .cra_module             = THIS_MODULE,
-       .cra_exit               = lrw_exit_tfm,
+       .cra_exit               = lrw_camellia_exit_tfm,
        .cra_u = {
                .blkcipher = {
                        .min_keysize    = CAMELLIA_MIN_KEY_SIZE +
index a41a3aaba220ded5fe44ae0e79c5cd3fe2b41228..15b00ac7cbd3a0e505229f205892055d7569445b 100644 (file)
 
 .file "cast5-avx-x86_64-asm_64.S"
 
-.extern cast5_s1
-.extern cast5_s2
-.extern cast5_s3
-.extern cast5_s4
+.extern cast_s1
+.extern cast_s2
+.extern cast_s3
+.extern cast_s4
 
 /* structure of crypto context */
 #define km     0
 #define rr     ((16*4)+16)
 
 /* s-boxes */
-#define s1     cast5_s1
-#define s2     cast5_s2
-#define s3     cast5_s3
-#define s4     cast5_s4
+#define s1     cast_s1
+#define s2     cast_s2
+#define s3     cast_s3
+#define s4     cast_s4
 
 /**********************************************************************
   16-way AVX cast5
        vpunpcklqdq             t1, t0, x0; \
        vpunpckhqdq             t1, t0, x1;
 
-#define inpack_blocks(in, x0, x1, t0, t1, rmask) \
-       vmovdqu (0*4*4)(in),    x0; \
-       vmovdqu (1*4*4)(in),    x1; \
+#define inpack_blocks(x0, x1, t0, t1, rmask) \
        vpshufb rmask,  x0,     x0; \
        vpshufb rmask,  x1,     x1; \
        \
        transpose_2x4(x0, x1, t0, t1)
 
-#define outunpack_blocks(out, x0, x1, t0, t1, rmask) \
+#define outunpack_blocks(x0, x1, t0, t1, rmask) \
        transpose_2x4(x0, x1, t0, t1) \
        \
        vpshufb rmask,  x0, x0;           \
-       vpshufb rmask,  x1, x1;           \
-       vmovdqu         x0, (0*4*4)(out); \
-       vmovdqu         x1, (1*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, t0, t1, rmask) \
-       transpose_2x4(x0, x1, t0, t1) \
-       \
-       vpshufb rmask,  x0, x0;               \
-       vpshufb rmask,  x1, x1;               \
-       vpxor           (0*4*4)(out), x0, x0; \
-       vmovdqu         x0, (0*4*4)(out);     \
-       vpxor           (1*4*4)(out), x1, x1; \
-       vmovdqu         x1, (1*4*4)(out);
+       vpshufb rmask,  x1, x1;
 
 .data
 
        .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
 .Lbswap128_mask:
        .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.Lbswap_iv_mask:
+       .byte 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0
 .L16_mask:
        .byte 16, 16, 16, 16
 .L32_mask:
 .text
 
 .align 16
-.global __cast5_enc_blk_16way
-.type   __cast5_enc_blk_16way,@function;
+.type   __cast5_enc_blk16,@function;
 
-__cast5_enc_blk_16way:
+__cast5_enc_blk16:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RL1: blocks 1 and 2
+        *      RR1: blocks 3 and 4
+        *      RL2: blocks 5 and 6
+        *      RR2: blocks 7 and 8
+        *      RL3: blocks 9 and 10
+        *      RR3: blocks 11 and 12
+        *      RL4: blocks 13 and 14
+        *      RR4: blocks 15 and 16
+        * output:
+        *      RL1: encrypted blocks 1 and 2
+        *      RR1: encrypted blocks 3 and 4
+        *      RL2: encrypted blocks 5 and 6
+        *      RR2: encrypted blocks 7 and 8
+        *      RL3: encrypted blocks 9 and 10
+        *      RR3: encrypted blocks 11 and 12
+        *      RL4: encrypted blocks 13 and 14
+        *      RR4: encrypted blocks 15 and 16
         */
 
        pushq %rbp;
        pushq %rbx;
-       pushq %rcx;
 
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
        enc_preload_rkr();
 
-       leaq 1*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
-       inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RL1, RR1, RTMP, RX, RKM);
+       inpack_blocks(RL2, RR2, RTMP, RX, RKM);
+       inpack_blocks(RL3, RR3, RTMP, RX, RKM);
+       inpack_blocks(RL4, RR4, RTMP, RX, RKM);
 
        round(RL, RR, 0, 1);
        round(RR, RL, 1, 2);
@@ -276,44 +271,41 @@ __cast5_enc_blk_16way:
        round(RR, RL, 15, 1);
 
 __skip_enc:
-       popq %rcx;
        popq %rbx;
        popq %rbp;
 
        vmovdqa .Lbswap_mask, RKM;
-       leaq 1*(2*4*4)(%r11), %rax;
 
-       testb %cl, %cl;
-       jnz __enc_xor16;
-
-       outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-       outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
-
-       ret;
-
-__enc_xor16:
-       outunpack_xor_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-       outunpack_xor_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%r11), %rax;
-       outunpack_xor_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%r11), %rax;
-       outunpack_xor_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+       outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
+       outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
+       outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+       outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
 
        ret;
 
 .align 16
-.global cast5_dec_blk_16way
-.type   cast5_dec_blk_16way,@function;
+.type   __cast5_dec_blk16,@function;
 
-cast5_dec_blk_16way:
+__cast5_dec_blk16:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RL1: encrypted blocks 1 and 2
+        *      RR1: encrypted blocks 3 and 4
+        *      RL2: encrypted blocks 5 and 6
+        *      RR2: encrypted blocks 7 and 8
+        *      RL3: encrypted blocks 9 and 10
+        *      RR3: encrypted blocks 11 and 12
+        *      RL4: encrypted blocks 13 and 14
+        *      RR4: encrypted blocks 15 and 16
+        * output:
+        *      RL1: decrypted blocks 1 and 2
+        *      RR1: decrypted blocks 3 and 4
+        *      RL2: decrypted blocks 5 and 6
+        *      RR2: decrypted blocks 7 and 8
+        *      RL3: decrypted blocks 9 and 10
+        *      RR3: decrypted blocks 11 and 12
+        *      RL4: decrypted blocks 13 and 14
+        *      RR4: decrypted blocks 15 and 16
         */
 
        pushq %rbp;
@@ -324,15 +316,10 @@ cast5_dec_blk_16way:
        vmovd .L32_mask, R32;
        dec_preload_rkr();
 
-       leaq 1*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
-       inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%rdx), %rax;
-       inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RL1, RR1, RTMP, RX, RKM);
+       inpack_blocks(RL2, RR2, RTMP, RX, RKM);
+       inpack_blocks(RL3, RR3, RTMP, RX, RKM);
+       inpack_blocks(RL4, RR4, RTMP, RX, RKM);
 
        movzbl rr(CTX), %eax;
        testl %eax, %eax;
@@ -361,16 +348,211 @@ __dec_tail:
        popq %rbx;
        popq %rbp;
 
-       leaq 1*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-       outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-       leaq 2*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-       leaq 3*(2*4*4)(%r11), %rax;
-       outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+       outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
+       outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
+       outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+       outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
 
        ret;
 
 __skip_dec:
        vpsrldq $4, RKR, RKR;
        jmp __dec_tail;
+
+.align 16
+.global cast5_ecb_enc_16way
+.type   cast5_ecb_enc_16way,@function;
+
+cast5_ecb_enc_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       vmovdqu (0*4*4)(%rdx), RL1;
+       vmovdqu (1*4*4)(%rdx), RR1;
+       vmovdqu (2*4*4)(%rdx), RL2;
+       vmovdqu (3*4*4)(%rdx), RR2;
+       vmovdqu (4*4*4)(%rdx), RL3;
+       vmovdqu (5*4*4)(%rdx), RR3;
+       vmovdqu (6*4*4)(%rdx), RL4;
+       vmovdqu (7*4*4)(%rdx), RR4;
+
+       call __cast5_enc_blk16;
+
+       vmovdqu RR1, (0*4*4)(%r11);
+       vmovdqu RL1, (1*4*4)(%r11);
+       vmovdqu RR2, (2*4*4)(%r11);
+       vmovdqu RL2, (3*4*4)(%r11);
+       vmovdqu RR3, (4*4*4)(%r11);
+       vmovdqu RL3, (5*4*4)(%r11);
+       vmovdqu RR4, (6*4*4)(%r11);
+       vmovdqu RL4, (7*4*4)(%r11);
+
+       ret;
+
+.align 16
+.global cast5_ecb_dec_16way
+.type   cast5_ecb_dec_16way,@function;
+
+cast5_ecb_dec_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       vmovdqu (0*4*4)(%rdx), RL1;
+       vmovdqu (1*4*4)(%rdx), RR1;
+       vmovdqu (2*4*4)(%rdx), RL2;
+       vmovdqu (3*4*4)(%rdx), RR2;
+       vmovdqu (4*4*4)(%rdx), RL3;
+       vmovdqu (5*4*4)(%rdx), RR3;
+       vmovdqu (6*4*4)(%rdx), RL4;
+       vmovdqu (7*4*4)(%rdx), RR4;
+
+       call __cast5_dec_blk16;
+
+       vmovdqu RR1, (0*4*4)(%r11);
+       vmovdqu RL1, (1*4*4)(%r11);
+       vmovdqu RR2, (2*4*4)(%r11);
+       vmovdqu RL2, (3*4*4)(%r11);
+       vmovdqu RR3, (4*4*4)(%r11);
+       vmovdqu RL3, (5*4*4)(%r11);
+       vmovdqu RR4, (6*4*4)(%r11);
+       vmovdqu RL4, (7*4*4)(%r11);
+
+       ret;
+
+.align 16
+.global cast5_cbc_dec_16way
+.type   cast5_cbc_dec_16way,@function;
+
+cast5_cbc_dec_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       vmovdqu (0*16)(%rdx), RL1;
+       vmovdqu (1*16)(%rdx), RR1;
+       vmovdqu (2*16)(%rdx), RL2;
+       vmovdqu (3*16)(%rdx), RR2;
+       vmovdqu (4*16)(%rdx), RL3;
+       vmovdqu (5*16)(%rdx), RR3;
+       vmovdqu (6*16)(%rdx), RL4;
+       vmovdqu (7*16)(%rdx), RR4;
+
+       call __cast5_dec_blk16;
+
+       /* xor with src */
+       vmovq (%r12), RX;
+       vpshufd $0x4f, RX, RX;
+       vpxor RX, RR1, RR1;
+       vpxor 0*16+8(%r12), RL1, RL1;
+       vpxor 1*16+8(%r12), RR2, RR2;
+       vpxor 2*16+8(%r12), RL2, RL2;
+       vpxor 3*16+8(%r12), RR3, RR3;
+       vpxor 4*16+8(%r12), RL3, RL3;
+       vpxor 5*16+8(%r12), RR4, RR4;
+       vpxor 6*16+8(%r12), RL4, RL4;
+
+       vmovdqu RR1, (0*16)(%r11);
+       vmovdqu RL1, (1*16)(%r11);
+       vmovdqu RR2, (2*16)(%r11);
+       vmovdqu RL2, (3*16)(%r11);
+       vmovdqu RR3, (4*16)(%r11);
+       vmovdqu RL3, (5*16)(%r11);
+       vmovdqu RR4, (6*16)(%r11);
+       vmovdqu RL4, (7*16)(%r11);
+
+       popq %r12;
+
+       ret;
+
+.align 16
+.global cast5_ctr_16way
+.type   cast5_ctr_16way,@function;
+
+cast5_ctr_16way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (big endian, 64bit)
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       vpcmpeqd RTMP, RTMP, RTMP;
+       vpsrldq $8, RTMP, RTMP; /* low: -1, high: 0 */
+
+       vpcmpeqd RKR, RKR, RKR;
+       vpaddq RKR, RKR, RKR; /* low: -2, high: -2 */
+       vmovdqa .Lbswap_iv_mask, R1ST;
+       vmovdqa .Lbswap128_mask, RKM;
+
+       /* load IV and byteswap */
+       vmovq (%rcx), RX;
+       vpshufb R1ST, RX, RX;
+
+       /* construct IVs */
+       vpsubq RTMP, RX, RX;  /* le: IV1, IV0 */
+       vpshufb RKM, RX, RL1; /* be: IV0, IV1 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR1; /* be: IV2, IV3 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RL2; /* be: IV4, IV5 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR2; /* be: IV6, IV7 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RL3; /* be: IV8, IV9 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR3; /* be: IV10, IV11 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RL4; /* be: IV12, IV13 */
+       vpsubq RKR, RX, RX;
+       vpshufb RKM, RX, RR4; /* be: IV14, IV15 */
+
+       /* store last IV */
+       vpsubq RTMP, RX, RX; /* le: IV16, IV14 */
+       vpshufb R1ST, RX, RX; /* be: IV16, IV16 */
+       vmovq RX, (%rcx);
+
+       call __cast5_enc_blk16;
+
+       /* dst = src ^ iv */
+       vpxor (0*16)(%r12), RR1, RR1;
+       vpxor (1*16)(%r12), RL1, RL1;
+       vpxor (2*16)(%r12), RR2, RR2;
+       vpxor (3*16)(%r12), RL2, RL2;
+       vpxor (4*16)(%r12), RR3, RR3;
+       vpxor (5*16)(%r12), RL3, RL3;
+       vpxor (6*16)(%r12), RR4, RR4;
+       vpxor (7*16)(%r12), RL4, RL4;
+       vmovdqu RR1, (0*16)(%r11);
+       vmovdqu RL1, (1*16)(%r11);
+       vmovdqu RR2, (2*16)(%r11);
+       vmovdqu RL2, (3*16)(%r11);
+       vmovdqu RR3, (4*16)(%r11);
+       vmovdqu RL3, (5*16)(%r11);
+       vmovdqu RR4, (6*16)(%r11);
+       vmovdqu RL4, (7*16)(%r11);
+
+       popq %r12;
+
+       ret;
index e0ea14f9547f269cb667868f137f5d3fc704d288..c6631813dc115c609e186044790aa5461cb6f0c7 100644 (file)
 
 #define CAST5_PARALLEL_BLOCKS 16
 
-asmlinkage void __cast5_enc_blk_16way(struct cast5_ctx *ctx, u8 *dst,
-                                     const u8 *src, bool xor);
-asmlinkage void cast5_dec_blk_16way(struct cast5_ctx *ctx, u8 *dst,
+asmlinkage void cast5_ecb_enc_16way(struct cast5_ctx *ctx, u8 *dst,
                                    const u8 *src);
-
-static inline void cast5_enc_blk_xway(struct cast5_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       __cast5_enc_blk_16way(ctx, dst, src, false);
-}
-
-static inline void cast5_enc_blk_xway_xor(struct cast5_ctx *ctx, u8 *dst,
-                                         const u8 *src)
-{
-       __cast5_enc_blk_16way(ctx, dst, src, true);
-}
-
-static inline void cast5_dec_blk_xway(struct cast5_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       cast5_dec_blk_16way(ctx, dst, src);
-}
-
+asmlinkage void cast5_ecb_dec_16way(struct cast5_ctx *ctx, u8 *dst,
+                                   const u8 *src);
+asmlinkage void cast5_cbc_dec_16way(struct cast5_ctx *ctx, u8 *dst,
+                                   const u8 *src);
+asmlinkage void cast5_ctr_16way(struct cast5_ctx *ctx, u8 *dst, const u8 *src,
+                               __be64 *iv);
 
 static inline bool cast5_fpu_begin(bool fpu_enabled, unsigned int nbytes)
 {
@@ -79,8 +64,11 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
        struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        const unsigned int bsize = CAST5_BLOCK_SIZE;
        unsigned int nbytes;
+       void (*fn)(struct cast5_ctx *ctx, u8 *dst, const u8 *src);
        int err;
 
+       fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way;
+
        err = blkcipher_walk_virt(desc, walk);
        desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
@@ -93,10 +81,7 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
                /* Process multi-block batch */
                if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
                        do {
-                               if (enc)
-                                       cast5_enc_blk_xway(ctx, wdst, wsrc);
-                               else
-                                       cast5_dec_blk_xway(ctx, wdst, wsrc);
+                               fn(ctx, wdst, wsrc);
 
                                wsrc += bsize * CAST5_PARALLEL_BLOCKS;
                                wdst += bsize * CAST5_PARALLEL_BLOCKS;
@@ -107,12 +92,11 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
                                goto done;
                }
 
+               fn = (enc) ? __cast5_encrypt : __cast5_decrypt;
+
                /* Handle leftovers */
                do {
-                       if (enc)
-                               __cast5_encrypt(ctx, wdst, wsrc);
-                       else
-                               __cast5_decrypt(ctx, wdst, wsrc);
+                       fn(ctx, wdst, wsrc);
 
                        wsrc += bsize;
                        wdst += bsize;
@@ -194,9 +178,7 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
        unsigned int nbytes = walk->nbytes;
        u64 *src = (u64 *)walk->src.virt.addr;
        u64 *dst = (u64 *)walk->dst.virt.addr;
-       u64 ivs[CAST5_PARALLEL_BLOCKS - 1];
        u64 last_iv;
-       int i;
 
        /* Start of the last block. */
        src += nbytes / bsize - 1;
@@ -211,13 +193,7 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
                        src -= CAST5_PARALLEL_BLOCKS - 1;
                        dst -= CAST5_PARALLEL_BLOCKS - 1;
 
-                       for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
-                               ivs[i] = src[i];
-
-                       cast5_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-                       for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
-                               *(dst + (i + 1)) ^= *(ivs + i);
+                       cast5_cbc_dec_16way(ctx, (u8 *)dst, (u8 *)src);
 
                        nbytes -= bsize;
                        if (nbytes < bsize)
@@ -298,23 +274,12 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
        unsigned int nbytes = walk->nbytes;
        u64 *src = (u64 *)walk->src.virt.addr;
        u64 *dst = (u64 *)walk->dst.virt.addr;
-       u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
-       __be64 ctrblocks[CAST5_PARALLEL_BLOCKS];
-       int i;
 
        /* Process multi-block batch */
        if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
                do {
-                       /* create ctrblks for parallel encrypt */
-                       for (i = 0; i < CAST5_PARALLEL_BLOCKS; i++) {
-                               if (dst != src)
-                                       dst[i] = src[i];
-
-                               ctrblocks[i] = cpu_to_be64(ctrblk++);
-                       }
-
-                       cast5_enc_blk_xway_xor(ctx, (u8 *)dst,
-                                              (u8 *)ctrblocks);
+                       cast5_ctr_16way(ctx, (u8 *)dst, (u8 *)src,
+                                       (__be64 *)walk->iv);
 
                        src += CAST5_PARALLEL_BLOCKS;
                        dst += CAST5_PARALLEL_BLOCKS;
@@ -327,13 +292,16 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
 
        /* Handle leftovers */
        do {
+               u64 ctrblk;
+
                if (dst != src)
                        *dst = *src;
 
-               ctrblocks[0] = cpu_to_be64(ctrblk++);
+               ctrblk = *(u64 *)walk->iv;
+               be64_add_cpu((__be64 *)walk->iv, 1);
 
-               __cast5_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
-               *dst ^= ctrblocks[0];
+               __cast5_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
+               *dst ^= ctrblk;
 
                src += 1;
                dst += 1;
@@ -341,7 +309,6 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
        } while (nbytes >= bsize);
 
 done:
-       *(__be64 *)walk->iv = cpu_to_be64(ctrblk);
        return nbytes;
 }
 
index 218d283772f420339e8ef7be42adb184e829753d..2569d0da841f1069f82d0a49ddcd003588310496 100644 (file)
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "cast6-avx-x86_64-asm_64.S"
 
-.extern cast6_s1
-.extern cast6_s2
-.extern cast6_s3
-.extern cast6_s4
+.extern cast_s1
+.extern cast_s2
+.extern cast_s3
+.extern cast_s4
 
 /* structure of crypto context */
 #define km     0
 #define kr     (12*4*4)
 
 /* s-boxes */
-#define s1     cast6_s1
-#define s2     cast6_s2
-#define s3     cast6_s3
-#define s4     cast6_s4
+#define s1     cast_s1
+#define s2     cast_s2
+#define s3     cast_s3
+#define s4     cast_s4
 
 /**********************************************************************
   8-way AVX cast6
        vpunpcklqdq             x3, t2, x2; \
        vpunpckhqdq             x3, t2, x3;
 
-#define inpack_blocks(in, x0, x1, x2, x3, t0, t1, t2, rmask) \
-       vmovdqu (0*4*4)(in),    x0; \
-       vmovdqu (1*4*4)(in),    x1; \
-       vmovdqu (2*4*4)(in),    x2; \
-       vmovdqu (3*4*4)(in),    x3; \
+#define inpack_blocks(x0, x1, x2, x3, t0, t1, t2, rmask) \
        vpshufb rmask, x0,      x0; \
        vpshufb rmask, x1,      x1; \
        vpshufb rmask, x2,      x2; \
        \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define outunpack_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
+#define outunpack_blocks(x0, x1, x2, x3, t0, t1, t2, rmask) \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
        \
        vpshufb rmask,          x0, x0;       \
        vpshufb rmask,          x1, x1;       \
        vpshufb rmask,          x2, x2;       \
-       vpshufb rmask,          x3, x3;       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vmovdqu x1,             (1*4*4)(out); \
-       vmovdqu x2,             (2*4*4)(out); \
-       vmovdqu x3,             (3*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vpshufb rmask,          x0, x0;       \
-       vpshufb rmask,          x1, x1;       \
-       vpshufb rmask,          x2, x2;       \
-       vpshufb rmask,          x3, x3;       \
-       vpxor (0*4*4)(out),     x0, x0;       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vpxor (1*4*4)(out),     x1, x1;       \
-       vmovdqu x1,             (1*4*4)(out); \
-       vpxor (2*4*4)(out),     x2, x2;       \
-       vmovdqu x2,             (2*4*4)(out); \
-       vpxor (3*4*4)(out),     x3, x3;       \
-       vmovdqu x3,             (3*4*4)(out);
+       vpshufb rmask,          x3, x3;
 
 .data
 
 .align 16
 .Lbswap_mask:
        .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
 .Lrkr_enc_Q_Q_QBAR_QBAR:
        .byte 0, 1, 2, 3, 4, 5, 6, 7, 11, 10, 9, 8, 15, 14, 13, 12
 .Lrkr_enc_QBAR_QBAR_QBAR_QBAR:
 
 .text
 
-.align 16
-.global __cast6_enc_blk_8way
-.type   __cast6_enc_blk_8way,@function;
+.align 8
+.type   __cast6_enc_blk8,@function;
 
-__cast6_enc_blk_8way:
+__cast6_enc_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
         */
 
        pushq %rbp;
        pushq %rbx;
-       pushq %rcx;
 
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
 
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       inpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
        preload_rkr(0, dummy, none);
        Q(0);
@@ -311,36 +286,25 @@ __cast6_enc_blk_8way:
        QBAR(10);
        QBAR(11);
 
-       popq %rcx;
        popq %rbx;
        popq %rbp;
 
        vmovdqa .Lbswap_mask, RKM;
-       leaq (4*4*4)(%r11), %rax;
-
-       testb %cl, %cl;
-       jnz __enc_xor8;
-
-       outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-       ret;
 
-__enc_xor8:
-       outunpack_xor_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       outunpack_xor_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
        ret;
 
-.align 16
-.global cast6_dec_blk_8way
-.type   cast6_dec_blk_8way,@function;
+.align 8
+.type   __cast6_dec_blk8,@function;
 
-cast6_dec_blk_8way:
+__cast6_dec_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
         */
 
        pushq %rbp;
@@ -350,11 +314,8 @@ cast6_dec_blk_8way:
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
 
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-       movq %rsi, %r11;
+       inpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       inpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
        preload_rkr(2, shuffle, .Lrkr_dec_Q_Q_Q_Q);
        Q(11);
@@ -376,8 +337,103 @@ cast6_dec_blk_8way:
        popq %rbp;
 
        vmovdqa .Lbswap_mask, RKM;
-       leaq (4*4*4)(%r11), %rax;
-       outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-       outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+       outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+       ret;
+
+.align 8
+.global cast6_ecb_enc_8way
+.type   cast6_ecb_enc_8way,@function;
+
+cast6_ecb_enc_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __cast6_enc_blk8;
+
+       store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global cast6_ecb_dec_8way
+.type   cast6_ecb_dec_8way,@function;
+
+cast6_ecb_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __cast6_dec_blk8;
+
+       store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global cast6_cbc_dec_8way
+.type   cast6_cbc_dec_8way,@function;
+
+cast6_cbc_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __cast6_dec_blk8;
+
+       store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       popq %r12;
+
+       ret;
+
+.align 8
+.global cast6_ctr_8way
+.type   cast6_ctr_8way,@function;
+
+cast6_ctr_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+                     RD2, RX, RKR, RKM);
+
+       call __cast6_enc_blk8;
+
+       store_ctr_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       popq %r12;
 
        ret;
index 15e5f85a50115a6eba3659011e35d5b95ff97558..92f7ca24790a60658c84ddae7a4741ec651b88b1 100644 (file)
 
 #define CAST6_PARALLEL_BLOCKS 8
 
-asmlinkage void __cast6_enc_blk_8way(struct cast6_ctx *ctx, u8 *dst,
-                                    const u8 *src, bool xor);
-asmlinkage void cast6_dec_blk_8way(struct cast6_ctx *ctx, u8 *dst,
+asmlinkage void cast6_ecb_enc_8way(struct cast6_ctx *ctx, u8 *dst,
+                                  const u8 *src);
+asmlinkage void cast6_ecb_dec_8way(struct cast6_ctx *ctx, u8 *dst,
                                   const u8 *src);
 
-static inline void cast6_enc_blk_xway(struct cast6_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       __cast6_enc_blk_8way(ctx, dst, src, false);
-}
-
-static inline void cast6_enc_blk_xway_xor(struct cast6_ctx *ctx, u8 *dst,
-                                         const u8 *src)
-{
-       __cast6_enc_blk_8way(ctx, dst, src, true);
-}
-
-static inline void cast6_dec_blk_xway(struct cast6_ctx *ctx, u8 *dst,
-                                     const u8 *src)
-{
-       cast6_dec_blk_8way(ctx, dst, src);
-}
-
-
-static void cast6_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-       u128 ivs[CAST6_PARALLEL_BLOCKS - 1];
-       unsigned int j;
-
-       for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
-               ivs[j] = src[j];
-
-       cast6_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-       for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
-               u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
-}
+asmlinkage void cast6_cbc_dec_8way(struct cast6_ctx *ctx, u8 *dst,
+                                  const u8 *src);
+asmlinkage void cast6_ctr_8way(struct cast6_ctx *ctx, u8 *dst, const u8 *src,
+                              le128 *iv);
 
-static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        __cast6_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void cast6_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                  u128 *iv)
-{
-       be128 ctrblks[CAST6_PARALLEL_BLOCKS];
-       unsigned int i;
-
-       for (i = 0; i < CAST6_PARALLEL_BLOCKS; i++) {
-               if (dst != src)
-                       dst[i] = src[i];
-
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
-       }
-
-       cast6_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
-
 static const struct common_glue_ctx cast6_enc = {
        .num_funcs = 2,
        .fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_enc_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_enc_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_encrypt) }
@@ -125,7 +80,7 @@ static const struct common_glue_ctx cast6_ctr = {
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr_xway) }
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_ctr_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr) }
@@ -138,7 +93,7 @@ static const struct common_glue_ctx cast6_dec = {
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_dec_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_dec_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_decrypt) }
@@ -151,7 +106,7 @@ static const struct common_glue_ctx cast6_dec_cbc = {
 
        .funcs = { {
                .num_blocks = CAST6_PARALLEL_BLOCKS,
-               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_decrypt_cbc_xway) }
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_cbc_dec_8way) }
        }, {
                .num_blocks = 1,
                .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__cast6_decrypt) }
@@ -215,7 +170,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
-               cast6_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+               cast6_ecb_enc_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
@@ -232,7 +187,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
-               cast6_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+               cast6_ecb_dec_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c
deleted file mode 100644 (file)
index 493f959..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal.
- * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE)
- * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at:
- * http://www.intel.com/products/processor/manuals/
- * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- * Volume 2A: Instruction Set Reference, A-M
- *
- * Copyright (C) 2008 Intel Corporation
- * Authors: Austin Zhang <austin_zhang@linux.intel.com>
- *          Kent Liu <kent.liu@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <crypto/internal/hash.h>
-
-#include <asm/cpufeature.h>
-#include <asm/cpu_device_id.h>
-
-#define CHKSUM_BLOCK_SIZE      1
-#define CHKSUM_DIGEST_SIZE     4
-
-#define SCALE_F        sizeof(unsigned long)
-
-#ifdef CONFIG_X86_64
-#define REX_PRE "0x48, "
-#else
-#define REX_PRE
-#endif
-
-static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
-{
-       while (length--) {
-               __asm__ __volatile__(
-                       ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
-                       :"=S"(crc)
-                       :"0"(crc), "c"(*data)
-               );
-               data++;
-       }
-
-       return crc;
-}
-
-static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len)
-{
-       unsigned int iquotient = len / SCALE_F;
-       unsigned int iremainder = len % SCALE_F;
-       unsigned long *ptmp = (unsigned long *)p;
-
-       while (iquotient--) {
-               __asm__ __volatile__(
-                       ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
-                       :"=S"(crc)
-                       :"0"(crc), "c"(*ptmp)
-               );
-               ptmp++;
-       }
-
-       if (iremainder)
-               crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp,
-                                iremainder);
-
-       return crc;
-}
-
-/*
- * Setting the seed allows arbitrary accumulators and flexible XOR policy
- * If your algorithm starts with ~0, then XOR with ~0 before you set
- * the seed.
- */
-static int crc32c_intel_setkey(struct crypto_shash *hash, const u8 *key,
-                       unsigned int keylen)
-{
-       u32 *mctx = crypto_shash_ctx(hash);
-
-       if (keylen != sizeof(u32)) {
-               crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
-               return -EINVAL;
-       }
-       *mctx = le32_to_cpup((__le32 *)key);
-       return 0;
-}
-
-static int crc32c_intel_init(struct shash_desc *desc)
-{
-       u32 *mctx = crypto_shash_ctx(desc->tfm);
-       u32 *crcp = shash_desc_ctx(desc);
-
-       *crcp = *mctx;
-
-       return 0;
-}
-
-static int crc32c_intel_update(struct shash_desc *desc, const u8 *data,
-                              unsigned int len)
-{
-       u32 *crcp = shash_desc_ctx(desc);
-
-       *crcp = crc32c_intel_le_hw(*crcp, data, len);
-       return 0;
-}
-
-static int __crc32c_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
-                               u8 *out)
-{
-       *(__le32 *)out = ~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
-       return 0;
-}
-
-static int crc32c_intel_finup(struct shash_desc *desc, const u8 *data,
-                             unsigned int len, u8 *out)
-{
-       return __crc32c_intel_finup(shash_desc_ctx(desc), data, len, out);
-}
-
-static int crc32c_intel_final(struct shash_desc *desc, u8 *out)
-{
-       u32 *crcp = shash_desc_ctx(desc);
-
-       *(__le32 *)out = ~cpu_to_le32p(crcp);
-       return 0;
-}
-
-static int crc32c_intel_digest(struct shash_desc *desc, const u8 *data,
-                              unsigned int len, u8 *out)
-{
-       return __crc32c_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
-                                   out);
-}
-
-static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
-{
-       u32 *key = crypto_tfm_ctx(tfm);
-
-       *key = ~0;
-
-       return 0;
-}
-
-static struct shash_alg alg = {
-       .setkey                 =       crc32c_intel_setkey,
-       .init                   =       crc32c_intel_init,
-       .update                 =       crc32c_intel_update,
-       .final                  =       crc32c_intel_final,
-       .finup                  =       crc32c_intel_finup,
-       .digest                 =       crc32c_intel_digest,
-       .descsize               =       sizeof(u32),
-       .digestsize             =       CHKSUM_DIGEST_SIZE,
-       .base                   =       {
-               .cra_name               =       "crc32c",
-               .cra_driver_name        =       "crc32c-intel",
-               .cra_priority           =       200,
-               .cra_blocksize          =       CHKSUM_BLOCK_SIZE,
-               .cra_ctxsize            =       sizeof(u32),
-               .cra_module             =       THIS_MODULE,
-               .cra_init               =       crc32c_intel_cra_init,
-       }
-};
-
-static const struct x86_cpu_id crc32c_cpu_id[] = {
-       X86_FEATURE_MATCH(X86_FEATURE_XMM4_2),
-       {}
-};
-MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id);
-
-static int __init crc32c_intel_mod_init(void)
-{
-       if (!x86_match_cpu(crc32c_cpu_id))
-               return -ENODEV;
-       return crypto_register_shash(&alg);
-}
-
-static void __exit crc32c_intel_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_init(crc32c_intel_mod_init);
-module_exit(crc32c_intel_mod_fini);
-
-MODULE_AUTHOR("Austin Zhang <austin.zhang@intel.com>, Kent Liu <kent.liu@intel.com>");
-MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware.");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("crc32c");
-MODULE_ALIAS("crc32c-intel");
diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c
new file mode 100644 (file)
index 0000000..6812ad9
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal.
+ * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE)
+ * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at:
+ * http://www.intel.com/products/processor/manuals/
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 2A: Instruction Set Reference, A-M
+ *
+ * Copyright (C) 2008 Intel Corporation
+ * Authors: Austin Zhang <austin_zhang@linux.intel.com>
+ *          Kent Liu <kent.liu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <crypto/internal/hash.h>
+
+#include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
+#include <asm/i387.h>
+#include <asm/fpu-internal.h>
+
+#define CHKSUM_BLOCK_SIZE      1
+#define CHKSUM_DIGEST_SIZE     4
+
+#define SCALE_F        sizeof(unsigned long)
+
+#ifdef CONFIG_X86_64
+#define REX_PRE "0x48, "
+#else
+#define REX_PRE
+#endif
+
+#ifdef CONFIG_X86_64
+/*
+ * use carryless multiply version of crc32c when buffer
+ * size is >= 512 (when eager fpu is enabled) or
+ * >= 1024 (when eager fpu is disabled) to account
+ * for fpu state save/restore overhead.
+ */
+#define CRC32C_PCL_BREAKEVEN_EAGERFPU  512
+#define CRC32C_PCL_BREAKEVEN_NOEAGERFPU        1024
+
+asmlinkage unsigned int crc_pcl(const u8 *buffer, int len,
+                               unsigned int crc_init);
+static int crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_EAGERFPU;
+#if defined(X86_FEATURE_EAGER_FPU)
+#define set_pcl_breakeven_point()                                      \
+do {                                                                   \
+       if (!use_eager_fpu())                                           \
+               crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU; \
+} while (0)
+#else
+#define set_pcl_breakeven_point()                                      \
+       (crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU)
+#endif
+#endif /* CONFIG_X86_64 */
+
+static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
+{
+       while (length--) {
+               __asm__ __volatile__(
+                       ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
+                       :"=S"(crc)
+                       :"0"(crc), "c"(*data)
+               );
+               data++;
+       }
+
+       return crc;
+}
+
+static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len)
+{
+       unsigned int iquotient = len / SCALE_F;
+       unsigned int iremainder = len % SCALE_F;
+       unsigned long *ptmp = (unsigned long *)p;
+
+       while (iquotient--) {
+               __asm__ __volatile__(
+                       ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
+                       :"=S"(crc)
+                       :"0"(crc), "c"(*ptmp)
+               );
+               ptmp++;
+       }
+
+       if (iremainder)
+               crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp,
+                                iremainder);
+
+       return crc;
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int crc32c_intel_setkey(struct crypto_shash *hash, const u8 *key,
+                       unsigned int keylen)
+{
+       u32 *mctx = crypto_shash_ctx(hash);
+
+       if (keylen != sizeof(u32)) {
+               crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+       *mctx = le32_to_cpup((__le32 *)key);
+       return 0;
+}
+
+static int crc32c_intel_init(struct shash_desc *desc)
+{
+       u32 *mctx = crypto_shash_ctx(desc->tfm);
+       u32 *crcp = shash_desc_ctx(desc);
+
+       *crcp = *mctx;
+
+       return 0;
+}
+
+static int crc32c_intel_update(struct shash_desc *desc, const u8 *data,
+                              unsigned int len)
+{
+       u32 *crcp = shash_desc_ctx(desc);
+
+       *crcp = crc32c_intel_le_hw(*crcp, data, len);
+       return 0;
+}
+
+static int __crc32c_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
+                               u8 *out)
+{
+       *(__le32 *)out = ~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
+       return 0;
+}
+
+static int crc32c_intel_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
+{
+       return __crc32c_intel_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_intel_final(struct shash_desc *desc, u8 *out)
+{
+       u32 *crcp = shash_desc_ctx(desc);
+
+       *(__le32 *)out = ~cpu_to_le32p(crcp);
+       return 0;
+}
+
+static int crc32c_intel_digest(struct shash_desc *desc, const u8 *data,
+                              unsigned int len, u8 *out)
+{
+       return __crc32c_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
+                                   out);
+}
+
+static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
+{
+       u32 *key = crypto_tfm_ctx(tfm);
+
+       *key = ~0;
+
+       return 0;
+}
+
+#ifdef CONFIG_X86_64
+static int crc32c_pcl_intel_update(struct shash_desc *desc, const u8 *data,
+                              unsigned int len)
+{
+       u32 *crcp = shash_desc_ctx(desc);
+
+       /*
+        * use faster PCL version if datasize is large enough to
+        * overcome kernel fpu state save/restore overhead
+        */
+       if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+               kernel_fpu_begin();
+               *crcp = crc_pcl(data, len, *crcp);
+               kernel_fpu_end();
+       } else
+               *crcp = crc32c_intel_le_hw(*crcp, data, len);
+       return 0;
+}
+
+static int __crc32c_pcl_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
+                               u8 *out)
+{
+       if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+               kernel_fpu_begin();
+               *(__le32 *)out = ~cpu_to_le32(crc_pcl(data, len, *crcp));
+               kernel_fpu_end();
+       } else
+               *(__le32 *)out =
+                       ~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
+       return 0;
+}
+
+static int crc32c_pcl_intel_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
+{
+       return __crc32c_pcl_intel_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_pcl_intel_digest(struct shash_desc *desc, const u8 *data,
+                              unsigned int len, u8 *out)
+{
+       return __crc32c_pcl_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
+                                   out);
+}
+#endif /* CONFIG_X86_64 */
+
+static struct shash_alg alg = {
+       .setkey                 =       crc32c_intel_setkey,
+       .init                   =       crc32c_intel_init,
+       .update                 =       crc32c_intel_update,
+       .final                  =       crc32c_intel_final,
+       .finup                  =       crc32c_intel_finup,
+       .digest                 =       crc32c_intel_digest,
+       .descsize               =       sizeof(u32),
+       .digestsize             =       CHKSUM_DIGEST_SIZE,
+       .base                   =       {
+               .cra_name               =       "crc32c",
+               .cra_driver_name        =       "crc32c-intel",
+               .cra_priority           =       200,
+               .cra_blocksize          =       CHKSUM_BLOCK_SIZE,
+               .cra_ctxsize            =       sizeof(u32),
+               .cra_module             =       THIS_MODULE,
+               .cra_init               =       crc32c_intel_cra_init,
+       }
+};
+
+static const struct x86_cpu_id crc32c_cpu_id[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_XMM4_2),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id);
+
+static int __init crc32c_intel_mod_init(void)
+{
+       if (!x86_match_cpu(crc32c_cpu_id))
+               return -ENODEV;
+#ifdef CONFIG_X86_64
+       if (cpu_has_pclmulqdq) {
+               alg.update = crc32c_pcl_intel_update;
+               alg.finup = crc32c_pcl_intel_finup;
+               alg.digest = crc32c_pcl_intel_digest;
+               set_pcl_breakeven_point();
+       }
+#endif
+       return crypto_register_shash(&alg);
+}
+
+static void __exit crc32c_intel_mod_fini(void)
+{
+       crypto_unregister_shash(&alg);
+}
+
+module_init(crc32c_intel_mod_init);
+module_exit(crc32c_intel_mod_fini);
+
+MODULE_AUTHOR("Austin Zhang <austin.zhang@intel.com>, Kent Liu <kent.liu@intel.com>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware.");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("crc32c");
+MODULE_ALIAS("crc32c-intel");
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
new file mode 100644 (file)
index 0000000..93c6d39
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Implement fast CRC32C with PCLMULQDQ instructions. (x86_64)
+ *
+ * The white paper on CRC32C calculations with PCLMULQDQ instruction can be
+ * downloaded from:
+ * http://download.intel.com/design/intarch/papers/323405.pdf
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors:
+ *     Wajdi Feghali <wajdi.k.feghali@intel.com>
+ *     James Guilford <james.guilford@intel.com>
+ *     David Cote <david.m.cote@intel.com>
+ *     Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
+
+.macro LABEL prefix n
+\prefix\n\():
+.endm
+
+.macro JMPTBL_ENTRY i
+.word crc_\i - crc_array
+.endm
+
+.macro JNC_LESS_THAN j
+       jnc less_than_\j
+.endm
+
+# Define threshold where buffers are considered "small" and routed to more
+# efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so
+# SMALL_SIZE can be no larger than 255.
+
+#define SMALL_SIZE 200
+
+.if (SMALL_SIZE > 255)
+.error "SMALL_ SIZE must be < 256"
+.endif
+
+# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init);
+
+.global crc_pcl
+crc_pcl:
+#define    bufp                %rdi
+#define    bufp_dw     %edi
+#define    bufp_w      %di
+#define    bufp_b      %dil
+#define    bufptmp     %rcx
+#define    block_0     %rcx
+#define    block_1     %rdx
+#define    block_2     %r11
+#define    len         %rsi
+#define    len_dw      %esi
+#define    len_w       %si
+#define    len_b       %sil
+#define    crc_init_arg %rdx
+#define    tmp         %rbx
+#define    crc_init    %r8
+#define    crc_init_dw %r8d
+#define    crc1                %r9
+#define    crc2                %r10
+
+       pushq   %rbx
+       pushq   %rdi
+       pushq   %rsi
+
+       ## Move crc_init for Linux to a different
+       mov     crc_init_arg, crc_init
+
+       ################################################################
+       ## 1) ALIGN:
+       ################################################################
+
+       mov     bufp, bufptmp           # rdi = *buf
+       neg     bufp
+       and     $7, bufp                # calculate the unalignment amount of
+                                       # the address
+       je      proc_block              # Skip if aligned
+
+       ## If len is less than 8 and we're unaligned, we need to jump
+       ## to special code to avoid reading beyond the end of the buffer
+       cmp     $8, len
+       jae     do_align
+       # less_than_8 expects length in upper 3 bits of len_dw
+       # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
+       shl     $32-3+1, len_dw
+       jmp     less_than_8_post_shl1
+
+do_align:
+       #### Calculate CRC of unaligned bytes of the buffer (if any)
+       movq    (bufptmp), tmp          # load a quadward from the buffer
+       add     bufp, bufptmp           # align buffer pointer for quadword
+                                       # processing
+       sub     bufp, len               # update buffer length
+align_loop:
+       crc32b  %bl, crc_init_dw        # compute crc32 of 1-byte
+       shr     $8, tmp                 # get next byte
+       dec     bufp
+       jne     align_loop
+
+proc_block:
+
+       ################################################################
+       ## 2) PROCESS  BLOCKS:
+       ################################################################
+
+       ## compute num of bytes to be processed
+       movq    len, tmp                # save num bytes in tmp
+
+       cmpq    $128*24, len
+       jae     full_block
+
+continue_block:
+       cmpq    $SMALL_SIZE, len
+       jb      small
+
+       ## len < 128*24
+       movq    $2731, %rax             # 2731 = ceil(2^16 / 24)
+       mul     len_dw
+       shrq    $16, %rax
+
+       ## eax contains floor(bytes / 24) = num 24-byte chunks to do
+
+       ## process rax 24-byte chunks (128 >= rax >= 0)
+
+       ## compute end address of each block
+       ## block 0 (base addr + RAX * 8)
+       ## block 1 (base addr + RAX * 16)
+       ## block 2 (base addr + RAX * 24)
+       lea     (bufptmp, %rax, 8), block_0
+       lea     (block_0, %rax, 8), block_1
+       lea     (block_1, %rax, 8), block_2
+
+       xor     crc1, crc1
+       xor     crc2, crc2
+
+       ## branch into array
+       lea     jump_table(%rip), bufp
+       movzxw  (bufp, %rax, 2), len
+       offset=crc_array-jump_table
+       lea     offset(bufp, len, 1), bufp
+       jmp     *bufp
+
+       ################################################################
+       ## 2a) PROCESS FULL BLOCKS:
+       ################################################################
+full_block:
+       movq    $128,%rax
+       lea     128*8*2(block_0), block_1
+       lea     128*8*3(block_0), block_2
+       add     $128*8*1, block_0
+
+       xor     crc1,crc1
+       xor     crc2,crc2
+
+       # Fall thruogh into top of crc array (crc_128)
+
+       ################################################################
+       ## 3) CRC Array:
+       ################################################################
+
+crc_array:
+       i=128
+.rept 128-1
+.altmacro
+LABEL crc_ %i
+.noaltmacro
+       crc32q   -i*8(block_0), crc_init
+       crc32q   -i*8(block_1), crc1
+       crc32q   -i*8(block_2), crc2
+       i=(i-1)
+.endr
+
+.altmacro
+LABEL crc_ %i
+.noaltmacro
+       crc32q   -i*8(block_0), crc_init
+       crc32q   -i*8(block_1), crc1
+# SKIP  crc32  -i*8(block_2), crc2 ; Don't do this one yet
+
+       mov     block_2, block_0
+
+       ################################################################
+       ## 4) Combine three results:
+       ################################################################
+
+       lea     (K_table-16)(%rip), bufp        # first entry is for idx 1
+       shlq    $3, %rax                        # rax *= 8
+       subq    %rax, tmp                       # tmp -= rax*8
+       shlq    $1, %rax
+       subq    %rax, tmp                       # tmp -= rax*16
+                                               # (total tmp -= rax*24)
+       addq    %rax, bufp
+
+       movdqa  (bufp), %xmm0                   # 2 consts: K1:K2
+
+       movq    crc_init, %xmm1                 # CRC for block 1
+       pclmulqdq $0x00,%xmm0,%xmm1             # Multiply by K2
+
+       movq    crc1, %xmm2                     # CRC for block 2
+       pclmulqdq $0x10, %xmm0, %xmm2           # Multiply by K1
+
+       pxor    %xmm2,%xmm1
+       movq    %xmm1, %rax
+       xor     -i*8(block_2), %rax
+       mov     crc2, crc_init
+       crc32   %rax, crc_init
+
+################################################################
+## 5) Check for end:
+################################################################
+
+LABEL crc_ 0
+       mov     tmp, len
+       cmp     $128*24, tmp
+       jae     full_block
+       cmp     $24, tmp
+       jae     continue_block
+
+less_than_24:
+       shl     $32-4, len_dw                   # less_than_16 expects length
+                                               # in upper 4 bits of len_dw
+       jnc     less_than_16
+       crc32q  (bufptmp), crc_init
+       crc32q  8(bufptmp), crc_init
+       jz      do_return
+       add     $16, bufptmp
+       # len is less than 8 if we got here
+       # less_than_8 expects length in upper 3 bits of len_dw
+       # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
+       shl     $2, len_dw
+       jmp     less_than_8_post_shl1
+
+       #######################################################################
+       ## 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full)
+       #######################################################################
+small:
+       shl $32-8, len_dw               # Prepare len_dw for less_than_256
+       j=256
+.rept 5                                        # j = {256, 128, 64, 32, 16}
+.altmacro
+LABEL less_than_ %j                    # less_than_j: Length should be in
+                                       # upper lg(j) bits of len_dw
+       j=(j/2)
+       shl     $1, len_dw              # Get next MSB
+       JNC_LESS_THAN %j
+.noaltmacro
+       i=0
+.rept (j/8)
+       crc32q  i(bufptmp), crc_init    # Compute crc32 of 8-byte data
+       i=i+8
+.endr
+       jz      do_return               # Return if remaining length is zero
+       add     $j, bufptmp             # Advance buf
+.endr
+
+less_than_8:                           # Length should be stored in
+                                       # upper 3 bits of len_dw
+       shl     $1, len_dw
+less_than_8_post_shl1:
+       jnc     less_than_4
+       crc32l  (bufptmp), crc_init_dw  # CRC of 4 bytes
+       jz      do_return               # return if remaining data is zero
+       add     $4, bufptmp
+less_than_4:                           # Length should be stored in
+                                       # upper 2 bits of len_dw
+       shl     $1, len_dw
+       jnc     less_than_2
+       crc32w  (bufptmp), crc_init_dw  # CRC of 2 bytes
+       jz      do_return               # return if remaining data is zero
+       add     $2, bufptmp
+less_than_2:                           # Length should be stored in the MSB
+                                       # of len_dw
+       shl     $1, len_dw
+       jnc     less_than_1
+       crc32b  (bufptmp), crc_init_dw  # CRC of 1 byte
+less_than_1:                           # Length should be zero
+do_return:
+       movq    crc_init, %rax
+       popq    %rsi
+       popq    %rdi
+       popq    %rbx
+        ret
+
+        ################################################################
+        ## jump table        Table is 129 entries x 2 bytes each
+        ################################################################
+.align 4
+jump_table:
+       i=0
+.rept 129
+.altmacro
+JMPTBL_ENTRY %i
+.noaltmacro
+       i=i+1
+.endr
+       ################################################################
+       ## PCLMULQDQ tables
+       ## Table is 128 entries x 2 quad words each
+       ################################################################
+.data
+.align 64
+K_table:
+        .quad 0x14cd00bd6,0x105ec76f0
+        .quad 0x0ba4fc28e,0x14cd00bd6
+        .quad 0x1d82c63da,0x0f20c0dfe
+        .quad 0x09e4addf8,0x0ba4fc28e
+        .quad 0x039d3b296,0x1384aa63a
+        .quad 0x102f9b8a2,0x1d82c63da
+        .quad 0x14237f5e6,0x01c291d04
+        .quad 0x00d3b6092,0x09e4addf8
+        .quad 0x0c96cfdc0,0x0740eef02
+        .quad 0x18266e456,0x039d3b296
+        .quad 0x0daece73e,0x0083a6eec
+        .quad 0x0ab7aff2a,0x102f9b8a2
+        .quad 0x1248ea574,0x1c1733996
+        .quad 0x083348832,0x14237f5e6
+        .quad 0x12c743124,0x02ad91c30
+        .quad 0x0b9e02b86,0x00d3b6092
+        .quad 0x018b33a4e,0x06992cea2
+        .quad 0x1b331e26a,0x0c96cfdc0
+        .quad 0x17d35ba46,0x07e908048
+        .quad 0x1bf2e8b8a,0x18266e456
+        .quad 0x1a3e0968a,0x11ed1f9d8
+        .quad 0x0ce7f39f4,0x0daece73e
+        .quad 0x061d82e56,0x0f1d0f55e
+        .quad 0x0d270f1a2,0x0ab7aff2a
+        .quad 0x1c3f5f66c,0x0a87ab8a8
+        .quad 0x12ed0daac,0x1248ea574
+        .quad 0x065863b64,0x08462d800
+        .quad 0x11eef4f8e,0x083348832
+        .quad 0x1ee54f54c,0x071d111a8
+        .quad 0x0b3e32c28,0x12c743124
+        .quad 0x0064f7f26,0x0ffd852c6
+        .quad 0x0dd7e3b0c,0x0b9e02b86
+        .quad 0x0f285651c,0x0dcb17aa4
+        .quad 0x010746f3c,0x018b33a4e
+        .quad 0x1c24afea4,0x0f37c5aee
+        .quad 0x0271d9844,0x1b331e26a
+        .quad 0x08e766a0c,0x06051d5a2
+        .quad 0x093a5f730,0x17d35ba46
+        .quad 0x06cb08e5c,0x11d5ca20e
+        .quad 0x06b749fb2,0x1bf2e8b8a
+        .quad 0x1167f94f2,0x021f3d99c
+        .quad 0x0cec3662e,0x1a3e0968a
+        .quad 0x19329634a,0x08f158014
+        .quad 0x0e6fc4e6a,0x0ce7f39f4
+        .quad 0x08227bb8a,0x1a5e82106
+        .quad 0x0b0cd4768,0x061d82e56
+        .quad 0x13c2b89c4,0x188815ab2
+        .quad 0x0d7a4825c,0x0d270f1a2
+        .quad 0x10f5ff2ba,0x105405f3e
+        .quad 0x00167d312,0x1c3f5f66c
+        .quad 0x0f6076544,0x0e9adf796
+        .quad 0x026f6a60a,0x12ed0daac
+        .quad 0x1a2adb74e,0x096638b34
+        .quad 0x19d34af3a,0x065863b64
+        .quad 0x049c3cc9c,0x1e50585a0
+        .quad 0x068bce87a,0x11eef4f8e
+        .quad 0x1524fa6c6,0x19f1c69dc
+        .quad 0x16cba8aca,0x1ee54f54c
+        .quad 0x042d98888,0x12913343e
+        .quad 0x1329d9f7e,0x0b3e32c28
+        .quad 0x1b1c69528,0x088f25a3a
+        .quad 0x02178513a,0x0064f7f26
+        .quad 0x0e0ac139e,0x04e36f0b0
+        .quad 0x0170076fa,0x0dd7e3b0c
+        .quad 0x141a1a2e2,0x0bd6f81f8
+        .quad 0x16ad828b4,0x0f285651c
+        .quad 0x041d17b64,0x19425cbba
+        .quad 0x1fae1cc66,0x010746f3c
+        .quad 0x1a75b4b00,0x18db37e8a
+        .quad 0x0f872e54c,0x1c24afea4
+        .quad 0x01e41e9fc,0x04c144932
+        .quad 0x086d8e4d2,0x0271d9844
+        .quad 0x160f7af7a,0x052148f02
+        .quad 0x05bb8f1bc,0x08e766a0c
+        .quad 0x0a90fd27a,0x0a3c6f37a
+        .quad 0x0b3af077a,0x093a5f730
+        .quad 0x04984d782,0x1d22c238e
+        .quad 0x0ca6ef3ac,0x06cb08e5c
+        .quad 0x0234e0b26,0x063ded06a
+        .quad 0x1d88abd4a,0x06b749fb2
+        .quad 0x04597456a,0x04d56973c
+        .quad 0x0e9e28eb4,0x1167f94f2
+        .quad 0x07b3ff57a,0x19385bf2e
+        .quad 0x0c9c8b782,0x0cec3662e
+        .quad 0x13a9cba9e,0x0e417f38a
+        .quad 0x093e106a4,0x19329634a
+        .quad 0x167001a9c,0x14e727980
+        .quad 0x1ddffc5d4,0x0e6fc4e6a
+        .quad 0x00df04680,0x0d104b8fc
+        .quad 0x02342001e,0x08227bb8a
+        .quad 0x00a2a8d7e,0x05b397730
+        .quad 0x168763fa6,0x0b0cd4768
+        .quad 0x1ed5a407a,0x0e78eb416
+        .quad 0x0d2c3ed1a,0x13c2b89c4
+        .quad 0x0995a5724,0x1641378f0
+        .quad 0x19b1afbc4,0x0d7a4825c
+        .quad 0x109ffedc0,0x08d96551c
+        .quad 0x0f2271e60,0x10f5ff2ba
+        .quad 0x00b0bf8ca,0x00bf80dd2
+        .quad 0x123888b7a,0x00167d312
+        .quad 0x1e888f7dc,0x18dcddd1c
+        .quad 0x002ee03b2,0x0f6076544
+        .quad 0x183e8d8fe,0x06a45d2b2
+        .quad 0x133d7a042,0x026f6a60a
+        .quad 0x116b0f50c,0x1dd3e10e8
+        .quad 0x05fabe670,0x1a2adb74e
+        .quad 0x130004488,0x0de87806c
+        .quad 0x000bcf5f6,0x19d34af3a
+        .quad 0x18f0c7078,0x014338754
+        .quad 0x017f27698,0x049c3cc9c
+        .quad 0x058ca5f00,0x15e3e77ee
+        .quad 0x1af900c24,0x068bce87a
+        .quad 0x0b5cfca28,0x0dd07448e
+        .quad 0x0ded288f8,0x1524fa6c6
+        .quad 0x059f229bc,0x1d8048348
+        .quad 0x06d390dec,0x16cba8aca
+        .quad 0x037170390,0x0a3e3e02c
+        .quad 0x06353c1cc,0x042d98888
+        .quad 0x0c4584f5c,0x0d73c7bea
+        .quad 0x1f16a3418,0x1329d9f7e
+        .quad 0x0531377e2,0x185137662
+        .quad 0x1d8d9ca7c,0x1b1c69528
+        .quad 0x0b25b29f2,0x18a08b5bc
+        .quad 0x19fb2a8b0,0x02178513a
+        .quad 0x1a08fe6ac,0x1da758ae0
+        .quad 0x045cddf4e,0x0e0ac139e
+        .quad 0x1a91647f2,0x169cf9eb0
+        .quad 0x1a0f717c4,0x0170076fa
diff --git a/arch/x86/crypto/glue_helper-asm-avx.S b/arch/x86/crypto/glue_helper-asm-avx.S
new file mode 100644 (file)
index 0000000..f7b6ea2
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Shared glue code for 128bit block ciphers, AVX assembler macros
+ *
+ * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * 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.
+ *
+ */
+
+#define load_8way(src, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vmovdqu (0*16)(src), x0; \
+       vmovdqu (1*16)(src), x1; \
+       vmovdqu (2*16)(src), x2; \
+       vmovdqu (3*16)(src), x3; \
+       vmovdqu (4*16)(src), x4; \
+       vmovdqu (5*16)(src), x5; \
+       vmovdqu (6*16)(src), x6; \
+       vmovdqu (7*16)(src), x7;
+
+#define store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vmovdqu x0, (0*16)(dst); \
+       vmovdqu x1, (1*16)(dst); \
+       vmovdqu x2, (2*16)(dst); \
+       vmovdqu x3, (3*16)(dst); \
+       vmovdqu x4, (4*16)(dst); \
+       vmovdqu x5, (5*16)(dst); \
+       vmovdqu x6, (6*16)(dst); \
+       vmovdqu x7, (7*16)(dst);
+
+#define store_cbc_8way(src, dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vpxor (0*16)(src), x1, x1; \
+       vpxor (1*16)(src), x2, x2; \
+       vpxor (2*16)(src), x3, x3; \
+       vpxor (3*16)(src), x4, x4; \
+       vpxor (4*16)(src), x5, x5; \
+       vpxor (5*16)(src), x6, x6; \
+       vpxor (6*16)(src), x7, x7; \
+       store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7);
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+#define load_ctr_8way(iv, bswap, x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2) \
+       vpcmpeqd t0, t0, t0; \
+       vpsrldq $8, t0, t0; /* low: -1, high: 0 */ \
+       vmovdqa bswap, t1; \
+       \
+       /* load IV and byteswap */ \
+       vmovdqu (iv), x7; \
+       vpshufb t1, x7, x0; \
+       \
+       /* construct IVs */ \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x1; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x2; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x3; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x4; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x5; \
+       inc_le128(x7, t0, t2); \
+       vpshufb t1, x7, x6; \
+       inc_le128(x7, t0, t2); \
+       vmovdqa x7, t2; \
+       vpshufb t1, x7, x7; \
+       inc_le128(t2, t0, t1); \
+       vmovdqu t2, (iv);
+
+#define store_ctr_8way(src, dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+       vpxor (0*16)(src), x0, x0; \
+       vpxor (1*16)(src), x1, x1; \
+       vpxor (2*16)(src), x2, x2; \
+       vpxor (3*16)(src), x3, x3; \
+       vpxor (4*16)(src), x4, x4; \
+       vpxor (5*16)(src), x5, x5; \
+       vpxor (6*16)(src), x6, x6; \
+       vpxor (7*16)(src), x7, x7; \
+       store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7);
index 30b3927bd733b6f0c17c0d492621ee1666de2b5a..22ce4f683e550da4b464c99d8fedfce6414ea885 100644 (file)
@@ -221,16 +221,16 @@ static void glue_ctr_crypt_final_128bit(const common_glue_ctr_func_t fn_ctr,
        u8 *src = (u8 *)walk->src.virt.addr;
        u8 *dst = (u8 *)walk->dst.virt.addr;
        unsigned int nbytes = walk->nbytes;
-       u128 ctrblk;
+       le128 ctrblk;
        u128 tmp;
 
-       be128_to_u128(&ctrblk, (be128 *)walk->iv);
+       be128_to_le128(&ctrblk, (be128 *)walk->iv);
 
        memcpy(&tmp, src, nbytes);
        fn_ctr(ctx, &tmp, &tmp, &ctrblk);
        memcpy(dst, &tmp, nbytes);
 
-       u128_to_be128((be128 *)walk->iv, &ctrblk);
+       le128_to_be128((be128 *)walk->iv, &ctrblk);
 }
 EXPORT_SYMBOL_GPL(glue_ctr_crypt_final_128bit);
 
@@ -243,11 +243,11 @@ static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx,
        unsigned int nbytes = walk->nbytes;
        u128 *src = (u128 *)walk->src.virt.addr;
        u128 *dst = (u128 *)walk->dst.virt.addr;
-       u128 ctrblk;
+       le128 ctrblk;
        unsigned int num_blocks, func_bytes;
        unsigned int i;
 
-       be128_to_u128(&ctrblk, (be128 *)walk->iv);
+       be128_to_le128(&ctrblk, (be128 *)walk->iv);
 
        /* Process multi-block batch */
        for (i = 0; i < gctx->num_funcs; i++) {
@@ -269,7 +269,7 @@ static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx,
        }
 
 done:
-       u128_to_be128((be128 *)walk->iv, &ctrblk);
+       le128_to_be128((be128 *)walk->iv, &ctrblk);
        return nbytes;
 }
 
index 504106bf04a289c2e1d2d1c7de6bf970062e1279..02b0e9fe997c9208e09da9e31bb798302f3be0f5 100644 (file)
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "serpent-avx-x86_64-asm_64.S"
+
+.data
+.align 16
+
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 .text
 
 #define CTX %rdi
        vpunpcklqdq             x3, t2, x2; \
        vpunpckhqdq             x3, t2, x3;
 
-#define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \
-       vmovdqu (0*4*4)(in),    x0; \
-       vmovdqu (1*4*4)(in),    x1; \
-       vmovdqu (2*4*4)(in),    x2; \
-       vmovdqu (3*4*4)(in),    x3; \
-       \
+#define read_blocks(x0, x1, x2, x3, t0, t1, t2) \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define write_blocks(out, x0, x1, x2, x3, t0, t1, t2) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vmovdqu x1,             (1*4*4)(out); \
-       vmovdqu x2,             (2*4*4)(out); \
-       vmovdqu x3,             (3*4*4)(out);
-
-#define xor_blocks(out, x0, x1, x2, x3, t0, t1, t2) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vpxor (0*4*4)(out),     x0, x0;       \
-       vmovdqu x0,             (0*4*4)(out); \
-       vpxor (1*4*4)(out),     x1, x1;       \
-       vmovdqu x1,             (1*4*4)(out); \
-       vpxor (2*4*4)(out),     x2, x2;       \
-       vmovdqu x2,             (2*4*4)(out); \
-       vpxor (3*4*4)(out),     x3, x3;       \
-       vmovdqu x3,             (3*4*4)(out);
+#define write_blocks(x0, x1, x2, x3, t0, t1, t2) \
+       transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
 .align 8
-.global __serpent_enc_blk_8way_avx
-.type   __serpent_enc_blk_8way_avx,@function;
+.type   __serpent_enc_blk8_avx,@function;
 
-__serpent_enc_blk_8way_avx:
+__serpent_enc_blk8_avx:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
         */
 
        vpcmpeqd RNOT, RNOT, RNOT;
 
-       leaq (4*4*4)(%rdx), %rax;
-       read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+       read_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+       read_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
                                                 K2(RA, RB, RC, RD, RE, 0);
        S(S0, RA, RB, RC, RD, RE);              LK2(RC, RB, RD, RA, RE, 1);
@@ -630,38 +615,26 @@ __serpent_enc_blk_8way_avx:
        S(S6, RA, RB, RD, RC, RE);              LK2(RD, RE, RB, RC, RA, 31);
        S(S7, RD, RE, RB, RC, RA);               K2(RA, RB, RC, RD, RE, 32);
 
-       leaq (4*4*4)(%rsi), %rax;
-
-       testb %cl, %cl;
-       jnz __enc_xor8;
-
-       write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
-
-       ret;
-
-__enc_xor8:
-       xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+       write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+       write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
        ret;
 
 .align 8
-.global serpent_dec_blk_8way_avx
-.type   serpent_dec_blk_8way_avx,@function;
+.type   __serpent_dec_blk8_avx,@function;
 
-serpent_dec_blk_8way_avx:
+__serpent_dec_blk8_avx:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
+        * output:
+        *      RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2: decrypted blocks
         */
 
        vpcmpeqd RNOT, RNOT, RNOT;
 
-       leaq (4*4*4)(%rdx), %rax;
-       read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-       read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+       read_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+       read_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
                                                 K2(RA, RB, RC, RD, RE, 32);
        SP(SI7, RA, RB, RC, RD, RE, 31);        KL2(RB, RD, RA, RE, RC, 31);
@@ -697,8 +670,85 @@ serpent_dec_blk_8way_avx:
        SP(SI1, RD, RB, RC, RA, RE, 1);         KL2(RE, RB, RC, RA, RD, 1);
        S(SI0, RE, RB, RC, RA, RD);              K2(RC, RD, RB, RE, RA, 0);
 
-       leaq (4*4*4)(%rsi), %rax;
-       write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2);
-       write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+       write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2);
+       write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+
+       ret;
+
+.align 8
+.global serpent_ecb_enc_8way_avx
+.type   serpent_ecb_enc_8way_avx,@function;
+
+serpent_ecb_enc_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __serpent_enc_blk8_avx;
+
+       store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global serpent_ecb_dec_8way_avx
+.type   serpent_ecb_dec_8way_avx,@function;
+
+serpent_ecb_dec_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __serpent_dec_blk8_avx;
+
+       store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+       ret;
+
+.align 8
+.global serpent_cbc_dec_8way_avx
+.type   serpent_cbc_dec_8way_avx,@function;
+
+serpent_cbc_dec_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __serpent_dec_blk8_avx;
+
+       store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+       ret;
+
+.align 8
+.global serpent_ctr_8way_avx
+.type   serpent_ctr_8way_avx,@function;
+
+serpent_ctr_8way_avx:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+                     RD2, RK0, RK1, RK2);
+
+       call __serpent_enc_blk8_avx;
+
+       store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
        ret;
index 3f543a04cf1ee2c697e2b2ea1b427ea7f8631386..52abaaf28e7fe798807950a38bfeb0ec6c7361ba 100644 (file)
 #include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
-static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-       u128 ivs[SERPENT_PARALLEL_BLOCKS - 1];
-       unsigned int j;
-
-       for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
-               ivs[j] = src[j];
-
-       serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-       for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
-               u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
-}
-
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        __serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                  u128 *iv)
-{
-       be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
-       unsigned int i;
-
-       for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) {
-               if (dst != src)
-                       dst[i] = src[i];
-
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
-       }
-
-       serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
-
 static const struct common_glue_ctx serpent_enc = {
        .num_funcs = 2,
        .fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS,
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_enc_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
@@ -103,7 +72,7 @@ static const struct common_glue_ctx serpent_ctr = {
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway) }
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr) }
@@ -116,7 +85,7 @@ static const struct common_glue_ctx serpent_dec = {
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_dec_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
@@ -129,7 +98,7 @@ static const struct common_glue_ctx serpent_dec_cbc = {
 
        .funcs = { {
                .num_blocks = SERPENT_PARALLEL_BLOCKS,
-               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway) }
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx) }
        }, {
                .num_blocks = 1,
                .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
@@ -193,7 +162,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
-               serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+               serpent_ecb_enc_8way_avx(ctx->ctx, srcdst, srcdst);
                return;
        }
 
@@ -210,7 +179,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
-               serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+               serpent_ecb_dec_8way_avx(ctx->ctx, srcdst, srcdst);
                return;
        }
 
index 9107a9908c41ecb4a3e591f0c10380487d5c5b47..97a356ece24d2b74d18090760e988c45d2bc914a 100644 (file)
@@ -59,19 +59,19 @@ static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
                u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
 }
 
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        __serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
 static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                  u128 *iv)
+                                  le128 *iv)
 {
        be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
        unsigned int i;
@@ -80,8 +80,8 @@ static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
                if (dst != src)
                        dst[i] = src[i];
 
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
+               le128_to_be128(&ctrblks[i], iv);
+               le128_inc(iv);
        }
 
        serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
index 1585abb13ddec3482c07bcd8fa09d470513814a7..ebac16bfa8302331d50bca8dc760965845a4428f 100644 (file)
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "twofish-avx-x86_64-asm_64.S"
+
+.data
+.align 16
+
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 .text
 
 /* structure of crypto context */
        vpunpcklqdq             x3, t2, x2; \
        vpunpckhqdq             x3, t2, x3;
 
-#define inpack_blocks(in, x0, x1, x2, x3, wkey, t0, t1, t2) \
-       vpxor (0*4*4)(in),      wkey, x0; \
-       vpxor (1*4*4)(in),      wkey, x1; \
-       vpxor (2*4*4)(in),      wkey, x2; \
-       vpxor (3*4*4)(in),      wkey, x3; \
+#define inpack_blocks(x0, x1, x2, x3, wkey, t0, t1, t2) \
+       vpxor           x0, wkey, x0; \
+       vpxor           x1, wkey, x1; \
+       vpxor           x2, wkey, x2; \
+       vpxor           x3, wkey, x3; \
        \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define outunpack_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \
-       transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-       \
-       vpxor           x0, wkey, x0;     \
-       vmovdqu         x0, (0*4*4)(out); \
-       vpxor           x1, wkey, x1;     \
-       vmovdqu         x1, (1*4*4)(out); \
-       vpxor           x2, wkey, x2;     \
-       vmovdqu         x2, (2*4*4)(out); \
-       vpxor           x3, wkey, x3;     \
-       vmovdqu         x3, (3*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \
+#define outunpack_blocks(x0, x1, x2, x3, wkey, t0, t1, t2) \
        transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
        \
-       vpxor           x0, wkey, x0;         \
-       vpxor           (0*4*4)(out), x0, x0; \
-       vmovdqu         x0, (0*4*4)(out);     \
-       vpxor           x1, wkey, x1;         \
-       vpxor           (1*4*4)(out), x1, x1; \
-       vmovdqu         x1, (1*4*4)(out);     \
-       vpxor           x2, wkey, x2;         \
-       vpxor           (2*4*4)(out), x2, x2; \
-       vmovdqu         x2, (2*4*4)(out);     \
-       vpxor           x3, wkey, x3;         \
-       vpxor           (3*4*4)(out), x3, x3; \
-       vmovdqu         x3, (3*4*4)(out);
+       vpxor           x0, wkey, x0; \
+       vpxor           x1, wkey, x1; \
+       vpxor           x2, wkey, x2; \
+       vpxor           x3, wkey, x3;
 
 .align 8
-.global __twofish_enc_blk_8way
-.type   __twofish_enc_blk_8way,@function;
+.type  __twofish_enc_blk8,@function;
 
-__twofish_enc_blk_8way:
+__twofish_enc_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
-        *      %rcx: bool, if true: xor output
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+        * output:
+        *      RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2: encrypted blocks
         */
 
+       vmovdqu w(CTX), RK1;
+
        pushq %rbp;
        pushq %rbx;
        pushq %rcx;
 
-       vmovdqu w(CTX), RK1;
-
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+       inpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
        preload_rgi(RA1);
        rotate_1l(RD1);
-       inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+       inpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
        rotate_1l(RD2);
 
-       movq %rsi, %r11;
-
        encrypt_cycle(0);
        encrypt_cycle(1);
        encrypt_cycle(2);
@@ -295,47 +280,33 @@ __twofish_enc_blk_8way:
        popq %rbx;
        popq %rbp;
 
-       leaq (4*4*4)(%r11), %rax;
-
-       testb %cl, %cl;
-       jnz __enc_xor8;
-
-       outunpack_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
-       outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
-
-       ret;
-
-__enc_xor8:
-       outunpack_xor_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
-       outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
 
        ret;
 
 .align 8
-.global twofish_dec_blk_8way
-.type   twofish_dec_blk_8way,@function;
+.type  __twofish_dec_blk8,@function;
 
-twofish_dec_blk_8way:
+__twofish_dec_blk8:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst
-        *      %rdx: src
+        *      RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2: encrypted blocks
+        * output:
+        *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
         */
 
+       vmovdqu (w+4*4)(CTX), RK1;
+
        pushq %rbp;
        pushq %rbx;
 
-       vmovdqu (w+4*4)(CTX), RK1;
-
-       leaq (4*4*4)(%rdx), %rax;
-       inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+       inpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
        preload_rgi(RC1);
        rotate_1l(RA1);
-       inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+       inpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
        rotate_1l(RA2);
 
-       movq %rsi, %r11;
-
        decrypt_cycle(7);
        decrypt_cycle(6);
        decrypt_cycle(5);
@@ -350,8 +321,103 @@ twofish_dec_blk_8way:
        popq %rbx;
        popq %rbp;
 
-       leaq (4*4*4)(%r11), %rax;
-       outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
-       outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+       outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+
+       ret;
+
+.align 8
+.global twofish_ecb_enc_8way
+.type   twofish_ecb_enc_8way,@function;
+
+twofish_ecb_enc_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       call __twofish_enc_blk8;
+
+       store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       ret;
+
+.align 8
+.global twofish_ecb_dec_8way
+.type   twofish_ecb_dec_8way,@function;
+
+twofish_ecb_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       movq %rsi, %r11;
+
+       load_8way(%rdx, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       call __twofish_dec_blk8;
+
+       store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       ret;
+
+.align 8
+.global twofish_cbc_dec_8way
+.type   twofish_cbc_dec_8way,@function;
+
+twofish_cbc_dec_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_8way(%rdx, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       call __twofish_dec_blk8;
+
+       store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+       popq %r12;
+
+       ret;
+
+.align 8
+.global twofish_ctr_8way
+.type   twofish_ctr_8way,@function;
+
+twofish_ctr_8way:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: iv (little endian, 128bit)
+        */
+
+       pushq %r12;
+
+       movq %rsi, %r11;
+       movq %rdx, %r12;
+
+       load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+                     RD2, RX0, RX1, RY0);
+
+       call __twofish_enc_blk8;
+
+       store_ctr_8way(%r12, %r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+       popq %r12;
 
        ret;
index e7708b5442e0b59ab7478306124c8c84493a551c..94ac91d26e47e3b4ef415df06115d1c490b9f6a9 100644 (file)
 
 #define TWOFISH_PARALLEL_BLOCKS 8
 
-static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-                                       const u8 *src)
-{
-       __twofish_enc_blk_3way(ctx, dst, src, false);
-}
-
 /* 8-way parallel cipher functions */
-asmlinkage void __twofish_enc_blk_8way(struct twofish_ctx *ctx, u8 *dst,
-                                      const u8 *src, bool xor);
-asmlinkage void twofish_dec_blk_8way(struct twofish_ctx *ctx, u8 *dst,
+asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst,
+                                    const u8 *src);
+asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst,
                                     const u8 *src);
 
-static inline void twofish_enc_blk_xway(struct twofish_ctx *ctx, u8 *dst,
-                                       const u8 *src)
-{
-       __twofish_enc_blk_8way(ctx, dst, src, false);
-}
-
-static inline void twofish_enc_blk_xway_xor(struct twofish_ctx *ctx, u8 *dst,
-                                           const u8 *src)
-{
-       __twofish_enc_blk_8way(ctx, dst, src, true);
-}
+asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst,
+                                    const u8 *src);
+asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst,
+                                const u8 *src, le128 *iv);
 
-static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst,
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
                                        const u8 *src)
 {
-       twofish_dec_blk_8way(ctx, dst, src);
-}
-
-static void twofish_dec_blk_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-       u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1];
-       unsigned int j;
-
-       for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++)
-               ivs[j] = src[j];
-
-       twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-       for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++)
-               u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
+       __twofish_enc_blk_3way(ctx, dst, src, false);
 }
 
-static void twofish_enc_blk_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-                                    u128 *iv)
-{
-       be128 ctrblks[TWOFISH_PARALLEL_BLOCKS];
-       unsigned int i;
-
-       for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) {
-               if (dst != src)
-                       dst[i] = src[i];
-
-               u128_to_be128(&ctrblks[i], iv);
-               u128_inc(iv);
-       }
-
-       twofish_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
 
 static const struct common_glue_ctx twofish_enc = {
        .num_funcs = 3,
@@ -112,7 +69,7 @@ static const struct common_glue_ctx twofish_enc = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
@@ -128,7 +85,7 @@ static const struct common_glue_ctx twofish_ctr = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_xway) }
+               .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) }
@@ -144,7 +101,7 @@ static const struct common_glue_ctx twofish_dec = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_xway) }
+               .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
@@ -160,7 +117,7 @@ static const struct common_glue_ctx twofish_dec_cbc = {
 
        .funcs = { {
                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
-               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_xway) }
+               .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_8way) }
        }, {
                .num_blocks = 3,
                .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
@@ -227,7 +184,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) {
-               twofish_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+               twofish_ecb_enc_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
@@ -249,7 +206,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
        ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes);
 
        if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) {
-               twofish_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+               twofish_ecb_dec_8way(ctx->ctx, srcdst, srcdst);
                return;
        }
 
index aa3eb358b7e81b82d1816cbafbc58a04349d3428..13e63b3e1dfb44593ea2274a63adebfbdce7e6ce 100644 (file)
@@ -62,15 +62,15 @@ void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src)
 }
 EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
 
-void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
        be128 ctrblk;
 
        if (dst != src)
                *dst = *src;
 
-       u128_to_be128(&ctrblk, iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblk, iv);
+       le128_inc(iv);
 
        twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
        u128_xor(dst, dst, (u128 *)&ctrblk);
@@ -78,7 +78,7 @@ void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
 EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr);
 
 void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-                                    u128 *iv)
+                             le128 *iv)
 {
        be128 ctrblks[3];
 
@@ -88,12 +88,12 @@ void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
                dst[2] = src[2];
        }
 
-       u128_to_be128(&ctrblks[0], iv);
-       u128_inc(iv);
-       u128_to_be128(&ctrblks[1], iv);
-       u128_inc(iv);
-       u128_to_be128(&ctrblks[2], iv);
-       u128_inc(iv);
+       le128_to_be128(&ctrblks[0], iv);
+       le128_inc(iv);
+       le128_to_be128(&ctrblks[1], iv);
+       le128_inc(iv);
+       le128_to_be128(&ctrblks[2], iv);
+       le128_inc(iv);
 
        twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblks);
 }
index 79fd8a3418f9d5cca461bef7fa0fb874c0d69aee..7f669853317a3e940647319c21705ca951fb18ac 100644 (file)
@@ -1,30 +1,4 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += boot.h
-header-y += bootparam.h
-header-y += debugreg.h
-header-y += e820.h
-header-y += hw_breakpoint.h
-header-y += hyperv.h
-header-y += ist.h
-header-y += ldt.h
-header-y += mce.h
-header-y += msr-index.h
-header-y += msr.h
-header-y += mtrr.h
-header-y += perf_regs.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += posix_types_x32.h
-header-y += prctl.h
-header-y += processor-flags.h
-header-y += ptrace-abi.h
-header-y += sigcontext32.h
-header-y += svm.h
-header-y += ucontext.h
-header-y += vm86.h
-header-y += vmx.h
-header-y += vsyscall.h
 
 genhdr-y += unistd_32.h
 genhdr-y += unistd_64.h
diff --git a/arch/x86/include/asm/a.out.h b/arch/x86/include/asm/a.out.h
deleted file mode 100644 (file)
index 4684f97..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_X86_A_OUT_H
-#define _ASM_X86_A_OUT_H
-
-struct exec
-{
-       unsigned int a_info;    /* Use macros N_MAGIC, etc for access */
-       unsigned a_text;        /* length of text, in bytes */
-       unsigned a_data;        /* length of data, in bytes */
-       unsigned a_bss;         /* length of uninitialized data area for file, in bytes */
-       unsigned a_syms;        /* length of symbol table data in file, in bytes */
-       unsigned a_entry;       /* start address */
-       unsigned a_trsize;      /* length of relocation info for text, in bytes */
-       unsigned a_drsize;      /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* _ASM_X86_A_OUT_H */
diff --git a/arch/x86/include/asm/auxvec.h b/arch/x86/include/asm/auxvec.h
deleted file mode 100644 (file)
index 77203ac..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_X86_AUXVEC_H
-#define _ASM_X86_AUXVEC_H
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#ifdef __i386__
-#define AT_SYSINFO             32
-#endif
-#define AT_SYSINFO_EHDR                33
-
-/* entries in ARCH_DLINFO: */
-#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64)
-# define AT_VECTOR_SIZE_ARCH 2
-#else /* else it's non-compat x86-64 */
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-#endif /* _ASM_X86_AUXVEC_H */
diff --git a/arch/x86/include/asm/bitsperlong.h b/arch/x86/include/asm/bitsperlong.h
deleted file mode 100644 (file)
index b0ae1c4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ASM_X86_BITSPERLONG_H
-#define __ASM_X86_BITSPERLONG_H
-
-#ifdef __x86_64__
-# define __BITS_PER_LONG 64
-#else
-# define __BITS_PER_LONG 32
-#endif
-
-#include <asm-generic/bitsperlong.h>
-
-#endif /* __ASM_X86_BITSPERLONG_H */
-
index b13fe63bdc59c20b9548acd66cbef81b39579320..4fa687a47a62d85d4fd84062c2a5fc7c622c1cc7 100644 (file)
@@ -1,14 +1,9 @@
 #ifndef _ASM_X86_BOOT_H
 #define _ASM_X86_BOOT_H
 
-/* Internal svga startup constants */
-#define NORMAL_VGA     0xffff          /* 80x25 mode */
-#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
-#define ASK_VGA                0xfffd          /* ask for it at bootup */
-
-#ifdef __KERNEL__
 
 #include <asm/pgtable_types.h>
+#include <uapi/asm/boot.h>
 
 /* Physical address where kernel should be loaded. */
 #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
@@ -42,6 +37,4 @@
 #define BOOT_STACK_SIZE        0x1000
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_BOOT_H */
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
deleted file mode 100644 (file)
index 2ad874c..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-#ifndef _ASM_X86_BOOTPARAM_H
-#define _ASM_X86_BOOTPARAM_H
-
-#include <linux/types.h>
-#include <linux/screen_info.h>
-#include <linux/apm_bios.h>
-#include <linux/edd.h>
-#include <asm/e820.h>
-#include <asm/ist.h>
-#include <video/edid.h>
-
-/* setup data types */
-#define SETUP_NONE                     0
-#define SETUP_E820_EXT                 1
-#define SETUP_DTB                      2
-
-/* extensible setup data list node */
-struct setup_data {
-       __u64 next;
-       __u32 type;
-       __u32 len;
-       __u8 data[0];
-};
-
-struct setup_header {
-       __u8    setup_sects;
-       __u16   root_flags;
-       __u32   syssize;
-       __u16   ram_size;
-#define RAMDISK_IMAGE_START_MASK       0x07FF
-#define RAMDISK_PROMPT_FLAG            0x8000
-#define RAMDISK_LOAD_FLAG              0x4000
-       __u16   vid_mode;
-       __u16   root_dev;
-       __u16   boot_flag;
-       __u16   jump;
-       __u32   header;
-       __u16   version;
-       __u32   realmode_swtch;
-       __u16   start_sys;
-       __u16   kernel_version;
-       __u8    type_of_loader;
-       __u8    loadflags;
-#define LOADED_HIGH    (1<<0)
-#define QUIET_FLAG     (1<<5)
-#define KEEP_SEGMENTS  (1<<6)
-#define CAN_USE_HEAP   (1<<7)
-       __u16   setup_move_size;
-       __u32   code32_start;
-       __u32   ramdisk_image;
-       __u32   ramdisk_size;
-       __u32   bootsect_kludge;
-       __u16   heap_end_ptr;
-       __u8    ext_loader_ver;
-       __u8    ext_loader_type;
-       __u32   cmd_line_ptr;
-       __u32   initrd_addr_max;
-       __u32   kernel_alignment;
-       __u8    relocatable_kernel;
-       __u8    _pad2[3];
-       __u32   cmdline_size;
-       __u32   hardware_subarch;
-       __u64   hardware_subarch_data;
-       __u32   payload_offset;
-       __u32   payload_length;
-       __u64   setup_data;
-       __u64   pref_address;
-       __u32   init_size;
-       __u32   handover_offset;
-} __attribute__((packed));
-
-struct sys_desc_table {
-       __u16 length;
-       __u8  table[14];
-};
-
-/* Gleaned from OFW's set-parameters in cpu/x86/pc/linux.fth */
-struct olpc_ofw_header {
-       __u32 ofw_magic;        /* OFW signature */
-       __u32 ofw_version;
-       __u32 cif_handler;      /* callback into OFW */
-       __u32 irq_desc_table;
-} __attribute__((packed));
-
-struct efi_info {
-       __u32 efi_loader_signature;
-       __u32 efi_systab;
-       __u32 efi_memdesc_size;
-       __u32 efi_memdesc_version;
-       __u32 efi_memmap;
-       __u32 efi_memmap_size;
-       __u32 efi_systab_hi;
-       __u32 efi_memmap_hi;
-};
-
-/* The so-called "zeropage" */
-struct boot_params {
-       struct screen_info screen_info;                 /* 0x000 */
-       struct apm_bios_info apm_bios_info;             /* 0x040 */
-       __u8  _pad2[4];                                 /* 0x054 */
-       __u64  tboot_addr;                              /* 0x058 */
-       struct ist_info ist_info;                       /* 0x060 */
-       __u8  _pad3[16];                                /* 0x070 */
-       __u8  hd0_info[16];     /* obsolete! */         /* 0x080 */
-       __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */
-       struct sys_desc_table sys_desc_table;           /* 0x0a0 */
-       struct olpc_ofw_header olpc_ofw_header;         /* 0x0b0 */
-       __u8  _pad4[128];                               /* 0x0c0 */
-       struct edid_info edid_info;                     /* 0x140 */
-       struct efi_info efi_info;                       /* 0x1c0 */
-       __u32 alt_mem_k;                                /* 0x1e0 */
-       __u32 scratch;          /* Scratch field! */    /* 0x1e4 */
-       __u8  e820_entries;                             /* 0x1e8 */
-       __u8  eddbuf_entries;                           /* 0x1e9 */
-       __u8  edd_mbr_sig_buf_entries;                  /* 0x1ea */
-       __u8  kbd_status;                               /* 0x1eb */
-       __u8  _pad6[5];                                 /* 0x1ec */
-       struct setup_header hdr;    /* setup header */  /* 0x1f1 */
-       __u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
-       __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];      /* 0x290 */
-       struct e820entry e820_map[E820MAX];             /* 0x2d0 */
-       __u8  _pad8[48];                                /* 0xcd0 */
-       struct edd_info eddbuf[EDDMAXNR];               /* 0xd00 */
-       __u8  _pad9[276];                               /* 0xeec */
-} __attribute__((packed));
-
-enum {
-       X86_SUBARCH_PC = 0,
-       X86_SUBARCH_LGUEST,
-       X86_SUBARCH_XEN,
-       X86_SUBARCH_MRST,
-       X86_SUBARCH_CE4100,
-       X86_NR_SUBARCHS,
-};
-
-
-
-#endif /* _ASM_X86_BOOTPARAM_H */
diff --git a/arch/x86/include/asm/byteorder.h b/arch/x86/include/asm/byteorder.h
deleted file mode 100644 (file)
index b13a7a8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_X86_BYTEORDER_H
-#define _ASM_X86_BYTEORDER_H
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* _ASM_X86_BYTEORDER_H */
index 0bdbbb3b9ce70545337d86b68c269867d6075384..16a57f4ed64de83d8e4321cbbd497d76b01239a7 100644 (file)
@@ -8,6 +8,7 @@
 #define VCLOCK_NONE 0  /* No vDSO clock available.     */
 #define VCLOCK_TSC  1  /* vDSO should use vread_tsc.   */
 #define VCLOCK_HPET 2  /* vDSO should use vread_hpet.  */
+#define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */
 
 struct arch_clocksource_data {
        int vclock_mode;
index da40b1e2228e16ab236992eafb30b410f94cd831..2d9075e863a0cfc25e43b7d40e706e8016586859 100644 (file)
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
 #define X86_FEATURE_FSGSBASE   (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
+#define X86_FEATURE_TSC_ADJUST (9*32+ 1) /* TSC adjustment MSR 0x3b */
 #define X86_FEATURE_BMI1       (9*32+ 3) /* 1st group bit manipulation extensions */
 #define X86_FEATURE_HLE                (9*32+ 4) /* Hardware Lock Elision */
 #define X86_FEATURE_AVX2       (9*32+ 5) /* AVX2 instructions */
diff --git a/arch/x86/include/asm/crypto/camellia.h b/arch/x86/include/asm/crypto/camellia.h
new file mode 100644 (file)
index 0000000..98038ad
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef ASM_X86_CAMELLIA_H
+#define ASM_X86_CAMELLIA_H
+
+#include <linux/kernel.h>
+#include <linux/crypto.h>
+
+#define CAMELLIA_MIN_KEY_SIZE  16
+#define CAMELLIA_MAX_KEY_SIZE  32
+#define CAMELLIA_BLOCK_SIZE    16
+#define CAMELLIA_TABLE_BYTE_LEN        272
+#define CAMELLIA_PARALLEL_BLOCKS 2
+
+struct camellia_ctx {
+       u64 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
+       u32 key_length;
+};
+
+struct camellia_lrw_ctx {
+       struct lrw_table_ctx lrw_table;
+       struct camellia_ctx camellia_ctx;
+};
+
+struct camellia_xts_ctx {
+       struct camellia_ctx tweak_ctx;
+       struct camellia_ctx crypt_ctx;
+};
+
+extern int __camellia_setkey(struct camellia_ctx *cctx,
+                            const unsigned char *key,
+                            unsigned int key_len, u32 *flags);
+
+extern int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+                              unsigned int keylen);
+extern void lrw_camellia_exit_tfm(struct crypto_tfm *tfm);
+
+extern int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+                              unsigned int keylen);
+
+/* regular block cipher functions */
+asmlinkage void __camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
+                                  const u8 *src, bool xor);
+asmlinkage void camellia_dec_blk(struct camellia_ctx *ctx, u8 *dst,
+                                const u8 *src);
+
+/* 2-way parallel cipher functions */
+asmlinkage void __camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+                                       const u8 *src, bool xor);
+asmlinkage void camellia_dec_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+                                     const u8 *src);
+
+static inline void camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
+                                   const u8 *src)
+{
+       __camellia_enc_blk(ctx, dst, src, false);
+}
+
+static inline void camellia_enc_blk_xor(struct camellia_ctx *ctx, u8 *dst,
+                                       const u8 *src)
+{
+       __camellia_enc_blk(ctx, dst, src, true);
+}
+
+static inline void camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+                                        const u8 *src)
+{
+       __camellia_enc_blk_2way(ctx, dst, src, false);
+}
+
+static inline void camellia_enc_blk_xor_2way(struct camellia_ctx *ctx, u8 *dst,
+                                            const u8 *src)
+{
+       __camellia_enc_blk_2way(ctx, dst, src, true);
+}
+
+/* glue helpers */
+extern void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src);
+extern void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src,
+                              le128 *iv);
+extern void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
+                                   le128 *iv);
+
+#endif /* ASM_X86_CAMELLIA_H */
index 3e408bddc96f1f80ae66c60152c14533fdd12012..e2d65b061d27801c0c515dda3d1bc956ada4b563 100644 (file)
@@ -13,7 +13,7 @@
 typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src);
 typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src);
 typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src,
-                                      u128 *iv);
+                                      le128 *iv);
 
 #define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn))
 #define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn))
@@ -71,23 +71,29 @@ static inline void glue_fpu_end(bool fpu_enabled)
                kernel_fpu_end();
 }
 
-static inline void u128_to_be128(be128 *dst, const u128 *src)
+static inline void le128_to_be128(be128 *dst, const le128 *src)
 {
-       dst->a = cpu_to_be64(src->a);
-       dst->b = cpu_to_be64(src->b);
+       dst->a = cpu_to_be64(le64_to_cpu(src->a));
+       dst->b = cpu_to_be64(le64_to_cpu(src->b));
 }
 
-static inline void be128_to_u128(u128 *dst, const be128 *src)
+static inline void be128_to_le128(le128 *dst, const be128 *src)
 {
-       dst->a = be64_to_cpu(src->a);
-       dst->b = be64_to_cpu(src->b);
+       dst->a = cpu_to_le64(be64_to_cpu(src->a));
+       dst->b = cpu_to_le64(be64_to_cpu(src->b));
 }
 
-static inline void u128_inc(u128 *i)
+static inline void le128_inc(le128 *i)
 {
-       i->b++;
-       if (!i->b)
-               i->a++;
+       u64 a = le64_to_cpu(i->a);
+       u64 b = le64_to_cpu(i->b);
+
+       b++;
+       if (!b)
+               a++;
+
+       i->a = cpu_to_le64(a);
+       i->b = cpu_to_le64(b);
 }
 
 extern int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx,
index 432deedd294570bd1b0807491fca242027d70ab7..0da1d3e2a55ce3710509d0f3051af046b081a5e4 100644 (file)
@@ -6,27 +6,14 @@
 
 #define SERPENT_PARALLEL_BLOCKS 8
 
-asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst,
-                                          const u8 *src, bool xor);
-asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+                                        const u8 *src);
+asmlinkage void serpent_ecb_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
                                         const u8 *src);
 
-static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-                                  const u8 *src)
-{
-       __serpent_enc_blk_8way_avx(ctx, dst, src, false);
-}
-
-static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst,
-                                      const u8 *src)
-{
-       __serpent_enc_blk_8way_avx(ctx, dst, src, true);
-}
-
-static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-                                  const u8 *src)
-{
-       serpent_dec_blk_8way_avx(ctx, dst, src);
-}
+asmlinkage void serpent_cbc_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+                                        const u8 *src);
+asmlinkage void serpent_ctr_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+                                    const u8 *src, le128 *iv);
 
 #endif
index 9d2c514bd5f90020b3d22036a73ab816735b3416..878c51ceebb57f408d78eb94abb13d16d0c2801d 100644 (file)
@@ -31,9 +31,9 @@ asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
 /* helpers from twofish_x86_64-3way module */
 extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src);
 extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src,
-                               u128 *iv);
+                               le128 *iv);
 extern void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-                                    u128 *iv);
+                                    le128 *iv);
 
 extern int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
                              unsigned int keylen);
index 2d91580bf2288d46076a5a22beb96895ee31836d..4b528a970bd43f0ceed423d4f01819e251d47284 100644 (file)
@@ -2,83 +2,8 @@
 #define _ASM_X86_DEBUGREG_H
 
 
-/* Indicate the register numbers for a number of the specific
-   debug registers.  Registers 0-3 contain the addresses we wish to trap on */
-#define DR_FIRSTADDR 0        /* u_debugreg[DR_FIRSTADDR] */
-#define DR_LASTADDR 3         /* u_debugreg[DR_LASTADDR]  */
-
-#define DR_STATUS 6           /* u_debugreg[DR_STATUS]     */
-#define DR_CONTROL 7          /* u_debugreg[DR_CONTROL] */
-
-/* Define a few things for the status register.  We can use this to determine
-   which debugging register was responsible for the trap.  The other bits
-   are either reserved or not of interest to us. */
-
-/* Define reserved bits in DR6 which are always set to 1 */
-#define DR6_RESERVED   (0xFFFF0FF0)
-
-#define DR_TRAP0       (0x1)           /* db0 */
-#define DR_TRAP1       (0x2)           /* db1 */
-#define DR_TRAP2       (0x4)           /* db2 */
-#define DR_TRAP3       (0x8)           /* db3 */
-#define DR_TRAP_BITS   (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)
-
-#define DR_STEP                (0x4000)        /* single-step */
-#define DR_SWITCH      (0x8000)        /* task switch */
-
-/* Now define a bunch of things for manipulating the control register.
-   The top two bytes of the control register consist of 4 fields of 4
-   bits - each field corresponds to one of the four debug registers,
-   and indicates what types of access we trap on, and how large the data
-   field is that we are looking at */
-
-#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */
-#define DR_CONTROL_SIZE 4   /* 4 control bits per register */
-
-#define DR_RW_EXECUTE (0x0)   /* Settings for the access types to trap on */
-#define DR_RW_WRITE (0x1)
-#define DR_RW_READ (0x3)
-
-#define DR_LEN_1 (0x0) /* Settings for data length to trap on */
-#define DR_LEN_2 (0x4)
-#define DR_LEN_4 (0xC)
-#define DR_LEN_8 (0x8)
-
-/* The low byte to the control register determine which registers are
-   enabled.  There are 4 fields of two bits.  One bit is "local", meaning
-   that the processor will reset the bit after a task switch and the other
-   is global meaning that we have to explicitly reset the bit.  With linux,
-   you can use either one, since we explicitly zero the register when we enter
-   kernel mode. */
-
-#define DR_LOCAL_ENABLE_SHIFT 0    /* Extra shift to the local enable bit */
-#define DR_GLOBAL_ENABLE_SHIFT 1   /* Extra shift to the global enable bit */
-#define DR_LOCAL_ENABLE (0x1)      /* Local enable for reg 0 */
-#define DR_GLOBAL_ENABLE (0x2)     /* Global enable for reg 0 */
-#define DR_ENABLE_SIZE 2           /* 2 enable bits per register */
-
-#define DR_LOCAL_ENABLE_MASK (0x55)  /* Set  local bits for all 4 regs */
-#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */
-
-/* The second byte to the control register has a few special things.
-   We can slow the instruction pipeline for instructions coming via the
-   gdt or the ldt if we want to.  I am not sure why this is an advantage */
-
-#ifdef __i386__
-#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */
-#else
-#define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */
-#endif
-
-#define DR_LOCAL_SLOWDOWN (0x100)   /* Local slow the pipeline */
-#define DR_GLOBAL_SLOWDOWN (0x200)  /* Global slow the pipeline */
-
-/*
- * HW breakpoint additions
- */
-#ifdef __KERNEL__
-
 #include <linux/bug.h>
+#include <uapi/asm/debugreg.h>
 
 DECLARE_PER_CPU(unsigned long, cpu_dr7);
 
@@ -190,6 +115,4 @@ static inline void debug_stack_usage_dec(void) { }
 #endif /* X86_64 */
 
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_DEBUGREG_H */
index 37782566af241dca3d6e0c8264935dc3e0a16258..cccd07fa5e3a83ce79cd183b3ed94821429e40c0 100644 (file)
@@ -1,81 +1,14 @@
 #ifndef _ASM_X86_E820_H
 #define _ASM_X86_E820_H
-#define E820MAP        0x2d0           /* our map */
-#define E820MAX        128             /* number of entries in E820MAP */
 
-/*
- * Legacy E820 BIOS limits us to 128 (E820MAX) nodes due to the
- * constrained space in the zeropage.  If we have more nodes than
- * that, and if we've booted off EFI firmware, then the EFI tables
- * passed us from the EFI firmware can list more nodes.  Size our
- * internal memory map tables to have room for these additional
- * nodes, based on up to three entries per node for which the
- * kernel was built: MAX_NUMNODES == (1 << CONFIG_NODES_SHIFT),
- * plus E820MAX, allowing space for the possible duplicate E820
- * entries that might need room in the same arrays, prior to the
- * call to sanitize_e820_map() to remove duplicates.  The allowance
- * of three memory map entries per node is "enough" entries for
- * the initial hardware platform motivating this mechanism to make
- * use of additional EFI map entries.  Future platforms may want
- * to allow more than three entries per node or otherwise refine
- * this size.
- */
-
-/*
- * Odd: 'make headers_check' complains about numa.h if I try
- * to collapse the next two #ifdef lines to a single line:
- *     #if defined(__KERNEL__) && defined(CONFIG_EFI)
- */
-#ifdef __KERNEL__
 #ifdef CONFIG_EFI
 #include <linux/numa.h>
 #define E820_X_MAX (E820MAX + 3 * MAX_NUMNODES)
 #else  /* ! CONFIG_EFI */
 #define E820_X_MAX E820MAX
 #endif
-#else  /* ! __KERNEL__ */
-#define E820_X_MAX E820MAX
-#endif
-
-#define E820NR 0x1e8           /* # entries in E820MAP */
-
-#define E820_RAM       1
-#define E820_RESERVED  2
-#define E820_ACPI      3
-#define E820_NVS       4
-#define E820_UNUSABLE  5
-
-/*
- * reserved RAM used by kernel itself
- * if CONFIG_INTEL_TXT is enabled, memory of this type will be
- * included in the S3 integrity calculation and so should not include
- * any memory that BIOS might alter over the S3 transition
- */
-#define E820_RESERVED_KERN        128
-
+#include <uapi/asm/e820.h>
 #ifndef __ASSEMBLY__
-#include <linux/types.h>
-struct e820entry {
-       __u64 addr;     /* start of memory segment */
-       __u64 size;     /* size of memory segment */
-       __u32 type;     /* type of memory segment */
-} __attribute__((packed));
-
-struct e820map {
-       __u32 nr_map;
-       struct e820entry map[E820_X_MAX];
-};
-
-#define ISA_START_ADDRESS      0xa0000
-#define ISA_END_ADDRESS                0x100000
-
-#define BIOS_BEGIN             0x000a0000
-#define BIOS_END               0x00100000
-
-#define BIOS_ROM_BASE          0xffe00000
-#define BIOS_ROM_END           0xffffffff
-
-#ifdef __KERNEL__
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map e820;
 extern struct e820map e820_saved;
@@ -137,13 +70,8 @@ static inline bool is_ISA_range(u64 s, u64 e)
        return s >= ISA_START_ADDRESS && e <= ISA_END_ADDRESS;
 }
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
-
-#ifdef __KERNEL__
 #include <linux/ioport.h>
 
 #define HIGH_MEMORY    (1024*1024)
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_E820_H */
index 6e8fdf5ad1135c0100c8b7a5220bb79db2359ddb..fd13815fe85c9d9d45a6c79b7c93d9e68f9ebff0 100644 (file)
@@ -69,23 +69,37 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
        efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3),         \
                  (u64)(a4), (u64)(a5), (u64)(a6))
 
+extern unsigned long efi_call_virt_prelog(void);
+extern void efi_call_virt_epilog(unsigned long);
+
+#define efi_callx(x, func, ...)                                        \
+       ({                                                      \
+               efi_status_t __status;                          \
+               unsigned long __pgd;                            \
+                                                               \
+               __pgd = efi_call_virt_prelog();                 \
+               __status = efi_call##x(func, __VA_ARGS__);      \
+               efi_call_virt_epilog(__pgd);                    \
+               __status;                                       \
+       })
+
 #define efi_call_virt0(f)                              \
-       efi_call0((void *)(efi.systab->runtime->f))
+       efi_callx(0, (void *)(efi.systab->runtime->f))
 #define efi_call_virt1(f, a1)                                  \
-       efi_call1((void *)(efi.systab->runtime->f), (u64)(a1))
+       efi_callx(1, (void *)(efi.systab->runtime->f), (u64)(a1))
 #define efi_call_virt2(f, a1, a2)                                      \
-       efi_call2((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
+       efi_callx(2, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
 #define efi_call_virt3(f, a1, a2, a3)                                  \
-       efi_call3((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+       efi_callx(3, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
                  (u64)(a3))
 #define efi_call_virt4(f, a1, a2, a3, a4)                              \
-       efi_call4((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+       efi_callx(4, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
                  (u64)(a3), (u64)(a4))
 #define efi_call_virt5(f, a1, a2, a3, a4, a5)                          \
-       efi_call5((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+       efi_callx(5, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
                  (u64)(a3), (u64)(a4), (u64)(a5))
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)                      \
-       efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+       efi_callx(6, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
                  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
diff --git a/arch/x86/include/asm/errno.h b/arch/x86/include/asm/errno.h
deleted file mode 100644 (file)
index 4c82b50..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/x86/include/asm/fcntl.h b/arch/x86/include/asm/fcntl.h
deleted file mode 100644 (file)
index 46ab12d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
index 4da3c0c4c9741c38efd6418ec081404bb43d8fef..a09c28571064d7d4d148dc34f7f86b3bcb319abb 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
+#include <asm/pvclock.h>
 #ifdef CONFIG_X86_32
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
@@ -80,6 +81,10 @@ enum fixed_addresses {
                            + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
        VVAR_PAGE,
        VSYSCALL_HPET,
+#endif
+#ifdef CONFIG_PARAVIRT_CLOCK
+       PVCLOCK_FIXMAP_BEGIN,
+       PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1,
 #endif
        FIX_DBGP_BASE,
        FIX_EARLYCON_MEM_BASE,
index 824ca07860d012cdcc9c46886500d056fdb2aeed..ef1c4d2d41eceff8cee01b4fdc9c18987c2dbe20 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef        _I386_HW_BREAKPOINT_H
 #define        _I386_HW_BREAKPOINT_H
 
-#ifdef __KERNEL__
+#include <uapi/asm/hw_breakpoint.h>
+
 #define        __ARCH_HW_BREAKPOINT_H
 
 /*
@@ -71,6 +72,4 @@ extern int arch_bp_generic_fields(int x86_len, int x86_type,
 
 extern struct pmu perf_ops_bp;
 
-#endif /* __KERNEL__ */
 #endif /* _I386_HW_BREAKPOINT_H */
-
diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h
deleted file mode 100644 (file)
index b80420b..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef _ASM_X86_HYPERV_H
-#define _ASM_X86_HYPERV_H
-
-#include <linux/types.h>
-
-/*
- * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
- * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
- */
-#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS  0x40000000
-#define HYPERV_CPUID_INTERFACE                 0x40000001
-#define HYPERV_CPUID_VERSION                   0x40000002
-#define HYPERV_CPUID_FEATURES                  0x40000003
-#define HYPERV_CPUID_ENLIGHTMENT_INFO          0x40000004
-#define HYPERV_CPUID_IMPLEMENT_LIMITS          0x40000005
-
-#define HYPERV_HYPERVISOR_PRESENT_BIT          0x80000000
-#define HYPERV_CPUID_MIN                       0x40000005
-#define HYPERV_CPUID_MAX                       0x4000ffff
-
-/*
- * Feature identification. EAX indicates which features are available
- * to the partition based upon the current partition privileges.
- */
-
-/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
-#define HV_X64_MSR_VP_RUNTIME_AVAILABLE                (1 << 0)
-/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
-#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE    (1 << 1)
-/*
- * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
- * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
- */
-#define HV_X64_MSR_SYNIC_AVAILABLE             (1 << 2)
-/*
- * Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
- * HV_X64_MSR_STIMER3_COUNT) available
- */
-#define HV_X64_MSR_SYNTIMER_AVAILABLE          (1 << 3)
-/*
- * APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
- * are available
- */
-#define HV_X64_MSR_APIC_ACCESS_AVAILABLE       (1 << 4)
-/* Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL) available*/
-#define HV_X64_MSR_HYPERCALL_AVAILABLE         (1 << 5)
-/* Access virtual processor index MSR (HV_X64_MSR_VP_INDEX) available*/
-#define HV_X64_MSR_VP_INDEX_AVAILABLE          (1 << 6)
-/* Virtual system reset MSR (HV_X64_MSR_RESET) is available*/
-#define HV_X64_MSR_RESET_AVAILABLE             (1 << 7)
- /*
-  * Access statistics pages MSRs (HV_X64_MSR_STATS_PARTITION_RETAIL_PAGE,
-  * HV_X64_MSR_STATS_PARTITION_INTERNAL_PAGE, HV_X64_MSR_STATS_VP_RETAIL_PAGE,
-  * HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available
-  */
-#define HV_X64_MSR_STAT_PAGES_AVAILABLE                (1 << 8)
-
-/*
- * Feature identification: EBX indicates which flags were specified at
- * partition creation. The format is the same as the partition creation
- * flag structure defined in section Partition Creation Flags.
- */
-#define HV_X64_CREATE_PARTITIONS               (1 << 0)
-#define HV_X64_ACCESS_PARTITION_ID             (1 << 1)
-#define HV_X64_ACCESS_MEMORY_POOL              (1 << 2)
-#define HV_X64_ADJUST_MESSAGE_BUFFERS          (1 << 3)
-#define HV_X64_POST_MESSAGES                   (1 << 4)
-#define HV_X64_SIGNAL_EVENTS                   (1 << 5)
-#define HV_X64_CREATE_PORT                     (1 << 6)
-#define HV_X64_CONNECT_PORT                    (1 << 7)
-#define HV_X64_ACCESS_STATS                    (1 << 8)
-#define HV_X64_DEBUGGING                       (1 << 11)
-#define HV_X64_CPU_POWER_MANAGEMENT            (1 << 12)
-#define HV_X64_CONFIGURE_PROFILER              (1 << 13)
-
-/*
- * Feature identification. EDX indicates which miscellaneous features
- * are available to the partition.
- */
-/* The MWAIT instruction is available (per section MONITOR / MWAIT) */
-#define HV_X64_MWAIT_AVAILABLE                         (1 << 0)
-/* Guest debugging support is available */
-#define HV_X64_GUEST_DEBUGGING_AVAILABLE               (1 << 1)
-/* Performance Monitor support is available*/
-#define HV_X64_PERF_MONITOR_AVAILABLE                  (1 << 2)
-/* Support for physical CPU dynamic partitioning events is available*/
-#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE      (1 << 3)
-/*
- * Support for passing hypercall input parameter block via XMM
- * registers is available
- */
-#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE          (1 << 4)
-/* Support for a virtual guest idle state is available */
-#define HV_X64_GUEST_IDLE_STATE_AVAILABLE              (1 << 5)
-
-/*
- * Implementation recommendations. Indicates which behaviors the hypervisor
- * recommends the OS implement for optimal performance.
- */
- /*
-  * Recommend using hypercall for address space switches rather
-  * than MOV to CR3 instruction
-  */
-#define HV_X64_MWAIT_RECOMMENDED               (1 << 0)
-/* Recommend using hypercall for local TLB flushes rather
- * than INVLPG or MOV to CR3 instructions */
-#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED     (1 << 1)
-/*
- * Recommend using hypercall for remote TLB flushes rather
- * than inter-processor interrupts
- */
-#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED    (1 << 2)
-/*
- * Recommend using MSRs for accessing APIC registers
- * EOI, ICR and TPR rather than their memory-mapped counterparts
- */
-#define HV_X64_APIC_ACCESS_RECOMMENDED         (1 << 3)
-/* Recommend using the hypervisor-provided MSR to initiate a system RESET */
-#define HV_X64_SYSTEM_RESET_RECOMMENDED                (1 << 4)
-/*
- * Recommend using relaxed timing for this partition. If used,
- * the VM should disable any watchdog timeouts that rely on the
- * timely delivery of external interrupts
- */
-#define HV_X64_RELAXED_TIMING_RECOMMENDED      (1 << 5)
-
-/* MSR used to identify the guest OS. */
-#define HV_X64_MSR_GUEST_OS_ID                 0x40000000
-
-/* MSR used to setup pages used to communicate with the hypervisor. */
-#define HV_X64_MSR_HYPERCALL                   0x40000001
-
-/* MSR used to provide vcpu index */
-#define HV_X64_MSR_VP_INDEX                    0x40000002
-
-/* MSR used to read the per-partition time reference counter */
-#define HV_X64_MSR_TIME_REF_COUNT              0x40000020
-
-/* Define the virtual APIC registers */
-#define HV_X64_MSR_EOI                         0x40000070
-#define HV_X64_MSR_ICR                         0x40000071
-#define HV_X64_MSR_TPR                         0x40000072
-#define HV_X64_MSR_APIC_ASSIST_PAGE            0x40000073
-
-/* Define synthetic interrupt controller model specific registers. */
-#define HV_X64_MSR_SCONTROL                    0x40000080
-#define HV_X64_MSR_SVERSION                    0x40000081
-#define HV_X64_MSR_SIEFP                       0x40000082
-#define HV_X64_MSR_SIMP                                0x40000083
-#define HV_X64_MSR_EOM                         0x40000084
-#define HV_X64_MSR_SINT0                       0x40000090
-#define HV_X64_MSR_SINT1                       0x40000091
-#define HV_X64_MSR_SINT2                       0x40000092
-#define HV_X64_MSR_SINT3                       0x40000093
-#define HV_X64_MSR_SINT4                       0x40000094
-#define HV_X64_MSR_SINT5                       0x40000095
-#define HV_X64_MSR_SINT6                       0x40000096
-#define HV_X64_MSR_SINT7                       0x40000097
-#define HV_X64_MSR_SINT8                       0x40000098
-#define HV_X64_MSR_SINT9                       0x40000099
-#define HV_X64_MSR_SINT10                      0x4000009A
-#define HV_X64_MSR_SINT11                      0x4000009B
-#define HV_X64_MSR_SINT12                      0x4000009C
-#define HV_X64_MSR_SINT13                      0x4000009D
-#define HV_X64_MSR_SINT14                      0x4000009E
-#define HV_X64_MSR_SINT15                      0x4000009F
-
-
-#define HV_X64_MSR_HYPERCALL_ENABLE            0x00000001
-#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT        12
-#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK \
-               (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
-
-/* Declare the various hypercall operations. */
-#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT                0x0008
-
-#define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE             0x00000001
-#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT      12
-#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK       \
-               (~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
-
-#define HV_PROCESSOR_POWER_STATE_C0            0
-#define HV_PROCESSOR_POWER_STATE_C1            1
-#define HV_PROCESSOR_POWER_STATE_C2            2
-#define HV_PROCESSOR_POWER_STATE_C3            3
-
-/* hypercall status code */
-#define HV_STATUS_SUCCESS                      0
-#define HV_STATUS_INVALID_HYPERCALL_CODE       2
-#define HV_STATUS_INVALID_HYPERCALL_INPUT      3
-#define HV_STATUS_INVALID_ALIGNMENT            4
-#define HV_STATUS_INSUFFICIENT_BUFFERS         19
-
-#endif
diff --git a/arch/x86/include/asm/ioctl.h b/arch/x86/include/asm/ioctl.h
deleted file mode 100644 (file)
index b279fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/x86/include/asm/ioctls.h b/arch/x86/include/asm/ioctls.h
deleted file mode 100644 (file)
index ec34c76..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctls.h>
diff --git a/arch/x86/include/asm/ipcbuf.h b/arch/x86/include/asm/ipcbuf.h
deleted file mode 100644 (file)
index 84c7e51..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
index 7e5dff1de0e9fc8a98cab9810a69f4549dec3c17..c9803f1a20337f8ed267d55d94542f4e72d0ebc2 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _ASM_X86_IST_H
-#define _ASM_X86_IST_H
-
 /*
  * Include file for the interface to IST BIOS
  * Copyright 2002 Andy Grover <andrew.grover@intel.com>
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  */
+#ifndef _ASM_X86_IST_H
+#define _ASM_X86_IST_H
 
+#include <uapi/asm/ist.h>
 
-#include <linux/types.h>
-
-struct ist_info {
-       __u32 signature;
-       __u32 command;
-       __u32 event;
-       __u32 perf_level;
-};
-
-#ifdef __KERNEL__
 
 extern struct ist_info ist_info;
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_X86_IST_H */
index 317ff1703d0b0a5e7eaf17b94fd93640b8e62997..6080d2694bad07fcf3507d7a37231f00a333668e 100644 (file)
@@ -163,6 +163,9 @@ struct kimage_arch {
 };
 #endif
 
+typedef void crash_vmclear_fn(void);
+extern crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss;
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_KEXEC_H */
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
deleted file mode 100644 (file)
index a65ec29..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-#ifndef _ASM_X86_KVM_H
-#define _ASM_X86_KVM_H
-
-/*
- * KVM x86 specific structures and definitions
- *
- */
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define DE_VECTOR 0
-#define DB_VECTOR 1
-#define BP_VECTOR 3
-#define OF_VECTOR 4
-#define BR_VECTOR 5
-#define UD_VECTOR 6
-#define NM_VECTOR 7
-#define DF_VECTOR 8
-#define TS_VECTOR 10
-#define NP_VECTOR 11
-#define SS_VECTOR 12
-#define GP_VECTOR 13
-#define PF_VECTOR 14
-#define MF_VECTOR 16
-#define MC_VECTOR 18
-
-/* Select x86 specific features in <linux/kvm.h> */
-#define __KVM_HAVE_PIT
-#define __KVM_HAVE_IOAPIC
-#define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_DEVICE_ASSIGNMENT
-#define __KVM_HAVE_MSI
-#define __KVM_HAVE_USER_NMI
-#define __KVM_HAVE_GUEST_DEBUG
-#define __KVM_HAVE_MSIX
-#define __KVM_HAVE_MCE
-#define __KVM_HAVE_PIT_STATE2
-#define __KVM_HAVE_XEN_HVM
-#define __KVM_HAVE_VCPU_EVENTS
-#define __KVM_HAVE_DEBUGREGS
-#define __KVM_HAVE_XSAVE
-#define __KVM_HAVE_XCRS
-#define __KVM_HAVE_READONLY_MEM
-
-/* Architectural interrupt line count. */
-#define KVM_NR_INTERRUPTS 256
-
-struct kvm_memory_alias {
-       __u32 slot;  /* this has a different namespace than memory slots */
-       __u32 flags;
-       __u64 guest_phys_addr;
-       __u64 memory_size;
-       __u64 target_phys_addr;
-};
-
-/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
-struct kvm_pic_state {
-       __u8 last_irr;  /* edge detection */
-       __u8 irr;               /* interrupt request register */
-       __u8 imr;               /* interrupt mask register */
-       __u8 isr;               /* interrupt service register */
-       __u8 priority_add;      /* highest irq priority */
-       __u8 irq_base;
-       __u8 read_reg_select;
-       __u8 poll;
-       __u8 special_mask;
-       __u8 init_state;
-       __u8 auto_eoi;
-       __u8 rotate_on_auto_eoi;
-       __u8 special_fully_nested_mode;
-       __u8 init4;             /* true if 4 byte init */
-       __u8 elcr;              /* PIIX edge/trigger selection */
-       __u8 elcr_mask;
-};
-
-#define KVM_IOAPIC_NUM_PINS  24
-struct kvm_ioapic_state {
-       __u64 base_address;
-       __u32 ioregsel;
-       __u32 id;
-       __u32 irr;
-       __u32 pad;
-       union {
-               __u64 bits;
-               struct {
-                       __u8 vector;
-                       __u8 delivery_mode:3;
-                       __u8 dest_mode:1;
-                       __u8 delivery_status:1;
-                       __u8 polarity:1;
-                       __u8 remote_irr:1;
-                       __u8 trig_mode:1;
-                       __u8 mask:1;
-                       __u8 reserve:7;
-                       __u8 reserved[4];
-                       __u8 dest_id;
-               } fields;
-       } redirtbl[KVM_IOAPIC_NUM_PINS];
-};
-
-#define KVM_IRQCHIP_PIC_MASTER   0
-#define KVM_IRQCHIP_PIC_SLAVE    1
-#define KVM_IRQCHIP_IOAPIC       2
-#define KVM_NR_IRQCHIPS          3
-
-/* for KVM_GET_REGS and KVM_SET_REGS */
-struct kvm_regs {
-       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
-       __u64 rax, rbx, rcx, rdx;
-       __u64 rsi, rdi, rsp, rbp;
-       __u64 r8,  r9,  r10, r11;
-       __u64 r12, r13, r14, r15;
-       __u64 rip, rflags;
-};
-
-/* for KVM_GET_LAPIC and KVM_SET_LAPIC */
-#define KVM_APIC_REG_SIZE 0x400
-struct kvm_lapic_state {
-       char regs[KVM_APIC_REG_SIZE];
-};
-
-struct kvm_segment {
-       __u64 base;
-       __u32 limit;
-       __u16 selector;
-       __u8  type;
-       __u8  present, dpl, db, s, l, g, avl;
-       __u8  unusable;
-       __u8  padding;
-};
-
-struct kvm_dtable {
-       __u64 base;
-       __u16 limit;
-       __u16 padding[3];
-};
-
-
-/* for KVM_GET_SREGS and KVM_SET_SREGS */
-struct kvm_sregs {
-       /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
-       struct kvm_segment cs, ds, es, fs, gs, ss;
-       struct kvm_segment tr, ldt;
-       struct kvm_dtable gdt, idt;
-       __u64 cr0, cr2, cr3, cr4, cr8;
-       __u64 efer;
-       __u64 apic_base;
-       __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
-};
-
-/* for KVM_GET_FPU and KVM_SET_FPU */
-struct kvm_fpu {
-       __u8  fpr[8][16];
-       __u16 fcw;
-       __u16 fsw;
-       __u8  ftwx;  /* in fxsave format */
-       __u8  pad1;
-       __u16 last_opcode;
-       __u64 last_ip;
-       __u64 last_dp;
-       __u8  xmm[16][16];
-       __u32 mxcsr;
-       __u32 pad2;
-};
-
-struct kvm_msr_entry {
-       __u32 index;
-       __u32 reserved;
-       __u64 data;
-};
-
-/* for KVM_GET_MSRS and KVM_SET_MSRS */
-struct kvm_msrs {
-       __u32 nmsrs; /* number of msrs in entries */
-       __u32 pad;
-
-       struct kvm_msr_entry entries[0];
-};
-
-/* for KVM_GET_MSR_INDEX_LIST */
-struct kvm_msr_list {
-       __u32 nmsrs; /* number of msrs in entries */
-       __u32 indices[0];
-};
-
-
-struct kvm_cpuid_entry {
-       __u32 function;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding;
-};
-
-/* for KVM_SET_CPUID */
-struct kvm_cpuid {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry entries[0];
-};
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
-#define KVM_CPUID_FLAG_STATEFUL_FUNC    2
-#define KVM_CPUID_FLAG_STATE_READ_NEXT  4
-
-/* for KVM_SET_CPUID2 */
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-/* for KVM_GET_PIT and KVM_SET_PIT */
-struct kvm_pit_channel_state {
-       __u32 count; /* can be 65536 */
-       __u16 latched_count;
-       __u8 count_latched;
-       __u8 status_latched;
-       __u8 status;
-       __u8 read_state;
-       __u8 write_state;
-       __u8 write_latch;
-       __u8 rw_mode;
-       __u8 mode;
-       __u8 bcd;
-       __u8 gate;
-       __s64 count_load_time;
-};
-
-struct kvm_debug_exit_arch {
-       __u32 exception;
-       __u32 pad;
-       __u64 pc;
-       __u64 dr6;
-       __u64 dr7;
-};
-
-#define KVM_GUESTDBG_USE_SW_BP         0x00010000
-#define KVM_GUESTDBG_USE_HW_BP         0x00020000
-#define KVM_GUESTDBG_INJECT_DB         0x00040000
-#define KVM_GUESTDBG_INJECT_BP         0x00080000
-
-/* for KVM_SET_GUEST_DEBUG */
-struct kvm_guest_debug_arch {
-       __u64 debugreg[8];
-};
-
-struct kvm_pit_state {
-       struct kvm_pit_channel_state channels[3];
-};
-
-#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
-
-struct kvm_pit_state2 {
-       struct kvm_pit_channel_state channels[3];
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-struct kvm_reinject_control {
-       __u8 pit_reinject;
-       __u8 reserved[31];
-};
-
-/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */
-#define KVM_VCPUEVENT_VALID_NMI_PENDING        0x00000001
-#define KVM_VCPUEVENT_VALID_SIPI_VECTOR        0x00000002
-#define KVM_VCPUEVENT_VALID_SHADOW     0x00000004
-
-/* Interrupt shadow states */
-#define KVM_X86_SHADOW_INT_MOV_SS      0x01
-#define KVM_X86_SHADOW_INT_STI         0x02
-
-/* for KVM_GET/SET_VCPU_EVENTS */
-struct kvm_vcpu_events {
-       struct {
-               __u8 injected;
-               __u8 nr;
-               __u8 has_error_code;
-               __u8 pad;
-               __u32 error_code;
-       } exception;
-       struct {
-               __u8 injected;
-               __u8 nr;
-               __u8 soft;
-               __u8 shadow;
-       } interrupt;
-       struct {
-               __u8 injected;
-               __u8 pending;
-               __u8 masked;
-               __u8 pad;
-       } nmi;
-       __u32 sipi_vector;
-       __u32 flags;
-       __u32 reserved[10];
-};
-
-/* for KVM_GET/SET_DEBUGREGS */
-struct kvm_debugregs {
-       __u64 db[4];
-       __u64 dr6;
-       __u64 dr7;
-       __u64 flags;
-       __u64 reserved[9];
-};
-
-/* for KVM_CAP_XSAVE */
-struct kvm_xsave {
-       __u32 region[1024];
-};
-
-#define KVM_MAX_XCRS   16
-
-struct kvm_xcr {
-       __u32 xcr;
-       __u32 reserved;
-       __u64 value;
-};
-
-struct kvm_xcrs {
-       __u32 nr_xcrs;
-       __u32 flags;
-       struct kvm_xcr xcrs[KVM_MAX_XCRS];
-       __u64 padding[16];
-};
-
-/* definition of registers in kvm_run */
-struct kvm_sync_regs {
-};
-
-#endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/include/asm/kvm_guest.h b/arch/x86/include/asm/kvm_guest.h
new file mode 100644 (file)
index 0000000..a92b176
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_KVM_GUEST_H
+#define _ASM_X86_KVM_GUEST_H
+
+int kvm_setup_vsyscall_timeinfo(void);
+
+#endif /* _ASM_X86_KVM_GUEST_H */
index b2e11f4524354db111134fb28ef9dfd99f3edaee..dc87b65e9c3a065b51c908bd9c964134718a5b94 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/kvm_para.h>
 #include <linux/kvm_types.h>
 #include <linux/perf_event.h>
+#include <linux/pvclock_gtod.h>
+#include <linux/clocksource.h>
 
 #include <asm/pvclock-abi.h>
 #include <asm/desc.h>
@@ -442,6 +444,7 @@ struct kvm_vcpu_arch {
        s8 virtual_tsc_shift;
        u32 virtual_tsc_mult;
        u32 virtual_tsc_khz;
+       s64 ia32_tsc_adjust_msr;
 
        atomic_t nmi_queued;  /* unprocessed asynchronous NMIs */
        unsigned nmi_pending; /* NMI queued after currently running handler */
@@ -559,6 +562,12 @@ struct kvm_arch {
        u64 cur_tsc_write;
        u64 cur_tsc_offset;
        u8  cur_tsc_generation;
+       int nr_vcpus_matched_tsc;
+
+       spinlock_t pvclock_gtod_sync_lock;
+       bool use_master_clock;
+       u64 master_kernel_ns;
+       cycle_t master_cycle_now;
 
        struct kvm_xen_hvm_config xen_hvm_config;
 
@@ -612,6 +621,12 @@ struct kvm_vcpu_stat {
 
 struct x86_instruction_info;
 
+struct msr_data {
+       bool host_initiated;
+       u32 index;
+       u64 data;
+};
+
 struct kvm_x86_ops {
        int (*cpu_has_kvm_support)(void);          /* __init */
        int (*disabled_by_bios)(void);             /* __init */
@@ -634,7 +649,7 @@ struct kvm_x86_ops {
 
        void (*update_db_bp_intercept)(struct kvm_vcpu *vcpu);
        int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
-       int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
+       int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr);
        u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
        void (*get_segment)(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
@@ -697,10 +712,11 @@ struct kvm_x86_ops {
        bool (*has_wbinvd_exit)(void);
 
        void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale);
+       u64 (*read_tsc_offset)(struct kvm_vcpu *vcpu);
        void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
        u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
-       u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu);
+       u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu, u64 host_tsc);
 
        void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
 
@@ -785,7 +801,7 @@ static inline int emulate_instruction(struct kvm_vcpu *vcpu,
 
 void kvm_enable_efer_bits(u64);
 int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *data);
-int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
+int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr);
 
 struct x86_emulate_ctxt;
 
@@ -812,7 +828,7 @@ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l);
 int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr);
 
 int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
-int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
+int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr);
 
 unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu);
 void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
index eb3e9d85e1f1c75fc0db709cc40dd7a226d928cd..5ed1f16187be177dc799531f4a1e0febd6f38d97 100644 (file)
@@ -1,103 +1,8 @@
 #ifndef _ASM_X86_KVM_PARA_H
 #define _ASM_X86_KVM_PARA_H
 
-#include <linux/types.h>
-#include <asm/hyperv.h>
-
-/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
- * should be used to determine that a VM is running under KVM.
- */
-#define KVM_CPUID_SIGNATURE    0x40000000
-
-/* This CPUID returns a feature bitmap in eax.  Before enabling a particular
- * paravirtualization, the appropriate feature bit should be checked.
- */
-#define KVM_CPUID_FEATURES     0x40000001
-#define KVM_FEATURE_CLOCKSOURCE                0
-#define KVM_FEATURE_NOP_IO_DELAY       1
-#define KVM_FEATURE_MMU_OP             2
-/* This indicates that the new set of kvmclock msrs
- * are available. The use of 0x11 and 0x12 is deprecated
- */
-#define KVM_FEATURE_CLOCKSOURCE2        3
-#define KVM_FEATURE_ASYNC_PF           4
-#define KVM_FEATURE_STEAL_TIME         5
-#define KVM_FEATURE_PV_EOI             6
-
-/* The last 8 bits are used to indicate how to interpret the flags field
- * in pvclock structure. If no bits are set, all flags are ignored.
- */
-#define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT     24
-
-#define MSR_KVM_WALL_CLOCK  0x11
-#define MSR_KVM_SYSTEM_TIME 0x12
-
-#define KVM_MSR_ENABLED 1
-/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
-#define MSR_KVM_WALL_CLOCK_NEW  0x4b564d00
-#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
-#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
-#define MSR_KVM_STEAL_TIME  0x4b564d03
-#define MSR_KVM_PV_EOI_EN      0x4b564d04
-
-struct kvm_steal_time {
-       __u64 steal;
-       __u32 version;
-       __u32 flags;
-       __u32 pad[12];
-};
-
-#define KVM_STEAL_ALIGNMENT_BITS 5
-#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
-#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
-
-#define KVM_MAX_MMU_OP_BATCH           32
-
-#define KVM_ASYNC_PF_ENABLED                   (1 << 0)
-#define KVM_ASYNC_PF_SEND_ALWAYS               (1 << 1)
-
-/* Operations for KVM_HC_MMU_OP */
-#define KVM_MMU_OP_WRITE_PTE            1
-#define KVM_MMU_OP_FLUSH_TLB           2
-#define KVM_MMU_OP_RELEASE_PT          3
-
-/* Payload for KVM_HC_MMU_OP */
-struct kvm_mmu_op_header {
-       __u32 op;
-       __u32 pad;
-};
-
-struct kvm_mmu_op_write_pte {
-       struct kvm_mmu_op_header header;
-       __u64 pte_phys;
-       __u64 pte_val;
-};
-
-struct kvm_mmu_op_flush_tlb {
-       struct kvm_mmu_op_header header;
-};
-
-struct kvm_mmu_op_release_pt {
-       struct kvm_mmu_op_header header;
-       __u64 pt_phys;
-};
-
-#define KVM_PV_REASON_PAGE_NOT_PRESENT 1
-#define KVM_PV_REASON_PAGE_READY 2
-
-struct kvm_vcpu_pv_apf_data {
-       __u32 reason;
-       __u8 pad[60];
-       __u32 enabled;
-};
-
-#define KVM_PV_EOI_BIT 0
-#define KVM_PV_EOI_MASK (0x1 << KVM_PV_EOI_BIT)
-#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
-#define KVM_PV_EOI_DISABLED 0x0
-
-#ifdef __KERNEL__
 #include <asm/processor.h>
+#include <uapi/asm/kvm_para.h>
 
 extern void kvmclock_init(void);
 extern int kvm_register_clock(char *txt);
@@ -228,6 +133,4 @@ static inline void kvm_disable_steal_time(void)
 }
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_KVM_PARA_H */
diff --git a/arch/x86/include/asm/ldt.h b/arch/x86/include/asm/ldt.h
deleted file mode 100644 (file)
index 46727eb..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ldt.h
- *
- * Definitions of structures used with the modify_ldt system call.
- */
-#ifndef _ASM_X86_LDT_H
-#define _ASM_X86_LDT_H
-
-/* Maximum number of LDT entries supported. */
-#define LDT_ENTRIES    8192
-/* The size of each LDT entry. */
-#define LDT_ENTRY_SIZE 8
-
-#ifndef __ASSEMBLY__
-/*
- * Note on 64bit base and limit is ignored and you cannot set DS/ES/CS
- * not to the default values if you still want to do syscalls. This
- * call is more for 32bit mode therefore.
- */
-struct user_desc {
-       unsigned int  entry_number;
-       unsigned int  base_addr;
-       unsigned int  limit;
-       unsigned int  seg_32bit:1;
-       unsigned int  contents:2;
-       unsigned int  read_exec_only:1;
-       unsigned int  limit_in_pages:1;
-       unsigned int  seg_not_present:1;
-       unsigned int  useable:1;
-#ifdef __x86_64__
-       unsigned int  lm:1;
-#endif
-};
-
-#define MODIFY_LDT_CONTENTS_DATA       0
-#define MODIFY_LDT_CONTENTS_STACK      1
-#define MODIFY_LDT_CONTENTS_CODE       2
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_X86_LDT_H */
index 54d73b1f00a0e21fd94394f829c94aa8d6a9bb46..ecdfee60ee4afb0e3b21e3c313420fc565468e56 100644 (file)
 #ifndef _ASM_X86_MCE_H
 #define _ASM_X86_MCE_H
 
-#include <linux/types.h>
-#include <asm/ioctls.h>
-
-/*
- * Machine Check support for x86
- */
-
-/* MCG_CAP register defines */
-#define MCG_BANKCNT_MASK       0xff         /* Number of Banks */
-#define MCG_CTL_P              (1ULL<<8)    /* MCG_CTL register available */
-#define MCG_EXT_P              (1ULL<<9)    /* Extended registers available */
-#define MCG_CMCI_P             (1ULL<<10)   /* CMCI supported */
-#define MCG_EXT_CNT_MASK       0xff0000     /* Number of Extended registers */
-#define MCG_EXT_CNT_SHIFT      16
-#define MCG_EXT_CNT(c)         (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
-#define MCG_SER_P              (1ULL<<24)   /* MCA recovery/new status bits */
-
-/* MCG_STATUS register defines */
-#define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
-#define MCG_STATUS_EIPV  (1ULL<<1)   /* ip points to correct instruction */
-#define MCG_STATUS_MCIP  (1ULL<<2)   /* machine check in progress */
-
-/* MCi_STATUS register defines */
-#define MCI_STATUS_VAL   (1ULL<<63)  /* valid error */
-#define MCI_STATUS_OVER  (1ULL<<62)  /* previous errors lost */
-#define MCI_STATUS_UC    (1ULL<<61)  /* uncorrected error */
-#define MCI_STATUS_EN    (1ULL<<60)  /* error enabled */
-#define MCI_STATUS_MISCV (1ULL<<59)  /* misc error reg. valid */
-#define MCI_STATUS_ADDRV (1ULL<<58)  /* addr reg. valid */
-#define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */
-#define MCI_STATUS_S    (1ULL<<56)  /* Signaled machine check */
-#define MCI_STATUS_AR   (1ULL<<55)  /* Action required */
-#define MCACOD           0xffff     /* MCA Error Code */
-
-/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */
-#define MCACOD_SCRUB   0x00C0  /* 0xC0-0xCF Memory Scrubbing */
-#define MCACOD_SCRUBMSK        0xfff0
-#define MCACOD_L3WB    0x017A  /* L3 Explicit Writeback */
-#define MCACOD_DATA    0x0134  /* Data Load */
-#define MCACOD_INSTR   0x0150  /* Instruction Fetch */
-
-/* MCi_MISC register defines */
-#define MCI_MISC_ADDR_LSB(m)   ((m) & 0x3f)
-#define MCI_MISC_ADDR_MODE(m)  (((m) >> 6) & 7)
-#define  MCI_MISC_ADDR_SEGOFF  0       /* segment offset */
-#define  MCI_MISC_ADDR_LINEAR  1       /* linear address */
-#define  MCI_MISC_ADDR_PHYS    2       /* physical address */
-#define  MCI_MISC_ADDR_MEM     3       /* memory address */
-#define  MCI_MISC_ADDR_GENERIC 7       /* generic */
-
-/* CTL2 register defines */
-#define MCI_CTL2_CMCI_EN               (1ULL << 30)
-#define MCI_CTL2_CMCI_THRESHOLD_MASK   0x7fffULL
-
-#define MCJ_CTX_MASK           3
-#define MCJ_CTX(flags)         ((flags) & MCJ_CTX_MASK)
-#define MCJ_CTX_RANDOM         0    /* inject context: random */
-#define MCJ_CTX_PROCESS                0x1  /* inject context: process */
-#define MCJ_CTX_IRQ            0x2  /* inject context: IRQ */
-#define MCJ_NMI_BROADCAST      0x4  /* do NMI broadcasting */
-#define MCJ_EXCEPTION          0x8  /* raise as exception */
-#define MCJ_IRQ_BRAODCAST      0x10 /* do IRQ broadcasting */
-
-/* Fields are zero when not available */
-struct mce {
-       __u64 status;
-       __u64 misc;
-       __u64 addr;
-       __u64 mcgstatus;
-       __u64 ip;
-       __u64 tsc;      /* cpu time stamp counter */
-       __u64 time;     /* wall time_t when error was detected */
-       __u8  cpuvendor;        /* cpu vendor as encoded in system.h */
-       __u8  inject_flags;     /* software inject flags */
-       __u16  pad;
-       __u32 cpuid;    /* CPUID 1 EAX */
-       __u8  cs;               /* code segment */
-       __u8  bank;     /* machine check bank */
-       __u8  cpu;      /* cpu number; obsolete; use extcpu now */
-       __u8  finished;   /* entry is valid */
-       __u32 extcpu;   /* linux cpu number that detected the error */
-       __u32 socketid; /* CPU socket ID */
-       __u32 apicid;   /* CPU initial apic ID */
-       __u64 mcgcap;   /* MCGCAP MSR: machine check capabilities of CPU */
-};
-
-/*
- * This structure contains all data related to the MCE log.  Also
- * carries a signature to make it easier to find from external
- * debugging tools.  Each entry is only valid when its finished flag
- * is set.
- */
-
-#define MCE_LOG_LEN 32
-
-struct mce_log {
-       char signature[12]; /* "MACHINECHECK" */
-       unsigned len;       /* = MCE_LOG_LEN */
-       unsigned next;
-       unsigned flags;
-       unsigned recordlen;     /* length of struct mce */
-       struct mce entry[MCE_LOG_LEN];
+#include <uapi/asm/mce.h>
+
+
+struct mca_config {
+       bool dont_log_ce;
+       bool cmci_disabled;
+       bool ignore_ce;
+       bool disabled;
+       bool ser;
+       bool bios_cmci_threshold;
+       u8 banks;
+       s8 bootlog;
+       int tolerant;
+       int monarch_timeout;
+       int panic_timeout;
+       u32 rip_msr;
 };
 
-#define MCE_OVERFLOW 0         /* bit 0 in flags means overflow */
-
-#define MCE_LOG_SIGNATURE      "MACHINECHECK"
-
-#define MCE_GET_RECORD_LEN   _IOR('M', 1, int)
-#define MCE_GET_LOG_LEN      _IOR('M', 2, int)
-#define MCE_GETCLEAR_FLAGS   _IOR('M', 3, int)
-
-/* Software defined banks */
-#define MCE_EXTENDED_BANK      128
-#define MCE_THERMAL_BANK       MCE_EXTENDED_BANK + 0
-#define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)
-
-#ifdef __KERNEL__
+extern struct mca_config mca_cfg;
 extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
 
@@ -126,7 +27,6 @@ extern void mce_unregister_decode_chain(struct notifier_block *nb);
 #include <linux/init.h>
 #include <linux/atomic.h>
 
-extern int mce_disabled;
 extern int mce_p5_enabled;
 
 #ifdef CONFIG_X86_MCE
@@ -159,9 +59,6 @@ DECLARE_PER_CPU(struct device *, mce_device);
 #define MAX_NR_BANKS 32
 
 #ifdef CONFIG_X86_MCE_INTEL
-extern int mce_cmci_disabled;
-extern int mce_ignore_ce;
-extern int mce_bios_cmci_threshold;
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
 void cmci_clear(void);
 void cmci_reenable(void);
@@ -247,5 +144,4 @@ struct cper_sec_mem_err;
 extern void apei_mce_report_mem_error(int corrected,
                                      struct cper_sec_mem_err *mem_err);
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/include/asm/mman.h b/arch/x86/include/asm/mman.h
deleted file mode 100644 (file)
index 513b05f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_X86_MMAN_H
-#define _ASM_X86_MMAN_H
-
-#define MAP_32BIT      0x40            /* only give out 32bit addresses */
-
-#define MAP_HUGE_2MB    (21 << MAP_HUGE_SHIFT)
-#define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)
-
-#include <asm-generic/mman.h>
-
-#endif /* _ASM_X86_MMAN_H */
diff --git a/arch/x86/include/asm/msgbuf.h b/arch/x86/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 809134c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/msgbuf.h>
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
deleted file mode 100644 (file)
index e400cdb..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-#ifndef _ASM_X86_MSR_INDEX_H
-#define _ASM_X86_MSR_INDEX_H
-
-/* CPU model specific register (MSR) numbers */
-
-/* x86-64 specific MSRs */
-#define MSR_EFER               0xc0000080 /* extended feature register */
-#define MSR_STAR               0xc0000081 /* legacy mode SYSCALL target */
-#define MSR_LSTAR              0xc0000082 /* long mode SYSCALL target */
-#define MSR_CSTAR              0xc0000083 /* compat mode SYSCALL target */
-#define MSR_SYSCALL_MASK       0xc0000084 /* EFLAGS mask for syscall */
-#define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
-#define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
-#define MSR_KERNEL_GS_BASE     0xc0000102 /* SwapGS GS shadow */
-#define MSR_TSC_AUX            0xc0000103 /* Auxiliary TSC */
-
-/* EFER bits: */
-#define _EFER_SCE              0  /* SYSCALL/SYSRET */
-#define _EFER_LME              8  /* Long mode enable */
-#define _EFER_LMA              10 /* Long mode active (read-only) */
-#define _EFER_NX               11 /* No execute enable */
-#define _EFER_SVME             12 /* Enable virtualization */
-#define _EFER_LMSLE            13 /* Long Mode Segment Limit Enable */
-#define _EFER_FFXSR            14 /* Enable Fast FXSAVE/FXRSTOR */
-
-#define EFER_SCE               (1<<_EFER_SCE)
-#define EFER_LME               (1<<_EFER_LME)
-#define EFER_LMA               (1<<_EFER_LMA)
-#define EFER_NX                        (1<<_EFER_NX)
-#define EFER_SVME              (1<<_EFER_SVME)
-#define EFER_LMSLE             (1<<_EFER_LMSLE)
-#define EFER_FFXSR             (1<<_EFER_FFXSR)
-
-/* Intel MSRs. Some also available on other CPUs */
-#define MSR_IA32_PERFCTR0              0x000000c1
-#define MSR_IA32_PERFCTR1              0x000000c2
-#define MSR_FSB_FREQ                   0x000000cd
-
-#define MSR_NHM_SNB_PKG_CST_CFG_CTL    0x000000e2
-#define NHM_C3_AUTO_DEMOTE             (1UL << 25)
-#define NHM_C1_AUTO_DEMOTE             (1UL << 26)
-#define ATM_LNC_C6_AUTO_DEMOTE         (1UL << 25)
-
-#define MSR_MTRRcap                    0x000000fe
-#define MSR_IA32_BBL_CR_CTL            0x00000119
-#define MSR_IA32_BBL_CR_CTL3           0x0000011e
-
-#define MSR_IA32_SYSENTER_CS           0x00000174
-#define MSR_IA32_SYSENTER_ESP          0x00000175
-#define MSR_IA32_SYSENTER_EIP          0x00000176
-
-#define MSR_IA32_MCG_CAP               0x00000179
-#define MSR_IA32_MCG_STATUS            0x0000017a
-#define MSR_IA32_MCG_CTL               0x0000017b
-
-#define MSR_OFFCORE_RSP_0              0x000001a6
-#define MSR_OFFCORE_RSP_1              0x000001a7
-
-#define MSR_LBR_SELECT                 0x000001c8
-#define MSR_LBR_TOS                    0x000001c9
-#define MSR_LBR_NHM_FROM               0x00000680
-#define MSR_LBR_NHM_TO                 0x000006c0
-#define MSR_LBR_CORE_FROM              0x00000040
-#define MSR_LBR_CORE_TO                        0x00000060
-
-#define MSR_IA32_PEBS_ENABLE           0x000003f1
-#define MSR_IA32_DS_AREA               0x00000600
-#define MSR_IA32_PERF_CAPABILITIES     0x00000345
-
-#define MSR_MTRRfix64K_00000           0x00000250
-#define MSR_MTRRfix16K_80000           0x00000258
-#define MSR_MTRRfix16K_A0000           0x00000259
-#define MSR_MTRRfix4K_C0000            0x00000268
-#define MSR_MTRRfix4K_C8000            0x00000269
-#define MSR_MTRRfix4K_D0000            0x0000026a
-#define MSR_MTRRfix4K_D8000            0x0000026b
-#define MSR_MTRRfix4K_E0000            0x0000026c
-#define MSR_MTRRfix4K_E8000            0x0000026d
-#define MSR_MTRRfix4K_F0000            0x0000026e
-#define MSR_MTRRfix4K_F8000            0x0000026f
-#define MSR_MTRRdefType                        0x000002ff
-
-#define MSR_IA32_CR_PAT                        0x00000277
-
-#define MSR_IA32_DEBUGCTLMSR           0x000001d9
-#define MSR_IA32_LASTBRANCHFROMIP      0x000001db
-#define MSR_IA32_LASTBRANCHTOIP                0x000001dc
-#define MSR_IA32_LASTINTFROMIP         0x000001dd
-#define MSR_IA32_LASTINTTOIP           0x000001de
-
-/* DEBUGCTLMSR bits (others vary by model): */
-#define DEBUGCTLMSR_LBR                        (1UL <<  0) /* last branch recording */
-#define DEBUGCTLMSR_BTF                        (1UL <<  1) /* single-step on branches */
-#define DEBUGCTLMSR_TR                 (1UL <<  6)
-#define DEBUGCTLMSR_BTS                        (1UL <<  7)
-#define DEBUGCTLMSR_BTINT              (1UL <<  8)
-#define DEBUGCTLMSR_BTS_OFF_OS         (1UL <<  9)
-#define DEBUGCTLMSR_BTS_OFF_USR                (1UL << 10)
-#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
-
-#define MSR_IA32_MC0_CTL               0x00000400
-#define MSR_IA32_MC0_STATUS            0x00000401
-#define MSR_IA32_MC0_ADDR              0x00000402
-#define MSR_IA32_MC0_MISC              0x00000403
-
-#define MSR_AMD64_MC0_MASK             0xc0010044
-
-#define MSR_IA32_MCx_CTL(x)            (MSR_IA32_MC0_CTL + 4*(x))
-#define MSR_IA32_MCx_STATUS(x)         (MSR_IA32_MC0_STATUS + 4*(x))
-#define MSR_IA32_MCx_ADDR(x)           (MSR_IA32_MC0_ADDR + 4*(x))
-#define MSR_IA32_MCx_MISC(x)           (MSR_IA32_MC0_MISC + 4*(x))
-
-#define MSR_AMD64_MCx_MASK(x)          (MSR_AMD64_MC0_MASK + (x))
-
-/* These are consecutive and not in the normal 4er MCE bank block */
-#define MSR_IA32_MC0_CTL2              0x00000280
-#define MSR_IA32_MCx_CTL2(x)           (MSR_IA32_MC0_CTL2 + (x))
-
-#define MSR_P6_PERFCTR0                        0x000000c1
-#define MSR_P6_PERFCTR1                        0x000000c2
-#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. */
-
-#define MSR_AMD64_PATCH_LEVEL          0x0000008b
-#define MSR_AMD64_TSC_RATIO            0xc0000104
-#define MSR_AMD64_NB_CFG               0xc001001f
-#define MSR_AMD64_PATCH_LOADER         0xc0010020
-#define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
-#define MSR_AMD64_OSVW_STATUS          0xc0010141
-#define MSR_AMD64_DC_CFG               0xc0011022
-#define MSR_AMD64_IBSFETCHCTL          0xc0011030
-#define MSR_AMD64_IBSFETCHLINAD                0xc0011031
-#define MSR_AMD64_IBSFETCHPHYSAD       0xc0011032
-#define MSR_AMD64_IBSFETCH_REG_COUNT   3
-#define MSR_AMD64_IBSFETCH_REG_MASK    ((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
-#define MSR_AMD64_IBSOPCTL             0xc0011033
-#define MSR_AMD64_IBSOPRIP             0xc0011034
-#define MSR_AMD64_IBSOPDATA            0xc0011035
-#define MSR_AMD64_IBSOPDATA2           0xc0011036
-#define MSR_AMD64_IBSOPDATA3           0xc0011037
-#define MSR_AMD64_IBSDCLINAD           0xc0011038
-#define MSR_AMD64_IBSDCPHYSAD          0xc0011039
-#define MSR_AMD64_IBSOP_REG_COUNT      7
-#define MSR_AMD64_IBSOP_REG_MASK       ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
-#define MSR_AMD64_IBSCTL               0xc001103a
-#define MSR_AMD64_IBSBRTARGET          0xc001103b
-#define MSR_AMD64_IBS_REG_COUNT_MAX    8 /* includes MSR_AMD64_IBSBRTARGET */
-
-/* Fam 15h MSRs */
-#define MSR_F15H_PERF_CTL              0xc0010200
-#define MSR_F15H_PERF_CTR              0xc0010201
-
-/* Fam 10h MSRs */
-#define MSR_FAM10H_MMIO_CONF_BASE      0xc0010058
-#define FAM10H_MMIO_CONF_ENABLE                (1<<0)
-#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
-#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
-#define FAM10H_MMIO_CONF_BASE_MASK     0xfffffffULL
-#define FAM10H_MMIO_CONF_BASE_SHIFT    20
-#define MSR_FAM10H_NODE_ID             0xc001100c
-
-/* K8 MSRs */
-#define MSR_K8_TOP_MEM1                        0xc001001a
-#define MSR_K8_TOP_MEM2                        0xc001001d
-#define MSR_K8_SYSCFG                  0xc0010010
-#define MSR_K8_INT_PENDING_MSG         0xc0010055
-/* C1E active bits in int pending message */
-#define K8_INTP_C1E_ACTIVE_MASK                0x18000000
-#define MSR_K8_TSEG_ADDR               0xc0010112
-#define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
-#define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
-#define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
-
-/* K7 MSRs */
-#define MSR_K7_EVNTSEL0                        0xc0010000
-#define MSR_K7_PERFCTR0                        0xc0010004
-#define MSR_K7_EVNTSEL1                        0xc0010001
-#define MSR_K7_PERFCTR1                        0xc0010005
-#define MSR_K7_EVNTSEL2                        0xc0010002
-#define MSR_K7_PERFCTR2                        0xc0010006
-#define MSR_K7_EVNTSEL3                        0xc0010003
-#define MSR_K7_PERFCTR3                        0xc0010007
-#define MSR_K7_CLK_CTL                 0xc001001b
-#define MSR_K7_HWCR                    0xc0010015
-#define MSR_K7_FID_VID_CTL             0xc0010041
-#define MSR_K7_FID_VID_STATUS          0xc0010042
-
-/* K6 MSRs */
-#define MSR_K6_WHCR                    0xc0000082
-#define MSR_K6_UWCCR                   0xc0000085
-#define MSR_K6_EPMR                    0xc0000086
-#define MSR_K6_PSOR                    0xc0000087
-#define MSR_K6_PFIR                    0xc0000088
-
-/* Centaur-Hauls/IDT defined MSRs. */
-#define MSR_IDT_FCR1                   0x00000107
-#define MSR_IDT_FCR2                   0x00000108
-#define MSR_IDT_FCR3                   0x00000109
-#define MSR_IDT_FCR4                   0x0000010a
-
-#define MSR_IDT_MCR0                   0x00000110
-#define MSR_IDT_MCR1                   0x00000111
-#define MSR_IDT_MCR2                   0x00000112
-#define MSR_IDT_MCR3                   0x00000113
-#define MSR_IDT_MCR4                   0x00000114
-#define MSR_IDT_MCR5                   0x00000115
-#define MSR_IDT_MCR6                   0x00000116
-#define MSR_IDT_MCR7                   0x00000117
-#define MSR_IDT_MCR_CTRL               0x00000120
-
-/* VIA Cyrix defined MSRs*/
-#define MSR_VIA_FCR                    0x00001107
-#define MSR_VIA_LONGHAUL               0x0000110a
-#define MSR_VIA_RNG                    0x0000110b
-#define MSR_VIA_BCR2                   0x00001147
-
-/* Transmeta defined MSRs */
-#define MSR_TMTA_LONGRUN_CTRL          0x80868010
-#define MSR_TMTA_LONGRUN_FLAGS         0x80868011
-#define MSR_TMTA_LRTI_READOUT          0x80868018
-#define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
-
-/* Intel defined MSRs. */
-#define MSR_IA32_P5_MC_ADDR            0x00000000
-#define MSR_IA32_P5_MC_TYPE            0x00000001
-#define MSR_IA32_TSC                   0x00000010
-#define MSR_IA32_PLATFORM_ID           0x00000017
-#define MSR_IA32_EBL_CR_POWERON                0x0000002a
-#define MSR_EBC_FREQUENCY_ID           0x0000002c
-#define MSR_IA32_FEATURE_CONTROL        0x0000003a
-
-#define FEATURE_CONTROL_LOCKED                         (1<<0)
-#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX       (1<<1)
-#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX      (1<<2)
-
-#define MSR_IA32_APICBASE              0x0000001b
-#define MSR_IA32_APICBASE_BSP          (1<<8)
-#define MSR_IA32_APICBASE_ENABLE       (1<<11)
-#define MSR_IA32_APICBASE_BASE         (0xfffff<<12)
-
-#define MSR_IA32_TSCDEADLINE           0x000006e0
-
-#define MSR_IA32_UCODE_WRITE           0x00000079
-#define MSR_IA32_UCODE_REV             0x0000008b
-
-#define MSR_IA32_PERF_STATUS           0x00000198
-#define MSR_IA32_PERF_CTL              0x00000199
-#define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
-#define MSR_AMD_PERF_STATUS            0xc0010063
-#define MSR_AMD_PERF_CTL               0xc0010062
-
-#define MSR_IA32_MPERF                 0x000000e7
-#define MSR_IA32_APERF                 0x000000e8
-
-#define MSR_IA32_THERM_CONTROL         0x0000019a
-#define MSR_IA32_THERM_INTERRUPT       0x0000019b
-
-#define THERM_INT_HIGH_ENABLE          (1 << 0)
-#define THERM_INT_LOW_ENABLE           (1 << 1)
-#define THERM_INT_PLN_ENABLE           (1 << 24)
-
-#define MSR_IA32_THERM_STATUS          0x0000019c
-
-#define THERM_STATUS_PROCHOT           (1 << 0)
-#define THERM_STATUS_POWER_LIMIT       (1 << 10)
-
-#define MSR_THERM2_CTL                 0x0000019d
-
-#define MSR_THERM2_CTL_TM_SELECT       (1ULL << 16)
-
-#define MSR_IA32_MISC_ENABLE           0x000001a0
-
-#define MSR_IA32_TEMPERATURE_TARGET    0x000001a2
-
-#define MSR_IA32_ENERGY_PERF_BIAS      0x000001b0
-#define ENERGY_PERF_BIAS_PERFORMANCE   0
-#define ENERGY_PERF_BIAS_NORMAL                6
-#define ENERGY_PERF_BIAS_POWERSAVE     15
-
-#define MSR_IA32_PACKAGE_THERM_STATUS          0x000001b1
-
-#define PACKAGE_THERM_STATUS_PROCHOT           (1 << 0)
-#define PACKAGE_THERM_STATUS_POWER_LIMIT       (1 << 10)
-
-#define MSR_IA32_PACKAGE_THERM_INTERRUPT       0x000001b2
-
-#define PACKAGE_THERM_INT_HIGH_ENABLE          (1 << 0)
-#define PACKAGE_THERM_INT_LOW_ENABLE           (1 << 1)
-#define PACKAGE_THERM_INT_PLN_ENABLE           (1 << 24)
-
-/* Thermal Thresholds Support */
-#define THERM_INT_THRESHOLD0_ENABLE    (1 << 15)
-#define THERM_SHIFT_THRESHOLD0        8
-#define THERM_MASK_THRESHOLD0          (0x7f << THERM_SHIFT_THRESHOLD0)
-#define THERM_INT_THRESHOLD1_ENABLE    (1 << 23)
-#define THERM_SHIFT_THRESHOLD1        16
-#define THERM_MASK_THRESHOLD1          (0x7f << THERM_SHIFT_THRESHOLD1)
-#define THERM_STATUS_THRESHOLD0        (1 << 6)
-#define THERM_LOG_THRESHOLD0           (1 << 7)
-#define THERM_STATUS_THRESHOLD1        (1 << 8)
-#define THERM_LOG_THRESHOLD1           (1 << 9)
-
-/* MISC_ENABLE bits: architectural */
-#define MSR_IA32_MISC_ENABLE_FAST_STRING       (1ULL << 0)
-#define MSR_IA32_MISC_ENABLE_TCC               (1ULL << 1)
-#define MSR_IA32_MISC_ENABLE_EMON              (1ULL << 7)
-#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       (1ULL << 11)
-#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      (1ULL << 12)
-#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP        (1ULL << 16)
-#define MSR_IA32_MISC_ENABLE_MWAIT             (1ULL << 18)
-#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       (1ULL << 22)
-#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE      (1ULL << 23)
-#define MSR_IA32_MISC_ENABLE_XD_DISABLE                (1ULL << 34)
-
-/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
-#define MSR_IA32_MISC_ENABLE_X87_COMPAT                (1ULL << 2)
-#define MSR_IA32_MISC_ENABLE_TM1               (1ULL << 3)
-#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE        (1ULL << 4)
-#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE   (1ULL << 6)
-#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK     (1ULL << 8)
-#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE  (1ULL << 9)
-#define MSR_IA32_MISC_ENABLE_FERR              (1ULL << 10)
-#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX    (1ULL << 10)
-#define MSR_IA32_MISC_ENABLE_TM2               (1ULL << 13)
-#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE  (1ULL << 19)
-#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK    (1ULL << 20)
-#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT       (1ULL << 24)
-#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE  (1ULL << 37)
-#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE     (1ULL << 38)
-#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE   (1ULL << 39)
-
-#define MSR_IA32_TSC_DEADLINE          0x000006E0
-
-/* P4/Xeon+ specific */
-#define MSR_IA32_MCG_EAX               0x00000180
-#define MSR_IA32_MCG_EBX               0x00000181
-#define MSR_IA32_MCG_ECX               0x00000182
-#define MSR_IA32_MCG_EDX               0x00000183
-#define MSR_IA32_MCG_ESI               0x00000184
-#define MSR_IA32_MCG_EDI               0x00000185
-#define MSR_IA32_MCG_EBP               0x00000186
-#define MSR_IA32_MCG_ESP               0x00000187
-#define MSR_IA32_MCG_EFLAGS            0x00000188
-#define MSR_IA32_MCG_EIP               0x00000189
-#define MSR_IA32_MCG_RESERVED          0x0000018a
-
-/* Pentium IV performance counter MSRs */
-#define MSR_P4_BPU_PERFCTR0            0x00000300
-#define MSR_P4_BPU_PERFCTR1            0x00000301
-#define MSR_P4_BPU_PERFCTR2            0x00000302
-#define MSR_P4_BPU_PERFCTR3            0x00000303
-#define MSR_P4_MS_PERFCTR0             0x00000304
-#define MSR_P4_MS_PERFCTR1             0x00000305
-#define MSR_P4_MS_PERFCTR2             0x00000306
-#define MSR_P4_MS_PERFCTR3             0x00000307
-#define MSR_P4_FLAME_PERFCTR0          0x00000308
-#define MSR_P4_FLAME_PERFCTR1          0x00000309
-#define MSR_P4_FLAME_PERFCTR2          0x0000030a
-#define MSR_P4_FLAME_PERFCTR3          0x0000030b
-#define MSR_P4_IQ_PERFCTR0             0x0000030c
-#define MSR_P4_IQ_PERFCTR1             0x0000030d
-#define MSR_P4_IQ_PERFCTR2             0x0000030e
-#define MSR_P4_IQ_PERFCTR3             0x0000030f
-#define MSR_P4_IQ_PERFCTR4             0x00000310
-#define MSR_P4_IQ_PERFCTR5             0x00000311
-#define MSR_P4_BPU_CCCR0               0x00000360
-#define MSR_P4_BPU_CCCR1               0x00000361
-#define MSR_P4_BPU_CCCR2               0x00000362
-#define MSR_P4_BPU_CCCR3               0x00000363
-#define MSR_P4_MS_CCCR0                        0x00000364
-#define MSR_P4_MS_CCCR1                        0x00000365
-#define MSR_P4_MS_CCCR2                        0x00000366
-#define MSR_P4_MS_CCCR3                        0x00000367
-#define MSR_P4_FLAME_CCCR0             0x00000368
-#define MSR_P4_FLAME_CCCR1             0x00000369
-#define MSR_P4_FLAME_CCCR2             0x0000036a
-#define MSR_P4_FLAME_CCCR3             0x0000036b
-#define MSR_P4_IQ_CCCR0                        0x0000036c
-#define MSR_P4_IQ_CCCR1                        0x0000036d
-#define MSR_P4_IQ_CCCR2                        0x0000036e
-#define MSR_P4_IQ_CCCR3                        0x0000036f
-#define MSR_P4_IQ_CCCR4                        0x00000370
-#define MSR_P4_IQ_CCCR5                        0x00000371
-#define MSR_P4_ALF_ESCR0               0x000003ca
-#define MSR_P4_ALF_ESCR1               0x000003cb
-#define MSR_P4_BPU_ESCR0               0x000003b2
-#define MSR_P4_BPU_ESCR1               0x000003b3
-#define MSR_P4_BSU_ESCR0               0x000003a0
-#define MSR_P4_BSU_ESCR1               0x000003a1
-#define MSR_P4_CRU_ESCR0               0x000003b8
-#define MSR_P4_CRU_ESCR1               0x000003b9
-#define MSR_P4_CRU_ESCR2               0x000003cc
-#define MSR_P4_CRU_ESCR3               0x000003cd
-#define MSR_P4_CRU_ESCR4               0x000003e0
-#define MSR_P4_CRU_ESCR5               0x000003e1
-#define MSR_P4_DAC_ESCR0               0x000003a8
-#define MSR_P4_DAC_ESCR1               0x000003a9
-#define MSR_P4_FIRM_ESCR0              0x000003a4
-#define MSR_P4_FIRM_ESCR1              0x000003a5
-#define MSR_P4_FLAME_ESCR0             0x000003a6
-#define MSR_P4_FLAME_ESCR1             0x000003a7
-#define MSR_P4_FSB_ESCR0               0x000003a2
-#define MSR_P4_FSB_ESCR1               0x000003a3
-#define MSR_P4_IQ_ESCR0                        0x000003ba
-#define MSR_P4_IQ_ESCR1                        0x000003bb
-#define MSR_P4_IS_ESCR0                        0x000003b4
-#define MSR_P4_IS_ESCR1                        0x000003b5
-#define MSR_P4_ITLB_ESCR0              0x000003b6
-#define MSR_P4_ITLB_ESCR1              0x000003b7
-#define MSR_P4_IX_ESCR0                        0x000003c8
-#define MSR_P4_IX_ESCR1                        0x000003c9
-#define MSR_P4_MOB_ESCR0               0x000003aa
-#define MSR_P4_MOB_ESCR1               0x000003ab
-#define MSR_P4_MS_ESCR0                        0x000003c0
-#define MSR_P4_MS_ESCR1                        0x000003c1
-#define MSR_P4_PMH_ESCR0               0x000003ac
-#define MSR_P4_PMH_ESCR1               0x000003ad
-#define MSR_P4_RAT_ESCR0               0x000003bc
-#define MSR_P4_RAT_ESCR1               0x000003bd
-#define MSR_P4_SAAT_ESCR0              0x000003ae
-#define MSR_P4_SAAT_ESCR1              0x000003af
-#define MSR_P4_SSU_ESCR0               0x000003be
-#define MSR_P4_SSU_ESCR1               0x000003bf /* guess: not in manual */
-
-#define MSR_P4_TBPU_ESCR0              0x000003c2
-#define MSR_P4_TBPU_ESCR1              0x000003c3
-#define MSR_P4_TC_ESCR0                        0x000003c4
-#define MSR_P4_TC_ESCR1                        0x000003c5
-#define MSR_P4_U2L_ESCR0               0x000003b0
-#define MSR_P4_U2L_ESCR1               0x000003b1
-
-#define MSR_P4_PEBS_MATRIX_VERT                0x000003f2
-
-/* Intel Core-based CPU performance counters */
-#define MSR_CORE_PERF_FIXED_CTR0       0x00000309
-#define MSR_CORE_PERF_FIXED_CTR1       0x0000030a
-#define MSR_CORE_PERF_FIXED_CTR2       0x0000030b
-#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x0000038d
-#define MSR_CORE_PERF_GLOBAL_STATUS    0x0000038e
-#define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
-#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
-
-/* Geode defined MSRs */
-#define MSR_GEODE_BUSCONT_CONF0                0x00001900
-
-/* Intel VT MSRs */
-#define MSR_IA32_VMX_BASIC              0x00000480
-#define MSR_IA32_VMX_PINBASED_CTLS      0x00000481
-#define MSR_IA32_VMX_PROCBASED_CTLS     0x00000482
-#define MSR_IA32_VMX_EXIT_CTLS          0x00000483
-#define MSR_IA32_VMX_ENTRY_CTLS         0x00000484
-#define MSR_IA32_VMX_MISC               0x00000485
-#define MSR_IA32_VMX_CR0_FIXED0         0x00000486
-#define MSR_IA32_VMX_CR0_FIXED1         0x00000487
-#define MSR_IA32_VMX_CR4_FIXED0         0x00000488
-#define MSR_IA32_VMX_CR4_FIXED1         0x00000489
-#define MSR_IA32_VMX_VMCS_ENUM          0x0000048a
-#define MSR_IA32_VMX_PROCBASED_CTLS2    0x0000048b
-#define MSR_IA32_VMX_EPT_VPID_CAP       0x0000048c
-#define MSR_IA32_VMX_TRUE_PINBASED_CTLS  0x0000048d
-#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
-#define MSR_IA32_VMX_TRUE_EXIT_CTLS      0x0000048f
-#define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
-
-/* VMX_BASIC bits and bitmasks */
-#define VMX_BASIC_VMCS_SIZE_SHIFT      32
-#define VMX_BASIC_64           0x0001000000000000LLU
-#define VMX_BASIC_MEM_TYPE_SHIFT       50
-#define VMX_BASIC_MEM_TYPE_MASK        0x003c000000000000LLU
-#define VMX_BASIC_MEM_TYPE_WB  6LLU
-#define VMX_BASIC_INOUT                0x0040000000000000LLU
-
-/* AMD-V MSRs */
-
-#define MSR_VM_CR                       0xc0010114
-#define MSR_VM_IGNNE                    0xc0010115
-#define MSR_VM_HSAVE_PA                 0xc0010117
-
-#endif /* _ASM_X86_MSR_INDEX_H */
index 813ed103f45edc0ac13042e8c18a922b909a8710..9264802e28245fa89fe3a0416d7c99d5326d704b 100644 (file)
@@ -1,18 +1,10 @@
 #ifndef _ASM_X86_MSR_H
 #define _ASM_X86_MSR_H
 
-#include <asm/msr-index.h>
+#include <uapi/asm/msr.h>
 
 #ifndef __ASSEMBLY__
 
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define X86_IOC_RDMSR_REGS     _IOWR('c', 0xA0, __u32[8])
-#define X86_IOC_WRMSR_REGS     _IOWR('c', 0xA1, __u32[8])
-
-#ifdef __KERNEL__
-
 #include <asm/asm.h>
 #include <asm/errno.h>
 #include <asm/cpumask.h>
@@ -271,6 +263,5 @@ static inline int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
        return wrmsr_safe_regs(regs);
 }
 #endif  /* CONFIG_SMP */
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_X86_MSR_H */
index 7e3f17f92c665ec79850eefa328567e06c50134c..e235582f99308123aec462fe90fba8684730f6f9 100644 (file)
 #ifndef _ASM_X86_MTRR_H
 #define _ASM_X86_MTRR_H
 
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <linux/errno.h>
+#include <uapi/asm/mtrr.h>
 
-#define        MTRR_IOCTL_BASE 'M'
-
-/* Warning: this structure has a different order from i386
-   on x86-64. The 32bit emulation code takes care of that.
-   But you need to use this for 64bit, otherwise your X server
-   will break. */
-
-#ifdef __i386__
-struct mtrr_sentry {
-    unsigned long base;    /*  Base address     */
-    unsigned int size;    /*  Size of region   */
-    unsigned int type;     /*  Type of region   */
-};
-
-struct mtrr_gentry {
-    unsigned int regnum;   /*  Register number  */
-    unsigned long base;    /*  Base address     */
-    unsigned int size;    /*  Size of region   */
-    unsigned int type;     /*  Type of region   */
-};
-
-#else /* __i386__ */
-
-struct mtrr_sentry {
-       __u64 base;             /*  Base address     */
-       __u32 size;             /*  Size of region   */
-       __u32 type;             /*  Type of region   */
-};
-
-struct mtrr_gentry {
-       __u64 base;             /*  Base address     */
-       __u32 size;             /*  Size of region   */
-       __u32 regnum;           /*  Register number  */
-       __u32 type;             /*  Type of region   */
-       __u32 _pad;             /*  Unused           */
-};
-
-#endif /* !__i386__ */
-
-struct mtrr_var_range {
-       __u32 base_lo;
-       __u32 base_hi;
-       __u32 mask_lo;
-       __u32 mask_hi;
-};
-
-/* In the Intel processor's MTRR interface, the MTRR type is always held in
-   an 8 bit field: */
-typedef __u8 mtrr_type;
-
-#define MTRR_NUM_FIXED_RANGES 88
-#define MTRR_MAX_VAR_RANGES 256
-
-struct mtrr_state_type {
-       struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES];
-       mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES];
-       unsigned char enabled;
-       unsigned char have_fixed;
-       mtrr_type def_type;
-};
-
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-/*  These are the various ioctls  */
-#define MTRRIOC_ADD_ENTRY        _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry)
-#define MTRRIOC_SET_ENTRY        _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry)
-#define MTRRIOC_DEL_ENTRY        _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry)
-#define MTRRIOC_GET_ENTRY        _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
-#define MTRRIOC_KILL_ENTRY       _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry)
-#define MTRRIOC_ADD_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry)
-#define MTRRIOC_SET_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry)
-#define MTRRIOC_DEL_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry)
-#define MTRRIOC_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
-#define MTRRIOC_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry)
-
-/*  These are the region types  */
-#define MTRR_TYPE_UNCACHABLE 0
-#define MTRR_TYPE_WRCOMB     1
-/*#define MTRR_TYPE_         2*/
-/*#define MTRR_TYPE_         3*/
-#define MTRR_TYPE_WRTHROUGH  4
-#define MTRR_TYPE_WRPROT     5
-#define MTRR_TYPE_WRBACK     6
-#define MTRR_NUM_TYPES       7
-
-#ifdef __KERNEL__
 
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
@@ -208,6 +119,4 @@ struct mtrr_gentry32 {
                                 _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
 #endif /* CONFIG_COMPAT */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_MTRR_H */
diff --git a/arch/x86/include/asm/numachip/numachip.h b/arch/x86/include/asm/numachip/numachip.h
new file mode 100644 (file)
index 0000000..1c6f7f6
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ *
+ * Numascale NumaConnect-specific header file
+ *
+ * Copyright (C) 2012 Numascale AS. All rights reserved.
+ *
+ * Send feedback to <support@numascale.com>
+ *
+ */
+
+#ifndef _ASM_X86_NUMACHIP_NUMACHIP_H
+#define _ASM_X86_NUMACHIP_NUMACHIP_H
+
+extern int __init pci_numachip_init(void);
+
+#endif /* _ASM_X86_NUMACHIP_NUMACHIP_H */
diff --git a/arch/x86/include/asm/param.h b/arch/x86/include/asm/param.h
deleted file mode 100644 (file)
index 965d454..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
index 6e41b9343928941a82533d4fb299c8b70aaf9add..dba7805176bf3cf705b5308d6c7d13b5142f9a61 100644 (file)
@@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
 }
 #endif
 
+struct pci_setup_rom {
+       struct setup_data data;
+       uint16_t vendor;
+       uint16_t devid;
+       uint64_t pcilen;
+       unsigned long segment;
+       unsigned long bus;
+       unsigned long device;
+       unsigned long function;
+       uint8_t romdata[0];
+};
+
 #endif /* _ASM_X86_PCI_H */
diff --git a/arch/x86/include/asm/perf_regs.h b/arch/x86/include/asm/perf_regs.h
deleted file mode 100644 (file)
index 3f2207b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _ASM_X86_PERF_REGS_H
-#define _ASM_X86_PERF_REGS_H
-
-enum perf_event_x86_regs {
-       PERF_REG_X86_AX,
-       PERF_REG_X86_BX,
-       PERF_REG_X86_CX,
-       PERF_REG_X86_DX,
-       PERF_REG_X86_SI,
-       PERF_REG_X86_DI,
-       PERF_REG_X86_BP,
-       PERF_REG_X86_SP,
-       PERF_REG_X86_IP,
-       PERF_REG_X86_FLAGS,
-       PERF_REG_X86_CS,
-       PERF_REG_X86_SS,
-       PERF_REG_X86_DS,
-       PERF_REG_X86_ES,
-       PERF_REG_X86_FS,
-       PERF_REG_X86_GS,
-       PERF_REG_X86_R8,
-       PERF_REG_X86_R9,
-       PERF_REG_X86_R10,
-       PERF_REG_X86_R11,
-       PERF_REG_X86_R12,
-       PERF_REG_X86_R13,
-       PERF_REG_X86_R14,
-       PERF_REG_X86_R15,
-
-       PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
-       PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
-};
-#endif /* _ASM_X86_PERF_REGS_H */
diff --git a/arch/x86/include/asm/poll.h b/arch/x86/include/asm/poll.h
deleted file mode 100644 (file)
index c98509d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
index bad3665c25fc3278f2cb00396e0b6d4147d77f85..f565f6dd59d4ed7ea8771d0dc6196ca28eff91c5 100644 (file)
@@ -1,15 +1,5 @@
-#ifdef __KERNEL__
 # ifdef CONFIG_X86_32
 #  include <asm/posix_types_32.h>
 # else
 #  include <asm/posix_types_64.h>
 # endif
-#else
-# ifdef __i386__
-#  include <asm/posix_types_32.h>
-# elif defined(__ILP32__)
-#  include <asm/posix_types_x32.h>
-# else
-#  include <asm/posix_types_64.h>
-# endif
-#endif
diff --git a/arch/x86/include/asm/posix_types_32.h b/arch/x86/include/asm/posix_types_32.h
deleted file mode 100644 (file)
index 8e52505..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _ASM_X86_POSIX_TYPES_32_H
-#define _ASM_X86_POSIX_TYPES_32_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-#define __kernel_uid_t __kernel_uid_t
-
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* _ASM_X86_POSIX_TYPES_32_H */
diff --git a/arch/x86/include/asm/posix_types_64.h b/arch/x86/include/asm/posix_types_64.h
deleted file mode 100644 (file)
index cba0c1e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_X86_POSIX_TYPES_64_H
-#define _ASM_X86_POSIX_TYPES_64_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-
-typedef unsigned long  __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* _ASM_X86_POSIX_TYPES_64_H */
diff --git a/arch/x86/include/asm/posix_types_x32.h b/arch/x86/include/asm/posix_types_x32.h
deleted file mode 100644 (file)
index 85f9bda..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_X86_POSIX_TYPES_X32_H
-#define _ASM_X86_POSIX_TYPES_X32_H
-
-/*
- * This file is only used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- *
- * These types should generally match the ones used by the 64-bit kernel,
- *
- */
-
-typedef long long __kernel_long_t;
-typedef unsigned long long __kernel_ulong_t;
-#define __kernel_long_t __kernel_long_t
-
-#include <asm/posix_types_64.h>
-
-#endif /* _ASM_X86_POSIX_TYPES_X32_H */
diff --git a/arch/x86/include/asm/prctl.h b/arch/x86/include/asm/prctl.h
deleted file mode 100644 (file)
index 3ac5032..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_X86_PRCTL_H
-#define _ASM_X86_PRCTL_H
-
-#define ARCH_SET_GS 0x1001
-#define ARCH_SET_FS 0x1002
-#define ARCH_GET_FS 0x1003
-#define ARCH_GET_GS 0x1004
-
-#endif /* _ASM_X86_PRCTL_H */
index 680cf09ed1004e1076bbad951e546bdd5e3be48f..39fb618e2211012ee190696488b707e0cfa2cab7 100644 (file)
 #ifndef _ASM_X86_PROCESSOR_FLAGS_H
 #define _ASM_X86_PROCESSOR_FLAGS_H
-/* Various flags defined: can be included from assembler. */
 
-/*
- * EFLAGS bits
- */
-#define X86_EFLAGS_CF  0x00000001 /* Carry Flag */
-#define X86_EFLAGS_BIT1        0x00000002 /* Bit 1 - always on */
-#define X86_EFLAGS_PF  0x00000004 /* Parity Flag */
-#define X86_EFLAGS_AF  0x00000010 /* Auxiliary carry Flag */
-#define X86_EFLAGS_ZF  0x00000040 /* Zero Flag */
-#define X86_EFLAGS_SF  0x00000080 /* Sign Flag */
-#define X86_EFLAGS_TF  0x00000100 /* Trap Flag */
-#define X86_EFLAGS_IF  0x00000200 /* Interrupt Flag */
-#define X86_EFLAGS_DF  0x00000400 /* Direction Flag */
-#define X86_EFLAGS_OF  0x00000800 /* Overflow Flag */
-#define X86_EFLAGS_IOPL        0x00003000 /* IOPL mask */
-#define X86_EFLAGS_NT  0x00004000 /* Nested Task */
-#define X86_EFLAGS_RF  0x00010000 /* Resume Flag */
-#define X86_EFLAGS_VM  0x00020000 /* Virtual Mode */
-#define X86_EFLAGS_AC  0x00040000 /* Alignment Check */
-#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
-#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
-#define X86_EFLAGS_ID  0x00200000 /* CPUID detection flag */
+#include <uapi/asm/processor-flags.h>
 
-/*
- * Basic CPU control in CR0
- */
-#define X86_CR0_PE     0x00000001 /* Protection Enable */
-#define X86_CR0_MP     0x00000002 /* Monitor Coprocessor */
-#define X86_CR0_EM     0x00000004 /* Emulation */
-#define X86_CR0_TS     0x00000008 /* Task Switched */
-#define X86_CR0_ET     0x00000010 /* Extension Type */
-#define X86_CR0_NE     0x00000020 /* Numeric Error */
-#define X86_CR0_WP     0x00010000 /* Write Protect */
-#define X86_CR0_AM     0x00040000 /* Alignment Mask */
-#define X86_CR0_NW     0x20000000 /* Not Write-through */
-#define X86_CR0_CD     0x40000000 /* Cache Disable */
-#define X86_CR0_PG     0x80000000 /* Paging */
-
-/*
- * Paging options in CR3
- */
-#define X86_CR3_PWT    0x00000008 /* Page Write Through */
-#define X86_CR3_PCD    0x00000010 /* Page Cache Disable */
-#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */
-
-/*
- * Intel CPU features in CR4
- */
-#define X86_CR4_VME    0x00000001 /* enable vm86 extensions */
-#define X86_CR4_PVI    0x00000002 /* virtual interrupts flag enable */
-#define X86_CR4_TSD    0x00000004 /* disable time stamp at ipl 3 */
-#define X86_CR4_DE     0x00000008 /* enable debugging extensions */
-#define X86_CR4_PSE    0x00000010 /* enable page size extensions */
-#define X86_CR4_PAE    0x00000020 /* enable physical address extensions */
-#define X86_CR4_MCE    0x00000040 /* Machine check enable */
-#define X86_CR4_PGE    0x00000080 /* enable global pages */
-#define X86_CR4_PCE    0x00000100 /* enable performance counters at ipl 3 */
-#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
-#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
-#define X86_CR4_VMXE   0x00002000 /* enable VMX virtualization */
-#define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
-#define X86_CR4_PCIDE  0x00020000 /* enable PCID support */
-#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
-#define X86_CR4_SMEP   0x00100000 /* enable SMEP support */
-#define X86_CR4_SMAP   0x00200000 /* enable SMAP support */
-
-/*
- * x86-64 Task Priority Register, CR8
- */
-#define X86_CR8_TPR    0x0000000F /* task priority register */
-
-/*
- * AMD and Transmeta use MSRs for configuration; see <asm/msr-index.h>
- */
-
-/*
- *      NSC/Cyrix CPU configuration register indexes
- */
-#define CX86_PCR0      0x20
-#define CX86_GCR       0xb8
-#define CX86_CCR0      0xc0
-#define CX86_CCR1      0xc1
-#define CX86_CCR2      0xc2
-#define CX86_CCR3      0xc3
-#define CX86_CCR4      0xe8
-#define CX86_CCR5      0xe9
-#define CX86_CCR6      0xea
-#define CX86_CCR7      0xeb
-#define CX86_PCR1      0xf0
-#define CX86_DIR0      0xfe
-#define CX86_DIR1      0xff
-#define CX86_ARR_BASE  0xc4
-#define CX86_RCR_BASE  0xdc
-
-#ifdef __KERNEL__
 #ifdef CONFIG_VM86
 #define X86_VM_MASK    X86_EFLAGS_VM
 #else
 #define X86_VM_MASK    0 /* No VM86 support */
 #endif
-#endif
-
 #endif /* _ASM_X86_PROCESSOR_FLAGS_H */
diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h
deleted file mode 100644 (file)
index 7b0a55a..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef _ASM_X86_PTRACE_ABI_H
-#define _ASM_X86_PTRACE_ABI_H
-
-#ifdef __i386__
-
-#define EBX 0
-#define ECX 1
-#define EDX 2
-#define ESI 3
-#define EDI 4
-#define EBP 5
-#define EAX 6
-#define DS 7
-#define ES 8
-#define FS 9
-#define GS 10
-#define ORIG_EAX 11
-#define EIP 12
-#define CS  13
-#define EFL 14
-#define UESP 15
-#define SS   16
-#define FRAME_SIZE 17
-
-#else /* __i386__ */
-
-#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS)
-#define R15 0
-#define R14 8
-#define R13 16
-#define R12 24
-#define RBP 32
-#define RBX 40
-/* arguments: interrupts/non tracing syscalls only save up to here*/
-#define R11 48
-#define R10 56
-#define R9 64
-#define R8 72
-#define RAX 80
-#define RCX 88
-#define RDX 96
-#define RSI 104
-#define RDI 112
-#define ORIG_RAX 120       /* = ERROR */
-/* end of arguments */
-/* cpu exception frame or undefined in case of fast syscall. */
-#define RIP 128
-#define CS 136
-#define EFLAGS 144
-#define RSP 152
-#define SS 160
-#define ARGOFFSET R11
-#endif /* __ASSEMBLY__ */
-
-/* top of stack page */
-#define FRAME_SIZE 168
-
-#endif /* !__i386__ */
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-#define PTRACE_GETFPXREGS         18
-#define PTRACE_SETFPXREGS         19
-
-#define PTRACE_OLDSETOPTIONS      21
-
-/* only useful for access 32bit programs / kernels */
-#define PTRACE_GET_THREAD_AREA    25
-#define PTRACE_SET_THREAD_AREA    26
-
-#ifdef __x86_64__
-# define PTRACE_ARCH_PRCTL       30
-#endif
-
-#define PTRACE_SYSEMU            31
-#define PTRACE_SYSEMU_SINGLESTEP  32
-
-#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
-
-#ifndef __ASSEMBLY__
-#include <linux/types.h>
-#endif
-
-#endif /* _ASM_X86_PTRACE_ABI_H */
index 54d80fddb7398495cf5723398d4b45ce49ac7719..03ca442d8f0d6af3ec3ab0ee73413eff3d392423 100644 (file)
@@ -1,44 +1,12 @@
 #ifndef _ASM_X86_PTRACE_H
 #define _ASM_X86_PTRACE_H
 
-#include <linux/compiler.h>    /* For __user */
-#include <asm/ptrace-abi.h>
-#include <asm/processor-flags.h>
-
-#ifdef __KERNEL__
 #include <asm/segment.h>
 #include <asm/page_types.h>
-#endif
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
-
 #ifdef __i386__
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-#ifndef __KERNEL__
-
-struct pt_regs {
-       long ebx;
-       long ecx;
-       long edx;
-       long esi;
-       long edi;
-       long ebp;
-       long eax;
-       int  xds;
-       int  xes;
-       int  xfs;
-       int  xgs;
-       long orig_eax;
-       long eip;
-       int  xcs;
-       long eflags;
-       long esp;
-       int  xss;
-};
-
-#else /* __KERNEL__ */
 
 struct pt_regs {
        unsigned long bx;
@@ -60,42 +28,8 @@ struct pt_regs {
        unsigned long ss;
 };
 
-#endif /* __KERNEL__ */
-
 #else /* __i386__ */
 
-#ifndef __KERNEL__
-
-struct pt_regs {
-       unsigned long r15;
-       unsigned long r14;
-       unsigned long r13;
-       unsigned long r12;
-       unsigned long rbp;
-       unsigned long rbx;
-/* arguments: non interrupts/non tracing syscalls only save up to here*/
-       unsigned long r11;
-       unsigned long r10;
-       unsigned long r9;
-       unsigned long r8;
-       unsigned long rax;
-       unsigned long rcx;
-       unsigned long rdx;
-       unsigned long rsi;
-       unsigned long rdi;
-       unsigned long orig_rax;
-/* end of arguments */
-/* cpu exception frame or undefined */
-       unsigned long rip;
-       unsigned long cs;
-       unsigned long eflags;
-       unsigned long rsp;
-       unsigned long ss;
-/* top of stack page */
-};
-
-#else /* __KERNEL__ */
-
 struct pt_regs {
        unsigned long r15;
        unsigned long r14;
@@ -124,12 +58,8 @@ struct pt_regs {
 /* top of stack page */
 };
 
-#endif /* __KERNEL__ */
 #endif /* !__i386__ */
 
-
-#ifdef __KERNEL__
-
 #include <linux/init.h>
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt_types.h>
@@ -301,8 +231,5 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
 extern int do_set_thread_area(struct task_struct *p, int idx,
                              struct user_desc __user *info, int can_allocate);
 
-#endif /* __KERNEL__ */
-
 #endif /* !__ASSEMBLY__ */
-
 #endif /* _ASM_X86_PTRACE_H */
index c59cc97fe6c1478225863d0d814bece995652f5a..109a9dd5d454f197414e2449617cf9cb73ab1220 100644 (file)
@@ -6,6 +6,7 @@
 
 /* some helper functions for xen and kvm pv clock sources */
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
+u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
 void pvclock_set_flags(u8 flags);
 unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
 void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
@@ -56,4 +57,50 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
        return product;
 }
 
+static __always_inline
+u64 pvclock_get_nsec_offset(const struct pvclock_vcpu_time_info *src)
+{
+       u64 delta = __native_read_tsc() - src->tsc_timestamp;
+       return pvclock_scale_delta(delta, src->tsc_to_system_mul,
+                                  src->tsc_shift);
+}
+
+static __always_inline
+unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
+                              cycle_t *cycles, u8 *flags)
+{
+       unsigned version;
+       cycle_t ret, offset;
+       u8 ret_flags;
+
+       version = src->version;
+       /* Note: emulated platforms which do not advertise SSE2 support
+        * result in kvmclock not using the necessary RDTSC barriers.
+        * Without barriers, it is possible that RDTSC instruction reads from
+        * the time stamp counter outside rdtsc_barrier protected section
+        * below, resulting in violation of monotonicity.
+        */
+       rdtsc_barrier();
+       offset = pvclock_get_nsec_offset(src);
+       ret = src->system_time + offset;
+       ret_flags = src->flags;
+       rdtsc_barrier();
+
+       *cycles = ret;
+       *flags = ret_flags;
+       return version;
+}
+
+struct pvclock_vsyscall_time_info {
+       struct pvclock_vcpu_time_info pvti;
+       u32 migrate_count;
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+#define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
+#define PVCLOCK_VSYSCALL_NR_PAGES (((NR_CPUS-1)/(PAGE_SIZE/PVTI_SIZE))+1)
+
+int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
+                                int size);
+struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu);
+
 #endif /* _ASM_X86_PVCLOCK_H */
diff --git a/arch/x86/include/asm/resource.h b/arch/x86/include/asm/resource.h
deleted file mode 100644 (file)
index 04bc4db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/x86/include/asm/sembuf.h b/arch/x86/include/asm/sembuf.h
deleted file mode 100644 (file)
index ee50c80..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _ASM_X86_SEMBUF_H
-#define _ASM_X86_SEMBUF_H
-
-/*
- * The semid64_ds structure for x86 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-struct semid64_ds {
-       struct ipc64_perm sem_perm;     /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime;      /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;      /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems;      /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _ASM_X86_SEMBUF_H */
index d0f19f9fb846956a0715e59e52836fd9bc767028..b7bf3505e1ec0ba4d1c42c51aeae60babf150a55 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef _ASM_X86_SETUP_H
 #define _ASM_X86_SETUP_H
 
-#ifdef __KERNEL__
+#include <uapi/asm/setup.h>
+
 
 #define COMMAND_LINE_SIZE 2048
 
@@ -123,6 +124,4 @@ void __init x86_64_start_reservations(char *real_mode_data);
        .size .brk.name,.-1b;                           \
        .popsection
 #endif /* __ASSEMBLY__ */
-#endif  /*  __KERNEL__  */
-
 #endif /* _ASM_X86_SETUP_H */
diff --git a/arch/x86/include/asm/shmbuf.h b/arch/x86/include/asm/shmbuf.h
deleted file mode 100644 (file)
index 83c05fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmbuf.h>
index 5ca71c065eef2d9a62af1defdb2b06ac7f64cbbd..9dfce4e0417d92adc623d32ff93f67109316b451 100644 (file)
@@ -1,104 +1,9 @@
 #ifndef _ASM_X86_SIGCONTEXT_H
 #define _ASM_X86_SIGCONTEXT_H
 
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-#define FP_XSTATE_MAGIC1       0x46505853U
-#define FP_XSTATE_MAGIC2       0x46505845U
-#define FP_XSTATE_MAGIC2_SIZE  sizeof(FP_XSTATE_MAGIC2)
-
-/*
- * bytes 464..511 in the current 512byte layout of fxsave/fxrstor frame
- * are reserved for SW usage. On cpu's supporting xsave/xrstor, these bytes
- * are used to extended the fpstate pointer in the sigcontext, which now
- * includes the extended state information along with fpstate information.
- *
- * Presence of FP_XSTATE_MAGIC1 at the beginning of this SW reserved
- * area and FP_XSTATE_MAGIC2 at the end of memory layout
- * (extended_size - FP_XSTATE_MAGIC2_SIZE) indicates the presence of the
- * extended state information in the memory layout pointed by the fpstate
- * pointer in sigcontext.
- */
-struct _fpx_sw_bytes {
-       __u32 magic1;           /* FP_XSTATE_MAGIC1 */
-       __u32 extended_size;    /* total size of the layout referred by
-                                * fpstate pointer in the sigcontext.
-                                */
-       __u64 xstate_bv;
-                               /* feature bit mask (including fp/sse/extended
-                                * state) that is present in the memory
-                                * layout.
-                                */
-       __u32 xstate_size;      /* actual xsave state size, based on the
-                                * features saved in the layout.
-                                * 'extended_size' will be greater than
-                                * 'xstate_size'.
-                                */
-       __u32 padding[7];       /*  for future use. */
-};
+#include <uapi/asm/sigcontext.h>
 
 #ifdef __i386__
-/*
- * As documented in the iBCS2 standard..
- *
- * The first part of "struct _fpstate" is just the normal i387
- * hardware setup, the extra "status" word is used to save the
- * coprocessor status word before entering the handler.
- *
- * Pentium III FXSR, SSE support
- *     Gareth Hughes <gareth@valinux.com>, May 2000
- *
- * The FPU state data structure has had to grow to accommodate the
- * extended FPU state required by the Streaming SIMD Extensions.
- * There is no documented standard to accomplish this at the moment.
- */
-struct _fpreg {
-       unsigned short significand[4];
-       unsigned short exponent;
-};
-
-struct _fpxreg {
-       unsigned short significand[4];
-       unsigned short exponent;
-       unsigned short padding[3];
-};
-
-struct _xmmreg {
-       unsigned long element[4];
-};
-
-struct _fpstate {
-       /* Regular FPU environment */
-       unsigned long   cw;
-       unsigned long   sw;
-       unsigned long   tag;
-       unsigned long   ipoff;
-       unsigned long   cssel;
-       unsigned long   dataoff;
-       unsigned long   datasel;
-       struct _fpreg   _st[8];
-       unsigned short  status;
-       unsigned short  magic;          /* 0xffff = regular FPU data only */
-
-       /* FXSR FPU environment */
-       unsigned long   _fxsr_env[6];   /* FXSR FPU env is ignored */
-       unsigned long   mxcsr;
-       unsigned long   reserved;
-       struct _fpxreg  _fxsr_st[8];    /* FXSR FPU reg data is ignored */
-       struct _xmmreg  _xmm[8];
-       unsigned long   padding1[44];
-
-       union {
-               unsigned long   padding2[12];
-               struct _fpx_sw_bytes sw_reserved; /* represents the extended
-                                                  * state info */
-       };
-};
-
-#define X86_FXSR_MAGIC         0x0000
-
-#ifdef __KERNEL__
 struct sigcontext {
        unsigned short gs, __gsh;
        unsigned short fs, __fsh;
@@ -131,62 +36,7 @@ struct sigcontext {
        unsigned long oldmask;
        unsigned long cr2;
 };
-#else /* __KERNEL__ */
-/*
- * User-space might still rely on the old definition:
- */
-struct sigcontext {
-       unsigned short gs, __gsh;
-       unsigned short fs, __fsh;
-       unsigned short es, __esh;
-       unsigned short ds, __dsh;
-       unsigned long edi;
-       unsigned long esi;
-       unsigned long ebp;
-       unsigned long esp;
-       unsigned long ebx;
-       unsigned long edx;
-       unsigned long ecx;
-       unsigned long eax;
-       unsigned long trapno;
-       unsigned long err;
-       unsigned long eip;
-       unsigned short cs, __csh;
-       unsigned long eflags;
-       unsigned long esp_at_signal;
-       unsigned short ss, __ssh;
-       struct _fpstate __user *fpstate;
-       unsigned long oldmask;
-       unsigned long cr2;
-};
-#endif /* !__KERNEL__ */
-
 #else /* __i386__ */
-
-/* FXSAVE frame */
-/* Note: reserved1/2 may someday contain valuable data. Always save/restore
-   them when you change signal frames. */
-struct _fpstate {
-       __u16   cwd;
-       __u16   swd;
-       __u16   twd;            /* Note this is not the same as the
-                                  32bit/x87/FSAVE twd */
-       __u16   fop;
-       __u64   rip;
-       __u64   rdp;
-       __u32   mxcsr;
-       __u32   mxcsr_mask;
-       __u32   st_space[32];   /* 8*16 bytes for each FP-reg */
-       __u32   xmm_space[64];  /* 16*16 bytes for each XMM-reg  */
-       __u32   reserved2[12];
-       union {
-               __u32   reserved3[12];
-               struct _fpx_sw_bytes sw_reserved; /* represents the extended
-                                                  * state information */
-       };
-};
-
-#ifdef __KERNEL__
 struct sigcontext {
        unsigned long r8;
        unsigned long r9;
@@ -225,69 +75,5 @@ struct sigcontext {
        void __user *fpstate;           /* zero when no FPU/extended context */
        unsigned long reserved1[8];
 };
-#else /* __KERNEL__ */
-/*
- * User-space might still rely on the old definition:
- */
-struct sigcontext {
-       __u64 r8;
-       __u64 r9;
-       __u64 r10;
-       __u64 r11;
-       __u64 r12;
-       __u64 r13;
-       __u64 r14;
-       __u64 r15;
-       __u64 rdi;
-       __u64 rsi;
-       __u64 rbp;
-       __u64 rbx;
-       __u64 rdx;
-       __u64 rax;
-       __u64 rcx;
-       __u64 rsp;
-       __u64 rip;
-       __u64 eflags;           /* RFLAGS */
-       __u16 cs;
-       __u16 gs;
-       __u16 fs;
-       __u16 __pad0;
-       __u64 err;
-       __u64 trapno;
-       __u64 oldmask;
-       __u64 cr2;
-       struct _fpstate __user *fpstate;        /* zero when no FPU context */
-#ifdef __ILP32__
-       __u32 __fpstate_pad;
-#endif
-       __u64 reserved1[8];
-};
-#endif /* !__KERNEL__ */
-
 #endif /* !__i386__ */
-
-struct _xsave_hdr {
-       __u64 xstate_bv;
-       __u64 reserved1[2];
-       __u64 reserved2[5];
-};
-
-struct _ymmh_state {
-       /* 16 * 16 bytes for each YMMH-reg */
-       __u32 ymmh_space[64];
-};
-
-/*
- * Extended state pointed by the fpstate pointer in the sigcontext.
- * In addition to the fpstate, information encoded in the xstate_hdr
- * indicates the presence of other extended state information
- * supported by the processor and OS.
- */
-struct _xstate {
-       struct _fpstate fpstate;
-       struct _xsave_hdr xstate_hdr;
-       struct _ymmh_state ymmh;
-       /* new processor state extensions go here */
-};
-
 #endif /* _ASM_X86_SIGCONTEXT_H */
diff --git a/arch/x86/include/asm/sigcontext32.h b/arch/x86/include/asm/sigcontext32.h
deleted file mode 100644 (file)
index ad1478c..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _ASM_X86_SIGCONTEXT32_H
-#define _ASM_X86_SIGCONTEXT32_H
-
-#include <linux/types.h>
-
-/* signal context for 32bit programs. */
-
-#define X86_FXSR_MAGIC         0x0000
-
-struct _fpreg {
-       unsigned short significand[4];
-       unsigned short exponent;
-};
-
-struct _fpxreg {
-       unsigned short significand[4];
-       unsigned short exponent;
-       unsigned short padding[3];
-};
-
-struct _xmmreg {
-       __u32   element[4];
-};
-
-/* FSAVE frame with extensions */
-struct _fpstate_ia32 {
-       /* Regular FPU environment */
-       __u32   cw;
-       __u32   sw;
-       __u32   tag;    /* not compatible to 64bit twd */
-       __u32   ipoff;
-       __u32   cssel;
-       __u32   dataoff;
-       __u32   datasel;
-       struct _fpreg   _st[8];
-       unsigned short  status;
-       unsigned short  magic;          /* 0xffff = regular FPU data only */
-
-       /* FXSR FPU environment */
-       __u32   _fxsr_env[6];
-       __u32   mxcsr;
-       __u32   reserved;
-       struct _fpxreg  _fxsr_st[8];
-       struct _xmmreg  _xmm[8];        /* It's actually 16 */
-       __u32   padding[44];
-       union {
-               __u32 padding2[12];
-               struct _fpx_sw_bytes sw_reserved;
-       };
-};
-
-struct sigcontext_ia32 {
-       unsigned short gs, __gsh;
-       unsigned short fs, __fsh;
-       unsigned short es, __esh;
-       unsigned short ds, __dsh;
-       unsigned int di;
-       unsigned int si;
-       unsigned int bp;
-       unsigned int sp;
-       unsigned int bx;
-       unsigned int dx;
-       unsigned int cx;
-       unsigned int ax;
-       unsigned int trapno;
-       unsigned int err;
-       unsigned int ip;
-       unsigned short cs, __csh;
-       unsigned int flags;
-       unsigned int sp_at_signal;
-       unsigned short ss, __ssh;
-       unsigned int fpstate;           /* really (struct _fpstate_ia32 *) */
-       unsigned int oldmask;
-       unsigned int cr2;
-};
-
-#endif /* _ASM_X86_SIGCONTEXT32_H */
diff --git a/arch/x86/include/asm/siginfo.h b/arch/x86/include/asm/siginfo.h
deleted file mode 100644 (file)
index 34c47b3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_X86_SIGINFO_H
-#define _ASM_X86_SIGINFO_H
-
-#ifdef __x86_64__
-# ifdef __ILP32__ /* x32 */
-typedef long long __kernel_si_clock_t __attribute__((aligned(4)));
-#  define __ARCH_SI_CLOCK_T            __kernel_si_clock_t
-#  define __ARCH_SI_ATTRIBUTES         __attribute__((aligned(8)))
-# else /* x86-64 */
-#  define __ARCH_SI_PREAMBLE_SIZE      (4 * sizeof(int))
-# endif
-#endif
-
-#include <asm-generic/siginfo.h>
-
-#endif /* _ASM_X86_SIGINFO_H */
index 0dba8b7a6ac7c6d8824e563d01889ca7134304a6..216bf364a7e7098a82962613faba2b6c6f20adca 100644 (file)
@@ -2,14 +2,6 @@
 #define _ASM_X86_SIGNAL_H
 
 #ifndef __ASSEMBLY__
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/compiler.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 #include <linux/linkage.h>
 
 /* Most things should be clean enough to redefine this at will, if care
@@ -35,102 +27,11 @@ typedef struct {
 typedef sigset_t compat_sigset_t;
 #endif
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
-
-#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   0x00000001u
-#define SA_NOCLDWAIT   0x00000002u
-#define SA_SIGINFO     0x00000004u
-#define SA_ONSTACK     0x08000000u
-#define SA_RESTART     0x10000000u
-#define SA_NODEFER     0x40000000u
-#define SA_RESETHAND   0x80000000u
-
-#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>
-
+#include <uapi/asm/signal.h>
 #ifndef __ASSEMBLY__
-
-# ifdef __KERNEL__
 extern void do_notify_resume(struct pt_regs *, void *, __u32);
-# endif /* __KERNEL__ */
-
 #ifdef __i386__
-# ifdef __KERNEL__
 struct old_sigaction {
        __sighandler_t sa_handler;
        old_sigset_t sa_mask;
@@ -149,45 +50,8 @@ struct k_sigaction {
        struct sigaction sa;
 };
 
-# else /* __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;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-# endif /* ! __KERNEL__ */
 #else /* __i386__ */
-
-struct sigaction {
-       __sighandler_t sa_handler;
-       unsigned long sa_flags;
-       __sigrestore_t sa_restorer;
-       sigset_t sa_mask;               /* mask last for extensibility */
-};
-
-struct k_sigaction {
-       struct sigaction sa;
-};
-
 #endif /* !__i386__ */
-
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
 #ifdef __i386__
@@ -260,7 +124,5 @@ struct pt_regs;
 
 #endif /* !__i386__ */
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_X86_SIGNAL_H */
diff --git a/arch/x86/include/asm/socket.h b/arch/x86/include/asm/socket.h
deleted file mode 100644 (file)
index 6b71384..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/socket.h>
diff --git a/arch/x86/include/asm/sockios.h b/arch/x86/include/asm/sockios.h
deleted file mode 100644 (file)
index def6d47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sockios.h>
diff --git a/arch/x86/include/asm/stat.h b/arch/x86/include/asm/stat.h
deleted file mode 100644 (file)
index 7b3ddc3..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _ASM_X86_STAT_H
-#define _ASM_X86_STAT_H
-
-#define STAT_HAVE_NSEC 1
-
-#ifdef __i386__
-struct stat {
-       unsigned long  st_dev;
-       unsigned long  st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned long  st_rdev;
-       unsigned long  st_size;
-       unsigned long  st_blksize;
-       unsigned long  st_blocks;
-       unsigned long  st_atime;
-       unsigned long  st_atime_nsec;
-       unsigned long  st_mtime;
-       unsigned long  st_mtime_nsec;
-       unsigned long  st_ctime;
-       unsigned long  st_ctime_nsec;
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-/* We don't need to memset the whole thing just to initialize the padding */
-#define INIT_STRUCT_STAT_PADDING(st) do {      \
-       st.__unused4 = 0;                       \
-       st.__unused5 = 0;                       \
-} while (0)
-
-#define STAT64_HAS_BROKEN_ST_INO       1
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
-       unsigned long long      st_dev;
-       unsigned char   __pad0[4];
-
-       unsigned long   __st_ino;
-
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned long   st_uid;
-       unsigned long   st_gid;
-
-       unsigned long long      st_rdev;
-       unsigned char   __pad3[4];
-
-       long long       st_size;
-       unsigned long   st_blksize;
-
-       /* Number 512-byte blocks allocated. */
-       unsigned long long      st_blocks;
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-
-       unsigned long   st_mtime;
-       unsigned int    st_mtime_nsec;
-
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-
-       unsigned long long      st_ino;
-};
-
-/* We don't need to memset the whole thing just to initialize the padding */
-#define INIT_STRUCT_STAT64_PADDING(st) do {            \
-       memset(&st.__pad0, 0, sizeof(st.__pad0));       \
-       memset(&st.__pad3, 0, sizeof(st.__pad3));       \
-} while (0)
-
-#else /* __i386__ */
-
-struct stat {
-       unsigned long   st_dev;
-       unsigned long   st_ino;
-       unsigned long   st_nlink;
-
-       unsigned int    st_mode;
-       unsigned int    st_uid;
-       unsigned int    st_gid;
-       unsigned int    __pad0;
-       unsigned long   st_rdev;
-       long            st_size;
-       long            st_blksize;
-       long            st_blocks;      /* Number 512-byte blocks allocated. */
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-       long            __unused[3];
-};
-
-/* We don't need to memset the whole thing just to initialize the padding */
-#define INIT_STRUCT_STAT_PADDING(st) do {      \
-       st.__pad0 = 0;                          \
-       st.__unused[0] = 0;                     \
-       st.__unused[1] = 0;                     \
-       st.__unused[2] = 0;                     \
-} while (0)
-
-#endif
-
-/* for 32bit emulation and 32 bit kernels */
-struct __old_kernel_stat {
-       unsigned short st_dev;
-       unsigned short st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-#ifdef __i386__
-       unsigned long  st_size;
-       unsigned long  st_atime;
-       unsigned long  st_mtime;
-       unsigned long  st_ctime;
-#else
-       unsigned int  st_size;
-       unsigned int  st_atime;
-       unsigned int  st_mtime;
-       unsigned int  st_ctime;
-#endif
-};
-
-#endif /* _ASM_X86_STAT_H */
diff --git a/arch/x86/include/asm/statfs.h b/arch/x86/include/asm/statfs.h
deleted file mode 100644 (file)
index 2d0adbf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_X86_STATFS_H
-#define _ASM_X86_STATFS_H
-
-/*
- * We need compat_statfs64 to be packed, because the i386 ABI won't
- * add padding at the end to bring it to a multiple of 8 bytes, but
- * the x86_64 ABI will.
- */
-#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
-
-#include <asm-generic/statfs.h>
-#endif /* _ASM_X86_STATFS_H */
index cdf5674dd23af305b6d1b5216f36e13775a765c9..6136d99f537b493f8c888b312fad3af996fe5787 100644 (file)
@@ -1,134 +1,8 @@
 #ifndef __SVM_H
 #define __SVM_H
 
-#define SVM_EXIT_READ_CR0      0x000
-#define SVM_EXIT_READ_CR3      0x003
-#define SVM_EXIT_READ_CR4      0x004
-#define SVM_EXIT_READ_CR8      0x008
-#define SVM_EXIT_WRITE_CR0     0x010
-#define SVM_EXIT_WRITE_CR3     0x013
-#define SVM_EXIT_WRITE_CR4     0x014
-#define SVM_EXIT_WRITE_CR8     0x018
-#define SVM_EXIT_READ_DR0      0x020
-#define SVM_EXIT_READ_DR1      0x021
-#define SVM_EXIT_READ_DR2      0x022
-#define SVM_EXIT_READ_DR3      0x023
-#define SVM_EXIT_READ_DR4      0x024
-#define SVM_EXIT_READ_DR5      0x025
-#define SVM_EXIT_READ_DR6      0x026
-#define SVM_EXIT_READ_DR7      0x027
-#define SVM_EXIT_WRITE_DR0     0x030
-#define SVM_EXIT_WRITE_DR1     0x031
-#define SVM_EXIT_WRITE_DR2     0x032
-#define SVM_EXIT_WRITE_DR3     0x033
-#define SVM_EXIT_WRITE_DR4     0x034
-#define SVM_EXIT_WRITE_DR5     0x035
-#define SVM_EXIT_WRITE_DR6     0x036
-#define SVM_EXIT_WRITE_DR7     0x037
-#define SVM_EXIT_EXCP_BASE     0x040
-#define SVM_EXIT_INTR          0x060
-#define SVM_EXIT_NMI           0x061
-#define SVM_EXIT_SMI           0x062
-#define SVM_EXIT_INIT          0x063
-#define SVM_EXIT_VINTR         0x064
-#define SVM_EXIT_CR0_SEL_WRITE 0x065
-#define SVM_EXIT_IDTR_READ     0x066
-#define SVM_EXIT_GDTR_READ     0x067
-#define SVM_EXIT_LDTR_READ     0x068
-#define SVM_EXIT_TR_READ       0x069
-#define SVM_EXIT_IDTR_WRITE    0x06a
-#define SVM_EXIT_GDTR_WRITE    0x06b
-#define SVM_EXIT_LDTR_WRITE    0x06c
-#define SVM_EXIT_TR_WRITE      0x06d
-#define SVM_EXIT_RDTSC         0x06e
-#define SVM_EXIT_RDPMC         0x06f
-#define SVM_EXIT_PUSHF         0x070
-#define SVM_EXIT_POPF          0x071
-#define SVM_EXIT_CPUID         0x072
-#define SVM_EXIT_RSM           0x073
-#define SVM_EXIT_IRET          0x074
-#define SVM_EXIT_SWINT         0x075
-#define SVM_EXIT_INVD          0x076
-#define SVM_EXIT_PAUSE         0x077
-#define SVM_EXIT_HLT           0x078
-#define SVM_EXIT_INVLPG        0x079
-#define SVM_EXIT_INVLPGA       0x07a
-#define SVM_EXIT_IOIO          0x07b
-#define SVM_EXIT_MSR           0x07c
-#define SVM_EXIT_TASK_SWITCH   0x07d
-#define SVM_EXIT_FERR_FREEZE   0x07e
-#define SVM_EXIT_SHUTDOWN      0x07f
-#define SVM_EXIT_VMRUN         0x080
-#define SVM_EXIT_VMMCALL       0x081
-#define SVM_EXIT_VMLOAD        0x082
-#define SVM_EXIT_VMSAVE        0x083
-#define SVM_EXIT_STGI          0x084
-#define SVM_EXIT_CLGI          0x085
-#define SVM_EXIT_SKINIT        0x086
-#define SVM_EXIT_RDTSCP        0x087
-#define SVM_EXIT_ICEBP         0x088
-#define SVM_EXIT_WBINVD        0x089
-#define SVM_EXIT_MONITOR       0x08a
-#define SVM_EXIT_MWAIT         0x08b
-#define SVM_EXIT_MWAIT_COND    0x08c
-#define SVM_EXIT_XSETBV        0x08d
-#define SVM_EXIT_NPF           0x400
-
-#define SVM_EXIT_ERR           -1
-
-#define SVM_EXIT_REASONS \
-       { SVM_EXIT_READ_CR0,    "read_cr0" }, \
-       { SVM_EXIT_READ_CR3,    "read_cr3" }, \
-       { SVM_EXIT_READ_CR4,    "read_cr4" }, \
-       { SVM_EXIT_READ_CR8,    "read_cr8" }, \
-       { SVM_EXIT_WRITE_CR0,   "write_cr0" }, \
-       { SVM_EXIT_WRITE_CR3,   "write_cr3" }, \
-       { SVM_EXIT_WRITE_CR4,   "write_cr4" }, \
-       { SVM_EXIT_WRITE_CR8,   "write_cr8" }, \
-       { SVM_EXIT_READ_DR0,    "read_dr0" }, \
-       { SVM_EXIT_READ_DR1,    "read_dr1" }, \
-       { SVM_EXIT_READ_DR2,    "read_dr2" }, \
-       { SVM_EXIT_READ_DR3,    "read_dr3" }, \
-       { SVM_EXIT_WRITE_DR0,   "write_dr0" }, \
-       { SVM_EXIT_WRITE_DR1,   "write_dr1" }, \
-       { SVM_EXIT_WRITE_DR2,   "write_dr2" }, \
-       { SVM_EXIT_WRITE_DR3,   "write_dr3" }, \
-       { SVM_EXIT_WRITE_DR5,   "write_dr5" }, \
-       { SVM_EXIT_WRITE_DR7,   "write_dr7" }, \
-       { SVM_EXIT_EXCP_BASE + DB_VECTOR,       "DB excp" }, \
-       { SVM_EXIT_EXCP_BASE + BP_VECTOR,       "BP excp" }, \
-       { SVM_EXIT_EXCP_BASE + UD_VECTOR,       "UD excp" }, \
-       { SVM_EXIT_EXCP_BASE + PF_VECTOR,       "PF excp" }, \
-       { SVM_EXIT_EXCP_BASE + NM_VECTOR,       "NM excp" }, \
-       { SVM_EXIT_EXCP_BASE + MC_VECTOR,       "MC excp" }, \
-       { SVM_EXIT_INTR,        "interrupt" }, \
-       { SVM_EXIT_NMI,         "nmi" }, \
-       { SVM_EXIT_SMI,         "smi" }, \
-       { SVM_EXIT_INIT,        "init" }, \
-       { SVM_EXIT_VINTR,       "vintr" }, \
-       { SVM_EXIT_CPUID,       "cpuid" }, \
-       { SVM_EXIT_INVD,        "invd" }, \
-       { SVM_EXIT_HLT,         "hlt" }, \
-       { SVM_EXIT_INVLPG,      "invlpg" }, \
-       { SVM_EXIT_INVLPGA,     "invlpga" }, \
-       { SVM_EXIT_IOIO,        "io" }, \
-       { SVM_EXIT_MSR,         "msr" }, \
-       { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
-       { SVM_EXIT_SHUTDOWN,    "shutdown" }, \
-       { SVM_EXIT_VMRUN,       "vmrun" }, \
-       { SVM_EXIT_VMMCALL,     "hypercall" }, \
-       { SVM_EXIT_VMLOAD,      "vmload" }, \
-       { SVM_EXIT_VMSAVE,      "vmsave" }, \
-       { SVM_EXIT_STGI,        "stgi" }, \
-       { SVM_EXIT_CLGI,        "clgi" }, \
-       { SVM_EXIT_SKINIT,      "skinit" }, \
-       { SVM_EXIT_WBINVD,      "wbinvd" }, \
-       { SVM_EXIT_MONITOR,     "monitor" }, \
-       { SVM_EXIT_MWAIT,       "mwait" }, \
-       { SVM_EXIT_XSETBV,      "xsetbv" }, \
-       { SVM_EXIT_NPF,         "npf" }
-
-#ifdef __KERNEL__
+#include <uapi/asm/svm.h>
+
 
 enum {
        INTERCEPT_INTR,
@@ -403,5 +277,3 @@ struct __attribute__ ((__packed__)) vmcb {
 #define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf"
 
 #endif
-
-#endif
diff --git a/arch/x86/include/asm/swab.h b/arch/x86/include/asm/swab.h
deleted file mode 100644 (file)
index 7f235c7..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _ASM_X86_SWAB_H
-#define _ASM_X86_SWAB_H
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-       asm("bswapl %0" : "=r" (val) : "0" (val));
-       return val;
-}
-#define __arch_swab32 __arch_swab32
-
-static inline __attribute_const__ __u64 __arch_swab64(__u64 val)
-{
-#ifdef __i386__
-       union {
-               struct {
-                       __u32 a;
-                       __u32 b;
-               } s;
-               __u64 u;
-       } v;
-       v.u = val;
-       asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
-           : "=r" (v.s.a), "=r" (v.s.b)
-           : "0" (v.s.a), "1" (v.s.b));
-       return v.u;
-#else /* __i386__ */
-       asm("bswapq %0" : "=r" (val) : "0" (val));
-       return val;
-#endif
-}
-#define __arch_swab64 __arch_swab64
-
-#endif /* _ASM_X86_SWAB_H */
diff --git a/arch/x86/include/asm/termbits.h b/arch/x86/include/asm/termbits.h
deleted file mode 100644 (file)
index 3935b10..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/x86/include/asm/termios.h b/arch/x86/include/asm/termios.h
deleted file mode 100644 (file)
index 280d78a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
deleted file mode 100644 (file)
index 8e8c23f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_X86_TYPES_H
-#define _ASM_X86_TYPES_H
-
-#include <asm-generic/types.h>
-
-#endif /* _ASM_X86_TYPES_H */
diff --git a/arch/x86/include/asm/ucontext.h b/arch/x86/include/asm/ucontext.h
deleted file mode 100644 (file)
index b7c29c8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_X86_UCONTEXT_H
-#define _ASM_X86_UCONTEXT_H
-
-#define UC_FP_XSTATE   0x1     /* indicates the presence of extended state
-                                * information in the memory layout pointed
-                                * by the fpstate pointer in the ucontext's
-                                * sigcontext struct (uc_mcontext).
-                                */
-
-#include <asm-generic/ucontext.h>
-
-#endif /* _ASM_X86_UCONTEXT_H */
index 0e7dea7d366982d18ab89cfe17a6a6b99edc255f..1003e69a40d9d217cf7443cea4609c3701fc7196 100644 (file)
@@ -1,10 +1,8 @@
 #ifndef _ASM_X86_UNISTD_H
 #define _ASM_X86_UNISTD_H 1
 
-/* x32 syscall flag bit */
-#define __X32_SYSCALL_BIT      0x40000000
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
 # ifdef CONFIG_X86_X32_ABI
 #  define __SYSCALL_MASK (~(__X32_SYSCALL_BIT))
  */
 # define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#else
-# ifdef __i386__
-#  include <asm/unistd_32.h>
-# elif defined(__ILP32__)
-#  include <asm/unistd_x32.h>
-# else
-#  include <asm/unistd_64.h>
-# endif
-#endif
-
 #endif /* _ASM_X86_UNISTD_H */
index f9303602fbc09b733e3f52319d43e0c3c65c8de3..1d8de3f3fecade2fc63bdab01582f566aa1d47d5 100644 (file)
@@ -1,133 +1,9 @@
 #ifndef _ASM_X86_VM86_H
 #define _ASM_X86_VM86_H
 
-/*
- * I'm guessing at the VIF/VIP flag usage, but hope that this is how
- * the Pentium uses them. Linux will return from vm86 mode when both
- * VIF and VIP is set.
- *
- * On a Pentium, we could probably optimize the virtual flags directly
- * in the eflags register instead of doing it "by hand" in vflags...
- *
- * Linus
- */
-
-#include <asm/processor-flags.h>
-
-#define BIOSSEG                0x0f000
-
-#define CPU_086                0
-#define CPU_186                1
-#define CPU_286                2
-#define CPU_386                3
-#define CPU_486                4
-#define CPU_586                5
-
-/*
- * Return values for the 'vm86()' system call
- */
-#define VM86_TYPE(retval)      ((retval) & 0xff)
-#define VM86_ARG(retval)       ((retval) >> 8)
-
-#define VM86_SIGNAL    0       /* return due to signal */
-#define VM86_UNKNOWN   1       /* unhandled GP fault
-                                  - IO-instruction or similar */
-#define VM86_INTx      2       /* int3/int x instruction (ARG = x) */
-#define VM86_STI       3       /* sti/popf/iret instruction enabled
-                                  virtual interrupts */
-
-/*
- * Additional return values when invoking new vm86()
- */
-#define VM86_PICRETURN 4       /* return due to pending PIC request */
-#define VM86_TRAP      6       /* return due to DOS-debugger request */
-
-/*
- * function codes when invoking new vm86()
- */
-#define VM86_PLUS_INSTALL_CHECK        0
-#define VM86_ENTER             1
-#define VM86_ENTER_NO_BYPASS   2
-#define        VM86_REQUEST_IRQ        3
-#define VM86_FREE_IRQ          4
-#define VM86_GET_IRQ_BITS      5
-#define VM86_GET_AND_RESET_IRQ 6
-
-/*
- * This is the stack-layout seen by the user space program when we have
- * done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout
- * is 'kernel_vm86_regs' (see below).
- */
-
-struct vm86_regs {
-/*
- * normal regs, with special meaning for the segment descriptors..
- */
-       long ebx;
-       long ecx;
-       long edx;
-       long esi;
-       long edi;
-       long ebp;
-       long eax;
-       long __null_ds;
-       long __null_es;
-       long __null_fs;
-       long __null_gs;
-       long orig_eax;
-       long eip;
-       unsigned short cs, __csh;
-       long eflags;
-       long esp;
-       unsigned short ss, __ssh;
-/*
- * these are specific to v86 mode:
- */
-       unsigned short es, __esh;
-       unsigned short ds, __dsh;
-       unsigned short fs, __fsh;
-       unsigned short gs, __gsh;
-};
-
-struct revectored_struct {
-       unsigned long __map[8];                 /* 256 bits */
-};
-
-struct vm86_struct {
-       struct vm86_regs regs;
-       unsigned long flags;
-       unsigned long screen_bitmap;
-       unsigned long cpu_type;
-       struct revectored_struct int_revectored;
-       struct revectored_struct int21_revectored;
-};
-
-/*
- * flags masks
- */
-#define VM86_SCREEN_BITMAP     0x0001
-
-struct vm86plus_info_struct {
-       unsigned long force_return_for_pic:1;
-       unsigned long vm86dbg_active:1;       /* for debugger */
-       unsigned long vm86dbg_TFpendig:1;     /* for debugger */
-       unsigned long unused:28;
-       unsigned long is_vm86pus:1;           /* for vm86 internal use */
-       unsigned char vm86dbg_intxxtab[32];   /* for debugger */
-};
-struct vm86plus_struct {
-       struct vm86_regs regs;
-       unsigned long flags;
-       unsigned long screen_bitmap;
-       unsigned long cpu_type;
-       struct revectored_struct int_revectored;
-       struct revectored_struct int21_revectored;
-       struct vm86plus_info_struct vm86plus;
-};
-
-#ifdef __KERNEL__
 
 #include <asm/ptrace.h>
+#include <uapi/asm/vm86.h>
 
 /*
  * This is the (kernel) stack-layout when we have done a "SAVE_ALL" from vm86
@@ -203,6 +79,4 @@ static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c)
 
 #endif /* CONFIG_VM86 */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_VM86_H */
index 36ec21c36d68dad618f31e1be5bf423950262f26..235b49fa554bd614c6cb6b61c9c3618f1cd91a99 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef VMX_H
-#define VMX_H
-
 /*
  * vmx.h: VMX Architecture related definitions
  * Copyright (c) 2004, Intel Corporation.
  *    Yaniv Kamay <yaniv@qumranet.com>
  *
  */
+#ifndef VMX_H
+#define VMX_H
 
-#define VMX_EXIT_REASONS_FAILED_VMENTRY         0x80000000
-
-#define EXIT_REASON_EXCEPTION_NMI       0
-#define EXIT_REASON_EXTERNAL_INTERRUPT  1
-#define EXIT_REASON_TRIPLE_FAULT        2
-
-#define EXIT_REASON_PENDING_INTERRUPT   7
-#define EXIT_REASON_NMI_WINDOW          8
-#define EXIT_REASON_TASK_SWITCH         9
-#define EXIT_REASON_CPUID               10
-#define EXIT_REASON_HLT                 12
-#define EXIT_REASON_INVD                13
-#define EXIT_REASON_INVLPG              14
-#define EXIT_REASON_RDPMC               15
-#define EXIT_REASON_RDTSC               16
-#define EXIT_REASON_VMCALL              18
-#define EXIT_REASON_VMCLEAR             19
-#define EXIT_REASON_VMLAUNCH            20
-#define EXIT_REASON_VMPTRLD             21
-#define EXIT_REASON_VMPTRST             22
-#define EXIT_REASON_VMREAD              23
-#define EXIT_REASON_VMRESUME            24
-#define EXIT_REASON_VMWRITE             25
-#define EXIT_REASON_VMOFF               26
-#define EXIT_REASON_VMON                27
-#define EXIT_REASON_CR_ACCESS           28
-#define EXIT_REASON_DR_ACCESS           29
-#define EXIT_REASON_IO_INSTRUCTION      30
-#define EXIT_REASON_MSR_READ            31
-#define EXIT_REASON_MSR_WRITE           32
-#define EXIT_REASON_INVALID_STATE       33
-#define EXIT_REASON_MWAIT_INSTRUCTION   36
-#define EXIT_REASON_MONITOR_INSTRUCTION 39
-#define EXIT_REASON_PAUSE_INSTRUCTION   40
-#define EXIT_REASON_MCE_DURING_VMENTRY  41
-#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
-#define EXIT_REASON_APIC_ACCESS         44
-#define EXIT_REASON_EPT_VIOLATION       48
-#define EXIT_REASON_EPT_MISCONFIG       49
-#define EXIT_REASON_WBINVD              54
-#define EXIT_REASON_XSETBV              55
-#define EXIT_REASON_INVPCID             58
-
-#define VMX_EXIT_REASONS \
-       { EXIT_REASON_EXCEPTION_NMI,         "EXCEPTION_NMI" }, \
-       { EXIT_REASON_EXTERNAL_INTERRUPT,    "EXTERNAL_INTERRUPT" }, \
-       { EXIT_REASON_TRIPLE_FAULT,          "TRIPLE_FAULT" }, \
-       { EXIT_REASON_PENDING_INTERRUPT,     "PENDING_INTERRUPT" }, \
-       { EXIT_REASON_NMI_WINDOW,            "NMI_WINDOW" }, \
-       { EXIT_REASON_TASK_SWITCH,           "TASK_SWITCH" }, \
-       { EXIT_REASON_CPUID,                 "CPUID" }, \
-       { EXIT_REASON_HLT,                   "HLT" }, \
-       { EXIT_REASON_INVLPG,                "INVLPG" }, \
-       { EXIT_REASON_RDPMC,                 "RDPMC" }, \
-       { EXIT_REASON_RDTSC,                 "RDTSC" }, \
-       { EXIT_REASON_VMCALL,                "VMCALL" }, \
-       { EXIT_REASON_VMCLEAR,               "VMCLEAR" }, \
-       { EXIT_REASON_VMLAUNCH,              "VMLAUNCH" }, \
-       { EXIT_REASON_VMPTRLD,               "VMPTRLD" }, \
-       { EXIT_REASON_VMPTRST,               "VMPTRST" }, \
-       { EXIT_REASON_VMREAD,                "VMREAD" }, \
-       { EXIT_REASON_VMRESUME,              "VMRESUME" }, \
-       { EXIT_REASON_VMWRITE,               "VMWRITE" }, \
-       { EXIT_REASON_VMOFF,                 "VMOFF" }, \
-       { EXIT_REASON_VMON,                  "VMON" }, \
-       { EXIT_REASON_CR_ACCESS,             "CR_ACCESS" }, \
-       { EXIT_REASON_DR_ACCESS,             "DR_ACCESS" }, \
-       { EXIT_REASON_IO_INSTRUCTION,        "IO_INSTRUCTION" }, \
-       { EXIT_REASON_MSR_READ,              "MSR_READ" }, \
-       { EXIT_REASON_MSR_WRITE,             "MSR_WRITE" }, \
-       { EXIT_REASON_MWAIT_INSTRUCTION,     "MWAIT_INSTRUCTION" }, \
-       { EXIT_REASON_MONITOR_INSTRUCTION,   "MONITOR_INSTRUCTION" }, \
-       { EXIT_REASON_PAUSE_INSTRUCTION,     "PAUSE_INSTRUCTION" }, \
-       { EXIT_REASON_MCE_DURING_VMENTRY,    "MCE_DURING_VMENTRY" }, \
-       { EXIT_REASON_TPR_BELOW_THRESHOLD,   "TPR_BELOW_THRESHOLD" }, \
-       { EXIT_REASON_APIC_ACCESS,           "APIC_ACCESS" }, \
-       { EXIT_REASON_EPT_VIOLATION,         "EPT_VIOLATION" }, \
-       { EXIT_REASON_EPT_MISCONFIG,         "EPT_MISCONFIG" }, \
-       { EXIT_REASON_WBINVD,                "WBINVD" }
-
-#ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <uapi/asm/vmx.h>
 
 /*
  * Definitions of Primary Processor-Based VM-Execution Controls.
@@ -445,8 +364,7 @@ enum vmcs_field {
 #define VMX_EPTP_WB_BIT                                (1ull << 14)
 #define VMX_EPT_2MB_PAGE_BIT                   (1ull << 16)
 #define VMX_EPT_1GB_PAGE_BIT                   (1ull << 17)
-#define VMX_EPT_AD_BIT                                 (1ull << 21)
-#define VMX_EPT_EXTENT_INDIVIDUAL_BIT          (1ull << 24)
+#define VMX_EPT_AD_BIT                             (1ull << 21)
 #define VMX_EPT_EXTENT_CONTEXT_BIT             (1ull << 25)
 #define VMX_EPT_EXTENT_GLOBAL_BIT              (1ull << 26)
 
@@ -527,5 +445,3 @@ enum vm_instruction_error_number {
 };
 
 #endif
-
-#endif
index eaea1d31f753092cd19ff6cf126f6c7c0f7cedb7..2a46ca720afca5fd6f5e5010698e8eea56748837 100644 (file)
@@ -1,20 +1,8 @@
 #ifndef _ASM_X86_VSYSCALL_H
 #define _ASM_X86_VSYSCALL_H
 
-enum vsyscall_num {
-       __NR_vgettimeofday,
-       __NR_vtime,
-       __NR_vgetcpu,
-};
-
-#define VSYSCALL_START (-10UL << 20)
-#define VSYSCALL_SIZE 1024
-#define VSYSCALL_END (-2UL << 20)
-#define VSYSCALL_MAPPED_PAGES 1
-#define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
-
-#ifdef __KERNEL__
 #include <linux/seqlock.h>
+#include <uapi/asm/vsyscall.h>
 
 #define VGETCPU_RDTSCP 1
 #define VGETCPU_LSL    2
@@ -33,6 +21,24 @@ extern void map_vsyscall(void);
  */
 extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
 
-#endif /* __KERNEL__ */
+#ifdef CONFIG_X86_64
+
+#define VGETCPU_CPU_MASK 0xfff
+
+static inline unsigned int __getcpu(void)
+{
+       unsigned int p;
+
+       if (VVAR(vgetcpu_mode) == VGETCPU_RDTSCP) {
+               /* Load per CPU data from RDTSCP */
+               native_read_tscp(&p);
+       } else {
+               /* Load per CPU data from GDT */
+               asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+       }
+
+       return p;
+}
+#endif /* CONFIG_X86_64 */
 
 #endif /* _ASM_X86_VSYSCALL_H */
index 54d52ff1304a3496bc240ef193030adbb73ec4bb..fd9cb7695b5f444266abebafe6c3fcfa59e2d66b 100644 (file)
@@ -63,6 +63,7 @@ DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
 DEFINE_GUEST_HANDLE(xen_pfn_t);
+DEFINE_GUEST_HANDLE(xen_ulong_t);
 #endif
 
 #ifndef HYPERVISOR_VIRT_START
index 83b6e9a0dce476c4840b02544b76ef049d92f166..09409c44f9a5672b03b4d8dd3710704e3846db03 100644 (file)
@@ -4,3 +4,61 @@ include include/uapi/asm-generic/Kbuild.asm
 genhdr-y += unistd_32.h
 genhdr-y += unistd_64.h
 genhdr-y += unistd_x32.h
+header-y += a.out.h
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += boot.h
+header-y += bootparam.h
+header-y += byteorder.h
+header-y += debugreg.h
+header-y += e820.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += hw_breakpoint.h
+header-y += hyperv.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += ist.h
+header-y += kvm.h
+header-y += kvm_para.h
+header-y += ldt.h
+header-y += mce.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += msr-index.h
+header-y += msr.h
+header-y += mtrr.h
+header-y += param.h
+header-y += perf_regs.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += posix_types_32.h
+header-y += posix_types_64.h
+header-y += posix_types_x32.h
+header-y += prctl.h
+header-y += processor-flags.h
+header-y += ptrace-abi.h
+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 += sigcontext32.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 += svm.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 += vm86.h
+header-y += vmx.h
+header-y += vsyscall.h
diff --git a/arch/x86/include/uapi/asm/a.out.h b/arch/x86/include/uapi/asm/a.out.h
new file mode 100644 (file)
index 0000000..4684f97
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _ASM_X86_A_OUT_H
+#define _ASM_X86_A_OUT_H
+
+struct exec
+{
+       unsigned int a_info;    /* Use macros N_MAGIC, etc for access */
+       unsigned a_text;        /* length of text, in bytes */
+       unsigned a_data;        /* length of data, in bytes */
+       unsigned a_bss;         /* length of uninitialized data area for file, in bytes */
+       unsigned a_syms;        /* length of symbol table data in file, in bytes */
+       unsigned a_entry;       /* start address */
+       unsigned a_trsize;      /* length of relocation info for text, in bytes */
+       unsigned a_drsize;      /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)    ((a).a_trsize)
+#define N_DRSIZE(a)    ((a).a_drsize)
+#define N_SYMSIZE(a)   ((a).a_syms)
+
+#endif /* _ASM_X86_A_OUT_H */
diff --git a/arch/x86/include/uapi/asm/auxvec.h b/arch/x86/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..77203ac
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_X86_AUXVEC_H
+#define _ASM_X86_AUXVEC_H
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#ifdef __i386__
+#define AT_SYSINFO             32
+#endif
+#define AT_SYSINFO_EHDR                33
+
+/* entries in ARCH_DLINFO: */
+#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64)
+# define AT_VECTOR_SIZE_ARCH 2
+#else /* else it's non-compat x86-64 */
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
+#endif /* _ASM_X86_AUXVEC_H */
diff --git a/arch/x86/include/uapi/asm/bitsperlong.h b/arch/x86/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..b0ae1c4
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ASM_X86_BITSPERLONG_H
+#define __ASM_X86_BITSPERLONG_H
+
+#ifdef __x86_64__
+# define __BITS_PER_LONG 64
+#else
+# define __BITS_PER_LONG 32
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_X86_BITSPERLONG_H */
+
diff --git a/arch/x86/include/uapi/asm/boot.h b/arch/x86/include/uapi/asm/boot.h
new file mode 100644 (file)
index 0000000..94292c4
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _UAPI_ASM_X86_BOOT_H
+#define _UAPI_ASM_X86_BOOT_H
+
+/* Internal svga startup constants */
+#define NORMAL_VGA     0xffff          /* 80x25 mode */
+#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
+#define ASK_VGA                0xfffd          /* ask for it at bootup */
+
+
+#endif /* _UAPI_ASM_X86_BOOT_H */
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
new file mode 100644 (file)
index 0000000..92862cd
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef _ASM_X86_BOOTPARAM_H
+#define _ASM_X86_BOOTPARAM_H
+
+#include <linux/types.h>
+#include <linux/screen_info.h>
+#include <linux/apm_bios.h>
+#include <linux/edd.h>
+#include <asm/e820.h>
+#include <asm/ist.h>
+#include <video/edid.h>
+
+/* setup data types */
+#define SETUP_NONE                     0
+#define SETUP_E820_EXT                 1
+#define SETUP_DTB                      2
+#define SETUP_PCI                      3
+
+/* extensible setup data list node */
+struct setup_data {
+       __u64 next;
+       __u32 type;
+       __u32 len;
+       __u8 data[0];
+};
+
+struct setup_header {
+       __u8    setup_sects;
+       __u16   root_flags;
+       __u32   syssize;
+       __u16   ram_size;
+#define RAMDISK_IMAGE_START_MASK       0x07FF
+#define RAMDISK_PROMPT_FLAG            0x8000
+#define RAMDISK_LOAD_FLAG              0x4000
+       __u16   vid_mode;
+       __u16   root_dev;
+       __u16   boot_flag;
+       __u16   jump;
+       __u32   header;
+       __u16   version;
+       __u32   realmode_swtch;
+       __u16   start_sys;
+       __u16   kernel_version;
+       __u8    type_of_loader;
+       __u8    loadflags;
+#define LOADED_HIGH    (1<<0)
+#define QUIET_FLAG     (1<<5)
+#define KEEP_SEGMENTS  (1<<6)
+#define CAN_USE_HEAP   (1<<7)
+       __u16   setup_move_size;
+       __u32   code32_start;
+       __u32   ramdisk_image;
+       __u32   ramdisk_size;
+       __u32   bootsect_kludge;
+       __u16   heap_end_ptr;
+       __u8    ext_loader_ver;
+       __u8    ext_loader_type;
+       __u32   cmd_line_ptr;
+       __u32   initrd_addr_max;
+       __u32   kernel_alignment;
+       __u8    relocatable_kernel;
+       __u8    _pad2[3];
+       __u32   cmdline_size;
+       __u32   hardware_subarch;
+       __u64   hardware_subarch_data;
+       __u32   payload_offset;
+       __u32   payload_length;
+       __u64   setup_data;
+       __u64   pref_address;
+       __u32   init_size;
+       __u32   handover_offset;
+} __attribute__((packed));
+
+struct sys_desc_table {
+       __u16 length;
+       __u8  table[14];
+};
+
+/* Gleaned from OFW's set-parameters in cpu/x86/pc/linux.fth */
+struct olpc_ofw_header {
+       __u32 ofw_magic;        /* OFW signature */
+       __u32 ofw_version;
+       __u32 cif_handler;      /* callback into OFW */
+       __u32 irq_desc_table;
+} __attribute__((packed));
+
+struct efi_info {
+       __u32 efi_loader_signature;
+       __u32 efi_systab;
+       __u32 efi_memdesc_size;
+       __u32 efi_memdesc_version;
+       __u32 efi_memmap;
+       __u32 efi_memmap_size;
+       __u32 efi_systab_hi;
+       __u32 efi_memmap_hi;
+};
+
+/* The so-called "zeropage" */
+struct boot_params {
+       struct screen_info screen_info;                 /* 0x000 */
+       struct apm_bios_info apm_bios_info;             /* 0x040 */
+       __u8  _pad2[4];                                 /* 0x054 */
+       __u64  tboot_addr;                              /* 0x058 */
+       struct ist_info ist_info;                       /* 0x060 */
+       __u8  _pad3[16];                                /* 0x070 */
+       __u8  hd0_info[16];     /* obsolete! */         /* 0x080 */
+       __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */
+       struct sys_desc_table sys_desc_table;           /* 0x0a0 */
+       struct olpc_ofw_header olpc_ofw_header;         /* 0x0b0 */
+       __u8  _pad4[128];                               /* 0x0c0 */
+       struct edid_info edid_info;                     /* 0x140 */
+       struct efi_info efi_info;                       /* 0x1c0 */
+       __u32 alt_mem_k;                                /* 0x1e0 */
+       __u32 scratch;          /* Scratch field! */    /* 0x1e4 */
+       __u8  e820_entries;                             /* 0x1e8 */
+       __u8  eddbuf_entries;                           /* 0x1e9 */
+       __u8  edd_mbr_sig_buf_entries;                  /* 0x1ea */
+       __u8  kbd_status;                               /* 0x1eb */
+       __u8  _pad6[5];                                 /* 0x1ec */
+       struct setup_header hdr;    /* setup header */  /* 0x1f1 */
+       __u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+       __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];      /* 0x290 */
+       struct e820entry e820_map[E820MAX];             /* 0x2d0 */
+       __u8  _pad8[48];                                /* 0xcd0 */
+       struct edd_info eddbuf[EDDMAXNR];               /* 0xd00 */
+       __u8  _pad9[276];                               /* 0xeec */
+} __attribute__((packed));
+
+enum {
+       X86_SUBARCH_PC = 0,
+       X86_SUBARCH_LGUEST,
+       X86_SUBARCH_XEN,
+       X86_SUBARCH_MRST,
+       X86_SUBARCH_CE4100,
+       X86_NR_SUBARCHS,
+};
+
+
+
+#endif /* _ASM_X86_BOOTPARAM_H */
diff --git a/arch/x86/include/uapi/asm/byteorder.h b/arch/x86/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..b13a7a8
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_BYTEORDER_H
+#define _ASM_X86_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_X86_BYTEORDER_H */
diff --git a/arch/x86/include/uapi/asm/debugreg.h b/arch/x86/include/uapi/asm/debugreg.h
new file mode 100644 (file)
index 0000000..3c0874d
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef _UAPI_ASM_X86_DEBUGREG_H
+#define _UAPI_ASM_X86_DEBUGREG_H
+
+
+/* Indicate the register numbers for a number of the specific
+   debug registers.  Registers 0-3 contain the addresses we wish to trap on */
+#define DR_FIRSTADDR 0        /* u_debugreg[DR_FIRSTADDR] */
+#define DR_LASTADDR 3         /* u_debugreg[DR_LASTADDR]  */
+
+#define DR_STATUS 6           /* u_debugreg[DR_STATUS]     */
+#define DR_CONTROL 7          /* u_debugreg[DR_CONTROL] */
+
+/* Define a few things for the status register.  We can use this to determine
+   which debugging register was responsible for the trap.  The other bits
+   are either reserved or not of interest to us. */
+
+/* Define reserved bits in DR6 which are always set to 1 */
+#define DR6_RESERVED   (0xFFFF0FF0)
+
+#define DR_TRAP0       (0x1)           /* db0 */
+#define DR_TRAP1       (0x2)           /* db1 */
+#define DR_TRAP2       (0x4)           /* db2 */
+#define DR_TRAP3       (0x8)           /* db3 */
+#define DR_TRAP_BITS   (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)
+
+#define DR_STEP                (0x4000)        /* single-step */
+#define DR_SWITCH      (0x8000)        /* task switch */
+
+/* Now define a bunch of things for manipulating the control register.
+   The top two bytes of the control register consist of 4 fields of 4
+   bits - each field corresponds to one of the four debug registers,
+   and indicates what types of access we trap on, and how large the data
+   field is that we are looking at */
+
+#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */
+#define DR_CONTROL_SIZE 4   /* 4 control bits per register */
+
+#define DR_RW_EXECUTE (0x0)   /* Settings for the access types to trap on */
+#define DR_RW_WRITE (0x1)
+#define DR_RW_READ (0x3)
+
+#define DR_LEN_1 (0x0) /* Settings for data length to trap on */
+#define DR_LEN_2 (0x4)
+#define DR_LEN_4 (0xC)
+#define DR_LEN_8 (0x8)
+
+/* The low byte to the control register determine which registers are
+   enabled.  There are 4 fields of two bits.  One bit is "local", meaning
+   that the processor will reset the bit after a task switch and the other
+   is global meaning that we have to explicitly reset the bit.  With linux,
+   you can use either one, since we explicitly zero the register when we enter
+   kernel mode. */
+
+#define DR_LOCAL_ENABLE_SHIFT 0    /* Extra shift to the local enable bit */
+#define DR_GLOBAL_ENABLE_SHIFT 1   /* Extra shift to the global enable bit */
+#define DR_LOCAL_ENABLE (0x1)      /* Local enable for reg 0 */
+#define DR_GLOBAL_ENABLE (0x2)     /* Global enable for reg 0 */
+#define DR_ENABLE_SIZE 2           /* 2 enable bits per register */
+
+#define DR_LOCAL_ENABLE_MASK (0x55)  /* Set  local bits for all 4 regs */
+#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */
+
+/* The second byte to the control register has a few special things.
+   We can slow the instruction pipeline for instructions coming via the
+   gdt or the ldt if we want to.  I am not sure why this is an advantage */
+
+#ifdef __i386__
+#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */
+#else
+#define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */
+#endif
+
+#define DR_LOCAL_SLOWDOWN (0x100)   /* Local slow the pipeline */
+#define DR_GLOBAL_SLOWDOWN (0x200)  /* Global slow the pipeline */
+
+/*
+ * HW breakpoint additions
+ */
+
+#endif /* _UAPI_ASM_X86_DEBUGREG_H */
diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h
new file mode 100644 (file)
index 0000000..bbae024
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef _UAPI_ASM_X86_E820_H
+#define _UAPI_ASM_X86_E820_H
+#define E820MAP        0x2d0           /* our map */
+#define E820MAX        128             /* number of entries in E820MAP */
+
+/*
+ * Legacy E820 BIOS limits us to 128 (E820MAX) nodes due to the
+ * constrained space in the zeropage.  If we have more nodes than
+ * that, and if we've booted off EFI firmware, then the EFI tables
+ * passed us from the EFI firmware can list more nodes.  Size our
+ * internal memory map tables to have room for these additional
+ * nodes, based on up to three entries per node for which the
+ * kernel was built: MAX_NUMNODES == (1 << CONFIG_NODES_SHIFT),
+ * plus E820MAX, allowing space for the possible duplicate E820
+ * entries that might need room in the same arrays, prior to the
+ * call to sanitize_e820_map() to remove duplicates.  The allowance
+ * of three memory map entries per node is "enough" entries for
+ * the initial hardware platform motivating this mechanism to make
+ * use of additional EFI map entries.  Future platforms may want
+ * to allow more than three entries per node or otherwise refine
+ * this size.
+ */
+
+/*
+ * Odd: 'make headers_check' complains about numa.h if I try
+ * to collapse the next two #ifdef lines to a single line:
+ *     #if defined(__KERNEL__) && defined(CONFIG_EFI)
+ */
+#ifndef __KERNEL__
+#define E820_X_MAX E820MAX
+#endif
+
+#define E820NR 0x1e8           /* # entries in E820MAP */
+
+#define E820_RAM       1
+#define E820_RESERVED  2
+#define E820_ACPI      3
+#define E820_NVS       4
+#define E820_UNUSABLE  5
+
+
+/*
+ * reserved RAM used by kernel itself
+ * if CONFIG_INTEL_TXT is enabled, memory of this type will be
+ * included in the S3 integrity calculation and so should not include
+ * any memory that BIOS might alter over the S3 transition
+ */
+#define E820_RESERVED_KERN        128
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+struct e820entry {
+       __u64 addr;     /* start of memory segment */
+       __u64 size;     /* size of memory segment */
+       __u32 type;     /* type of memory segment */
+} __attribute__((packed));
+
+struct e820map {
+       __u32 nr_map;
+       struct e820entry map[E820_X_MAX];
+};
+
+#define ISA_START_ADDRESS      0xa0000
+#define ISA_END_ADDRESS                0x100000
+
+#define BIOS_BEGIN             0x000a0000
+#define BIOS_END               0x00100000
+
+#define BIOS_ROM_BASE          0xffe00000
+#define BIOS_ROM_END           0xffffffff
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* _UAPI_ASM_X86_E820_H */
diff --git a/arch/x86/include/uapi/asm/errno.h b/arch/x86/include/uapi/asm/errno.h
new file mode 100644 (file)
index 0000000..4c82b50
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/x86/include/uapi/asm/fcntl.h b/arch/x86/include/uapi/asm/fcntl.h
new file mode 100644 (file)
index 0000000..46ab12d
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/fcntl.h>
diff --git a/arch/x86/include/uapi/asm/hw_breakpoint.h b/arch/x86/include/uapi/asm/hw_breakpoint.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
new file mode 100644 (file)
index 0000000..b80420b
--- /dev/null
@@ -0,0 +1,194 @@
+#ifndef _ASM_X86_HYPERV_H
+#define _ASM_X86_HYPERV_H
+
+#include <linux/types.h>
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
+ */
+#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS  0x40000000
+#define HYPERV_CPUID_INTERFACE                 0x40000001
+#define HYPERV_CPUID_VERSION                   0x40000002
+#define HYPERV_CPUID_FEATURES                  0x40000003
+#define HYPERV_CPUID_ENLIGHTMENT_INFO          0x40000004
+#define HYPERV_CPUID_IMPLEMENT_LIMITS          0x40000005
+
+#define HYPERV_HYPERVISOR_PRESENT_BIT          0x80000000
+#define HYPERV_CPUID_MIN                       0x40000005
+#define HYPERV_CPUID_MAX                       0x4000ffff
+
+/*
+ * Feature identification. EAX indicates which features are available
+ * to the partition based upon the current partition privileges.
+ */
+
+/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
+#define HV_X64_MSR_VP_RUNTIME_AVAILABLE                (1 << 0)
+/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
+#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE    (1 << 1)
+/*
+ * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
+ * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
+ */
+#define HV_X64_MSR_SYNIC_AVAILABLE             (1 << 2)
+/*
+ * Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
+ * HV_X64_MSR_STIMER3_COUNT) available
+ */
+#define HV_X64_MSR_SYNTIMER_AVAILABLE          (1 << 3)
+/*
+ * APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * are available
+ */
+#define HV_X64_MSR_APIC_ACCESS_AVAILABLE       (1 << 4)
+/* Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL) available*/
+#define HV_X64_MSR_HYPERCALL_AVAILABLE         (1 << 5)
+/* Access virtual processor index MSR (HV_X64_MSR_VP_INDEX) available*/
+#define HV_X64_MSR_VP_INDEX_AVAILABLE          (1 << 6)
+/* Virtual system reset MSR (HV_X64_MSR_RESET) is available*/
+#define HV_X64_MSR_RESET_AVAILABLE             (1 << 7)
+ /*
+  * Access statistics pages MSRs (HV_X64_MSR_STATS_PARTITION_RETAIL_PAGE,
+  * HV_X64_MSR_STATS_PARTITION_INTERNAL_PAGE, HV_X64_MSR_STATS_VP_RETAIL_PAGE,
+  * HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available
+  */
+#define HV_X64_MSR_STAT_PAGES_AVAILABLE                (1 << 8)
+
+/*
+ * Feature identification: EBX indicates which flags were specified at
+ * partition creation. The format is the same as the partition creation
+ * flag structure defined in section Partition Creation Flags.
+ */
+#define HV_X64_CREATE_PARTITIONS               (1 << 0)
+#define HV_X64_ACCESS_PARTITION_ID             (1 << 1)
+#define HV_X64_ACCESS_MEMORY_POOL              (1 << 2)
+#define HV_X64_ADJUST_MESSAGE_BUFFERS          (1 << 3)
+#define HV_X64_POST_MESSAGES                   (1 << 4)
+#define HV_X64_SIGNAL_EVENTS                   (1 << 5)
+#define HV_X64_CREATE_PORT                     (1 << 6)
+#define HV_X64_CONNECT_PORT                    (1 << 7)
+#define HV_X64_ACCESS_STATS                    (1 << 8)
+#define HV_X64_DEBUGGING                       (1 << 11)
+#define HV_X64_CPU_POWER_MANAGEMENT            (1 << 12)
+#define HV_X64_CONFIGURE_PROFILER              (1 << 13)
+
+/*
+ * Feature identification. EDX indicates which miscellaneous features
+ * are available to the partition.
+ */
+/* The MWAIT instruction is available (per section MONITOR / MWAIT) */
+#define HV_X64_MWAIT_AVAILABLE                         (1 << 0)
+/* Guest debugging support is available */
+#define HV_X64_GUEST_DEBUGGING_AVAILABLE               (1 << 1)
+/* Performance Monitor support is available*/
+#define HV_X64_PERF_MONITOR_AVAILABLE                  (1 << 2)
+/* Support for physical CPU dynamic partitioning events is available*/
+#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE      (1 << 3)
+/*
+ * Support for passing hypercall input parameter block via XMM
+ * registers is available
+ */
+#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE          (1 << 4)
+/* Support for a virtual guest idle state is available */
+#define HV_X64_GUEST_IDLE_STATE_AVAILABLE              (1 << 5)
+
+/*
+ * Implementation recommendations. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal performance.
+ */
+ /*
+  * Recommend using hypercall for address space switches rather
+  * than MOV to CR3 instruction
+  */
+#define HV_X64_MWAIT_RECOMMENDED               (1 << 0)
+/* Recommend using hypercall for local TLB flushes rather
+ * than INVLPG or MOV to CR3 instructions */
+#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED     (1 << 1)
+/*
+ * Recommend using hypercall for remote TLB flushes rather
+ * than inter-processor interrupts
+ */
+#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED    (1 << 2)
+/*
+ * Recommend using MSRs for accessing APIC registers
+ * EOI, ICR and TPR rather than their memory-mapped counterparts
+ */
+#define HV_X64_APIC_ACCESS_RECOMMENDED         (1 << 3)
+/* Recommend using the hypervisor-provided MSR to initiate a system RESET */
+#define HV_X64_SYSTEM_RESET_RECOMMENDED                (1 << 4)
+/*
+ * Recommend using relaxed timing for this partition. If used,
+ * the VM should disable any watchdog timeouts that rely on the
+ * timely delivery of external interrupts
+ */
+#define HV_X64_RELAXED_TIMING_RECOMMENDED      (1 << 5)
+
+/* MSR used to identify the guest OS. */
+#define HV_X64_MSR_GUEST_OS_ID                 0x40000000
+
+/* MSR used to setup pages used to communicate with the hypervisor. */
+#define HV_X64_MSR_HYPERCALL                   0x40000001
+
+/* MSR used to provide vcpu index */
+#define HV_X64_MSR_VP_INDEX                    0x40000002
+
+/* MSR used to read the per-partition time reference counter */
+#define HV_X64_MSR_TIME_REF_COUNT              0x40000020
+
+/* Define the virtual APIC registers */
+#define HV_X64_MSR_EOI                         0x40000070
+#define HV_X64_MSR_ICR                         0x40000071
+#define HV_X64_MSR_TPR                         0x40000072
+#define HV_X64_MSR_APIC_ASSIST_PAGE            0x40000073
+
+/* Define synthetic interrupt controller model specific registers. */
+#define HV_X64_MSR_SCONTROL                    0x40000080
+#define HV_X64_MSR_SVERSION                    0x40000081
+#define HV_X64_MSR_SIEFP                       0x40000082
+#define HV_X64_MSR_SIMP                                0x40000083
+#define HV_X64_MSR_EOM                         0x40000084
+#define HV_X64_MSR_SINT0                       0x40000090
+#define HV_X64_MSR_SINT1                       0x40000091
+#define HV_X64_MSR_SINT2                       0x40000092
+#define HV_X64_MSR_SINT3                       0x40000093
+#define HV_X64_MSR_SINT4                       0x40000094
+#define HV_X64_MSR_SINT5                       0x40000095
+#define HV_X64_MSR_SINT6                       0x40000096
+#define HV_X64_MSR_SINT7                       0x40000097
+#define HV_X64_MSR_SINT8                       0x40000098
+#define HV_X64_MSR_SINT9                       0x40000099
+#define HV_X64_MSR_SINT10                      0x4000009A
+#define HV_X64_MSR_SINT11                      0x4000009B
+#define HV_X64_MSR_SINT12                      0x4000009C
+#define HV_X64_MSR_SINT13                      0x4000009D
+#define HV_X64_MSR_SINT14                      0x4000009E
+#define HV_X64_MSR_SINT15                      0x4000009F
+
+
+#define HV_X64_MSR_HYPERCALL_ENABLE            0x00000001
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT        12
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK \
+               (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
+
+/* Declare the various hypercall operations. */
+#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT                0x0008
+
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE             0x00000001
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT      12
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK       \
+               (~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
+
+#define HV_PROCESSOR_POWER_STATE_C0            0
+#define HV_PROCESSOR_POWER_STATE_C1            1
+#define HV_PROCESSOR_POWER_STATE_C2            2
+#define HV_PROCESSOR_POWER_STATE_C3            3
+
+/* hypercall status code */
+#define HV_STATUS_SUCCESS                      0
+#define HV_STATUS_INVALID_HYPERCALL_CODE       2
+#define HV_STATUS_INVALID_HYPERCALL_INPUT      3
+#define HV_STATUS_INVALID_ALIGNMENT            4
+#define HV_STATUS_INSUFFICIENT_BUFFERS         19
+
+#endif
diff --git a/arch/x86/include/uapi/asm/ioctl.h b/arch/x86/include/uapi/asm/ioctl.h
new file mode 100644 (file)
index 0000000..b279fe0
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/x86/include/uapi/asm/ioctls.h b/arch/x86/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..ec34c76
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ioctls.h>
diff --git a/arch/x86/include/uapi/asm/ipcbuf.h b/arch/x86/include/uapi/asm/ipcbuf.h
new file mode 100644 (file)
index 0000000..84c7e51
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/ipcbuf.h>
diff --git a/arch/x86/include/uapi/asm/ist.h b/arch/x86/include/uapi/asm/ist.h
new file mode 100644 (file)
index 0000000..bad9f5e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Include file for the interface to IST BIOS
+ * Copyright 2002 Andy Grover <andrew.grover@intel.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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef _UAPI_ASM_X86_IST_H
+#define _UAPI_ASM_X86_IST_H
+
+
+
+#include <linux/types.h>
+
+struct ist_info {
+       __u32 signature;
+       __u32 command;
+       __u32 event;
+       __u32 perf_level;
+};
+
+#endif /* _UAPI_ASM_X86_IST_H */
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
new file mode 100644 (file)
index 0000000..a65ec29
--- /dev/null
@@ -0,0 +1,346 @@
+#ifndef _ASM_X86_KVM_H
+#define _ASM_X86_KVM_H
+
+/*
+ * KVM x86 specific structures and definitions
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define DE_VECTOR 0
+#define DB_VECTOR 1
+#define BP_VECTOR 3
+#define OF_VECTOR 4
+#define BR_VECTOR 5
+#define UD_VECTOR 6
+#define NM_VECTOR 7
+#define DF_VECTOR 8
+#define TS_VECTOR 10
+#define NP_VECTOR 11
+#define SS_VECTOR 12
+#define GP_VECTOR 13
+#define PF_VECTOR 14
+#define MF_VECTOR 16
+#define MC_VECTOR 18
+
+/* Select x86 specific features in <linux/kvm.h> */
+#define __KVM_HAVE_PIT
+#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_IRQ_LINE
+#define __KVM_HAVE_DEVICE_ASSIGNMENT
+#define __KVM_HAVE_MSI
+#define __KVM_HAVE_USER_NMI
+#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_MSIX
+#define __KVM_HAVE_MCE
+#define __KVM_HAVE_PIT_STATE2
+#define __KVM_HAVE_XEN_HVM
+#define __KVM_HAVE_VCPU_EVENTS
+#define __KVM_HAVE_DEBUGREGS
+#define __KVM_HAVE_XSAVE
+#define __KVM_HAVE_XCRS
+#define __KVM_HAVE_READONLY_MEM
+
+/* Architectural interrupt line count. */
+#define KVM_NR_INTERRUPTS 256
+
+struct kvm_memory_alias {
+       __u32 slot;  /* this has a different namespace than memory slots */
+       __u32 flags;
+       __u64 guest_phys_addr;
+       __u64 memory_size;
+       __u64 target_phys_addr;
+};
+
+/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
+struct kvm_pic_state {
+       __u8 last_irr;  /* edge detection */
+       __u8 irr;               /* interrupt request register */
+       __u8 imr;               /* interrupt mask register */
+       __u8 isr;               /* interrupt service register */
+       __u8 priority_add;      /* highest irq priority */
+       __u8 irq_base;
+       __u8 read_reg_select;
+       __u8 poll;
+       __u8 special_mask;
+       __u8 init_state;
+       __u8 auto_eoi;
+       __u8 rotate_on_auto_eoi;
+       __u8 special_fully_nested_mode;
+       __u8 init4;             /* true if 4 byte init */
+       __u8 elcr;              /* PIIX edge/trigger selection */
+       __u8 elcr_mask;
+};
+
+#define KVM_IOAPIC_NUM_PINS  24
+struct kvm_ioapic_state {
+       __u64 base_address;
+       __u32 ioregsel;
+       __u32 id;
+       __u32 irr;
+       __u32 pad;
+       union {
+               __u64 bits;
+               struct {
+                       __u8 vector;
+                       __u8 delivery_mode:3;
+                       __u8 dest_mode:1;
+                       __u8 delivery_status:1;
+                       __u8 polarity:1;
+                       __u8 remote_irr:1;
+                       __u8 trig_mode:1;
+                       __u8 mask:1;
+                       __u8 reserve:7;
+                       __u8 reserved[4];
+                       __u8 dest_id;
+               } fields;
+       } redirtbl[KVM_IOAPIC_NUM_PINS];
+};
+
+#define KVM_IRQCHIP_PIC_MASTER   0
+#define KVM_IRQCHIP_PIC_SLAVE    1
+#define KVM_IRQCHIP_IOAPIC       2
+#define KVM_NR_IRQCHIPS          3
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 rax, rbx, rcx, rdx;
+       __u64 rsi, rdi, rsp, rbp;
+       __u64 r8,  r9,  r10, r11;
+       __u64 r12, r13, r14, r15;
+       __u64 rip, rflags;
+};
+
+/* for KVM_GET_LAPIC and KVM_SET_LAPIC */
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+       char regs[KVM_APIC_REG_SIZE];
+};
+
+struct kvm_segment {
+       __u64 base;
+       __u32 limit;
+       __u16 selector;
+       __u8  type;
+       __u8  present, dpl, db, s, l, g, avl;
+       __u8  unusable;
+       __u8  padding;
+};
+
+struct kvm_dtable {
+       __u64 base;
+       __u16 limit;
+       __u16 padding[3];
+};
+
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+       /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
+       struct kvm_segment cs, ds, es, fs, gs, ss;
+       struct kvm_segment tr, ldt;
+       struct kvm_dtable gdt, idt;
+       __u64 cr0, cr2, cr3, cr4, cr8;
+       __u64 efer;
+       __u64 apic_base;
+       __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
+};
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u8  fpr[8][16];
+       __u16 fcw;
+       __u16 fsw;
+       __u8  ftwx;  /* in fxsave format */
+       __u8  pad1;
+       __u16 last_opcode;
+       __u64 last_ip;
+       __u64 last_dp;
+       __u8  xmm[16][16];
+       __u32 mxcsr;
+       __u32 pad2;
+};
+
+struct kvm_msr_entry {
+       __u32 index;
+       __u32 reserved;
+       __u64 data;
+};
+
+/* for KVM_GET_MSRS and KVM_SET_MSRS */
+struct kvm_msrs {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 pad;
+
+       struct kvm_msr_entry entries[0];
+};
+
+/* for KVM_GET_MSR_INDEX_LIST */
+struct kvm_msr_list {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 indices[0];
+};
+
+
+struct kvm_cpuid_entry {
+       __u32 function;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding;
+};
+
+/* for KVM_SET_CPUID */
+struct kvm_cpuid {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry entries[0];
+};
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
+#define KVM_CPUID_FLAG_STATEFUL_FUNC    2
+#define KVM_CPUID_FLAG_STATE_READ_NEXT  4
+
+/* for KVM_SET_CPUID2 */
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+/* for KVM_GET_PIT and KVM_SET_PIT */
+struct kvm_pit_channel_state {
+       __u32 count; /* can be 65536 */
+       __u16 latched_count;
+       __u8 count_latched;
+       __u8 status_latched;
+       __u8 status;
+       __u8 read_state;
+       __u8 write_state;
+       __u8 write_latch;
+       __u8 rw_mode;
+       __u8 mode;
+       __u8 bcd;
+       __u8 gate;
+       __s64 count_load_time;
+};
+
+struct kvm_debug_exit_arch {
+       __u32 exception;
+       __u32 pad;
+       __u64 pc;
+       __u64 dr6;
+       __u64 dr7;
+};
+
+#define KVM_GUESTDBG_USE_SW_BP         0x00010000
+#define KVM_GUESTDBG_USE_HW_BP         0x00020000
+#define KVM_GUESTDBG_INJECT_DB         0x00040000
+#define KVM_GUESTDBG_INJECT_BP         0x00080000
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+       __u64 debugreg[8];
+};
+
+struct kvm_pit_state {
+       struct kvm_pit_channel_state channels[3];
+};
+
+#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
+
+struct kvm_pit_state2 {
+       struct kvm_pit_channel_state channels[3];
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+struct kvm_reinject_control {
+       __u8 pit_reinject;
+       __u8 reserved[31];
+};
+
+/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */
+#define KVM_VCPUEVENT_VALID_NMI_PENDING        0x00000001
+#define KVM_VCPUEVENT_VALID_SIPI_VECTOR        0x00000002
+#define KVM_VCPUEVENT_VALID_SHADOW     0x00000004
+
+/* Interrupt shadow states */
+#define KVM_X86_SHADOW_INT_MOV_SS      0x01
+#define KVM_X86_SHADOW_INT_STI         0x02
+
+/* for KVM_GET/SET_VCPU_EVENTS */
+struct kvm_vcpu_events {
+       struct {
+               __u8 injected;
+               __u8 nr;
+               __u8 has_error_code;
+               __u8 pad;
+               __u32 error_code;
+       } exception;
+       struct {
+               __u8 injected;
+               __u8 nr;
+               __u8 soft;
+               __u8 shadow;
+       } interrupt;
+       struct {
+               __u8 injected;
+               __u8 pending;
+               __u8 masked;
+               __u8 pad;
+       } nmi;
+       __u32 sipi_vector;
+       __u32 flags;
+       __u32 reserved[10];
+};
+
+/* for KVM_GET/SET_DEBUGREGS */
+struct kvm_debugregs {
+       __u64 db[4];
+       __u64 dr6;
+       __u64 dr7;
+       __u64 flags;
+       __u64 reserved[9];
+};
+
+/* for KVM_CAP_XSAVE */
+struct kvm_xsave {
+       __u32 region[1024];
+};
+
+#define KVM_MAX_XCRS   16
+
+struct kvm_xcr {
+       __u32 xcr;
+       __u32 reserved;
+       __u64 value;
+};
+
+struct kvm_xcrs {
+       __u32 nr_xcrs;
+       __u32 flags;
+       struct kvm_xcr xcrs[KVM_MAX_XCRS];
+       __u64 padding[16];
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+#endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..06fdbd9
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef _UAPI_ASM_X86_KVM_PARA_H
+#define _UAPI_ASM_X86_KVM_PARA_H
+
+#include <linux/types.h>
+#include <asm/hyperv.h>
+
+/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
+ * should be used to determine that a VM is running under KVM.
+ */
+#define KVM_CPUID_SIGNATURE    0x40000000
+
+/* This CPUID returns a feature bitmap in eax.  Before enabling a particular
+ * paravirtualization, the appropriate feature bit should be checked.
+ */
+#define KVM_CPUID_FEATURES     0x40000001
+#define KVM_FEATURE_CLOCKSOURCE                0
+#define KVM_FEATURE_NOP_IO_DELAY       1
+#define KVM_FEATURE_MMU_OP             2
+/* This indicates that the new set of kvmclock msrs
+ * are available. The use of 0x11 and 0x12 is deprecated
+ */
+#define KVM_FEATURE_CLOCKSOURCE2        3
+#define KVM_FEATURE_ASYNC_PF           4
+#define KVM_FEATURE_STEAL_TIME         5
+#define KVM_FEATURE_PV_EOI             6
+
+/* The last 8 bits are used to indicate how to interpret the flags field
+ * in pvclock structure. If no bits are set, all flags are ignored.
+ */
+#define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT     24
+
+#define MSR_KVM_WALL_CLOCK  0x11
+#define MSR_KVM_SYSTEM_TIME 0x12
+
+#define KVM_MSR_ENABLED 1
+/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
+#define MSR_KVM_WALL_CLOCK_NEW  0x4b564d00
+#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
+#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
+#define MSR_KVM_STEAL_TIME  0x4b564d03
+#define MSR_KVM_PV_EOI_EN      0x4b564d04
+
+struct kvm_steal_time {
+       __u64 steal;
+       __u32 version;
+       __u32 flags;
+       __u32 pad[12];
+};
+
+#define KVM_STEAL_ALIGNMENT_BITS 5
+#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
+#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
+
+#define KVM_MAX_MMU_OP_BATCH           32
+
+#define KVM_ASYNC_PF_ENABLED                   (1 << 0)
+#define KVM_ASYNC_PF_SEND_ALWAYS               (1 << 1)
+
+/* Operations for KVM_HC_MMU_OP */
+#define KVM_MMU_OP_WRITE_PTE            1
+#define KVM_MMU_OP_FLUSH_TLB           2
+#define KVM_MMU_OP_RELEASE_PT          3
+
+/* Payload for KVM_HC_MMU_OP */
+struct kvm_mmu_op_header {
+       __u32 op;
+       __u32 pad;
+};
+
+struct kvm_mmu_op_write_pte {
+       struct kvm_mmu_op_header header;
+       __u64 pte_phys;
+       __u64 pte_val;
+};
+
+struct kvm_mmu_op_flush_tlb {
+       struct kvm_mmu_op_header header;
+};
+
+struct kvm_mmu_op_release_pt {
+       struct kvm_mmu_op_header header;
+       __u64 pt_phys;
+};
+
+#define KVM_PV_REASON_PAGE_NOT_PRESENT 1
+#define KVM_PV_REASON_PAGE_READY 2
+
+struct kvm_vcpu_pv_apf_data {
+       __u32 reason;
+       __u8 pad[60];
+       __u32 enabled;
+};
+
+#define KVM_PV_EOI_BIT 0
+#define KVM_PV_EOI_MASK (0x1 << KVM_PV_EOI_BIT)
+#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
+#define KVM_PV_EOI_DISABLED 0x0
+
+
+#endif /* _UAPI_ASM_X86_KVM_PARA_H */
diff --git a/arch/x86/include/uapi/asm/ldt.h b/arch/x86/include/uapi/asm/ldt.h
new file mode 100644 (file)
index 0000000..46727eb
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * ldt.h
+ *
+ * Definitions of structures used with the modify_ldt system call.
+ */
+#ifndef _ASM_X86_LDT_H
+#define _ASM_X86_LDT_H
+
+/* Maximum number of LDT entries supported. */
+#define LDT_ENTRIES    8192
+/* The size of each LDT entry. */
+#define LDT_ENTRY_SIZE 8
+
+#ifndef __ASSEMBLY__
+/*
+ * Note on 64bit base and limit is ignored and you cannot set DS/ES/CS
+ * not to the default values if you still want to do syscalls. This
+ * call is more for 32bit mode therefore.
+ */
+struct user_desc {
+       unsigned int  entry_number;
+       unsigned int  base_addr;
+       unsigned int  limit;
+       unsigned int  seg_32bit:1;
+       unsigned int  contents:2;
+       unsigned int  read_exec_only:1;
+       unsigned int  limit_in_pages:1;
+       unsigned int  seg_not_present:1;
+       unsigned int  useable:1;
+#ifdef __x86_64__
+       unsigned int  lm:1;
+#endif
+};
+
+#define MODIFY_LDT_CONTENTS_DATA       0
+#define MODIFY_LDT_CONTENTS_STACK      1
+#define MODIFY_LDT_CONTENTS_CODE       2
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_X86_LDT_H */
diff --git a/arch/x86/include/uapi/asm/mce.h b/arch/x86/include/uapi/asm/mce.h
new file mode 100644 (file)
index 0000000..58c8298
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef _UAPI_ASM_X86_MCE_H
+#define _UAPI_ASM_X86_MCE_H
+
+#include <linux/types.h>
+#include <asm/ioctls.h>
+
+/*
+ * Machine Check support for x86
+ */
+
+/* MCG_CAP register defines */
+#define MCG_BANKCNT_MASK       0xff         /* Number of Banks */
+#define MCG_CTL_P              (1ULL<<8)    /* MCG_CTL register available */
+#define MCG_EXT_P              (1ULL<<9)    /* Extended registers available */
+#define MCG_CMCI_P             (1ULL<<10)   /* CMCI supported */
+#define MCG_EXT_CNT_MASK       0xff0000     /* Number of Extended registers */
+#define MCG_EXT_CNT_SHIFT      16
+#define MCG_EXT_CNT(c)         (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
+#define MCG_SER_P              (1ULL<<24)   /* MCA recovery/new status bits */
+
+/* MCG_STATUS register defines */
+#define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
+#define MCG_STATUS_EIPV  (1ULL<<1)   /* ip points to correct instruction */
+#define MCG_STATUS_MCIP  (1ULL<<2)   /* machine check in progress */
+
+/* MCi_STATUS register defines */
+#define MCI_STATUS_VAL   (1ULL<<63)  /* valid error */
+#define MCI_STATUS_OVER  (1ULL<<62)  /* previous errors lost */
+#define MCI_STATUS_UC    (1ULL<<61)  /* uncorrected error */
+#define MCI_STATUS_EN    (1ULL<<60)  /* error enabled */
+#define MCI_STATUS_MISCV (1ULL<<59)  /* misc error reg. valid */
+#define MCI_STATUS_ADDRV (1ULL<<58)  /* addr reg. valid */
+#define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */
+#define MCI_STATUS_S    (1ULL<<56)  /* Signaled machine check */
+#define MCI_STATUS_AR   (1ULL<<55)  /* Action required */
+#define MCACOD           0xffff     /* MCA Error Code */
+
+/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */
+#define MCACOD_SCRUB   0x00C0  /* 0xC0-0xCF Memory Scrubbing */
+#define MCACOD_SCRUBMSK        0xfff0
+#define MCACOD_L3WB    0x017A  /* L3 Explicit Writeback */
+#define MCACOD_DATA    0x0134  /* Data Load */
+#define MCACOD_INSTR   0x0150  /* Instruction Fetch */
+
+/* MCi_MISC register defines */
+#define MCI_MISC_ADDR_LSB(m)   ((m) & 0x3f)
+#define MCI_MISC_ADDR_MODE(m)  (((m) >> 6) & 7)
+#define  MCI_MISC_ADDR_SEGOFF  0       /* segment offset */
+#define  MCI_MISC_ADDR_LINEAR  1       /* linear address */
+#define  MCI_MISC_ADDR_PHYS    2       /* physical address */
+#define  MCI_MISC_ADDR_MEM     3       /* memory address */
+#define  MCI_MISC_ADDR_GENERIC 7       /* generic */
+
+/* CTL2 register defines */
+#define MCI_CTL2_CMCI_EN               (1ULL << 30)
+#define MCI_CTL2_CMCI_THRESHOLD_MASK   0x7fffULL
+
+#define MCJ_CTX_MASK           3
+#define MCJ_CTX(flags)         ((flags) & MCJ_CTX_MASK)
+#define MCJ_CTX_RANDOM         0    /* inject context: random */
+#define MCJ_CTX_PROCESS                0x1  /* inject context: process */
+#define MCJ_CTX_IRQ            0x2  /* inject context: IRQ */
+#define MCJ_NMI_BROADCAST      0x4  /* do NMI broadcasting */
+#define MCJ_EXCEPTION          0x8  /* raise as exception */
+#define MCJ_IRQ_BRAODCAST      0x10 /* do IRQ broadcasting */
+
+/* Fields are zero when not available */
+struct mce {
+       __u64 status;
+       __u64 misc;
+       __u64 addr;
+       __u64 mcgstatus;
+       __u64 ip;
+       __u64 tsc;      /* cpu time stamp counter */
+       __u64 time;     /* wall time_t when error was detected */
+       __u8  cpuvendor;        /* cpu vendor as encoded in system.h */
+       __u8  inject_flags;     /* software inject flags */
+       __u16  pad;
+       __u32 cpuid;    /* CPUID 1 EAX */
+       __u8  cs;               /* code segment */
+       __u8  bank;     /* machine check bank */
+       __u8  cpu;      /* cpu number; obsolete; use extcpu now */
+       __u8  finished;   /* entry is valid */
+       __u32 extcpu;   /* linux cpu number that detected the error */
+       __u32 socketid; /* CPU socket ID */
+       __u32 apicid;   /* CPU initial apic ID */
+       __u64 mcgcap;   /* MCGCAP MSR: machine check capabilities of CPU */
+};
+
+/*
+ * This structure contains all data related to the MCE log.  Also
+ * carries a signature to make it easier to find from external
+ * debugging tools.  Each entry is only valid when its finished flag
+ * is set.
+ */
+
+#define MCE_LOG_LEN 32
+
+struct mce_log {
+       char signature[12]; /* "MACHINECHECK" */
+       unsigned len;       /* = MCE_LOG_LEN */
+       unsigned next;
+       unsigned flags;
+       unsigned recordlen;     /* length of struct mce */
+       struct mce entry[MCE_LOG_LEN];
+};
+
+#define MCE_OVERFLOW 0         /* bit 0 in flags means overflow */
+
+#define MCE_LOG_SIGNATURE      "MACHINECHECK"
+
+#define MCE_GET_RECORD_LEN   _IOR('M', 1, int)
+#define MCE_GET_LOG_LEN      _IOR('M', 2, int)
+#define MCE_GETCLEAR_FLAGS   _IOR('M', 3, int)
+
+/* Software defined banks */
+#define MCE_EXTENDED_BANK      128
+#define MCE_THERMAL_BANK       MCE_EXTENDED_BANK + 0
+#define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)
+
+#endif /* _UAPI_ASM_X86_MCE_H */
diff --git a/arch/x86/include/uapi/asm/mman.h b/arch/x86/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..513b05f
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _ASM_X86_MMAN_H
+#define _ASM_X86_MMAN_H
+
+#define MAP_32BIT      0x40            /* only give out 32bit addresses */
+
+#define MAP_HUGE_2MB    (21 << MAP_HUGE_SHIFT)
+#define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)
+
+#include <asm-generic/mman.h>
+
+#endif /* _ASM_X86_MMAN_H */
diff --git a/arch/x86/include/uapi/asm/msgbuf.h b/arch/x86/include/uapi/asm/msgbuf.h
new file mode 100644 (file)
index 0000000..809134c
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/msgbuf.h>
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
new file mode 100644 (file)
index 0000000..6e930b2
--- /dev/null
@@ -0,0 +1,488 @@
+#ifndef _ASM_X86_MSR_INDEX_H
+#define _ASM_X86_MSR_INDEX_H
+
+/* CPU model specific register (MSR) numbers */
+
+/* x86-64 specific MSRs */
+#define MSR_EFER               0xc0000080 /* extended feature register */
+#define MSR_STAR               0xc0000081 /* legacy mode SYSCALL target */
+#define MSR_LSTAR              0xc0000082 /* long mode SYSCALL target */
+#define MSR_CSTAR              0xc0000083 /* compat mode SYSCALL target */
+#define MSR_SYSCALL_MASK       0xc0000084 /* EFLAGS mask for syscall */
+#define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
+#define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
+#define MSR_KERNEL_GS_BASE     0xc0000102 /* SwapGS GS shadow */
+#define MSR_TSC_AUX            0xc0000103 /* Auxiliary TSC */
+
+/* EFER bits: */
+#define _EFER_SCE              0  /* SYSCALL/SYSRET */
+#define _EFER_LME              8  /* Long mode enable */
+#define _EFER_LMA              10 /* Long mode active (read-only) */
+#define _EFER_NX               11 /* No execute enable */
+#define _EFER_SVME             12 /* Enable virtualization */
+#define _EFER_LMSLE            13 /* Long Mode Segment Limit Enable */
+#define _EFER_FFXSR            14 /* Enable Fast FXSAVE/FXRSTOR */
+
+#define EFER_SCE               (1<<_EFER_SCE)
+#define EFER_LME               (1<<_EFER_LME)
+#define EFER_LMA               (1<<_EFER_LMA)
+#define EFER_NX                        (1<<_EFER_NX)
+#define EFER_SVME              (1<<_EFER_SVME)
+#define EFER_LMSLE             (1<<_EFER_LMSLE)
+#define EFER_FFXSR             (1<<_EFER_FFXSR)
+
+/* Intel MSRs. Some also available on other CPUs */
+#define MSR_IA32_PERFCTR0              0x000000c1
+#define MSR_IA32_PERFCTR1              0x000000c2
+#define MSR_FSB_FREQ                   0x000000cd
+
+#define MSR_NHM_SNB_PKG_CST_CFG_CTL    0x000000e2
+#define NHM_C3_AUTO_DEMOTE             (1UL << 25)
+#define NHM_C1_AUTO_DEMOTE             (1UL << 26)
+#define ATM_LNC_C6_AUTO_DEMOTE         (1UL << 25)
+
+#define MSR_MTRRcap                    0x000000fe
+#define MSR_IA32_BBL_CR_CTL            0x00000119
+#define MSR_IA32_BBL_CR_CTL3           0x0000011e
+
+#define MSR_IA32_SYSENTER_CS           0x00000174
+#define MSR_IA32_SYSENTER_ESP          0x00000175
+#define MSR_IA32_SYSENTER_EIP          0x00000176
+
+#define MSR_IA32_MCG_CAP               0x00000179
+#define MSR_IA32_MCG_STATUS            0x0000017a
+#define MSR_IA32_MCG_CTL               0x0000017b
+
+#define MSR_OFFCORE_RSP_0              0x000001a6
+#define MSR_OFFCORE_RSP_1              0x000001a7
+
+#define MSR_LBR_SELECT                 0x000001c8
+#define MSR_LBR_TOS                    0x000001c9
+#define MSR_LBR_NHM_FROM               0x00000680
+#define MSR_LBR_NHM_TO                 0x000006c0
+#define MSR_LBR_CORE_FROM              0x00000040
+#define MSR_LBR_CORE_TO                        0x00000060
+
+#define MSR_IA32_PEBS_ENABLE           0x000003f1
+#define MSR_IA32_DS_AREA               0x00000600
+#define MSR_IA32_PERF_CAPABILITIES     0x00000345
+
+#define MSR_MTRRfix64K_00000           0x00000250
+#define MSR_MTRRfix16K_80000           0x00000258
+#define MSR_MTRRfix16K_A0000           0x00000259
+#define MSR_MTRRfix4K_C0000            0x00000268
+#define MSR_MTRRfix4K_C8000            0x00000269
+#define MSR_MTRRfix4K_D0000            0x0000026a
+#define MSR_MTRRfix4K_D8000            0x0000026b
+#define MSR_MTRRfix4K_E0000            0x0000026c
+#define MSR_MTRRfix4K_E8000            0x0000026d
+#define MSR_MTRRfix4K_F0000            0x0000026e
+#define MSR_MTRRfix4K_F8000            0x0000026f
+#define MSR_MTRRdefType                        0x000002ff
+
+#define MSR_IA32_CR_PAT                        0x00000277
+
+#define MSR_IA32_DEBUGCTLMSR           0x000001d9
+#define MSR_IA32_LASTBRANCHFROMIP      0x000001db
+#define MSR_IA32_LASTBRANCHTOIP                0x000001dc
+#define MSR_IA32_LASTINTFROMIP         0x000001dd
+#define MSR_IA32_LASTINTTOIP           0x000001de
+
+/* DEBUGCTLMSR bits (others vary by model): */
+#define DEBUGCTLMSR_LBR                        (1UL <<  0) /* last branch recording */
+#define DEBUGCTLMSR_BTF                        (1UL <<  1) /* single-step on branches */
+#define DEBUGCTLMSR_TR                 (1UL <<  6)
+#define DEBUGCTLMSR_BTS                        (1UL <<  7)
+#define DEBUGCTLMSR_BTINT              (1UL <<  8)
+#define DEBUGCTLMSR_BTS_OFF_OS         (1UL <<  9)
+#define DEBUGCTLMSR_BTS_OFF_USR                (1UL << 10)
+#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
+
+#define MSR_IA32_MC0_CTL               0x00000400
+#define MSR_IA32_MC0_STATUS            0x00000401
+#define MSR_IA32_MC0_ADDR              0x00000402
+#define MSR_IA32_MC0_MISC              0x00000403
+
+#define MSR_AMD64_MC0_MASK             0xc0010044
+
+#define MSR_IA32_MCx_CTL(x)            (MSR_IA32_MC0_CTL + 4*(x))
+#define MSR_IA32_MCx_STATUS(x)         (MSR_IA32_MC0_STATUS + 4*(x))
+#define MSR_IA32_MCx_ADDR(x)           (MSR_IA32_MC0_ADDR + 4*(x))
+#define MSR_IA32_MCx_MISC(x)           (MSR_IA32_MC0_MISC + 4*(x))
+
+#define MSR_AMD64_MCx_MASK(x)          (MSR_AMD64_MC0_MASK + (x))
+
+/* These are consecutive and not in the normal 4er MCE bank block */
+#define MSR_IA32_MC0_CTL2              0x00000280
+#define MSR_IA32_MCx_CTL2(x)           (MSR_IA32_MC0_CTL2 + (x))
+
+#define MSR_P6_PERFCTR0                        0x000000c1
+#define MSR_P6_PERFCTR1                        0x000000c2
+#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. */
+
+#define MSR_AMD64_PATCH_LEVEL          0x0000008b
+#define MSR_AMD64_TSC_RATIO            0xc0000104
+#define MSR_AMD64_NB_CFG               0xc001001f
+#define MSR_AMD64_PATCH_LOADER         0xc0010020
+#define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
+#define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD64_DC_CFG               0xc0011022
+#define MSR_AMD64_IBSFETCHCTL          0xc0011030
+#define MSR_AMD64_IBSFETCHLINAD                0xc0011031
+#define MSR_AMD64_IBSFETCHPHYSAD       0xc0011032
+#define MSR_AMD64_IBSFETCH_REG_COUNT   3
+#define MSR_AMD64_IBSFETCH_REG_MASK    ((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
+#define MSR_AMD64_IBSOPCTL             0xc0011033
+#define MSR_AMD64_IBSOPRIP             0xc0011034
+#define MSR_AMD64_IBSOPDATA            0xc0011035
+#define MSR_AMD64_IBSOPDATA2           0xc0011036
+#define MSR_AMD64_IBSOPDATA3           0xc0011037
+#define MSR_AMD64_IBSDCLINAD           0xc0011038
+#define MSR_AMD64_IBSDCPHYSAD          0xc0011039
+#define MSR_AMD64_IBSOP_REG_COUNT      7
+#define MSR_AMD64_IBSOP_REG_MASK       ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
+#define MSR_AMD64_IBSCTL               0xc001103a
+#define MSR_AMD64_IBSBRTARGET          0xc001103b
+#define MSR_AMD64_IBS_REG_COUNT_MAX    8 /* includes MSR_AMD64_IBSBRTARGET */
+
+/* Fam 15h MSRs */
+#define MSR_F15H_PERF_CTL              0xc0010200
+#define MSR_F15H_PERF_CTR              0xc0010201
+
+/* Fam 10h MSRs */
+#define MSR_FAM10H_MMIO_CONF_BASE      0xc0010058
+#define FAM10H_MMIO_CONF_ENABLE                (1<<0)
+#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
+#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
+#define FAM10H_MMIO_CONF_BASE_MASK     0xfffffffULL
+#define FAM10H_MMIO_CONF_BASE_SHIFT    20
+#define MSR_FAM10H_NODE_ID             0xc001100c
+
+/* K8 MSRs */
+#define MSR_K8_TOP_MEM1                        0xc001001a
+#define MSR_K8_TOP_MEM2                        0xc001001d
+#define MSR_K8_SYSCFG                  0xc0010010
+#define MSR_K8_INT_PENDING_MSG         0xc0010055
+/* C1E active bits in int pending message */
+#define K8_INTP_C1E_ACTIVE_MASK                0x18000000
+#define MSR_K8_TSEG_ADDR               0xc0010112
+#define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
+#define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
+#define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
+
+/* K7 MSRs */
+#define MSR_K7_EVNTSEL0                        0xc0010000
+#define MSR_K7_PERFCTR0                        0xc0010004
+#define MSR_K7_EVNTSEL1                        0xc0010001
+#define MSR_K7_PERFCTR1                        0xc0010005
+#define MSR_K7_EVNTSEL2                        0xc0010002
+#define MSR_K7_PERFCTR2                        0xc0010006
+#define MSR_K7_EVNTSEL3                        0xc0010003
+#define MSR_K7_PERFCTR3                        0xc0010007
+#define MSR_K7_CLK_CTL                 0xc001001b
+#define MSR_K7_HWCR                    0xc0010015
+#define MSR_K7_FID_VID_CTL             0xc0010041
+#define MSR_K7_FID_VID_STATUS          0xc0010042
+
+/* K6 MSRs */
+#define MSR_K6_WHCR                    0xc0000082
+#define MSR_K6_UWCCR                   0xc0000085
+#define MSR_K6_EPMR                    0xc0000086
+#define MSR_K6_PSOR                    0xc0000087
+#define MSR_K6_PFIR                    0xc0000088
+
+/* Centaur-Hauls/IDT defined MSRs. */
+#define MSR_IDT_FCR1                   0x00000107
+#define MSR_IDT_FCR2                   0x00000108
+#define MSR_IDT_FCR3                   0x00000109
+#define MSR_IDT_FCR4                   0x0000010a
+
+#define MSR_IDT_MCR0                   0x00000110
+#define MSR_IDT_MCR1                   0x00000111
+#define MSR_IDT_MCR2                   0x00000112
+#define MSR_IDT_MCR3                   0x00000113
+#define MSR_IDT_MCR4                   0x00000114
+#define MSR_IDT_MCR5                   0x00000115
+#define MSR_IDT_MCR6                   0x00000116
+#define MSR_IDT_MCR7                   0x00000117
+#define MSR_IDT_MCR_CTRL               0x00000120
+
+/* VIA Cyrix defined MSRs*/
+#define MSR_VIA_FCR                    0x00001107
+#define MSR_VIA_LONGHAUL               0x0000110a
+#define MSR_VIA_RNG                    0x0000110b
+#define MSR_VIA_BCR2                   0x00001147
+
+/* Transmeta defined MSRs */
+#define MSR_TMTA_LONGRUN_CTRL          0x80868010
+#define MSR_TMTA_LONGRUN_FLAGS         0x80868011
+#define MSR_TMTA_LRTI_READOUT          0x80868018
+#define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
+
+/* Intel defined MSRs. */
+#define MSR_IA32_P5_MC_ADDR            0x00000000
+#define MSR_IA32_P5_MC_TYPE            0x00000001
+#define MSR_IA32_TSC                   0x00000010
+#define MSR_IA32_PLATFORM_ID           0x00000017
+#define MSR_IA32_EBL_CR_POWERON                0x0000002a
+#define MSR_EBC_FREQUENCY_ID           0x0000002c
+#define MSR_IA32_FEATURE_CONTROL        0x0000003a
+#define MSR_IA32_TSC_ADJUST             0x0000003b
+
+#define FEATURE_CONTROL_LOCKED                         (1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX       (1<<1)
+#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX      (1<<2)
+
+#define MSR_IA32_APICBASE              0x0000001b
+#define MSR_IA32_APICBASE_BSP          (1<<8)
+#define MSR_IA32_APICBASE_ENABLE       (1<<11)
+#define MSR_IA32_APICBASE_BASE         (0xfffff<<12)
+
+#define MSR_IA32_TSCDEADLINE           0x000006e0
+
+#define MSR_IA32_UCODE_WRITE           0x00000079
+#define MSR_IA32_UCODE_REV             0x0000008b
+
+#define MSR_IA32_PERF_STATUS           0x00000198
+#define MSR_IA32_PERF_CTL              0x00000199
+#define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
+#define MSR_AMD_PERF_STATUS            0xc0010063
+#define MSR_AMD_PERF_CTL               0xc0010062
+
+#define MSR_IA32_MPERF                 0x000000e7
+#define MSR_IA32_APERF                 0x000000e8
+
+#define MSR_IA32_THERM_CONTROL         0x0000019a
+#define MSR_IA32_THERM_INTERRUPT       0x0000019b
+
+#define THERM_INT_HIGH_ENABLE          (1 << 0)
+#define THERM_INT_LOW_ENABLE           (1 << 1)
+#define THERM_INT_PLN_ENABLE           (1 << 24)
+
+#define MSR_IA32_THERM_STATUS          0x0000019c
+
+#define THERM_STATUS_PROCHOT           (1 << 0)
+#define THERM_STATUS_POWER_LIMIT       (1 << 10)
+
+#define MSR_THERM2_CTL                 0x0000019d
+
+#define MSR_THERM2_CTL_TM_SELECT       (1ULL << 16)
+
+#define MSR_IA32_MISC_ENABLE           0x000001a0
+
+#define MSR_IA32_TEMPERATURE_TARGET    0x000001a2
+
+#define MSR_IA32_ENERGY_PERF_BIAS      0x000001b0
+#define ENERGY_PERF_BIAS_PERFORMANCE   0
+#define ENERGY_PERF_BIAS_NORMAL                6
+#define ENERGY_PERF_BIAS_POWERSAVE     15
+
+#define MSR_IA32_PACKAGE_THERM_STATUS          0x000001b1
+
+#define PACKAGE_THERM_STATUS_PROCHOT           (1 << 0)
+#define PACKAGE_THERM_STATUS_POWER_LIMIT       (1 << 10)
+
+#define MSR_IA32_PACKAGE_THERM_INTERRUPT       0x000001b2
+
+#define PACKAGE_THERM_INT_HIGH_ENABLE          (1 << 0)
+#define PACKAGE_THERM_INT_LOW_ENABLE           (1 << 1)
+#define PACKAGE_THERM_INT_PLN_ENABLE           (1 << 24)
+
+/* Thermal Thresholds Support */
+#define THERM_INT_THRESHOLD0_ENABLE    (1 << 15)
+#define THERM_SHIFT_THRESHOLD0        8
+#define THERM_MASK_THRESHOLD0          (0x7f << THERM_SHIFT_THRESHOLD0)
+#define THERM_INT_THRESHOLD1_ENABLE    (1 << 23)
+#define THERM_SHIFT_THRESHOLD1        16
+#define THERM_MASK_THRESHOLD1          (0x7f << THERM_SHIFT_THRESHOLD1)
+#define THERM_STATUS_THRESHOLD0        (1 << 6)
+#define THERM_LOG_THRESHOLD0           (1 << 7)
+#define THERM_STATUS_THRESHOLD1        (1 << 8)
+#define THERM_LOG_THRESHOLD1           (1 << 9)
+
+/* MISC_ENABLE bits: architectural */
+#define MSR_IA32_MISC_ENABLE_FAST_STRING       (1ULL << 0)
+#define MSR_IA32_MISC_ENABLE_TCC               (1ULL << 1)
+#define MSR_IA32_MISC_ENABLE_EMON              (1ULL << 7)
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       (1ULL << 11)
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      (1ULL << 12)
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP        (1ULL << 16)
+#define MSR_IA32_MISC_ENABLE_MWAIT             (1ULL << 18)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       (1ULL << 22)
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE      (1ULL << 23)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE                (1ULL << 34)
+
+/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT                (1ULL << 2)
+#define MSR_IA32_MISC_ENABLE_TM1               (1ULL << 3)
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE        (1ULL << 4)
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE   (1ULL << 6)
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK     (1ULL << 8)
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE  (1ULL << 9)
+#define MSR_IA32_MISC_ENABLE_FERR              (1ULL << 10)
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX    (1ULL << 10)
+#define MSR_IA32_MISC_ENABLE_TM2               (1ULL << 13)
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE  (1ULL << 19)
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK    (1ULL << 20)
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT       (1ULL << 24)
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE  (1ULL << 37)
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE     (1ULL << 38)
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE   (1ULL << 39)
+
+#define MSR_IA32_TSC_DEADLINE          0x000006E0
+
+/* P4/Xeon+ specific */
+#define MSR_IA32_MCG_EAX               0x00000180
+#define MSR_IA32_MCG_EBX               0x00000181
+#define MSR_IA32_MCG_ECX               0x00000182
+#define MSR_IA32_MCG_EDX               0x00000183
+#define MSR_IA32_MCG_ESI               0x00000184
+#define MSR_IA32_MCG_EDI               0x00000185
+#define MSR_IA32_MCG_EBP               0x00000186
+#define MSR_IA32_MCG_ESP               0x00000187
+#define MSR_IA32_MCG_EFLAGS            0x00000188
+#define MSR_IA32_MCG_EIP               0x00000189
+#define MSR_IA32_MCG_RESERVED          0x0000018a
+
+/* Pentium IV performance counter MSRs */
+#define MSR_P4_BPU_PERFCTR0            0x00000300
+#define MSR_P4_BPU_PERFCTR1            0x00000301
+#define MSR_P4_BPU_PERFCTR2            0x00000302
+#define MSR_P4_BPU_PERFCTR3            0x00000303
+#define MSR_P4_MS_PERFCTR0             0x00000304
+#define MSR_P4_MS_PERFCTR1             0x00000305
+#define MSR_P4_MS_PERFCTR2             0x00000306
+#define MSR_P4_MS_PERFCTR3             0x00000307
+#define MSR_P4_FLAME_PERFCTR0          0x00000308
+#define MSR_P4_FLAME_PERFCTR1          0x00000309
+#define MSR_P4_FLAME_PERFCTR2          0x0000030a
+#define MSR_P4_FLAME_PERFCTR3          0x0000030b
+#define MSR_P4_IQ_PERFCTR0             0x0000030c
+#define MSR_P4_IQ_PERFCTR1             0x0000030d
+#define MSR_P4_IQ_PERFCTR2             0x0000030e
+#define MSR_P4_IQ_PERFCTR3             0x0000030f
+#define MSR_P4_IQ_PERFCTR4             0x00000310
+#define MSR_P4_IQ_PERFCTR5             0x00000311
+#define MSR_P4_BPU_CCCR0               0x00000360
+#define MSR_P4_BPU_CCCR1               0x00000361
+#define MSR_P4_BPU_CCCR2               0x00000362
+#define MSR_P4_BPU_CCCR3               0x00000363
+#define MSR_P4_MS_CCCR0                        0x00000364
+#define MSR_P4_MS_CCCR1                        0x00000365
+#define MSR_P4_MS_CCCR2                        0x00000366
+#define MSR_P4_MS_CCCR3                        0x00000367
+#define MSR_P4_FLAME_CCCR0             0x00000368
+#define MSR_P4_FLAME_CCCR1             0x00000369
+#define MSR_P4_FLAME_CCCR2             0x0000036a
+#define MSR_P4_FLAME_CCCR3             0x0000036b
+#define MSR_P4_IQ_CCCR0                        0x0000036c
+#define MSR_P4_IQ_CCCR1                        0x0000036d
+#define MSR_P4_IQ_CCCR2                        0x0000036e
+#define MSR_P4_IQ_CCCR3                        0x0000036f
+#define MSR_P4_IQ_CCCR4                        0x00000370
+#define MSR_P4_IQ_CCCR5                        0x00000371
+#define MSR_P4_ALF_ESCR0               0x000003ca
+#define MSR_P4_ALF_ESCR1               0x000003cb
+#define MSR_P4_BPU_ESCR0               0x000003b2
+#define MSR_P4_BPU_ESCR1               0x000003b3
+#define MSR_P4_BSU_ESCR0               0x000003a0
+#define MSR_P4_BSU_ESCR1               0x000003a1
+#define MSR_P4_CRU_ESCR0               0x000003b8
+#define MSR_P4_CRU_ESCR1               0x000003b9
+#define MSR_P4_CRU_ESCR2               0x000003cc
+#define MSR_P4_CRU_ESCR3               0x000003cd
+#define MSR_P4_CRU_ESCR4               0x000003e0
+#define MSR_P4_CRU_ESCR5               0x000003e1
+#define MSR_P4_DAC_ESCR0               0x000003a8
+#define MSR_P4_DAC_ESCR1               0x000003a9
+#define MSR_P4_FIRM_ESCR0              0x000003a4
+#define MSR_P4_FIRM_ESCR1              0x000003a5
+#define MSR_P4_FLAME_ESCR0             0x000003a6
+#define MSR_P4_FLAME_ESCR1             0x000003a7
+#define MSR_P4_FSB_ESCR0               0x000003a2
+#define MSR_P4_FSB_ESCR1               0x000003a3
+#define MSR_P4_IQ_ESCR0                        0x000003ba
+#define MSR_P4_IQ_ESCR1                        0x000003bb
+#define MSR_P4_IS_ESCR0                        0x000003b4
+#define MSR_P4_IS_ESCR1                        0x000003b5
+#define MSR_P4_ITLB_ESCR0              0x000003b6
+#define MSR_P4_ITLB_ESCR1              0x000003b7
+#define MSR_P4_IX_ESCR0                        0x000003c8
+#define MSR_P4_IX_ESCR1                        0x000003c9
+#define MSR_P4_MOB_ESCR0               0x000003aa
+#define MSR_P4_MOB_ESCR1               0x000003ab
+#define MSR_P4_MS_ESCR0                        0x000003c0
+#define MSR_P4_MS_ESCR1                        0x000003c1
+#define MSR_P4_PMH_ESCR0               0x000003ac
+#define MSR_P4_PMH_ESCR1               0x000003ad
+#define MSR_P4_RAT_ESCR0               0x000003bc
+#define MSR_P4_RAT_ESCR1               0x000003bd
+#define MSR_P4_SAAT_ESCR0              0x000003ae
+#define MSR_P4_SAAT_ESCR1              0x000003af
+#define MSR_P4_SSU_ESCR0               0x000003be
+#define MSR_P4_SSU_ESCR1               0x000003bf /* guess: not in manual */
+
+#define MSR_P4_TBPU_ESCR0              0x000003c2
+#define MSR_P4_TBPU_ESCR1              0x000003c3
+#define MSR_P4_TC_ESCR0                        0x000003c4
+#define MSR_P4_TC_ESCR1                        0x000003c5
+#define MSR_P4_U2L_ESCR0               0x000003b0
+#define MSR_P4_U2L_ESCR1               0x000003b1
+
+#define MSR_P4_PEBS_MATRIX_VERT                0x000003f2
+
+/* Intel Core-based CPU performance counters */
+#define MSR_CORE_PERF_FIXED_CTR0       0x00000309
+#define MSR_CORE_PERF_FIXED_CTR1       0x0000030a
+#define MSR_CORE_PERF_FIXED_CTR2       0x0000030b
+#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x0000038d
+#define MSR_CORE_PERF_GLOBAL_STATUS    0x0000038e
+#define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
+
+/* Geode defined MSRs */
+#define MSR_GEODE_BUSCONT_CONF0                0x00001900
+
+/* Intel VT MSRs */
+#define MSR_IA32_VMX_BASIC              0x00000480
+#define MSR_IA32_VMX_PINBASED_CTLS      0x00000481
+#define MSR_IA32_VMX_PROCBASED_CTLS     0x00000482
+#define MSR_IA32_VMX_EXIT_CTLS          0x00000483
+#define MSR_IA32_VMX_ENTRY_CTLS         0x00000484
+#define MSR_IA32_VMX_MISC               0x00000485
+#define MSR_IA32_VMX_CR0_FIXED0         0x00000486
+#define MSR_IA32_VMX_CR0_FIXED1         0x00000487
+#define MSR_IA32_VMX_CR4_FIXED0         0x00000488
+#define MSR_IA32_VMX_CR4_FIXED1         0x00000489
+#define MSR_IA32_VMX_VMCS_ENUM          0x0000048a
+#define MSR_IA32_VMX_PROCBASED_CTLS2    0x0000048b
+#define MSR_IA32_VMX_EPT_VPID_CAP       0x0000048c
+#define MSR_IA32_VMX_TRUE_PINBASED_CTLS  0x0000048d
+#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
+#define MSR_IA32_VMX_TRUE_EXIT_CTLS      0x0000048f
+#define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
+
+/* VMX_BASIC bits and bitmasks */
+#define VMX_BASIC_VMCS_SIZE_SHIFT      32
+#define VMX_BASIC_64           0x0001000000000000LLU
+#define VMX_BASIC_MEM_TYPE_SHIFT       50
+#define VMX_BASIC_MEM_TYPE_MASK        0x003c000000000000LLU
+#define VMX_BASIC_MEM_TYPE_WB  6LLU
+#define VMX_BASIC_INOUT                0x0040000000000000LLU
+
+/* AMD-V MSRs */
+
+#define MSR_VM_CR                       0xc0010114
+#define MSR_VM_IGNNE                    0xc0010115
+#define MSR_VM_HSAVE_PA                 0xc0010117
+
+#endif /* _ASM_X86_MSR_INDEX_H */
diff --git a/arch/x86/include/uapi/asm/msr.h b/arch/x86/include/uapi/asm/msr.h
new file mode 100644 (file)
index 0000000..155e510
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _UAPI_ASM_X86_MSR_H
+#define _UAPI_ASM_X86_MSR_H
+
+#include <asm/msr-index.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define X86_IOC_RDMSR_REGS     _IOWR('c', 0xA0, __u32[8])
+#define X86_IOC_WRMSR_REGS     _IOWR('c', 0xA1, __u32[8])
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_ASM_X86_MSR_H */
diff --git a/arch/x86/include/uapi/asm/mtrr.h b/arch/x86/include/uapi/asm/mtrr.h
new file mode 100644 (file)
index 0000000..d0acb65
--- /dev/null
@@ -0,0 +1,117 @@
+/*  Generic MTRR (Memory Type Range Register) ioctls.
+
+    Copyright (C) 1997-1999  Richard Gooch
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
+    The postal address is:
+      Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
+*/
+#ifndef _UAPI_ASM_X86_MTRR_H
+#define _UAPI_ASM_X86_MTRR_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/errno.h>
+
+#define        MTRR_IOCTL_BASE 'M'
+
+/* Warning: this structure has a different order from i386
+   on x86-64. The 32bit emulation code takes care of that.
+   But you need to use this for 64bit, otherwise your X server
+   will break. */
+
+#ifdef __i386__
+struct mtrr_sentry {
+    unsigned long base;    /*  Base address     */
+    unsigned int size;    /*  Size of region   */
+    unsigned int type;     /*  Type of region   */
+};
+
+struct mtrr_gentry {
+    unsigned int regnum;   /*  Register number  */
+    unsigned long base;    /*  Base address     */
+    unsigned int size;    /*  Size of region   */
+    unsigned int type;     /*  Type of region   */
+};
+
+#else /* __i386__ */
+
+struct mtrr_sentry {
+       __u64 base;             /*  Base address     */
+       __u32 size;             /*  Size of region   */
+       __u32 type;             /*  Type of region   */
+};
+
+struct mtrr_gentry {
+       __u64 base;             /*  Base address     */
+       __u32 size;             /*  Size of region   */
+       __u32 regnum;           /*  Register number  */
+       __u32 type;             /*  Type of region   */
+       __u32 _pad;             /*  Unused           */
+};
+
+#endif /* !__i386__ */
+
+struct mtrr_var_range {
+       __u32 base_lo;
+       __u32 base_hi;
+       __u32 mask_lo;
+       __u32 mask_hi;
+};
+
+/* In the Intel processor's MTRR interface, the MTRR type is always held in
+   an 8 bit field: */
+typedef __u8 mtrr_type;
+
+#define MTRR_NUM_FIXED_RANGES 88
+#define MTRR_MAX_VAR_RANGES 256
+
+struct mtrr_state_type {
+       struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES];
+       mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES];
+       unsigned char enabled;
+       unsigned char have_fixed;
+       mtrr_type def_type;
+};
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+/*  These are the various ioctls  */
+#define MTRRIOC_ADD_ENTRY        _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry)
+#define MTRRIOC_SET_ENTRY        _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry)
+#define MTRRIOC_DEL_ENTRY        _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry)
+#define MTRRIOC_GET_ENTRY        _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
+#define MTRRIOC_KILL_ENTRY       _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry)
+#define MTRRIOC_ADD_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry)
+#define MTRRIOC_SET_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry)
+#define MTRRIOC_DEL_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry)
+#define MTRRIOC_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
+#define MTRRIOC_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry)
+
+/*  These are the region types  */
+#define MTRR_TYPE_UNCACHABLE 0
+#define MTRR_TYPE_WRCOMB     1
+/*#define MTRR_TYPE_         2*/
+/*#define MTRR_TYPE_         3*/
+#define MTRR_TYPE_WRTHROUGH  4
+#define MTRR_TYPE_WRPROT     5
+#define MTRR_TYPE_WRBACK     6
+#define MTRR_NUM_TYPES       7
+
+
+#endif /* _UAPI_ASM_X86_MTRR_H */
diff --git a/arch/x86/include/uapi/asm/param.h b/arch/x86/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..965d454
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/param.h>
diff --git a/arch/x86/include/uapi/asm/perf_regs.h b/arch/x86/include/uapi/asm/perf_regs.h
new file mode 100644 (file)
index 0000000..3f2207b
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _ASM_X86_PERF_REGS_H
+#define _ASM_X86_PERF_REGS_H
+
+enum perf_event_x86_regs {
+       PERF_REG_X86_AX,
+       PERF_REG_X86_BX,
+       PERF_REG_X86_CX,
+       PERF_REG_X86_DX,
+       PERF_REG_X86_SI,
+       PERF_REG_X86_DI,
+       PERF_REG_X86_BP,
+       PERF_REG_X86_SP,
+       PERF_REG_X86_IP,
+       PERF_REG_X86_FLAGS,
+       PERF_REG_X86_CS,
+       PERF_REG_X86_SS,
+       PERF_REG_X86_DS,
+       PERF_REG_X86_ES,
+       PERF_REG_X86_FS,
+       PERF_REG_X86_GS,
+       PERF_REG_X86_R8,
+       PERF_REG_X86_R9,
+       PERF_REG_X86_R10,
+       PERF_REG_X86_R11,
+       PERF_REG_X86_R12,
+       PERF_REG_X86_R13,
+       PERF_REG_X86_R14,
+       PERF_REG_X86_R15,
+
+       PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
+       PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
+};
+#endif /* _ASM_X86_PERF_REGS_H */
diff --git a/arch/x86/include/uapi/asm/poll.h b/arch/x86/include/uapi/asm/poll.h
new file mode 100644 (file)
index 0000000..c98509d
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/poll.h>
diff --git a/arch/x86/include/uapi/asm/posix_types.h b/arch/x86/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..85506b3
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __KERNEL__
+# ifdef __i386__
+#  include <asm/posix_types_32.h>
+# elif defined(__ILP32__)
+#  include <asm/posix_types_x32.h>
+# else
+#  include <asm/posix_types_64.h>
+# endif
+#endif
diff --git a/arch/x86/include/uapi/asm/posix_types_32.h b/arch/x86/include/uapi/asm/posix_types_32.h
new file mode 100644 (file)
index 0000000..8e52505
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _ASM_X86_POSIX_TYPES_32_H
+#define _ASM_X86_POSIX_TYPES_32_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* _ASM_X86_POSIX_TYPES_32_H */
diff --git a/arch/x86/include/uapi/asm/posix_types_64.h b/arch/x86/include/uapi/asm/posix_types_64.h
new file mode 100644 (file)
index 0000000..cba0c1e
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_X86_POSIX_TYPES_64_H
+#define _ASM_X86_POSIX_TYPES_64_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
+
+typedef unsigned long  __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* _ASM_X86_POSIX_TYPES_64_H */
diff --git a/arch/x86/include/uapi/asm/posix_types_x32.h b/arch/x86/include/uapi/asm/posix_types_x32.h
new file mode 100644 (file)
index 0000000..85f9bda
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_X86_POSIX_TYPES_X32_H
+#define _ASM_X86_POSIX_TYPES_X32_H
+
+/*
+ * This file is only used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ *
+ * These types should generally match the ones used by the 64-bit kernel,
+ *
+ */
+
+typedef long long __kernel_long_t;
+typedef unsigned long long __kernel_ulong_t;
+#define __kernel_long_t __kernel_long_t
+
+#include <asm/posix_types_64.h>
+
+#endif /* _ASM_X86_POSIX_TYPES_X32_H */
diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h
new file mode 100644 (file)
index 0000000..3ac5032
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ASM_X86_PRCTL_H
+#define _ASM_X86_PRCTL_H
+
+#define ARCH_SET_GS 0x1001
+#define ARCH_SET_FS 0x1002
+#define ARCH_GET_FS 0x1003
+#define ARCH_GET_GS 0x1004
+
+#endif /* _ASM_X86_PRCTL_H */
diff --git a/arch/x86/include/uapi/asm/processor-flags.h b/arch/x86/include/uapi/asm/processor-flags.h
new file mode 100644 (file)
index 0000000..54991a7
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef _UAPI_ASM_X86_PROCESSOR_FLAGS_H
+#define _UAPI_ASM_X86_PROCESSOR_FLAGS_H
+/* Various flags defined: can be included from assembler. */
+
+/*
+ * EFLAGS bits
+ */
+#define X86_EFLAGS_CF  0x00000001 /* Carry Flag */
+#define X86_EFLAGS_BIT1        0x00000002 /* Bit 1 - always on */
+#define X86_EFLAGS_PF  0x00000004 /* Parity Flag */
+#define X86_EFLAGS_AF  0x00000010 /* Auxiliary carry Flag */
+#define X86_EFLAGS_ZF  0x00000040 /* Zero Flag */
+#define X86_EFLAGS_SF  0x00000080 /* Sign Flag */
+#define X86_EFLAGS_TF  0x00000100 /* Trap Flag */
+#define X86_EFLAGS_IF  0x00000200 /* Interrupt Flag */
+#define X86_EFLAGS_DF  0x00000400 /* Direction Flag */
+#define X86_EFLAGS_OF  0x00000800 /* Overflow Flag */
+#define X86_EFLAGS_IOPL        0x00003000 /* IOPL mask */
+#define X86_EFLAGS_NT  0x00004000 /* Nested Task */
+#define X86_EFLAGS_RF  0x00010000 /* Resume Flag */
+#define X86_EFLAGS_VM  0x00020000 /* Virtual Mode */
+#define X86_EFLAGS_AC  0x00040000 /* Alignment Check */
+#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
+#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
+#define X86_EFLAGS_ID  0x00200000 /* CPUID detection flag */
+
+/*
+ * Basic CPU control in CR0
+ */
+#define X86_CR0_PE     0x00000001 /* Protection Enable */
+#define X86_CR0_MP     0x00000002 /* Monitor Coprocessor */
+#define X86_CR0_EM     0x00000004 /* Emulation */
+#define X86_CR0_TS     0x00000008 /* Task Switched */
+#define X86_CR0_ET     0x00000010 /* Extension Type */
+#define X86_CR0_NE     0x00000020 /* Numeric Error */
+#define X86_CR0_WP     0x00010000 /* Write Protect */
+#define X86_CR0_AM     0x00040000 /* Alignment Mask */
+#define X86_CR0_NW     0x20000000 /* Not Write-through */
+#define X86_CR0_CD     0x40000000 /* Cache Disable */
+#define X86_CR0_PG     0x80000000 /* Paging */
+
+/*
+ * Paging options in CR3
+ */
+#define X86_CR3_PWT    0x00000008 /* Page Write Through */
+#define X86_CR3_PCD    0x00000010 /* Page Cache Disable */
+#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */
+
+/*
+ * Intel CPU features in CR4
+ */
+#define X86_CR4_VME    0x00000001 /* enable vm86 extensions */
+#define X86_CR4_PVI    0x00000002 /* virtual interrupts flag enable */
+#define X86_CR4_TSD    0x00000004 /* disable time stamp at ipl 3 */
+#define X86_CR4_DE     0x00000008 /* enable debugging extensions */
+#define X86_CR4_PSE    0x00000010 /* enable page size extensions */
+#define X86_CR4_PAE    0x00000020 /* enable physical address extensions */
+#define X86_CR4_MCE    0x00000040 /* Machine check enable */
+#define X86_CR4_PGE    0x00000080 /* enable global pages */
+#define X86_CR4_PCE    0x00000100 /* enable performance counters at ipl 3 */
+#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
+#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
+#define X86_CR4_VMXE   0x00002000 /* enable VMX virtualization */
+#define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
+#define X86_CR4_PCIDE  0x00020000 /* enable PCID support */
+#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
+#define X86_CR4_SMEP   0x00100000 /* enable SMEP support */
+#define X86_CR4_SMAP   0x00200000 /* enable SMAP support */
+
+/*
+ * x86-64 Task Priority Register, CR8
+ */
+#define X86_CR8_TPR    0x0000000F /* task priority register */
+
+/*
+ * AMD and Transmeta use MSRs for configuration; see <asm/msr-index.h>
+ */
+
+/*
+ *      NSC/Cyrix CPU configuration register indexes
+ */
+#define CX86_PCR0      0x20
+#define CX86_GCR       0xb8
+#define CX86_CCR0      0xc0
+#define CX86_CCR1      0xc1
+#define CX86_CCR2      0xc2
+#define CX86_CCR3      0xc3
+#define CX86_CCR4      0xe8
+#define CX86_CCR5      0xe9
+#define CX86_CCR6      0xea
+#define CX86_CCR7      0xeb
+#define CX86_PCR1      0xf0
+#define CX86_DIR0      0xfe
+#define CX86_DIR1      0xff
+#define CX86_ARR_BASE  0xc4
+#define CX86_RCR_BASE  0xdc
+
+
+#endif /* _UAPI_ASM_X86_PROCESSOR_FLAGS_H */
diff --git a/arch/x86/include/uapi/asm/ptrace-abi.h b/arch/x86/include/uapi/asm/ptrace-abi.h
new file mode 100644 (file)
index 0000000..7b0a55a
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef _ASM_X86_PTRACE_ABI_H
+#define _ASM_X86_PTRACE_ABI_H
+
+#ifdef __i386__
+
+#define EBX 0
+#define ECX 1
+#define EDX 2
+#define ESI 3
+#define EDI 4
+#define EBP 5
+#define EAX 6
+#define DS 7
+#define ES 8
+#define FS 9
+#define GS 10
+#define ORIG_EAX 11
+#define EIP 12
+#define CS  13
+#define EFL 14
+#define UESP 15
+#define SS   16
+#define FRAME_SIZE 17
+
+#else /* __i386__ */
+
+#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS)
+#define R15 0
+#define R14 8
+#define R13 16
+#define R12 24
+#define RBP 32
+#define RBX 40
+/* arguments: interrupts/non tracing syscalls only save up to here*/
+#define R11 48
+#define R10 56
+#define R9 64
+#define R8 72
+#define RAX 80
+#define RCX 88
+#define RDX 96
+#define RSI 104
+#define RDI 112
+#define ORIG_RAX 120       /* = ERROR */
+/* end of arguments */
+/* cpu exception frame or undefined in case of fast syscall. */
+#define RIP 128
+#define CS 136
+#define EFLAGS 144
+#define RSP 152
+#define SS 160
+#define ARGOFFSET R11
+#endif /* __ASSEMBLY__ */
+
+/* top of stack page */
+#define FRAME_SIZE 168
+
+#endif /* !__i386__ */
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETFPXREGS         18
+#define PTRACE_SETFPXREGS         19
+
+#define PTRACE_OLDSETOPTIONS      21
+
+/* only useful for access 32bit programs / kernels */
+#define PTRACE_GET_THREAD_AREA    25
+#define PTRACE_SET_THREAD_AREA    26
+
+#ifdef __x86_64__
+# define PTRACE_ARCH_PRCTL       30
+#endif
+
+#define PTRACE_SYSEMU            31
+#define PTRACE_SYSEMU_SINGLESTEP  32
+
+#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
+
+#endif /* _ASM_X86_PTRACE_ABI_H */
diff --git a/arch/x86/include/uapi/asm/ptrace.h b/arch/x86/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..ac4b9aa
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _UAPI_ASM_X86_PTRACE_H
+#define _UAPI_ASM_X86_PTRACE_H
+
+#include <linux/compiler.h>    /* For __user */
+#include <asm/ptrace-abi.h>
+#include <asm/processor-flags.h>
+
+
+#ifndef __ASSEMBLY__
+
+#ifdef __i386__
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+#ifndef __KERNEL__
+
+struct pt_regs {
+       long ebx;
+       long ecx;
+       long edx;
+       long esi;
+       long edi;
+       long ebp;
+       long eax;
+       int  xds;
+       int  xes;
+       int  xfs;
+       int  xgs;
+       long orig_eax;
+       long eip;
+       int  xcs;
+       long eflags;
+       long esp;
+       int  xss;
+};
+
+#endif /* __KERNEL__ */
+
+#else /* __i386__ */
+
+#ifndef __KERNEL__
+
+struct pt_regs {
+       unsigned long r15;
+       unsigned long r14;
+       unsigned long r13;
+       unsigned long r12;
+       unsigned long rbp;
+       unsigned long rbx;
+/* arguments: non interrupts/non tracing syscalls only save up to here*/
+       unsigned long r11;
+       unsigned long r10;
+       unsigned long r9;
+       unsigned long r8;
+       unsigned long rax;
+       unsigned long rcx;
+       unsigned long rdx;
+       unsigned long rsi;
+       unsigned long rdi;
+       unsigned long orig_rax;
+/* end of arguments */
+/* cpu exception frame or undefined */
+       unsigned long rip;
+       unsigned long cs;
+       unsigned long eflags;
+       unsigned long rsp;
+       unsigned long ss;
+/* top of stack page */
+};
+
+#endif /* __KERNEL__ */
+#endif /* !__i386__ */
+
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_X86_PTRACE_H */
diff --git a/arch/x86/include/uapi/asm/resource.h b/arch/x86/include/uapi/asm/resource.h
new file mode 100644 (file)
index 0000000..04bc4db
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/resource.h>
diff --git a/arch/x86/include/uapi/asm/sembuf.h b/arch/x86/include/uapi/asm/sembuf.h
new file mode 100644 (file)
index 0000000..ee50c80
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _ASM_X86_SEMBUF_H
+#define _ASM_X86_SEMBUF_H
+
+/*
+ * The semid64_ds structure for x86 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+struct semid64_ds {
+       struct ipc64_perm sem_perm;     /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;      /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;      /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;      /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _ASM_X86_SEMBUF_H */
diff --git a/arch/x86/include/uapi/asm/setup.h b/arch/x86/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/x86/include/uapi/asm/shmbuf.h b/arch/x86/include/uapi/asm/shmbuf.h
new file mode 100644 (file)
index 0000000..83c05fc
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/shmbuf.h>
diff --git a/arch/x86/include/uapi/asm/sigcontext.h b/arch/x86/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..d8b9f90
--- /dev/null
@@ -0,0 +1,221 @@
+#ifndef _UAPI_ASM_X86_SIGCONTEXT_H
+#define _UAPI_ASM_X86_SIGCONTEXT_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#define FP_XSTATE_MAGIC1       0x46505853U
+#define FP_XSTATE_MAGIC2       0x46505845U
+#define FP_XSTATE_MAGIC2_SIZE  sizeof(FP_XSTATE_MAGIC2)
+
+/*
+ * bytes 464..511 in the current 512byte layout of fxsave/fxrstor frame
+ * are reserved for SW usage. On cpu's supporting xsave/xrstor, these bytes
+ * are used to extended the fpstate pointer in the sigcontext, which now
+ * includes the extended state information along with fpstate information.
+ *
+ * Presence of FP_XSTATE_MAGIC1 at the beginning of this SW reserved
+ * area and FP_XSTATE_MAGIC2 at the end of memory layout
+ * (extended_size - FP_XSTATE_MAGIC2_SIZE) indicates the presence of the
+ * extended state information in the memory layout pointed by the fpstate
+ * pointer in sigcontext.
+ */
+struct _fpx_sw_bytes {
+       __u32 magic1;           /* FP_XSTATE_MAGIC1 */
+       __u32 extended_size;    /* total size of the layout referred by
+                                * fpstate pointer in the sigcontext.
+                                */
+       __u64 xstate_bv;
+                               /* feature bit mask (including fp/sse/extended
+                                * state) that is present in the memory
+                                * layout.
+                                */
+       __u32 xstate_size;      /* actual xsave state size, based on the
+                                * features saved in the layout.
+                                * 'extended_size' will be greater than
+                                * 'xstate_size'.
+                                */
+       __u32 padding[7];       /*  for future use. */
+};
+
+#ifdef __i386__
+/*
+ * As documented in the iBCS2 standard..
+ *
+ * The first part of "struct _fpstate" is just the normal i387
+ * hardware setup, the extra "status" word is used to save the
+ * coprocessor status word before entering the handler.
+ *
+ * Pentium III FXSR, SSE support
+ *     Gareth Hughes <gareth@valinux.com>, May 2000
+ *
+ * The FPU state data structure has had to grow to accommodate the
+ * extended FPU state required by the Streaming SIMD Extensions.
+ * There is no documented standard to accomplish this at the moment.
+ */
+struct _fpreg {
+       unsigned short significand[4];
+       unsigned short exponent;
+};
+
+struct _fpxreg {
+       unsigned short significand[4];
+       unsigned short exponent;
+       unsigned short padding[3];
+};
+
+struct _xmmreg {
+       unsigned long element[4];
+};
+
+struct _fpstate {
+       /* Regular FPU environment */
+       unsigned long   cw;
+       unsigned long   sw;
+       unsigned long   tag;
+       unsigned long   ipoff;
+       unsigned long   cssel;
+       unsigned long   dataoff;
+       unsigned long   datasel;
+       struct _fpreg   _st[8];
+       unsigned short  status;
+       unsigned short  magic;          /* 0xffff = regular FPU data only */
+
+       /* FXSR FPU environment */
+       unsigned long   _fxsr_env[6];   /* FXSR FPU env is ignored */
+       unsigned long   mxcsr;
+       unsigned long   reserved;
+       struct _fpxreg  _fxsr_st[8];    /* FXSR FPU reg data is ignored */
+       struct _xmmreg  _xmm[8];
+       unsigned long   padding1[44];
+
+       union {
+               unsigned long   padding2[12];
+               struct _fpx_sw_bytes sw_reserved; /* represents the extended
+                                                  * state info */
+       };
+};
+
+#define X86_FXSR_MAGIC         0x0000
+
+#ifndef __KERNEL__
+/*
+ * User-space might still rely on the old definition:
+ */
+struct sigcontext {
+       unsigned short gs, __gsh;
+       unsigned short fs, __fsh;
+       unsigned short es, __esh;
+       unsigned short ds, __dsh;
+       unsigned long edi;
+       unsigned long esi;
+       unsigned long ebp;
+       unsigned long esp;
+       unsigned long ebx;
+       unsigned long edx;
+       unsigned long ecx;
+       unsigned long eax;
+       unsigned long trapno;
+       unsigned long err;
+       unsigned long eip;
+       unsigned short cs, __csh;
+       unsigned long eflags;
+       unsigned long esp_at_signal;
+       unsigned short ss, __ssh;
+       struct _fpstate __user *fpstate;
+       unsigned long oldmask;
+       unsigned long cr2;
+};
+#endif /* !__KERNEL__ */
+
+#else /* __i386__ */
+
+/* FXSAVE frame */
+/* Note: reserved1/2 may someday contain valuable data. Always save/restore
+   them when you change signal frames. */
+struct _fpstate {
+       __u16   cwd;
+       __u16   swd;
+       __u16   twd;            /* Note this is not the same as the
+                                  32bit/x87/FSAVE twd */
+       __u16   fop;
+       __u64   rip;
+       __u64   rdp;
+       __u32   mxcsr;
+       __u32   mxcsr_mask;
+       __u32   st_space[32];   /* 8*16 bytes for each FP-reg */
+       __u32   xmm_space[64];  /* 16*16 bytes for each XMM-reg  */
+       __u32   reserved2[12];
+       union {
+               __u32   reserved3[12];
+               struct _fpx_sw_bytes sw_reserved; /* represents the extended
+                                                  * state information */
+       };
+};
+
+#ifndef __KERNEL__
+/*
+ * User-space might still rely on the old definition:
+ */
+struct sigcontext {
+       __u64 r8;
+       __u64 r9;
+       __u64 r10;
+       __u64 r11;
+       __u64 r12;
+       __u64 r13;
+       __u64 r14;
+       __u64 r15;
+       __u64 rdi;
+       __u64 rsi;
+       __u64 rbp;
+       __u64 rbx;
+       __u64 rdx;
+       __u64 rax;
+       __u64 rcx;
+       __u64 rsp;
+       __u64 rip;
+       __u64 eflags;           /* RFLAGS */
+       __u16 cs;
+       __u16 gs;
+       __u16 fs;
+       __u16 __pad0;
+       __u64 err;
+       __u64 trapno;
+       __u64 oldmask;
+       __u64 cr2;
+       struct _fpstate __user *fpstate;        /* zero when no FPU context */
+#ifdef __ILP32__
+       __u32 __fpstate_pad;
+#endif
+       __u64 reserved1[8];
+};
+#endif /* !__KERNEL__ */
+
+#endif /* !__i386__ */
+
+struct _xsave_hdr {
+       __u64 xstate_bv;
+       __u64 reserved1[2];
+       __u64 reserved2[5];
+};
+
+struct _ymmh_state {
+       /* 16 * 16 bytes for each YMMH-reg */
+       __u32 ymmh_space[64];
+};
+
+/*
+ * Extended state pointed by the fpstate pointer in the sigcontext.
+ * In addition to the fpstate, information encoded in the xstate_hdr
+ * indicates the presence of other extended state information
+ * supported by the processor and OS.
+ */
+struct _xstate {
+       struct _fpstate fpstate;
+       struct _xsave_hdr xstate_hdr;
+       struct _ymmh_state ymmh;
+       /* new processor state extensions go here */
+};
+
+#endif /* _UAPI_ASM_X86_SIGCONTEXT_H */
diff --git a/arch/x86/include/uapi/asm/sigcontext32.h b/arch/x86/include/uapi/asm/sigcontext32.h
new file mode 100644 (file)
index 0000000..ad1478c
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _ASM_X86_SIGCONTEXT32_H
+#define _ASM_X86_SIGCONTEXT32_H
+
+#include <linux/types.h>
+
+/* signal context for 32bit programs. */
+
+#define X86_FXSR_MAGIC         0x0000
+
+struct _fpreg {
+       unsigned short significand[4];
+       unsigned short exponent;
+};
+
+struct _fpxreg {
+       unsigned short significand[4];
+       unsigned short exponent;
+       unsigned short padding[3];
+};
+
+struct _xmmreg {
+       __u32   element[4];
+};
+
+/* FSAVE frame with extensions */
+struct _fpstate_ia32 {
+       /* Regular FPU environment */
+       __u32   cw;
+       __u32   sw;
+       __u32   tag;    /* not compatible to 64bit twd */
+       __u32   ipoff;
+       __u32   cssel;
+       __u32   dataoff;
+       __u32   datasel;
+       struct _fpreg   _st[8];
+       unsigned short  status;
+       unsigned short  magic;          /* 0xffff = regular FPU data only */
+
+       /* FXSR FPU environment */
+       __u32   _fxsr_env[6];
+       __u32   mxcsr;
+       __u32   reserved;
+       struct _fpxreg  _fxsr_st[8];
+       struct _xmmreg  _xmm[8];        /* It's actually 16 */
+       __u32   padding[44];
+       union {
+               __u32 padding2[12];
+               struct _fpx_sw_bytes sw_reserved;
+       };
+};
+
+struct sigcontext_ia32 {
+       unsigned short gs, __gsh;
+       unsigned short fs, __fsh;
+       unsigned short es, __esh;
+       unsigned short ds, __dsh;
+       unsigned int di;
+       unsigned int si;
+       unsigned int bp;
+       unsigned int sp;
+       unsigned int bx;
+       unsigned int dx;
+       unsigned int cx;
+       unsigned int ax;
+       unsigned int trapno;
+       unsigned int err;
+       unsigned int ip;
+       unsigned short cs, __csh;
+       unsigned int flags;
+       unsigned int sp_at_signal;
+       unsigned short ss, __ssh;
+       unsigned int fpstate;           /* really (struct _fpstate_ia32 *) */
+       unsigned int oldmask;
+       unsigned int cr2;
+};
+
+#endif /* _ASM_X86_SIGCONTEXT32_H */
diff --git a/arch/x86/include/uapi/asm/siginfo.h b/arch/x86/include/uapi/asm/siginfo.h
new file mode 100644 (file)
index 0000000..34c47b3
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _ASM_X86_SIGINFO_H
+#define _ASM_X86_SIGINFO_H
+
+#ifdef __x86_64__
+# ifdef __ILP32__ /* x32 */
+typedef long long __kernel_si_clock_t __attribute__((aligned(4)));
+#  define __ARCH_SI_CLOCK_T            __kernel_si_clock_t
+#  define __ARCH_SI_ATTRIBUTES         __attribute__((aligned(8)))
+# else /* x86-64 */
+#  define __ARCH_SI_PREAMBLE_SIZE      (4 * sizeof(int))
+# endif
+#endif
+
+#include <asm-generic/siginfo.h>
+
+#endif /* _ASM_X86_SIGINFO_H */
diff --git a/arch/x86/include/uapi/asm/signal.h b/arch/x86/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..0818f9a
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef _UAPI_ASM_X86_SIGNAL_H
+#define _UAPI_ASM_X86_SIGNAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/compiler.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
+
+#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   0x00000001u
+#define SA_NOCLDWAIT   0x00000002u
+#define SA_SIGINFO     0x00000004u
+#define SA_ONSTACK     0x08000000u
+#define SA_RESTART     0x10000000u
+#define SA_NODEFER     0x40000000u
+#define SA_RESETHAND   0x80000000u
+
+#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 __ASSEMBLY__
+
+
+#ifdef __i386__
+# 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;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+# endif /* ! __KERNEL__ */
+#else /* __i386__ */
+
+struct sigaction {
+       __sighandler_t sa_handler;
+       unsigned long sa_flags;
+       __sigrestore_t sa_restorer;
+       sigset_t sa_mask;               /* mask last for extensibility */
+};
+
+struct k_sigaction {
+       struct sigaction sa;
+};
+
+#endif /* !__i386__ */
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_X86_SIGNAL_H */
diff --git a/arch/x86/include/uapi/asm/socket.h b/arch/x86/include/uapi/asm/socket.h
new file mode 100644 (file)
index 0000000..6b71384
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/socket.h>
diff --git a/arch/x86/include/uapi/asm/sockios.h b/arch/x86/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..def6d47
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/sockios.h>
diff --git a/arch/x86/include/uapi/asm/stat.h b/arch/x86/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..7b3ddc3
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef _ASM_X86_STAT_H
+#define _ASM_X86_STAT_H
+
+#define STAT_HAVE_NSEC 1
+
+#ifdef __i386__
+struct stat {
+       unsigned long  st_dev;
+       unsigned long  st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned long  st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_blksize;
+       unsigned long  st_blocks;
+       unsigned long  st_atime;
+       unsigned long  st_atime_nsec;
+       unsigned long  st_mtime;
+       unsigned long  st_mtime_nsec;
+       unsigned long  st_ctime;
+       unsigned long  st_ctime_nsec;
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do {      \
+       st.__unused4 = 0;                       \
+       st.__unused5 = 0;                       \
+} while (0)
+
+#define STAT64_HAS_BROKEN_ST_INO       1
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned long long      st_dev;
+       unsigned char   __pad0[4];
+
+       unsigned long   __st_ino;
+
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned long   st_uid;
+       unsigned long   st_gid;
+
+       unsigned long long      st_rdev;
+       unsigned char   __pad3[4];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+       /* Number 512-byte blocks allocated. */
+       unsigned long long      st_blocks;
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+
+       unsigned long   st_mtime;
+       unsigned int    st_mtime_nsec;
+
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+
+       unsigned long long      st_ino;
+};
+
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT64_PADDING(st) do {            \
+       memset(&st.__pad0, 0, sizeof(st.__pad0));       \
+       memset(&st.__pad3, 0, sizeof(st.__pad3));       \
+} while (0)
+
+#else /* __i386__ */
+
+struct stat {
+       unsigned long   st_dev;
+       unsigned long   st_ino;
+       unsigned long   st_nlink;
+
+       unsigned int    st_mode;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    __pad0;
+       unsigned long   st_rdev;
+       long            st_size;
+       long            st_blksize;
+       long            st_blocks;      /* Number 512-byte blocks allocated. */
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+       long            __unused[3];
+};
+
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do {      \
+       st.__pad0 = 0;                          \
+       st.__unused[0] = 0;                     \
+       st.__unused[1] = 0;                     \
+       st.__unused[2] = 0;                     \
+} while (0)
+
+#endif
+
+/* for 32bit emulation and 32 bit kernels */
+struct __old_kernel_stat {
+       unsigned short st_dev;
+       unsigned short st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+#ifdef __i386__
+       unsigned long  st_size;
+       unsigned long  st_atime;
+       unsigned long  st_mtime;
+       unsigned long  st_ctime;
+#else
+       unsigned int  st_size;
+       unsigned int  st_atime;
+       unsigned int  st_mtime;
+       unsigned int  st_ctime;
+#endif
+};
+
+#endif /* _ASM_X86_STAT_H */
diff --git a/arch/x86/include/uapi/asm/statfs.h b/arch/x86/include/uapi/asm/statfs.h
new file mode 100644 (file)
index 0000000..2d0adbf
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _ASM_X86_STATFS_H
+#define _ASM_X86_STATFS_H
+
+/*
+ * We need compat_statfs64 to be packed, because the i386 ABI won't
+ * add padding at the end to bring it to a multiple of 8 bytes, but
+ * the x86_64 ABI will.
+ */
+#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
+
+#include <asm-generic/statfs.h>
+#endif /* _ASM_X86_STATFS_H */
diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
new file mode 100644 (file)
index 0000000..b5d7640
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef _UAPI__SVM_H
+#define _UAPI__SVM_H
+
+#define SVM_EXIT_READ_CR0      0x000
+#define SVM_EXIT_READ_CR3      0x003
+#define SVM_EXIT_READ_CR4      0x004
+#define SVM_EXIT_READ_CR8      0x008
+#define SVM_EXIT_WRITE_CR0     0x010
+#define SVM_EXIT_WRITE_CR3     0x013
+#define SVM_EXIT_WRITE_CR4     0x014
+#define SVM_EXIT_WRITE_CR8     0x018
+#define SVM_EXIT_READ_DR0      0x020
+#define SVM_EXIT_READ_DR1      0x021
+#define SVM_EXIT_READ_DR2      0x022
+#define SVM_EXIT_READ_DR3      0x023
+#define SVM_EXIT_READ_DR4      0x024
+#define SVM_EXIT_READ_DR5      0x025
+#define SVM_EXIT_READ_DR6      0x026
+#define SVM_EXIT_READ_DR7      0x027
+#define SVM_EXIT_WRITE_DR0     0x030
+#define SVM_EXIT_WRITE_DR1     0x031
+#define SVM_EXIT_WRITE_DR2     0x032
+#define SVM_EXIT_WRITE_DR3     0x033
+#define SVM_EXIT_WRITE_DR4     0x034
+#define SVM_EXIT_WRITE_DR5     0x035
+#define SVM_EXIT_WRITE_DR6     0x036
+#define SVM_EXIT_WRITE_DR7     0x037
+#define SVM_EXIT_EXCP_BASE     0x040
+#define SVM_EXIT_INTR          0x060
+#define SVM_EXIT_NMI           0x061
+#define SVM_EXIT_SMI           0x062
+#define SVM_EXIT_INIT          0x063
+#define SVM_EXIT_VINTR         0x064
+#define SVM_EXIT_CR0_SEL_WRITE 0x065
+#define SVM_EXIT_IDTR_READ     0x066
+#define SVM_EXIT_GDTR_READ     0x067
+#define SVM_EXIT_LDTR_READ     0x068
+#define SVM_EXIT_TR_READ       0x069
+#define SVM_EXIT_IDTR_WRITE    0x06a
+#define SVM_EXIT_GDTR_WRITE    0x06b
+#define SVM_EXIT_LDTR_WRITE    0x06c
+#define SVM_EXIT_TR_WRITE      0x06d
+#define SVM_EXIT_RDTSC         0x06e
+#define SVM_EXIT_RDPMC         0x06f
+#define SVM_EXIT_PUSHF         0x070
+#define SVM_EXIT_POPF          0x071
+#define SVM_EXIT_CPUID         0x072
+#define SVM_EXIT_RSM           0x073
+#define SVM_EXIT_IRET          0x074
+#define SVM_EXIT_SWINT         0x075
+#define SVM_EXIT_INVD          0x076
+#define SVM_EXIT_PAUSE         0x077
+#define SVM_EXIT_HLT           0x078
+#define SVM_EXIT_INVLPG        0x079
+#define SVM_EXIT_INVLPGA       0x07a
+#define SVM_EXIT_IOIO          0x07b
+#define SVM_EXIT_MSR           0x07c
+#define SVM_EXIT_TASK_SWITCH   0x07d
+#define SVM_EXIT_FERR_FREEZE   0x07e
+#define SVM_EXIT_SHUTDOWN      0x07f
+#define SVM_EXIT_VMRUN         0x080
+#define SVM_EXIT_VMMCALL       0x081
+#define SVM_EXIT_VMLOAD        0x082
+#define SVM_EXIT_VMSAVE        0x083
+#define SVM_EXIT_STGI          0x084
+#define SVM_EXIT_CLGI          0x085
+#define SVM_EXIT_SKINIT        0x086
+#define SVM_EXIT_RDTSCP        0x087
+#define SVM_EXIT_ICEBP         0x088
+#define SVM_EXIT_WBINVD        0x089
+#define SVM_EXIT_MONITOR       0x08a
+#define SVM_EXIT_MWAIT         0x08b
+#define SVM_EXIT_MWAIT_COND    0x08c
+#define SVM_EXIT_XSETBV        0x08d
+#define SVM_EXIT_NPF           0x400
+
+#define SVM_EXIT_ERR           -1
+
+#define SVM_EXIT_REASONS \
+       { SVM_EXIT_READ_CR0,    "read_cr0" }, \
+       { SVM_EXIT_READ_CR3,    "read_cr3" }, \
+       { SVM_EXIT_READ_CR4,    "read_cr4" }, \
+       { SVM_EXIT_READ_CR8,    "read_cr8" }, \
+       { SVM_EXIT_WRITE_CR0,   "write_cr0" }, \
+       { SVM_EXIT_WRITE_CR3,   "write_cr3" }, \
+       { SVM_EXIT_WRITE_CR4,   "write_cr4" }, \
+       { SVM_EXIT_WRITE_CR8,   "write_cr8" }, \
+       { SVM_EXIT_READ_DR0,    "read_dr0" }, \
+       { SVM_EXIT_READ_DR1,    "read_dr1" }, \
+       { SVM_EXIT_READ_DR2,    "read_dr2" }, \
+       { SVM_EXIT_READ_DR3,    "read_dr3" }, \
+       { SVM_EXIT_WRITE_DR0,   "write_dr0" }, \
+       { SVM_EXIT_WRITE_DR1,   "write_dr1" }, \
+       { SVM_EXIT_WRITE_DR2,   "write_dr2" }, \
+       { SVM_EXIT_WRITE_DR3,   "write_dr3" }, \
+       { SVM_EXIT_WRITE_DR5,   "write_dr5" }, \
+       { SVM_EXIT_WRITE_DR7,   "write_dr7" }, \
+       { SVM_EXIT_EXCP_BASE + DB_VECTOR,       "DB excp" }, \
+       { SVM_EXIT_EXCP_BASE + BP_VECTOR,       "BP excp" }, \
+       { SVM_EXIT_EXCP_BASE + UD_VECTOR,       "UD excp" }, \
+       { SVM_EXIT_EXCP_BASE + PF_VECTOR,       "PF excp" }, \
+       { SVM_EXIT_EXCP_BASE + NM_VECTOR,       "NM excp" }, \
+       { SVM_EXIT_EXCP_BASE + MC_VECTOR,       "MC excp" }, \
+       { SVM_EXIT_INTR,        "interrupt" }, \
+       { SVM_EXIT_NMI,         "nmi" }, \
+       { SVM_EXIT_SMI,         "smi" }, \
+       { SVM_EXIT_INIT,        "init" }, \
+       { SVM_EXIT_VINTR,       "vintr" }, \
+       { SVM_EXIT_CPUID,       "cpuid" }, \
+       { SVM_EXIT_INVD,        "invd" }, \
+       { SVM_EXIT_HLT,         "hlt" }, \
+       { SVM_EXIT_INVLPG,      "invlpg" }, \
+       { SVM_EXIT_INVLPGA,     "invlpga" }, \
+       { SVM_EXIT_IOIO,        "io" }, \
+       { SVM_EXIT_MSR,         "msr" }, \
+       { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
+       { SVM_EXIT_SHUTDOWN,    "shutdown" }, \
+       { SVM_EXIT_VMRUN,       "vmrun" }, \
+       { SVM_EXIT_VMMCALL,     "hypercall" }, \
+       { SVM_EXIT_VMLOAD,      "vmload" }, \
+       { SVM_EXIT_VMSAVE,      "vmsave" }, \
+       { SVM_EXIT_STGI,        "stgi" }, \
+       { SVM_EXIT_CLGI,        "clgi" }, \
+       { SVM_EXIT_SKINIT,      "skinit" }, \
+       { SVM_EXIT_WBINVD,      "wbinvd" }, \
+       { SVM_EXIT_MONITOR,     "monitor" }, \
+       { SVM_EXIT_MWAIT,       "mwait" }, \
+       { SVM_EXIT_XSETBV,      "xsetbv" }, \
+       { SVM_EXIT_NPF,         "npf" }
+
+
+#endif /* _UAPI__SVM_H */
diff --git a/arch/x86/include/uapi/asm/swab.h b/arch/x86/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..7f235c7
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _ASM_X86_SWAB_H
+#define _ASM_X86_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+       asm("bswapl %0" : "=r" (val) : "0" (val));
+       return val;
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __attribute_const__ __u64 __arch_swab64(__u64 val)
+{
+#ifdef __i386__
+       union {
+               struct {
+                       __u32 a;
+                       __u32 b;
+               } s;
+               __u64 u;
+       } v;
+       v.u = val;
+       asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+           : "=r" (v.s.a), "=r" (v.s.b)
+           : "0" (v.s.a), "1" (v.s.b));
+       return v.u;
+#else /* __i386__ */
+       asm("bswapq %0" : "=r" (val) : "0" (val));
+       return val;
+#endif
+}
+#define __arch_swab64 __arch_swab64
+
+#endif /* _ASM_X86_SWAB_H */
diff --git a/arch/x86/include/uapi/asm/termbits.h b/arch/x86/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..3935b10
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/termbits.h>
diff --git a/arch/x86/include/uapi/asm/termios.h b/arch/x86/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..280d78a
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/termios.h>
diff --git a/arch/x86/include/uapi/asm/types.h b/arch/x86/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..8e8c23f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TYPES_H
+#define _ASM_X86_TYPES_H
+
+#include <asm-generic/types.h>
+
+#endif /* _ASM_X86_TYPES_H */
diff --git a/arch/x86/include/uapi/asm/ucontext.h b/arch/x86/include/uapi/asm/ucontext.h
new file mode 100644 (file)
index 0000000..b7c29c8
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _ASM_X86_UCONTEXT_H
+#define _ASM_X86_UCONTEXT_H
+
+#define UC_FP_XSTATE   0x1     /* indicates the presence of extended state
+                                * information in the memory layout pointed
+                                * by the fpstate pointer in the ucontext's
+                                * sigcontext struct (uc_mcontext).
+                                */
+
+#include <asm-generic/ucontext.h>
+
+#endif /* _ASM_X86_UCONTEXT_H */
diff --git a/arch/x86/include/uapi/asm/unistd.h b/arch/x86/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..a26df0d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _UAPI_ASM_X86_UNISTD_H
+#define _UAPI_ASM_X86_UNISTD_H
+
+/* x32 syscall flag bit */
+#define __X32_SYSCALL_BIT      0x40000000
+
+#ifndef __KERNEL__
+# ifdef __i386__
+#  include <asm/unistd_32.h>
+# elif defined(__ILP32__)
+#  include <asm/unistd_x32.h>
+# else
+#  include <asm/unistd_64.h>
+# endif
+#endif
+
+#endif /* _UAPI_ASM_X86_UNISTD_H */
diff --git a/arch/x86/include/uapi/asm/vm86.h b/arch/x86/include/uapi/asm/vm86.h
new file mode 100644 (file)
index 0000000..e0b243e
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _UAPI_ASM_X86_VM86_H
+#define _UAPI_ASM_X86_VM86_H
+
+/*
+ * I'm guessing at the VIF/VIP flag usage, but hope that this is how
+ * the Pentium uses them. Linux will return from vm86 mode when both
+ * VIF and VIP is set.
+ *
+ * On a Pentium, we could probably optimize the virtual flags directly
+ * in the eflags register instead of doing it "by hand" in vflags...
+ *
+ * Linus
+ */
+
+#include <asm/processor-flags.h>
+
+#define BIOSSEG                0x0f000
+
+#define CPU_086                0
+#define CPU_186                1
+#define CPU_286                2
+#define CPU_386                3
+#define CPU_486                4
+#define CPU_586                5
+
+/*
+ * Return values for the 'vm86()' system call
+ */
+#define VM86_TYPE(retval)      ((retval) & 0xff)
+#define VM86_ARG(retval)       ((retval) >> 8)
+
+#define VM86_SIGNAL    0       /* return due to signal */
+#define VM86_UNKNOWN   1       /* unhandled GP fault
+                                  - IO-instruction or similar */
+#define VM86_INTx      2       /* int3/int x instruction (ARG = x) */
+#define VM86_STI       3       /* sti/popf/iret instruction enabled
+                                  virtual interrupts */
+
+/*
+ * Additional return values when invoking new vm86()
+ */
+#define VM86_PICRETURN 4       /* return due to pending PIC request */
+#define VM86_TRAP      6       /* return due to DOS-debugger request */
+
+/*
+ * function codes when invoking new vm86()
+ */
+#define VM86_PLUS_INSTALL_CHECK        0
+#define VM86_ENTER             1
+#define VM86_ENTER_NO_BYPASS   2
+#define        VM86_REQUEST_IRQ        3
+#define VM86_FREE_IRQ          4
+#define VM86_GET_IRQ_BITS      5
+#define VM86_GET_AND_RESET_IRQ 6
+
+/*
+ * This is the stack-layout seen by the user space program when we have
+ * done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout
+ * is 'kernel_vm86_regs' (see below).
+ */
+
+struct vm86_regs {
+/*
+ * normal regs, with special meaning for the segment descriptors..
+ */
+       long ebx;
+       long ecx;
+       long edx;
+       long esi;
+       long edi;
+       long ebp;
+       long eax;
+       long __null_ds;
+       long __null_es;
+       long __null_fs;
+       long __null_gs;
+       long orig_eax;
+       long eip;
+       unsigned short cs, __csh;
+       long eflags;
+       long esp;
+       unsigned short ss, __ssh;
+/*
+ * these are specific to v86 mode:
+ */
+       unsigned short es, __esh;
+       unsigned short ds, __dsh;
+       unsigned short fs, __fsh;
+       unsigned short gs, __gsh;
+};
+
+struct revectored_struct {
+       unsigned long __map[8];                 /* 256 bits */
+};
+
+struct vm86_struct {
+       struct vm86_regs regs;
+       unsigned long flags;
+       unsigned long screen_bitmap;
+       unsigned long cpu_type;
+       struct revectored_struct int_revectored;
+       struct revectored_struct int21_revectored;
+};
+
+/*
+ * flags masks
+ */
+#define VM86_SCREEN_BITMAP     0x0001
+
+struct vm86plus_info_struct {
+       unsigned long force_return_for_pic:1;
+       unsigned long vm86dbg_active:1;       /* for debugger */
+       unsigned long vm86dbg_TFpendig:1;     /* for debugger */
+       unsigned long unused:28;
+       unsigned long is_vm86pus:1;           /* for vm86 internal use */
+       unsigned char vm86dbg_intxxtab[32];   /* for debugger */
+};
+struct vm86plus_struct {
+       struct vm86_regs regs;
+       unsigned long flags;
+       unsigned long screen_bitmap;
+       unsigned long cpu_type;
+       struct revectored_struct int_revectored;
+       struct revectored_struct int21_revectored;
+       struct vm86plus_info_struct vm86plus;
+};
+
+
+#endif /* _UAPI_ASM_X86_VM86_H */
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
new file mode 100644 (file)
index 0000000..979d03b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * vmx.h: VMX Architecture related definitions
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * A few random additions are:
+ * Copyright (C) 2006 Qumranet
+ *    Avi Kivity <avi@qumranet.com>
+ *    Yaniv Kamay <yaniv@qumranet.com>
+ *
+ */
+#ifndef _UAPIVMX_H
+#define _UAPIVMX_H
+
+
+#define VMX_EXIT_REASONS_FAILED_VMENTRY         0x80000000
+
+#define EXIT_REASON_EXCEPTION_NMI       0
+#define EXIT_REASON_EXTERNAL_INTERRUPT  1
+#define EXIT_REASON_TRIPLE_FAULT        2
+
+#define EXIT_REASON_PENDING_INTERRUPT   7
+#define EXIT_REASON_NMI_WINDOW          8
+#define EXIT_REASON_TASK_SWITCH         9
+#define EXIT_REASON_CPUID               10
+#define EXIT_REASON_HLT                 12
+#define EXIT_REASON_INVD                13
+#define EXIT_REASON_INVLPG              14
+#define EXIT_REASON_RDPMC               15
+#define EXIT_REASON_RDTSC               16
+#define EXIT_REASON_VMCALL              18
+#define EXIT_REASON_VMCLEAR             19
+#define EXIT_REASON_VMLAUNCH            20
+#define EXIT_REASON_VMPTRLD             21
+#define EXIT_REASON_VMPTRST             22
+#define EXIT_REASON_VMREAD              23
+#define EXIT_REASON_VMRESUME            24
+#define EXIT_REASON_VMWRITE             25
+#define EXIT_REASON_VMOFF               26
+#define EXIT_REASON_VMON                27
+#define EXIT_REASON_CR_ACCESS           28
+#define EXIT_REASON_DR_ACCESS           29
+#define EXIT_REASON_IO_INSTRUCTION      30
+#define EXIT_REASON_MSR_READ            31
+#define EXIT_REASON_MSR_WRITE           32
+#define EXIT_REASON_INVALID_STATE       33
+#define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_MONITOR_INSTRUCTION 39
+#define EXIT_REASON_PAUSE_INSTRUCTION   40
+#define EXIT_REASON_MCE_DURING_VMENTRY  41
+#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
+#define EXIT_REASON_APIC_ACCESS         44
+#define EXIT_REASON_EPT_VIOLATION       48
+#define EXIT_REASON_EPT_MISCONFIG       49
+#define EXIT_REASON_WBINVD              54
+#define EXIT_REASON_XSETBV              55
+#define EXIT_REASON_INVPCID             58
+
+#define VMX_EXIT_REASONS \
+       { EXIT_REASON_EXCEPTION_NMI,         "EXCEPTION_NMI" }, \
+       { EXIT_REASON_EXTERNAL_INTERRUPT,    "EXTERNAL_INTERRUPT" }, \
+       { EXIT_REASON_TRIPLE_FAULT,          "TRIPLE_FAULT" }, \
+       { EXIT_REASON_PENDING_INTERRUPT,     "PENDING_INTERRUPT" }, \
+       { EXIT_REASON_NMI_WINDOW,            "NMI_WINDOW" }, \
+       { EXIT_REASON_TASK_SWITCH,           "TASK_SWITCH" }, \
+       { EXIT_REASON_CPUID,                 "CPUID" }, \
+       { EXIT_REASON_HLT,                   "HLT" }, \
+       { EXIT_REASON_INVLPG,                "INVLPG" }, \
+       { EXIT_REASON_RDPMC,                 "RDPMC" }, \
+       { EXIT_REASON_RDTSC,                 "RDTSC" }, \
+       { EXIT_REASON_VMCALL,                "VMCALL" }, \
+       { EXIT_REASON_VMCLEAR,               "VMCLEAR" }, \
+       { EXIT_REASON_VMLAUNCH,              "VMLAUNCH" }, \
+       { EXIT_REASON_VMPTRLD,               "VMPTRLD" }, \
+       { EXIT_REASON_VMPTRST,               "VMPTRST" }, \
+       { EXIT_REASON_VMREAD,                "VMREAD" }, \
+       { EXIT_REASON_VMRESUME,              "VMRESUME" }, \
+       { EXIT_REASON_VMWRITE,               "VMWRITE" }, \
+       { EXIT_REASON_VMOFF,                 "VMOFF" }, \
+       { EXIT_REASON_VMON,                  "VMON" }, \
+       { EXIT_REASON_CR_ACCESS,             "CR_ACCESS" }, \
+       { EXIT_REASON_DR_ACCESS,             "DR_ACCESS" }, \
+       { EXIT_REASON_IO_INSTRUCTION,        "IO_INSTRUCTION" }, \
+       { EXIT_REASON_MSR_READ,              "MSR_READ" }, \
+       { EXIT_REASON_MSR_WRITE,             "MSR_WRITE" }, \
+       { EXIT_REASON_MWAIT_INSTRUCTION,     "MWAIT_INSTRUCTION" }, \
+       { EXIT_REASON_MONITOR_INSTRUCTION,   "MONITOR_INSTRUCTION" }, \
+       { EXIT_REASON_PAUSE_INSTRUCTION,     "PAUSE_INSTRUCTION" }, \
+       { EXIT_REASON_MCE_DURING_VMENTRY,    "MCE_DURING_VMENTRY" }, \
+       { EXIT_REASON_TPR_BELOW_THRESHOLD,   "TPR_BELOW_THRESHOLD" }, \
+       { EXIT_REASON_APIC_ACCESS,           "APIC_ACCESS" }, \
+       { EXIT_REASON_EPT_VIOLATION,         "EPT_VIOLATION" }, \
+       { EXIT_REASON_EPT_MISCONFIG,         "EPT_MISCONFIG" }, \
+       { EXIT_REASON_WBINVD,                "WBINVD" }
+
+
+#endif /* _UAPIVMX_H */
diff --git a/arch/x86/include/uapi/asm/vsyscall.h b/arch/x86/include/uapi/asm/vsyscall.h
new file mode 100644 (file)
index 0000000..85dc1b3
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _UAPI_ASM_X86_VSYSCALL_H
+#define _UAPI_ASM_X86_VSYSCALL_H
+
+enum vsyscall_num {
+       __NR_vgettimeofday,
+       __NR_vtime,
+       __NR_vgetcpu,
+};
+
+#define VSYSCALL_START (-10UL << 20)
+#define VSYSCALL_SIZE 1024
+#define VSYSCALL_END (-2UL << 20)
+#define VSYSCALL_MAPPED_PAGES 1
+#define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
+
+
+#endif /* _UAPI_ASM_X86_VSYSCALL_H */
index e48cafcf92ae4614ca43e7a504fb36ea7af79dea..bacf4b0d91f4e0e01c4b7bc7cbcfebe6e1e3a680 100644 (file)
@@ -1706,3 +1706,9 @@ int __acpi_release_global_lock(unsigned int *lock)
        } while (unlikely (val != old));
        return old & 0x1;
 }
+
+void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
+{
+       e820_add_region(addr, size, E820_ACPI);
+       update_e820();
+}
index a65829ac2b9a1b4cb9517f94318bc106291061ad..9c2aa89a11cbf8d4a124d25bdea25d726cedba17 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/hardirq.h>
 #include <linux/delay.h>
 
+#include <asm/numachip/numachip.h>
 #include <asm/numachip/numachip_csr.h>
 #include <asm/smp.h>
 #include <asm/apic.h>
@@ -179,6 +180,7 @@ static int __init numachip_system_init(void)
                return 0;
 
        x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
+       x86_init.pci.arch_init = pci_numachip_init;
 
        map_csrs();
 
index 6a05c1d327a9627819729c83a762f2c3fe9bc923..5b7d4fa5d3b726da00a0b4102ce9aa22681a98ac 100644 (file)
@@ -24,8 +24,6 @@ struct mce_bank {
 int mce_severity(struct mce *a, int tolerant, char **msg);
 struct dentry *mce_get_debugfs_dir(void);
 
-extern int mce_ser;
-
 extern struct mce_bank *mce_banks;
 
 #ifdef CONFIG_X86_MCE_INTEL
index 13017626f9a85c0948fe99cafa1102c0c9d010da..beb1f1689e5261b1dca299ea3cd442133843ca40 100644 (file)
@@ -193,9 +193,9 @@ int mce_severity(struct mce *m, int tolerant, char **msg)
                        continue;
                if ((m->mcgstatus & s->mcgmask) != s->mcgres)
                        continue;
-               if (s->ser == SER_REQUIRED && !mce_ser)
+               if (s->ser == SER_REQUIRED && !mca_cfg.ser)
                        continue;
-               if (s->ser == NO_SER && mce_ser)
+               if (s->ser == NO_SER && mca_cfg.ser)
                        continue;
                if (s->context && ctx != s->context)
                        continue;
index 46cbf8689692fdbd3d0517d6e20d20a9e192f5e0..80dbda84f1c3c2b215242d5e5381848a4ec0c372 100644 (file)
@@ -58,34 +58,26 @@ static DEFINE_MUTEX(mce_chrdev_read_mutex);
 #define CREATE_TRACE_POINTS
 #include <trace/events/mce.h>
 
-int mce_disabled __read_mostly;
-
 #define SPINUNIT 100   /* 100ns */
 
 atomic_t mce_entry;
 
 DEFINE_PER_CPU(unsigned, mce_exception_count);
 
-/*
- * Tolerant levels:
- *   0: always panic on uncorrected errors, log corrected errors
- *   1: panic or SIGBUS on uncorrected errors, log corrected errors
- *   2: SIGBUS or log uncorrected errors (if possible), log corrected errors
- *   3: never panic or SIGBUS, log all errors (for testing only)
- */
-static int                     tolerant                __read_mostly = 1;
-static int                     banks                   __read_mostly;
-static int                     rip_msr                 __read_mostly;
-static int                     mce_bootlog             __read_mostly = -1;
-static int                     monarch_timeout         __read_mostly = -1;
-static int                     mce_panic_timeout       __read_mostly;
-static int                     mce_dont_log_ce         __read_mostly;
-int                            mce_cmci_disabled       __read_mostly;
-int                            mce_ignore_ce           __read_mostly;
-int                            mce_ser                 __read_mostly;
-int                            mce_bios_cmci_threshold __read_mostly;
-
-struct mce_bank                *mce_banks              __read_mostly;
+struct mce_bank *mce_banks __read_mostly;
+
+struct mca_config mca_cfg __read_mostly = {
+       .bootlog  = -1,
+       /*
+        * Tolerant levels:
+        * 0: always panic on uncorrected errors, log corrected errors
+        * 1: panic or SIGBUS on uncorrected errors, log corrected errors
+        * 2: SIGBUS or log uncorrected errors (if possible), log corr. errors
+        * 3: never panic or SIGBUS, log all errors (for testing only)
+        */
+       .tolerant = 1,
+       .monarch_timeout = -1
+};
 
 /* User mode helper program triggered by machine check event */
 static unsigned long           mce_need_notify;
@@ -302,7 +294,7 @@ static void wait_for_panic(void)
        while (timeout-- > 0)
                udelay(1);
        if (panic_timeout == 0)
-               panic_timeout = mce_panic_timeout;
+               panic_timeout = mca_cfg.panic_timeout;
        panic("Panicing machine check CPU died");
 }
 
@@ -360,7 +352,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
                pr_emerg(HW_ERR "Machine check: %s\n", exp);
        if (!fake_panic) {
                if (panic_timeout == 0)
-                       panic_timeout = mce_panic_timeout;
+                       panic_timeout = mca_cfg.panic_timeout;
                panic(msg);
        } else
                pr_emerg(HW_ERR "Fake kernel panic: %s\n", msg);
@@ -372,7 +364,7 @@ static int msr_to_offset(u32 msr)
 {
        unsigned bank = __this_cpu_read(injectm.bank);
 
-       if (msr == rip_msr)
+       if (msr == mca_cfg.rip_msr)
                return offsetof(struct mce, ip);
        if (msr == MSR_IA32_MCx_STATUS(bank))
                return offsetof(struct mce, status);
@@ -451,8 +443,8 @@ static inline void mce_gather_info(struct mce *m, struct pt_regs *regs)
                                m->cs |= 3;
                }
                /* Use accurate RIP reporting if available. */
-               if (rip_msr)
-                       m->ip = mce_rdmsrl(rip_msr);
+               if (mca_cfg.rip_msr)
+                       m->ip = mce_rdmsrl(mca_cfg.rip_msr);
        }
 }
 
@@ -513,7 +505,7 @@ static int mce_ring_add(unsigned long pfn)
 
 int mce_available(struct cpuinfo_x86 *c)
 {
-       if (mce_disabled)
+       if (mca_cfg.disabled)
                return 0;
        return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
 }
@@ -565,7 +557,7 @@ static void mce_read_aux(struct mce *m, int i)
                /*
                 * Mask the reported address by the reported granularity.
                 */
-               if (mce_ser && (m->status & MCI_STATUS_MISCV)) {
+               if (mca_cfg.ser && (m->status & MCI_STATUS_MISCV)) {
                        u8 shift = MCI_MISC_ADDR_LSB(m->misc);
                        m->addr >>= shift;
                        m->addr <<= shift;
@@ -599,7 +591,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 
        mce_gather_info(&m, NULL);
 
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                if (!mce_banks[i].ctl || !test_bit(i, *b))
                        continue;
 
@@ -620,7 +612,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
                 * TBD do the same check for MCI_STATUS_EN here?
                 */
                if (!(flags & MCP_UC) &&
-                   (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)))
+                   (m.status & (mca_cfg.ser ? MCI_STATUS_S : MCI_STATUS_UC)))
                        continue;
 
                mce_read_aux(&m, i);
@@ -631,7 +623,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
                 * Don't get the IP here because it's unlikely to
                 * have anything to do with the actual error location.
                 */
-               if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
+               if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce)
                        mce_log(&m);
 
                /*
@@ -658,14 +650,14 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
 {
        int i, ret = 0;
 
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
                if (m->status & MCI_STATUS_VAL) {
                        __set_bit(i, validp);
                        if (quirk_no_way_out)
                                quirk_no_way_out(i, m, regs);
                }
-               if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY)
+               if (mce_severity(m, mca_cfg.tolerant, msg) >= MCE_PANIC_SEVERITY)
                        ret = 1;
        }
        return ret;
@@ -696,11 +688,11 @@ static int mce_timed_out(u64 *t)
        rmb();
        if (atomic_read(&mce_paniced))
                wait_for_panic();
-       if (!monarch_timeout)
+       if (!mca_cfg.monarch_timeout)
                goto out;
        if ((s64)*t < SPINUNIT) {
                /* CHECKME: Make panic default for 1 too? */
-               if (tolerant < 1)
+               if (mca_cfg.tolerant < 1)
                        mce_panic("Timeout synchronizing machine check over CPUs",
                                  NULL, NULL);
                cpu_missing = 1;
@@ -750,7 +742,8 @@ static void mce_reign(void)
         * Grade the severity of the errors of all the CPUs.
         */
        for_each_possible_cpu(cpu) {
-               int severity = mce_severity(&per_cpu(mces_seen, cpu), tolerant,
+               int severity = mce_severity(&per_cpu(mces_seen, cpu),
+                                           mca_cfg.tolerant,
                                            &nmsg);
                if (severity > global_worst) {
                        msg = nmsg;
@@ -764,7 +757,7 @@ static void mce_reign(void)
         * This dumps all the mces in the log buffer and stops the
         * other CPUs.
         */
-       if (m && global_worst >= MCE_PANIC_SEVERITY && tolerant < 3)
+       if (m && global_worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3)
                mce_panic("Fatal Machine check", m, msg);
 
        /*
@@ -777,7 +770,7 @@ static void mce_reign(void)
         * No machine check event found. Must be some external
         * source or one CPU is hung. Panic.
         */
-       if (global_worst <= MCE_KEEP_SEVERITY && tolerant < 3)
+       if (global_worst <= MCE_KEEP_SEVERITY && mca_cfg.tolerant < 3)
                mce_panic("Machine check from unknown source", NULL, NULL);
 
        /*
@@ -801,7 +794,7 @@ static int mce_start(int *no_way_out)
 {
        int order;
        int cpus = num_online_cpus();
-       u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
+       u64 timeout = (u64)mca_cfg.monarch_timeout * NSEC_PER_USEC;
 
        if (!timeout)
                return -1;
@@ -865,7 +858,7 @@ static int mce_start(int *no_way_out)
 static int mce_end(int order)
 {
        int ret = -1;
-       u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
+       u64 timeout = (u64)mca_cfg.monarch_timeout * NSEC_PER_USEC;
 
        if (!timeout)
                goto reset;
@@ -946,7 +939,7 @@ static void mce_clear_state(unsigned long *toclear)
 {
        int i;
 
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                if (test_bit(i, toclear))
                        mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
        }
@@ -1011,6 +1004,7 @@ static void mce_clear_info(struct mce_info *mi)
  */
 void do_machine_check(struct pt_regs *regs, long error_code)
 {
+       struct mca_config *cfg = &mca_cfg;
        struct mce m, *final;
        int i;
        int worst = 0;
@@ -1022,7 +1016,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
        int order;
        /*
         * If no_way_out gets set, there is no safe way to recover from this
-        * MCE.  If tolerant is cranked up, we'll try anyway.
+        * MCE.  If mca_cfg.tolerant is cranked up, we'll try anyway.
         */
        int no_way_out = 0;
        /*
@@ -1038,7 +1032,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 
        this_cpu_inc(mce_exception_count);
 
-       if (!banks)
+       if (!cfg->banks)
                goto out;
 
        mce_gather_info(&m, regs);
@@ -1065,7 +1059,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
         * because the first one to see it will clear it.
         */
        order = mce_start(&no_way_out);
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < cfg->banks; i++) {
                __clear_bit(i, toclear);
                if (!test_bit(i, valid_banks))
                        continue;
@@ -1084,7 +1078,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
                 * Non uncorrected or non signaled errors are handled by
                 * machine_check_poll. Leave them alone, unless this panics.
                 */
-               if (!(m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)) &&
+               if (!(m.status & (cfg->ser ? MCI_STATUS_S : MCI_STATUS_UC)) &&
                        !no_way_out)
                        continue;
 
@@ -1093,7 +1087,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
                 */
                add_taint(TAINT_MACHINE_CHECK);
 
-               severity = mce_severity(&m, tolerant, NULL);
+               severity = mce_severity(&m, cfg->tolerant, NULL);
 
                /*
                 * When machine check was for corrected handler don't touch,
@@ -1117,7 +1111,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
                 * When the ring overflows we just ignore the AO error.
                 * RED-PEN add some logging mechanism when
                 * usable_address or mce_add_ring fails.
-                * RED-PEN don't ignore overflow for tolerant == 0
+                * RED-PEN don't ignore overflow for mca_cfg.tolerant == 0
                 */
                if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
                        mce_ring_add(m.addr >> PAGE_SHIFT);
@@ -1149,7 +1143,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
         * issues we try to recover, or limit damage to the current
         * process.
         */
-       if (tolerant < 3) {
+       if (cfg->tolerant < 3) {
                if (no_way_out)
                        mce_panic("Fatal machine check on current CPU", &m, msg);
                if (worst == MCE_AR_SEVERITY) {
@@ -1377,11 +1371,13 @@ EXPORT_SYMBOL_GPL(mce_notify_irq);
 static int __cpuinit __mcheck_cpu_mce_banks_init(void)
 {
        int i;
+       u8 num_banks = mca_cfg.banks;
 
-       mce_banks = kzalloc(banks * sizeof(struct mce_bank), GFP_KERNEL);
+       mce_banks = kzalloc(num_banks * sizeof(struct mce_bank), GFP_KERNEL);
        if (!mce_banks)
                return -ENOMEM;
-       for (i = 0; i < banks; i++) {
+
+       for (i = 0; i < num_banks; i++) {
                struct mce_bank *b = &mce_banks[i];
 
                b->ctl = -1ULL;
@@ -1401,7 +1397,7 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
        rdmsrl(MSR_IA32_MCG_CAP, cap);
 
        b = cap & MCG_BANKCNT_MASK;
-       if (!banks)
+       if (!mca_cfg.banks)
                pr_info("CPU supports %d MCE banks\n", b);
 
        if (b > MAX_NR_BANKS) {
@@ -1411,8 +1407,9 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
        }
 
        /* Don't support asymmetric configurations today */
-       WARN_ON(banks != 0 && b != banks);
-       banks = b;
+       WARN_ON(mca_cfg.banks != 0 && b != mca_cfg.banks);
+       mca_cfg.banks = b;
+
        if (!mce_banks) {
                int err = __mcheck_cpu_mce_banks_init();
 
@@ -1422,25 +1419,29 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
 
        /* Use accurate RIP reporting if available. */
        if ((cap & MCG_EXT_P) && MCG_EXT_CNT(cap) >= 9)
-               rip_msr = MSR_IA32_MCG_EIP;
+               mca_cfg.rip_msr = MSR_IA32_MCG_EIP;
 
        if (cap & MCG_SER_P)
-               mce_ser = 1;
+               mca_cfg.ser = true;
 
        return 0;
 }
 
 static void __mcheck_cpu_init_generic(void)
 {
+       enum mcp_flags m_fl = 0;
        mce_banks_t all_banks;
        u64 cap;
        int i;
 
+       if (!mca_cfg.bootlog)
+               m_fl = MCP_DONTLOG;
+
        /*
         * Log the machine checks left over from the previous reset.
         */
        bitmap_fill(all_banks, MAX_NR_BANKS);
-       machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks);
+       machine_check_poll(MCP_UC | m_fl, &all_banks);
 
        set_in_cr4(X86_CR4_MCE);
 
@@ -1448,7 +1449,7 @@ static void __mcheck_cpu_init_generic(void)
        if (cap & MCG_CTL_P)
                wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                struct mce_bank *b = &mce_banks[i];
 
                if (!b->init)
@@ -1489,6 +1490,8 @@ static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs)
 /* Add per CPU specific workarounds here */
 static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 {
+       struct mca_config *cfg = &mca_cfg;
+
        if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
                pr_info("unknown CPU type - not enabling MCE support\n");
                return -EOPNOTSUPP;
@@ -1496,7 +1499,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 
        /* This should be disabled by the BIOS, but isn't always */
        if (c->x86_vendor == X86_VENDOR_AMD) {
-               if (c->x86 == 15 && banks > 4) {
+               if (c->x86 == 15 && cfg->banks > 4) {
                        /*
                         * disable GART TBL walk error reporting, which
                         * trips off incorrectly with the IOMMU & 3ware
@@ -1504,18 +1507,18 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
                         */
                        clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
                }
-               if (c->x86 <= 17 && mce_bootlog < 0) {
+               if (c->x86 <= 17 && cfg->bootlog < 0) {
                        /*
                         * Lots of broken BIOS around that don't clear them
                         * by default and leave crap in there. Don't log:
                         */
-                       mce_bootlog = 0;
+                       cfg->bootlog = 0;
                }
                /*
                 * Various K7s with broken bank 0 around. Always disable
                 * by default.
                 */
-                if (c->x86 == 6 && banks > 0)
+                if (c->x86 == 6 && cfg->banks > 0)
                        mce_banks[0].ctl = 0;
 
                 /*
@@ -1566,7 +1569,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
                 * valid event later, merely don't write CTL0.
                 */
 
-               if (c->x86 == 6 && c->x86_model < 0x1A && banks > 0)
+               if (c->x86 == 6 && c->x86_model < 0x1A && cfg->banks > 0)
                        mce_banks[0].init = 0;
 
                /*
@@ -1574,23 +1577,23 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
                 * synchronization with a one second timeout.
                 */
                if ((c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xe)) &&
-                       monarch_timeout < 0)
-                       monarch_timeout = USEC_PER_SEC;
+                       cfg->monarch_timeout < 0)
+                       cfg->monarch_timeout = USEC_PER_SEC;
 
                /*
                 * There are also broken BIOSes on some Pentium M and
                 * earlier systems:
                 */
-               if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)
-                       mce_bootlog = 0;
+               if (c->x86 == 6 && c->x86_model <= 13 && cfg->bootlog < 0)
+                       cfg->bootlog = 0;
 
                if (c->x86 == 6 && c->x86_model == 45)
                        quirk_no_way_out = quirk_sandybridge_ifu;
        }
-       if (monarch_timeout < 0)
-               monarch_timeout = 0;
-       if (mce_bootlog != 0)
-               mce_panic_timeout = 30;
+       if (cfg->monarch_timeout < 0)
+               cfg->monarch_timeout = 0;
+       if (cfg->bootlog != 0)
+               cfg->panic_timeout = 30;
 
        return 0;
 }
@@ -1635,7 +1638,7 @@ static void mce_start_timer(unsigned int cpu, struct timer_list *t)
 
        __this_cpu_write(mce_next_interval, iv);
 
-       if (mce_ignore_ce || !iv)
+       if (mca_cfg.ignore_ce || !iv)
                return;
 
        t->expires = round_jiffies(jiffies + iv);
@@ -1668,7 +1671,7 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) =
  */
 void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
 {
-       if (mce_disabled)
+       if (mca_cfg.disabled)
                return;
 
        if (__mcheck_cpu_ancient_init(c))
@@ -1678,7 +1681,7 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
                return;
 
        if (__mcheck_cpu_cap_init() < 0 || __mcheck_cpu_apply_quirks(c) < 0) {
-               mce_disabled = 1;
+               mca_cfg.disabled = true;
                return;
        }
 
@@ -1951,6 +1954,8 @@ static struct miscdevice mce_chrdev_device = {
  */
 static int __init mcheck_enable(char *str)
 {
+       struct mca_config *cfg = &mca_cfg;
+
        if (*str == 0) {
                enable_p5_mce();
                return 1;
@@ -1958,22 +1963,22 @@ static int __init mcheck_enable(char *str)
        if (*str == '=')
                str++;
        if (!strcmp(str, "off"))
-               mce_disabled = 1;
+               cfg->disabled = true;
        else if (!strcmp(str, "no_cmci"))
-               mce_cmci_disabled = 1;
+               cfg->cmci_disabled = true;
        else if (!strcmp(str, "dont_log_ce"))
-               mce_dont_log_ce = 1;
+               cfg->dont_log_ce = true;
        else if (!strcmp(str, "ignore_ce"))
-               mce_ignore_ce = 1;
+               cfg->ignore_ce = true;
        else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog"))
-               mce_bootlog = (str[0] == 'b');
+               cfg->bootlog = (str[0] == 'b');
        else if (!strcmp(str, "bios_cmci_threshold"))
-               mce_bios_cmci_threshold = 1;
+               cfg->bios_cmci_threshold = true;
        else if (isdigit(str[0])) {
-               get_option(&str, &tolerant);
+               get_option(&str, &(cfg->tolerant));
                if (*str == ',') {
                        ++str;
-                       get_option(&str, &monarch_timeout);
+                       get_option(&str, &(cfg->monarch_timeout));
                }
        } else {
                pr_info("mce argument %s ignored. Please use /sys\n", str);
@@ -2002,7 +2007,7 @@ static int mce_disable_error_reporting(void)
 {
        int i;
 
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                struct mce_bank *b = &mce_banks[i];
 
                if (b->init)
@@ -2142,15 +2147,15 @@ static ssize_t set_ignore_ce(struct device *s,
        if (strict_strtoull(buf, 0, &new) < 0)
                return -EINVAL;
 
-       if (mce_ignore_ce ^ !!new) {
+       if (mca_cfg.ignore_ce ^ !!new) {
                if (new) {
                        /* disable ce features */
                        mce_timer_delete_all();
                        on_each_cpu(mce_disable_cmci, NULL, 1);
-                       mce_ignore_ce = 1;
+                       mca_cfg.ignore_ce = true;
                } else {
                        /* enable ce features */
-                       mce_ignore_ce = 0;
+                       mca_cfg.ignore_ce = false;
                        on_each_cpu(mce_enable_ce, (void *)1, 1);
                }
        }
@@ -2166,14 +2171,14 @@ static ssize_t set_cmci_disabled(struct device *s,
        if (strict_strtoull(buf, 0, &new) < 0)
                return -EINVAL;
 
-       if (mce_cmci_disabled ^ !!new) {
+       if (mca_cfg.cmci_disabled ^ !!new) {
                if (new) {
                        /* disable cmci */
                        on_each_cpu(mce_disable_cmci, NULL, 1);
-                       mce_cmci_disabled = 1;
+                       mca_cfg.cmci_disabled = true;
                } else {
                        /* enable cmci */
-                       mce_cmci_disabled = 0;
+                       mca_cfg.cmci_disabled = false;
                        on_each_cpu(mce_enable_ce, NULL, 1);
                }
        }
@@ -2190,9 +2195,9 @@ static ssize_t store_int_with_restart(struct device *s,
 }
 
 static DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger);
-static DEVICE_INT_ATTR(tolerant, 0644, tolerant);
-static DEVICE_INT_ATTR(monarch_timeout, 0644, monarch_timeout);
-static DEVICE_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce);
+static DEVICE_INT_ATTR(tolerant, 0644, mca_cfg.tolerant);
+static DEVICE_INT_ATTR(monarch_timeout, 0644, mca_cfg.monarch_timeout);
+static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce);
 
 static struct dev_ext_attribute dev_attr_check_interval = {
        __ATTR(check_interval, 0644, device_show_int, store_int_with_restart),
@@ -2200,13 +2205,13 @@ static struct dev_ext_attribute dev_attr_check_interval = {
 };
 
 static struct dev_ext_attribute dev_attr_ignore_ce = {
-       __ATTR(ignore_ce, 0644, device_show_int, set_ignore_ce),
-       &mce_ignore_ce
+       __ATTR(ignore_ce, 0644, device_show_bool, set_ignore_ce),
+       &mca_cfg.ignore_ce
 };
 
 static struct dev_ext_attribute dev_attr_cmci_disabled = {
-       __ATTR(cmci_disabled, 0644, device_show_int, set_cmci_disabled),
-       &mce_cmci_disabled
+       __ATTR(cmci_disabled, 0644, device_show_bool, set_cmci_disabled),
+       &mca_cfg.cmci_disabled
 };
 
 static struct device_attribute *mce_device_attrs[] = {
@@ -2253,7 +2258,7 @@ static __cpuinit int mce_device_create(unsigned int cpu)
                if (err)
                        goto error;
        }
-       for (j = 0; j < banks; j++) {
+       for (j = 0; j < mca_cfg.banks; j++) {
                err = device_create_file(dev, &mce_banks[j].attr);
                if (err)
                        goto error2;
@@ -2285,7 +2290,7 @@ static __cpuinit void mce_device_remove(unsigned int cpu)
        for (i = 0; mce_device_attrs[i]; i++)
                device_remove_file(dev, mce_device_attrs[i]);
 
-       for (i = 0; i < banks; i++)
+       for (i = 0; i < mca_cfg.banks; i++)
                device_remove_file(dev, &mce_banks[i].attr);
 
        device_unregister(dev);
@@ -2304,7 +2309,7 @@ static void __cpuinit mce_disable_cpu(void *h)
 
        if (!(action & CPU_TASKS_FROZEN))
                cmci_clear();
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                struct mce_bank *b = &mce_banks[i];
 
                if (b->init)
@@ -2322,7 +2327,7 @@ static void __cpuinit mce_reenable_cpu(void *h)
 
        if (!(action & CPU_TASKS_FROZEN))
                cmci_reenable();
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                struct mce_bank *b = &mce_banks[i];
 
                if (b->init)
@@ -2375,7 +2380,7 @@ static __init void mce_init_banks(void)
 {
        int i;
 
-       for (i = 0; i < banks; i++) {
+       for (i = 0; i < mca_cfg.banks; i++) {
                struct mce_bank *b = &mce_banks[i];
                struct device_attribute *a = &b->attr;
 
@@ -2426,7 +2431,7 @@ device_initcall_sync(mcheck_init_device);
  */
 static int __init mcheck_disable(char *str)
 {
-       mce_disabled = 1;
+       mca_cfg.disabled = true;
        return 1;
 }
 __setup("nomce", mcheck_disable);
index 4f9a3cbfc4a33fb801ab1bf2c822a83e76122897..402c454fbff0992423ec5346a30dd7a26667e983 100644 (file)
@@ -53,7 +53,7 @@ static int cmci_supported(int *banks)
 {
        u64 cap;
 
-       if (mce_cmci_disabled || mce_ignore_ce)
+       if (mca_cfg.cmci_disabled || mca_cfg.ignore_ce)
                return 0;
 
        /*
@@ -200,7 +200,7 @@ static void cmci_discover(int banks)
                        continue;
                }
 
-               if (!mce_bios_cmci_threshold) {
+               if (!mca_cfg.bios_cmci_threshold) {
                        val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK;
                        val |= CMCI_THRESHOLD;
                } else if (!(val & MCI_CTL2_CMCI_THRESHOLD_MASK)) {
@@ -227,7 +227,7 @@ static void cmci_discover(int banks)
                         * set the thresholds properly or does not work with
                         * this boot option. Note down now and report later.
                         */
-                       if (mce_bios_cmci_threshold && bios_zero_thresh &&
+                       if (mca_cfg.bios_cmci_threshold && bios_zero_thresh &&
                                        (val & MCI_CTL2_CMCI_THRESHOLD_MASK))
                                bios_wrong_thresh = 1;
                } else {
@@ -235,7 +235,7 @@ static void cmci_discover(int banks)
                }
        }
        raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
-       if (mce_bios_cmci_threshold && bios_wrong_thresh) {
+       if (mca_cfg.bios_cmci_threshold && bios_wrong_thresh) {
                pr_info_once(
                        "bios_cmci_threshold: Some banks do not have valid thresholds set\n");
                pr_info_once(
index e4c1a41845317b1f91a72774474d9c2a4dac9293..726bf963c2276569c39c67377b64fd7a74fb539e 100644 (file)
@@ -606,7 +606,7 @@ void __init mtrr_bp_init(void)
 
                /*
                 * This is an AMD specific MSR, but we assume(hope?) that
-                * Intel will implement it to when they extend the address
+                * Intel will implement it too when they extend the address
                 * bus of the Xeon.
                 */
                if (cpuid_eax(0x80000000) >= 0x80000008) {
index 13ad89971d474557c4825d22dcb6d7da6e49ffc1..74467feb4dc55b2d4e8495992925efe5a51d77f7 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
+#include <linux/module.h>
 
 #include <asm/processor.h>
 #include <asm/hardirq.h>
 
 int in_crash_kexec;
 
+/*
+ * This is used to VMCLEAR all VMCSs loaded on the
+ * processor. And when loading kvm_intel module, the
+ * callback function pointer will be assigned.
+ *
+ * protected by rcu.
+ */
+crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL;
+EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);
+
+static inline void cpu_crash_vmclear_loaded_vmcss(void)
+{
+       crash_vmclear_fn *do_vmclear_operation = NULL;
+
+       rcu_read_lock();
+       do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss);
+       if (do_vmclear_operation)
+               do_vmclear_operation();
+       rcu_read_unlock();
+}
+
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 
 static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
@@ -46,6 +68,11 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
 #endif
        crash_save_cpu(regs, cpu);
 
+       /*
+        * VMCLEAR VMCSs loaded on all cpus if needed.
+        */
+       cpu_crash_vmclear_loaded_vmcss();
+
        /* Disable VMX or SVM if needed.
         *
         * We need to disable virtualization on all CPUs.
@@ -88,6 +115,11 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
 
        kdump_nmi_shootdown_cpus();
 
+       /*
+        * VMCLEAR VMCSs loaded on this cpu if needed.
+        */
+       cpu_crash_vmclear_loaded_vmcss();
+
        /* Booting kdump kernel with VMX or SVM enabled won't work,
         * because (among other limitations) we can't disable paging
         * with the virt flags.
index 4180a874c764d4df9d514648082eee5ac6907930..08b973f64032ba31f5e91a0558e2dc003904531a 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/apic.h>
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
+#include <asm/kvm_guest.h>
 
 static int kvmapf = 1;
 
@@ -62,6 +63,15 @@ static int parse_no_stealacc(char *arg)
 
 early_param("no-steal-acc", parse_no_stealacc);
 
+static int kvmclock_vsyscall = 1;
+static int parse_no_kvmclock_vsyscall(char *arg)
+{
+        kvmclock_vsyscall = 0;
+        return 0;
+}
+
+early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
+
 static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
 static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
 static int has_steal_clock = 0;
@@ -110,11 +120,6 @@ void kvm_async_pf_task_wait(u32 token)
        struct kvm_task_sleep_head *b = &async_pf_sleepers[key];
        struct kvm_task_sleep_node n, *e;
        DEFINE_WAIT(wait);
-       int cpu, idle;
-
-       cpu = get_cpu();
-       idle = idle_cpu(cpu);
-       put_cpu();
 
        spin_lock(&b->lock);
        e = _find_apf_task(b, token);
@@ -128,7 +133,7 @@ void kvm_async_pf_task_wait(u32 token)
 
        n.token = token;
        n.cpu = smp_processor_id();
-       n.halted = idle || preempt_count() > 1;
+       n.halted = is_idle_task(current) || preempt_count() > 1;
        init_waitqueue_head(&n.wq);
        hlist_add_head(&n.link, &b->list);
        spin_unlock(&b->lock);
@@ -471,6 +476,9 @@ void __init kvm_guest_init(void)
        if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
                apic_set_eoi_write(kvm_guest_apic_eoi_write);
 
+       if (kvmclock_vsyscall)
+               kvm_setup_vsyscall_timeinfo();
+
 #ifdef CONFIG_SMP
        smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
        register_cpu_notifier(&kvm_cpu_notifier);
index f1b42b3a186c7ec7594203b0e58c31e424181908..220a360010f8a01ffbcdce4dbd98e12503144f47 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/apic.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/memblock.h>
 
 #include <asm/x86_init.h>
 #include <asm/reboot.h>
@@ -39,7 +40,7 @@ static int parse_no_kvmclock(char *arg)
 early_param("no-kvmclock", parse_no_kvmclock);
 
 /* The hypervisor will put information about time periodically here */
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct pvclock_vcpu_time_info, hv_clock);
+static struct pvclock_vsyscall_time_info *hv_clock;
 static struct pvclock_wall_clock wall_clock;
 
 /*
@@ -52,15 +53,20 @@ static unsigned long kvm_get_wallclock(void)
        struct pvclock_vcpu_time_info *vcpu_time;
        struct timespec ts;
        int low, high;
+       int cpu;
 
        low = (int)__pa_symbol(&wall_clock);
        high = ((u64)__pa_symbol(&wall_clock) >> 32);
 
        native_write_msr(msr_kvm_wall_clock, low, high);
 
-       vcpu_time = &get_cpu_var(hv_clock);
+       preempt_disable();
+       cpu = smp_processor_id();
+
+       vcpu_time = &hv_clock[cpu].pvti;
        pvclock_read_wallclock(&wall_clock, vcpu_time, &ts);
-       put_cpu_var(hv_clock);
+
+       preempt_enable();
 
        return ts.tv_sec;
 }
@@ -74,9 +80,11 @@ static cycle_t kvm_clock_read(void)
 {
        struct pvclock_vcpu_time_info *src;
        cycle_t ret;
+       int cpu;
 
        preempt_disable_notrace();
-       src = &__get_cpu_var(hv_clock);
+       cpu = smp_processor_id();
+       src = &hv_clock[cpu].pvti;
        ret = pvclock_clocksource_read(src);
        preempt_enable_notrace();
        return ret;
@@ -99,8 +107,15 @@ static cycle_t kvm_clock_get_cycles(struct clocksource *cs)
 static unsigned long kvm_get_tsc_khz(void)
 {
        struct pvclock_vcpu_time_info *src;
-       src = &per_cpu(hv_clock, 0);
-       return pvclock_tsc_khz(src);
+       int cpu;
+       unsigned long tsc_khz;
+
+       preempt_disable();
+       cpu = smp_processor_id();
+       src = &hv_clock[cpu].pvti;
+       tsc_khz = pvclock_tsc_khz(src);
+       preempt_enable();
+       return tsc_khz;
 }
 
 static void kvm_get_preset_lpj(void)
@@ -119,10 +134,14 @@ bool kvm_check_and_clear_guest_paused(void)
 {
        bool ret = false;
        struct pvclock_vcpu_time_info *src;
+       int cpu = smp_processor_id();
 
-       src = &__get_cpu_var(hv_clock);
+       if (!hv_clock)
+               return ret;
+
+       src = &hv_clock[cpu].pvti;
        if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) {
-               __this_cpu_and(hv_clock.flags, ~PVCLOCK_GUEST_STOPPED);
+               src->flags &= ~PVCLOCK_GUEST_STOPPED;
                ret = true;
        }
 
@@ -141,9 +160,10 @@ int kvm_register_clock(char *txt)
 {
        int cpu = smp_processor_id();
        int low, high, ret;
+       struct pvclock_vcpu_time_info *src = &hv_clock[cpu].pvti;
 
-       low = (int)__pa(&per_cpu(hv_clock, cpu)) | 1;
-       high = ((u64)__pa(&per_cpu(hv_clock, cpu)) >> 32);
+       low = (int)__pa(src) | 1;
+       high = ((u64)__pa(src) >> 32);
        ret = native_write_msr_safe(msr_kvm_system_time, low, high);
        printk(KERN_INFO "kvm-clock: cpu %d, msr %x:%x, %s\n",
               cpu, high, low, txt);
@@ -197,6 +217,8 @@ static void kvm_shutdown(void)
 
 void __init kvmclock_init(void)
 {
+       unsigned long mem;
+
        if (!kvm_para_available())
                return;
 
@@ -209,8 +231,18 @@ void __init kvmclock_init(void)
        printk(KERN_INFO "kvm-clock: Using msrs %x and %x",
                msr_kvm_system_time, msr_kvm_wall_clock);
 
-       if (kvm_register_clock("boot clock"))
+       mem = memblock_alloc(sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS,
+                            PAGE_SIZE);
+       if (!mem)
+               return;
+       hv_clock = __va(mem);
+
+       if (kvm_register_clock("boot clock")) {
+               hv_clock = NULL;
+               memblock_free(mem,
+                       sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS);
                return;
+       }
        pv_time_ops.sched_clock = kvm_clock_read;
        x86_platform.calibrate_tsc = kvm_get_tsc_khz;
        x86_platform.get_wallclock = kvm_get_wallclock;
@@ -233,3 +265,37 @@ void __init kvmclock_init(void)
        if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))
                pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
 }
+
+int __init kvm_setup_vsyscall_timeinfo(void)
+{
+#ifdef CONFIG_X86_64
+       int cpu;
+       int ret;
+       u8 flags;
+       struct pvclock_vcpu_time_info *vcpu_time;
+       unsigned int size;
+
+       size = sizeof(struct pvclock_vsyscall_time_info)*NR_CPUS;
+
+       preempt_disable();
+       cpu = smp_processor_id();
+
+       vcpu_time = &hv_clock[cpu].pvti;
+       flags = pvclock_read_flags(vcpu_time);
+
+       if (!(flags & PVCLOCK_TSC_STABLE_BIT)) {
+               preempt_enable();
+               return 1;
+       }
+
+       if ((ret = pvclock_init_vsyscall(hv_clock, size))) {
+               preempt_enable();
+               return ret;
+       }
+
+       preempt_enable();
+
+       kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK;
+#endif
+       return 0;
+}
index 42eb3300dfc6c35630aab267e051678f1a677e59..85c39590c1a4b79d4384ddfddfb1cd82428f1ea2 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/gfp.h>
+#include <linux/bootmem.h>
+#include <asm/fixmap.h>
 #include <asm/pvclock.h>
 
-/*
- * These are perodically updated
- *    xen: magic shared_info page
- *    kvm: gpa registered via msr
- * and then copied here.
- */
-struct pvclock_shadow_time {
-       u64 tsc_timestamp;     /* TSC at last update of time vals.  */
-       u64 system_timestamp;  /* Time, in nanosecs, since boot.    */
-       u32 tsc_to_nsec_mul;
-       int tsc_shift;
-       u32 version;
-       u8  flags;
-};
-
 static u8 valid_flags __read_mostly = 0;
 
 void pvclock_set_flags(u8 flags)
@@ -41,34 +31,6 @@ void pvclock_set_flags(u8 flags)
        valid_flags = flags;
 }
 
-static u64 pvclock_get_nsec_offset(struct pvclock_shadow_time *shadow)
-{
-       u64 delta = native_read_tsc() - shadow->tsc_timestamp;
-       return pvclock_scale_delta(delta, shadow->tsc_to_nsec_mul,
-                                  shadow->tsc_shift);
-}
-
-/*
- * Reads a consistent set of time-base values from hypervisor,
- * into a shadow data area.
- */
-static unsigned pvclock_get_time_values(struct pvclock_shadow_time *dst,
-                                       struct pvclock_vcpu_time_info *src)
-{
-       do {
-               dst->version = src->version;
-               rmb();          /* fetch version before data */
-               dst->tsc_timestamp     = src->tsc_timestamp;
-               dst->system_timestamp  = src->system_time;
-               dst->tsc_to_nsec_mul   = src->tsc_to_system_mul;
-               dst->tsc_shift         = src->tsc_shift;
-               dst->flags             = src->flags;
-               rmb();          /* test version after fetching data */
-       } while ((src->version & 1) || (dst->version != src->version));
-
-       return dst->version;
-}
-
 unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
 {
        u64 pv_tsc_khz = 1000000ULL << 32;
@@ -88,23 +50,32 @@ void pvclock_resume(void)
        atomic64_set(&last_value, 0);
 }
 
+u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src)
+{
+       unsigned version;
+       cycle_t ret;
+       u8 flags;
+
+       do {
+               version = __pvclock_read_cycles(src, &ret, &flags);
+       } while ((src->version & 1) || version != src->version);
+
+       return flags & valid_flags;
+}
+
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
 {
-       struct pvclock_shadow_time shadow;
        unsigned version;
-       cycle_t ret, offset;
+       cycle_t ret;
        u64 last;
+       u8 flags;
 
        do {
-               version = pvclock_get_time_values(&shadow, src);
-               barrier();
-               offset = pvclock_get_nsec_offset(&shadow);
-               ret = shadow.system_timestamp + offset;
-               barrier();
-       } while (version != src->version);
+               version = __pvclock_read_cycles(src, &ret, &flags);
+       } while ((src->version & 1) || version != src->version);
 
        if ((valid_flags & PVCLOCK_TSC_STABLE_BIT) &&
-               (shadow.flags & PVCLOCK_TSC_STABLE_BIT))
+               (flags & PVCLOCK_TSC_STABLE_BIT))
                return ret;
 
        /*
@@ -156,3 +127,71 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
 
        set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
 }
+
+static struct pvclock_vsyscall_time_info *pvclock_vdso_info;
+
+static struct pvclock_vsyscall_time_info *
+pvclock_get_vsyscall_user_time_info(int cpu)
+{
+       if (!pvclock_vdso_info) {
+               BUG();
+               return NULL;
+       }
+
+       return &pvclock_vdso_info[cpu];
+}
+
+struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu)
+{
+       return &pvclock_get_vsyscall_user_time_info(cpu)->pvti;
+}
+
+#ifdef CONFIG_X86_64
+static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l,
+                               void *v)
+{
+       struct task_migration_notifier *mn = v;
+       struct pvclock_vsyscall_time_info *pvti;
+
+       pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu);
+
+       /* this is NULL when pvclock vsyscall is not initialized */
+       if (unlikely(pvti == NULL))
+               return NOTIFY_DONE;
+
+       pvti->migrate_count++;
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block pvclock_migrate = {
+       .notifier_call = pvclock_task_migrate,
+};
+
+/*
+ * Initialize the generic pvclock vsyscall state.  This will allocate
+ * a/some page(s) for the per-vcpu pvclock information, set up a
+ * fixmap mapping for the page(s)
+ */
+
+int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
+                                int size)
+{
+       int idx;
+
+       WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE);
+
+       pvclock_vdso_info = i;
+
+       for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) {
+               __set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx,
+                            __pa_symbol(i) + (idx*PAGE_SIZE),
+                            PAGE_KERNEL_VVAR);
+       }
+
+
+       register_task_migration_notifier(&pvclock_migrate);
+
+       return 0;
+}
+#endif
index ca45696f30fb8a01a4d6852388d08ab19d4bb778..23ddd558fbd52d1376576b200122448d94165708 100644 (file)
@@ -143,11 +143,7 @@ int default_check_phys_apicid_present(int phys_apicid)
 }
 #endif
 
-#ifndef CONFIG_DEBUG_BOOT_PARAMS
-struct boot_params __initdata boot_params;
-#else
 struct boot_params boot_params;
-#endif
 
 /*
  * Machine setup..
@@ -956,6 +952,10 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_initrd();
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
+       acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
+#endif
+
        reserve_crashkernel();
 
        vsmp_init();
index f84fe00fad48a4e1c2273a9f46a18b47af96204c..d4f460f962ee35d5202894223cc36732524f051f 100644 (file)
@@ -103,71 +103,13 @@ void __init tboot_probe(void)
        pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);
 }
 
-static pgd_t *tboot_pg_dir;
-static struct mm_struct tboot_mm = {
-       .mm_rb          = RB_ROOT,
-       .pgd            = swapper_pg_dir,
-       .mm_users       = ATOMIC_INIT(2),
-       .mm_count       = ATOMIC_INIT(1),
-       .mmap_sem       = __RWSEM_INITIALIZER(init_mm.mmap_sem),
-       .page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
-       .mmlist         = LIST_HEAD_INIT(init_mm.mmlist),
-};
-
 static inline void switch_to_tboot_pt(void)
 {
-       write_cr3(virt_to_phys(tboot_pg_dir));
-}
-
-static int map_tboot_page(unsigned long vaddr, unsigned long pfn,
-                         pgprot_t prot)
-{
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-
-       pgd = pgd_offset(&tboot_mm, vaddr);
-       pud = pud_alloc(&tboot_mm, pgd, vaddr);
-       if (!pud)
-               return -1;
-       pmd = pmd_alloc(&tboot_mm, pud, vaddr);
-       if (!pmd)
-               return -1;
-       pte = pte_alloc_map(&tboot_mm, NULL, pmd, vaddr);
-       if (!pte)
-               return -1;
-       set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
-       pte_unmap(pte);
-       return 0;
-}
-
-static int map_tboot_pages(unsigned long vaddr, unsigned long start_pfn,
-                          unsigned long nr)
-{
-       /* Reuse the original kernel mapping */
-       tboot_pg_dir = pgd_alloc(&tboot_mm);
-       if (!tboot_pg_dir)
-               return -1;
-
-       for (; nr > 0; nr--, vaddr += PAGE_SIZE, start_pfn++) {
-               if (map_tboot_page(vaddr, start_pfn, PAGE_KERNEL_EXEC))
-                       return -1;
-       }
-
-       return 0;
-}
-
-static void tboot_create_trampoline(void)
-{
-       u32 map_base, map_size;
-
-       /* Create identity map for tboot shutdown code. */
-       map_base = PFN_DOWN(tboot->tboot_base);
-       map_size = PFN_UP(tboot->tboot_size);
-       if (map_tboot_pages(map_base << PAGE_SHIFT, map_base, map_size))
-               panic("tboot: Error mapping tboot pages (mfns) @ 0x%x, 0x%x\n",
-                     map_base, map_size);
+#ifdef CONFIG_X86_32
+       load_cr3(initial_page_table);
+#else
+       write_cr3(real_mode_header->trampoline_pgd);
+#endif
 }
 
 #ifdef CONFIG_ACPI_SLEEP
@@ -225,14 +167,6 @@ void tboot_shutdown(u32 shutdown_type)
        if (!tboot_enabled())
                return;
 
-       /*
-        * if we're being called before the 1:1 mapping is set up then just
-        * return and let the normal shutdown happen; this should only be
-        * due to very early panic()
-        */
-       if (!tboot_pg_dir)
-               return;
-
        /* if this is S3 then set regions to MAC */
        if (shutdown_type == TB_SHUTDOWN_S3)
                if (tboot_setup_sleep())
@@ -343,8 +277,6 @@ static __init int tboot_late_init(void)
        if (!tboot_enabled())
                return 0;
 
-       tboot_create_trampoline();
-
        atomic_set(&ap_wfs_count, 0);
        register_hotcpu_notifier(&tboot_cpu_notifier);
 
index 5c9687b1bde6706293e199331e7c866f1b752095..1dfe69cc78a81b90cc7d1edefc6d8e53f51c38c8 100644 (file)
@@ -182,7 +182,7 @@ static void mark_screen_rdonly(struct mm_struct *mm)
        if (pud_none_or_clear_bad(pud))
                goto out;
        pmd = pmd_offset(pud, 0xA0000);
-       split_huge_page_pmd(mm, pmd);
+       split_huge_page_pmd_mm(mm, 0xA0000, pmd);
        if (pmd_none_or_clear_bad(pmd))
                goto out;
        pte = pte_offset_map_lock(mm, pmd, 0xA0000, &ptl);
index ec79e773342ea58cc28d614b7a1ca911f3677694..a20ecb5b6cbf3543490ab6a74a969aa45a1862c5 100644 (file)
@@ -320,6 +320,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                if (index == 0) {
                        entry->ebx &= kvm_supported_word9_x86_features;
                        cpuid_mask(&entry->ebx, 9);
+                       // TSC_ADJUST is emulated
+                       entry->ebx |= F(TSC_ADJUST);
                } else
                        entry->ebx = 0;
                entry->eax = 0;
@@ -659,6 +661,7 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
        } else
                *eax = *ebx = *ecx = *edx = 0;
 }
+EXPORT_SYMBOL_GPL(kvm_cpuid);
 
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 {
index 58fc5148882857c014a49b78403a597424c08e64..b7fd07984888e9f348c04df9043c6596928c1cd3 100644 (file)
@@ -31,6 +31,14 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
 
+static inline bool guest_cpuid_has_tsc_adjust(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 7, 0);
+       return best && (best->ebx & bit(X86_FEATURE_TSC_ADJUST));
+}
+
 static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index bba39bfa1c4b03806cf1f42773cd8041f18b8759..a27e763711087df9e095f440b7e6aaf76cfeff5b 100644 (file)
@@ -676,8 +676,9 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
                                                addr.seg);
                if (!usable)
                        goto bad;
-               /* code segment or read-only data segment */
-               if (((desc.type & 8) || !(desc.type & 2)) && write)
+               /* code segment in protected mode or read-only data segment */
+               if ((((ctxt->mode != X86EMUL_MODE_REAL) && (desc.type & 8))
+                                       || !(desc.type & 2)) && write)
                        goto bad;
                /* unreadable code segment */
                if (!fetch && (desc.type & 8) && !(desc.type & 2))
index 43e9fadca5d080a4e98a65735cbe071102742911..9392f527f107490b9fc8d036f971994c3823b31d 100644 (file)
@@ -1011,7 +1011,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
                local_irq_save(flags);
 
                now = apic->lapic_timer.timer.base->get_time();
-               guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+               guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, native_read_tsc());
                if (likely(tscdeadline > guest_tsc)) {
                        ns = (tscdeadline - guest_tsc) * 1000000ULL;
                        do_div(ns, this_tsc_khz);
index 6f85fe0bf958987f0275f1fa25e2b9e5240aad02..01d7c2ad05f5760bb656fef17f512c66e5e87dce 100644 (file)
@@ -2382,12 +2382,20 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
            || (!vcpu->arch.mmu.direct_map && write_fault
                && !is_write_protection(vcpu) && !user_fault)) {
 
+               /*
+                * There are two cases:
+                * - the one is other vcpu creates new sp in the window
+                *   between mapping_level() and acquiring mmu-lock.
+                * - the another case is the new sp is created by itself
+                *   (page-fault path) when guest uses the target gfn as
+                *   its page table.
+                * Both of these cases can be fixed by allowing guest to
+                * retry the access, it will refault, then we can establish
+                * the mapping by using small page.
+                */
                if (level > PT_PAGE_TABLE_LEVEL &&
-                   has_wrprotected_page(vcpu->kvm, gfn, level)) {
-                       ret = 1;
-                       drop_spte(vcpu->kvm, sptep);
+                   has_wrprotected_page(vcpu->kvm, gfn, level))
                        goto done;
-               }
 
                spte |= PT_WRITABLE_MASK | SPTE_MMU_WRITEABLE;
 
@@ -2505,6 +2513,14 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
        mmu_free_roots(vcpu);
 }
 
+static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
+{
+       int bit7;
+
+       bit7 = (gpte >> 7) & 1;
+       return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
+}
+
 static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
                                     bool no_dirty_log)
 {
@@ -2517,6 +2533,26 @@ static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
        return gfn_to_pfn_memslot_atomic(slot, gfn);
 }
 
+static bool prefetch_invalid_gpte(struct kvm_vcpu *vcpu,
+                                 struct kvm_mmu_page *sp, u64 *spte,
+                                 u64 gpte)
+{
+       if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
+               goto no_present;
+
+       if (!is_present_gpte(gpte))
+               goto no_present;
+
+       if (!(gpte & PT_ACCESSED_MASK))
+               goto no_present;
+
+       return false;
+
+no_present:
+       drop_spte(vcpu->kvm, spte);
+       return true;
+}
+
 static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
                                    struct kvm_mmu_page *sp,
                                    u64 *start, u64 *end)
@@ -2671,7 +2707,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
         * PT_PAGE_TABLE_LEVEL and there would be no adjustment done
         * here.
         */
-       if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
+       if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
            level == PT_PAGE_TABLE_LEVEL &&
            PageTransCompound(pfn_to_page(pfn)) &&
            !has_wrprotected_page(vcpu->kvm, gfn, PT_DIRECTORY_LEVEL)) {
@@ -2699,18 +2735,13 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
        }
 }
 
-static bool mmu_invalid_pfn(pfn_t pfn)
-{
-       return unlikely(is_invalid_pfn(pfn));
-}
-
 static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
                                pfn_t pfn, unsigned access, int *ret_val)
 {
        bool ret = true;
 
        /* The pfn is invalid, report the error! */
-       if (unlikely(is_invalid_pfn(pfn))) {
+       if (unlikely(is_error_pfn(pfn))) {
                *ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
                goto exit;
        }
@@ -2862,7 +2893,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code,
                return r;
 
        spin_lock(&vcpu->kvm->mmu_lock);
-       if (mmu_notifier_retry(vcpu, mmu_seq))
+       if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
                goto out_unlock;
        kvm_mmu_free_some_pages(vcpu);
        if (likely(!force_pt_level))
@@ -3331,7 +3362,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
                return r;
 
        spin_lock(&vcpu->kvm->mmu_lock);
-       if (mmu_notifier_retry(vcpu, mmu_seq))
+       if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
                goto out_unlock;
        kvm_mmu_free_some_pages(vcpu);
        if (likely(!force_pt_level))
@@ -3399,14 +3430,6 @@ static void paging_free(struct kvm_vcpu *vcpu)
        nonpaging_free(vcpu);
 }
 
-static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
-{
-       int bit7;
-
-       bit7 = (gpte >> 7) & 1;
-       return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
-}
-
 static inline void protect_clean_gpte(unsigned *access, unsigned gpte)
 {
        unsigned mask;
index 714e2c01a6fe0fd714f66146c8613f17f31f4a68..891eb6d93b8b32b2d4bb7f85c45702d314d14615 100644 (file)
@@ -305,51 +305,43 @@ static int FNAME(walk_addr_nested)(struct guest_walker *walker,
                                        addr, access);
 }
 
-static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
-                                   struct kvm_mmu_page *sp, u64 *spte,
-                                   pt_element_t gpte)
+static bool
+FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+                    u64 *spte, pt_element_t gpte, bool no_dirty_log)
 {
-       if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
-               goto no_present;
-
-       if (!is_present_gpte(gpte))
-               goto no_present;
-
-       if (!(gpte & PT_ACCESSED_MASK))
-               goto no_present;
-
-       return false;
-
-no_present:
-       drop_spte(vcpu->kvm, spte);
-       return true;
-}
-
-static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-                             u64 *spte, const void *pte)
-{
-       pt_element_t gpte;
        unsigned pte_access;
+       gfn_t gfn;
        pfn_t pfn;
 
-       gpte = *(const pt_element_t *)pte;
-       if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
-               return;
+       if (prefetch_invalid_gpte(vcpu, sp, spte, gpte))
+               return false;
 
        pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
+
+       gfn = gpte_to_gfn(gpte);
        pte_access = sp->role.access & gpte_access(vcpu, gpte);
        protect_clean_gpte(&pte_access, gpte);
-       pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
-       if (mmu_invalid_pfn(pfn))
-               return;
+       pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
+                       no_dirty_log && (pte_access & ACC_WRITE_MASK));
+       if (is_error_pfn(pfn))
+               return false;
 
        /*
-        * we call mmu_set_spte() with host_writable = true because that
-        * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
+        * we call mmu_set_spte() with host_writable = true because
+        * pte_prefetch_gfn_to_pfn always gets a writable pfn.
         */
        mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
-                    NULL, PT_PAGE_TABLE_LEVEL,
-                    gpte_to_gfn(gpte), pfn, true, true);
+                    NULL, PT_PAGE_TABLE_LEVEL, gfn, pfn, true, true);
+
+       return true;
+}
+
+static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+                             u64 *spte, const void *pte)
+{
+       pt_element_t gpte = *(const pt_element_t *)pte;
+
+       FNAME(prefetch_gpte)(vcpu, sp, spte, gpte, false);
 }
 
 static bool FNAME(gpte_changed)(struct kvm_vcpu *vcpu,
@@ -395,53 +387,34 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
        spte = sp->spt + i;
 
        for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) {
-               pt_element_t gpte;
-               unsigned pte_access;
-               gfn_t gfn;
-               pfn_t pfn;
-
                if (spte == sptep)
                        continue;
 
                if (is_shadow_present_pte(*spte))
                        continue;
 
-               gpte = gptep[i];
-
-               if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
-                       continue;
-
-               pte_access = sp->role.access & gpte_access(vcpu, gpte);
-               protect_clean_gpte(&pte_access, gpte);
-               gfn = gpte_to_gfn(gpte);
-               pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
-                                     pte_access & ACC_WRITE_MASK);
-               if (mmu_invalid_pfn(pfn))
+               if (!FNAME(prefetch_gpte)(vcpu, sp, spte, gptep[i], true))
                        break;
-
-               mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
-                            NULL, PT_PAGE_TABLE_LEVEL, gfn,
-                            pfn, true, true);
        }
 }
 
 /*
  * Fetch a shadow pte for a specific level in the paging hierarchy.
+ * If the guest tries to write a write-protected page, we need to
+ * emulate this operation, return 1 to indicate this case.
  */
-static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                         struct guest_walker *gw,
                         int user_fault, int write_fault, int hlevel,
-                        int *emulate, pfn_t pfn, bool map_writable,
-                        bool prefault)
+                        pfn_t pfn, bool map_writable, bool prefault)
 {
-       unsigned access = gw->pt_access;
        struct kvm_mmu_page *sp = NULL;
-       int top_level;
-       unsigned direct_access;
        struct kvm_shadow_walk_iterator it;
+       unsigned direct_access, access = gw->pt_access;
+       int top_level, emulate = 0;
 
        if (!is_present_gpte(gw->ptes[gw->level - 1]))
-               return NULL;
+               return 0;
 
        direct_access = gw->pte_access;
 
@@ -505,17 +478,17 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 
        clear_sp_write_flooding_count(it.sptep);
        mmu_set_spte(vcpu, it.sptep, access, gw->pte_access,
-                    user_fault, write_fault, emulate, it.level,
+                    user_fault, write_fault, &emulate, it.level,
                     gw->gfn, pfn, prefault, map_writable);
        FNAME(pte_prefetch)(vcpu, gw, it.sptep);
 
-       return it.sptep;
+       return emulate;
 
 out_gpte_changed:
        if (sp)
                kvm_mmu_put_page(sp, it.sptep);
        kvm_release_pfn_clean(pfn);
-       return NULL;
+       return 0;
 }
 
 /*
@@ -538,8 +511,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
        int write_fault = error_code & PFERR_WRITE_MASK;
        int user_fault = error_code & PFERR_USER_MASK;
        struct guest_walker walker;
-       u64 *sptep;
-       int emulate = 0;
        int r;
        pfn_t pfn;
        int level = PT_PAGE_TABLE_LEVEL;
@@ -594,24 +565,20 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
                return r;
 
        spin_lock(&vcpu->kvm->mmu_lock);
-       if (mmu_notifier_retry(vcpu, mmu_seq))
+       if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
                goto out_unlock;
 
        kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
        kvm_mmu_free_some_pages(vcpu);
        if (!force_pt_level)
                transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
-       sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
-                            level, &emulate, pfn, map_writable, prefault);
-       (void)sptep;
-       pgprintk("%s: shadow pte %p %llx emulate %d\n", __func__,
-                sptep, *sptep, emulate);
-
+       r = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
+                        level, pfn, map_writable, prefault);
        ++vcpu->stat.pf_fixed;
        kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
        spin_unlock(&vcpu->kvm->mmu_lock);
 
-       return emulate;
+       return r;
 
 out_unlock:
        spin_unlock(&vcpu->kvm->mmu_lock);
@@ -757,7 +724,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
                                          sizeof(pt_element_t)))
                        return -EINVAL;
 
-               if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
+               if (prefetch_invalid_gpte(vcpu, sp, &sp->spt[i], gpte)) {
                        vcpu->kvm->tlbs_dirty++;
                        continue;
                }
index d017df3899ef23a2dc339ebcf7c7d88b6eef6e8e..d29d3cd1c15657619086e5e4877766aaefc02214 100644 (file)
@@ -20,6 +20,7 @@
 #include "mmu.h"
 #include "kvm_cache_regs.h"
 #include "x86.h"
+#include "cpuid.h"
 
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
@@ -630,15 +631,12 @@ static int svm_hardware_enable(void *garbage)
                return -EBUSY;
 
        if (!has_svm()) {
-               printk(KERN_ERR "svm_hardware_enable: err EOPNOTSUPP on %d\n",
-                      me);
+               pr_err("%s: err EOPNOTSUPP on %d\n", __func__, me);
                return -EINVAL;
        }
        sd = per_cpu(svm_data, me);
-
        if (!sd) {
-               printk(KERN_ERR "svm_hardware_enable: svm_data is NULL on %d\n",
-                      me);
+               pr_err("%s: svm_data is NULL on %d\n", __func__, me);
                return -EINVAL;
        }
 
@@ -1012,6 +1010,13 @@ static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
        svm->tsc_ratio             = ratio;
 }
 
+static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+
+       return svm->vmcb->control.tsc_offset;
+}
+
 static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1189,6 +1194,8 @@ static void init_vmcb(struct vcpu_svm *svm)
 static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
+       u32 dummy;
+       u32 eax = 1;
 
        init_vmcb(svm);
 
@@ -1197,8 +1204,9 @@ static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
                svm->vmcb->save.cs.base = svm->vcpu.arch.sipi_vector << 12;
                svm->vmcb->save.cs.selector = svm->vcpu.arch.sipi_vector << 8;
        }
-       vcpu->arch.regs_avail = ~0;
-       vcpu->arch.regs_dirty = ~0;
+
+       kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
+       kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
 
        return 0;
 }
@@ -1254,11 +1262,6 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
        svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
        svm->asid_generation = 0;
        init_vmcb(svm);
-       kvm_write_tsc(&svm->vcpu, 0);
-
-       err = fx_init(&svm->vcpu);
-       if (err)
-               goto free_page4;
 
        svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
        if (kvm_vcpu_is_bsp(&svm->vcpu))
@@ -1268,8 +1271,6 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
 
        return &svm->vcpu;
 
-free_page4:
-       __free_page(hsave_page);
 free_page3:
        __free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER);
 free_page2:
@@ -3008,11 +3009,11 @@ static int cr8_write_interception(struct vcpu_svm *svm)
        return 0;
 }
 
-u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu)
+u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
 {
        struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
        return vmcb->control.tsc_offset +
-               svm_scale_tsc(vcpu, native_read_tsc());
+               svm_scale_tsc(vcpu, host_tsc);
 }
 
 static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
@@ -3131,13 +3132,15 @@ static int svm_set_vm_cr(struct kvm_vcpu *vcpu, u64 data)
        return 0;
 }
 
-static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
+static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
+       u32 ecx = msr->index;
+       u64 data = msr->data;
        switch (ecx) {
        case MSR_IA32_TSC:
-               kvm_write_tsc(vcpu, data);
+               kvm_write_tsc(vcpu, msr);
                break;
        case MSR_STAR:
                svm->vmcb->save.star = data;
@@ -3192,20 +3195,24 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
                vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
                break;
        default:
-               return kvm_set_msr_common(vcpu, ecx, data);
+               return kvm_set_msr_common(vcpu, msr);
        }
        return 0;
 }
 
 static int wrmsr_interception(struct vcpu_svm *svm)
 {
+       struct msr_data msr;
        u32 ecx = svm->vcpu.arch.regs[VCPU_REGS_RCX];
        u64 data = (svm->vcpu.arch.regs[VCPU_REGS_RAX] & -1u)
                | ((u64)(svm->vcpu.arch.regs[VCPU_REGS_RDX] & -1u) << 32);
 
+       msr.data = data;
+       msr.index = ecx;
+       msr.host_initiated = false;
 
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
-       if (svm_set_msr(&svm->vcpu, ecx, data)) {
+       if (svm_set_msr(&svm->vcpu, &msr)) {
                trace_kvm_msr_write_ex(ecx, data);
                kvm_inject_gp(&svm->vcpu, 0);
        } else {
@@ -4302,6 +4309,7 @@ static struct kvm_x86_ops svm_x86_ops = {
        .has_wbinvd_exit = svm_has_wbinvd_exit,
 
        .set_tsc_khz = svm_set_tsc_khz,
+       .read_tsc_offset = svm_read_tsc_offset,
        .write_tsc_offset = svm_write_tsc_offset,
        .adjust_tsc_offset = svm_adjust_tsc_offset,
        .compute_tsc_offset = svm_compute_tsc_offset,
index bca63f04dccb61a8326f9375e1d7142b4ffa38a5..fe5e00ed70369c129442a61df519bfe1823f6112 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/tracepoint.h>
 #include <asm/vmx.h>
 #include <asm/svm.h>
+#include <asm/clocksource.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
@@ -754,6 +755,68 @@ TRACE_EVENT(
                  __entry->write ? "Write" : "Read",
                  __entry->gpa_match ? "GPA" : "GVA")
 );
+
+#ifdef CONFIG_X86_64
+
+#define host_clocks                                    \
+       {VCLOCK_NONE, "none"},                          \
+       {VCLOCK_TSC,  "tsc"},                           \
+       {VCLOCK_HPET, "hpet"}                           \
+
+TRACE_EVENT(kvm_update_master_clock,
+       TP_PROTO(bool use_master_clock, unsigned int host_clock, bool offset_matched),
+       TP_ARGS(use_master_clock, host_clock, offset_matched),
+
+       TP_STRUCT__entry(
+               __field(                bool,   use_master_clock        )
+               __field(        unsigned int,   host_clock              )
+               __field(                bool,   offset_matched          )
+       ),
+
+       TP_fast_assign(
+               __entry->use_master_clock       = use_master_clock;
+               __entry->host_clock             = host_clock;
+               __entry->offset_matched         = offset_matched;
+       ),
+
+       TP_printk("masterclock %d hostclock %s offsetmatched %u",
+                 __entry->use_master_clock,
+                 __print_symbolic(__entry->host_clock, host_clocks),
+                 __entry->offset_matched)
+);
+
+TRACE_EVENT(kvm_track_tsc,
+       TP_PROTO(unsigned int vcpu_id, unsigned int nr_matched,
+                unsigned int online_vcpus, bool use_master_clock,
+                unsigned int host_clock),
+       TP_ARGS(vcpu_id, nr_matched, online_vcpus, use_master_clock,
+               host_clock),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   vcpu_id                 )
+               __field(        unsigned int,   nr_vcpus_matched_tsc    )
+               __field(        unsigned int,   online_vcpus            )
+               __field(        bool,           use_master_clock        )
+               __field(        unsigned int,   host_clock              )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_id                = vcpu_id;
+               __entry->nr_vcpus_matched_tsc   = nr_matched;
+               __entry->online_vcpus           = online_vcpus;
+               __entry->use_master_clock       = use_master_clock;
+               __entry->host_clock             = host_clock;
+       ),
+
+       TP_printk("vcpu_id %u masterclock %u offsetmatched %u nr_online %u"
+                 " hostclock %s",
+                 __entry->vcpu_id, __entry->use_master_clock,
+                 __entry->nr_vcpus_matched_tsc, __entry->online_vcpus,
+                 __print_symbolic(__entry->host_clock, host_clocks))
+);
+
+#endif /* CONFIG_X86_64 */
+
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
index f85815945fc6d62532c9735747759452cbe7c101..9120ae1901e42804828dbde5db41707c113b0cbc 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/i387.h>
 #include <asm/xcr.h>
 #include <asm/perf_event.h>
+#include <asm/kexec.h>
 
 #include "trace.h"
 
@@ -802,11 +803,6 @@ static inline bool cpu_has_vmx_ept_ad_bits(void)
        return vmx_capability.ept & VMX_EPT_AD_BIT;
 }
 
-static inline bool cpu_has_vmx_invept_individual_addr(void)
-{
-       return vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT;
-}
-
 static inline bool cpu_has_vmx_invept_context(void)
 {
        return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
@@ -992,6 +988,46 @@ static void vmcs_load(struct vmcs *vmcs)
                       vmcs, phys_addr);
 }
 
+#ifdef CONFIG_KEXEC
+/*
+ * This bitmap is used to indicate whether the vmclear
+ * operation is enabled on all cpus. All disabled by
+ * default.
+ */
+static cpumask_t crash_vmclear_enabled_bitmap = CPU_MASK_NONE;
+
+static inline void crash_enable_local_vmclear(int cpu)
+{
+       cpumask_set_cpu(cpu, &crash_vmclear_enabled_bitmap);
+}
+
+static inline void crash_disable_local_vmclear(int cpu)
+{
+       cpumask_clear_cpu(cpu, &crash_vmclear_enabled_bitmap);
+}
+
+static inline int crash_local_vmclear_enabled(int cpu)
+{
+       return cpumask_test_cpu(cpu, &crash_vmclear_enabled_bitmap);
+}
+
+static void crash_vmclear_local_loaded_vmcss(void)
+{
+       int cpu = raw_smp_processor_id();
+       struct loaded_vmcs *v;
+
+       if (!crash_local_vmclear_enabled(cpu))
+               return;
+
+       list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
+                           loaded_vmcss_on_cpu_link)
+               vmcs_clear(v->vmcs);
+}
+#else
+static inline void crash_enable_local_vmclear(int cpu) { }
+static inline void crash_disable_local_vmclear(int cpu) { }
+#endif /* CONFIG_KEXEC */
+
 static void __loaded_vmcs_clear(void *arg)
 {
        struct loaded_vmcs *loaded_vmcs = arg;
@@ -1001,15 +1037,28 @@ static void __loaded_vmcs_clear(void *arg)
                return; /* vcpu migration can race with cpu offline */
        if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
                per_cpu(current_vmcs, cpu) = NULL;
+       crash_disable_local_vmclear(cpu);
        list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
+
+       /*
+        * we should ensure updating loaded_vmcs->loaded_vmcss_on_cpu_link
+        * is before setting loaded_vmcs->vcpu to -1 which is done in
+        * loaded_vmcs_init. Otherwise, other cpu can see vcpu = -1 fist
+        * then adds the vmcs into percpu list before it is deleted.
+        */
+       smp_wmb();
+
        loaded_vmcs_init(loaded_vmcs);
+       crash_enable_local_vmclear(cpu);
 }
 
 static void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
 {
-       if (loaded_vmcs->cpu != -1)
-               smp_call_function_single(
-                       loaded_vmcs->cpu, __loaded_vmcs_clear, loaded_vmcs, 1);
+       int cpu = loaded_vmcs->cpu;
+
+       if (cpu != -1)
+               smp_call_function_single(cpu,
+                        __loaded_vmcs_clear, loaded_vmcs, 1);
 }
 
 static inline void vpid_sync_vcpu_single(struct vcpu_vmx *vmx)
@@ -1051,17 +1100,6 @@ static inline void ept_sync_context(u64 eptp)
        }
 }
 
-static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
-{
-       if (enable_ept) {
-               if (cpu_has_vmx_invept_individual_addr())
-                       __invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
-                                       eptp, gpa);
-               else
-                       ept_sync_context(eptp);
-       }
-}
-
 static __always_inline unsigned long vmcs_readl(unsigned long field)
 {
        unsigned long value;
@@ -1535,8 +1573,18 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
                kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
                local_irq_disable();
+               crash_disable_local_vmclear(cpu);
+
+               /*
+                * Read loaded_vmcs->cpu should be before fetching
+                * loaded_vmcs->loaded_vmcss_on_cpu_link.
+                * See the comments in __loaded_vmcs_clear().
+                */
+               smp_rmb();
+
                list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
                         &per_cpu(loaded_vmcss_on_cpu, cpu));
+               crash_enable_local_vmclear(cpu);
                local_irq_enable();
 
                /*
@@ -1839,11 +1887,10 @@ static u64 guest_read_tsc(void)
  * Like guest_read_tsc, but always returns L1's notion of the timestamp
  * counter, even if a nested guest (L2) is currently running.
  */
-u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu)
+u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
 {
-       u64 host_tsc, tsc_offset;
+       u64 tsc_offset;
 
-       rdtscll(host_tsc);
        tsc_offset = is_guest_mode(vcpu) ?
                to_vmx(vcpu)->nested.vmcs01_tsc_offset :
                vmcs_read64(TSC_OFFSET);
@@ -1866,6 +1913,11 @@ static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
                WARN(1, "user requested TSC rate below hardware speed\n");
 }
 
+static u64 vmx_read_tsc_offset(struct kvm_vcpu *vcpu)
+{
+       return vmcs_read64(TSC_OFFSET);
+}
+
 /*
  * writes 'offset' into guest's timestamp counter offset register
  */
@@ -2202,15 +2254,17 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
  * Returns 0 on success, non-0 otherwise.
  * Assumes vcpu_load() was already called.
  */
-static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct shared_msr_entry *msr;
        int ret = 0;
+       u32 msr_index = msr_info->index;
+       u64 data = msr_info->data;
 
        switch (msr_index) {
        case MSR_EFER:
-               ret = kvm_set_msr_common(vcpu, msr_index, data);
+               ret = kvm_set_msr_common(vcpu, msr_info);
                break;
 #ifdef CONFIG_X86_64
        case MSR_FS_BASE:
@@ -2236,7 +2290,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                vmcs_writel(GUEST_SYSENTER_ESP, data);
                break;
        case MSR_IA32_TSC:
-               kvm_write_tsc(vcpu, data);
+               kvm_write_tsc(vcpu, msr_info);
                break;
        case MSR_IA32_CR_PAT:
                if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
@@ -2244,7 +2298,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                        vcpu->arch.pat = data;
                        break;
                }
-               ret = kvm_set_msr_common(vcpu, msr_index, data);
+               ret = kvm_set_msr_common(vcpu, msr_info);
+               break;
+       case MSR_IA32_TSC_ADJUST:
+               ret = kvm_set_msr_common(vcpu, msr_info);
                break;
        case MSR_TSC_AUX:
                if (!vmx->rdtscp_enabled)
@@ -2267,7 +2324,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                        }
                        break;
                }
-               ret = kvm_set_msr_common(vcpu, msr_index, data);
+               ret = kvm_set_msr_common(vcpu, msr_info);
        }
 
        return ret;
@@ -2341,6 +2398,18 @@ static int hardware_enable(void *garbage)
                return -EBUSY;
 
        INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
+
+       /*
+        * Now we can enable the vmclear operation in kdump
+        * since the loaded_vmcss_on_cpu list on this cpu
+        * has been initialized.
+        *
+        * Though the cpu is not in VMX operation now, there
+        * is no problem to enable the vmclear operation
+        * for the loaded_vmcss_on_cpu list is empty!
+        */
+       crash_enable_local_vmclear(cpu);
+
        rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
 
        test_bits = FEATURE_CONTROL_LOCKED;
@@ -2697,6 +2766,7 @@ static void fix_pmode_dataseg(struct kvm_vcpu *vcpu, int seg, struct kvm_segment
        if (!(vmcs_readl(sf->base) == tmp.base && tmp.s)) {
                tmp.base = vmcs_readl(sf->base);
                tmp.selector = vmcs_read16(sf->selector);
+               tmp.dpl = tmp.selector & SELECTOR_RPL_MASK;
                tmp.s = 1;
        }
        vmx_set_segment(vcpu, &tmp, seg);
@@ -3246,7 +3316,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
         * unrestricted guest like Westmere to older host that don't have
         * unrestricted guest like Nehelem.
         */
-       if (!enable_unrestricted_guest && vmx->rmode.vm86_active) {
+       if (vmx->rmode.vm86_active) {
                switch (seg) {
                case VCPU_SREG_CS:
                        vmcs_write32(GUEST_CS_AR_BYTES, 0xf3);
@@ -3897,8 +3967,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
        set_cr4_guest_host_mask(vmx);
 
-       kvm_write_tsc(&vmx->vcpu, 0);
-
        return 0;
 }
 
@@ -3908,8 +3976,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        u64 msr;
        int ret;
 
-       vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
-
        vmx->rmode.vm86_active = 0;
 
        vmx->soft_vnmi_blocked = 0;
@@ -3921,10 +3987,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                msr |= MSR_IA32_APICBASE_BSP;
        kvm_set_apic_base(&vmx->vcpu, msr);
 
-       ret = fx_init(&vmx->vcpu);
-       if (ret != 0)
-               goto out;
-
        vmx_segment_cache_clear(vmx);
 
        seg_setup(VCPU_SREG_CS);
@@ -3965,7 +4027,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                kvm_rip_write(vcpu, 0xfff0);
        else
                kvm_rip_write(vcpu, 0);
-       kvm_register_write(vcpu, VCPU_REGS_RSP, 0);
 
        vmcs_writel(GUEST_GDTR_BASE, 0);
        vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
@@ -4015,7 +4076,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        /* HACK: Don't enable emulation on guest boot/reset */
        vmx->emulation_required = 0;
 
-out:
        return ret;
 }
 
@@ -4287,16 +4347,6 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        if (is_machine_check(intr_info))
                return handle_machine_check(vcpu);
 
-       if ((vect_info & VECTORING_INFO_VALID_MASK) &&
-           !is_page_fault(intr_info)) {
-               vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-               vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
-               vcpu->run->internal.ndata = 2;
-               vcpu->run->internal.data[0] = vect_info;
-               vcpu->run->internal.data[1] = intr_info;
-               return 0;
-       }
-
        if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
                return 1;  /* already handled by vmx_vcpu_run() */
 
@@ -4315,6 +4365,22 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        error_code = 0;
        if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+
+       /*
+        * The #PF with PFEC.RSVD = 1 indicates the guest is accessing
+        * MMIO, it is better to report an internal error.
+        * See the comments in vmx_handle_exit.
+        */
+       if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+           !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) {
+               vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
+               vcpu->run->internal.ndata = 2;
+               vcpu->run->internal.data[0] = vect_info;
+               vcpu->run->internal.data[1] = intr_info;
+               return 0;
+       }
+
        if (is_page_fault(intr_info)) {
                /* EPT won't cause page fault directly */
                BUG_ON(enable_ept);
@@ -4626,11 +4692,15 @@ static int handle_rdmsr(struct kvm_vcpu *vcpu)
 
 static int handle_wrmsr(struct kvm_vcpu *vcpu)
 {
+       struct msr_data msr;
        u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
        u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
                | ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
 
-       if (vmx_set_msr(vcpu, ecx, data) != 0) {
+       msr.data = data;
+       msr.index = ecx;
+       msr.host_initiated = false;
+       if (vmx_set_msr(vcpu, &msr) != 0) {
                trace_kvm_msr_write_ex(ecx, data);
                kvm_inject_gp(vcpu, 0);
                return 1;
@@ -4827,11 +4897,6 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
 
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
-       if (exit_qualification & (1 << 6)) {
-               printk(KERN_ERR "EPT: GPA exceeds GAW!\n");
-               return -EINVAL;
-       }
-
        gla_validity = (exit_qualification >> 7) & 0x3;
        if (gla_validity != 0x3 && gla_validity != 0x1 && gla_validity != 0) {
                printk(KERN_ERR "EPT: Handling EPT violation failed!\n");
@@ -5979,13 +6044,24 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
                return 0;
        }
 
+       /*
+        * Note:
+        * Do not try to fix EXIT_REASON_EPT_MISCONFIG if it caused by
+        * delivery event since it indicates guest is accessing MMIO.
+        * The vm-exit can be triggered again after return to guest that
+        * will cause infinite loop.
+        */
        if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
                        (exit_reason != EXIT_REASON_EXCEPTION_NMI &&
                        exit_reason != EXIT_REASON_EPT_VIOLATION &&
-                       exit_reason != EXIT_REASON_TASK_SWITCH))
-               printk(KERN_WARNING "%s: unexpected, valid vectoring info "
-                      "(0x%x) and exit reason is 0x%x\n",
-                      __func__, vectoring_info, exit_reason);
+                       exit_reason != EXIT_REASON_TASK_SWITCH)) {
+               vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
+               vcpu->run->internal.ndata = 2;
+               vcpu->run->internal.data[0] = vectoring_info;
+               vcpu->run->internal.data[1] = exit_reason;
+               return 0;
+       }
 
        if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked &&
            !(is_guest_mode(vcpu) && nested_cpu_has_virtual_nmis(
@@ -7309,6 +7385,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
 
        .set_tsc_khz = vmx_set_tsc_khz,
+       .read_tsc_offset = vmx_read_tsc_offset,
        .write_tsc_offset = vmx_write_tsc_offset,
        .adjust_tsc_offset = vmx_adjust_tsc_offset,
        .compute_tsc_offset = vmx_compute_tsc_offset,
@@ -7367,6 +7444,11 @@ static int __init vmx_init(void)
        if (r)
                goto out3;
 
+#ifdef CONFIG_KEXEC
+       rcu_assign_pointer(crash_vmclear_loaded_vmcss,
+                          crash_vmclear_local_loaded_vmcss);
+#endif
+
        vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
        vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
        vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
@@ -7404,6 +7486,11 @@ static void __exit vmx_exit(void)
        free_page((unsigned long)vmx_io_bitmap_b);
        free_page((unsigned long)vmx_io_bitmap_a);
 
+#ifdef CONFIG_KEXEC
+       rcu_assign_pointer(crash_vmclear_loaded_vmcss, NULL);
+       synchronize_rcu();
+#endif
+
        kvm_exit();
 }
 
index 4f7641756be2d046cd55e3d59de76e145d3c39ae..76f54461f7cb83a13a0ec8e76add8968532a1eae 100644 (file)
@@ -46,6 +46,8 @@
 #include <linux/uaccess.h>
 #include <linux/hash.h>
 #include <linux/pci.h>
+#include <linux/timekeeper_internal.h>
+#include <linux/pvclock_gtod.h>
 #include <trace/events/kvm.h>
 
 #define CREATE_TRACE_POINTS
@@ -158,7 +160,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
+static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
+
+static int kvm_vcpu_reset(struct kvm_vcpu *vcpu);
 
 static inline void kvm_async_pf_hash_reset(struct kvm_vcpu *vcpu)
 {
@@ -633,7 +637,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
        }
 
        if (is_long_mode(vcpu)) {
-               if (kvm_read_cr4(vcpu) & X86_CR4_PCIDE) {
+               if (kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE)) {
                        if (cr3 & CR3_PCID_ENABLED_RESERVED_BITS)
                                return 1;
                } else
@@ -827,6 +831,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static const u32 emulated_msrs[] = {
+       MSR_IA32_TSC_ADJUST,
        MSR_IA32_TSCDEADLINE,
        MSR_IA32_MISC_ENABLE,
        MSR_IA32_MCG_STATUS,
@@ -886,9 +891,9 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
  * Returns 0 on success, non-0 otherwise.
  * Assumes vcpu_load() was already called.
  */
-int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 {
-       return kvm_x86_ops->set_msr(vcpu, msr_index, data);
+       return kvm_x86_ops->set_msr(vcpu, msr);
 }
 
 /*
@@ -896,9 +901,63 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
  */
 static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
 {
-       return kvm_set_msr(vcpu, index, *data);
+       struct msr_data msr;
+
+       msr.data = *data;
+       msr.index = index;
+       msr.host_initiated = true;
+       return kvm_set_msr(vcpu, &msr);
 }
 
+#ifdef CONFIG_X86_64
+struct pvclock_gtod_data {
+       seqcount_t      seq;
+
+       struct { /* extract of a clocksource struct */
+               int vclock_mode;
+               cycle_t cycle_last;
+               cycle_t mask;
+               u32     mult;
+               u32     shift;
+       } clock;
+
+       /* open coded 'struct timespec' */
+       u64             monotonic_time_snsec;
+       time_t          monotonic_time_sec;
+};
+
+static struct pvclock_gtod_data pvclock_gtod_data;
+
+static void update_pvclock_gtod(struct timekeeper *tk)
+{
+       struct pvclock_gtod_data *vdata = &pvclock_gtod_data;
+
+       write_seqcount_begin(&vdata->seq);
+
+       /* copy pvclock gtod data */
+       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->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++;
+       }
+
+       write_seqcount_end(&vdata->seq);
+}
+#endif
+
+
 static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
 {
        int version;
@@ -995,6 +1054,10 @@ static inline u64 get_kernel_ns(void)
        return timespec_to_ns(&ts);
 }
 
+#ifdef CONFIG_X86_64
+static atomic_t kvm_guest_has_master_clock = ATOMIC_INIT(0);
+#endif
+
 static DEFINE_PER_CPU(unsigned long, cpu_tsc_khz);
 unsigned long max_tsc_khz;
 
@@ -1046,12 +1109,47 @@ static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
        return tsc;
 }
 
-void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
+void kvm_track_tsc_matching(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_X86_64
+       bool vcpus_matched;
+       bool do_request = false;
+       struct kvm_arch *ka = &vcpu->kvm->arch;
+       struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+
+       vcpus_matched = (ka->nr_vcpus_matched_tsc + 1 ==
+                        atomic_read(&vcpu->kvm->online_vcpus));
+
+       if (vcpus_matched && gtod->clock.vclock_mode == VCLOCK_TSC)
+               if (!ka->use_master_clock)
+                       do_request = 1;
+
+       if (!vcpus_matched && ka->use_master_clock)
+                       do_request = 1;
+
+       if (do_request)
+               kvm_make_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu);
+
+       trace_kvm_track_tsc(vcpu->vcpu_id, ka->nr_vcpus_matched_tsc,
+                           atomic_read(&vcpu->kvm->online_vcpus),
+                           ka->use_master_clock, gtod->clock.vclock_mode);
+#endif
+}
+
+static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 offset)
+{
+       u64 curr_offset = kvm_x86_ops->read_tsc_offset(vcpu);
+       vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset;
+}
+
+void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
 {
        struct kvm *kvm = vcpu->kvm;
        u64 offset, ns, elapsed;
        unsigned long flags;
        s64 usdiff;
+       bool matched;
+       u64 data = msr->data;
 
        raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
        offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
@@ -1094,6 +1192,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
                        offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
                        pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
                }
+               matched = true;
        } else {
                /*
                 * We split periods of matched TSC writes into generations.
@@ -1108,6 +1207,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
                kvm->arch.cur_tsc_nsec = ns;
                kvm->arch.cur_tsc_write = data;
                kvm->arch.cur_tsc_offset = offset;
+               matched = false;
                pr_debug("kvm: new tsc generation %u, clock %llu\n",
                         kvm->arch.cur_tsc_generation, data);
        }
@@ -1129,26 +1229,195 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
        vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec;
        vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write;
 
+       if (guest_cpuid_has_tsc_adjust(vcpu) && !msr->host_initiated)
+               update_ia32_tsc_adjust_msr(vcpu, offset);
        kvm_x86_ops->write_tsc_offset(vcpu, offset);
        raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
+
+       spin_lock(&kvm->arch.pvclock_gtod_sync_lock);
+       if (matched)
+               kvm->arch.nr_vcpus_matched_tsc++;
+       else
+               kvm->arch.nr_vcpus_matched_tsc = 0;
+
+       kvm_track_tsc_matching(vcpu);
+       spin_unlock(&kvm->arch.pvclock_gtod_sync_lock);
 }
 
 EXPORT_SYMBOL_GPL(kvm_write_tsc);
 
+#ifdef CONFIG_X86_64
+
+static cycle_t read_tsc(void)
+{
+       cycle_t ret;
+       u64 last;
+
+       /*
+        * Empirically, a fence (of type that depends on the CPU)
+        * before rdtsc is enough to ensure that rdtsc is ordered
+        * with respect to loads.  The various CPU manuals are unclear
+        * as to whether rdtsc can be reordered with later loads,
+        * but no one has ever seen it happen.
+        */
+       rdtsc_barrier();
+       ret = (cycle_t)vget_cycles();
+
+       last = pvclock_gtod_data.clock.cycle_last;
+
+       if (likely(ret >= last))
+               return ret;
+
+       /*
+        * GCC likes to generate cmov here, but this branch is extremely
+        * predictable (it's just a funciton of time and the likely is
+        * very likely) and there's a data dependence, so force GCC
+        * to generate a branch instead.  I don't barrier() because
+        * we don't actually need a barrier, and if this function
+        * ever gets inlined it will generate worse code.
+        */
+       asm volatile ("");
+       return last;
+}
+
+static inline u64 vgettsc(cycle_t *cycle_now)
+{
+       long v;
+       struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+
+       *cycle_now = read_tsc();
+
+       v = (*cycle_now - gtod->clock.cycle_last) & gtod->clock.mask;
+       return v * gtod->clock.mult;
+}
+
+static int do_monotonic(struct timespec *ts, cycle_t *cycle_now)
+{
+       unsigned long seq;
+       u64 ns;
+       int mode;
+       struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+
+       ts->tv_nsec = 0;
+       do {
+               seq = read_seqcount_begin(&gtod->seq);
+               mode = gtod->clock.vclock_mode;
+               ts->tv_sec = gtod->monotonic_time_sec;
+               ns = gtod->monotonic_time_snsec;
+               ns += vgettsc(cycle_now);
+               ns >>= gtod->clock.shift;
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
+       timespec_add_ns(ts, ns);
+
+       return mode;
+}
+
+/* returns true if host is using tsc clocksource */
+static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
+{
+       struct timespec ts;
+
+       /* checked again under seqlock below */
+       if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
+               return false;
+
+       if (do_monotonic(&ts, cycle_now) != VCLOCK_TSC)
+               return false;
+
+       monotonic_to_bootbased(&ts);
+       *kernel_ns = timespec_to_ns(&ts);
+
+       return true;
+}
+#endif
+
+/*
+ *
+ * Assuming a stable TSC across physical CPUS, and a stable TSC
+ * across virtual CPUs, the following condition is possible.
+ * Each numbered line represents an event visible to both
+ * CPUs at the next numbered event.
+ *
+ * "timespecX" represents host monotonic time. "tscX" represents
+ * RDTSC value.
+ *
+ *             VCPU0 on CPU0           |       VCPU1 on CPU1
+ *
+ * 1.  read timespec0,tsc0
+ * 2.                                  | timespec1 = timespec0 + N
+ *                                     | tsc1 = tsc0 + M
+ * 3. transition to guest              | transition to guest
+ * 4. ret0 = timespec0 + (rdtsc - tsc0) |
+ * 5.                                  | ret1 = timespec1 + (rdtsc - tsc1)
+ *                                     | ret1 = timespec0 + N + (rdtsc - (tsc0 + M))
+ *
+ * Since ret0 update is visible to VCPU1 at time 5, to obey monotonicity:
+ *
+ *     - ret0 < ret1
+ *     - timespec0 + (rdtsc - tsc0) < timespec0 + N + (rdtsc - (tsc0 + M))
+ *             ...
+ *     - 0 < N - M => M < N
+ *
+ * That is, when timespec0 != timespec1, M < N. Unfortunately that is not
+ * always the case (the difference between two distinct xtime instances
+ * might be smaller then the difference between corresponding TSC reads,
+ * when updating guest vcpus pvclock areas).
+ *
+ * To avoid that problem, do not allow visibility of distinct
+ * system_timestamp/tsc_timestamp values simultaneously: use a master
+ * copy of host monotonic time values. Update that master copy
+ * in lockstep.
+ *
+ * Rely on synchronization of host TSCs and guest TSCs for monotonicity.
+ *
+ */
+
+static void pvclock_update_vm_gtod_copy(struct kvm *kvm)
+{
+#ifdef CONFIG_X86_64
+       struct kvm_arch *ka = &kvm->arch;
+       int vclock_mode;
+       bool host_tsc_clocksource, vcpus_matched;
+
+       vcpus_matched = (ka->nr_vcpus_matched_tsc + 1 ==
+                       atomic_read(&kvm->online_vcpus));
+
+       /*
+        * If the host uses TSC clock, then passthrough TSC as stable
+        * to the guest.
+        */
+       host_tsc_clocksource = kvm_get_time_and_clockread(
+                                       &ka->master_kernel_ns,
+                                       &ka->master_cycle_now);
+
+       ka->use_master_clock = host_tsc_clocksource & vcpus_matched;
+
+       if (ka->use_master_clock)
+               atomic_set(&kvm_guest_has_master_clock, 1);
+
+       vclock_mode = pvclock_gtod_data.clock.vclock_mode;
+       trace_kvm_update_master_clock(ka->use_master_clock, vclock_mode,
+                                       vcpus_matched);
+#endif
+}
+
 static int kvm_guest_time_update(struct kvm_vcpu *v)
 {
-       unsigned long flags;
+       unsigned long flags, this_tsc_khz;
        struct kvm_vcpu_arch *vcpu = &v->arch;
+       struct kvm_arch *ka = &v->kvm->arch;
        void *shared_kaddr;
-       unsigned long this_tsc_khz;
        s64 kernel_ns, max_kernel_ns;
-       u64 tsc_timestamp;
+       u64 tsc_timestamp, host_tsc;
+       struct pvclock_vcpu_time_info *guest_hv_clock;
        u8 pvclock_flags;
+       bool use_master_clock;
+
+       kernel_ns = 0;
+       host_tsc = 0;
 
        /* Keep irq disabled to prevent changes to the clock */
        local_irq_save(flags);
-       tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
-       kernel_ns = get_kernel_ns();
        this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
        if (unlikely(this_tsc_khz == 0)) {
                local_irq_restore(flags);
@@ -1156,6 +1425,24 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                return 1;
        }
 
+       /*
+        * If the host uses TSC clock, then passthrough TSC as stable
+        * to the guest.
+        */
+       spin_lock(&ka->pvclock_gtod_sync_lock);
+       use_master_clock = ka->use_master_clock;
+       if (use_master_clock) {
+               host_tsc = ka->master_cycle_now;
+               kernel_ns = ka->master_kernel_ns;
+       }
+       spin_unlock(&ka->pvclock_gtod_sync_lock);
+       if (!use_master_clock) {
+               host_tsc = native_read_tsc();
+               kernel_ns = get_kernel_ns();
+       }
+
+       tsc_timestamp = kvm_x86_ops->read_l1_tsc(v, host_tsc);
+
        /*
         * We may have to catch up the TSC to match elapsed wall clock
         * time for two reasons, even if kvmclock is used.
@@ -1217,23 +1504,20 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                vcpu->hw_tsc_khz = this_tsc_khz;
        }
 
-       if (max_kernel_ns > kernel_ns)
-               kernel_ns = max_kernel_ns;
-
+       /* with a master <monotonic time, tsc value> tuple,
+        * pvclock clock reads always increase at the (scaled) rate
+        * of guest TSC - no need to deal with sampling errors.
+        */
+       if (!use_master_clock) {
+               if (max_kernel_ns > kernel_ns)
+                       kernel_ns = max_kernel_ns;
+       }
        /* With all the info we got, fill in the values */
        vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
        vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
        vcpu->last_kernel_ns = kernel_ns;
        vcpu->last_guest_tsc = tsc_timestamp;
 
-       pvclock_flags = 0;
-       if (vcpu->pvclock_set_guest_stopped_request) {
-               pvclock_flags |= PVCLOCK_GUEST_STOPPED;
-               vcpu->pvclock_set_guest_stopped_request = false;
-       }
-
-       vcpu->hv_clock.flags = pvclock_flags;
-
        /*
         * The interface expects us to write an even number signaling that the
         * update is finished. Since the guest won't see the intermediate
@@ -1243,6 +1527,22 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 
        shared_kaddr = kmap_atomic(vcpu->time_page);
 
+       guest_hv_clock = shared_kaddr + vcpu->time_offset;
+
+       /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
+       pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
+
+       if (vcpu->pvclock_set_guest_stopped_request) {
+               pvclock_flags |= PVCLOCK_GUEST_STOPPED;
+               vcpu->pvclock_set_guest_stopped_request = false;
+       }
+
+       /* If the host uses TSC clocksource, then it is stable */
+       if (use_master_clock)
+               pvclock_flags |= PVCLOCK_TSC_STABLE_BIT;
+
+       vcpu->hv_clock.flags = pvclock_flags;
+
        memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
               sizeof(vcpu->hv_clock));
 
@@ -1572,9 +1872,11 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
                &vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
 }
 
-int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
        bool pr = false;
+       u32 msr = msr_info->index;
+       u64 data = msr_info->data;
 
        switch (msr) {
        case MSR_EFER:
@@ -1625,6 +1927,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
        case MSR_IA32_TSCDEADLINE:
                kvm_set_lapic_tscdeadline_msr(vcpu, data);
                break;
+       case MSR_IA32_TSC_ADJUST:
+               if (guest_cpuid_has_tsc_adjust(vcpu)) {
+                       if (!msr_info->host_initiated) {
+                               u64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
+                               kvm_x86_ops->adjust_tsc_offset(vcpu, adj, true);
+                       }
+                       vcpu->arch.ia32_tsc_adjust_msr = data;
+               }
+               break;
        case MSR_IA32_MISC_ENABLE:
                vcpu->arch.ia32_misc_enable_msr = data;
                break;
@@ -1984,6 +2295,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_IA32_TSCDEADLINE:
                data = kvm_get_lapic_tscdeadline_msr(vcpu);
                break;
+       case MSR_IA32_TSC_ADJUST:
+               data = (u64)vcpu->arch.ia32_tsc_adjust_msr;
+               break;
        case MSR_IA32_MISC_ENABLE:
                data = vcpu->arch.ia32_misc_enable_msr;
                break;
@@ -2342,7 +2656,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                        kvm_x86_ops->write_tsc_offset(vcpu, offset);
                        vcpu->arch.tsc_catchup = 1;
                }
-               kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
+               /*
+                * On a host with synchronized TSC, there is no need to update
+                * kvmclock on vcpu->cpu migration
+                */
+               if (!vcpu->kvm->arch.use_master_clock || vcpu->cpu == -1)
+                       kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
                if (vcpu->cpu != cpu)
                        kvm_migrate_timers(vcpu);
                vcpu->cpu = cpu;
@@ -2691,15 +3010,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                if (!vcpu->arch.apic)
                        goto out;
                u.lapic = memdup_user(argp, sizeof(*u.lapic));
-               if (IS_ERR(u.lapic)) {
-                       r = PTR_ERR(u.lapic);
-                       goto out;
-               }
+               if (IS_ERR(u.lapic))
+                       return PTR_ERR(u.lapic);
 
                r = kvm_vcpu_ioctl_set_lapic(vcpu, u.lapic);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_INTERRUPT: {
@@ -2709,16 +3023,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                if (copy_from_user(&irq, argp, sizeof irq))
                        goto out;
                r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_NMI: {
                r = kvm_vcpu_ioctl_nmi(vcpu);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_SET_CPUID: {
@@ -2729,8 +3037,6 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
                        goto out;
                r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
-               if (r)
-                       goto out;
                break;
        }
        case KVM_SET_CPUID2: {
@@ -2742,8 +3048,6 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                        goto out;
                r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid,
                                              cpuid_arg->entries);
-               if (r)
-                       goto out;
                break;
        }
        case KVM_GET_CPUID2: {
@@ -2875,10 +3179,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        }
        case KVM_SET_XSAVE: {
                u.xsave = memdup_user(argp, sizeof(*u.xsave));
-               if (IS_ERR(u.xsave)) {
-                       r = PTR_ERR(u.xsave);
-                       goto out;
-               }
+               if (IS_ERR(u.xsave))
+                       return PTR_ERR(u.xsave);
 
                r = kvm_vcpu_ioctl_x86_set_xsave(vcpu, u.xsave);
                break;
@@ -2900,10 +3202,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        }
        case KVM_SET_XCRS: {
                u.xcrs = memdup_user(argp, sizeof(*u.xcrs));
-               if (IS_ERR(u.xcrs)) {
-                       r = PTR_ERR(u.xcrs);
-                       goto out;
-               }
+               if (IS_ERR(u.xcrs))
+                       return PTR_ERR(u.xcrs);
 
                r = kvm_vcpu_ioctl_x86_set_xcrs(vcpu, u.xcrs);
                break;
@@ -2951,7 +3251,7 @@ static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
        int ret;
 
        if (addr > (unsigned int)(-3 * PAGE_SIZE))
-               return -1;
+               return -EINVAL;
        ret = kvm_x86_ops->set_tss_addr(kvm, addr);
        return ret;
 }
@@ -3212,8 +3512,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
        switch (ioctl) {
        case KVM_SET_TSS_ADDR:
                r = kvm_vm_ioctl_set_tss_addr(kvm, arg);
-               if (r < 0)
-                       goto out;
                break;
        case KVM_SET_IDENTITY_MAP_ADDR: {
                u64 ident_addr;
@@ -3222,14 +3520,10 @@ long kvm_arch_vm_ioctl(struct file *filp,
                if (copy_from_user(&ident_addr, argp, sizeof ident_addr))
                        goto out;
                r = kvm_vm_ioctl_set_identity_map_addr(kvm, ident_addr);
-               if (r < 0)
-                       goto out;
                break;
        }
        case KVM_SET_NR_MMU_PAGES:
                r = kvm_vm_ioctl_set_nr_mmu_pages(kvm, arg);
-               if (r)
-                       goto out;
                break;
        case KVM_GET_NR_MMU_PAGES:
                r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
@@ -3320,8 +3614,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = 0;
        get_irqchip_out:
                kfree(chip);
-               if (r)
-                       goto out;
                break;
        }
        case KVM_SET_IRQCHIP: {
@@ -3343,8 +3635,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = 0;
        set_irqchip_out:
                kfree(chip);
-               if (r)
-                       goto out;
                break;
        }
        case KVM_GET_PIT: {
@@ -3371,9 +3661,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
                if (!kvm->arch.vpit)
                        goto out;
                r = kvm_vm_ioctl_set_pit(kvm, &u.ps);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_GET_PIT2: {
@@ -3397,9 +3684,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
                if (!kvm->arch.vpit)
                        goto out;
                r = kvm_vm_ioctl_set_pit2(kvm, &u.ps2);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_REINJECT_CONTROL: {
@@ -3408,9 +3692,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
                if (copy_from_user(&control, argp, sizeof(control)))
                        goto out;
                r = kvm_vm_ioctl_reinject(kvm, &control);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_XEN_HVM_CONFIG: {
@@ -4273,7 +4554,12 @@ static int emulator_get_msr(struct x86_emulate_ctxt *ctxt,
 static int emulator_set_msr(struct x86_emulate_ctxt *ctxt,
                            u32 msr_index, u64 data)
 {
-       return kvm_set_msr(emul_to_vcpu(ctxt), msr_index, data);
+       struct msr_data msr;
+
+       msr.data = data;
+       msr.index = msr_index;
+       msr.host_initiated = false;
+       return kvm_set_msr(emul_to_vcpu(ctxt), &msr);
 }
 
 static int emulator_read_pmc(struct x86_emulate_ctxt *ctxt,
@@ -4495,7 +4781,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
         * instruction -> ...
         */
        pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa));
-       if (!is_error_pfn(pfn)) {
+       if (!is_error_noslot_pfn(pfn)) {
                kvm_release_pfn_clean(pfn);
                return true;
        }
@@ -4881,6 +5167,50 @@ static void kvm_set_mmio_spte_mask(void)
        kvm_mmu_set_mmio_spte_mask(mask);
 }
 
+#ifdef CONFIG_X86_64
+static void pvclock_gtod_update_fn(struct work_struct *work)
+{
+       struct kvm *kvm;
+
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       raw_spin_lock(&kvm_lock);
+       list_for_each_entry(kvm, &vm_list, vm_list)
+               kvm_for_each_vcpu(i, vcpu, kvm)
+                       set_bit(KVM_REQ_MASTERCLOCK_UPDATE, &vcpu->requests);
+       atomic_set(&kvm_guest_has_master_clock, 0);
+       raw_spin_unlock(&kvm_lock);
+}
+
+static DECLARE_WORK(pvclock_gtod_work, pvclock_gtod_update_fn);
+
+/*
+ * Notification about pvclock gtod data update.
+ */
+static int pvclock_gtod_notify(struct notifier_block *nb, unsigned long unused,
+                              void *priv)
+{
+       struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+       struct timekeeper *tk = priv;
+
+       update_pvclock_gtod(tk);
+
+       /* disable master clock if host does not trust, or does not
+        * use, TSC clocksource
+        */
+       if (gtod->clock.vclock_mode != VCLOCK_TSC &&
+           atomic_read(&kvm_guest_has_master_clock) != 0)
+               queue_work(system_long_wq, &pvclock_gtod_work);
+
+       return 0;
+}
+
+static struct notifier_block pvclock_gtod_notifier = {
+       .notifier_call = pvclock_gtod_notify,
+};
+#endif
+
 int kvm_arch_init(void *opaque)
 {
        int r;
@@ -4922,6 +5252,10 @@ int kvm_arch_init(void *opaque)
                host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
 
        kvm_lapic_init();
+#ifdef CONFIG_X86_64
+       pvclock_gtod_register_notifier(&pvclock_gtod_notifier);
+#endif
+
        return 0;
 
 out:
@@ -4936,6 +5270,9 @@ void kvm_arch_exit(void)
                cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block,
                                            CPUFREQ_TRANSITION_NOTIFIER);
        unregister_hotcpu_notifier(&kvmclock_cpu_notifier_block);
+#ifdef CONFIG_X86_64
+       pvclock_gtod_unregister_notifier(&pvclock_gtod_notifier);
+#endif
        kvm_x86_ops = NULL;
        kvm_mmu_module_exit();
 }
@@ -5059,7 +5396,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
 
-int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
+static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
 {
        struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
        char instruction[3];
@@ -5235,6 +5572,29 @@ static void process_nmi(struct kvm_vcpu *vcpu)
        kvm_make_request(KVM_REQ_EVENT, vcpu);
 }
 
+static void kvm_gen_update_masterclock(struct kvm *kvm)
+{
+#ifdef CONFIG_X86_64
+       int i;
+       struct kvm_vcpu *vcpu;
+       struct kvm_arch *ka = &kvm->arch;
+
+       spin_lock(&ka->pvclock_gtod_sync_lock);
+       kvm_make_mclock_inprogress_request(kvm);
+       /* no guest entries from this point */
+       pvclock_update_vm_gtod_copy(kvm);
+
+       kvm_for_each_vcpu(i, vcpu, kvm)
+               set_bit(KVM_REQ_CLOCK_UPDATE, &vcpu->requests);
+
+       /* guest entries allowed */
+       kvm_for_each_vcpu(i, vcpu, kvm)
+               clear_bit(KVM_REQ_MCLOCK_INPROGRESS, &vcpu->requests);
+
+       spin_unlock(&ka->pvclock_gtod_sync_lock);
+#endif
+}
+
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 {
        int r;
@@ -5247,6 +5607,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                        kvm_mmu_unload(vcpu);
                if (kvm_check_request(KVM_REQ_MIGRATE_TIMER, vcpu))
                        __kvm_migrate_timers(vcpu);
+               if (kvm_check_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu))
+                       kvm_gen_update_masterclock(vcpu->kvm);
                if (kvm_check_request(KVM_REQ_CLOCK_UPDATE, vcpu)) {
                        r = kvm_guest_time_update(vcpu);
                        if (unlikely(r))
@@ -5362,7 +5724,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
        if (hw_breakpoint_active())
                hw_breakpoint_restore();
 
-       vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+       vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu,
+                                                          native_read_tsc());
 
        vcpu->mode = OUTSIDE_GUEST_MODE;
        smp_wmb();
@@ -5419,7 +5782,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                pr_debug("vcpu %d received sipi with vector # %x\n",
                         vcpu->vcpu_id, vcpu->arch.sipi_vector);
                kvm_lapic_reset(vcpu);
-               r = kvm_arch_vcpu_reset(vcpu);
+               r = kvm_vcpu_reset(vcpu);
                if (r)
                        return r;
                vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
@@ -6047,7 +6410,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        r = vcpu_load(vcpu);
        if (r)
                return r;
-       r = kvm_arch_vcpu_reset(vcpu);
+       r = kvm_vcpu_reset(vcpu);
        if (r == 0)
                r = kvm_mmu_setup(vcpu);
        vcpu_put(vcpu);
@@ -6055,6 +6418,23 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        return r;
 }
 
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+       int r;
+       struct msr_data msr;
+
+       r = vcpu_load(vcpu);
+       if (r)
+               return r;
+       msr.data = 0x0;
+       msr.index = MSR_IA32_TSC;
+       msr.host_initiated = true;
+       kvm_write_tsc(vcpu, &msr);
+       vcpu_put(vcpu);
+
+       return r;
+}
+
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        int r;
@@ -6069,7 +6449,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
        kvm_x86_ops->vcpu_free(vcpu);
 }
 
-int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
+static int kvm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
        atomic_set(&vcpu->arch.nmi_queued, 0);
        vcpu->arch.nmi_pending = 0;
@@ -6092,6 +6472,10 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
 
        kvm_pmu_reset(vcpu);
 
+       memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs));
+       vcpu->arch.regs_avail = ~0;
+       vcpu->arch.regs_dirty = ~0;
+
        return kvm_x86_ops->vcpu_reset(vcpu);
 }
 
@@ -6168,6 +6552,8 @@ int kvm_arch_hardware_enable(void *garbage)
                        kvm_for_each_vcpu(i, vcpu, kvm) {
                                vcpu->arch.tsc_offset_adjustment += delta_cyc;
                                vcpu->arch.last_host_tsc = local_tsc;
+                               set_bit(KVM_REQ_MASTERCLOCK_UPDATE,
+                                       &vcpu->requests);
                        }
 
                        /*
@@ -6258,10 +6644,17 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask, GFP_KERNEL))
                goto fail_free_mce_banks;
 
+       r = fx_init(vcpu);
+       if (r)
+               goto fail_free_wbinvd_dirty_mask;
+
+       vcpu->arch.ia32_tsc_adjust_msr = 0x0;
        kvm_async_pf_hash_reset(vcpu);
        kvm_pmu_init(vcpu);
 
        return 0;
+fail_free_wbinvd_dirty_mask:
+       free_cpumask_var(vcpu->arch.wbinvd_dirty_mask);
 fail_free_mce_banks:
        kfree(vcpu->arch.mce_banks);
 fail_free_lapic:
@@ -6305,6 +6698,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
        raw_spin_lock_init(&kvm->arch.tsc_write_lock);
        mutex_init(&kvm->arch.apic_map_lock);
+       spin_lock_init(&kvm->arch.pvclock_gtod_sync_lock);
+
+       pvclock_update_vm_gtod_copy(kvm);
 
        return 0;
 }
index 2b5219c12ac8566c24a837ccff3f2fb14db1c7f8..e224f7a671b66fb23a291cdf25c5eda7f4bdd157 100644 (file)
@@ -112,7 +112,7 @@ void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
 
-void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data);
+void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr);
 
 int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
        gva_t addr, void *val, unsigned int bytes,
index 642d8805bc1bb967f03715d3585a9cd0fa99e5bb..df4176cdbb321e8223dfdffb056b35981c3c63f8 100644 (file)
@@ -1412,7 +1412,7 @@ __init void lguest_init(void)
 
        /* We don't have features.  We have puppies!  Puppies! */
 #ifdef CONFIG_X86_MCE
-       mce_disabled = 1;
+       mca_cfg.disabled = true;
 #endif
 #ifdef CONFIG_ACPI
        acpi_disabled = 1;
index 7a529cbab7ad1dd96d70cdc323f6943c9219b8f7..027088f2f7dd9b6b836abfe410088579106a7324 100644 (file)
@@ -803,20 +803,6 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
        __bad_area(regs, error_code, address, SEGV_ACCERR);
 }
 
-/* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */
-static void
-out_of_memory(struct pt_regs *regs, unsigned long error_code,
-             unsigned long address)
-{
-       /*
-        * We ran out of memory, call the OOM killer, and return the userspace
-        * (which will retry the fault, or kill us if we got oom-killed):
-        */
-       up_read(&current->mm->mmap_sem);
-
-       pagefault_out_of_memory();
-}
-
 static void
 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
          unsigned int fault)
@@ -879,7 +865,14 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
                        return 1;
                }
 
-               out_of_memory(regs, error_code, address);
+               up_read(&current->mm->mmap_sem);
+
+               /*
+                * We ran out of memory, call the OOM killer, and return the
+                * userspace (which will retry the fault, or kill us if we got
+                * oom-killed):
+                */
+               pagefault_out_of_memory();
        } else {
                if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
                             VM_FAULT_HWPOISON_LARGE))
index 3baff255adac6472570298d7e9ee60df75e93dfc..2ead3c8a4c8419da92a61fbba35eb695e5205dde 100644 (file)
@@ -630,7 +630,9 @@ void __init paging_init(void)
         *       numa support is not compiled in, and later node_set_state
         *       will not set it back.
         */
-       node_clear_state(0, N_NORMAL_MEMORY);
+       node_clear_state(0, N_MEMORY);
+       if (N_MEMORY != N_NORMAL_MEMORY)
+               node_clear_state(0, N_NORMAL_MEMORY);
 
        zone_sizes_init();
 }
index a718e0d23503fdc4bb3149d4ad5c7046458f2a57..931930a96160b2de489b1dc9c955b676c7a250dd 100644 (file)
@@ -919,11 +919,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
 
        /*
         * On success we use clflush, when the CPU supports it to
-        * avoid the wbindv. If the CPU does not support it and in the
-        * error case we fall back to cpa_flush_all (which uses
-        * wbindv):
+        * avoid the wbindv. If the CPU does not support it, in the
+        * error case, and during early boot (for EFI) we fall back
+        * to cpa_flush_all (which uses wbinvd):
         */
-       if (!ret && cpu_has_clflush) {
+       if (early_boot_irqs_disabled)
+               __cpa_flush_all((void *)(long)cache);
+       else if (!ret && cpu_has_clflush) {
                if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
                        cpa_flush_array(addr, numpages, cache,
                                        cpa.flags, pages);
index 8573b83a63d037bf2f7eb09c8922b94c2b535c45..217eb705fac073188fb18e908b675340834e1f97 100644 (file)
@@ -137,7 +137,7 @@ static void pgd_dtor(pgd_t *pgd)
  * against pageattr.c; it is the unique case in which a valid change
  * of kernel pagetables can't be lazily synchronized by vmalloc faults.
  * vmalloc faults work because attached pagetables are never freed.
- * -- wli
+ * -- nyc
  */
 
 #ifdef CONFIG_X86_PAE
index 3af5a1e79c9ccc5ebe98c64b3af921562f397141..ee0af58ca5bd7e5e75ae22885a887ff86381fe46 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_STA2X11)           += sta2x11-fixup.o
 obj-$(CONFIG_X86_VISWS)                += visws.o
 
 obj-$(CONFIG_X86_NUMAQ)                += numaq_32.o
+obj-$(CONFIG_X86_NUMACHIP)     += numachip.o
 
 obj-$(CONFIG_X86_INTEL_MID)    += mrst.o
 
index 192397c98606690f34d1d510052738f04bbdd931..0c01261fe5a846bc2500fc24c1ff56c2b432e86f 100644 (file)
@@ -12,6 +12,7 @@ struct pci_root_info {
        char name[16];
        unsigned int res_num;
        struct resource *res;
+       resource_size_t *res_offset;
        struct pci_sysdata sd;
 #ifdef CONFIG_PCI_MMCONFIG
        bool mcfg_added;
@@ -22,6 +23,7 @@ struct pci_root_info {
 };
 
 static bool pci_use_crs = true;
+static bool pci_ignore_seg = false;
 
 static int __init set_use_crs(const struct dmi_system_id *id)
 {
@@ -35,7 +37,14 @@ static int __init set_nouse_crs(const struct dmi_system_id *id)
        return 0;
 }
 
-static const struct dmi_system_id pci_use_crs_table[] __initconst = {
+static int __init set_ignore_seg(const struct dmi_system_id *id)
+{
+       printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
+       pci_ignore_seg = true;
+       return 0;
+}
+
+static const struct dmi_system_id pci_crs_quirks[] __initconst = {
        /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
        {
                .callback = set_use_crs,
@@ -98,6 +107,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
                        DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
                },
        },
+
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
+       {
+               .callback = set_ignore_seg,
+               .ident = "HP xw9300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
+               },
+       },
        {}
 };
 
@@ -108,7 +127,7 @@ void __init pci_acpi_crs_quirks(void)
        if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
                pci_use_crs = false;
 
-       dmi_check_system(pci_use_crs_table);
+       dmi_check_system(pci_crs_quirks);
 
        /*
         * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
@@ -305,6 +324,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        res->flags = flags;
        res->start = start;
        res->end = end;
+       info->res_offset[info->res_num] = addr.translation_offset;
 
        if (!pci_use_crs) {
                dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -374,7 +394,8 @@ static void add_resources(struct pci_root_info *info,
                                 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
                                 res, conflict->name, conflict);
                else
-                       pci_add_resource(resources, res);
+                       pci_add_resource_offset(resources, res,
+                                       info->res_offset[i]);
        }
 }
 
@@ -382,6 +403,8 @@ static void free_pci_root_info_res(struct pci_root_info *info)
 {
        kfree(info->res);
        info->res = NULL;
+       kfree(info->res_offset);
+       info->res_offset = NULL;
        info->res_num = 0;
 }
 
@@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
                return;
 
        size = sizeof(*info->res) * info->res_num;
-       info->res_num = 0;
        info->res = kzalloc(size, GFP_KERNEL);
-       if (!info->res)
+       if (!info->res) {
+               info->res_num = 0;
+               return;
+       }
+
+       size = sizeof(*info->res_offset) * info->res_num;
+       info->res_num = 0;
+       info->res_offset = kzalloc(size, GFP_KERNEL);
+       if (!info->res_offset) {
+               kfree(info->res);
+               info->res = NULL;
                return;
+       }
 
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
                                info);
@@ -455,6 +488,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
        int pxm;
 #endif
 
+       if (pci_ignore_seg)
+               domain = 0;
+
        if (domain && !pci_domains_supported) {
                printk(KERN_WARNING "pci_bus %04x:%02x: "
                       "ignored (multiple domains not supported)\n",
index 720e973fc34a31b856998715165f7fc50ec9ec6d..1b1dda90a945ede1550294e83dfc51d7a2f9f663 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/pci_x86.h>
+#include <asm/setup.h>
 
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
                                PCI_PROBE_MMCONF;
@@ -608,6 +609,35 @@ unsigned int pcibios_assign_all_busses(void)
        return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
 }
 
+int pcibios_add_device(struct pci_dev *dev)
+{
+       struct setup_data *data;
+       struct pci_setup_rom *rom;
+       u64 pa_data;
+
+       pa_data = boot_params.hdr.setup_data;
+       while (pa_data) {
+               data = phys_to_virt(pa_data);
+
+               if (data->type == SETUP_PCI) {
+                       rom = (struct pci_setup_rom *)data;
+
+                       if ((pci_domain_nr(dev->bus) == rom->segment) &&
+                           (dev->bus->number == rom->bus) &&
+                           (PCI_SLOT(dev->devfn) == rom->device) &&
+                           (PCI_FUNC(dev->devfn) == rom->function) &&
+                           (dev->vendor == rom->vendor) &&
+                           (dev->device == rom->devid)) {
+                               dev->rom = pa_data +
+                                     offsetof(struct pci_setup_rom, romdata);
+                               dev->romlen = rom->pcilen;
+                       }
+               }
+               pa_data = data->next;
+       }
+       return 0;
+}
+
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
        int err;
@@ -626,7 +656,7 @@ void pcibios_disable_device (struct pci_dev *dev)
                pcibios_disable_irq(dev);
 }
 
-int pci_ext_cfg_avail(struct pci_dev *dev)
+int pci_ext_cfg_avail(void)
 {
        if (raw_pci_ext_ops)
                return 1;
diff --git a/arch/x86/pci/numachip.c b/arch/x86/pci/numachip.c
new file mode 100644 (file)
index 0000000..7307d9d
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ * Numascale NumaConnect-specific PCI code
+ *
+ * Copyright (C) 2012 Numascale AS. All rights reserved.
+ *
+ * Send feedback to <support@numascale.com>
+ *
+ * PCI accessor functions derived from mmconfig_64.c
+ *
+ */
+
+#include <linux/pci.h>
+#include <asm/pci_x86.h>
+
+static u8 limit __read_mostly;
+
+static inline char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
+{
+       struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
+
+       if (cfg && cfg->virt)
+               return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12));
+       return NULL;
+}
+
+static int pci_mmcfg_read_numachip(unsigned int seg, unsigned int bus,
+                         unsigned int devfn, int reg, int len, u32 *value)
+{
+       char __iomem *addr;
+
+       /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+       if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
+err:           *value = -1;
+               return -EINVAL;
+       }
+
+       /* Ensure AMD Northbridges don't decode reads to other devices */
+       if (unlikely(bus == 0 && devfn >= limit)) {
+               *value = -1;
+               return 0;
+       }
+
+       rcu_read_lock();
+       addr = pci_dev_base(seg, bus, devfn);
+       if (!addr) {
+               rcu_read_unlock();
+               goto err;
+       }
+
+       switch (len) {
+       case 1:
+               *value = mmio_config_readb(addr + reg);
+               break;
+       case 2:
+               *value = mmio_config_readw(addr + reg);
+               break;
+       case 4:
+               *value = mmio_config_readl(addr + reg);
+               break;
+       }
+       rcu_read_unlock();
+
+       return 0;
+}
+
+static int pci_mmcfg_write_numachip(unsigned int seg, unsigned int bus,
+                          unsigned int devfn, int reg, int len, u32 value)
+{
+       char __iomem *addr;
+
+       /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+       if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
+               return -EINVAL;
+
+       /* Ensure AMD Northbridges don't decode writes to other devices */
+       if (unlikely(bus == 0 && devfn >= limit))
+               return 0;
+
+       rcu_read_lock();
+       addr = pci_dev_base(seg, bus, devfn);
+       if (!addr) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+
+       switch (len) {
+       case 1:
+               mmio_config_writeb(addr + reg, value);
+               break;
+       case 2:
+               mmio_config_writew(addr + reg, value);
+               break;
+       case 4:
+               mmio_config_writel(addr + reg, value);
+               break;
+       }
+       rcu_read_unlock();
+
+       return 0;
+}
+
+const struct pci_raw_ops pci_mmcfg_numachip = {
+       .read = pci_mmcfg_read_numachip,
+       .write = pci_mmcfg_write_numachip,
+};
+
+int __init pci_numachip_init(void)
+{
+       int ret = 0;
+       u32 val;
+
+       /* For remote I/O, restrict bus 0 access to the actual number of AMD
+          Northbridges, which starts at device number 0x18 */
+       ret = raw_pci_read(0, 0, PCI_DEVFN(0x18, 0), 0x60, sizeof(val), &val);
+       if (ret)
+               goto out;
+
+       /* HyperTransport fabric size in bits 6:4 */
+       limit = PCI_DEVFN(0x18 + ((val >> 4) & 7) + 1, 0);
+
+       /* Use NumaChip PCI accessors for non-extended and extended access */
+       raw_pci_ops = raw_pci_ext_ops = &pci_mmcfg_numachip;
+out:
+       return ret;
+}
index f6a0c1b8e518f91ef4992be10a3091e514cc5a50..d9c1b95af17c1ead797783eed225c94c9aa7fe5f 100644 (file)
@@ -39,6 +39,8 @@ void efi_bgrt_init(void)
        if (ACPI_FAILURE(status))
                return;
 
+       if (bgrt_tab->header.length < sizeof(*bgrt_tab))
+               return;
        if (bgrt_tab->version != 1)
                return;
        if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
index ad4439145f858314dfe518cf7cd9336c5fe9c96d..0a34d9e9c263ed1a2074cb9d5beac2a0648dc525 100644 (file)
@@ -239,22 +239,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
        return status;
 }
 
-static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
-                                            efi_time_cap_t *tc)
-{
-       unsigned long flags;
-       efi_status_t status;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       efi_call_phys_prelog();
-       status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm),
-                               virt_to_phys(tc));
-       efi_call_phys_epilog();
-       spin_unlock_irqrestore(&rtc_lock, flags);
-       return status;
-}
-
-int efi_set_rtc_mmss(unsigned long nowtime)
+static int efi_set_rtc_mmss(unsigned long nowtime)
 {
        int real_seconds, real_minutes;
        efi_status_t    status;
@@ -283,7 +268,7 @@ int efi_set_rtc_mmss(unsigned long nowtime)
        return 0;
 }
 
-unsigned long efi_get_time(void)
+static unsigned long efi_get_time(void)
 {
        efi_status_t status;
        efi_time_t eft;
@@ -639,18 +624,13 @@ static int __init efi_runtime_init(void)
        }
        /*
         * We will only need *early* access to the following
-        * two EFI runtime services before set_virtual_address_map
+        * EFI runtime service before set_virtual_address_map
         * is invoked.
         */
-       efi_phys.get_time = (efi_get_time_t *)runtime->get_time;
        efi_phys.set_virtual_address_map =
                (efi_set_virtual_address_map_t *)
                runtime->set_virtual_address_map;
-       /*
-        * Make efi_get_time can be called before entering
-        * virtual mode.
-        */
-       efi.get_time = phys_efi_get_time;
+
        early_iounmap(runtime, sizeof(efi_runtime_services_t));
 
        return 0;
@@ -736,12 +716,10 @@ void __init efi_init(void)
                efi_enabled = 0;
                return;
        }
-#ifdef CONFIG_X86_32
        if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
                x86_platform.set_wallclock = efi_set_rtc_mmss;
        }
-#endif
 
 #if EFI_DEBUG
        print_efi_memmap();
index 95fd505dfeb6e43dd37b0c41954f0b0db6535d1c..06c8b2e662ab6c5a9d6581a7bb9c2a256d1826e7 100644 (file)
@@ -58,6 +58,21 @@ static void __init early_code_mapping_set_exec(int executable)
        }
 }
 
+unsigned long efi_call_virt_prelog(void)
+{
+       unsigned long saved;
+
+       saved = read_cr3();
+       write_cr3(real_mode_header->trampoline_pgd);
+
+       return saved;
+}
+
+void efi_call_virt_epilog(unsigned long saved)
+{
+       write_cr3(saved);
+}
+
 void __init efi_call_phys_prelog(void)
 {
        unsigned long vaddress;
index 4df6c373421a435dfeac34d68407ce10602d688d..205ad328aa52810975dd332771a16911f5e6935b 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hpet.h>
 #include <asm/unistd.h>
 #include <asm/io.h>
+#include <asm/pvclock.h>
 
 #define gtod (&VVAR(vsyscall_gtod_data))
 
@@ -62,6 +63,76 @@ static notrace cycle_t vread_hpet(void)
        return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
 }
 
+#ifdef CONFIG_PARAVIRT_CLOCK
+
+static notrace const struct pvclock_vsyscall_time_info *get_pvti(int cpu)
+{
+       const struct pvclock_vsyscall_time_info *pvti_base;
+       int idx = cpu / (PAGE_SIZE/PVTI_SIZE);
+       int offset = cpu % (PAGE_SIZE/PVTI_SIZE);
+
+       BUG_ON(PVCLOCK_FIXMAP_BEGIN + idx > PVCLOCK_FIXMAP_END);
+
+       pvti_base = (struct pvclock_vsyscall_time_info *)
+                   __fix_to_virt(PVCLOCK_FIXMAP_BEGIN+idx);
+
+       return &pvti_base[offset];
+}
+
+static notrace cycle_t vread_pvclock(int *mode)
+{
+       const struct pvclock_vsyscall_time_info *pvti;
+       cycle_t ret;
+       u64 last;
+       u32 version;
+       u32 migrate_count;
+       u8 flags;
+       unsigned cpu, cpu1;
+
+
+       /*
+        * When looping to get a consistent (time-info, tsc) pair, we
+        * also need to deal with the possibility we can switch vcpus,
+        * so make sure we always re-fetch time-info for the current vcpu.
+        */
+       do {
+               cpu = __getcpu() & VGETCPU_CPU_MASK;
+               /* TODO: We can put vcpu id into higher bits of pvti.version.
+                * This will save a couple of cycles by getting rid of
+                * __getcpu() calls (Gleb).
+                */
+
+               pvti = get_pvti(cpu);
+
+               migrate_count = pvti->migrate_count;
+
+               version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
+
+               /*
+                * Test we're still on the cpu as well as the version.
+                * We could have been migrated just after the first
+                * vgetcpu but before fetching the version, so we
+                * wouldn't notice a version change.
+                */
+               cpu1 = __getcpu() & VGETCPU_CPU_MASK;
+       } while (unlikely(cpu != cpu1 ||
+                         (pvti->pvti.version & 1) ||
+                         pvti->pvti.version != version ||
+                         pvti->migrate_count != migrate_count));
+
+       if (unlikely(!(flags & PVCLOCK_TSC_STABLE_BIT)))
+               *mode = VCLOCK_NONE;
+
+       /* refer to tsc.c read_tsc() comment for rationale */
+       last = VVAR(vsyscall_gtod_data).clock.cycle_last;
+
+       if (likely(ret >= last))
+               return ret;
+
+       return last;
+}
+#endif
+
 notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
 {
        long ret;
@@ -80,7 +151,7 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz)
 }
 
 
-notrace static inline u64 vgetsns(void)
+notrace static inline u64 vgetsns(int *mode)
 {
        long v;
        cycles_t cycles;
@@ -88,6 +159,10 @@ notrace static inline u64 vgetsns(void)
                cycles = vread_tsc();
        else if (gtod->clock.vclock_mode == VCLOCK_HPET)
                cycles = vread_hpet();
+#ifdef CONFIG_PARAVIRT_CLOCK
+       else if (gtod->clock.vclock_mode == VCLOCK_PVCLOCK)
+               cycles = vread_pvclock(mode);
+#endif
        else
                return 0;
        v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
@@ -107,7 +182,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ns = gtod->wall_time_snsec;
-               ns += vgetsns();
+               ns += vgetsns(&mode);
                ns >>= gtod->clock.shift;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
@@ -127,7 +202,7 @@ notrace static int do_monotonic(struct timespec *ts)
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->monotonic_time_sec;
                ns = gtod->monotonic_time_snsec;
-               ns += vgetsns();
+               ns += vgetsns(&mode);
                ns >>= gtod->clock.shift;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
        timespec_add_ns(ts, ns);
index 5463ad558573de5424d4d654e0cfdc20263930dd..2f94b039e55b6c2da8f40616af7445e0f8454a27 100644 (file)
@@ -17,15 +17,10 @@ __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
 {
        unsigned int p;
 
-       if (VVAR(vgetcpu_mode) == VGETCPU_RDTSCP) {
-               /* Load per CPU data from RDTSCP */
-               native_read_tscp(&p);
-       } else {
-               /* Load per CPU data from GDT */
-               asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
-       }
+       p = __getcpu();
+
        if (cpu)
-               *cpu = p & 0xfff;
+               *cpu = p & VGETCPU_CPU_MASK;
        if (node)
                *node = p >> 12;
        return 0;
index 9a6775c9ddca2dc3436b255b0153c2745cba4b9e..131dacd2748a0faedc9986c112652ec52875ab1d 100644 (file)
@@ -6,6 +6,7 @@ config XEN
        bool "Xen guest support"
        select PARAVIRT
        select PARAVIRT_CLOCK
+       select XEN_HAVE_PVMMU
        depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
        depends on X86_TSC
        help
index 586d83812b67b64f96594f1eebdc859bdcb12adc..3aeaa933b5278cc48944aaa4eeb9fdfaffcade50 100644 (file)
@@ -223,6 +223,21 @@ static void __init xen_banner(void)
               version >> 16, version & 0xffff, extra.extraversion,
               xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
 }
+/* Check if running on Xen version (major, minor) or later */
+bool
+xen_running_on_version_or_later(unsigned int major, unsigned int minor)
+{
+       unsigned int version;
+
+       if (!xen_domain())
+               return false;
+
+       version = HYPERVISOR_xen_version(XENVER_version, NULL);
+       if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) ||
+               ((version >> 16) > major))
+               return true;
+       return false;
+}
 
 #define CPUID_THERM_POWER_LEAF 6
 #define APERFMPERF_PRESENT 0
@@ -287,8 +302,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 
 static bool __init xen_check_mwait(void)
 {
-#if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \
-       !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
+#ifdef CONFIG_ACPI
        struct xen_platform_op op = {
                .cmd                    = XENPF_set_processor_pminfo,
                .u.set_pminfo.id        = -1,
@@ -309,6 +323,13 @@ static bool __init xen_check_mwait(void)
        if (!xen_initial_domain())
                return false;
 
+       /*
+        * When running under platform earlier than Xen4.2, do not expose
+        * mwait, to avoid the risk of loading native acpi pad driver
+        */
+       if (!xen_running_on_version_or_later(4, 2))
+               return false;
+
        ax = 1;
        cx = 0;
 
@@ -1495,51 +1516,72 @@ asmlinkage void __init xen_start_kernel(void)
 #endif
 }
 
-void __ref xen_hvm_init_shared_info(void)
+#ifdef CONFIG_XEN_PVHVM
+#define HVM_SHARED_INFO_ADDR 0xFE700000UL
+static struct shared_info *xen_hvm_shared_info;
+static unsigned long xen_hvm_sip_phys;
+static int xen_major, xen_minor;
+
+static void xen_hvm_connect_shared_info(unsigned long pfn)
 {
-       int cpu;
        struct xen_add_to_physmap xatp;
-       static struct shared_info *shared_info_page = 0;
 
-       if (!shared_info_page)
-               shared_info_page = (struct shared_info *)
-                       extend_brk(PAGE_SIZE, PAGE_SIZE);
        xatp.domid = DOMID_SELF;
        xatp.idx = 0;
        xatp.space = XENMAPSPACE_shared_info;
-       xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+       xatp.gpfn = pfn;
        if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
                BUG();
 
-       HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+}
+static void __init xen_hvm_set_shared_info(struct shared_info *sip)
+{
+       int cpu;
+
+       HYPERVISOR_shared_info = sip;
 
        /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
         * page, we use it in the event channel upcall and in some pvclock
         * related functions. We don't need the vcpu_info placement
         * optimizations because we don't use any pv_mmu or pv_irq op on
-        * HVM.
-        * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
-        * online but xen_hvm_init_shared_info is run at resume time too and
-        * in that case multiple vcpus might be online. */
-       for_each_online_cpu(cpu) {
+        * HVM. */
+       for_each_online_cpu(cpu)
                per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+}
+
+/* Reconnect the shared_info pfn to a (new) mfn */
+void xen_hvm_resume_shared_info(void)
+{
+       xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
+}
+
+/* Xen tools prior to Xen 4 do not provide a E820_Reserved area for guest usage.
+ * On these old tools the shared info page will be placed in E820_Ram.
+ * Xen 4 provides a E820_Reserved area at 0xFC000000, and this code expects
+ * that nothing is mapped up to HVM_SHARED_INFO_ADDR.
+ * Xen 4.3+ provides an explicit 1MB area at HVM_SHARED_INFO_ADDR which is used
+ * here for the shared info page. */
+static void __init xen_hvm_init_shared_info(void)
+{
+       if (xen_major < 4) {
+               xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               xen_hvm_sip_phys = __pa(xen_hvm_shared_info);
+       } else {
+               xen_hvm_sip_phys = HVM_SHARED_INFO_ADDR;
+               set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_hvm_sip_phys);
+               xen_hvm_shared_info =
+               (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
        }
+       xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
+       xen_hvm_set_shared_info(xen_hvm_shared_info);
 }
 
-#ifdef CONFIG_XEN_PVHVM
 static void __init init_hvm_pv_info(void)
 {
-       int major, minor;
-       uint32_t eax, ebx, ecx, edx, pages, msr, base;
+       uint32_t ecx, edx, pages, msr, base;
        u64 pfn;
 
        base = xen_cpuid_base();
-       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
-
-       major = eax >> 16;
-       minor = eax & 0xffff;
-       printk(KERN_INFO "Xen version %d.%d.\n", major, minor);
-
        cpuid(base + 2, &pages, &msr, &ecx, &edx);
 
        pfn = __pa(hypercall_page);
@@ -1590,12 +1632,22 @@ static void __init xen_hvm_guest_init(void)
 
 static bool __init xen_hvm_platform(void)
 {
+       uint32_t eax, ebx, ecx, edx, base;
+
        if (xen_pv_domain())
                return false;
 
-       if (!xen_cpuid_base())
+       base = xen_cpuid_base();
+       if (!base)
                return false;
 
+       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
+
+       xen_major = eax >> 16;
+       xen_minor = eax & 0xffff;
+
+       printk(KERN_INFO "Xen version %d.%d.\n", xen_major, xen_minor);
+
        return true;
 }
 
index dcf5f2dd91ec4fd91d814d46c7d6dbd6c5312a61..01de35c772210120075300504189c22bd00c5899 100644 (file)
@@ -2497,8 +2497,10 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
 
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
                               unsigned long addr,
-                              unsigned long mfn, int nr,
-                              pgprot_t prot, unsigned domid)
+                              xen_pfn_t mfn, int nr,
+                              pgprot_t prot, unsigned domid,
+                              struct page **pages)
+
 {
        struct remap_data rmd;
        struct mmu_update mmu_update[REMAP_BATCH_SIZE];
@@ -2542,3 +2544,14 @@ out:
        return err;
 }
 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
+
+/* Returns: 0 success */
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+                              int numpgs, struct page **pages)
+{
+       if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
+               return 0;
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
index 45329c8c226e4c4070f16a791b300265a0bf472b..ae8a00c39de4b0d02cfad0722715d0fbd159a1cb 100644 (file)
@@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
 {
 #ifdef CONFIG_XEN_PVHVM
        int cpu;
-       xen_hvm_init_shared_info();
+       xen_hvm_resume_shared_info();
        xen_callback_vector();
        xen_unplug_emulated_devices();
        if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
index a95b41744ad0bafdcde069cb965cabb67ab0f61b..d2e73d19d366d54820e453f44ff886cecea8d174 100644 (file)
@@ -40,7 +40,7 @@ void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
 
 void xen_callback_vector(void);
-void xen_hvm_init_shared_info(void);
+void xen_hvm_resume_shared_info(void);
 void xen_unplug_emulated_devices(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
index 6563366bae809f8e5b052e003ad42c6c2f2adb33..4641d95651d3ffb18b474f788b9d655e8ac3afa9 100644 (file)
@@ -324,9 +324,19 @@ config CRYPTO_CRC32C
          by iSCSI for header and data digests and by others.
          See Castagnoli93.  Module will be crc32c.
 
+config CRYPTO_CRC32C_X86_64
+       bool
+       depends on X86 && 64BIT
+       select CRYPTO_HASH
+       help
+         In Intel processor with SSE4.2 supported, the processor will
+         support CRC32C calculation using hardware accelerated CRC32
+         instruction optimized with PCLMULQDQ instruction when available.
+
 config CRYPTO_CRC32C_INTEL
        tristate "CRC32c INTEL hardware acceleration"
        depends on X86
+       select CRYPTO_CRC32C_X86_64 if 64BIT
        select CRYPTO_HASH
        help
          In Intel processor with SSE4.2 supported, the processor will
@@ -793,6 +803,28 @@ config CRYPTO_CAMELLIA_X86_64
          See also:
          <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
 
+config CRYPTO_CAMELLIA_AESNI_AVX_X86_64
+       tristate "Camellia cipher algorithm (x86_64/AES-NI/AVX)"
+       depends on X86 && 64BIT
+       depends on CRYPTO
+       select CRYPTO_ALGAPI
+       select CRYPTO_CRYPTD
+       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_GLUE_HELPER_X86
+       select CRYPTO_CAMELLIA_X86_64
+       select CRYPTO_LRW
+       select CRYPTO_XTS
+       help
+         Camellia cipher algorithm module (x86_64/AES-NI/AVX).
+
+         Camellia is a symmetric key block cipher developed jointly
+         at NTT and Mitsubishi Electric Corporation.
+
+         The Camellia specifies three key sizes: 128, 192 and 256 bits.
+
+         See also:
+         <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
+
 config CRYPTO_CAMELLIA_SPARC64
        tristate "Camellia cipher algorithm (SPARC64)"
        depends on SPARC64
@@ -809,9 +841,16 @@ config CRYPTO_CAMELLIA_SPARC64
          See also:
          <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
 
+config CRYPTO_CAST_COMMON
+       tristate
+       help
+         Common parts of the CAST cipher algorithms shared by the
+         generic c and the assembler implementations.
+
 config CRYPTO_CAST5
        tristate "CAST5 (CAST-128) cipher algorithm"
        select CRYPTO_ALGAPI
+       select CRYPTO_CAST_COMMON
        help
          The CAST5 encryption algorithm (synonymous with CAST-128) is
          described in RFC2144.
@@ -822,6 +861,7 @@ config CRYPTO_CAST5_AVX_X86_64
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
        select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_CAST_COMMON
        select CRYPTO_CAST5
        help
          The CAST5 encryption algorithm (synonymous with CAST-128) is
@@ -833,6 +873,7 @@ config CRYPTO_CAST5_AVX_X86_64
 config CRYPTO_CAST6
        tristate "CAST6 (CAST-256) cipher algorithm"
        select CRYPTO_ALGAPI
+       select CRYPTO_CAST_COMMON
        help
          The CAST6 encryption algorithm (synonymous with CAST-256) is
          described in RFC2612.
@@ -844,6 +885,7 @@ config CRYPTO_CAST6_AVX_X86_64
        select CRYPTO_CRYPTD
        select CRYPTO_ABLK_HELPER_X86
        select CRYPTO_GLUE_HELPER_X86
+       select CRYPTO_CAST_COMMON
        select CRYPTO_CAST6
        select CRYPTO_LRW
        select CRYPTO_XTS
index 8cf61ffe35138af8c8d5e139c0a0798beb7a119b..d59dec749804d7d98f7405205cae66ed6a783c02 100644 (file)
@@ -68,6 +68,7 @@ obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o
 obj-$(CONFIG_CRYPTO_AES) += aes_generic.o
 obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o
+obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5_generic.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6_generic.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
index bc525dbd8a4bfa79009d2838ac1dd0d0f379ac7e..5558f630a0ebd254462cf6fc72486ea8d00bccd0 100644 (file)
 #include <linux/types.h>
 #include <crypto/cast5.h>
 
-
-const u32 cast5_s1[256] = {
-       0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
-       0x9c004dd3, 0x6003e540, 0xcf9fc949,
-       0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
-       0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-       0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
-       0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-       0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
-       0xaa54166b, 0x22568e3a, 0xa2d341d0,
-       0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
-       0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-       0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
-       0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-       0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
-       0xe93b159f, 0xb48ee411, 0x4bff345d,
-       0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
-       0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-       0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
-       0xc59c5319, 0xb949e354, 0xb04669fe,
-       0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
-       0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-       0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
-       0xf61b1891, 0xbb72275e, 0xaa508167,
-       0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
-       0xa2d1936b, 0x2ad286af, 0xaa56d291,
-       0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
-       0x73e2bb14, 0xa0bebc3c, 0x54623779,
-       0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
-       0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-       0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
-       0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-       0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
-       0x051ef495, 0xaa573b04, 0x4a805d8d,
-       0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
-       0x50afd341, 0xa7c13275, 0x915a0bf5,
-       0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
-       0xab85c5f3, 0x1b55db94, 0xaad4e324,
-       0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
-       0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-       0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
-       0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-       0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
-       0x032268d4, 0xc9600acc, 0xce387e6d,
-       0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
-       0x4736f464, 0x5ad328d8, 0xb347cc96,
-       0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
-       0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-       0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
-       0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-       0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
-       0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-       0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
-       0x51c85f4d, 0x56907596, 0xa5bb15e6,
-       0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
-       0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-       0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
-       0x700b45e1, 0xd5ea50f1, 0x85a92872,
-       0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
-       0x0cd0ede7, 0x26470db8, 0xf881814c,
-       0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
-       0xab838653, 0x6e2f1e23, 0x83719c9e,
-       0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
-       0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-       0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
-       0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
-};
-EXPORT_SYMBOL_GPL(cast5_s1);
-const u32 cast5_s2[256] = {
-       0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
-       0xeec5207a, 0x55889c94, 0x72fc0651,
-       0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
-       0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-       0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
-       0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-       0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
-       0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-       0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
-       0x77e83f4e, 0x79929269, 0x24fa9f7b,
-       0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
-       0x0d554b63, 0x5d681121, 0xc866c359,
-       0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
-       0x39f7627f, 0x361e3084, 0xe4eb573b,
-       0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
-       0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-       0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
-       0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-       0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
-       0x1d804366, 0x721d9bfd, 0xa58684bb,
-       0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
-       0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-       0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
-       0xe0b56714, 0x21f043b7, 0xe5d05860,
-       0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
-       0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-       0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
-       0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-       0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
-       0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-       0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
-       0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-       0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
-       0xe3214517, 0xb4542835, 0x9f63293c,
-       0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
-       0x30a22c95, 0x31a70850, 0x60930f13,
-       0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
-       0xa02b1741, 0x7cbad9a2, 0x2180036f,
-       0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
-       0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-       0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
-       0x846a3bae, 0x8ff77888, 0xee5d60f6,
-       0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
-       0x157fd7fa, 0xef8579cc, 0xd152de58,
-       0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
-       0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-       0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
-       0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-       0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
-       0x301e16e6, 0x273be979, 0xb0ffeaa6,
-       0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
-       0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-       0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
-       0x1a513742, 0xef6828bc, 0x520365d6,
-       0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
-       0x5eea29cb, 0x145892f5, 0x91584f7f,
-       0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
-       0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-       0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
-       0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-       0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
-       0xa345415e, 0x5c038323, 0x3e5d3bb9,
-       0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
-       0x73bfbe70, 0x83877605, 0x4523ecf1
-};
-EXPORT_SYMBOL_GPL(cast5_s2);
-const u32 cast5_s3[256] = {
-       0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
-       0x369fe44b, 0x8c1fc644, 0xaececa90,
-       0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
-       0xf0ad0548, 0xe13c8d83, 0x927010d5,
-       0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
-       0xfade82e0, 0xa067268b, 0x8272792e,
-       0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
-       0x825b1bfd, 0x9255c5ed, 0x1257a240,
-       0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
-       0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-       0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
-       0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-       0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
-       0x4a012d6e, 0xc5884a28, 0xccc36f71,
-       0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
-       0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-       0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
-       0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-       0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
-       0x1eac5790, 0x796fb449, 0x8252dc15,
-       0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
-       0xe83ec305, 0x4f91751a, 0x925669c2,
-       0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
-       0x927985b2, 0x8276dbcb, 0x02778176,
-       0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
-       0x340ce5c8, 0x96bbb682, 0x93b4b148,
-       0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
-       0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-       0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
-       0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-       0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
-       0xbda8229c, 0x127dadaa, 0x438a074e,
-       0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
-       0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-       0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
-       0x76a2e214, 0xb9a40368, 0x925d958f,
-       0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
-       0x193cbcfa, 0x27627545, 0x825cf47a,
-       0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
-       0x8272a972, 0x9270c4a8, 0x127de50b,
-       0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
-       0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-       0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
-       0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-       0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
-       0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-       0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
-       0x7c34671c, 0x02717ef6, 0x4feb5536,
-       0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
-       0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-       0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
-       0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-       0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
-       0x856302e0, 0x72dbd92b, 0xee971b69,
-       0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
-       0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-       0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
-       0x0ff0443d, 0x606e6dc6, 0x60543a49,
-       0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
-       0x68458425, 0x99833be5, 0x600d457d,
-       0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
-       0x9c305a00, 0x52bce688, 0x1b03588a,
-       0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
-       0xa133c501, 0xe9d3531c, 0xee353783
-};
-EXPORT_SYMBOL_GPL(cast5_s3);
-const u32 cast5_s4[256] = {
-       0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
-       0x64ad8c57, 0x85510443, 0xfa020ed1,
-       0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
-       0x6497b7b1, 0xf3641f63, 0x241e4adf,
-       0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
-       0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-       0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
-       0x0c13fefe, 0x081b08ca, 0x05170121,
-       0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
-       0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-       0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
-       0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-       0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
-       0x11b638e1, 0x72500e03, 0xf80eb2bb,
-       0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
-       0x6920318f, 0x081dbb99, 0xffc304a5,
-       0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
-       0x9f926f91, 0x9f46222f, 0x3991467d,
-       0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
-       0x3fb6180c, 0x18f8931e, 0x281658e6,
-       0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
-       0x79098b02, 0xe4eabb81, 0x28123b23,
-       0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
-       0x0014377b, 0x041e8ac8, 0x09114003,
-       0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
-       0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-       0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
-       0x56c8c391, 0x6b65811c, 0x5e146119,
-       0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
-       0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-       0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
-       0xeca1d7c7, 0x041afa32, 0x1d16625a,
-       0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
-       0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-       0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
-       0xedda04eb, 0x17a9be04, 0x2c18f4df,
-       0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
-       0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-       0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
-       0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-       0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
-       0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-       0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
-       0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-       0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
-       0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-       0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
-       0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-       0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
-       0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-       0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
-       0x0ce454a9, 0xd60acd86, 0x015f1919,
-       0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
-       0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-       0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
-       0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-       0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
-       0x296b299e, 0x492fc295, 0x9266beab,
-       0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
-       0xf65324e6, 0x6afce36c, 0x0316cc04,
-       0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
-       0x932bcdf6, 0xb657c34d, 0x4edfd282,
-       0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
-       0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
-};
-EXPORT_SYMBOL_GPL(cast5_s4);
 static const u32 s5[256] = {
        0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff,
        0x1dd358f5, 0x44dd9d44, 0x1731167f,
@@ -564,10 +295,10 @@ static const u32 sb8[256] = {
        0xeaee6801, 0x8db2a283, 0xea8bf59e
 };
 
-#define s1 cast5_s1
-#define s2 cast5_s2
-#define s3 cast5_s3
-#define s4 cast5_s4
+#define s1 cast_s1
+#define s2 cast_s2
+#define s3 cast_s3
+#define s4 cast_s4
 
 #define F1(D, m, r)  ((I = ((m) + (D))), (I = rol32(I, (r))),   \
        (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]))
index 1acd2f1c48fcf57966fd99bb414dcfc1eb050efb..de732528a43042b0445dba87145653b0ce4f313a 100644 (file)
 #include <linux/types.h>
 #include <crypto/cast6.h>
 
-#define s1 cast6_s1
-#define s2 cast6_s2
-#define s3 cast6_s3
-#define s4 cast6_s4
+#define s1 cast_s1
+#define s2 cast_s2
+#define s3 cast_s3
+#define s4 cast_s4
 
 #define F1(D, r, m)  ((I = ((m) + (D))), (I = rol32(I, (r))),   \
        (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]))
 #define F3(D, r, m)  ((I = ((m) - (D))), (I = rol32(I, (r))),   \
        (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]))
 
-const u32 cast6_s1[256] = {
-       0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
-       0x9c004dd3, 0x6003e540, 0xcf9fc949,
-       0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
-       0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-       0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
-       0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-       0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
-       0xaa54166b, 0x22568e3a, 0xa2d341d0,
-       0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
-       0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-       0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
-       0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-       0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
-       0xe93b159f, 0xb48ee411, 0x4bff345d,
-       0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
-       0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-       0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
-       0xc59c5319, 0xb949e354, 0xb04669fe,
-       0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
-       0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-       0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
-       0xf61b1891, 0xbb72275e, 0xaa508167,
-       0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
-       0xa2d1936b, 0x2ad286af, 0xaa56d291,
-       0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
-       0x73e2bb14, 0xa0bebc3c, 0x54623779,
-       0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
-       0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-       0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
-       0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-       0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
-       0x051ef495, 0xaa573b04, 0x4a805d8d,
-       0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
-       0x50afd341, 0xa7c13275, 0x915a0bf5,
-       0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
-       0xab85c5f3, 0x1b55db94, 0xaad4e324,
-       0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
-       0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-       0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
-       0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-       0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
-       0x032268d4, 0xc9600acc, 0xce387e6d,
-       0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
-       0x4736f464, 0x5ad328d8, 0xb347cc96,
-       0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
-       0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-       0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
-       0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-       0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
-       0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-       0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
-       0x51c85f4d, 0x56907596, 0xa5bb15e6,
-       0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
-       0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-       0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
-       0x700b45e1, 0xd5ea50f1, 0x85a92872,
-       0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
-       0x0cd0ede7, 0x26470db8, 0xf881814c,
-       0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
-       0xab838653, 0x6e2f1e23, 0x83719c9e,
-       0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
-       0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-       0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
-       0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
-};
-EXPORT_SYMBOL_GPL(cast6_s1);
-
-const u32 cast6_s2[256] = {
-       0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
-       0xeec5207a, 0x55889c94, 0x72fc0651,
-       0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
-       0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-       0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
-       0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-       0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
-       0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-       0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
-       0x77e83f4e, 0x79929269, 0x24fa9f7b,
-       0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
-       0x0d554b63, 0x5d681121, 0xc866c359,
-       0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
-       0x39f7627f, 0x361e3084, 0xe4eb573b,
-       0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
-       0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-       0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
-       0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-       0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
-       0x1d804366, 0x721d9bfd, 0xa58684bb,
-       0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
-       0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-       0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
-       0xe0b56714, 0x21f043b7, 0xe5d05860,
-       0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
-       0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-       0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
-       0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-       0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
-       0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-       0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
-       0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-       0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
-       0xe3214517, 0xb4542835, 0x9f63293c,
-       0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
-       0x30a22c95, 0x31a70850, 0x60930f13,
-       0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
-       0xa02b1741, 0x7cbad9a2, 0x2180036f,
-       0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
-       0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-       0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
-       0x846a3bae, 0x8ff77888, 0xee5d60f6,
-       0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
-       0x157fd7fa, 0xef8579cc, 0xd152de58,
-       0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
-       0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-       0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
-       0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-       0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
-       0x301e16e6, 0x273be979, 0xb0ffeaa6,
-       0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
-       0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-       0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
-       0x1a513742, 0xef6828bc, 0x520365d6,
-       0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
-       0x5eea29cb, 0x145892f5, 0x91584f7f,
-       0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
-       0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-       0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
-       0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-       0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
-       0xa345415e, 0x5c038323, 0x3e5d3bb9,
-       0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
-       0x73bfbe70, 0x83877605, 0x4523ecf1
-};
-EXPORT_SYMBOL_GPL(cast6_s2);
-
-const u32 cast6_s3[256] = {
-       0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
-       0x369fe44b, 0x8c1fc644, 0xaececa90,
-       0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
-       0xf0ad0548, 0xe13c8d83, 0x927010d5,
-       0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
-       0xfade82e0, 0xa067268b, 0x8272792e,
-       0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
-       0x825b1bfd, 0x9255c5ed, 0x1257a240,
-       0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
-       0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-       0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
-       0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-       0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
-       0x4a012d6e, 0xc5884a28, 0xccc36f71,
-       0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
-       0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-       0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
-       0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-       0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
-       0x1eac5790, 0x796fb449, 0x8252dc15,
-       0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
-       0xe83ec305, 0x4f91751a, 0x925669c2,
-       0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
-       0x927985b2, 0x8276dbcb, 0x02778176,
-       0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
-       0x340ce5c8, 0x96bbb682, 0x93b4b148,
-       0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
-       0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-       0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
-       0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-       0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
-       0xbda8229c, 0x127dadaa, 0x438a074e,
-       0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
-       0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-       0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
-       0x76a2e214, 0xb9a40368, 0x925d958f,
-       0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
-       0x193cbcfa, 0x27627545, 0x825cf47a,
-       0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
-       0x8272a972, 0x9270c4a8, 0x127de50b,
-       0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
-       0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-       0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
-       0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-       0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
-       0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-       0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
-       0x7c34671c, 0x02717ef6, 0x4feb5536,
-       0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
-       0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-       0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
-       0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-       0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
-       0x856302e0, 0x72dbd92b, 0xee971b69,
-       0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
-       0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-       0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
-       0x0ff0443d, 0x606e6dc6, 0x60543a49,
-       0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
-       0x68458425, 0x99833be5, 0x600d457d,
-       0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
-       0x9c305a00, 0x52bce688, 0x1b03588a,
-       0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
-       0xa133c501, 0xe9d3531c, 0xee353783
-};
-EXPORT_SYMBOL_GPL(cast6_s3);
-
-const u32 cast6_s4[256] = {
-       0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
-       0x64ad8c57, 0x85510443, 0xfa020ed1,
-       0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
-       0x6497b7b1, 0xf3641f63, 0x241e4adf,
-       0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
-       0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-       0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
-       0x0c13fefe, 0x081b08ca, 0x05170121,
-       0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
-       0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-       0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
-       0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-       0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
-       0x11b638e1, 0x72500e03, 0xf80eb2bb,
-       0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
-       0x6920318f, 0x081dbb99, 0xffc304a5,
-       0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
-       0x9f926f91, 0x9f46222f, 0x3991467d,
-       0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
-       0x3fb6180c, 0x18f8931e, 0x281658e6,
-       0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
-       0x79098b02, 0xe4eabb81, 0x28123b23,
-       0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
-       0x0014377b, 0x041e8ac8, 0x09114003,
-       0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
-       0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-       0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
-       0x56c8c391, 0x6b65811c, 0x5e146119,
-       0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
-       0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-       0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
-       0xeca1d7c7, 0x041afa32, 0x1d16625a,
-       0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
-       0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-       0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
-       0xedda04eb, 0x17a9be04, 0x2c18f4df,
-       0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
-       0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-       0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
-       0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-       0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
-       0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-       0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
-       0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-       0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
-       0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-       0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
-       0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-       0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
-       0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-       0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
-       0x0ce454a9, 0xd60acd86, 0x015f1919,
-       0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
-       0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-       0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
-       0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-       0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
-       0x296b299e, 0x492fc295, 0x9266beab,
-       0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
-       0xf65324e6, 0x6afce36c, 0x0316cc04,
-       0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
-       0x932bcdf6, 0xb657c34d, 0x4edfd282,
-       0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
-       0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
-};
-EXPORT_SYMBOL_GPL(cast6_s4);
-
 static const u32 Tm[24][8] = {
        { 0x5a827999, 0xc95c653a, 0x383650db, 0xa7103c7c, 0x15ea281d,
                0x84c413be, 0xf39dff5f, 0x6277eb00 } ,
diff --git a/crypto/cast_common.c b/crypto/cast_common.c
new file mode 100644 (file)
index 0000000..a15f523
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Common lookup tables for CAST-128 (cast5) and CAST-256 (cast6)
+ *
+ * Copyright © 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright © 2003 Kartikey Mahendra Bhatt <kartik_me@hotmail.com>
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of 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 <crypto/cast_common.h>
+
+const u32 cast_s1[256] = {
+       0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
+       0x9c004dd3, 0x6003e540, 0xcf9fc949,
+       0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
+       0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+       0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
+       0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+       0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
+       0xaa54166b, 0x22568e3a, 0xa2d341d0,
+       0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
+       0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+       0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
+       0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+       0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
+       0xe93b159f, 0xb48ee411, 0x4bff345d,
+       0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
+       0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+       0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
+       0xc59c5319, 0xb949e354, 0xb04669fe,
+       0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
+       0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+       0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
+       0xf61b1891, 0xbb72275e, 0xaa508167,
+       0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
+       0xa2d1936b, 0x2ad286af, 0xaa56d291,
+       0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
+       0x73e2bb14, 0xa0bebc3c, 0x54623779,
+       0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
+       0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+       0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
+       0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+       0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
+       0x051ef495, 0xaa573b04, 0x4a805d8d,
+       0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
+       0x50afd341, 0xa7c13275, 0x915a0bf5,
+       0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
+       0xab85c5f3, 0x1b55db94, 0xaad4e324,
+       0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
+       0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+       0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
+       0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+       0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
+       0x032268d4, 0xc9600acc, 0xce387e6d,
+       0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
+       0x4736f464, 0x5ad328d8, 0xb347cc96,
+       0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
+       0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+       0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
+       0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+       0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
+       0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+       0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
+       0x51c85f4d, 0x56907596, 0xa5bb15e6,
+       0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
+       0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+       0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
+       0x700b45e1, 0xd5ea50f1, 0x85a92872,
+       0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
+       0x0cd0ede7, 0x26470db8, 0xf881814c,
+       0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
+       0xab838653, 0x6e2f1e23, 0x83719c9e,
+       0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
+       0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+       0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
+       0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+};
+EXPORT_SYMBOL_GPL(cast_s1);
+
+const u32 cast_s2[256] = {
+       0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
+       0xeec5207a, 0x55889c94, 0x72fc0651,
+       0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
+       0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+       0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
+       0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+       0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
+       0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+       0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
+       0x77e83f4e, 0x79929269, 0x24fa9f7b,
+       0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
+       0x0d554b63, 0x5d681121, 0xc866c359,
+       0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
+       0x39f7627f, 0x361e3084, 0xe4eb573b,
+       0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
+       0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+       0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
+       0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+       0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
+       0x1d804366, 0x721d9bfd, 0xa58684bb,
+       0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
+       0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+       0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
+       0xe0b56714, 0x21f043b7, 0xe5d05860,
+       0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
+       0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+       0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
+       0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+       0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
+       0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+       0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
+       0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+       0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
+       0xe3214517, 0xb4542835, 0x9f63293c,
+       0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
+       0x30a22c95, 0x31a70850, 0x60930f13,
+       0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
+       0xa02b1741, 0x7cbad9a2, 0x2180036f,
+       0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
+       0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+       0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
+       0x846a3bae, 0x8ff77888, 0xee5d60f6,
+       0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
+       0x157fd7fa, 0xef8579cc, 0xd152de58,
+       0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
+       0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+       0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
+       0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+       0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
+       0x301e16e6, 0x273be979, 0xb0ffeaa6,
+       0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
+       0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+       0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
+       0x1a513742, 0xef6828bc, 0x520365d6,
+       0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
+       0x5eea29cb, 0x145892f5, 0x91584f7f,
+       0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
+       0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+       0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
+       0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+       0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
+       0xa345415e, 0x5c038323, 0x3e5d3bb9,
+       0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
+       0x73bfbe70, 0x83877605, 0x4523ecf1
+};
+EXPORT_SYMBOL_GPL(cast_s2);
+
+const u32 cast_s3[256] = {
+       0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
+       0x369fe44b, 0x8c1fc644, 0xaececa90,
+       0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
+       0xf0ad0548, 0xe13c8d83, 0x927010d5,
+       0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
+       0xfade82e0, 0xa067268b, 0x8272792e,
+       0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
+       0x825b1bfd, 0x9255c5ed, 0x1257a240,
+       0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
+       0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+       0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
+       0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+       0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
+       0x4a012d6e, 0xc5884a28, 0xccc36f71,
+       0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
+       0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+       0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
+       0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+       0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
+       0x1eac5790, 0x796fb449, 0x8252dc15,
+       0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
+       0xe83ec305, 0x4f91751a, 0x925669c2,
+       0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
+       0x927985b2, 0x8276dbcb, 0x02778176,
+       0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
+       0x340ce5c8, 0x96bbb682, 0x93b4b148,
+       0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
+       0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+       0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
+       0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+       0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
+       0xbda8229c, 0x127dadaa, 0x438a074e,
+       0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
+       0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+       0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
+       0x76a2e214, 0xb9a40368, 0x925d958f,
+       0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
+       0x193cbcfa, 0x27627545, 0x825cf47a,
+       0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
+       0x8272a972, 0x9270c4a8, 0x127de50b,
+       0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
+       0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+       0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
+       0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+       0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
+       0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+       0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
+       0x7c34671c, 0x02717ef6, 0x4feb5536,
+       0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
+       0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+       0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
+       0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+       0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
+       0x856302e0, 0x72dbd92b, 0xee971b69,
+       0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
+       0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+       0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
+       0x0ff0443d, 0x606e6dc6, 0x60543a49,
+       0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
+       0x68458425, 0x99833be5, 0x600d457d,
+       0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
+       0x9c305a00, 0x52bce688, 0x1b03588a,
+       0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
+       0xa133c501, 0xe9d3531c, 0xee353783
+};
+EXPORT_SYMBOL_GPL(cast_s3);
+
+const u32 cast_s4[256] = {
+       0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
+       0x64ad8c57, 0x85510443, 0xfa020ed1,
+       0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
+       0x6497b7b1, 0xf3641f63, 0x241e4adf,
+       0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
+       0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+       0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
+       0x0c13fefe, 0x081b08ca, 0x05170121,
+       0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
+       0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+       0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
+       0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+       0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
+       0x11b638e1, 0x72500e03, 0xf80eb2bb,
+       0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
+       0x6920318f, 0x081dbb99, 0xffc304a5,
+       0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
+       0x9f926f91, 0x9f46222f, 0x3991467d,
+       0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
+       0x3fb6180c, 0x18f8931e, 0x281658e6,
+       0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
+       0x79098b02, 0xe4eabb81, 0x28123b23,
+       0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
+       0x0014377b, 0x041e8ac8, 0x09114003,
+       0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
+       0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+       0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
+       0x56c8c391, 0x6b65811c, 0x5e146119,
+       0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
+       0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+       0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
+       0xeca1d7c7, 0x041afa32, 0x1d16625a,
+       0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
+       0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+       0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
+       0xedda04eb, 0x17a9be04, 0x2c18f4df,
+       0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
+       0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+       0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
+       0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+       0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
+       0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+       0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
+       0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+       0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
+       0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+       0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
+       0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+       0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
+       0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+       0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
+       0x0ce454a9, 0xd60acd86, 0x015f1919,
+       0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
+       0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+       0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
+       0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+       0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
+       0x296b299e, 0x492fc295, 0x9266beab,
+       0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
+       0xf65324e6, 0x6afce36c, 0x0316cc04,
+       0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
+       0x932bcdf6, 0xb657c34d, 0x4edfd282,
+       0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
+       0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+};
+EXPORT_SYMBOL_GPL(cast_s4);
+
+MODULE_LICENSE("GPL");
index e87fa60f58311f4d471686009f500087afae9ce5..7ae2130e1b002890900907fc415b1eb51094e8a7 100644 (file)
@@ -971,11 +971,13 @@ static int do_test(int m)
        case 3:
                ret += tcrypt_test("ecb(des)");
                ret += tcrypt_test("cbc(des)");
+               ret += tcrypt_test("ctr(des)");
                break;
 
        case 4:
                ret += tcrypt_test("ecb(des3_ede)");
                ret += tcrypt_test("cbc(des3_ede)");
+               ret += tcrypt_test("ctr(des3_ede)");
                break;
 
        case 5:
@@ -1479,6 +1481,10 @@ static int do_test(int m)
                test_hash_speed("ghash-generic", sec, hash_speed_template_16);
                if (mode > 300 && mode < 400) break;
 
+       case 319:
+               test_hash_speed("crc32c", sec, generic_hash_speed_template);
+               if (mode > 300 && mode < 400) break;
+
        case 399:
                break;
 
@@ -1722,6 +1728,29 @@ static int do_test(int m)
                                   speed_template_32_64);
                break;
 
+       case 508:
+               test_acipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
+                                  speed_template_16_32);
+               test_acipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
+                                  speed_template_16_32);
+               test_acipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
+                                  speed_template_16_32);
+               test_acipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
+                                  speed_template_16_32);
+               test_acipher_speed("ctr(camellia)", ENCRYPT, sec, NULL, 0,
+                                  speed_template_16_32);
+               test_acipher_speed("ctr(camellia)", DECRYPT, sec, NULL, 0,
+                                  speed_template_16_32);
+               test_acipher_speed("lrw(camellia)", ENCRYPT, sec, NULL, 0,
+                                  speed_template_32_48);
+               test_acipher_speed("lrw(camellia)", DECRYPT, sec, NULL, 0,
+                                  speed_template_32_48);
+               test_acipher_speed("xts(camellia)", ENCRYPT, sec, NULL, 0,
+                                  speed_template_32_64);
+               test_acipher_speed("xts(camellia)", DECRYPT, sec, NULL, 0,
+                                  speed_template_32_64);
+               break;
+
        case 1000:
                test_available();
                break;
index 941d75cd1f7cd918ef2ef1b436854cd9ec7abb03..edf4a0818773483538f09ecfbe246dd96eb9aaf5 100644 (file)
@@ -1638,270 +1638,66 @@ static const struct alg_test_desc alg_test_descs[] = {
        {
                .alg = "__cbc-cast5-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__cbc-cast6-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__cbc-serpent-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__cbc-serpent-sse2",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__cbc-twofish-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-cbc-aes-aesni",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
+       }, {
+               .alg = "__driver-cbc-camellia-aesni",
+               .test = alg_test_null,
        }, {
                .alg = "__driver-cbc-cast5-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-cbc-cast6-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-cbc-serpent-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-cbc-serpent-sse2",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-cbc-twofish-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-ecb-aes-aesni",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
+       }, {
+               .alg = "__driver-ecb-camellia-aesni",
+               .test = alg_test_null,
        }, {
                .alg = "__driver-ecb-cast5-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-ecb-cast6-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-ecb-serpent-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-ecb-serpent-sse2",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__driver-ecb-twofish-avx",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "__ghash-pclmulqdqni",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .hash = {
-                               .vecs = NULL,
-                               .count = 0
-                       }
-               }
        }, {
                .alg = "ansi_cprng",
                .test = alg_test_cprng,
@@ -2130,135 +1926,39 @@ static const struct alg_test_desc alg_test_descs[] = {
                .alg = "cryptd(__driver-cbc-aes-aesni)",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
+       }, {
+               .alg = "cryptd(__driver-cbc-camellia-aesni)",
+               .test = alg_test_null,
        }, {
                .alg = "cryptd(__driver-ecb-aes-aesni)",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
+       }, {
+               .alg = "cryptd(__driver-ecb-camellia-aesni)",
+               .test = alg_test_null,
        }, {
                .alg = "cryptd(__driver-ecb-cast5-avx)",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "cryptd(__driver-ecb-cast6-avx)",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "cryptd(__driver-ecb-serpent-avx)",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "cryptd(__driver-ecb-serpent-sse2)",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "cryptd(__driver-ecb-twofish-avx)",
                .test = alg_test_null,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "cryptd(__driver-gcm-aes-aesni)",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "cryptd(__ghash-pclmulqdqni)",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .hash = {
-                               .vecs = NULL,
-                               .count = 0
-                       }
-               }
        }, {
                .alg = "ctr(aes)",
                .test = alg_test_skcipher,
@@ -2335,6 +2035,36 @@ static const struct alg_test_desc alg_test_descs[] = {
                                }
                        }
                }
+       }, {
+               .alg = "ctr(des)",
+               .test = alg_test_skcipher,
+               .suite = {
+                       .cipher = {
+                               .enc = {
+                                       .vecs = des_ctr_enc_tv_template,
+                                       .count = DES_CTR_ENC_TEST_VECTORS
+                               },
+                               .dec = {
+                                       .vecs = des_ctr_dec_tv_template,
+                                       .count = DES_CTR_DEC_TEST_VECTORS
+                               }
+                       }
+               }
+       }, {
+               .alg = "ctr(des3_ede)",
+               .test = alg_test_skcipher,
+               .suite = {
+                       .cipher = {
+                               .enc = {
+                                       .vecs = des3_ede_ctr_enc_tv_template,
+                                       .count = DES3_EDE_CTR_ENC_TEST_VECTORS
+                               },
+                               .dec = {
+                                       .vecs = des3_ede_ctr_dec_tv_template,
+                                       .count = DES3_EDE_CTR_DEC_TEST_VECTORS
+                               }
+                       }
+               }
        }, {
                .alg = "ctr(serpent)",
                .test = alg_test_skcipher,
@@ -2383,6 +2113,7 @@ static const struct alg_test_desc alg_test_descs[] = {
        }, {
                .alg = "deflate",
                .test = alg_test_comp,
+               .fips_allowed = 1,
                .suite = {
                        .comp = {
                                .comp = {
@@ -2399,18 +2130,6 @@ static const struct alg_test_desc alg_test_descs[] = {
                .alg = "ecb(__aes-aesni)",
                .test = alg_test_null,
                .fips_allowed = 1,
-               .suite = {
-                       .cipher = {
-                               .enc = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               },
-                               .dec = {
-                                       .vecs = NULL,
-                                       .count = 0
-                               }
-                       }
-               }
        }, {
                .alg = "ecb(aes)",
                .test = alg_test_skcipher,
@@ -2859,6 +2578,7 @@ static const struct alg_test_desc alg_test_descs[] = {
        }, {
                .alg = "lzo",
                .test = alg_test_comp,
+               .fips_allowed = 1,
                .suite = {
                        .comp = {
                                .comp = {
@@ -3226,6 +2946,7 @@ static const struct alg_test_desc alg_test_descs[] = {
        }, {
                .alg = "zlib",
                .test = alg_test_pcomp,
+               .fips_allowed = 1,
                .suite = {
                        .pcomp = {
                                .comp = {
index 76d7f6cc82f554f8be2846b393846218f5c9a587..b5721e0b979c4001bde7d9d1461bc3f105ace32d 100644 (file)
@@ -41,7 +41,7 @@ struct hash_testvec {
        char *plaintext;
        char *digest;
        unsigned char tap[MAX_TAP];
-       unsigned char psize;
+       unsigned short psize;
        unsigned char np;
        unsigned char ksize;
 };
@@ -1707,7 +1707,7 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
        }
 };
 
-#define VMAC_AES_TEST_VECTORS  8
+#define VMAC_AES_TEST_VECTORS  11
 static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01',
                                '\x02', '\x03', '\x02', '\x02',
                                '\x02', '\x04', '\x01', '\x07',
@@ -1723,6 +1723,19 @@ static char vmac_string3[128] = {'a', 'b', 'c', 'a', 'b', 'c',
                                'a', 'b', 'c', 'a', 'b', 'c',
                                };
 
+static char vmac_string4[17] = {'b', 'c', 'e', 'f',
+                               'i', 'j', 'l', 'm',
+                               'o', 'p', 'r', 's',
+                               't', 'u', 'w', 'x', 'z'};
+
+static char vmac_string5[127] = {'r', 'm', 'b', 't', 'c',
+                                'o', 'l', 'k', ']', '%',
+                                '9', '2', '7', '!', 'A'};
+
+static char vmac_string6[129] = {'p', 't', '*', '7', 'l',
+                                'i', '!', '#', 'w', '0',
+                                'z', '/', '4', 'A', 'n'};
+
 static struct hash_testvec aes_vmac128_tv_template[] = {
        {
                .key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
@@ -1776,6 +1789,24 @@ static struct hash_testvec aes_vmac128_tv_template[] = {
                .digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4",
                .psize  = 128,
                .ksize  = 16,
+       }, {
+               .key = "a09b5cd!f#07K\x00\x00\x00",
+               .plaintext = vmac_string4,
+               .digest = "\xab\xa5\x0f\xea\x42\x4e\xa1\x5f",
+               .psize = sizeof(vmac_string4),
+               .ksize = 16,
+       }, {
+               .key = "a09b5cd!f#07K\x00\x00\x00",
+               .plaintext = vmac_string5,
+               .digest = "\x25\x31\x98\xbc\x1d\xe8\x67\x60",
+               .psize = sizeof(vmac_string5),
+               .ksize = 16,
+       }, {
+               .key = "a09b5cd!f#07K\x00\x00\x00",
+               .plaintext = vmac_string6,
+               .digest = "\xc4\xae\x9b\x47\x95\x65\xeb\x41",
+               .psize = sizeof(vmac_string6),
+               .ksize = 16,
        },
 };
 
@@ -1993,14 +2024,18 @@ static struct hash_testvec hmac_sha512_tv_template[] = {
 /*
  * DES test vectors.
  */
-#define DES_ENC_TEST_VECTORS           10
-#define DES_DEC_TEST_VECTORS           4
-#define DES_CBC_ENC_TEST_VECTORS       5
-#define DES_CBC_DEC_TEST_VECTORS       4
-#define DES3_EDE_ENC_TEST_VECTORS      3
-#define DES3_EDE_DEC_TEST_VECTORS      3
-#define DES3_EDE_CBC_ENC_TEST_VECTORS  1
-#define DES3_EDE_CBC_DEC_TEST_VECTORS  1
+#define DES_ENC_TEST_VECTORS           11
+#define DES_DEC_TEST_VECTORS           5
+#define DES_CBC_ENC_TEST_VECTORS       6
+#define DES_CBC_DEC_TEST_VECTORS       5
+#define DES_CTR_ENC_TEST_VECTORS       2
+#define DES_CTR_DEC_TEST_VECTORS       2
+#define DES3_EDE_ENC_TEST_VECTORS      4
+#define DES3_EDE_DEC_TEST_VECTORS      4
+#define DES3_EDE_CBC_ENC_TEST_VECTORS  2
+#define DES3_EDE_CBC_DEC_TEST_VECTORS  2
+#define DES3_EDE_CTR_ENC_TEST_VECTORS  2
+#define DES3_EDE_CTR_DEC_TEST_VECTORS  2
 
 static struct cipher_testvec des_enc_tv_template[] = {
        { /* From Applied Cryptography */
@@ -2103,6 +2138,76 @@ static struct cipher_testvec des_enc_tv_template[] = {
                .rlen   = 8,
                .np     = 8,
                .tap    = { 1, 1, 1, 1, 1, 1, 1, 1 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .ilen   = 248,
+               .result = "\x88\xCB\x1F\xAB\x2F\x2A\x49\x57"
+                         "\x92\xB9\x77\xFF\x2F\x47\x58\xDD"
+                         "\xD7\x8A\x91\x95\x26\x33\x78\xB2"
+                         "\x33\xBA\xB2\x3E\x02\xF5\x1F\xEF"
+                         "\x98\xC5\xA6\xD2\x7D\x79\xEC\xB3"
+                         "\x45\xF3\x4C\x61\xAC\x6C\xC2\x55"
+                         "\xE5\xD3\x06\x58\x8A\x42\x3E\xDD"
+                         "\x3D\x20\x45\xE9\x6F\x0D\x25\xA8"
+                         "\xA5\xC7\x69\xCE\xD5\x3B\x7B\xC9"
+                         "\x9E\x65\xE7\xA3\xF2\xE4\x18\x94"
+                         "\xD2\x81\xE9\x33\x2B\x2D\x49\xC4"
+                         "\xFE\xDA\x7F\xE2\xF2\x8C\x9C\xDC"
+                         "\x73\x58\x11\x1F\x81\xD7\x21\x1A"
+                         "\x80\xD0\x0D\xE8\x45\xD6\xD8\xD5"
+                         "\x2E\x51\x16\xCA\x09\x89\x54\x62"
+                         "\xF7\x04\x3D\x75\xB9\xA3\x84\xF4"
+                         "\x62\xF0\x02\x58\x83\xAF\x30\x87"
+                         "\x85\x3F\x01\xCD\x8E\x58\x42\xC4"
+                         "\x41\x73\xE0\x15\x0A\xE6\x2E\x80"
+                         "\x94\xF8\x5B\x3A\x4E\xDF\x51\xB2"
+                         "\x9D\xE4\xC4\x9D\xF7\x3F\xF8\x8E"
+                         "\x37\x22\x4D\x00\x2A\xEF\xC1\x0F"
+                         "\x14\xA0\x66\xAB\x79\x39\xD0\x8E"
+                         "\xE9\x95\x61\x74\x12\xED\x07\xD7"
+                         "\xDD\x95\xDC\x7B\x57\x25\x27\x9C"
+                         "\x51\x96\x16\xF7\x94\x61\xB8\x87"
+                         "\xF0\x21\x1B\x32\xFB\x07\x0F\x29"
+                         "\x56\xBD\x9D\x22\xA2\x9F\xA2\xB9"
+                         "\x46\x31\x4C\x5E\x2E\x95\x61\xEF"
+                         "\xE1\x58\x39\x09\xB4\x8B\x40\xAC"
+                         "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
        },
 };
 
@@ -2143,6 +2248,76 @@ static struct cipher_testvec des_dec_tv_template[] = {
                .rlen   = 16,
                .np     = 3,
                .tap    = { 3, 12, 1 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .input  = "\x88\xCB\x1F\xAB\x2F\x2A\x49\x57"
+                         "\x92\xB9\x77\xFF\x2F\x47\x58\xDD"
+                         "\xD7\x8A\x91\x95\x26\x33\x78\xB2"
+                         "\x33\xBA\xB2\x3E\x02\xF5\x1F\xEF"
+                         "\x98\xC5\xA6\xD2\x7D\x79\xEC\xB3"
+                         "\x45\xF3\x4C\x61\xAC\x6C\xC2\x55"
+                         "\xE5\xD3\x06\x58\x8A\x42\x3E\xDD"
+                         "\x3D\x20\x45\xE9\x6F\x0D\x25\xA8"
+                         "\xA5\xC7\x69\xCE\xD5\x3B\x7B\xC9"
+                         "\x9E\x65\xE7\xA3\xF2\xE4\x18\x94"
+                         "\xD2\x81\xE9\x33\x2B\x2D\x49\xC4"
+                         "\xFE\xDA\x7F\xE2\xF2\x8C\x9C\xDC"
+                         "\x73\x58\x11\x1F\x81\xD7\x21\x1A"
+                         "\x80\xD0\x0D\xE8\x45\xD6\xD8\xD5"
+                         "\x2E\x51\x16\xCA\x09\x89\x54\x62"
+                         "\xF7\x04\x3D\x75\xB9\xA3\x84\xF4"
+                         "\x62\xF0\x02\x58\x83\xAF\x30\x87"
+                         "\x85\x3F\x01\xCD\x8E\x58\x42\xC4"
+                         "\x41\x73\xE0\x15\x0A\xE6\x2E\x80"
+                         "\x94\xF8\x5B\x3A\x4E\xDF\x51\xB2"
+                         "\x9D\xE4\xC4\x9D\xF7\x3F\xF8\x8E"
+                         "\x37\x22\x4D\x00\x2A\xEF\xC1\x0F"
+                         "\x14\xA0\x66\xAB\x79\x39\xD0\x8E"
+                         "\xE9\x95\x61\x74\x12\xED\x07\xD7"
+                         "\xDD\x95\xDC\x7B\x57\x25\x27\x9C"
+                         "\x51\x96\x16\xF7\x94\x61\xB8\x87"
+                         "\xF0\x21\x1B\x32\xFB\x07\x0F\x29"
+                         "\x56\xBD\x9D\x22\xA2\x9F\xA2\xB9"
+                         "\x46\x31\x4C\x5E\x2E\x95\x61\xEF"
+                         "\xE1\x58\x39\x09\xB4\x8B\x40\xAC"
+                         "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
+               .ilen   = 248,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
        },
 };
 
@@ -2198,6 +2373,77 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
                .rlen   = 24,
                .np     = 2,
                .tap    = { 13, 11 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .ilen   = 248,
+               .result = "\x71\xCC\x56\x1C\x87\x2C\x43\x20"
+                         "\x1C\x20\x13\x09\xF9\x2B\x40\x47"
+                         "\x99\x10\xD1\x1B\x65\x33\x33\xBA"
+                         "\x88\x0D\xA2\xD1\x86\xFF\x4D\xF4"
+                         "\x5A\x0C\x12\x96\x32\x57\xAA\x26"
+                         "\xA7\xF4\x32\x8D\xBC\x10\x31\x9E"
+                         "\x81\x72\x74\xDE\x30\x19\x69\x49"
+                         "\x54\x9C\xC3\xEB\x0B\x97\xDD\xD1"
+                         "\xE8\x6D\x0D\x05\x83\xA5\x12\x08"
+                         "\x47\xF8\x88\x03\x86\x51\x3C\xEF"
+                         "\xE7\x11\x73\x4D\x44\x2B\xE2\x16"
+                         "\xE8\xA5\x06\x50\x66\x70\x0E\x14"
+                         "\xBA\x21\x3B\xD5\x23\x5B\xA7\x8F"
+                         "\x56\xB6\xA7\x44\xDB\x86\xAB\x69"
+                         "\x33\x3C\xBE\x64\xC4\x22\xD3\xFE"
+                         "\x49\x90\x88\x6A\x09\x8F\x76\x59"
+                         "\xCB\xB7\xA0\x2D\x79\x75\x92\x8A"
+                         "\x82\x1D\xC2\xFE\x09\x1F\x78\x6B"
+                         "\x2F\xD6\xA4\x87\x1E\xC4\x53\x63"
+                         "\x80\x02\x61\x2F\xE3\x46\xB6\xB5"
+                         "\xAA\x95\xF4\xEE\xA7\x64\x2B\x4F"
+                         "\x20\xCF\xD2\x47\x4E\x39\x65\xB3"
+                         "\x11\x87\xA2\x6C\x49\x7E\x36\xC7"
+                         "\x62\x8B\x48\x0D\x6A\x64\x00\xBD"
+                         "\x71\x91\x8C\xE9\x70\x19\x01\x4F"
+                         "\x4E\x68\x23\xBA\xDA\x24\x2E\x45"
+                         "\x02\x14\x33\x21\xAE\x58\x4B\xCF"
+                         "\x3B\x4B\xE8\xF8\xF6\x4F\x34\x93"
+                         "\xD7\x07\x8A\xD7\x18\x92\x36\x8C"
+                         "\x82\xA9\xBD\x6A\x31\x91\x39\x11"
+                         "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
        },
 };
 
@@ -2236,6 +2482,369 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
                .rlen   = 8,
                .np     = 2,
                .tap    = { 4, 4 }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x71\xCC\x56\x1C\x87\x2C\x43\x20"
+                         "\x1C\x20\x13\x09\xF9\x2B\x40\x47"
+                         "\x99\x10\xD1\x1B\x65\x33\x33\xBA"
+                         "\x88\x0D\xA2\xD1\x86\xFF\x4D\xF4"
+                         "\x5A\x0C\x12\x96\x32\x57\xAA\x26"
+                         "\xA7\xF4\x32\x8D\xBC\x10\x31\x9E"
+                         "\x81\x72\x74\xDE\x30\x19\x69\x49"
+                         "\x54\x9C\xC3\xEB\x0B\x97\xDD\xD1"
+                         "\xE8\x6D\x0D\x05\x83\xA5\x12\x08"
+                         "\x47\xF8\x88\x03\x86\x51\x3C\xEF"
+                         "\xE7\x11\x73\x4D\x44\x2B\xE2\x16"
+                         "\xE8\xA5\x06\x50\x66\x70\x0E\x14"
+                         "\xBA\x21\x3B\xD5\x23\x5B\xA7\x8F"
+                         "\x56\xB6\xA7\x44\xDB\x86\xAB\x69"
+                         "\x33\x3C\xBE\x64\xC4\x22\xD3\xFE"
+                         "\x49\x90\x88\x6A\x09\x8F\x76\x59"
+                         "\xCB\xB7\xA0\x2D\x79\x75\x92\x8A"
+                         "\x82\x1D\xC2\xFE\x09\x1F\x78\x6B"
+                         "\x2F\xD6\xA4\x87\x1E\xC4\x53\x63"
+                         "\x80\x02\x61\x2F\xE3\x46\xB6\xB5"
+                         "\xAA\x95\xF4\xEE\xA7\x64\x2B\x4F"
+                         "\x20\xCF\xD2\x47\x4E\x39\x65\xB3"
+                         "\x11\x87\xA2\x6C\x49\x7E\x36\xC7"
+                         "\x62\x8B\x48\x0D\x6A\x64\x00\xBD"
+                         "\x71\x91\x8C\xE9\x70\x19\x01\x4F"
+                         "\x4E\x68\x23\xBA\xDA\x24\x2E\x45"
+                         "\x02\x14\x33\x21\xAE\x58\x4B\xCF"
+                         "\x3B\x4B\xE8\xF8\xF6\x4F\x34\x93"
+                         "\xD7\x07\x8A\xD7\x18\x92\x36\x8C"
+                         "\x82\xA9\xBD\x6A\x31\x91\x39\x11"
+                         "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
+               .ilen   = 248,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
+       },
+};
+
+static struct cipher_testvec des_ctr_enc_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .ilen   = 248,
+               .result = "\x2F\x96\x06\x0F\x50\xC9\x68\x03"
+                         "\x0F\x31\xD4\x64\xA5\x29\x77\x35"
+                         "\xBC\x7A\x9F\x19\xE7\x0D\x33\x3E"
+                         "\x12\x0B\x8C\xAE\x48\xAE\xD9\x02"
+                         "\x0A\xD4\xB0\xD6\x37\xB2\x65\x1C"
+                         "\x4B\x65\xEB\x24\xB5\x8E\xAD\x47"
+                         "\x0D\xDA\x79\x77\xA0\x29\xA0\x2B"
+                         "\xC8\x0F\x85\xDC\x03\x13\xA9\x04"
+                         "\x19\x40\xBE\xBE\x5C\x49\x4A\x69"
+                         "\xED\xE8\xE1\x9E\x14\x43\x74\xDE"
+                         "\xEC\x6E\x11\x3F\x36\xEF\x7B\xFB"
+                         "\xBE\x4C\x91\x43\x22\x65\x72\x48"
+                         "\xE2\x12\xED\x88\xAC\xA7\xC9\x91"
+                         "\x14\xA2\x36\x1C\x29\xFF\xC8\x4F"
+                         "\x72\x5C\x4B\xB0\x1E\x93\xC2\xFA"
+                         "\x9D\x53\x86\xA0\xAE\xC6\xB7\x3C"
+                         "\x59\x0C\xD0\x8F\xA6\xD8\xA4\x31"
+                         "\xB7\x30\x1C\x21\x38\xFB\x68\x8C"
+                         "\x2E\xF5\x6E\x73\xC3\x16\x5F\x12"
+                         "\x0C\x33\xB9\x1E\x7B\x70\xDE\x86"
+                         "\x32\xB3\xC1\x16\xAB\xD9\x49\x0B"
+                         "\x96\x28\x72\x6B\xF3\x30\xA9\xEB"
+                         "\x69\xE2\x1E\x58\x46\xA2\x8E\xC7"
+                         "\xC0\xEF\x07\xB7\x77\x2C\x00\x05"
+                         "\x46\xBD\xFE\x53\x81\x8B\xA4\x03"
+                         "\x20\x0F\xDB\x78\x0B\x1F\x53\x04"
+                         "\x4C\x60\x4C\xC3\x2A\x86\x86\x7E"
+                         "\x13\xD2\x26\xED\x5D\x3E\x9C\xF2"
+                         "\x5C\xC4\x15\xC9\x9A\x21\xC5\xCD"
+                         "\x19\x7F\x99\x19\x53\xCE\x1D\x14"
+                         "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82",
+               .ilen   = 247,
+               .result = "\x62\xE5\xF4\xDC\x99\xE7\x89\xE3"
+                         "\xF4\x10\xCC\x21\x99\xEB\xDC\x15"
+                         "\x19\x13\x93\x27\x9D\xB6\x6F\x45"
+                         "\x17\x55\x61\x72\xC8\xD3\x7F\xA5"
+                         "\x32\xD0\xD3\x02\x15\xA4\x05\x23"
+                         "\x9C\x23\x61\x60\x77\x7B\x6C\x95"
+                         "\x26\x49\x42\x2E\xF3\xC1\x8C\x6D"
+                         "\xC8\x47\xD5\x94\xE7\x53\xC8\x23"
+                         "\x1B\xA5\x0B\xCB\x12\xD3\x7A\x12"
+                         "\xA4\x42\x15\x34\xF7\x5F\xDC\x58"
+                         "\x5B\x58\x4C\xAD\xD1\x33\x8E\xE6"
+                         "\xE5\xA0\xDA\x4D\x94\x3D\x63\xA8"
+                         "\x02\x82\xBB\x16\xB8\xDC\xB5\x58"
+                         "\xC3\x2D\x79\xE4\x25\x79\x43\xF9"
+                         "\x6D\xD3\xCA\xC0\xE8\x12\xD4\x7E"
+                         "\x04\x25\x79\xFD\x27\xFB\xC4\xEA"
+                         "\x32\x94\x48\x92\xF3\x68\x1A\x7F"
+                         "\x36\x33\x43\x79\xF7\xCA\xC2\x38"
+                         "\xC0\x68\xD4\x53\xA9\xCC\x43\x0C"
+                         "\x40\x57\x3E\xED\x00\x9F\x22\x6E"
+                         "\x80\x99\x0B\xCC\x40\x63\x46\x8A"
+                         "\xE8\xC4\x9B\x6D\x7A\x08\x6E\xA9"
+                         "\x6F\x84\xBC\xB3\xF4\x95\x0B\x2D"
+                         "\x6A\xBA\x37\x50\xC3\xCF\x9F\x7C"
+                         "\x59\x5E\xDE\x0B\x30\xFA\x34\x8A"
+                         "\xF8\xD1\xA2\xF8\x4E\xBD\x5D\x5E"
+                         "\x7D\x71\x99\xE0\xF6\xE5\x7C\xE0"
+                         "\x6D\xEE\x82\x89\x92\xD4\xF5\xD7"
+                         "\xDF\x85\x2D\xE1\xB2\xD6\xAB\x94"
+                         "\xA5\xA6\xE7\xB0\x51\x36\x52\x37"
+                         "\x91\x45\x05\x3E\x58\xBF\x32",
+               .rlen   = 247,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 247 - 8, 8 },
+       },
+};
+
+static struct cipher_testvec des_ctr_dec_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x2F\x96\x06\x0F\x50\xC9\x68\x03"
+                         "\x0F\x31\xD4\x64\xA5\x29\x77\x35"
+                         "\xBC\x7A\x9F\x19\xE7\x0D\x33\x3E"
+                         "\x12\x0B\x8C\xAE\x48\xAE\xD9\x02"
+                         "\x0A\xD4\xB0\xD6\x37\xB2\x65\x1C"
+                         "\x4B\x65\xEB\x24\xB5\x8E\xAD\x47"
+                         "\x0D\xDA\x79\x77\xA0\x29\xA0\x2B"
+                         "\xC8\x0F\x85\xDC\x03\x13\xA9\x04"
+                         "\x19\x40\xBE\xBE\x5C\x49\x4A\x69"
+                         "\xED\xE8\xE1\x9E\x14\x43\x74\xDE"
+                         "\xEC\x6E\x11\x3F\x36\xEF\x7B\xFB"
+                         "\xBE\x4C\x91\x43\x22\x65\x72\x48"
+                         "\xE2\x12\xED\x88\xAC\xA7\xC9\x91"
+                         "\x14\xA2\x36\x1C\x29\xFF\xC8\x4F"
+                         "\x72\x5C\x4B\xB0\x1E\x93\xC2\xFA"
+                         "\x9D\x53\x86\xA0\xAE\xC6\xB7\x3C"
+                         "\x59\x0C\xD0\x8F\xA6\xD8\xA4\x31"
+                         "\xB7\x30\x1C\x21\x38\xFB\x68\x8C"
+                         "\x2E\xF5\x6E\x73\xC3\x16\x5F\x12"
+                         "\x0C\x33\xB9\x1E\x7B\x70\xDE\x86"
+                         "\x32\xB3\xC1\x16\xAB\xD9\x49\x0B"
+                         "\x96\x28\x72\x6B\xF3\x30\xA9\xEB"
+                         "\x69\xE2\x1E\x58\x46\xA2\x8E\xC7"
+                         "\xC0\xEF\x07\xB7\x77\x2C\x00\x05"
+                         "\x46\xBD\xFE\x53\x81\x8B\xA4\x03"
+                         "\x20\x0F\xDB\x78\x0B\x1F\x53\x04"
+                         "\x4C\x60\x4C\xC3\x2A\x86\x86\x7E"
+                         "\x13\xD2\x26\xED\x5D\x3E\x9C\xF2"
+                         "\x5C\xC4\x15\xC9\x9A\x21\xC5\xCD"
+                         "\x19\x7F\x99\x19\x53\xCE\x1D\x14"
+                         "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
+               .ilen   = 248,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+               .rlen   = 248,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 248 - 8, 8 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+               .klen   = 8,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+               .input  = "\x62\xE5\xF4\xDC\x99\xE7\x89\xE3"
+                         "\xF4\x10\xCC\x21\x99\xEB\xDC\x15"
+                         "\x19\x13\x93\x27\x9D\xB6\x6F\x45"
+                         "\x17\x55\x61\x72\xC8\xD3\x7F\xA5"
+                         "\x32\xD0\xD3\x02\x15\xA4\x05\x23"
+                         "\x9C\x23\x61\x60\x77\x7B\x6C\x95"
+                         "\x26\x49\x42\x2E\xF3\xC1\x8C\x6D"
+                         "\xC8\x47\xD5\x94\xE7\x53\xC8\x23"
+                         "\x1B\xA5\x0B\xCB\x12\xD3\x7A\x12"
+                         "\xA4\x42\x15\x34\xF7\x5F\xDC\x58"
+                         "\x5B\x58\x4C\xAD\xD1\x33\x8E\xE6"
+                         "\xE5\xA0\xDA\x4D\x94\x3D\x63\xA8"
+                         "\x02\x82\xBB\x16\xB8\xDC\xB5\x58"
+                         "\xC3\x2D\x79\xE4\x25\x79\x43\xF9"
+                         "\x6D\xD3\xCA\xC0\xE8\x12\xD4\x7E"
+                         "\x04\x25\x79\xFD\x27\xFB\xC4\xEA"
+                         "\x32\x94\x48\x92\xF3\x68\x1A\x7F"
+                         "\x36\x33\x43\x79\xF7\xCA\xC2\x38"
+                         "\xC0\x68\xD4\x53\xA9\xCC\x43\x0C"
+                         "\x40\x57\x3E\xED\x00\x9F\x22\x6E"
+                         "\x80\x99\x0B\xCC\x40\x63\x46\x8A"
+                         "\xE8\xC4\x9B\x6D\x7A\x08\x6E\xA9"
+                         "\x6F\x84\xBC\xB3\xF4\x95\x0B\x2D"
+                         "\x6A\xBA\x37\x50\xC3\xCF\x9F\x7C"
+                         "\x59\x5E\xDE\x0B\x30\xFA\x34\x8A"
+                         "\xF8\xD1\xA2\xF8\x4E\xBD\x5D\x5E"
+                         "\x7D\x71\x99\xE0\xF6\xE5\x7C\xE0"
+                         "\x6D\xEE\x82\x89\x92\xD4\xF5\xD7"
+                         "\xDF\x85\x2D\xE1\xB2\xD6\xAB\x94"
+                         "\xA5\xA6\xE7\xB0\x51\x36\x52\x37"
+                         "\x91\x45\x05\x3E\x58\xBF\x32",
+               .ilen   = 247,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82",
+               .rlen   = 247,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 247 - 8, 8 },
        },
 };
 
@@ -2267,6 +2876,140 @@ static struct cipher_testvec des3_ede_enc_tv_template[] = {
                .ilen   = 8,
                .result = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
                .rlen   = 8,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xF3\x9C\xD6\xF3\x9C\xB9\x5A\x67"
+                         "\x00\x5A\x67\x00\x2D\xCE\xEB\x2D"
+                         "\xCE\xEB\xB4\x51\x72\xB4\x51\x72",
+               .klen   = 24,
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .ilen   = 496,
+               .result = "\x4E\x9A\x40\x3D\x61\x7D\x17\xFA"
+                         "\x16\x86\x88\x0B\xD8\xAE\xF8\xE4"
+                         "\x81\x01\x04\x00\x76\xFA\xED\xD3"
+                         "\x44\x7E\x21\x9D\xF0\xFB\x2B\x64"
+                         "\xCA\x4E\x90\xE0\xC0\x63\x28\x92"
+                         "\xF3\x1F\xA4\x53\x2C\x77\xCC\x77"
+                         "\x69\x56\xD0\x19\xAD\x00\x2D\x97"
+                         "\xBC\xDE\x49\x6A\x82\xBC\x16\xE2"
+                         "\x2F\x3E\x72\xEE\xD1\xCE\xFC\x1B"
+                         "\xEA\x32\x56\xE4\x0B\xAF\x27\x36"
+                         "\xAF\x08\xB9\x61\xB7\x48\x23\x27"
+                         "\xEE\x4D\xC8\x79\x56\x06\xEB\xC7"
+                         "\x5B\xCA\x0A\xC6\x5E\x5C\xCB\xB6"
+                         "\x9D\xDA\x04\x59\xE2\x09\x48\x7E"
+                         "\x6B\x37\xC6\xFE\x92\xA9\x1E\x6E"
+                         "\x0D\x19\xFA\x33\x0F\xEE\x36\x68"
+                         "\x11\xBB\xF9\x5A\x73\xAB\x3A\xEA"
+                         "\xAC\x28\xD8\xD5\x27\xE8\x6B\x16"
+                         "\x45\x86\x50\x01\x70\x35\x99\x92"
+                         "\xDF\x0C\x07\x88\x8B\x7F\x9E\x4B"
+                         "\xD2\x04\x84\x90\xC4\x27\xDF\x0A"
+                         "\x49\xA8\xA7\x1A\x6D\x78\x16\xCA"
+                         "\xB3\x18\x5C\xC3\x93\x63\x5A\x68"
+                         "\x77\x02\xBA\xED\x62\x71\xB1\xD9"
+                         "\x5E\xE5\x6F\x1A\xCC\x1D\xBE\x2E"
+                         "\x11\xF3\xA6\x97\xCA\x8E\xBF\xB4"
+                         "\x56\xA1\x36\x6B\xB1\x0A\x3E\x70"
+                         "\xEA\xD7\xCD\x72\x7B\x79\xC8\xAD"
+                         "\x6B\xFE\xFB\xBA\x64\xAE\x19\xC1"
+                         "\x82\xCF\x8A\xA1\x50\x17\x7F\xB2"
+                         "\x6F\x7B\x0F\x52\xC5\x3E\x4A\x52"
+                         "\x3F\xD9\x3F\x01\xA6\x41\x1A\xB3"
+                         "\xB3\x7A\x0E\x8E\x75\xB2\xB1\x5F"
+                         "\xDB\xEA\x84\x13\x26\x6C\x85\x4E"
+                         "\xAE\x6B\xDC\xE7\xE7\xAD\xB0\x06"
+                         "\x5C\xBA\x92\xD0\x30\xBB\x8D\xD2"
+                         "\xAE\x4C\x70\x85\xA0\x07\xE3\x2C"
+                         "\xD1\x27\x9C\xCF\xDB\x13\xB7\xE5"
+                         "\xF9\x6A\x02\xD0\x39\x9D\xB6\xE7"
+                         "\xD1\x17\x25\x08\xF9\xA9\xA6\x67"
+                         "\x38\x80\xD1\x22\xAB\x1A\xD7\x26"
+                         "\xAD\xCA\x19\x1B\xFA\x18\xA7\x57"
+                         "\x31\xEC\xC9\xED\xDB\x79\xC0\x48"
+                         "\xAC\x31\x9F\x03\x8B\x62\x5B\x7E"
+                         "\x0E\xA6\xD0\x64\xEE\xEA\x00\xFC"
+                         "\x58\xC8\xDE\x51\x4E\x17\x15\x11"
+                         "\x66\x58\xB6\x90\xDC\xDF\xA1\x49"
+                         "\xCA\x79\xE9\x31\x31\x42\xDC\x56"
+                         "\x0B\xCD\xB6\x0D\xC7\x64\xF7\x19"
+                         "\xD9\x42\x05\x7F\xBC\x2F\xFC\x90"
+                         "\xAE\x29\x86\xAA\x43\x7A\x4F\x6B"
+                         "\xCE\xEA\xBC\x31\x8D\x65\x9D\x46"
+                         "\xEA\x77\xB4\xF9\x58\xEA\x5D\x84"
+                         "\xE4\xDC\x14\xBB\xBD\x15\x0E\xDA"
+                         "\xD8\xE4\xA4\x5D\x61\xF9\x58\x0F"
+                         "\xE4\x82\x77\xCE\x87\xC0\x09\xF0"
+                         "\xD6\x10\x9E\x34\xE1\x0C\x67\x55"
+                         "\x7B\x6D\xD5\x51\x4B\x00\xEE\xBA"
+                         "\xF2\x7B\xBE\x75\x07\x42\x9D\x99"
+                         "\x12\xE1\x71\x4A\xF9\x2A\xF5\xF6"
+                         "\x93\x03\xD7\x51\x09\xFA\xBE\x68"
+                         "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -2298,6 +3041,140 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
                .ilen   = 8,
                .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
                .rlen   = 8,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xF3\x9C\xD6\xF3\x9C\xB9\x5A\x67"
+                         "\x00\x5A\x67\x00\x2D\xCE\xEB\x2D"
+                         "\xCE\xEB\xB4\x51\x72\xB4\x51\x72",
+               .klen   = 24,
+               .input  = "\x4E\x9A\x40\x3D\x61\x7D\x17\xFA"
+                         "\x16\x86\x88\x0B\xD8\xAE\xF8\xE4"
+                         "\x81\x01\x04\x00\x76\xFA\xED\xD3"
+                         "\x44\x7E\x21\x9D\xF0\xFB\x2B\x64"
+                         "\xCA\x4E\x90\xE0\xC0\x63\x28\x92"
+                         "\xF3\x1F\xA4\x53\x2C\x77\xCC\x77"
+                         "\x69\x56\xD0\x19\xAD\x00\x2D\x97"
+                         "\xBC\xDE\x49\x6A\x82\xBC\x16\xE2"
+                         "\x2F\x3E\x72\xEE\xD1\xCE\xFC\x1B"
+                         "\xEA\x32\x56\xE4\x0B\xAF\x27\x36"
+                         "\xAF\x08\xB9\x61\xB7\x48\x23\x27"
+                         "\xEE\x4D\xC8\x79\x56\x06\xEB\xC7"
+                         "\x5B\xCA\x0A\xC6\x5E\x5C\xCB\xB6"
+                         "\x9D\xDA\x04\x59\xE2\x09\x48\x7E"
+                         "\x6B\x37\xC6\xFE\x92\xA9\x1E\x6E"
+                         "\x0D\x19\xFA\x33\x0F\xEE\x36\x68"
+                         "\x11\xBB\xF9\x5A\x73\xAB\x3A\xEA"
+                         "\xAC\x28\xD8\xD5\x27\xE8\x6B\x16"
+                         "\x45\x86\x50\x01\x70\x35\x99\x92"
+                         "\xDF\x0C\x07\x88\x8B\x7F\x9E\x4B"
+                         "\xD2\x04\x84\x90\xC4\x27\xDF\x0A"
+                         "\x49\xA8\xA7\x1A\x6D\x78\x16\xCA"
+                         "\xB3\x18\x5C\xC3\x93\x63\x5A\x68"
+                         "\x77\x02\xBA\xED\x62\x71\xB1\xD9"
+                         "\x5E\xE5\x6F\x1A\xCC\x1D\xBE\x2E"
+                         "\x11\xF3\xA6\x97\xCA\x8E\xBF\xB4"
+                         "\x56\xA1\x36\x6B\xB1\x0A\x3E\x70"
+                         "\xEA\xD7\xCD\x72\x7B\x79\xC8\xAD"
+                         "\x6B\xFE\xFB\xBA\x64\xAE\x19\xC1"
+                         "\x82\xCF\x8A\xA1\x50\x17\x7F\xB2"
+                         "\x6F\x7B\x0F\x52\xC5\x3E\x4A\x52"
+                         "\x3F\xD9\x3F\x01\xA6\x41\x1A\xB3"
+                         "\xB3\x7A\x0E\x8E\x75\xB2\xB1\x5F"
+                         "\xDB\xEA\x84\x13\x26\x6C\x85\x4E"
+                         "\xAE\x6B\xDC\xE7\xE7\xAD\xB0\x06"
+                         "\x5C\xBA\x92\xD0\x30\xBB\x8D\xD2"
+                         "\xAE\x4C\x70\x85\xA0\x07\xE3\x2C"
+                         "\xD1\x27\x9C\xCF\xDB\x13\xB7\xE5"
+                         "\xF9\x6A\x02\xD0\x39\x9D\xB6\xE7"
+                         "\xD1\x17\x25\x08\xF9\xA9\xA6\x67"
+                         "\x38\x80\xD1\x22\xAB\x1A\xD7\x26"
+                         "\xAD\xCA\x19\x1B\xFA\x18\xA7\x57"
+                         "\x31\xEC\xC9\xED\xDB\x79\xC0\x48"
+                         "\xAC\x31\x9F\x03\x8B\x62\x5B\x7E"
+                         "\x0E\xA6\xD0\x64\xEE\xEA\x00\xFC"
+                         "\x58\xC8\xDE\x51\x4E\x17\x15\x11"
+                         "\x66\x58\xB6\x90\xDC\xDF\xA1\x49"
+                         "\xCA\x79\xE9\x31\x31\x42\xDC\x56"
+                         "\x0B\xCD\xB6\x0D\xC7\x64\xF7\x19"
+                         "\xD9\x42\x05\x7F\xBC\x2F\xFC\x90"
+                         "\xAE\x29\x86\xAA\x43\x7A\x4F\x6B"
+                         "\xCE\xEA\xBC\x31\x8D\x65\x9D\x46"
+                         "\xEA\x77\xB4\xF9\x58\xEA\x5D\x84"
+                         "\xE4\xDC\x14\xBB\xBD\x15\x0E\xDA"
+                         "\xD8\xE4\xA4\x5D\x61\xF9\x58\x0F"
+                         "\xE4\x82\x77\xCE\x87\xC0\x09\xF0"
+                         "\xD6\x10\x9E\x34\xE1\x0C\x67\x55"
+                         "\x7B\x6D\xD5\x51\x4B\x00\xEE\xBA"
+                         "\xF2\x7B\xBE\x75\x07\x42\x9D\x99"
+                         "\x12\xE1\x71\x4A\xF9\x2A\xF5\xF6"
+                         "\x93\x03\xD7\x51\x09\xFA\xBE\x68"
+                         "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
+               .ilen   = 496,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -2342,6 +3219,142 @@ static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = {
                          "\x9d\xde\xa5\x70\xe9\x42\x45\x8a"
                          "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19",
                .rlen   = 128,
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .ilen   = 496,
+               .result = "\xF8\xF6\xB5\x60\x5C\x5A\x75\x84"
+                         "\x87\x81\x53\xBA\xC9\x6F\xEC\xD5"
+                         "\x1E\x68\x8E\x85\x12\x86\x1D\x38"
+                         "\x1C\x91\x40\xCC\x69\x6A\xD5\x35"
+                         "\x0D\x7C\xB5\x07\x7C\x7B\x2A\xAF"
+                         "\x32\xBC\xA1\xB3\x84\x31\x1B\x3C"
+                         "\x0A\x2B\xFA\xD3\x9F\xB0\x8C\x37"
+                         "\x8F\x9D\xA7\x6D\x6C\xFA\xD7\x90"
+                         "\xE3\x69\x54\xED\x3A\xC4\xF1\x6B"
+                         "\xB1\xCC\xFB\x7D\xD8\x8E\x17\x0B"
+                         "\x9C\xF6\x4C\xD6\xFF\x03\x4E\xD9"
+                         "\xE6\xA5\xAD\x25\xE6\x17\x69\x63"
+                         "\x11\x35\x61\x94\x88\x7B\x1C\x48"
+                         "\xF1\x24\x20\x29\x6B\x93\x1A\x8E"
+                         "\x43\x03\x89\xD8\xB1\xDA\x47\x7B"
+                         "\x79\x3A\x83\x76\xDA\xAE\xC6\xBB"
+                         "\x22\xF8\xE8\x3D\x9A\x65\x54\xD8"
+                         "\x4C\xE9\xE7\xE4\x63\x2F\x5C\x73"
+                         "\x5A\xC3\xAE\x46\xA8\xCD\x57\xE6"
+                         "\x67\x88\xA5\x20\x6F\x5F\x97\xC7"
+                         "\xCC\x15\xA2\x0A\x93\xEA\x33\xE7"
+                         "\x03\x5F\xEC\x64\x30\x6F\xEE\xD7"
+                         "\x7E\xDF\xD6\xE9\x6F\x3F\xD6\x1E"
+                         "\xBE\x67\x6C\x5B\x97\xA0\x09\xE6"
+                         "\xEE\xFE\x55\xA3\x29\x65\xE0\x12"
+                         "\xA1\x6A\x8A\x6F\xF2\xE6\xF1\x96"
+                         "\x87\xFB\x9C\x05\xDD\x80\xEC\xFF"
+                         "\xC5\xED\x50\xFE\xFC\x91\xCD\xCE"
+                         "\x25\x2C\x5F\xD9\xAD\x95\x7D\x99"
+                         "\xF0\x05\xC4\x71\x46\x5F\xF9\x0D"
+                         "\xD2\x63\xDF\x9B\x96\x2E\x2B\xA6"
+                         "\x2B\x1C\xD5\xFB\x96\x24\x60\x60"
+                         "\x54\x40\xB8\x62\xA4\xF8\x46\x95"
+                         "\x73\x28\xA3\xA6\x16\x2B\x17\xE7"
+                         "\x7A\xF8\x62\x54\x3B\x64\x69\xE1"
+                         "\x71\x34\x29\x5B\x4E\x05\x9B\xFA"
+                         "\x5E\xF1\x96\xB7\xCE\x16\x9B\x59"
+                         "\xF1\x1A\x4C\x51\x26\xFD\x79\xE2"
+                         "\x3B\x8E\x71\x69\x6A\x91\xB6\x65"
+                         "\x32\x09\xB8\xE4\x09\x1F\xEA\x39"
+                         "\xCE\x20\x65\x9F\xD6\xD1\xC7\xF0"
+                         "\x73\x50\x08\x56\x20\x9B\x94\x23"
+                         "\x14\x39\xB7\x2B\xB1\x2D\x6D\x6F"
+                         "\x41\x5B\xCC\xE2\x18\xAE\x62\x89"
+                         "\x78\x8E\x67\x23\xD0\xFB\x2B\xE5"
+                         "\x25\xC9\x48\x97\xB5\xD3\x17\xD5"
+                         "\x6A\x9F\xA7\x48\x0C\x2B\x73\x3B"
+                         "\x57\x08\xAE\x91\xF2\xB7\x57\x89"
+                         "\xF4\xD0\xB0\x07\xB0\x42\x6C\xAF"
+                         "\x98\x1A\xE7\xD1\xAC\x1E\xB5\x02"
+                         "\xD4\x56\x42\x79\x79\x7F\x2A\x77"
+                         "\x25\xE9\x7D\xC1\x88\x19\x2B\x49"
+                         "\x6F\x46\x59\xAB\x56\x1F\x61\xE0"
+                         "\x0C\x24\x9C\xC9\x5B\x63\xA9\x12"
+                         "\xCF\x88\x96\xB6\xA8\x24\xC6\xA8"
+                         "\x21\x85\x1A\x62\x7E\x34\xBB\xEB"
+                         "\xBD\x02\x2A\xC7\xD8\x89\x80\xC5"
+                         "\xB1\xBB\x60\xA5\x22\xFC\x6F\x38"
+                         "\x02\x80\xA3\x28\x22\x75\xE1\xE9"
+                         "\x90\xE9\xFA\x4B\x00\x10\xAC\x58"
+                         "\x83\x70\xFF\x86\xE6\xAA\x0F\x1F"
+                         "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -2386,6 +3399,698 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
                          "\x63\x65\x65\x72\x73\x74\x54\x20"
                          "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79",
                .rlen   = 128,
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\xF8\xF6\xB5\x60\x5C\x5A\x75\x84"
+                         "\x87\x81\x53\xBA\xC9\x6F\xEC\xD5"
+                         "\x1E\x68\x8E\x85\x12\x86\x1D\x38"
+                         "\x1C\x91\x40\xCC\x69\x6A\xD5\x35"
+                         "\x0D\x7C\xB5\x07\x7C\x7B\x2A\xAF"
+                         "\x32\xBC\xA1\xB3\x84\x31\x1B\x3C"
+                         "\x0A\x2B\xFA\xD3\x9F\xB0\x8C\x37"
+                         "\x8F\x9D\xA7\x6D\x6C\xFA\xD7\x90"
+                         "\xE3\x69\x54\xED\x3A\xC4\xF1\x6B"
+                         "\xB1\xCC\xFB\x7D\xD8\x8E\x17\x0B"
+                         "\x9C\xF6\x4C\xD6\xFF\x03\x4E\xD9"
+                         "\xE6\xA5\xAD\x25\xE6\x17\x69\x63"
+                         "\x11\x35\x61\x94\x88\x7B\x1C\x48"
+                         "\xF1\x24\x20\x29\x6B\x93\x1A\x8E"
+                         "\x43\x03\x89\xD8\xB1\xDA\x47\x7B"
+                         "\x79\x3A\x83\x76\xDA\xAE\xC6\xBB"
+                         "\x22\xF8\xE8\x3D\x9A\x65\x54\xD8"
+                         "\x4C\xE9\xE7\xE4\x63\x2F\x5C\x73"
+                         "\x5A\xC3\xAE\x46\xA8\xCD\x57\xE6"
+                         "\x67\x88\xA5\x20\x6F\x5F\x97\xC7"
+                         "\xCC\x15\xA2\x0A\x93\xEA\x33\xE7"
+                         "\x03\x5F\xEC\x64\x30\x6F\xEE\xD7"
+                         "\x7E\xDF\xD6\xE9\x6F\x3F\xD6\x1E"
+                         "\xBE\x67\x6C\x5B\x97\xA0\x09\xE6"
+                         "\xEE\xFE\x55\xA3\x29\x65\xE0\x12"
+                         "\xA1\x6A\x8A\x6F\xF2\xE6\xF1\x96"
+                         "\x87\xFB\x9C\x05\xDD\x80\xEC\xFF"
+                         "\xC5\xED\x50\xFE\xFC\x91\xCD\xCE"
+                         "\x25\x2C\x5F\xD9\xAD\x95\x7D\x99"
+                         "\xF0\x05\xC4\x71\x46\x5F\xF9\x0D"
+                         "\xD2\x63\xDF\x9B\x96\x2E\x2B\xA6"
+                         "\x2B\x1C\xD5\xFB\x96\x24\x60\x60"
+                         "\x54\x40\xB8\x62\xA4\xF8\x46\x95"
+                         "\x73\x28\xA3\xA6\x16\x2B\x17\xE7"
+                         "\x7A\xF8\x62\x54\x3B\x64\x69\xE1"
+                         "\x71\x34\x29\x5B\x4E\x05\x9B\xFA"
+                         "\x5E\xF1\x96\xB7\xCE\x16\x9B\x59"
+                         "\xF1\x1A\x4C\x51\x26\xFD\x79\xE2"
+                         "\x3B\x8E\x71\x69\x6A\x91\xB6\x65"
+                         "\x32\x09\xB8\xE4\x09\x1F\xEA\x39"
+                         "\xCE\x20\x65\x9F\xD6\xD1\xC7\xF0"
+                         "\x73\x50\x08\x56\x20\x9B\x94\x23"
+                         "\x14\x39\xB7\x2B\xB1\x2D\x6D\x6F"
+                         "\x41\x5B\xCC\xE2\x18\xAE\x62\x89"
+                         "\x78\x8E\x67\x23\xD0\xFB\x2B\xE5"
+                         "\x25\xC9\x48\x97\xB5\xD3\x17\xD5"
+                         "\x6A\x9F\xA7\x48\x0C\x2B\x73\x3B"
+                         "\x57\x08\xAE\x91\xF2\xB7\x57\x89"
+                         "\xF4\xD0\xB0\x07\xB0\x42\x6C\xAF"
+                         "\x98\x1A\xE7\xD1\xAC\x1E\xB5\x02"
+                         "\xD4\x56\x42\x79\x79\x7F\x2A\x77"
+                         "\x25\xE9\x7D\xC1\x88\x19\x2B\x49"
+                         "\x6F\x46\x59\xAB\x56\x1F\x61\xE0"
+                         "\x0C\x24\x9C\xC9\x5B\x63\xA9\x12"
+                         "\xCF\x88\x96\xB6\xA8\x24\xC6\xA8"
+                         "\x21\x85\x1A\x62\x7E\x34\xBB\xEB"
+                         "\xBD\x02\x2A\xC7\xD8\x89\x80\xC5"
+                         "\xB1\xBB\x60\xA5\x22\xFC\x6F\x38"
+                         "\x02\x80\xA3\x28\x22\x75\xE1\xE9"
+                         "\x90\xE9\xFA\x4B\x00\x10\xAC\x58"
+                         "\x83\x70\xFF\x86\xE6\xAA\x0F\x1F"
+                         "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
+               .ilen   = 496,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       },
+};
+
+static struct cipher_testvec des3_ede_ctr_enc_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .ilen   = 496,
+               .result = "\x07\xC2\x08\x20\x72\x1F\x49\xEF"
+                         "\x19\xCD\x6F\x32\x53\x05\x22\x15"
+                         "\xA2\x85\x2B\xDB\x85\xD2\xD8\xB9"
+                         "\xDD\x0D\x1B\x45\xCB\x69\x11\xD4"
+                         "\xEA\xBE\xB2\x45\x5D\x0C\xAE\xBE"
+                         "\xA0\xC1\x27\xAC\x65\x9F\x53\x7E"
+                         "\xAF\xC2\x1B\xB5\xB8\x6D\x36\x0C"
+                         "\x25\xC0\xF8\x6D\x0B\x29\x01\xDA"
+                         "\x13\x78\xDC\x89\x12\x12\x43\xFA"
+                         "\xF6\x12\xEF\x8D\x87\x62\x78\x83"
+                         "\xE2\xBE\x41\x20\x4C\x6D\x35\x1B"
+                         "\xD1\x0C\x30\xCF\xE2\xDE\x2B\x03"
+                         "\xBF\x45\x73\xD4\xE5\x59\x95\xD1"
+                         "\xB3\x9B\x27\x62\x97\xBD\xDE\x7F"
+                         "\xA4\xD2\x39\x80\xAA\x50\x23\xF0"
+                         "\x74\x88\x3D\xA8\x6A\x18\x79\x3B"
+                         "\xC4\x96\x6C\x8D\x22\x40\x92\x6E"
+                         "\xD6\xAD\x2A\x1F\xDE\x63\xC0\xE7"
+                         "\x07\xF7\x2D\xF7\xB5\xF3\xF0\xCC"
+                         "\x01\x7C\x2A\x9B\xC2\x10\xCA\xAA"
+                         "\xFD\x2B\x3F\xC5\xF3\xF6\xFC\x9B"
+                         "\x45\xDB\x53\xE4\x5B\xF3\xC9\x7B"
+                         "\x8E\x52\xFF\xC8\x02\xB8\xAC\x9D"
+                         "\xA1\x00\x39\xDA\x3D\x2D\x0E\x01"
+                         "\x09\x7D\x8D\x5E\xBE\x53\xB9\xB0"
+                         "\x8E\xE7\xE2\x96\x6A\xB2\x78\xEA"
+                         "\xDE\x23\x8B\xA5\xFA\x5C\xE3\xDA"
+                         "\xBF\x8E\x31\x6A\x55\xD1\x6A\xB2"
+                         "\xB5\x46\x6F\xA5\xF0\xEE\xBA\x1F"
+                         "\x9F\x98\xB0\x66\x4F\xD0\x3F\xA9"
+                         "\xDF\x5F\x58\xC4\xF4\xFF\x75\x5C"
+                         "\x40\x3A\x09\x7E\x6E\x1C\x97\xD4"
+                         "\xCC\xE7\xE7\x71\xCF\x0B\x15\x08"
+                         "\x71\xFA\x07\x97\xCD\xE6\xCA\x1D"
+                         "\x14\x28\x0C\xCF\x99\x13\x7A\xF1"
+                         "\xEB\xFA\xFA\x92\x07\xDE\x1D\xA1"
+                         "\xD3\x36\x69\xFE\x51\x4D\x9F\x2E"
+                         "\x83\x37\x4F\x1F\x48\x30\xED\x04"
+                         "\x4D\xA4\xEF\x3A\xCA\x76\xF4\x1C"
+                         "\x41\x8F\x63\x37\x78\x2F\x86\xA6"
+                         "\xEF\x41\x7E\xD2\xAF\x88\xAB\x67"
+                         "\x52\x71\xC3\x8E\xF8\x26\x93\x72"
+                         "\xAA\xD6\x0E\xE7\x0B\x46\xB1\x3A"
+                         "\xB4\x08\xA9\xA8\xA0\xCF\x20\x0C"
+                         "\x52\xBC\x8B\x05\x56\xB2\xBC\x31"
+                         "\x9B\x74\xB9\x29\x29\x96\x9A\x50"
+                         "\xDC\x45\xDC\x1A\xEB\x0C\x64\xD4"
+                         "\xD3\x05\x7E\x59\x55\xC3\xF4\x90"
+                         "\xC2\xAB\xF8\x9B\x8A\xDA\xCE\xA1"
+                         "\xC3\xF4\xAD\x77\xDD\x44\xC8\xAC"
+                         "\xA3\xF1\xC9\xD2\x19\x5C\xB0\xCA"
+                         "\xA2\x34\xC1\xF7\x6C\xFD\xAC\x65"
+                         "\x32\xDC\x48\xC4\xF2\x00\x6B\x77"
+                         "\xF1\x7D\x76\xAC\xC0\x31\x63\x2A"
+                         "\xA5\x3A\x62\xC8\x91\xB1\x03\x65"
+                         "\xCB\x43\xD1\x06\xDF\xC3\x67\xBC"
+                         "\xDC\xE0\xCD\x35\xCE\x49\x65\xA0"
+                         "\x52\x7B\xA7\x0D\x07\xA9\x1B\xB0"
+                         "\x40\x77\x72\xC2\xEA\x0E\x3A\x78"
+                         "\x46\xB9\x91\xB6\xE7\x3D\x51\x42"
+                         "\xFD\x51\xB0\xC6\x2C\x63\x13\x78"
+                         "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47"
+                         "\x2E\xB1\x18",
+               .ilen   = 499,
+               .result = "\x23\xFF\x5C\x99\x75\xBB\x1F\xD4"
+                         "\xBC\x27\x9D\x36\x60\xA9\xC9\xF7"
+                         "\x94\x9D\x1B\xFF\x8E\x95\x57\x89"
+                         "\x8C\x2E\x33\x70\x43\x61\xE6\xD2"
+                         "\x82\x33\x63\xB6\xC4\x34\x5E\xF8"
+                         "\x96\x07\xA7\xD2\x3B\x8E\xC9\xAA"
+                         "\x7C\xA0\x55\x89\x2E\xE1\x85\x25"
+                         "\x14\x04\xDA\x6B\xE0\xEE\x56\xCF"
+                         "\x08\x2E\x69\xD4\x54\xDE\x22\x84"
+                         "\x69\xA6\xA7\xD3\x3A\x9A\xE8\x05"
+                         "\x63\xDB\xBF\x46\x3A\x26\x2E\x0F"
+                         "\x58\x5C\x46\xEA\x07\x40\xDA\xE1"
+                         "\x14\x1D\xCD\x4F\x06\xC0\xCA\x54"
+                         "\x1E\xC9\x45\x85\x67\x7C\xC2\xB5"
+                         "\x97\x5D\x61\x78\x2E\x46\xEC\x6A"
+                         "\x53\xF4\xD0\xAE\xFA\xB4\x86\x29"
+                         "\x9F\x17\x33\x24\xD8\xB9\xB2\x05"
+                         "\x93\x88\xEA\xF7\xA0\x70\x69\x49"
+                         "\x88\x6B\x73\x40\x41\x8D\xD9\xD9"
+                         "\x7E\x78\xE9\xBE\x6C\x14\x22\x7A"
+                         "\x66\xE1\xDA\xED\x10\xFF\x69\x1D"
+                         "\xB9\xAA\xF2\x56\x72\x1B\x23\xE2"
+                         "\x45\x54\x8B\xA3\x70\x23\xB4\x5E"
+                         "\x8E\x96\xC9\x05\x00\xB3\xB6\xC2"
+                         "\x2A\x02\x43\x7A\x62\xD5\xC8\xD2"
+                         "\xC2\xD0\xE4\x78\xA1\x7B\x3E\xE8"
+                         "\x9F\x7F\x7D\x40\x54\x30\x3B\xC0"
+                         "\xA5\x54\xFD\xCA\x25\xEC\x44\x3E"
+                         "\x1A\x54\x7F\x88\xD0\xE1\xFE\x71"
+                         "\xCE\x05\x49\x89\xBA\xD6\x72\xE7"
+                         "\xD6\x5D\x3F\xA2\xD9\xAB\xC5\x02"
+                         "\xD6\x43\x22\xAF\xA2\xE4\x80\x85"
+                         "\xD7\x87\xB9\xEA\x43\xDB\xC8\xEF"
+                         "\x5C\x82\x2E\x98\x0D\x30\x41\x6B"
+                         "\x08\x48\x8D\xF0\xF8\x60\xD7\x9D"
+                         "\xE9\xDE\x40\xAD\x0D\xAD\x0D\x58"
+                         "\x2A\x98\x35\xFE\xF7\xDD\x4B\x40"
+                         "\xDE\xB0\x05\xD9\x7B\x09\x4D\xBC"
+                         "\x42\xC0\xF1\x15\x0B\xFA\x26\x6B"
+                         "\xC6\x12\x13\x4F\xCB\x35\xBA\x35"
+                         "\xDD\x7A\x36\x9C\x12\x57\x55\x83"
+                         "\x78\x58\x09\xD0\xB0\xCF\x7C\x5C"
+                         "\x38\xCF\xBD\x79\x5B\x13\x4D\x97"
+                         "\xC1\x85\x6F\x97\xC9\xE8\xC2\xA4"
+                         "\x98\xE2\xBD\x77\x6B\x53\x39\x1A"
+                         "\x28\x10\xE7\xE0\xE7\xDE\x9D\x69"
+                         "\x78\x6F\x8E\xD2\xD9\x5D\xD2\x15"
+                         "\x9E\xB5\x4D\x8C\xC0\x78\x22\x2F"
+                         "\x17\x11\x2E\x99\xD7\xE3\xA4\x4F"
+                         "\x65\xA5\x6B\x03\x2C\x35\x6F\xDA"
+                         "\x8A\x19\x08\xE1\x08\x48\x59\x51"
+                         "\x53\x4B\xD1\xDF\xDA\x14\x50\x5F"
+                         "\xDF\xB5\x8C\xDF\xC6\xFD\x85\xFA"
+                         "\xD4\xF9\x64\x45\x65\x0D\x7D\xF4"
+                         "\xC8\xCD\x3F\x32\xAF\xDD\x30\xED"
+                         "\x7B\xAA\xAC\xF0\xDA\x7F\xDF\x75"
+                         "\x1C\xA4\xF1\xCB\x5E\x4F\x0B\xB4"
+                         "\x97\x73\x28\xDE\xCF\xAF\x82\xBD"
+                         "\xC4\xBA\xB4\x9C\x0D\x16\x77\x42"
+                         "\x42\x39\x7C\x53\xA4\xD4\xDD\x40"
+                         "\x5C\x60\x1F\x6E\xA7\xE2\xDC\xE7"
+                         "\x32\x0F\x05\x2F\xF2\x4C\x95\x3B"
+                         "\xF2\x79\xD9",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
+       },
+};
+
+static struct cipher_testvec des3_ede_ctr_dec_tv_template[] = {
+       { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x07\xC2\x08\x20\x72\x1F\x49\xEF"
+                         "\x19\xCD\x6F\x32\x53\x05\x22\x15"
+                         "\xA2\x85\x2B\xDB\x85\xD2\xD8\xB9"
+                         "\xDD\x0D\x1B\x45\xCB\x69\x11\xD4"
+                         "\xEA\xBE\xB2\x45\x5D\x0C\xAE\xBE"
+                         "\xA0\xC1\x27\xAC\x65\x9F\x53\x7E"
+                         "\xAF\xC2\x1B\xB5\xB8\x6D\x36\x0C"
+                         "\x25\xC0\xF8\x6D\x0B\x29\x01\xDA"
+                         "\x13\x78\xDC\x89\x12\x12\x43\xFA"
+                         "\xF6\x12\xEF\x8D\x87\x62\x78\x83"
+                         "\xE2\xBE\x41\x20\x4C\x6D\x35\x1B"
+                         "\xD1\x0C\x30\xCF\xE2\xDE\x2B\x03"
+                         "\xBF\x45\x73\xD4\xE5\x59\x95\xD1"
+                         "\xB3\x9B\x27\x62\x97\xBD\xDE\x7F"
+                         "\xA4\xD2\x39\x80\xAA\x50\x23\xF0"
+                         "\x74\x88\x3D\xA8\x6A\x18\x79\x3B"
+                         "\xC4\x96\x6C\x8D\x22\x40\x92\x6E"
+                         "\xD6\xAD\x2A\x1F\xDE\x63\xC0\xE7"
+                         "\x07\xF7\x2D\xF7\xB5\xF3\xF0\xCC"
+                         "\x01\x7C\x2A\x9B\xC2\x10\xCA\xAA"
+                         "\xFD\x2B\x3F\xC5\xF3\xF6\xFC\x9B"
+                         "\x45\xDB\x53\xE4\x5B\xF3\xC9\x7B"
+                         "\x8E\x52\xFF\xC8\x02\xB8\xAC\x9D"
+                         "\xA1\x00\x39\xDA\x3D\x2D\x0E\x01"
+                         "\x09\x7D\x8D\x5E\xBE\x53\xB9\xB0"
+                         "\x8E\xE7\xE2\x96\x6A\xB2\x78\xEA"
+                         "\xDE\x23\x8B\xA5\xFA\x5C\xE3\xDA"
+                         "\xBF\x8E\x31\x6A\x55\xD1\x6A\xB2"
+                         "\xB5\x46\x6F\xA5\xF0\xEE\xBA\x1F"
+                         "\x9F\x98\xB0\x66\x4F\xD0\x3F\xA9"
+                         "\xDF\x5F\x58\xC4\xF4\xFF\x75\x5C"
+                         "\x40\x3A\x09\x7E\x6E\x1C\x97\xD4"
+                         "\xCC\xE7\xE7\x71\xCF\x0B\x15\x08"
+                         "\x71\xFA\x07\x97\xCD\xE6\xCA\x1D"
+                         "\x14\x28\x0C\xCF\x99\x13\x7A\xF1"
+                         "\xEB\xFA\xFA\x92\x07\xDE\x1D\xA1"
+                         "\xD3\x36\x69\xFE\x51\x4D\x9F\x2E"
+                         "\x83\x37\x4F\x1F\x48\x30\xED\x04"
+                         "\x4D\xA4\xEF\x3A\xCA\x76\xF4\x1C"
+                         "\x41\x8F\x63\x37\x78\x2F\x86\xA6"
+                         "\xEF\x41\x7E\xD2\xAF\x88\xAB\x67"
+                         "\x52\x71\xC3\x8E\xF8\x26\x93\x72"
+                         "\xAA\xD6\x0E\xE7\x0B\x46\xB1\x3A"
+                         "\xB4\x08\xA9\xA8\xA0\xCF\x20\x0C"
+                         "\x52\xBC\x8B\x05\x56\xB2\xBC\x31"
+                         "\x9B\x74\xB9\x29\x29\x96\x9A\x50"
+                         "\xDC\x45\xDC\x1A\xEB\x0C\x64\xD4"
+                         "\xD3\x05\x7E\x59\x55\xC3\xF4\x90"
+                         "\xC2\xAB\xF8\x9B\x8A\xDA\xCE\xA1"
+                         "\xC3\xF4\xAD\x77\xDD\x44\xC8\xAC"
+                         "\xA3\xF1\xC9\xD2\x19\x5C\xB0\xCA"
+                         "\xA2\x34\xC1\xF7\x6C\xFD\xAC\x65"
+                         "\x32\xDC\x48\xC4\xF2\x00\x6B\x77"
+                         "\xF1\x7D\x76\xAC\xC0\x31\x63\x2A"
+                         "\xA5\x3A\x62\xC8\x91\xB1\x03\x65"
+                         "\xCB\x43\xD1\x06\xDF\xC3\x67\xBC"
+                         "\xDC\xE0\xCD\x35\xCE\x49\x65\xA0"
+                         "\x52\x7B\xA7\x0D\x07\xA9\x1B\xB0"
+                         "\x40\x77\x72\xC2\xEA\x0E\x3A\x78"
+                         "\x46\xB9\x91\xB6\xE7\x3D\x51\x42"
+                         "\xFD\x51\xB0\xC6\x2C\x63\x13\x78"
+                         "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
+               .ilen   = 496,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+                         "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+                         "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+               .klen   = 24,
+               .iv     = "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+                         "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+               .input  = "\x23\xFF\x5C\x99\x75\xBB\x1F\xD4"
+                         "\xBC\x27\x9D\x36\x60\xA9\xC9\xF7"
+                         "\x94\x9D\x1B\xFF\x8E\x95\x57\x89"
+                         "\x8C\x2E\x33\x70\x43\x61\xE6\xD2"
+                         "\x82\x33\x63\xB6\xC4\x34\x5E\xF8"
+                         "\x96\x07\xA7\xD2\x3B\x8E\xC9\xAA"
+                         "\x7C\xA0\x55\x89\x2E\xE1\x85\x25"
+                         "\x14\x04\xDA\x6B\xE0\xEE\x56\xCF"
+                         "\x08\x2E\x69\xD4\x54\xDE\x22\x84"
+                         "\x69\xA6\xA7\xD3\x3A\x9A\xE8\x05"
+                         "\x63\xDB\xBF\x46\x3A\x26\x2E\x0F"
+                         "\x58\x5C\x46\xEA\x07\x40\xDA\xE1"
+                         "\x14\x1D\xCD\x4F\x06\xC0\xCA\x54"
+                         "\x1E\xC9\x45\x85\x67\x7C\xC2\xB5"
+                         "\x97\x5D\x61\x78\x2E\x46\xEC\x6A"
+                         "\x53\xF4\xD0\xAE\xFA\xB4\x86\x29"
+                         "\x9F\x17\x33\x24\xD8\xB9\xB2\x05"
+                         "\x93\x88\xEA\xF7\xA0\x70\x69\x49"
+                         "\x88\x6B\x73\x40\x41\x8D\xD9\xD9"
+                         "\x7E\x78\xE9\xBE\x6C\x14\x22\x7A"
+                         "\x66\xE1\xDA\xED\x10\xFF\x69\x1D"
+                         "\xB9\xAA\xF2\x56\x72\x1B\x23\xE2"
+                         "\x45\x54\x8B\xA3\x70\x23\xB4\x5E"
+                         "\x8E\x96\xC9\x05\x00\xB3\xB6\xC2"
+                         "\x2A\x02\x43\x7A\x62\xD5\xC8\xD2"
+                         "\xC2\xD0\xE4\x78\xA1\x7B\x3E\xE8"
+                         "\x9F\x7F\x7D\x40\x54\x30\x3B\xC0"
+                         "\xA5\x54\xFD\xCA\x25\xEC\x44\x3E"
+                         "\x1A\x54\x7F\x88\xD0\xE1\xFE\x71"
+                         "\xCE\x05\x49\x89\xBA\xD6\x72\xE7"
+                         "\xD6\x5D\x3F\xA2\xD9\xAB\xC5\x02"
+                         "\xD6\x43\x22\xAF\xA2\xE4\x80\x85"
+                         "\xD7\x87\xB9\xEA\x43\xDB\xC8\xEF"
+                         "\x5C\x82\x2E\x98\x0D\x30\x41\x6B"
+                         "\x08\x48\x8D\xF0\xF8\x60\xD7\x9D"
+                         "\xE9\xDE\x40\xAD\x0D\xAD\x0D\x58"
+                         "\x2A\x98\x35\xFE\xF7\xDD\x4B\x40"
+                         "\xDE\xB0\x05\xD9\x7B\x09\x4D\xBC"
+                         "\x42\xC0\xF1\x15\x0B\xFA\x26\x6B"
+                         "\xC6\x12\x13\x4F\xCB\x35\xBA\x35"
+                         "\xDD\x7A\x36\x9C\x12\x57\x55\x83"
+                         "\x78\x58\x09\xD0\xB0\xCF\x7C\x5C"
+                         "\x38\xCF\xBD\x79\x5B\x13\x4D\x97"
+                         "\xC1\x85\x6F\x97\xC9\xE8\xC2\xA4"
+                         "\x98\xE2\xBD\x77\x6B\x53\x39\x1A"
+                         "\x28\x10\xE7\xE0\xE7\xDE\x9D\x69"
+                         "\x78\x6F\x8E\xD2\xD9\x5D\xD2\x15"
+                         "\x9E\xB5\x4D\x8C\xC0\x78\x22\x2F"
+                         "\x17\x11\x2E\x99\xD7\xE3\xA4\x4F"
+                         "\x65\xA5\x6B\x03\x2C\x35\x6F\xDA"
+                         "\x8A\x19\x08\xE1\x08\x48\x59\x51"
+                         "\x53\x4B\xD1\xDF\xDA\x14\x50\x5F"
+                         "\xDF\xB5\x8C\xDF\xC6\xFD\x85\xFA"
+                         "\xD4\xF9\x64\x45\x65\x0D\x7D\xF4"
+                         "\xC8\xCD\x3F\x32\xAF\xDD\x30\xED"
+                         "\x7B\xAA\xAC\xF0\xDA\x7F\xDF\x75"
+                         "\x1C\xA4\xF1\xCB\x5E\x4F\x0B\xB4"
+                         "\x97\x73\x28\xDE\xCF\xAF\x82\xBD"
+                         "\xC4\xBA\xB4\x9C\x0D\x16\x77\x42"
+                         "\x42\x39\x7C\x53\xA4\xD4\xDD\x40"
+                         "\x5C\x60\x1F\x6E\xA7\xE2\xDC\xE7"
+                         "\x32\x0F\x05\x2F\xF2\x4C\x95\x3B"
+                         "\xF2\x79\xD9",
+               .ilen   = 499,
+               .result = "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+                         "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+                         "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+                         "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+                         "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+                         "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+                         "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+                         "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+                         "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+                         "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+                         "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+                         "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+                         "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+                         "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+                         "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+                         "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+                         "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+                         "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+                         "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+                         "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+                         "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+                         "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+                         "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+                         "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+                         "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+                         "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+                         "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+                         "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+                         "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+                         "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+                         "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+                         "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+                         "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+                         "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+                         "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+                         "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+                         "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+                         "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+                         "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+                         "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+                         "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+                         "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+                         "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+                         "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+                         "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+                         "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+                         "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+                         "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+                         "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+                         "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+                         "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+                         "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+                         "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+                         "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+                         "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+                         "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+                         "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+                         "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+                         "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+                         "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+                         "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+                         "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47"
+                         "\x2E\xB1\x18",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
        },
 };
 
@@ -2461,17 +4166,133 @@ static struct cipher_testvec bf_enc_tv_template[] = {
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .ilen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .ilen   = 504,
                .result = "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
                          "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
                          "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
                          "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
-                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
-               .rlen   = 40,
+                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B"
+                         "\xD3\xB2\xD4\x61\xC7\x9F\x06\xE9"
+                         "\xCD\xF3\x88\x39\x39\x7A\xDF\x19"
+                         "\xE8\x03\x2A\x0B\x9E\xA0\x2B\x86"
+                         "\x31\xF8\x9D\xB1\xEE\x78\x9D\xB5"
+                         "\xCD\x8B\x7C\x2E\xF5\xA2\x2D\x5D"
+                         "\x6E\x66\xAF\x38\x6C\xD3\x13\xED"
+                         "\x14\xEA\x5D\xD0\x17\x77\x0F\x4A"
+                         "\x50\xF2\xD0\x0F\xC8\xF7\x1E\x7B"
+                         "\x9D\x5B\x54\x65\x4F\x16\x8A\x97"
+                         "\xF3\xF6\xD4\xAA\x87\x36\x77\x72"
+                         "\x99\x4A\xB5\x5E\x88\xC3\xCD\x7D"
+                         "\x1D\x97\xF9\x11\xBD\xE0\x1F\x1F"
+                         "\x96\x3E\x4B\x22\xF4\xC0\xE6\xB8"
+                         "\x47\x82\x98\x23\x33\x36\xBC\x1B"
+                         "\x36\xE7\xF6\xCF\x97\x37\x16\xC0"
+                         "\x87\x31\x8B\xB0\xDB\x19\x42\xA5"
+                         "\x1F\x90\x7E\x66\x34\xDD\x5E\xE9"
+                         "\x4F\xB2\x2B\x9A\xDE\xB3\x5D\x71"
+                         "\x4D\x68\xF0\xDC\xA6\xEA\xE3\x9B"
+                         "\x60\x00\x55\x57\x06\x8B\xD5\xB3"
+                         "\x86\x30\x78\xDA\x33\x9A\x9D\xCC"
+                         "\xBA\x0B\x81\x06\x77\x43\xC7\xC9"
+                         "\xDB\x37\x60\x11\x45\x59\x6D\x2D"
+                         "\x90\x3D\x65\x3E\xD0\x13\xC6\x3C"
+                         "\x0E\x78\x7D\x9A\x00\xD6\x2F\x0B"
+                         "\x3B\x53\x19\x1E\xA8\x9B\x11\xD9"
+                         "\x98\xE4\x7F\xC3\x6E\x51\x24\x70"
+                         "\x9F\x04\x9C\xC2\x9E\x44\x84\xE3"
+                         "\xE0\x8A\x44\xA2\x5C\x94\x74\x34"
+                         "\x37\x52\x7C\x03\xE8\x8E\x97\xE1"
+                         "\x5B\x5C\x0E\xB0\x70\xFE\x54\x3F"
+                         "\xD8\x65\xA9\xC5\xCD\xEC\xF4\x45"
+                         "\x55\xC5\xA7\xA3\x19\x80\x28\x51"
+                         "\xBE\x64\x4A\xC1\xD4\xE1\xBE\xEB"
+                         "\x73\x4C\xB6\xF9\x5F\x6D\x82\xBC"
+                         "\x3E\x42\x14\x49\x88\x51\xBF\x68"
+                         "\x45\x75\x27\x1B\x0A\x72\xED\xAF"
+                         "\xDA\xC4\x4D\x67\x0D\xEE\x75\xE3"
+                         "\x34\xDD\x91\x19\x42\x3A\xCB\xDA"
+                         "\x38\xFA\x3C\x93\x62\xF2\xE3\x81"
+                         "\xB3\xE4\xBB\xF6\x0D\x0B\x1D\x09"
+                         "\x9C\x52\x0D\x50\x63\xA4\xB2\xD2"
+                         "\x82\xA0\x23\x3F\x1F\xB6\xED\x6E"
+                         "\xC2\x9C\x1C\xD0\x9A\x40\xB6\xFC"
+                         "\x36\x56\x6E\x85\x73\xD7\x52\xBA"
+                         "\x35\x5E\x32\x89\x5D\x42\xF5\x36"
+                         "\x52\x8D\x46\x7D\xC8\x71\xAD\x33"
+                         "\xE1\xAF\x6A\xA8\xEC\xBA\x1C\xDC"
+                         "\xFE\x88\xE6\x16\xE4\xC8\x13\x00"
+                         "\x3C\xDA\x59\x32\x38\x19\xD5\xEB"
+                         "\xB6\x7F\x78\x45\x1B\x8E\x07\x8C"
+                         "\x66\x52\x75\xFF\xAF\xCE\x2D\x2B"
+                         "\x22\x29\xCA\xB3\x5F\x7F\xE3\x29"
+                         "\xB2\xB8\x9D\xEB\x16\xC8\xC5\x1D"
+                         "\xC9\x0D\x59\x82\x27\x57\x9D\x42"
+                         "\x54\x59\x09\xA5\x3D\xC5\x84\x68"
+                         "\x56\xEB\x36\x77\x3D\xAA\xB8\xF5"
+                         "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
+               .rlen   = 504,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 40 - 8, 8 },
+               .tap    = { 504 - 8, 8 },
        },
 };
 
@@ -2537,17 +4358,133 @@ static struct cipher_testvec bf_dec_tv_template[] = {
                          "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
                          "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
                          "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
-                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
-               .ilen   = 40,
+                         "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B"
+                         "\xD3\xB2\xD4\x61\xC7\x9F\x06\xE9"
+                         "\xCD\xF3\x88\x39\x39\x7A\xDF\x19"
+                         "\xE8\x03\x2A\x0B\x9E\xA0\x2B\x86"
+                         "\x31\xF8\x9D\xB1\xEE\x78\x9D\xB5"
+                         "\xCD\x8B\x7C\x2E\xF5\xA2\x2D\x5D"
+                         "\x6E\x66\xAF\x38\x6C\xD3\x13\xED"
+                         "\x14\xEA\x5D\xD0\x17\x77\x0F\x4A"
+                         "\x50\xF2\xD0\x0F\xC8\xF7\x1E\x7B"
+                         "\x9D\x5B\x54\x65\x4F\x16\x8A\x97"
+                         "\xF3\xF6\xD4\xAA\x87\x36\x77\x72"
+                         "\x99\x4A\xB5\x5E\x88\xC3\xCD\x7D"
+                         "\x1D\x97\xF9\x11\xBD\xE0\x1F\x1F"
+                         "\x96\x3E\x4B\x22\xF4\xC0\xE6\xB8"
+                         "\x47\x82\x98\x23\x33\x36\xBC\x1B"
+                         "\x36\xE7\xF6\xCF\x97\x37\x16\xC0"
+                         "\x87\x31\x8B\xB0\xDB\x19\x42\xA5"
+                         "\x1F\x90\x7E\x66\x34\xDD\x5E\xE9"
+                         "\x4F\xB2\x2B\x9A\xDE\xB3\x5D\x71"
+                         "\x4D\x68\xF0\xDC\xA6\xEA\xE3\x9B"
+                         "\x60\x00\x55\x57\x06\x8B\xD5\xB3"
+                         "\x86\x30\x78\xDA\x33\x9A\x9D\xCC"
+                         "\xBA\x0B\x81\x06\x77\x43\xC7\xC9"
+                         "\xDB\x37\x60\x11\x45\x59\x6D\x2D"
+                         "\x90\x3D\x65\x3E\xD0\x13\xC6\x3C"
+                         "\x0E\x78\x7D\x9A\x00\xD6\x2F\x0B"
+                         "\x3B\x53\x19\x1E\xA8\x9B\x11\xD9"
+                         "\x98\xE4\x7F\xC3\x6E\x51\x24\x70"
+                         "\x9F\x04\x9C\xC2\x9E\x44\x84\xE3"
+                         "\xE0\x8A\x44\xA2\x5C\x94\x74\x34"
+                         "\x37\x52\x7C\x03\xE8\x8E\x97\xE1"
+                         "\x5B\x5C\x0E\xB0\x70\xFE\x54\x3F"
+                         "\xD8\x65\xA9\xC5\xCD\xEC\xF4\x45"
+                         "\x55\xC5\xA7\xA3\x19\x80\x28\x51"
+                         "\xBE\x64\x4A\xC1\xD4\xE1\xBE\xEB"
+                         "\x73\x4C\xB6\xF9\x5F\x6D\x82\xBC"
+                         "\x3E\x42\x14\x49\x88\x51\xBF\x68"
+                         "\x45\x75\x27\x1B\x0A\x72\xED\xAF"
+                         "\xDA\xC4\x4D\x67\x0D\xEE\x75\xE3"
+                         "\x34\xDD\x91\x19\x42\x3A\xCB\xDA"
+                         "\x38\xFA\x3C\x93\x62\xF2\xE3\x81"
+                         "\xB3\xE4\xBB\xF6\x0D\x0B\x1D\x09"
+                         "\x9C\x52\x0D\x50\x63\xA4\xB2\xD2"
+                         "\x82\xA0\x23\x3F\x1F\xB6\xED\x6E"
+                         "\xC2\x9C\x1C\xD0\x9A\x40\xB6\xFC"
+                         "\x36\x56\x6E\x85\x73\xD7\x52\xBA"
+                         "\x35\x5E\x32\x89\x5D\x42\xF5\x36"
+                         "\x52\x8D\x46\x7D\xC8\x71\xAD\x33"
+                         "\xE1\xAF\x6A\xA8\xEC\xBA\x1C\xDC"
+                         "\xFE\x88\xE6\x16\xE4\xC8\x13\x00"
+                         "\x3C\xDA\x59\x32\x38\x19\xD5\xEB"
+                         "\xB6\x7F\x78\x45\x1B\x8E\x07\x8C"
+                         "\x66\x52\x75\xFF\xAF\xCE\x2D\x2B"
+                         "\x22\x29\xCA\xB3\x5F\x7F\xE3\x29"
+                         "\xB2\xB8\x9D\xEB\x16\xC8\xC5\x1D"
+                         "\xC9\x0D\x59\x82\x27\x57\x9D\x42"
+                         "\x54\x59\x09\xA5\x3D\xC5\x84\x68"
+                         "\x56\xEB\x36\x77\x3D\xAA\xB8\xF5"
+                         "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
+               .ilen   = 504,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .rlen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .rlen   = 504,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 40 - 8, 8 },
+               .tap    = { 504 - 8, 8 },
        },
 };
 
@@ -2578,29 +4515,145 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .ilen   = 40,
-               .result = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
-                         "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
-                         "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
-                         "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
-                         "\x01\x9C\x93\x63\x51\x60\x82\xD2",
-               .rlen   = 40,
-               .also_non_np = 1,
-               .np     = 2,
-               .tap    = { 40 - 8, 8 },
-       },
-};
-
-static struct cipher_testvec bf_cbc_dec_tv_template[] = {
-       { /* From OpenSSL */
-               .key    = "\x01\x23\x45\x67\x89\xab\xcd\xef"
-                         "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
-               .klen   = 16,
-               .iv     = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
-               .input  = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
-                         "\x05\xb1\x56\xe2\x74\x03\x97\x93"
-                         "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .ilen   = 504,
+               .result = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+                         "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+                         "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+                         "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+                         "\x01\x9C\x93\x63\x51\x60\x82\xD2"
+                         "\x4D\xE5\xC2\xB7\xAE\x60\xD8\xAD"
+                         "\x9F\xAB\x6C\xFA\x20\x05\xDA\x6F"
+                         "\x1F\xD1\xD8\x36\x0F\xB5\x16\x69"
+                         "\x3C\xAF\xB3\x30\x18\x33\xE6\xB5"
+                         "\x43\x29\x9D\x94\xF4\x2F\x0A\x65"
+                         "\x40\xB2\xB2\xB2\x42\x89\xEE\x8A"
+                         "\x60\xD3\x52\xA8\xED\x91\xDF\xE1"
+                         "\x91\x73\x7C\x28\xA1\x14\xC3\x4C"
+                         "\x82\x72\x4B\x7D\x7D\x32\xD5\x19"
+                         "\xE8\xB8\x6B\x30\x21\x09\x0E\x27"
+                         "\x10\x9D\x2D\x3A\x6A\x4B\x7B\xE6"
+                         "\x8D\x4E\x02\x32\xFF\x7F\x8E\x13"
+                         "\xB0\x96\xF4\xC2\xA1\x60\x8A\x69"
+                         "\xEF\x0F\x86\xD0\x25\x13\x1A\x7C"
+                         "\x6E\xF0\x41\xA3\xFB\xB3\xAB\x40"
+                         "\x7D\x19\xA0\x11\x4F\x3E\x1D\x43"
+                         "\x65\xFE\x15\x40\xD0\x62\x41\x02"
+                         "\xEA\x0C\x7A\xC3\x84\xEE\xB0\xBE"
+                         "\xBE\xC8\x57\x51\xCD\x4F\xAD\x5C"
+                         "\xCC\x79\xBA\x0D\x85\x3A\xED\x6B"
+                         "\xAC\x6B\xA3\x4D\xBC\xE8\x02\x6A"
+                         "\xC2\x6D\xBD\x5E\x89\x95\x86\x43"
+                         "\x2C\x17\x4B\xC6\x40\xA2\xBD\x24"
+                         "\x04\xF0\x86\x08\x78\x18\x42\xE0"
+                         "\x39\x1B\x22\x9E\x89\x4C\x04\x6B"
+                         "\x65\xC5\xB6\x0E\xF6\x63\xFC\xD7"
+                         "\xAE\x9E\x87\x13\xCC\xD3\x1A\xEC"
+                         "\xF0\x51\xCC\x93\x68\xFC\xE9\x19"
+                         "\x7C\x4E\x9B\xCC\x17\xAD\xD2\xFC"
+                         "\x97\x18\x92\xFF\x15\x11\xCE\xED"
+                         "\x04\x41\x05\xA3\x92\xFF\x3B\xE6"
+                         "\xB6\x8C\x90\xC6\xCD\x15\xA0\x04"
+                         "\x25\x8B\x5D\x5B\x5F\xDB\xAE\x68"
+                         "\xEF\xB3\x61\x18\xDB\x83\x9B\x39"
+                         "\xCA\x82\xD1\x88\xF0\xA2\x5C\x02"
+                         "\x87\xBD\x8D\x8F\xBB\x62\xF0\x35"
+                         "\x75\x6F\x06\x81\x0A\x97\x4D\xF0"
+                         "\x43\x12\x73\x77\xDB\x91\x83\x5B"
+                         "\xE7\x3A\xA6\x07\x7B\xBF\x2C\x50"
+                         "\x94\xDE\x7B\x65\xDA\x1C\xF1\x9F"
+                         "\x7E\x12\x40\xB2\x3E\x19\x23\xF1"
+                         "\x7C\x1B\x5F\xA8\xF3\xAC\x63\x87"
+                         "\xEB\x3E\x0C\xBE\xA3\x63\x97\x88"
+                         "\x8D\x27\xC6\x2A\xF8\xF2\x67\x9A"
+                         "\x0D\x14\x16\x2B\x6F\xCB\xD4\x76"
+                         "\x14\x48\x2E\xDE\x2A\x44\x5E\x45"
+                         "\xF1\x97\x82\xEF\xB7\xAE\xED\x3A"
+                         "\xED\x73\xD3\x79\xF7\x38\x1D\xD0"
+                         "\xC5\xF8\x69\x83\x28\x84\x87\x56"
+                         "\x3F\xAE\x81\x04\x79\x1F\xD1\x09"
+                         "\xC5\xE5\x05\x0D\x64\x16\xCE\x42"
+                         "\xC5\xF8\xDB\x57\x89\x33\x22\xFC"
+                         "\xB4\xD7\x94\xB9\xF3\xCC\x02\x90"
+                         "\x02\xBA\x55\x1E\x24\x3E\x02\x1D"
+                         "\xC6\xCD\x8F\xD9\xBD\xED\xB0\x51"
+                         "\xCD\xE9\xD5\x0C\xFE\x12\x39\xA9"
+                         "\x93\x9B\xEE\xB5\x97\x41\xD2\xA0"
+                         "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
+               .rlen   = 504,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 504 - 8, 8 },
+       },
+};
+
+static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+       { /* From OpenSSL */
+               .key    = "\x01\x23\x45\x67\x89\xab\xcd\xef"
+                         "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+               .klen   = 16,
+               .iv     = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+               .input  = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
+                         "\x05\xb1\x56\xe2\x74\x03\x97\x93"
+                         "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
                          "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
                .ilen   = 32,
                .result = "\x37\x36\x35\x34\x33\x32\x31\x20"
@@ -2619,17 +4672,133 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
                          "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
                          "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
                          "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
-                         "\x01\x9C\x93\x63\x51\x60\x82\xD2",
-               .ilen   = 40,
+                         "\x01\x9C\x93\x63\x51\x60\x82\xD2"
+                         "\x4D\xE5\xC2\xB7\xAE\x60\xD8\xAD"
+                         "\x9F\xAB\x6C\xFA\x20\x05\xDA\x6F"
+                         "\x1F\xD1\xD8\x36\x0F\xB5\x16\x69"
+                         "\x3C\xAF\xB3\x30\x18\x33\xE6\xB5"
+                         "\x43\x29\x9D\x94\xF4\x2F\x0A\x65"
+                         "\x40\xB2\xB2\xB2\x42\x89\xEE\x8A"
+                         "\x60\xD3\x52\xA8\xED\x91\xDF\xE1"
+                         "\x91\x73\x7C\x28\xA1\x14\xC3\x4C"
+                         "\x82\x72\x4B\x7D\x7D\x32\xD5\x19"
+                         "\xE8\xB8\x6B\x30\x21\x09\x0E\x27"
+                         "\x10\x9D\x2D\x3A\x6A\x4B\x7B\xE6"
+                         "\x8D\x4E\x02\x32\xFF\x7F\x8E\x13"
+                         "\xB0\x96\xF4\xC2\xA1\x60\x8A\x69"
+                         "\xEF\x0F\x86\xD0\x25\x13\x1A\x7C"
+                         "\x6E\xF0\x41\xA3\xFB\xB3\xAB\x40"
+                         "\x7D\x19\xA0\x11\x4F\x3E\x1D\x43"
+                         "\x65\xFE\x15\x40\xD0\x62\x41\x02"
+                         "\xEA\x0C\x7A\xC3\x84\xEE\xB0\xBE"
+                         "\xBE\xC8\x57\x51\xCD\x4F\xAD\x5C"
+                         "\xCC\x79\xBA\x0D\x85\x3A\xED\x6B"
+                         "\xAC\x6B\xA3\x4D\xBC\xE8\x02\x6A"
+                         "\xC2\x6D\xBD\x5E\x89\x95\x86\x43"
+                         "\x2C\x17\x4B\xC6\x40\xA2\xBD\x24"
+                         "\x04\xF0\x86\x08\x78\x18\x42\xE0"
+                         "\x39\x1B\x22\x9E\x89\x4C\x04\x6B"
+                         "\x65\xC5\xB6\x0E\xF6\x63\xFC\xD7"
+                         "\xAE\x9E\x87\x13\xCC\xD3\x1A\xEC"
+                         "\xF0\x51\xCC\x93\x68\xFC\xE9\x19"
+                         "\x7C\x4E\x9B\xCC\x17\xAD\xD2\xFC"
+                         "\x97\x18\x92\xFF\x15\x11\xCE\xED"
+                         "\x04\x41\x05\xA3\x92\xFF\x3B\xE6"
+                         "\xB6\x8C\x90\xC6\xCD\x15\xA0\x04"
+                         "\x25\x8B\x5D\x5B\x5F\xDB\xAE\x68"
+                         "\xEF\xB3\x61\x18\xDB\x83\x9B\x39"
+                         "\xCA\x82\xD1\x88\xF0\xA2\x5C\x02"
+                         "\x87\xBD\x8D\x8F\xBB\x62\xF0\x35"
+                         "\x75\x6F\x06\x81\x0A\x97\x4D\xF0"
+                         "\x43\x12\x73\x77\xDB\x91\x83\x5B"
+                         "\xE7\x3A\xA6\x07\x7B\xBF\x2C\x50"
+                         "\x94\xDE\x7B\x65\xDA\x1C\xF1\x9F"
+                         "\x7E\x12\x40\xB2\x3E\x19\x23\xF1"
+                         "\x7C\x1B\x5F\xA8\xF3\xAC\x63\x87"
+                         "\xEB\x3E\x0C\xBE\xA3\x63\x97\x88"
+                         "\x8D\x27\xC6\x2A\xF8\xF2\x67\x9A"
+                         "\x0D\x14\x16\x2B\x6F\xCB\xD4\x76"
+                         "\x14\x48\x2E\xDE\x2A\x44\x5E\x45"
+                         "\xF1\x97\x82\xEF\xB7\xAE\xED\x3A"
+                         "\xED\x73\xD3\x79\xF7\x38\x1D\xD0"
+                         "\xC5\xF8\x69\x83\x28\x84\x87\x56"
+                         "\x3F\xAE\x81\x04\x79\x1F\xD1\x09"
+                         "\xC5\xE5\x05\x0D\x64\x16\xCE\x42"
+                         "\xC5\xF8\xDB\x57\x89\x33\x22\xFC"
+                         "\xB4\xD7\x94\xB9\xF3\xCC\x02\x90"
+                         "\x02\xBA\x55\x1E\x24\x3E\x02\x1D"
+                         "\xC6\xCD\x8F\xD9\xBD\xED\xB0\x51"
+                         "\xCD\xE9\xD5\x0C\xFE\x12\x39\xA9"
+                         "\x93\x9B\xEE\xB5\x97\x41\xD2\xA0"
+                         "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
+               .ilen   = 504,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .rlen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .rlen   = 504,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 40 - 8, 8 },
+               .tap    = { 504 - 8, 8 },
        },
 };
 
@@ -2645,14 +4814,130 @@ static struct cipher_testvec bf_ctr_enc_tv_template[] = {
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .ilen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .ilen   = 504,
                .result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
                          "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
-                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
-               .rlen   = 40,
+                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D\x29",
+               .rlen   = 504,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2665,18 +4950,132 @@ static struct cipher_testvec bf_ctr_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B",
-               .ilen   = 43,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92",
+               .ilen   = 503,
                .result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
                          "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
                          "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
-                         "\x3D\xA7\xE9",
-               .rlen   = 43,
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D",
+               .rlen   = 503,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 43 - 8, 8 },
+               .tap    = { 503 - 8, 8 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2827,14 +5226,130 @@ static struct cipher_testvec bf_ctr_dec_tv_template[] = {
                          "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
-                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
-               .ilen   = 40,
+                         "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D\x29",
+               .ilen   = 504,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-               .rlen   = 40,
+                         "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+               .rlen   = 504,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2847,18 +5362,132 @@ static struct cipher_testvec bf_ctr_dec_tv_template[] = {
                          "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
                          "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
                          "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
-                         "\x3D\xA7\xE9",
-               .ilen   = 43,
+                         "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+                         "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+                         "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+                         "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+                         "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+                         "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+                         "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+                         "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+                         "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+                         "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+                         "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+                         "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+                         "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+                         "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+                         "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+                         "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+                         "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+                         "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+                         "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+                         "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+                         "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+                         "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+                         "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+                         "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+                         "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+                         "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+                         "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+                         "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+                         "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+                         "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+                         "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+                         "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+                         "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+                         "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+                         "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+                         "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+                         "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+                         "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+                         "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+                         "\x82\x63\x11\xB3\x54\x49\x00\x08"
+                         "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+                         "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+                         "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+                         "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+                         "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+                         "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+                         "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+                         "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+                         "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+                         "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+                         "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+                         "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+                         "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+                         "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+                         "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+                         "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+                         "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+                         "\xF3\x71\xEF\xEB\x4E\xBB\x4D",
+               .ilen   = 503,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B",
-               .rlen   = 43,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59\xF0\x64\xFB\x92",
+               .rlen   = 503,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 43 - 8, 8 },
+               .tap    = { 503 - 8, 8 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -5808,8 +8437,52 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .ilen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xFB\xB0\x5D\xDE\xC0\xFE\xFC\xEB"
                          "\xB1\x80\x10\x43\xDE\x62\x70\xBD"
                          "\xFA\x8A\x93\xEA\x6B\xF7\xC5\xD7"
@@ -5827,11 +8500,55 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
                          "\x9D\x74\x2B\x77\x53\x2D\xE5\xBD"
                          "\x69\xDA\x7A\x01\xF5\x6A\x70\x39"
                          "\x30\xD4\x2C\xF2\x8E\x06\x4B\x39"
-                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6",
-               .rlen   = 144,
+                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6"
+                         "\xB6\x31\x36\x34\x38\x3C\x1D\x69"
+                         "\x9F\x47\x28\x9A\x1D\x96\x70\x54"
+                         "\x8E\x88\xCB\xE0\xF5\x6A\xAE\x0A"
+                         "\x3C\xD5\x93\x1C\x21\xC9\x14\x3A"
+                         "\x23\x9C\x9B\x79\xC7\x75\xC8\x39"
+                         "\xA6\xAC\x65\x9A\x99\x37\xAF\x6D"
+                         "\xBD\xB5\x32\xFD\xD8\x9C\x95\x7B"
+                         "\xC6\x6A\x80\x64\xEA\xEF\x6D\x3F"
+                         "\xA9\xFE\x5B\x16\xA3\xCF\x32\xC8"
+                         "\xEF\x50\x22\x20\x93\x30\xBE\xE2"
+                         "\x38\x05\x65\xAF\xBA\xB6\xE4\x72"
+                         "\xA9\xEE\x05\x42\x88\xBD\x9D\x49"
+                         "\xAD\x93\xCA\x4D\x45\x11\x43\x4D"
+                         "\xB8\xF5\x74\x2B\x48\xE7\x21\xE4"
+                         "\x4E\x3A\x4C\xDE\x65\x7A\x5A\xAD"
+                         "\x86\xE6\x23\xEC\x6B\xA7\x17\xE6"
+                         "\xF6\xA1\xAC\x29\xAE\xF9\x9B\x69"
+                         "\x73\x65\x65\x51\xD6\x0B\x4E\x8C"
+                         "\x17\x15\x9D\xB0\xCF\xB2\x42\x2B"
+                         "\x51\xC3\x03\xE8\xB7\x7D\x2D\x39"
+                         "\xE8\x10\x93\x16\xC8\x68\x4C\x60"
+                         "\x87\x70\x14\xD0\x01\x57\xCB\x42"
+                         "\x13\x59\xB1\x7F\x12\x4F\xBB\xC7"
+                         "\xBD\x2B\xD4\xA9\x12\x26\x4F\xDE"
+                         "\xFD\x72\xEC\xD7\x6F\x97\x14\x90"
+                         "\x0E\x37\x13\xE6\x67\x1D\xE5\xFE"
+                         "\x9E\x18\x3C\x8F\x3A\x3F\x59\x9B"
+                         "\x71\x80\x05\x35\x3F\x40\x0B\x21"
+                         "\x76\xE5\xEF\x42\x6C\xDB\x31\x05"
+                         "\x5F\x05\xCF\x14\xE3\xF0\x61\xA2"
+                         "\x49\x03\x5E\x77\x2E\x20\xBA\xA1"
+                         "\xAF\x46\x51\xC0\x2B\xC4\x64\x1E"
+                         "\x65\xCC\x51\x58\x0A\xDF\xF0\x5F"
+                         "\x75\x9F\x48\xCD\x81\xEC\xC3\xF6"
+                         "\xED\xC9\x4B\x7B\x4E\x26\x23\xE1"
+                         "\xBB\xE9\x83\x0B\xCF\xE4\xDE\x00"
+                         "\x48\xFF\xBF\x6C\xB4\x72\x16\xEF"
+                         "\xC7\x46\xEE\x48\x8C\xB8\xAF\x45"
+                         "\x91\x76\xE7\x6E\x65\x3D\x15\x86"
+                         "\x10\xF8\xDB\x66\x97\x7C\x43\x4D"
+                         "\x79\x12\x4E\xCE\x06\xD1\xD1\x6A"
+                         "\x34\xC1\xC9\xF2\x28\x4A\xCD\x02"
+                         "\x75\x55\x9B\xFF\x36\x73\xAB\x7C"
+                         "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -5946,8 +8663,52 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
                          "\x9D\x74\x2B\x77\x53\x2D\xE5\xBD"
                          "\x69\xDA\x7A\x01\xF5\x6A\x70\x39"
                          "\x30\xD4\x2C\xF2\x8E\x06\x4B\x39"
-                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6",
-               .ilen   = 144,
+                         "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6"
+                         "\xB6\x31\x36\x34\x38\x3C\x1D\x69"
+                         "\x9F\x47\x28\x9A\x1D\x96\x70\x54"
+                         "\x8E\x88\xCB\xE0\xF5\x6A\xAE\x0A"
+                         "\x3C\xD5\x93\x1C\x21\xC9\x14\x3A"
+                         "\x23\x9C\x9B\x79\xC7\x75\xC8\x39"
+                         "\xA6\xAC\x65\x9A\x99\x37\xAF\x6D"
+                         "\xBD\xB5\x32\xFD\xD8\x9C\x95\x7B"
+                         "\xC6\x6A\x80\x64\xEA\xEF\x6D\x3F"
+                         "\xA9\xFE\x5B\x16\xA3\xCF\x32\xC8"
+                         "\xEF\x50\x22\x20\x93\x30\xBE\xE2"
+                         "\x38\x05\x65\xAF\xBA\xB6\xE4\x72"
+                         "\xA9\xEE\x05\x42\x88\xBD\x9D\x49"
+                         "\xAD\x93\xCA\x4D\x45\x11\x43\x4D"
+                         "\xB8\xF5\x74\x2B\x48\xE7\x21\xE4"
+                         "\x4E\x3A\x4C\xDE\x65\x7A\x5A\xAD"
+                         "\x86\xE6\x23\xEC\x6B\xA7\x17\xE6"
+                         "\xF6\xA1\xAC\x29\xAE\xF9\x9B\x69"
+                         "\x73\x65\x65\x51\xD6\x0B\x4E\x8C"
+                         "\x17\x15\x9D\xB0\xCF\xB2\x42\x2B"
+                         "\x51\xC3\x03\xE8\xB7\x7D\x2D\x39"
+                         "\xE8\x10\x93\x16\xC8\x68\x4C\x60"
+                         "\x87\x70\x14\xD0\x01\x57\xCB\x42"
+                         "\x13\x59\xB1\x7F\x12\x4F\xBB\xC7"
+                         "\xBD\x2B\xD4\xA9\x12\x26\x4F\xDE"
+                         "\xFD\x72\xEC\xD7\x6F\x97\x14\x90"
+                         "\x0E\x37\x13\xE6\x67\x1D\xE5\xFE"
+                         "\x9E\x18\x3C\x8F\x3A\x3F\x59\x9B"
+                         "\x71\x80\x05\x35\x3F\x40\x0B\x21"
+                         "\x76\xE5\xEF\x42\x6C\xDB\x31\x05"
+                         "\x5F\x05\xCF\x14\xE3\xF0\x61\xA2"
+                         "\x49\x03\x5E\x77\x2E\x20\xBA\xA1"
+                         "\xAF\x46\x51\xC0\x2B\xC4\x64\x1E"
+                         "\x65\xCC\x51\x58\x0A\xDF\xF0\x5F"
+                         "\x75\x9F\x48\xCD\x81\xEC\xC3\xF6"
+                         "\xED\xC9\x4B\x7B\x4E\x26\x23\xE1"
+                         "\xBB\xE9\x83\x0B\xCF\xE4\xDE\x00"
+                         "\x48\xFF\xBF\x6C\xB4\x72\x16\xEF"
+                         "\xC7\x46\xEE\x48\x8C\xB8\xAF\x45"
+                         "\x91\x76\xE7\x6E\x65\x3D\x15\x86"
+                         "\x10\xF8\xDB\x66\x97\x7C\x43\x4D"
+                         "\x79\x12\x4E\xCE\x06\xD1\xD1\x6A"
+                         "\x34\xC1\xC9\xF2\x28\x4A\xCD\x02"
+                         "\x75\x55\x9B\xFF\x36\x73\xAB\x7C"
+                         "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -5965,11 +8726,55 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .rlen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -6040,8 +8845,52 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .ilen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\x80\xCF\x11\x41\x1A\xB9\x4B\x9C"
                          "\xFF\xB7\x6C\xEA\xF0\xAF\x77\x6E"
                          "\x71\x75\x95\x9D\x4E\x1C\xCF\xAD"
@@ -6059,11 +8908,55 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
                          "\x15\x26\xE1\xDB\xA4\x3D\x74\xD2"
                          "\x41\x1E\x3F\xA9\xC6\x7D\x2A\xAB"
                          "\x27\xDF\x89\x1D\x86\x3E\xF7\x5A"
-                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C",
-               .rlen   = 144,
+                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C"
+                         "\x2D\x12\xA5\x05\x92\xCB\xD7\x4A"
+                         "\x4D\x1E\x88\x21\xE1\x63\xB4\xFC"
+                         "\x4A\xF2\xCD\x35\xB9\xD7\x70\x97"
+                         "\x5A\x5E\x7E\x96\x52\x20\xDC\x25"
+                         "\xE9\x6B\x36\xB4\xE0\x98\x85\x2C"
+                         "\x3C\xD2\xF7\x78\x8A\x73\x26\x9B"
+                         "\xAF\x0B\x11\xE8\x4D\x67\x23\xE9"
+                         "\x77\xDF\x58\xF6\x6F\x9E\xA4\xC5"
+                         "\x10\xA1\x82\x0E\x80\xA0\x8F\x4B"
+                         "\xA1\xC0\x12\x54\x4E\xC9\x20\x92"
+                         "\x11\x00\x10\x4E\xB3\x7C\xCA\x63"
+                         "\xE5\x3F\xD3\x41\x37\xCD\x74\xB7"
+                         "\xA5\x7C\x61\xB8\x0B\x7A\x7F\x4D"
+                         "\xFE\x96\x7D\x1B\xBE\x60\x37\xB7"
+                         "\x81\x92\x66\x67\x15\x1E\x39\x98"
+                         "\x52\xC0\xF4\x69\xC0\x99\x4F\x5A"
+                         "\x2E\x32\xAD\x7C\x8B\xE9\xAD\x05"
+                         "\x55\xF9\x0A\x1F\x97\x5C\xFA\x2B"
+                         "\xF4\x99\x76\x3A\x6E\x4D\xE1\x4C"
+                         "\x14\x4E\x6F\x87\xEE\x1A\x85\xA3"
+                         "\x96\xC6\x66\x49\xDA\x0D\x71\xAC"
+                         "\x04\x05\x46\xD3\x90\x0F\x64\x64"
+                         "\x01\x66\x2C\x62\x5D\x34\xD1\xCB"
+                         "\x3A\x24\xCE\x95\xEF\xAE\x2C\x97"
+                         "\x0E\x0C\x1D\x36\x49\xEB\xE9\x3D"
+                         "\x62\xA6\x19\x28\x9E\x26\xB4\x3F"
+                         "\xD7\x55\x42\x3C\xCD\x72\x0A\xF0"
+                         "\x7D\xE9\x95\x45\x86\xED\xB1\xE0"
+                         "\x8D\xE9\xC5\x86\x13\x24\x28\x7D"
+                         "\x74\xEF\xCA\x50\x12\x7E\x64\x8F"
+                         "\x1B\xF5\x5B\xFE\xE2\xAC\xFA\xE7"
+                         "\xBD\x38\x8C\x11\x20\xEF\xB1\xAA"
+                         "\x7B\xE5\xE5\x78\xAD\x9D\x2D\xA2"
+                         "\x8E\xDD\x48\xB3\xEF\x18\x92\x7E"
+                         "\xE6\x75\x0D\x54\x64\x11\xA3\x3A"
+                         "\xDB\x97\x0F\xD3\xDF\x07\xD3\x7E"
+                         "\x1E\xD1\x87\xE4\x74\xBB\x46\xF4"
+                         "\xBA\x23\x2D\x8D\x29\x07\x12\xCF"
+                         "\x34\xCD\x72\x7F\x01\x30\xE7\xA0"
+                         "\xF8\xDD\xA8\x08\xF0\xBC\xB1\xA2"
+                         "\xCC\xE1\x6B\x5F\xBE\xEA\xF1\xE4"
+                         "\x02\xC4\xAF\xFA\xAD\x31\xF4\xBF"
+                         "\xFC\x66\xAA\x37\xF2\x37\x39\x6B"
+                         "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -6093,8 +8986,52 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
                          "\x15\x26\xE1\xDB\xA4\x3D\x74\xD2"
                          "\x41\x1E\x3F\xA9\xC6\x7D\x2A\xAB"
                          "\x27\xDF\x89\x1D\x86\x3E\xF7\x5A"
-                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C",
-               .ilen   = 144,
+                         "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C"
+                         "\x2D\x12\xA5\x05\x92\xCB\xD7\x4A"
+                         "\x4D\x1E\x88\x21\xE1\x63\xB4\xFC"
+                         "\x4A\xF2\xCD\x35\xB9\xD7\x70\x97"
+                         "\x5A\x5E\x7E\x96\x52\x20\xDC\x25"
+                         "\xE9\x6B\x36\xB4\xE0\x98\x85\x2C"
+                         "\x3C\xD2\xF7\x78\x8A\x73\x26\x9B"
+                         "\xAF\x0B\x11\xE8\x4D\x67\x23\xE9"
+                         "\x77\xDF\x58\xF6\x6F\x9E\xA4\xC5"
+                         "\x10\xA1\x82\x0E\x80\xA0\x8F\x4B"
+                         "\xA1\xC0\x12\x54\x4E\xC9\x20\x92"
+                         "\x11\x00\x10\x4E\xB3\x7C\xCA\x63"
+                         "\xE5\x3F\xD3\x41\x37\xCD\x74\xB7"
+                         "\xA5\x7C\x61\xB8\x0B\x7A\x7F\x4D"
+                         "\xFE\x96\x7D\x1B\xBE\x60\x37\xB7"
+                         "\x81\x92\x66\x67\x15\x1E\x39\x98"
+                         "\x52\xC0\xF4\x69\xC0\x99\x4F\x5A"
+                         "\x2E\x32\xAD\x7C\x8B\xE9\xAD\x05"
+                         "\x55\xF9\x0A\x1F\x97\x5C\xFA\x2B"
+                         "\xF4\x99\x76\x3A\x6E\x4D\xE1\x4C"
+                         "\x14\x4E\x6F\x87\xEE\x1A\x85\xA3"
+                         "\x96\xC6\x66\x49\xDA\x0D\x71\xAC"
+                         "\x04\x05\x46\xD3\x90\x0F\x64\x64"
+                         "\x01\x66\x2C\x62\x5D\x34\xD1\xCB"
+                         "\x3A\x24\xCE\x95\xEF\xAE\x2C\x97"
+                         "\x0E\x0C\x1D\x36\x49\xEB\xE9\x3D"
+                         "\x62\xA6\x19\x28\x9E\x26\xB4\x3F"
+                         "\xD7\x55\x42\x3C\xCD\x72\x0A\xF0"
+                         "\x7D\xE9\x95\x45\x86\xED\xB1\xE0"
+                         "\x8D\xE9\xC5\x86\x13\x24\x28\x7D"
+                         "\x74\xEF\xCA\x50\x12\x7E\x64\x8F"
+                         "\x1B\xF5\x5B\xFE\xE2\xAC\xFA\xE7"
+                         "\xBD\x38\x8C\x11\x20\xEF\xB1\xAA"
+                         "\x7B\xE5\xE5\x78\xAD\x9D\x2D\xA2"
+                         "\x8E\xDD\x48\xB3\xEF\x18\x92\x7E"
+                         "\xE6\x75\x0D\x54\x64\x11\xA3\x3A"
+                         "\xDB\x97\x0F\xD3\xDF\x07\xD3\x7E"
+                         "\x1E\xD1\x87\xE4\x74\xBB\x46\xF4"
+                         "\xBA\x23\x2D\x8D\x29\x07\x12\xCF"
+                         "\x34\xCD\x72\x7F\x01\x30\xE7\xA0"
+                         "\xF8\xDD\xA8\x08\xF0\xBC\xB1\xA2"
+                         "\xCC\xE1\x6B\x5F\xBE\xEA\xF1\xE4"
+                         "\x02\xC4\xAF\xFA\xAD\x31\xF4\xBF"
+                         "\xFC\x66\xAA\x37\xF2\x37\x39\x6B"
+                         "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6112,11 +9049,55 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .rlen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 144 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -6146,8 +9127,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .ilen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\x84\x68\xEC\xF2\x1C\x88\x20\xCA"
                          "\x37\x69\xE3\x3A\x22\x85\x48\x46"
                          "\x70\xAA\x25\xB4\xCD\x8B\x04\x4E"
@@ -6165,8 +9190,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\xBA\x58\x2A\x1C\xDF\xC2\x3A\xA5"
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
-                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9",
-               .rlen   = 144,
+                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13",
+               .rlen   = 496,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6193,8 +9262,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
                          "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
-                         "\xF1\x65\xFC",
-               .ilen   = 147,
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .ilen   = 499,
                .result = "\x84\x68\xEC\xF2\x1C\x88\x20\xCA"
                          "\x37\x69\xE3\x3A\x22\x85\x48\x46"
                          "\x70\xAA\x25\xB4\xCD\x8B\x04\x4E"
@@ -6213,11 +9326,55 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
                          "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
-                         "\xE6\xD0\x97",
-               .rlen   = 147,
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13"
+                         "\x38\xE2\xE5",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 147 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6381,8 +9538,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\xBA\x58\x2A\x1C\xDF\xC2\x3A\xA5"
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
-                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9",
-               .ilen   = 144,
+                         "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6400,8 +9601,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-               .rlen   = 144,
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6428,8 +9673,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
                          "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
                          "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
-                         "\xE6\xD0\x97",
-               .ilen   = 147,
+                         "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+                         "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+                         "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+                         "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+                         "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+                         "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+                         "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+                         "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+                         "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+                         "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+                         "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+                         "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+                         "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+                         "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+                         "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+                         "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+                         "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+                         "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+                         "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+                         "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+                         "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+                         "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+                         "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+                         "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+                         "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+                         "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+                         "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+                         "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+                         "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+                         "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+                         "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+                         "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+                         "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+                         "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+                         "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+                         "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+                         "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+                         "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+                         "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+                         "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+                         "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+                         "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+                         "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+                         "\x40\x53\x77\x8C\x15\xF8\x8D\x13"
+                         "\x38\xE2\xE5",
+               .ilen   = 499,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6448,11 +9737,55 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
                          "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
                          "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
                          "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
-                         "\xF1\x65\xFC",
-               .rlen   = 147,
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 147 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -9326,10 +12659,10 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 /*
  * AES test vectors.
  */
-#define AES_ENC_TEST_VECTORS 3
-#define AES_DEC_TEST_VECTORS 3
-#define AES_CBC_ENC_TEST_VECTORS 4
-#define AES_CBC_DEC_TEST_VECTORS 4
+#define AES_ENC_TEST_VECTORS 4
+#define AES_DEC_TEST_VECTORS 4
+#define AES_CBC_ENC_TEST_VECTORS 5
+#define AES_CBC_DEC_TEST_VECTORS 5
 #define HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS 7
 #define HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS 7
 #define HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS 7
@@ -9337,8 +12670,8 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 #define AES_LRW_DEC_TEST_VECTORS 8
 #define AES_XTS_ENC_TEST_VECTORS 5
 #define AES_XTS_DEC_TEST_VECTORS 5
-#define AES_CTR_ENC_TEST_VECTORS 3
-#define AES_CTR_DEC_TEST_VECTORS 3
+#define AES_CTR_ENC_TEST_VECTORS 5
+#define AES_CTR_DEC_TEST_VECTORS 5
 #define AES_OFB_ENC_TEST_VECTORS 1
 #define AES_OFB_DEC_TEST_VECTORS 1
 #define AES_CTR_3686_ENC_TEST_VECTORS 7
@@ -9386,6 +12719,141 @@ static struct cipher_testvec aes_enc_tv_template[] = {
                .result = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
                          "\xea\xfc\x49\x90\x4b\x49\x60\x89",
                .rlen   = 16,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xA6\xC9\x83\xA6\xC9\xEC\x0F\x32"
+                         "\x55\x0F\x32\x55\x78\x9B\xBE\x78"
+                         "\x9B\xBE\xE1\x04\x27\xE1\x04\x27"
+                         "\x4A\x6D\x90\x4A\x6D\x90\xB3\xD6",
+               .klen   = 32,
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .ilen   = 496,
+               .result = "\x71\x73\xF7\xDB\x24\x93\x21\x6D"
+                         "\x61\x1E\xBB\x63\x42\x79\xDB\x64"
+                         "\x6F\x82\xC0\xCA\xA3\x9B\xFA\x0B"
+                         "\xD9\x08\xC7\x4A\x90\xAE\x8F\x5F"
+                         "\x5E\x06\xF0\x5F\x31\x51\x18\x37"
+                         "\x45\xD7\xCA\x3A\xFD\x6C\x3F\xE1"
+                         "\xDD\x8D\x22\x65\x2B\x00\x50\xCE"
+                         "\xBA\x28\x67\xD7\xCE\x0E\x0D\xEA"
+                         "\x78\x69\x7F\xAE\x8F\x8B\x69\x37"
+                         "\x75\xE0\xDC\x96\xE0\xB7\xF4\x09"
+                         "\xCB\x6D\xA2\xFB\xDA\xAF\x09\xF8"
+                         "\x81\x82\x27\xFA\x45\x9C\x29\xA4"
+                         "\x22\x8B\x78\x69\x5B\x46\xF9\x39"
+                         "\x1B\xCC\xF9\x1D\x09\xEB\xBC\x5C"
+                         "\x41\x72\x51\x97\x1D\x07\x49\xA0"
+                         "\x1B\x8E\x65\x4B\xB2\x6A\x12\x03"
+                         "\x6A\x60\x95\xAC\xBD\xAC\x1A\x64"
+                         "\xDE\x5A\xA5\xF0\x83\x2F\xCB\xCA"
+                         "\x22\x74\xA6\x6C\x9B\x73\xCE\x3F"
+                         "\xE1\x8B\x22\x17\x59\x0C\x47\x89"
+                         "\x33\xA1\xD6\x47\x03\x19\x4F\xA8"
+                         "\x67\x69\xF0\x5B\xF0\x20\xAD\x06"
+                         "\x27\x81\x92\xD8\xC5\xBA\x98\x12"
+                         "\xBE\x24\xB5\x2F\x75\x02\xC2\xAD"
+                         "\x12\x2F\x07\x32\xEE\x39\xAF\x64"
+                         "\x05\x8F\xB3\xD4\xEB\x1B\x46\x6E"
+                         "\xD9\x21\xF9\xC4\xB7\xC9\x45\x68"
+                         "\xB4\xA1\x74\x9F\x82\x47\xEB\xCC"
+                         "\xBD\x0A\x14\x95\x0F\x8B\xA8\x2F"
+                         "\x4B\x1B\xA7\xBF\x82\xA6\x43\x0C"
+                         "\xB9\x39\x4A\xA8\x10\x6F\x50\x7B"
+                         "\x25\xFB\x26\x81\xE0\x2F\xF0\x96"
+                         "\x8D\x8B\xAC\x92\x0F\xF6\xED\x64"
+                         "\x63\x29\x4C\x8E\x18\x13\xC5\xBF"
+                         "\xFC\xA0\xD9\xBF\x7C\x3A\x0E\x29"
+                         "\x6F\xD1\x6C\x6F\xA5\xDA\xBF\xB1"
+                         "\x30\xEA\x44\x2D\xC3\x8F\x16\xE1"
+                         "\x66\xFA\xA3\x21\x3E\xFC\x13\xCA"
+                         "\xF0\xF6\xF0\x59\xBD\x8F\x38\x50"
+                         "\x31\xCB\x69\x3F\x96\x15\xD6\xF5"
+                         "\xAE\xFF\xF6\xAA\x41\x85\x4C\x10"
+                         "\x58\xE3\xF9\x44\xE6\x28\xDA\x9A"
+                         "\xDC\x6A\x80\x34\x73\x97\x1B\xC5"
+                         "\xCA\x26\x16\x77\x0E\x60\xAB\x89"
+                         "\x0F\x04\x27\xBD\xCE\x3E\x71\xB4"
+                         "\xA0\xD7\x22\x7E\xDB\xEB\x24\x70"
+                         "\x42\x71\x51\x78\x70\xB3\xE0\x3D"
+                         "\x84\x8E\x8D\x7B\xD0\x6D\xEA\x92"
+                         "\x11\x08\x42\x4F\xE5\xAD\x26\x92"
+                         "\xD2\x00\xAE\xA8\xE3\x4B\x37\x47"
+                         "\x22\xC1\x95\xC1\x63\x7F\xCB\x03"
+                         "\xF3\xE3\xD7\x9D\x60\xC7\xBC\xEA"
+                         "\x35\xA2\xFD\x45\x52\x39\x13\x6F"
+                         "\xC1\x53\xF3\x53\xDF\x33\x84\xD7"
+                         "\xD2\xC8\x37\xB0\x75\xE3\x41\x46"
+                         "\xB3\xC7\x83\x2E\x8A\xBB\xA4\xE5"
+                         "\x7F\x3C\xFD\x8B\xEB\xEA\x63\xBD"
+                         "\xB7\x46\xE7\xBF\x09\x9C\x0D\x0F"
+                         "\x40\x86\x7F\x51\xE1\x11\x9C\xCB"
+                         "\x88\xE6\x68\x47\xE3\x2B\xC5\xFF"
+                         "\x09\x79\xA0\x43\x5C\x0D\x08\x58"
+                         "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -9423,6 +12891,141 @@ static struct cipher_testvec aes_dec_tv_template[] = {
                .result = "\x00\x11\x22\x33\x44\x55\x66\x77"
                          "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
                .rlen   = 16,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xA6\xC9\x83\xA6\xC9\xEC\x0F\x32"
+                         "\x55\x0F\x32\x55\x78\x9B\xBE\x78"
+                         "\x9B\xBE\xE1\x04\x27\xE1\x04\x27"
+                         "\x4A\x6D\x90\x4A\x6D\x90\xB3\xD6",
+               .klen   = 32,
+               .input  = "\x71\x73\xF7\xDB\x24\x93\x21\x6D"
+                         "\x61\x1E\xBB\x63\x42\x79\xDB\x64"
+                         "\x6F\x82\xC0\xCA\xA3\x9B\xFA\x0B"
+                         "\xD9\x08\xC7\x4A\x90\xAE\x8F\x5F"
+                         "\x5E\x06\xF0\x5F\x31\x51\x18\x37"
+                         "\x45\xD7\xCA\x3A\xFD\x6C\x3F\xE1"
+                         "\xDD\x8D\x22\x65\x2B\x00\x50\xCE"
+                         "\xBA\x28\x67\xD7\xCE\x0E\x0D\xEA"
+                         "\x78\x69\x7F\xAE\x8F\x8B\x69\x37"
+                         "\x75\xE0\xDC\x96\xE0\xB7\xF4\x09"
+                         "\xCB\x6D\xA2\xFB\xDA\xAF\x09\xF8"
+                         "\x81\x82\x27\xFA\x45\x9C\x29\xA4"
+                         "\x22\x8B\x78\x69\x5B\x46\xF9\x39"
+                         "\x1B\xCC\xF9\x1D\x09\xEB\xBC\x5C"
+                         "\x41\x72\x51\x97\x1D\x07\x49\xA0"
+                         "\x1B\x8E\x65\x4B\xB2\x6A\x12\x03"
+                         "\x6A\x60\x95\xAC\xBD\xAC\x1A\x64"
+                         "\xDE\x5A\xA5\xF0\x83\x2F\xCB\xCA"
+                         "\x22\x74\xA6\x6C\x9B\x73\xCE\x3F"
+                         "\xE1\x8B\x22\x17\x59\x0C\x47\x89"
+                         "\x33\xA1\xD6\x47\x03\x19\x4F\xA8"
+                         "\x67\x69\xF0\x5B\xF0\x20\xAD\x06"
+                         "\x27\x81\x92\xD8\xC5\xBA\x98\x12"
+                         "\xBE\x24\xB5\x2F\x75\x02\xC2\xAD"
+                         "\x12\x2F\x07\x32\xEE\x39\xAF\x64"
+                         "\x05\x8F\xB3\xD4\xEB\x1B\x46\x6E"
+                         "\xD9\x21\xF9\xC4\xB7\xC9\x45\x68"
+                         "\xB4\xA1\x74\x9F\x82\x47\xEB\xCC"
+                         "\xBD\x0A\x14\x95\x0F\x8B\xA8\x2F"
+                         "\x4B\x1B\xA7\xBF\x82\xA6\x43\x0C"
+                         "\xB9\x39\x4A\xA8\x10\x6F\x50\x7B"
+                         "\x25\xFB\x26\x81\xE0\x2F\xF0\x96"
+                         "\x8D\x8B\xAC\x92\x0F\xF6\xED\x64"
+                         "\x63\x29\x4C\x8E\x18\x13\xC5\xBF"
+                         "\xFC\xA0\xD9\xBF\x7C\x3A\x0E\x29"
+                         "\x6F\xD1\x6C\x6F\xA5\xDA\xBF\xB1"
+                         "\x30\xEA\x44\x2D\xC3\x8F\x16\xE1"
+                         "\x66\xFA\xA3\x21\x3E\xFC\x13\xCA"
+                         "\xF0\xF6\xF0\x59\xBD\x8F\x38\x50"
+                         "\x31\xCB\x69\x3F\x96\x15\xD6\xF5"
+                         "\xAE\xFF\xF6\xAA\x41\x85\x4C\x10"
+                         "\x58\xE3\xF9\x44\xE6\x28\xDA\x9A"
+                         "\xDC\x6A\x80\x34\x73\x97\x1B\xC5"
+                         "\xCA\x26\x16\x77\x0E\x60\xAB\x89"
+                         "\x0F\x04\x27\xBD\xCE\x3E\x71\xB4"
+                         "\xA0\xD7\x22\x7E\xDB\xEB\x24\x70"
+                         "\x42\x71\x51\x78\x70\xB3\xE0\x3D"
+                         "\x84\x8E\x8D\x7B\xD0\x6D\xEA\x92"
+                         "\x11\x08\x42\x4F\xE5\xAD\x26\x92"
+                         "\xD2\x00\xAE\xA8\xE3\x4B\x37\x47"
+                         "\x22\xC1\x95\xC1\x63\x7F\xCB\x03"
+                         "\xF3\xE3\xD7\x9D\x60\xC7\xBC\xEA"
+                         "\x35\xA2\xFD\x45\x52\x39\x13\x6F"
+                         "\xC1\x53\xF3\x53\xDF\x33\x84\xD7"
+                         "\xD2\xC8\x37\xB0\x75\xE3\x41\x46"
+                         "\xB3\xC7\x83\x2E\x8A\xBB\xA4\xE5"
+                         "\x7F\x3C\xFD\x8B\xEB\xEA\x63\xBD"
+                         "\xB7\x46\xE7\xBF\x09\x9C\x0D\x0F"
+                         "\x40\x86\x7F\x51\xE1\x11\x9C\xCB"
+                         "\x88\xE6\x68\x47\xE3\x2B\xC5\xFF"
+                         "\x09\x79\xA0\x43\x5C\x0D\x08\x58"
+                         "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
+               .ilen   = 496,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -9505,6 +13108,143 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
                          "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
                          "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
                .rlen   = 64,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .ilen   = 496,
+               .result = "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F"
+                         "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF"
+                         "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F"
+                         "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8"
+                         "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0"
+                         "\x11\x15\xFF\x6D\x1E\x82\x04\xA6"
+                         "\xB1\x74\xD1\x08\x13\xFD\x90\x7C"
+                         "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F"
+                         "\x0A\x70\xF1\x88\x07\xCF\x21\x26"
+                         "\x40\x40\x8A\xF5\x53\xF7\x24\x4F"
+                         "\x83\x38\x43\x5F\x08\x99\xEB\xE3"
+                         "\xDC\x02\x64\x67\x50\x6E\x15\xC3"
+                         "\x01\x1A\xA0\x81\x13\x65\xA6\x73"
+                         "\x71\xA6\x3B\x91\x83\x77\xBE\xFA"
+                         "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3"
+                         "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F"
+                         "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F"
+                         "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43"
+                         "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40"
+                         "\x03\xA8\x6C\x50\x42\x9F\x77\x59"
+                         "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99"
+                         "\x16\x24\x02\x07\x48\xAE\xF2\x31"
+                         "\x34\x0E\xC3\x85\xFE\x1C\x95\x99"
+                         "\x87\x58\x98\x8B\xE7\xC6\xC5\x70"
+                         "\x73\x81\x07\x7C\x56\x2F\xD8\x1B"
+                         "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F"
+                         "\xD8\xBB\xC0\x0D\xAC\x2C\x2F\x98"
+                         "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04"
+                         "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5"
+                         "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD"
+                         "\xF1\xE3\x3D\x98\x50\x02\x77\x9E"
+                         "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66"
+                         "\x20\x02\x23\xDA\xDF\xA0\x89\xF6"
+                         "\xD8\xF3\x45\x24\x53\x6F\x16\x77"
+                         "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78"
+                         "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3"
+                         "\x57\xBC\x0B\x9F\x43\x51\x28\x4F"
+                         "\x07\x50\x6C\x68\x12\x07\xCF\xFA"
+                         "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C"
+                         "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD"
+                         "\x22\x39\x7B\x16\x03\x01\x69\xAF"
+                         "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5"
+                         "\x03\xB4\x2F\x51\x8A\x56\x17\x2B"
+                         "\x88\x42\x6D\x40\x68\x8F\xD0\x11"
+                         "\x19\xF9\x1F\x43\x79\x95\x31\xFA"
+                         "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC"
+                         "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC"
+                         "\x8D\x53\x6E\x72\x68\xA3\xC7\x63"
+                         "\x43\x2B\x78\xE0\x04\x29\x8F\x72"
+                         "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD"
+                         "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D"
+                         "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44"
+                         "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61"
+                         "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC"
+                         "\x58\x08\x15\xAB\x12\xAB\x17\x4A"
+                         "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB"
+                         "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F"
+                         "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61"
+                         "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD"
+                         "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A"
+                         "\xE0\x1F\x91\xF8\x82\x96\x2D\x65"
+                         "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -9587,6 +13327,143 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
                          "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
                          "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
                .rlen   = 64,
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F"
+                         "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF"
+                         "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F"
+                         "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8"
+                         "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0"
+                         "\x11\x15\xFF\x6D\x1E\x82\x04\xA6"
+                         "\xB1\x74\xD1\x08\x13\xFD\x90\x7C"
+                         "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F"
+                         "\x0A\x70\xF1\x88\x07\xCF\x21\x26"
+                         "\x40\x40\x8A\xF5\x53\xF7\x24\x4F"
+                         "\x83\x38\x43\x5F\x08\x99\xEB\xE3"
+                         "\xDC\x02\x64\x67\x50\x6E\x15\xC3"
+                         "\x01\x1A\xA0\x81\x13\x65\xA6\x73"
+                         "\x71\xA6\x3B\x91\x83\x77\xBE\xFA"
+                         "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3"
+                         "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F"
+                         "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F"
+                         "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43"
+                         "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40"
+                         "\x03\xA8\x6C\x50\x42\x9F\x77\x59"
+                         "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99"
+                         "\x16\x24\x02\x07\x48\xAE\xF2\x31"
+                         "\x34\x0E\xC3\x85\xFE\x1C\x95\x99"
+                         "\x87\x58\x98\x8B\xE7\xC6\xC5\x70"
+                         "\x73\x81\x07\x7C\x56\x2F\xD8\x1B"
+                         "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F"
+                         "\xD8\xBB\xC0\x0D\xAC\x2C\x2F\x98"
+                         "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04"
+                         "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5"
+                         "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD"
+                         "\xF1\xE3\x3D\x98\x50\x02\x77\x9E"
+                         "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66"
+                         "\x20\x02\x23\xDA\xDF\xA0\x89\xF6"
+                         "\xD8\xF3\x45\x24\x53\x6F\x16\x77"
+                         "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78"
+                         "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3"
+                         "\x57\xBC\x0B\x9F\x43\x51\x28\x4F"
+                         "\x07\x50\x6C\x68\x12\x07\xCF\xFA"
+                         "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C"
+                         "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD"
+                         "\x22\x39\x7B\x16\x03\x01\x69\xAF"
+                         "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5"
+                         "\x03\xB4\x2F\x51\x8A\x56\x17\x2B"
+                         "\x88\x42\x6D\x40\x68\x8F\xD0\x11"
+                         "\x19\xF9\x1F\x43\x79\x95\x31\xFA"
+                         "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC"
+                         "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC"
+                         "\x8D\x53\x6E\x72\x68\xA3\xC7\x63"
+                         "\x43\x2B\x78\xE0\x04\x29\x8F\x72"
+                         "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD"
+                         "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D"
+                         "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44"
+                         "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61"
+                         "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC"
+                         "\x58\x08\x15\xAB\x12\xAB\x17\x4A"
+                         "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB"
+                         "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F"
+                         "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61"
+                         "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD"
+                         "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A"
+                         "\xE0\x1F\x91\xF8\x82\x96\x2D\x65"
+                         "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
+               .ilen   = 496,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -11134,8 +15011,6 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
                .klen   = 64,
                .iv     = "\xff\x00\x00\x00\x00\x00\x00\x00"
                          "\x00\x00\x00\x00\x00\x00\x00\x00",
-                         "\x00\x00\x00\x00\x00\x00\x00\x00",
-                         "\x00\x00\x00\x00\x00\x00\x00\x00",
                .input  = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
                          "\x10\x11\x12\x13\x14\x15\x16\x17"
@@ -11478,8 +15353,6 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
                .klen   = 64,
                .iv     = "\xff\x00\x00\x00\x00\x00\x00\x00"
                          "\x00\x00\x00\x00\x00\x00\x00\x00",
-                         "\x00\x00\x00\x00\x00\x00\x00\x00",
-                         "\x00\x00\x00\x00\x00\x00\x00\x00",
                .input  = "\x1c\x3b\x3a\x10\x2f\x77\x03\x86"
                          "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b"
                          "\xea\x00\x80\x3f\x5e\x48\x23\x57"
@@ -11693,7 +15566,283 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
                          "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
                          "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
                .rlen   = 64,
-       }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .ilen   = 496,
+               .result = "\x04\xF3\xD3\x88\x17\xEF\xDC\xEF"
+                         "\x8B\x04\xF8\x3A\x66\x8D\x1A\x53"
+                         "\x57\x1F\x4B\x23\xE4\xA0\xAF\xF9"
+                         "\x69\x95\x35\x98\x8D\x4D\x8C\xC1"
+                         "\xF0\xB2\x7F\x80\xBB\x54\x28\xA2"
+                         "\x7A\x1B\x9F\x77\xEC\x0E\x6E\xDE"
+                         "\xF0\xEC\xB8\xE4\x20\x62\xEE\xDB"
+                         "\x5D\xF5\xDD\xE3\x54\xFC\xDD\xEB"
+                         "\x6A\xEE\x65\xA1\x21\xD6\xD7\x81"
+                         "\x47\x61\x12\x4D\xC2\x8C\xFA\x78"
+                         "\x1F\x28\x02\x01\xC3\xFC\x1F\xEC"
+                         "\x0F\x10\x4F\xB3\x12\x45\xC6\x3B"
+                         "\x7E\x08\xF9\x5A\xD0\x5D\x73\x2D"
+                         "\x58\xA4\xE5\xCB\x1C\xB4\xCE\x74"
+                         "\x32\x41\x1F\x31\x9C\x08\xA2\x5D"
+                         "\x67\xEB\x72\x1D\xF8\xE7\x70\x54"
+                         "\x34\x4B\x31\x69\x84\x66\x96\x44"
+                         "\x56\xCC\x1E\xD9\xE6\x13\x6A\xB9"
+                         "\x2D\x0A\x05\x45\x2D\x90\xCC\xDF"
+                         "\x16\x5C\x5F\x79\x34\x52\x54\xFE"
+                         "\xFE\xCD\xAD\x04\x2E\xAD\x86\x06"
+                         "\x1F\x37\xE8\x28\xBC\xD3\x8F\x5B"
+                         "\x92\x66\x87\x3B\x8A\x0A\x1A\xCC"
+                         "\x6E\xAB\x9F\x0B\xFA\x5C\xE6\xFD"
+                         "\x3C\x98\x08\x12\xEC\xAA\x9E\x11"
+                         "\xCA\xB2\x1F\xCE\x5E\x5B\xB2\x72"
+                         "\x9C\xCC\x5D\xC5\xE0\x32\xC0\x56"
+                         "\xD5\x45\x16\xD2\xAF\x13\x66\xF7"
+                         "\x8C\x67\xAC\x79\xB2\xAF\x56\x27"
+                         "\x3F\xCC\xFE\xCB\x1E\xC0\x75\xF1"
+                         "\xA7\xC9\xC3\x1D\x8E\xDD\xF9\xD4"
+                         "\x42\xC8\x21\x08\x16\xF7\x01\xD7"
+                         "\xAC\x8E\x3F\x1D\x56\xC1\x06\xE4"
+                         "\x9C\x62\xD6\xA5\x6A\x50\x44\xB3"
+                         "\x35\x1C\x82\xB9\x10\xF9\x42\xA1"
+                         "\xFC\x74\x9B\x44\x4F\x25\x02\xE3"
+                         "\x08\xF5\xD4\x32\x39\x08\x11\xE8"
+                         "\xD2\x6B\x50\x53\xD4\x08\xD1\x6B"
+                         "\x3A\x4A\x68\x7B\x7C\xCD\x46\x5E"
+                         "\x0D\x07\x19\xDB\x67\xD7\x98\x91"
+                         "\xD7\x17\x10\x9B\x7B\x8A\x9B\x33"
+                         "\xAE\xF3\x00\xA6\xD4\x15\xD9\xEA"
+                         "\x85\x99\x22\xE8\x91\x38\x70\x83"
+                         "\x93\x01\x24\x6C\xFA\x9A\xB9\x07"
+                         "\xEA\x8D\x3B\xD9\x2A\x43\x59\x16"
+                         "\x2F\x69\xEE\x84\x36\x44\x76\x98"
+                         "\xF3\x04\x2A\x7C\x74\x3D\x29\x2B"
+                         "\x0D\xAD\x8F\x44\x82\x9E\x57\x8D"
+                         "\xAC\xED\x18\x1F\x50\xA4\xF5\x98"
+                         "\x1F\xBD\x92\x91\x1B\x2D\xA6\xD6"
+                         "\xD2\xE3\x02\xAA\x92\x3B\xC6\xB3"
+                         "\x1B\x39\x72\xD5\x26\xCA\x04\xE0"
+                         "\xFC\x58\x78\xBB\xB1\x3F\xA1\x9C"
+                         "\x42\x24\x3E\x2E\x22\xBB\x4B\xBA"
+                         "\xF4\x52\x0A\xE6\xAE\x47\xB4\x7D"
+                         "\x1D\xA8\xBE\x81\x1A\x75\xDA\xAC"
+                         "\xA6\x25\x1E\xEF\x3A\xC0\x6C\x63"
+                         "\xEF\xDC\xC9\x79\x10\x26\xE8\x61"
+                         "\x29\xFC\xA4\x05\xDF\x7D\x5C\x63"
+                         "\x10\x09\x9B\x46\x9B\xF2\x2C\x2B"
+                         "\xFA\x3A\x05\x4C\xFA\xD1\xFF\xFE"
+                         "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12"
+                         "\x7B\xE4\x4D",
+               .ilen   = 499,
+               .result = "\xDA\x4E\x3F\xBC\xE8\xB6\x3A\xA2"
+                         "\xD5\x4D\x84\x4A\xA9\x0C\xE1\xA5"
+                         "\xB8\x73\xBC\xF9\xBB\x59\x2F\x44"
+                         "\x8B\xAB\x82\x6C\xB4\x32\x9A\xDE"
+                         "\x5A\x0B\xDB\x7A\x6B\xF2\x38\x9F"
+                         "\x06\xF7\xF7\xFF\xFF\xC0\x8A\x2E"
+                         "\x76\xEA\x06\x32\x23\xF3\x59\x2E"
+                         "\x75\xDE\x71\x86\x3C\x98\x23\x44"
+                         "\x5B\xF2\xFA\x6A\x00\xBB\xC1\xAD"
+                         "\x58\xBD\x3E\x6F\x2E\xB4\x19\x04"
+                         "\x70\x8B\x92\x55\x23\xE9\x6A\x3A"
+                         "\x78\x7A\x1B\x10\x85\x52\x9C\x12"
+                         "\xE4\x55\x81\x21\xCE\x53\xD0\x3B"
+                         "\x63\x77\x2C\x74\xD1\xF5\x60\xF3"
+                         "\xA1\xDE\x44\x3C\x8F\x4D\x2F\xDD"
+                         "\x8A\xFE\x3C\x42\x8E\xD3\xF2\x8E"
+                         "\xA8\x28\x69\x65\x31\xE1\x45\x83"
+                         "\xE4\x49\xC4\x9C\xA7\x28\xAA\x21"
+                         "\xCD\x5D\x0F\x15\xB7\x93\x07\x26"
+                         "\xB0\x65\x6D\x91\x90\x23\x7A\xC6"
+                         "\xDB\x68\xB0\xA1\x8E\xA4\x76\x4E"
+                         "\xC6\x91\x83\x20\x92\x4D\x63\x7A"
+                         "\x45\x18\x18\x74\x19\xAD\x71\x01"
+                         "\x6B\x23\xAD\x9D\x4E\xE4\x6E\x46"
+                         "\xC9\x73\x7A\xF9\x02\x95\xF4\x07"
+                         "\x0E\x7A\xA6\xC5\xAE\xFA\x15\x2C"
+                         "\x51\x71\xF1\xDC\x22\xB6\xAC\xD8"
+                         "\x19\x24\x44\xBC\x0C\xFB\x3C\x2D"
+                         "\xB1\x50\x47\x15\x0E\xDB\xB6\xD7"
+                         "\xE8\x61\xE5\x95\x52\x1E\x3E\x49"
+                         "\x70\xE9\x66\x04\x4C\xE1\xAF\xBD"
+                         "\xDD\x15\x3B\x20\x59\x24\xFF\xB0"
+                         "\x39\xAA\xE7\xBF\x23\xA3\x6E\xD5"
+                         "\x15\xF0\x61\x4F\xAE\x89\x10\x58"
+                         "\x5A\x33\x95\x52\x2A\xB5\x77\x9C"
+                         "\xA5\x43\x80\x40\x27\x2D\xAE\xD9"
+                         "\x3F\xE0\x80\x94\x78\x79\xCB\x7E"
+                         "\xAD\x12\x44\x4C\xEC\x27\xB0\xEE"
+                         "\x0B\x05\x2A\x82\x99\x58\xBB\x7A"
+                         "\x8D\x6D\x9D\x8E\xE2\x8E\xE7\x93"
+                         "\x2F\xB3\x09\x8D\x06\xD5\xEE\x70"
+                         "\x16\xAE\x35\xC5\x52\x0F\x46\x1F"
+                         "\x71\xF9\x5E\xF2\x67\xDC\x98\x2F"
+                         "\xA3\x23\xAA\xD5\xD0\x49\xF4\xA6"
+                         "\xF6\xB8\x32\xCD\xD6\x85\x73\x60"
+                         "\x59\x20\xE7\x55\x0E\x91\xE2\x0C"
+                         "\x3F\x1C\xEB\x3D\xDF\x52\x64\xF2"
+                         "\x7D\x8B\x5D\x63\x16\xB9\xB2\x5D"
+                         "\x5E\xAB\xB2\x97\xAB\x78\x44\xE7"
+                         "\xC6\x72\x20\xC5\x90\x9B\xDC\x5D"
+                         "\xB0\xEF\x44\xEF\x87\x31\x8D\xF4"
+                         "\xFB\x81\x5D\xF7\x96\x96\xD4\x50"
+                         "\x89\xA7\xF6\xB9\x67\x76\x40\x9E"
+                         "\x9D\x40\xD5\x2C\x30\xB8\x01\x8F"
+                         "\xE4\x7B\x71\x48\xA9\xA0\xA0\x1D"
+                         "\x87\x52\xA4\x91\xA9\xD7\xA9\x51"
+                         "\xD9\x59\xF7\xCC\x63\x22\xC1\x8D"
+                         "\x84\x7B\xD8\x22\x32\x5C\x6F\x1D"
+                         "\x6E\x9F\xFA\xDD\x49\x40\xDC\x37"
+                         "\x14\x8C\xE1\x80\x1B\xDD\x36\x2A"
+                         "\xD0\xE9\x54\x99\x5D\xBA\x3B\x11"
+                         "\xD8\xFE\xC9\x5B\x5C\x25\xE5\x76"
+                         "\xFB\xF2\x3F",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
+       },
 };
 
 static struct cipher_testvec aes_ctr_dec_tv_template[] = {
@@ -11772,7 +15921,283 @@ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
                          "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
                          "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
                .rlen   = 64,
-       }
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+               .input  = "\x04\xF3\xD3\x88\x17\xEF\xDC\xEF"
+                         "\x8B\x04\xF8\x3A\x66\x8D\x1A\x53"
+                         "\x57\x1F\x4B\x23\xE4\xA0\xAF\xF9"
+                         "\x69\x95\x35\x98\x8D\x4D\x8C\xC1"
+                         "\xF0\xB2\x7F\x80\xBB\x54\x28\xA2"
+                         "\x7A\x1B\x9F\x77\xEC\x0E\x6E\xDE"
+                         "\xF0\xEC\xB8\xE4\x20\x62\xEE\xDB"
+                         "\x5D\xF5\xDD\xE3\x54\xFC\xDD\xEB"
+                         "\x6A\xEE\x65\xA1\x21\xD6\xD7\x81"
+                         "\x47\x61\x12\x4D\xC2\x8C\xFA\x78"
+                         "\x1F\x28\x02\x01\xC3\xFC\x1F\xEC"
+                         "\x0F\x10\x4F\xB3\x12\x45\xC6\x3B"
+                         "\x7E\x08\xF9\x5A\xD0\x5D\x73\x2D"
+                         "\x58\xA4\xE5\xCB\x1C\xB4\xCE\x74"
+                         "\x32\x41\x1F\x31\x9C\x08\xA2\x5D"
+                         "\x67\xEB\x72\x1D\xF8\xE7\x70\x54"
+                         "\x34\x4B\x31\x69\x84\x66\x96\x44"
+                         "\x56\xCC\x1E\xD9\xE6\x13\x6A\xB9"
+                         "\x2D\x0A\x05\x45\x2D\x90\xCC\xDF"
+                         "\x16\x5C\x5F\x79\x34\x52\x54\xFE"
+                         "\xFE\xCD\xAD\x04\x2E\xAD\x86\x06"
+                         "\x1F\x37\xE8\x28\xBC\xD3\x8F\x5B"
+                         "\x92\x66\x87\x3B\x8A\x0A\x1A\xCC"
+                         "\x6E\xAB\x9F\x0B\xFA\x5C\xE6\xFD"
+                         "\x3C\x98\x08\x12\xEC\xAA\x9E\x11"
+                         "\xCA\xB2\x1F\xCE\x5E\x5B\xB2\x72"
+                         "\x9C\xCC\x5D\xC5\xE0\x32\xC0\x56"
+                         "\xD5\x45\x16\xD2\xAF\x13\x66\xF7"
+                         "\x8C\x67\xAC\x79\xB2\xAF\x56\x27"
+                         "\x3F\xCC\xFE\xCB\x1E\xC0\x75\xF1"
+                         "\xA7\xC9\xC3\x1D\x8E\xDD\xF9\xD4"
+                         "\x42\xC8\x21\x08\x16\xF7\x01\xD7"
+                         "\xAC\x8E\x3F\x1D\x56\xC1\x06\xE4"
+                         "\x9C\x62\xD6\xA5\x6A\x50\x44\xB3"
+                         "\x35\x1C\x82\xB9\x10\xF9\x42\xA1"
+                         "\xFC\x74\x9B\x44\x4F\x25\x02\xE3"
+                         "\x08\xF5\xD4\x32\x39\x08\x11\xE8"
+                         "\xD2\x6B\x50\x53\xD4\x08\xD1\x6B"
+                         "\x3A\x4A\x68\x7B\x7C\xCD\x46\x5E"
+                         "\x0D\x07\x19\xDB\x67\xD7\x98\x91"
+                         "\xD7\x17\x10\x9B\x7B\x8A\x9B\x33"
+                         "\xAE\xF3\x00\xA6\xD4\x15\xD9\xEA"
+                         "\x85\x99\x22\xE8\x91\x38\x70\x83"
+                         "\x93\x01\x24\x6C\xFA\x9A\xB9\x07"
+                         "\xEA\x8D\x3B\xD9\x2A\x43\x59\x16"
+                         "\x2F\x69\xEE\x84\x36\x44\x76\x98"
+                         "\xF3\x04\x2A\x7C\x74\x3D\x29\x2B"
+                         "\x0D\xAD\x8F\x44\x82\x9E\x57\x8D"
+                         "\xAC\xED\x18\x1F\x50\xA4\xF5\x98"
+                         "\x1F\xBD\x92\x91\x1B\x2D\xA6\xD6"
+                         "\xD2\xE3\x02\xAA\x92\x3B\xC6\xB3"
+                         "\x1B\x39\x72\xD5\x26\xCA\x04\xE0"
+                         "\xFC\x58\x78\xBB\xB1\x3F\xA1\x9C"
+                         "\x42\x24\x3E\x2E\x22\xBB\x4B\xBA"
+                         "\xF4\x52\x0A\xE6\xAE\x47\xB4\x7D"
+                         "\x1D\xA8\xBE\x81\x1A\x75\xDA\xAC"
+                         "\xA6\x25\x1E\xEF\x3A\xC0\x6C\x63"
+                         "\xEF\xDC\xC9\x79\x10\x26\xE8\x61"
+                         "\x29\xFC\xA4\x05\xDF\x7D\x5C\x63"
+                         "\x10\x09\x9B\x46\x9B\xF2\x2C\x2B"
+                         "\xFA\x3A\x05\x4C\xFA\xD1\xFF\xFE"
+                         "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
+               .ilen   = 496,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+               .rlen   = 496,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 496 - 16, 16 },
+       }, { /* Generated with Crypto++ */
+               .key    = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+                         "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+                         "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+                         "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+               .klen   = 32,
+               .iv     = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+                         "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+               .input  = "\xDA\x4E\x3F\xBC\xE8\xB6\x3A\xA2"
+                         "\xD5\x4D\x84\x4A\xA9\x0C\xE1\xA5"
+                         "\xB8\x73\xBC\xF9\xBB\x59\x2F\x44"
+                         "\x8B\xAB\x82\x6C\xB4\x32\x9A\xDE"
+                         "\x5A\x0B\xDB\x7A\x6B\xF2\x38\x9F"
+                         "\x06\xF7\xF7\xFF\xFF\xC0\x8A\x2E"
+                         "\x76\xEA\x06\x32\x23\xF3\x59\x2E"
+                         "\x75\xDE\x71\x86\x3C\x98\x23\x44"
+                         "\x5B\xF2\xFA\x6A\x00\xBB\xC1\xAD"
+                         "\x58\xBD\x3E\x6F\x2E\xB4\x19\x04"
+                         "\x70\x8B\x92\x55\x23\xE9\x6A\x3A"
+                         "\x78\x7A\x1B\x10\x85\x52\x9C\x12"
+                         "\xE4\x55\x81\x21\xCE\x53\xD0\x3B"
+                         "\x63\x77\x2C\x74\xD1\xF5\x60\xF3"
+                         "\xA1\xDE\x44\x3C\x8F\x4D\x2F\xDD"
+                         "\x8A\xFE\x3C\x42\x8E\xD3\xF2\x8E"
+                         "\xA8\x28\x69\x65\x31\xE1\x45\x83"
+                         "\xE4\x49\xC4\x9C\xA7\x28\xAA\x21"
+                         "\xCD\x5D\x0F\x15\xB7\x93\x07\x26"
+                         "\xB0\x65\x6D\x91\x90\x23\x7A\xC6"
+                         "\xDB\x68\xB0\xA1\x8E\xA4\x76\x4E"
+                         "\xC6\x91\x83\x20\x92\x4D\x63\x7A"
+                         "\x45\x18\x18\x74\x19\xAD\x71\x01"
+                         "\x6B\x23\xAD\x9D\x4E\xE4\x6E\x46"
+                         "\xC9\x73\x7A\xF9\x02\x95\xF4\x07"
+                         "\x0E\x7A\xA6\xC5\xAE\xFA\x15\x2C"
+                         "\x51\x71\xF1\xDC\x22\xB6\xAC\xD8"
+                         "\x19\x24\x44\xBC\x0C\xFB\x3C\x2D"
+                         "\xB1\x50\x47\x15\x0E\xDB\xB6\xD7"
+                         "\xE8\x61\xE5\x95\x52\x1E\x3E\x49"
+                         "\x70\xE9\x66\x04\x4C\xE1\xAF\xBD"
+                         "\xDD\x15\x3B\x20\x59\x24\xFF\xB0"
+                         "\x39\xAA\xE7\xBF\x23\xA3\x6E\xD5"
+                         "\x15\xF0\x61\x4F\xAE\x89\x10\x58"
+                         "\x5A\x33\x95\x52\x2A\xB5\x77\x9C"
+                         "\xA5\x43\x80\x40\x27\x2D\xAE\xD9"
+                         "\x3F\xE0\x80\x94\x78\x79\xCB\x7E"
+                         "\xAD\x12\x44\x4C\xEC\x27\xB0\xEE"
+                         "\x0B\x05\x2A\x82\x99\x58\xBB\x7A"
+                         "\x8D\x6D\x9D\x8E\xE2\x8E\xE7\x93"
+                         "\x2F\xB3\x09\x8D\x06\xD5\xEE\x70"
+                         "\x16\xAE\x35\xC5\x52\x0F\x46\x1F"
+                         "\x71\xF9\x5E\xF2\x67\xDC\x98\x2F"
+                         "\xA3\x23\xAA\xD5\xD0\x49\xF4\xA6"
+                         "\xF6\xB8\x32\xCD\xD6\x85\x73\x60"
+                         "\x59\x20\xE7\x55\x0E\x91\xE2\x0C"
+                         "\x3F\x1C\xEB\x3D\xDF\x52\x64\xF2"
+                         "\x7D\x8B\x5D\x63\x16\xB9\xB2\x5D"
+                         "\x5E\xAB\xB2\x97\xAB\x78\x44\xE7"
+                         "\xC6\x72\x20\xC5\x90\x9B\xDC\x5D"
+                         "\xB0\xEF\x44\xEF\x87\x31\x8D\xF4"
+                         "\xFB\x81\x5D\xF7\x96\x96\xD4\x50"
+                         "\x89\xA7\xF6\xB9\x67\x76\x40\x9E"
+                         "\x9D\x40\xD5\x2C\x30\xB8\x01\x8F"
+                         "\xE4\x7B\x71\x48\xA9\xA0\xA0\x1D"
+                         "\x87\x52\xA4\x91\xA9\xD7\xA9\x51"
+                         "\xD9\x59\xF7\xCC\x63\x22\xC1\x8D"
+                         "\x84\x7B\xD8\x22\x32\x5C\x6F\x1D"
+                         "\x6E\x9F\xFA\xDD\x49\x40\xDC\x37"
+                         "\x14\x8C\xE1\x80\x1B\xDD\x36\x2A"
+                         "\xD0\xE9\x54\x99\x5D\xBA\x3B\x11"
+                         "\xD8\xFE\xC9\x5B\x5C\x25\xE5\x76"
+                         "\xFB\xF2\x3F",
+               .ilen   = 499,
+               .result = "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+                         "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+                         "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+                         "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+                         "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+                         "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+                         "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+                         "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+                         "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+                         "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+                         "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+                         "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+                         "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+                         "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+                         "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+                         "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+                         "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+                         "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+                         "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+                         "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+                         "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+                         "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+                         "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+                         "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+                         "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+                         "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+                         "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+                         "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+                         "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+                         "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+                         "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+                         "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+                         "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+                         "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+                         "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+                         "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+                         "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+                         "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+                         "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+                         "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+                         "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+                         "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+                         "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+                         "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+                         "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+                         "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+                         "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+                         "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+                         "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+                         "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+                         "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+                         "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+                         "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+                         "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+                         "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+                         "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+                         "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+                         "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+                         "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+                         "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+                         "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+                         "\xED\x56\xBF\x28\xB4\x1D\x86\x12"
+                         "\x7B\xE4\x4D",
+               .rlen   = 499,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 499 - 16, 16 },
+       },
 };
 
 static struct cipher_testvec aes_ctr_rfc3686_enc_tv_template[] = {
@@ -16291,8 +20716,7 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
                .result = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
                          "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
                .rlen   = 16,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
                          "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
                          "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
@@ -16303,18 +20727,130 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .ilen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xED\xCD\xDB\xB8\x68\xCE\xBD\xEA"
                          "\x9D\x9D\xCD\x9F\x4F\xFC\x4D\xB7"
                          "\xA5\xFF\x6F\x43\x0F\xBA\x32\x04"
                          "\xB3\xC2\xB9\x03\xAA\x91\x56\x29"
                          "\x0D\xD0\xFD\xC4\x65\xA5\x69\xB9"
-                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A",
-               .rlen   = 48,
+                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A"
+                         "\x8D\x7D\x1B\x9B\xC7\x68\x72\xF8"
+                         "\x01\x9B\x17\x0A\x29\xE7\x61\x28"
+                         "\x7F\xA7\x50\xCA\x20\x2C\x96\x3B"
+                         "\x6E\x5C\x5D\x3F\xB5\x7F\xF3\x2B"
+                         "\x04\xEF\x9D\xD4\xCE\x41\x28\x8E"
+                         "\x83\x54\xAE\x7C\x82\x46\x10\xC9"
+                         "\xC4\x8A\x1E\x1F\x4C\xA9\xFC\xEC"
+                         "\x3C\x8C\x30\xFC\x59\xD2\x54\xC4"
+                         "\x6F\x50\xC6\xCA\x8C\x14\x5B\x9C"
+                         "\x18\x56\x5B\xF8\x33\x0E\x4A\xDB"
+                         "\xEC\xB5\x6E\x5B\x31\xC4\x0E\x98"
+                         "\x9F\x32\xBA\xA2\x18\xCF\x55\x43"
+                         "\xFE\x80\x8F\x60\xCF\x05\x30\x9B"
+                         "\x70\x50\x1E\x9C\x08\x87\xE6\x20"
+                         "\xD2\xF3\x27\xF8\x2A\x8D\x12\xB2"
+                         "\xBC\x5F\xFE\x52\x52\xF6\x7F\xB6"
+                         "\xB8\x30\x86\x3B\x0F\x94\x1E\x79"
+                         "\x13\x94\x35\xA2\xB1\x35\x5B\x05"
+                         "\x2A\x98\x6B\x96\x4C\xB1\x20\xBE"
+                         "\xB6\x14\xC2\x06\xBF\xFD\x5F\x2A"
+                         "\xF5\x33\xC8\x19\x45\x14\x44\x5D"
+                         "\xFE\x94\x7B\xBB\x63\x13\x57\xC3"
+                         "\x2A\x8F\x6C\x11\x2A\x07\xA7\x6A"
+                         "\xBF\x20\xD3\x99\xC6\x00\x0B\xBF"
+                         "\x83\x46\x25\x3A\xB0\xF6\xC5\xC8"
+                         "\x00\xCA\xE5\x28\x4A\x7C\x95\x9C"
+                         "\x7B\x43\xAB\xF9\xE4\xF8\x74\xAB"
+                         "\xA7\xB8\x9C\x0F\x53\x7B\xB6\x74"
+                         "\x60\x64\x0D\x1C\x80\xD1\x20\x9E"
+                         "\xDC\x14\x27\x9B\xFC\xBD\x5C\x96"
+                         "\xD2\x51\xDC\x96\xEE\xE5\xEA\x2B"
+                         "\x02\x7C\xAA\x3C\xDC\x9D\x7B\x01"
+                         "\x20\xC3\xE1\x0B\xDD\xAB\xF3\x1E"
+                         "\x19\xA8\x84\x29\x5F\xCC\xC3\x5B"
+                         "\xE4\x33\x59\xDC\x12\xEB\x2B\x4D"
+                         "\x5B\x55\x23\xB7\x40\x31\xDE\xEE"
+                         "\x18\xC9\x3C\x4D\xBC\xED\xE0\x42"
+                         "\xAD\xDE\xA0\xA3\xC3\xFE\x44\xD3"
+                         "\xE1\x9A\xDA\xAB\x32\xFC\x1A\xBF"
+                         "\x63\xA9\xF0\x6A\x08\x46\xBD\x48"
+                         "\x83\x06\xAB\x82\x99\x01\x16\x1A"
+                         "\x03\x36\xC5\x59\x6B\xB8\x8C\x9F"
+                         "\xC6\x51\x3D\xE5\x7F\xBF\xAB\xBC"
+                         "\xC9\xA1\x88\x34\x5F\xA9\x7C\x3B"
+                         "\x9F\x1B\x98\x2B\x4F\xFB\x9B\xF0"
+                         "\xCD\xB6\x45\xB2\x29\x2E\x34\x23"
+                         "\xA9\x97\xC0\x22\x8C\x42\x9B\x5F"
+                         "\x40\xC8\xD7\x3D\x82\x9A\x6F\xAA"
+                         "\x74\x83\x29\x05\xE8\xC4\x4D\x01"
+                         "\xB5\xE5\x84\x3F\x7F\xD3\xE0\x99"
+                         "\xDA\xE7\x6F\x30\xFD\xAA\x92\x30"
+                         "\xA5\x46\x8B\xA2\xE6\x58\x62\x7C"
+                         "\x2C\x35\x1B\x38\x85\x7D\xE8\xF3"
+                         "\x87\x4F\xDA\xD8\x5F\xFC\xB6\x44"
+                         "\xD0\xE3\x9B\x8B\xBF\xD6\xB8\xC4"
+                         "\x73\xAE\x1D\x8B\x5B\x74\x8B\xCB",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16352,8 +20888,7 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
                .result = "\x01\x23\x45\x67\x89\xab\xcd\xef"
                          "\xfe\xdc\xba\x98\x76\x54\x32\x10",
                .rlen   = 16,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
                          "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
                          "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
@@ -16364,18 +20899,130 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
                          "\xA5\xFF\x6F\x43\x0F\xBA\x32\x04"
                          "\xB3\xC2\xB9\x03\xAA\x91\x56\x29"
                          "\x0D\xD0\xFD\xC4\x65\xA5\x69\xB9"
-                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A",
-               .ilen   = 48,
+                         "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A"
+                         "\x8D\x7D\x1B\x9B\xC7\x68\x72\xF8"
+                         "\x01\x9B\x17\x0A\x29\xE7\x61\x28"
+                         "\x7F\xA7\x50\xCA\x20\x2C\x96\x3B"
+                         "\x6E\x5C\x5D\x3F\xB5\x7F\xF3\x2B"
+                         "\x04\xEF\x9D\xD4\xCE\x41\x28\x8E"
+                         "\x83\x54\xAE\x7C\x82\x46\x10\xC9"
+                         "\xC4\x8A\x1E\x1F\x4C\xA9\xFC\xEC"
+                         "\x3C\x8C\x30\xFC\x59\xD2\x54\xC4"
+                         "\x6F\x50\xC6\xCA\x8C\x14\x5B\x9C"
+                         "\x18\x56\x5B\xF8\x33\x0E\x4A\xDB"
+                         "\xEC\xB5\x6E\x5B\x31\xC4\x0E\x98"
+                         "\x9F\x32\xBA\xA2\x18\xCF\x55\x43"
+                         "\xFE\x80\x8F\x60\xCF\x05\x30\x9B"
+                         "\x70\x50\x1E\x9C\x08\x87\xE6\x20"
+                         "\xD2\xF3\x27\xF8\x2A\x8D\x12\xB2"
+                         "\xBC\x5F\xFE\x52\x52\xF6\x7F\xB6"
+                         "\xB8\x30\x86\x3B\x0F\x94\x1E\x79"
+                         "\x13\x94\x35\xA2\xB1\x35\x5B\x05"
+                         "\x2A\x98\x6B\x96\x4C\xB1\x20\xBE"
+                         "\xB6\x14\xC2\x06\xBF\xFD\x5F\x2A"
+                         "\xF5\x33\xC8\x19\x45\x14\x44\x5D"
+                         "\xFE\x94\x7B\xBB\x63\x13\x57\xC3"
+                         "\x2A\x8F\x6C\x11\x2A\x07\xA7\x6A"
+                         "\xBF\x20\xD3\x99\xC6\x00\x0B\xBF"
+                         "\x83\x46\x25\x3A\xB0\xF6\xC5\xC8"
+                         "\x00\xCA\xE5\x28\x4A\x7C\x95\x9C"
+                         "\x7B\x43\xAB\xF9\xE4\xF8\x74\xAB"
+                         "\xA7\xB8\x9C\x0F\x53\x7B\xB6\x74"
+                         "\x60\x64\x0D\x1C\x80\xD1\x20\x9E"
+                         "\xDC\x14\x27\x9B\xFC\xBD\x5C\x96"
+                         "\xD2\x51\xDC\x96\xEE\xE5\xEA\x2B"
+                         "\x02\x7C\xAA\x3C\xDC\x9D\x7B\x01"
+                         "\x20\xC3\xE1\x0B\xDD\xAB\xF3\x1E"
+                         "\x19\xA8\x84\x29\x5F\xCC\xC3\x5B"
+                         "\xE4\x33\x59\xDC\x12\xEB\x2B\x4D"
+                         "\x5B\x55\x23\xB7\x40\x31\xDE\xEE"
+                         "\x18\xC9\x3C\x4D\xBC\xED\xE0\x42"
+                         "\xAD\xDE\xA0\xA3\xC3\xFE\x44\xD3"
+                         "\xE1\x9A\xDA\xAB\x32\xFC\x1A\xBF"
+                         "\x63\xA9\xF0\x6A\x08\x46\xBD\x48"
+                         "\x83\x06\xAB\x82\x99\x01\x16\x1A"
+                         "\x03\x36\xC5\x59\x6B\xB8\x8C\x9F"
+                         "\xC6\x51\x3D\xE5\x7F\xBF\xAB\xBC"
+                         "\xC9\xA1\x88\x34\x5F\xA9\x7C\x3B"
+                         "\x9F\x1B\x98\x2B\x4F\xFB\x9B\xF0"
+                         "\xCD\xB6\x45\xB2\x29\x2E\x34\x23"
+                         "\xA9\x97\xC0\x22\x8C\x42\x9B\x5F"
+                         "\x40\xC8\xD7\x3D\x82\x9A\x6F\xAA"
+                         "\x74\x83\x29\x05\xE8\xC4\x4D\x01"
+                         "\xB5\xE5\x84\x3F\x7F\xD3\xE0\x99"
+                         "\xDA\xE7\x6F\x30\xFD\xAA\x92\x30"
+                         "\xA5\x46\x8B\xA2\xE6\x58\x62\x7C"
+                         "\x2C\x35\x1B\x38\x85\x7D\xE8\xF3"
+                         "\x87\x4F\xDA\xD8\x5F\xFC\xB6\x44"
+                         "\xD0\xE3\x9B\x8B\xBF\xD6\xB8\xC4"
+                         "\x73\xAE\x1D\x8B\x5B\x74\x8B\xCB",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .rlen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16407,8 +21054,7 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
                          "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
                          "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
                .rlen   = 32,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16421,18 +21067,130 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .ilen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xCD\x3E\x2A\x3B\x3E\x94\xC5\x77"
                          "\xBA\xBB\x5B\xB1\xDE\x7B\xA4\x40"
                          "\x88\x39\xE3\xFD\x94\x4B\x25\x58"
                          "\xE1\x4B\xC4\x18\x7A\xFD\x17\x2B"
                          "\xB9\xF9\xC2\x27\x6A\xB6\x31\x27"
-                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01",
-               .rlen   = 48,
+                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01"
+                         "\x56\x2E\x10\xC2\x2C\xFF\xC6\x83"
+                         "\xB5\xDC\x4F\x63\xAD\x0E\x63\x5E"
+                         "\x56\xC8\x18\x3D\x79\x86\x97\xEF"
+                         "\x57\x0E\x63\xA1\xC1\x41\x48\xB8"
+                         "\x98\xB7\x51\x6D\x18\xF6\x19\x82"
+                         "\x37\x49\x88\xA4\xEF\x91\x21\x47"
+                         "\x03\x28\xEA\x42\xF4\xFB\x7A\x58"
+                         "\x28\x90\x77\x46\xD8\xD2\x35\x16"
+                         "\x44\xA9\x9E\x49\x52\x2A\xE4\x16"
+                         "\x5D\xF7\x65\xEB\x0F\xC9\x29\xE6"
+                         "\xCF\x76\x91\x89\x8A\x94\x39\xFA"
+                         "\x6B\x5F\x63\x53\x74\x43\x91\xF5"
+                         "\x3F\xBC\x88\x53\xB2\x1A\x02\x3F"
+                         "\x9D\x32\x84\xEB\x56\x28\xD6\x06"
+                         "\xD5\xB2\x20\xA9\xFC\xC3\x76\x62"
+                         "\x32\xCC\x86\xC8\x36\x67\x5E\x7E"
+                         "\xA4\xAA\x15\x63\x6B\xA9\x86\xAF"
+                         "\x1A\x52\x82\x36\x5F\xF4\x3F\x7A"
+                         "\x9B\x78\x62\x3B\x02\x28\x60\xB3"
+                         "\xBA\x82\xB1\xDD\xC9\x60\x8F\x47"
+                         "\xF1\x6B\xFE\xE5\x39\x34\xA0\x28"
+                         "\xA4\xB3\xC9\x7E\xED\x28\x8D\x70"
+                         "\xB2\x1D\xFD\xC6\x00\xCF\x1A\x94"
+                         "\x28\xF8\xC1\x34\xB7\x58\xA5\x6C"
+                         "\x1A\x9D\xE4\xE4\xF6\xB9\xB4\xB0"
+                         "\x5D\x51\x54\x9A\x53\xA0\xF9\x32"
+                         "\xBD\x31\x54\x14\x7B\x33\xEE\x17"
+                         "\xD3\xC7\x1F\x48\xBF\x0B\x22\xA2"
+                         "\x7D\x0C\xDF\xD0\x2E\x98\xFA\xD2"
+                         "\xFA\xCF\x24\x1D\x99\x9B\xD0\x7E"
+                         "\xF4\x4F\x88\xFF\x45\x99\x4A\xF4"
+                         "\xF2\x0A\x5B\x3B\x21\xAB\x92\xAE"
+                         "\x40\x78\x91\x95\xC4\x2F\xA3\xE8"
+                         "\x18\xC7\x07\xA6\xC8\xC0\x66\x33"
+                         "\x35\xC0\xB4\xA0\xF8\xEE\x1E\xF3"
+                         "\x40\xF5\x40\x54\xF1\x84\x8C\xEA"
+                         "\x27\x38\x1F\xF8\x77\xC7\xDF\xD8"
+                         "\x1D\xE2\xD9\x59\x40\x4F\x59\xD4"
+                         "\xF8\x17\x99\x8D\x58\x2D\x72\x44"
+                         "\x9D\x1D\x91\x64\xD6\x3F\x0A\x82"
+                         "\xC7\x57\x3D\xEF\xD3\x41\xFA\xA7"
+                         "\x68\xA3\xB8\xA5\x93\x74\x2E\x85"
+                         "\x4C\x9D\x69\x59\xCE\x15\xAE\xBF"
+                         "\x9C\x8F\x14\x64\x5D\x7F\xCF\x0B"
+                         "\xCE\x43\x5D\x28\xC0\x2F\xFB\x18"
+                         "\x79\x9A\xFC\x43\x16\x7C\x6B\x7B"
+                         "\x38\xB8\x48\x36\x66\x4E\x20\x43"
+                         "\xBA\x76\x13\x9A\xC3\xF2\xEB\x52"
+                         "\xD7\xDC\xB2\x67\x63\x14\x25\xCD"
+                         "\xB1\x13\x4B\xDE\x8C\x59\x21\x84"
+                         "\x81\x8D\x97\x23\x45\x33\x7C\xF3"
+                         "\xC5\xBC\x79\x95\xAA\x84\x68\x31"
+                         "\x2D\x1A\x68\xFE\xEC\x92\x94\xDA"
+                         "\x94\x2A\x6F\xD6\xFE\xE5\x76\x97"
+                         "\xF4\x6E\xEE\xCB\x2B\x95\x4E\x36"
+                         "\x5F\x74\x8C\x86\x5B\x71\xD0\x20",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16464,8 +21222,7 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
                          "\x10\x11\x12\x13\x14\x15\x16\x17"
                          "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
                .rlen   = 32,
-       },
-       { /* Generated with Crypto++ */
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16478,18 +21235,130 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
                          "\x88\x39\xE3\xFD\x94\x4B\x25\x58"
                          "\xE1\x4B\xC4\x18\x7A\xFD\x17\x2B"
                          "\xB9\xF9\xC2\x27\x6A\xB6\x31\x27"
-                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01",
-               .ilen   = 48,
+                         "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01"
+                         "\x56\x2E\x10\xC2\x2C\xFF\xC6\x83"
+                         "\xB5\xDC\x4F\x63\xAD\x0E\x63\x5E"
+                         "\x56\xC8\x18\x3D\x79\x86\x97\xEF"
+                         "\x57\x0E\x63\xA1\xC1\x41\x48\xB8"
+                         "\x98\xB7\x51\x6D\x18\xF6\x19\x82"
+                         "\x37\x49\x88\xA4\xEF\x91\x21\x47"
+                         "\x03\x28\xEA\x42\xF4\xFB\x7A\x58"
+                         "\x28\x90\x77\x46\xD8\xD2\x35\x16"
+                         "\x44\xA9\x9E\x49\x52\x2A\xE4\x16"
+                         "\x5D\xF7\x65\xEB\x0F\xC9\x29\xE6"
+                         "\xCF\x76\x91\x89\x8A\x94\x39\xFA"
+                         "\x6B\x5F\x63\x53\x74\x43\x91\xF5"
+                         "\x3F\xBC\x88\x53\xB2\x1A\x02\x3F"
+                         "\x9D\x32\x84\xEB\x56\x28\xD6\x06"
+                         "\xD5\xB2\x20\xA9\xFC\xC3\x76\x62"
+                         "\x32\xCC\x86\xC8\x36\x67\x5E\x7E"
+                         "\xA4\xAA\x15\x63\x6B\xA9\x86\xAF"
+                         "\x1A\x52\x82\x36\x5F\xF4\x3F\x7A"
+                         "\x9B\x78\x62\x3B\x02\x28\x60\xB3"
+                         "\xBA\x82\xB1\xDD\xC9\x60\x8F\x47"
+                         "\xF1\x6B\xFE\xE5\x39\x34\xA0\x28"
+                         "\xA4\xB3\xC9\x7E\xED\x28\x8D\x70"
+                         "\xB2\x1D\xFD\xC6\x00\xCF\x1A\x94"
+                         "\x28\xF8\xC1\x34\xB7\x58\xA5\x6C"
+                         "\x1A\x9D\xE4\xE4\xF6\xB9\xB4\xB0"
+                         "\x5D\x51\x54\x9A\x53\xA0\xF9\x32"
+                         "\xBD\x31\x54\x14\x7B\x33\xEE\x17"
+                         "\xD3\xC7\x1F\x48\xBF\x0B\x22\xA2"
+                         "\x7D\x0C\xDF\xD0\x2E\x98\xFA\xD2"
+                         "\xFA\xCF\x24\x1D\x99\x9B\xD0\x7E"
+                         "\xF4\x4F\x88\xFF\x45\x99\x4A\xF4"
+                         "\xF2\x0A\x5B\x3B\x21\xAB\x92\xAE"
+                         "\x40\x78\x91\x95\xC4\x2F\xA3\xE8"
+                         "\x18\xC7\x07\xA6\xC8\xC0\x66\x33"
+                         "\x35\xC0\xB4\xA0\xF8\xEE\x1E\xF3"
+                         "\x40\xF5\x40\x54\xF1\x84\x8C\xEA"
+                         "\x27\x38\x1F\xF8\x77\xC7\xDF\xD8"
+                         "\x1D\xE2\xD9\x59\x40\x4F\x59\xD4"
+                         "\xF8\x17\x99\x8D\x58\x2D\x72\x44"
+                         "\x9D\x1D\x91\x64\xD6\x3F\x0A\x82"
+                         "\xC7\x57\x3D\xEF\xD3\x41\xFA\xA7"
+                         "\x68\xA3\xB8\xA5\x93\x74\x2E\x85"
+                         "\x4C\x9D\x69\x59\xCE\x15\xAE\xBF"
+                         "\x9C\x8F\x14\x64\x5D\x7F\xCF\x0B"
+                         "\xCE\x43\x5D\x28\xC0\x2F\xFB\x18"
+                         "\x79\x9A\xFC\x43\x16\x7C\x6B\x7B"
+                         "\x38\xB8\x48\x36\x66\x4E\x20\x43"
+                         "\xBA\x76\x13\x9A\xC3\xF2\xEB\x52"
+                         "\xD7\xDC\xB2\x67\x63\x14\x25\xCD"
+                         "\xB1\x13\x4B\xDE\x8C\x59\x21\x84"
+                         "\x81\x8D\x97\x23\x45\x33\x7C\xF3"
+                         "\xC5\xBC\x79\x95\xAA\x84\x68\x31"
+                         "\x2D\x1A\x68\xFE\xEC\x92\x94\xDA"
+                         "\x94\x2A\x6F\xD6\xFE\xE5\x76\x97"
+                         "\xF4\x6E\xEE\xCB\x2B\x95\x4E\x36"
+                         "\x5F\x74\x8C\x86\x5B\x71\xD0\x20",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .rlen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 48 - 16, 16 },
+               .tap    = { 496 - 16, 16 },
        },
 };
 
@@ -16507,17 +21376,128 @@ static struct cipher_testvec camellia_ctr_enc_tv_template[] = {
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .ilen   = 48,
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .ilen   = 496,
                .result = "\xF3\x06\x3A\x84\xCD\xBA\x8E\x11"
                          "\xB7\x74\x6F\x5C\x97\xFB\x36\xFE"
                          "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
-                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C",
-               .rlen   = 48,
-       },
-       { /* Generated with Crypto++ */
+                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D",
+               .rlen   = 496,
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16531,19 +21511,131 @@ static struct cipher_testvec camellia_ctr_enc_tv_template[] = {
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
                          "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
-                         "\xDF\x76\x0D",
-               .ilen   = 51,
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .ilen   = 499,
                .result = "\xF3\x06\x3A\x84\xCD\xBA\x8E\x11"
                          "\xB7\x74\x6F\x5C\x97\xFB\x36\xFE"
                          "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
                          "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
-                         "\x1E\x43\xEF",
-               .rlen   = 51,
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D"
+                         "\x93\x11\x1C",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 51 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -16695,17 +21787,128 @@ static struct cipher_testvec camellia_ctr_dec_tv_template[] = {
                          "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
-                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C",
-               .ilen   = 48,
+                         "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D",
+               .ilen   = 496,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-               .rlen   = 48,
-       },
-       { /* Generated with Crypto++ */
+                         "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+               .rlen   = 496,
+       }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
                          "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16719,19 +21922,131 @@ static struct cipher_testvec camellia_ctr_dec_tv_template[] = {
                          "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
                          "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
                          "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
-                         "\x1E\x43\xEF",
-               .ilen   = 51,
+                         "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+                         "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+                         "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+                         "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+                         "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+                         "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+                         "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+                         "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+                         "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+                         "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+                         "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+                         "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+                         "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+                         "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+                         "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+                         "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+                         "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+                         "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+                         "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+                         "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+                         "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+                         "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+                         "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+                         "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+                         "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+                         "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+                         "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+                         "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+                         "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+                         "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+                         "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+                         "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+                         "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+                         "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+                         "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+                         "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+                         "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+                         "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+                         "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+                         "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+                         "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+                         "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+                         "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+                         "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+                         "\x76\x44\x45\xF3\x24\x11\x57\x98"
+                         "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+                         "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+                         "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+                         "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+                         "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+                         "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+                         "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+                         "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+                         "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+                         "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+                         "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D"
+                         "\x93\x11\x1C",
+               .ilen   = 499,
                .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
                          "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
                          "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
                          "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
                          "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
                          "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
-                         "\xDF\x76\x0D",
-               .rlen   = 51,
+                         "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+                         "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+                         "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+                         "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+                         "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+                         "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+                         "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+                         "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+                         "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+                         "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+                         "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+                         "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+                         "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+                         "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+                         "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+                         "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+                         "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+                         "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+                         "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+                         "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+                         "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+                         "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+                         "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+                         "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+                         "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+                         "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+                         "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+                         "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+                         "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+                         "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+                         "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+                         "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+                         "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+                         "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+                         "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+                         "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+                         "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+                         "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+                         "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+                         "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+                         "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+                         "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+                         "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+                         "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+                         "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+                         "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+                         "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+                         "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+                         "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+                         "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+                         "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+                         "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+                         "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+                         "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+                         "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+                         "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+                         "\x2B\xC2\x59",
+               .rlen   = 499,
                .also_non_np = 1,
                .np     = 2,
-               .tap    = { 51 - 16, 16 },
+               .tap    = { 499 - 16, 16 },
        }, { /* Generated with Crypto++ */
                .key    = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
                          "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -19895,7 +25210,7 @@ static struct hash_testvec michael_mic_tv_template[] = {
 /*
  * CRC32C test vectors
  */
-#define CRC32C_TEST_VECTORS 14
+#define CRC32C_TEST_VECTORS 15
 
 static struct hash_testvec crc32c_tv_template[] = {
        {
@@ -20066,7 +25381,268 @@ static struct hash_testvec crc32c_tv_template[] = {
                .digest = "\x75\xd3\xc5\x24",
                .np = 2,
                .tap = { 31, 209 }
-       },
+       }, {
+               .key = "\xff\xff\xff\xff",
+               .ksize = 4,
+               .plaintext =    "\x6e\x05\x79\x10\xa7\x1b\xb2\x49"
+                               "\xe0\x54\xeb\x82\x19\x8d\x24\xbb"
+                               "\x2f\xc6\x5d\xf4\x68\xff\x96\x0a"
+                               "\xa1\x38\xcf\x43\xda\x71\x08\x7c"
+                               "\x13\xaa\x1e\xb5\x4c\xe3\x57\xee"
+                               "\x85\x1c\x90\x27\xbe\x32\xc9\x60"
+                               "\xf7\x6b\x02\x99\x0d\xa4\x3b\xd2"
+                               "\x46\xdd\x74\x0b\x7f\x16\xad\x21"
+                               "\xb8\x4f\xe6\x5a\xf1\x88\x1f\x93"
+                               "\x2a\xc1\x35\xcc\x63\xfa\x6e\x05"
+                               "\x9c\x10\xa7\x3e\xd5\x49\xe0\x77"
+                               "\x0e\x82\x19\xb0\x24\xbb\x52\xe9"
+                               "\x5d\xf4\x8b\x22\x96\x2d\xc4\x38"
+                               "\xcf\x66\xfd\x71\x08\x9f\x13\xaa"
+                               "\x41\xd8\x4c\xe3\x7a\x11\x85\x1c"
+                               "\xb3\x27\xbe\x55\xec\x60\xf7\x8e"
+                               "\x02\x99\x30\xc7\x3b\xd2\x69\x00"
+                               "\x74\x0b\xa2\x16\xad\x44\xdb\x4f"
+                               "\xe6\x7d\x14\x88\x1f\xb6\x2a\xc1"
+                               "\x58\xef\x63\xfa\x91\x05\x9c\x33"
+                               "\xca\x3e\xd5\x6c\x03\x77\x0e\xa5"
+                               "\x19\xb0\x47\xde\x52\xe9\x80\x17"
+                               "\x8b\x22\xb9\x2d\xc4\x5b\xf2\x66"
+                               "\xfd\x94\x08\x9f\x36\xcd\x41\xd8"
+                               "\x6f\x06\x7a\x11\xa8\x1c\xb3\x4a"
+                               "\xe1\x55\xec\x83\x1a\x8e\x25\xbc"
+                               "\x30\xc7\x5e\xf5\x69\x00\x97\x0b"
+                               "\xa2\x39\xd0\x44\xdb\x72\x09\x7d"
+                               "\x14\xab\x1f\xb6\x4d\xe4\x58\xef"
+                               "\x86\x1d\x91\x28\xbf\x33\xca\x61"
+                               "\xf8\x6c\x03\x9a\x0e\xa5\x3c\xd3"
+                               "\x47\xde\x75\x0c\x80\x17\xae\x22"
+                               "\xb9\x50\xe7\x5b\xf2\x89\x20\x94"
+                               "\x2b\xc2\x36\xcd\x64\xfb\x6f\x06"
+                               "\x9d\x11\xa8\x3f\xd6\x4a\xe1\x78"
+                               "\x0f\x83\x1a\xb1\x25\xbc\x53\xea"
+                               "\x5e\xf5\x8c\x00\x97\x2e\xc5\x39"
+                               "\xd0\x67\xfe\x72\x09\xa0\x14\xab"
+                               "\x42\xd9\x4d\xe4\x7b\x12\x86\x1d"
+                               "\xb4\x28\xbf\x56\xed\x61\xf8\x8f"
+                               "\x03\x9a\x31\xc8\x3c\xd3\x6a\x01"
+                               "\x75\x0c\xa3\x17\xae\x45\xdc\x50"
+                               "\xe7\x7e\x15\x89\x20\xb7\x2b\xc2"
+                               "\x59\xf0\x64\xfb\x92\x06\x9d\x34"
+                               "\xcb\x3f\xd6\x6d\x04\x78\x0f\xa6"
+                               "\x1a\xb1\x48\xdf\x53\xea\x81\x18"
+                               "\x8c\x23\xba\x2e\xc5\x5c\xf3\x67"
+                               "\xfe\x95\x09\xa0\x37\xce\x42\xd9"
+                               "\x70\x07\x7b\x12\xa9\x1d\xb4\x4b"
+                               "\xe2\x56\xed\x84\x1b\x8f\x26\xbd"
+                               "\x31\xc8\x5f\xf6\x6a\x01\x98\x0c"
+                               "\xa3\x3a\xd1\x45\xdc\x73\x0a\x7e"
+                               "\x15\xac\x20\xb7\x4e\xe5\x59\xf0"
+                               "\x87\x1e\x92\x29\xc0\x34\xcb\x62"
+                               "\xf9\x6d\x04\x9b\x0f\xa6\x3d\xd4"
+                               "\x48\xdf\x76\x0d\x81\x18\xaf\x23"
+                               "\xba\x51\xe8\x5c\xf3\x8a\x21\x95"
+                               "\x2c\xc3\x37\xce\x65\xfc\x70\x07"
+                               "\x9e\x12\xa9\x40\xd7\x4b\xe2\x79"
+                               "\x10\x84\x1b\xb2\x26\xbd\x54\xeb"
+                               "\x5f\xf6\x8d\x01\x98\x2f\xc6\x3a"
+                               "\xd1\x68\xff\x73\x0a\xa1\x15\xac"
+                               "\x43\xda\x4e\xe5\x7c\x13\x87\x1e"
+                               "\xb5\x29\xc0\x57\xee\x62\xf9\x90"
+                               "\x04\x9b\x32\xc9\x3d\xd4\x6b\x02"
+                               "\x76\x0d\xa4\x18\xaf\x46\xdd\x51"
+                               "\xe8\x7f\x16\x8a\x21\xb8\x2c\xc3"
+                               "\x5a\xf1\x65\xfc\x93\x07\x9e\x35"
+                               "\xcc\x40\xd7\x6e\x05\x79\x10\xa7"
+                               "\x1b\xb2\x49\xe0\x54\xeb\x82\x19"
+                               "\x8d\x24\xbb\x2f\xc6\x5d\xf4\x68"
+                               "\xff\x96\x0a\xa1\x38\xcf\x43\xda"
+                               "\x71\x08\x7c\x13\xaa\x1e\xb5\x4c"
+                               "\xe3\x57\xee\x85\x1c\x90\x27\xbe"
+                               "\x32\xc9\x60\xf7\x6b\x02\x99\x0d"
+                               "\xa4\x3b\xd2\x46\xdd\x74\x0b\x7f"
+                               "\x16\xad\x21\xb8\x4f\xe6\x5a\xf1"
+                               "\x88\x1f\x93\x2a\xc1\x35\xcc\x63"
+                               "\xfa\x6e\x05\x9c\x10\xa7\x3e\xd5"
+                               "\x49\xe0\x77\x0e\x82\x19\xb0\x24"
+                               "\xbb\x52\xe9\x5d\xf4\x8b\x22\x96"
+                               "\x2d\xc4\x38\xcf\x66\xfd\x71\x08"
+                               "\x9f\x13\xaa\x41\xd8\x4c\xe3\x7a"
+                               "\x11\x85\x1c\xb3\x27\xbe\x55\xec"
+                               "\x60\xf7\x8e\x02\x99\x30\xc7\x3b"
+                               "\xd2\x69\x00\x74\x0b\xa2\x16\xad"
+                               "\x44\xdb\x4f\xe6\x7d\x14\x88\x1f"
+                               "\xb6\x2a\xc1\x58\xef\x63\xfa\x91"
+                               "\x05\x9c\x33\xca\x3e\xd5\x6c\x03"
+                               "\x77\x0e\xa5\x19\xb0\x47\xde\x52"
+                               "\xe9\x80\x17\x8b\x22\xb9\x2d\xc4"
+                               "\x5b\xf2\x66\xfd\x94\x08\x9f\x36"
+                               "\xcd\x41\xd8\x6f\x06\x7a\x11\xa8"
+                               "\x1c\xb3\x4a\xe1\x55\xec\x83\x1a"
+                               "\x8e\x25\xbc\x30\xc7\x5e\xf5\x69"
+                               "\x00\x97\x0b\xa2\x39\xd0\x44\xdb"
+                               "\x72\x09\x7d\x14\xab\x1f\xb6\x4d"
+                               "\xe4\x58\xef\x86\x1d\x91\x28\xbf"
+                               "\x33\xca\x61\xf8\x6c\x03\x9a\x0e"
+                               "\xa5\x3c\xd3\x47\xde\x75\x0c\x80"
+                               "\x17\xae\x22\xb9\x50\xe7\x5b\xf2"
+                               "\x89\x20\x94\x2b\xc2\x36\xcd\x64"
+                               "\xfb\x6f\x06\x9d\x11\xa8\x3f\xd6"
+                               "\x4a\xe1\x78\x0f\x83\x1a\xb1\x25"
+                               "\xbc\x53\xea\x5e\xf5\x8c\x00\x97"
+                               "\x2e\xc5\x39\xd0\x67\xfe\x72\x09"
+                               "\xa0\x14\xab\x42\xd9\x4d\xe4\x7b"
+                               "\x12\x86\x1d\xb4\x28\xbf\x56\xed"
+                               "\x61\xf8\x8f\x03\x9a\x31\xc8\x3c"
+                               "\xd3\x6a\x01\x75\x0c\xa3\x17\xae"
+                               "\x45\xdc\x50\xe7\x7e\x15\x89\x20"
+                               "\xb7\x2b\xc2\x59\xf0\x64\xfb\x92"
+                               "\x06\x9d\x34\xcb\x3f\xd6\x6d\x04"
+                               "\x78\x0f\xa6\x1a\xb1\x48\xdf\x53"
+                               "\xea\x81\x18\x8c\x23\xba\x2e\xc5"
+                               "\x5c\xf3\x67\xfe\x95\x09\xa0\x37"
+                               "\xce\x42\xd9\x70\x07\x7b\x12\xa9"
+                               "\x1d\xb4\x4b\xe2\x56\xed\x84\x1b"
+                               "\x8f\x26\xbd\x31\xc8\x5f\xf6\x6a"
+                               "\x01\x98\x0c\xa3\x3a\xd1\x45\xdc"
+                               "\x73\x0a\x7e\x15\xac\x20\xb7\x4e"
+                               "\xe5\x59\xf0\x87\x1e\x92\x29\xc0"
+                               "\x34\xcb\x62\xf9\x6d\x04\x9b\x0f"
+                               "\xa6\x3d\xd4\x48\xdf\x76\x0d\x81"
+                               "\x18\xaf\x23\xba\x51\xe8\x5c\xf3"
+                               "\x8a\x21\x95\x2c\xc3\x37\xce\x65"
+                               "\xfc\x70\x07\x9e\x12\xa9\x40\xd7"
+                               "\x4b\xe2\x79\x10\x84\x1b\xb2\x26"
+                               "\xbd\x54\xeb\x5f\xf6\x8d\x01\x98"
+                               "\x2f\xc6\x3a\xd1\x68\xff\x73\x0a"
+                               "\xa1\x15\xac\x43\xda\x4e\xe5\x7c"
+                               "\x13\x87\x1e\xb5\x29\xc0\x57\xee"
+                               "\x62\xf9\x90\x04\x9b\x32\xc9\x3d"
+                               "\xd4\x6b\x02\x76\x0d\xa4\x18\xaf"
+                               "\x46\xdd\x51\xe8\x7f\x16\x8a\x21"
+                               "\xb8\x2c\xc3\x5a\xf1\x65\xfc\x93"
+                               "\x07\x9e\x35\xcc\x40\xd7\x6e\x05"
+                               "\x79\x10\xa7\x1b\xb2\x49\xe0\x54"
+                               "\xeb\x82\x19\x8d\x24\xbb\x2f\xc6"
+                               "\x5d\xf4\x68\xff\x96\x0a\xa1\x38"
+                               "\xcf\x43\xda\x71\x08\x7c\x13\xaa"
+                               "\x1e\xb5\x4c\xe3\x57\xee\x85\x1c"
+                               "\x90\x27\xbe\x32\xc9\x60\xf7\x6b"
+                               "\x02\x99\x0d\xa4\x3b\xd2\x46\xdd"
+                               "\x74\x0b\x7f\x16\xad\x21\xb8\x4f"
+                               "\xe6\x5a\xf1\x88\x1f\x93\x2a\xc1"
+                               "\x35\xcc\x63\xfa\x6e\x05\x9c\x10"
+                               "\xa7\x3e\xd5\x49\xe0\x77\x0e\x82"
+                               "\x19\xb0\x24\xbb\x52\xe9\x5d\xf4"
+                               "\x8b\x22\x96\x2d\xc4\x38\xcf\x66"
+                               "\xfd\x71\x08\x9f\x13\xaa\x41\xd8"
+                               "\x4c\xe3\x7a\x11\x85\x1c\xb3\x27"
+                               "\xbe\x55\xec\x60\xf7\x8e\x02\x99"
+                               "\x30\xc7\x3b\xd2\x69\x00\x74\x0b"
+                               "\xa2\x16\xad\x44\xdb\x4f\xe6\x7d"
+                               "\x14\x88\x1f\xb6\x2a\xc1\x58\xef"
+                               "\x63\xfa\x91\x05\x9c\x33\xca\x3e"
+                               "\xd5\x6c\x03\x77\x0e\xa5\x19\xb0"
+                               "\x47\xde\x52\xe9\x80\x17\x8b\x22"
+                               "\xb9\x2d\xc4\x5b\xf2\x66\xfd\x94"
+                               "\x08\x9f\x36\xcd\x41\xd8\x6f\x06"
+                               "\x7a\x11\xa8\x1c\xb3\x4a\xe1\x55"
+                               "\xec\x83\x1a\x8e\x25\xbc\x30\xc7"
+                               "\x5e\xf5\x69\x00\x97\x0b\xa2\x39"
+                               "\xd0\x44\xdb\x72\x09\x7d\x14\xab"
+                               "\x1f\xb6\x4d\xe4\x58\xef\x86\x1d"
+                               "\x91\x28\xbf\x33\xca\x61\xf8\x6c"
+                               "\x03\x9a\x0e\xa5\x3c\xd3\x47\xde"
+                               "\x75\x0c\x80\x17\xae\x22\xb9\x50"
+                               "\xe7\x5b\xf2\x89\x20\x94\x2b\xc2"
+                               "\x36\xcd\x64\xfb\x6f\x06\x9d\x11"
+                               "\xa8\x3f\xd6\x4a\xe1\x78\x0f\x83"
+                               "\x1a\xb1\x25\xbc\x53\xea\x5e\xf5"
+                               "\x8c\x00\x97\x2e\xc5\x39\xd0\x67"
+                               "\xfe\x72\x09\xa0\x14\xab\x42\xd9"
+                               "\x4d\xe4\x7b\x12\x86\x1d\xb4\x28"
+                               "\xbf\x56\xed\x61\xf8\x8f\x03\x9a"
+                               "\x31\xc8\x3c\xd3\x6a\x01\x75\x0c"
+                               "\xa3\x17\xae\x45\xdc\x50\xe7\x7e"
+                               "\x15\x89\x20\xb7\x2b\xc2\x59\xf0"
+                               "\x64\xfb\x92\x06\x9d\x34\xcb\x3f"
+                               "\xd6\x6d\x04\x78\x0f\xa6\x1a\xb1"
+                               "\x48\xdf\x53\xea\x81\x18\x8c\x23"
+                               "\xba\x2e\xc5\x5c\xf3\x67\xfe\x95"
+                               "\x09\xa0\x37\xce\x42\xd9\x70\x07"
+                               "\x7b\x12\xa9\x1d\xb4\x4b\xe2\x56"
+                               "\xed\x84\x1b\x8f\x26\xbd\x31\xc8"
+                               "\x5f\xf6\x6a\x01\x98\x0c\xa3\x3a"
+                               "\xd1\x45\xdc\x73\x0a\x7e\x15\xac"
+                               "\x20\xb7\x4e\xe5\x59\xf0\x87\x1e"
+                               "\x92\x29\xc0\x34\xcb\x62\xf9\x6d"
+                               "\x04\x9b\x0f\xa6\x3d\xd4\x48\xdf"
+                               "\x76\x0d\x81\x18\xaf\x23\xba\x51"
+                               "\xe8\x5c\xf3\x8a\x21\x95\x2c\xc3"
+                               "\x37\xce\x65\xfc\x70\x07\x9e\x12"
+                               "\xa9\x40\xd7\x4b\xe2\x79\x10\x84"
+                               "\x1b\xb2\x26\xbd\x54\xeb\x5f\xf6"
+                               "\x8d\x01\x98\x2f\xc6\x3a\xd1\x68"
+                               "\xff\x73\x0a\xa1\x15\xac\x43\xda"
+                               "\x4e\xe5\x7c\x13\x87\x1e\xb5\x29"
+                               "\xc0\x57\xee\x62\xf9\x90\x04\x9b"
+                               "\x32\xc9\x3d\xd4\x6b\x02\x76\x0d"
+                               "\xa4\x18\xaf\x46\xdd\x51\xe8\x7f"
+                               "\x16\x8a\x21\xb8\x2c\xc3\x5a\xf1"
+                               "\x65\xfc\x93\x07\x9e\x35\xcc\x40"
+                               "\xd7\x6e\x05\x79\x10\xa7\x1b\xb2"
+                               "\x49\xe0\x54\xeb\x82\x19\x8d\x24"
+                               "\xbb\x2f\xc6\x5d\xf4\x68\xff\x96"
+                               "\x0a\xa1\x38\xcf\x43\xda\x71\x08"
+                               "\x7c\x13\xaa\x1e\xb5\x4c\xe3\x57"
+                               "\xee\x85\x1c\x90\x27\xbe\x32\xc9"
+                               "\x60\xf7\x6b\x02\x99\x0d\xa4\x3b"
+                               "\xd2\x46\xdd\x74\x0b\x7f\x16\xad"
+                               "\x21\xb8\x4f\xe6\x5a\xf1\x88\x1f"
+                               "\x93\x2a\xc1\x35\xcc\x63\xfa\x6e"
+                               "\x05\x9c\x10\xa7\x3e\xd5\x49\xe0"
+                               "\x77\x0e\x82\x19\xb0\x24\xbb\x52"
+                               "\xe9\x5d\xf4\x8b\x22\x96\x2d\xc4"
+                               "\x38\xcf\x66\xfd\x71\x08\x9f\x13"
+                               "\xaa\x41\xd8\x4c\xe3\x7a\x11\x85"
+                               "\x1c\xb3\x27\xbe\x55\xec\x60\xf7"
+                               "\x8e\x02\x99\x30\xc7\x3b\xd2\x69"
+                               "\x00\x74\x0b\xa2\x16\xad\x44\xdb"
+                               "\x4f\xe6\x7d\x14\x88\x1f\xb6\x2a"
+                               "\xc1\x58\xef\x63\xfa\x91\x05\x9c"
+                               "\x33\xca\x3e\xd5\x6c\x03\x77\x0e"
+                               "\xa5\x19\xb0\x47\xde\x52\xe9\x80"
+                               "\x17\x8b\x22\xb9\x2d\xc4\x5b\xf2"
+                               "\x66\xfd\x94\x08\x9f\x36\xcd\x41"
+                               "\xd8\x6f\x06\x7a\x11\xa8\x1c\xb3"
+                               "\x4a\xe1\x55\xec\x83\x1a\x8e\x25"
+                               "\xbc\x30\xc7\x5e\xf5\x69\x00\x97"
+                               "\x0b\xa2\x39\xd0\x44\xdb\x72\x09"
+                               "\x7d\x14\xab\x1f\xb6\x4d\xe4\x58"
+                               "\xef\x86\x1d\x91\x28\xbf\x33\xca"
+                               "\x61\xf8\x6c\x03\x9a\x0e\xa5\x3c"
+                               "\xd3\x47\xde\x75\x0c\x80\x17\xae"
+                               "\x22\xb9\x50\xe7\x5b\xf2\x89\x20"
+                               "\x94\x2b\xc2\x36\xcd\x64\xfb\x6f"
+                               "\x06\x9d\x11\xa8\x3f\xd6\x4a\xe1"
+                               "\x78\x0f\x83\x1a\xb1\x25\xbc\x53"
+                               "\xea\x5e\xf5\x8c\x00\x97\x2e\xc5"
+                               "\x39\xd0\x67\xfe\x72\x09\xa0\x14"
+                               "\xab\x42\xd9\x4d\xe4\x7b\x12\x86"
+                               "\x1d\xb4\x28\xbf\x56\xed\x61\xf8"
+                               "\x8f\x03\x9a\x31\xc8\x3c\xd3\x6a"
+                               "\x01\x75\x0c\xa3\x17\xae\x45\xdc"
+                               "\x50\xe7\x7e\x15\x89\x20\xb7\x2b"
+                               "\xc2\x59\xf0\x64\xfb\x92\x06\x9d"
+                               "\x34\xcb\x3f\xd6\x6d\x04\x78\x0f"
+                               "\xa6\x1a\xb1\x48\xdf\x53\xea\x81"
+                               "\x18\x8c\x23\xba\x2e\xc5\x5c\xf3"
+                               "\x67\xfe\x95\x09\xa0\x37\xce\x42"
+                               "\xd9\x70\x07\x7b\x12\xa9\x1d\xb4"
+                               "\x4b\xe2\x56\xed\x84\x1b\x8f\x26"
+                               "\xbd\x31\xc8\x5f\xf6\x6a\x01\x98",
+               .psize = 2048,
+               .digest = "\xec\x26\x4d\x95",
+       }
 };
 
 /*
index f2338ca983686c5aea9f57d1ad733097bd6a1455..2eb11a30c29cee93203a1b90a990cc4463368440 100644 (file)
@@ -375,6 +375,11 @@ static void vhash_update(const unsigned char *m,
        u64 pkh = ctx->polykey[0];
        u64 pkl = ctx->polykey[1];
 
+       if (!mbytes)
+               return;
+
+       BUG_ON(mbytes % VMAC_NHBYTES);
+
        mptr = (u64 *)m;
        i = mbytes / VMAC_NHBYTES;  /* Must be non-zero */
 
@@ -454,7 +459,7 @@ do_l3:
 }
 
 static u64 vmac(unsigned char m[], unsigned int mbytes,
-                       unsigned char n[16], u64 *tagl,
+                       const unsigned char n[16], u64 *tagl,
                        struct vmac_ctx_t *ctx)
 {
        u64 *in_n, *out_p;
@@ -559,8 +564,33 @@ static int vmac_update(struct shash_desc *pdesc, const u8 *p,
 {
        struct crypto_shash *parent = pdesc->tfm;
        struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
+       int expand;
+       int min;
+
+       expand = VMAC_NHBYTES - ctx->partial_size > 0 ?
+                       VMAC_NHBYTES - ctx->partial_size : 0;
+
+       min = len < expand ? len : expand;
+
+       memcpy(ctx->partial + ctx->partial_size, p, min);
+       ctx->partial_size += min;
+
+       if (len < expand)
+               return 0;
 
-       vhash_update(p, len, &ctx->__vmac_ctx);
+       vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx);
+       ctx->partial_size = 0;
+
+       len -= expand;
+       p += expand;
+
+       if (len % VMAC_NHBYTES) {
+               memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES),
+                       len % VMAC_NHBYTES);
+               ctx->partial_size = len % VMAC_NHBYTES;
+       }
+
+       vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx);
 
        return 0;
 }
@@ -572,10 +602,20 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
        vmac_t mac;
        u8 nonce[16] = {};
 
-       mac = vmac(NULL, 0, nonce, NULL, ctx);
+       /* vmac() ends up accessing outside the array bounds that
+        * we specify.  In appears to access up to the next 2-word
+        * boundary.  We'll just be uber cautious and zero the
+        * unwritten bytes in the buffer.
+        */
+       if (ctx->partial_size) {
+               memset(ctx->partial + ctx->partial_size, 0,
+                       VMAC_NHBYTES - ctx->partial_size);
+       }
+       mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
        memcpy(out, &mac, sizeof(vmac_t));
        memset(&mac, 0, sizeof(vmac_t));
        memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
+       ctx->partial_size = 0;
        return 0;
 }
 
@@ -673,4 +713,3 @@ module_exit(vmac_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VMAC hash algorithm");
-
index 0300bf612946c53ca18a75a8d44c7e2ac2f6c1ff..38c5078da11d67ea9db98cf936812982b62f313c 100644 (file)
@@ -267,6 +267,15 @@ config ACPI_CUSTOM_DSDT
        bool
        default ACPI_CUSTOM_DSDT_FILE != ""
 
+config ACPI_INITRD_TABLE_OVERRIDE
+       bool "ACPI tables can be passed via uncompressed cpio in initrd"
+       default n
+       help
+         This option provides functionality to override arbitrary ACPI tables
+         via initrd. No functional change if no ACPI tables are passed via
+         initrd, therefore it's safe to say Y.
+         See Documentation/acpi/initrd_table_override.txt for details
+
 config ACPI_BLACKLIST_YEAR
        int "Disable ACPI for systems before Jan 1st this year" if X86_32
        default 0
index 0df024e5fb63fe75ba828fd3d4a847beb22ecb32..d09c6b4bab2c9632cf2bfa88ea5fb8ed196e10d4 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: dsopcode - Dispatcher suport for regions and fields
+ * Module Name: dsopcode - Dispatcher support for regions and fields
  *
  *****************************************************************************/
 
index 6dc4a2b1e956ea7463868f418a1e8a6cb3d95fe1..3ff267861541f7570a5b110b7893e0cb012f5917 100644 (file)
@@ -534,6 +534,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
        return AE_OK;
 }
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+#include <linux/earlycpio.h>
+#include <linux/memblock.h>
+
+static u64 acpi_tables_addr;
+static int all_tables_size;
+
+/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
+u8 __init acpi_table_checksum(u8 *buffer, u32 length)
+{
+       u8 sum = 0;
+       u8 *end = buffer + length;
+
+       while (buffer < end)
+               sum = (u8) (sum + *(buffer++));
+       return sum;
+}
+
+/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
+static const char * const table_sigs[] = {
+       ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
+       ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
+       ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
+       ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
+       ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
+       ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
+       ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
+       ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
+       ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
+
+/* Non-fatal errors: Affected tables/files are ignored */
+#define INVALID_TABLE(x, path, name)                                   \
+       { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
+
+#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
+
+/* Must not increase 10 or needs code modification below */
+#define ACPI_OVERRIDE_TABLES 10
+
+void __init acpi_initrd_override(void *data, size_t size)
+{
+       int sig, no, table_nr = 0, total_offset = 0;
+       long offset = 0;
+       struct acpi_table_header *table;
+       char cpio_path[32] = "kernel/firmware/acpi/";
+       struct cpio_data file;
+       struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
+       char *p;
+
+       if (data == NULL || size == 0)
+               return;
+
+       for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
+               file = find_cpio_data(cpio_path, data, size, &offset);
+               if (!file.data)
+                       break;
+
+               data += offset;
+               size -= offset;
+
+               if (file.size < sizeof(struct acpi_table_header))
+                       INVALID_TABLE("Table smaller than ACPI header",
+                                     cpio_path, file.name);
+
+               table = file.data;
+
+               for (sig = 0; table_sigs[sig]; sig++)
+                       if (!memcmp(table->signature, table_sigs[sig], 4))
+                               break;
+
+               if (!table_sigs[sig])
+                       INVALID_TABLE("Unknown signature",
+                                     cpio_path, file.name);
+               if (file.size != table->length)
+                       INVALID_TABLE("File length does not match table length",
+                                     cpio_path, file.name);
+               if (acpi_table_checksum(file.data, table->length))
+                       INVALID_TABLE("Bad table checksum",
+                                     cpio_path, file.name);
+
+               pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
+                       table->signature, cpio_path, file.name, table->length);
+
+               all_tables_size += table->length;
+               early_initrd_files[table_nr].data = file.data;
+               early_initrd_files[table_nr].size = file.size;
+               table_nr++;
+       }
+       if (table_nr == 0)
+               return;
+
+       acpi_tables_addr =
+               memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+                                      all_tables_size, PAGE_SIZE);
+       if (!acpi_tables_addr) {
+               WARN_ON(1);
+               return;
+       }
+       /*
+        * Only calling e820_add_reserve does not work and the
+        * tables are invalid (memory got used) later.
+        * memblock_reserve works as expected and the tables won't get modified.
+        * But it's not enough on X86 because ioremap will
+        * complain later (used by acpi_os_map_memory) that the pages
+        * that should get mapped are not marked "reserved".
+        * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
+        * works fine.
+        */
+       memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
+       arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
+
+       p = early_ioremap(acpi_tables_addr, all_tables_size);
+
+       for (no = 0; no < table_nr; no++) {
+               memcpy(p + total_offset, early_initrd_files[no].data,
+                      early_initrd_files[no].size);
+               total_offset += early_initrd_files[no].size;
+       }
+       early_iounmap(p, all_tables_size);
+}
+#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
+
+static void acpi_table_taint(struct acpi_table_header *table)
+{
+       pr_warn(PREFIX
+               "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+               table->signature, table->oem_table_id);
+       add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+}
+
+
 acpi_status
 acpi_os_table_override(struct acpi_table_header * existing_table,
                       struct acpi_table_header ** new_table)
@@ -547,24 +678,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
        if (strncmp(existing_table->signature, "DSDT", 4) == 0)
                *new_table = (struct acpi_table_header *)AmlCode;
 #endif
-       if (*new_table != NULL) {
-               printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
-                          "this is unsafe: tainting kernel\n",
-                      existing_table->signature,
-                      existing_table->oem_table_id);
-               add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
-       }
+       if (*new_table != NULL)
+               acpi_table_taint(existing_table);
        return AE_OK;
 }
 
 acpi_status
 acpi_os_physical_table_override(struct acpi_table_header *existing_table,
-                               acpi_physical_address * new_address,
-                               u32 *new_table_length)
+                               acpi_physical_address *address,
+                               u32 *table_length)
 {
-       return AE_SUPPORT;
-}
+#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+       *table_length = 0;
+       *address = 0;
+       return AE_OK;
+#else
+       int table_offset = 0;
+       struct acpi_table_header *table;
+
+       *table_length = 0;
+       *address = 0;
+
+       if (!acpi_tables_addr)
+               return AE_OK;
+
+       do {
+               if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
+                       WARN_ON(1);
+                       return AE_OK;
+               }
 
+               table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+                                          ACPI_HEADER_SIZE);
+
+               if (table_offset + table->length > all_tables_size) {
+                       acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+                       WARN_ON(1);
+                       return AE_OK;
+               }
+
+               table_offset += table->length;
+
+               if (memcmp(existing_table->signature, table->signature, 4)) {
+                       acpi_os_unmap_memory(table,
+                                    ACPI_HEADER_SIZE);
+                       continue;
+               }
+
+               /* Only override tables with matching oem id */
+               if (memcmp(table->oem_table_id, existing_table->oem_table_id,
+                          ACPI_OEM_TABLE_ID_SIZE)) {
+                       acpi_os_unmap_memory(table,
+                                    ACPI_HEADER_SIZE);
+                       continue;
+               }
+
+               table_offset -= table->length;
+               *table_length = table->length;
+               acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+               *address = acpi_tables_addr + table_offset;
+               break;
+       } while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
+
+       if (*address != 0)
+               acpi_table_taint(existing_table);
+       return AE_OK;
+#endif
+}
 
 static irqreturn_t acpi_irq(int irq, void *dev_id)
 {
index 2ef04098cc1d5f4d01942d3e4de79014c4911efe..a1dee29beed328430491bdbff3cfe386692b06ba 100644 (file)
@@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device)
 
        device_set_run_wake(&dev->dev, false);
        pci_acpi_remove_pm_notifier(device);
+       acpi_power_resource_unregister_device(&dev->dev, device->handle);
 
        if (!dev->subordinate)
                goto out;
 
-       acpi_pci_irq_del_prt(dev->subordinate);
+       acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
 
        device->ops.bind = NULL;
        device->ops.unbind = NULL;
@@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
 {
        acpi_status status;
        acpi_handle handle;
-       struct pci_bus *bus;
+       unsigned char bus;
        struct pci_dev *dev;
 
        dev = acpi_get_pci_dev(device->handle);
@@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device)
                return 0;
 
        pci_acpi_add_pm_notifier(device, dev);
+       acpi_power_resource_register_device(&dev->dev, device->handle);
        if (device->wakeup.flags.run_wake)
                device_set_run_wake(&dev->dev, true);
 
@@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
                goto out;
 
        if (dev->subordinate)
-               bus = dev->subordinate;
+               bus = dev->subordinate->number;
        else
-               bus = dev->bus;
+               bus = dev->bus->number;
 
-       acpi_pci_irq_add_prt(device->handle, bus);
+       acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
 
 out:
        pci_dev_put(dev);
index 23a0324901307b9f0c930f7be00beeff45dbbec0..68a921d032475edbaa7740d9f880ee5bf52a8db3 100644 (file)
@@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
        }
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
+static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
                                  struct acpi_pci_routing_table *prt)
 {
        struct acpi_prt_entry *entry;
@@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
         * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
         * it here.
         */
-       entry->id.segment = pci_domain_nr(bus);
-       entry->id.bus = bus->number;
+       entry->id.segment = segment;
+       entry->id.bus = bus;
        entry->id.device = (prt->address >> 16) & 0xFFFF;
        entry->pin = prt->pin + 1;
 
@@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
        return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
 {
        acpi_status status;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
 
        entry = buffer.pointer;
        while (entry && (entry->length > 0)) {
-               acpi_pci_irq_add_entry(handle, bus, entry);
+               acpi_pci_irq_add_entry(handle, segment, bus, entry);
                entry = (struct acpi_pci_routing_table *)
                    ((unsigned long)entry + entry->length);
        }
@@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
        return 0;
 }
 
-void acpi_pci_irq_del_prt(struct pci_bus *bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
 {
        struct acpi_prt_entry *entry, *tmp;
 
        printk(KERN_DEBUG
               "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-              pci_domain_nr(bus), bus->number);
+              segment, bus);
        spin_lock(&acpi_prt_lock);
        list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-               if (pci_domain_nr(bus) == entry->id.segment
-                       && bus->number == entry->id.bus) {
+               if (segment == entry->id.segment && bus == entry->id.bus) {
                        list_del(&entry->list);
                        kfree(entry);
                }
index f70b9e5fc1b59098b530e58567bba2ae36ea99d3..7928d4dc705618a833ccce3172ed5113307d4cff 100644 (file)
@@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
        acpi_handle handle;
        struct acpi_device *child;
        u32 flags, base_flags;
+       bool is_osc_granted = false;
 
        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
        if (!root)
@@ -501,52 +502,10 @@ static int acpi_pci_root_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
        device->driver_data = root;
 
-       root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
-
-       /*
-        * All supported architectures that use ACPI have support for
-        * PCI domains, so we indicate this in _OSC support capabilities.
-        */
-       flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
-       acpi_pci_osc_support(root, flags);
-
-       /*
-        * TBD: Need PCI interface for enumeration/configuration of roots.
-        */
-
-       mutex_lock(&acpi_pci_root_lock);
-       list_add_tail(&root->node, &acpi_pci_roots);
-       mutex_unlock(&acpi_pci_root_lock);
-
        printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
               acpi_device_name(device), acpi_device_bid(device),
               root->segment, &root->secondary);
 
-       /*
-        * Scan the Root Bridge
-        * --------------------
-        * Must do this prior to any attempt to bind the root device, as the
-        * PCI namespace does not get created until this call is made (and 
-        * thus the root bridge's pci_dev does not exist).
-        */
-       root->bus = pci_acpi_scan_root(root);
-       if (!root->bus) {
-               printk(KERN_ERR PREFIX
-                           "Bus %04x:%02x not present in PCI namespace\n",
-                           root->segment, (unsigned int)root->secondary.start);
-               result = -ENODEV;
-               goto out_del_root;
-       }
-
-       /*
-        * Attach ACPI-PCI Context
-        * -----------------------
-        * Thus binding the ACPI and PCI devices.
-        */
-       result = acpi_pci_bind_root(device);
-       if (result)
-               goto out_del_root;
-
        /*
         * PCI Routing Table
         * -----------------
@@ -554,32 +513,36 @@ static int acpi_pci_root_add(struct acpi_device *device)
         */
        status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
        if (ACPI_SUCCESS(status))
-               result = acpi_pci_irq_add_prt(device->handle, root->bus);
+               result = acpi_pci_irq_add_prt(device->handle, root->segment,
+                                             root->secondary.start);
+
+       root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
        /*
-        * Scan and bind all _ADR-Based Devices
+        * All supported architectures that use ACPI have support for
+        * PCI domains, so we indicate this in _OSC support capabilities.
         */
-       list_for_each_entry(child, &device->children, node)
-               acpi_pci_bridge_scan(child);
+       flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+       acpi_pci_osc_support(root, flags);
 
        /* Indicate support for various _OSC capabilities. */
-       if (pci_ext_cfg_avail(root->bus->self))
+       if (pci_ext_cfg_avail())
                flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
-       if (pcie_aspm_support_enabled())
+       if (pcie_aspm_support_enabled()) {
                flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
-                       OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+               OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+       }
        if (pci_msi_enabled())
                flags |= OSC_MSI_SUPPORT;
        if (flags != base_flags) {
                status = acpi_pci_osc_support(root, flags);
                if (ACPI_FAILURE(status)) {
-                       dev_info(root->bus->bridge, "ACPI _OSC support "
+                       dev_info(&device->dev, "ACPI _OSC support "
                                "notification failed, disabling PCIe ASPM\n");
                        pcie_no_aspm();
                        flags = base_flags;
                }
        }
-
        if (!pcie_ports_disabled
            && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
                flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -588,40 +551,81 @@ static int acpi_pci_root_add(struct acpi_device *device)
 
                if (pci_aer_available()) {
                        if (aer_acpi_firmware_first())
-                               dev_dbg(root->bus->bridge,
+                               dev_dbg(&device->dev,
                                        "PCIe errors handled by BIOS.\n");
                        else
                                flags |= OSC_PCI_EXPRESS_AER_CONTROL;
                }
 
-               dev_info(root->bus->bridge,
+               dev_info(&device->dev,
                        "Requesting ACPI _OSC control (0x%02x)\n", flags);
 
                status = acpi_pci_osc_control_set(device->handle, &flags,
-                                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+                                      OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
                if (ACPI_SUCCESS(status)) {
-                       dev_info(root->bus->bridge,
+                       is_osc_granted = true;
+                       dev_info(&device->dev,
                                "ACPI _OSC control (0x%02x) granted\n", flags);
-                       if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
-                               /*
-                                * We have ASPM control, but the FADT indicates
-                                * that it's unsupported. Clear it.
-                                */
-                               pcie_clear_aspm(root->bus);
-                       }
                } else {
-                       dev_info(root->bus->bridge,
+                       is_osc_granted = false;
+                       dev_info(&device->dev,
                                "ACPI _OSC request failed (%s), "
                                "returned control mask: 0x%02x\n",
                                acpi_format_exception(status), flags);
-                       pr_info("ACPI _OSC control for PCIe not granted, "
-                               "disabling ASPM\n");
-                       pcie_no_aspm();
                }
        } else {
-               dev_info(root->bus->bridge,
-                        "Unable to request _OSC control "
-                        "(_OSC support mask: 0x%02x)\n", flags);
+               dev_info(&device->dev,
+                       "Unable to request _OSC control "
+                       "(_OSC support mask: 0x%02x)\n", flags);
+       }
+
+       /*
+        * TBD: Need PCI interface for enumeration/configuration of roots.
+        */
+
+       mutex_lock(&acpi_pci_root_lock);
+       list_add_tail(&root->node, &acpi_pci_roots);
+       mutex_unlock(&acpi_pci_root_lock);
+
+       /*
+        * Scan the Root Bridge
+        * --------------------
+        * Must do this prior to any attempt to bind the root device, as the
+        * PCI namespace does not get created until this call is made (and 
+        * thus the root bridge's pci_dev does not exist).
+        */
+       root->bus = pci_acpi_scan_root(root);
+       if (!root->bus) {
+               printk(KERN_ERR PREFIX
+                           "Bus %04x:%02x not present in PCI namespace\n",
+                           root->segment, (unsigned int)root->secondary.start);
+               result = -ENODEV;
+               goto out_del_root;
+       }
+
+       /*
+        * Attach ACPI-PCI Context
+        * -----------------------
+        * Thus binding the ACPI and PCI devices.
+        */
+       result = acpi_pci_bind_root(device);
+       if (result)
+               goto out_del_root;
+
+       /*
+        * Scan and bind all _ADR-Based Devices
+        */
+       list_for_each_entry(child, &device->children, node)
+               acpi_pci_bridge_scan(child);
+
+       /* ASPM setting */
+       if (is_osc_granted) {
+               if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
+                       pcie_clear_aspm(root->bus);
+       } else {
+               pr_info("ACPI _OSC control for PCIe not granted, "
+                       "disabling ASPM\n");
+               pcie_no_aspm();
        }
 
        pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -634,6 +638,8 @@ out_del_root:
        mutex_lock(&acpi_pci_root_lock);
        list_del(&root->node);
        mutex_unlock(&acpi_pci_root_lock);
+
+       acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
        kfree(root);
        return result;
@@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device)
        struct acpi_pci_root *root = acpi_driver_data(device);
        struct acpi_pci_driver *driver;
 
+       if (system_state != SYSTEM_BOOTING)
+               pci_assign_unassigned_bus_resources(root->bus);
+
        mutex_lock(&acpi_pci_root_lock);
        list_for_each_entry(driver, &acpi_pci_drivers, node)
                if (driver->add)
                        driver->add(root);
        mutex_unlock(&acpi_pci_root_lock);
 
+       /* need to after hot-added ioapic is registered */
+       if (system_state != SYSTEM_BOOTING)
+               pci_enable_bridges(root->bus);
+
        pci_bus_add_devices(root->bus);
 
        return 0;
@@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device)
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
+       acpi_status status;
+       acpi_handle handle;
        struct acpi_pci_root *root = acpi_driver_data(device);
        struct acpi_pci_driver *driver;
 
+       pci_stop_root_bus(root->bus);
+
        mutex_lock(&acpi_pci_root_lock);
-       list_for_each_entry(driver, &acpi_pci_drivers, node)
+       list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
                if (driver->remove)
                        driver->remove(root);
+       mutex_unlock(&acpi_pci_root_lock);
 
        device_set_run_wake(root->bus->bridge, false);
        pci_acpi_remove_bus_pm_notifier(device);
 
+       status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
+       if (ACPI_SUCCESS(status))
+               acpi_pci_irq_del_prt(root->segment, root->secondary.start);
+
+       pci_remove_root_bus(root->bus);
+
+       mutex_lock(&acpi_pci_root_lock);
        list_del(&root->node);
        mutex_unlock(&acpi_pci_root_lock);
        kfree(root);
index b7078afddb74fe91c403642cf4679beec06c0ef9..1cc467bdb63d9e4b456743452c5168e606db79f2 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/ahci_platform.h>
 #include "ahci.h"
 
+static void ahci_host_stop(struct ata_host *host);
+
 enum ahci_type {
        AHCI,           /* standard platform ahci */
        IMX53_AHCI,     /* ahci on i.mx53 */
@@ -47,6 +49,15 @@ static struct platform_device_id ahci_devtype[] = {
 };
 MODULE_DEVICE_TABLE(platform, ahci_devtype);
 
+static struct ata_port_operations ahci_platform_ops = {
+       .inherits       = &ahci_ops,
+       .host_stop      = ahci_host_stop,
+};
+
+static struct ata_port_operations ahci_platform_retry_srst_ops = {
+       .inherits       = &ahci_pmp_retry_srst_ops,
+       .host_stop      = ahci_host_stop,
+};
 
 static const struct ata_port_info ahci_port_info[] = {
        /* by features */
@@ -54,20 +65,20 @@ static const struct ata_port_info ahci_port_info[] = {
                .flags          = AHCI_FLAG_COMMON,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
-               .port_ops       = &ahci_ops,
+               .port_ops       = &ahci_platform_ops,
        },
        [IMX53_AHCI] = {
                .flags          = AHCI_FLAG_COMMON,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
-               .port_ops       = &ahci_pmp_retry_srst_ops,
+               .port_ops       = &ahci_platform_retry_srst_ops,
        },
        [STRICT_AHCI] = {
                AHCI_HFLAGS     (AHCI_HFLAG_DELAY_ENGINE),
                .flags          = AHCI_FLAG_COMMON,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
-               .port_ops       = &ahci_ops,
+               .port_ops       = &ahci_platform_ops,
        },
 };
 
@@ -75,7 +86,7 @@ static struct scsi_host_template ahci_platform_sht = {
        AHCI_SHT("ahci_platform"),
 };
 
-static int __init ahci_probe(struct platform_device *pdev)
+static int __devinit ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
@@ -218,15 +229,12 @@ free_clk:
        return rc;
 }
 
-static int __devexit ahci_remove(struct platform_device *pdev)
+static void ahci_host_stop(struct ata_host *host)
 {
-       struct device *dev = &pdev->dev;
+       struct device *dev = host->dev;
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
-       struct ata_host *host = dev_get_drvdata(dev);
        struct ahci_host_priv *hpriv = host->private_data;
 
-       ata_host_detach(host);
-
        if (pdata && pdata->exit)
                pdata->exit(dev);
 
@@ -234,8 +242,6 @@ static int __devexit ahci_remove(struct platform_device *pdev)
                clk_disable_unprepare(hpriv->clk);
                clk_put(hpriv->clk);
        }
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -317,7 +323,7 @@ disable_unprepare_clk:
 }
 #endif
 
-SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
 
 static const struct of_device_id ahci_of_match[] = {
        { .compatible = "snps,spear-ahci", },
@@ -326,7 +332,8 @@ static const struct of_device_id ahci_of_match[] = {
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
 static struct platform_driver ahci_driver = {
-       .remove = __devexit_p(ahci_remove),
+       .probe = ahci_probe,
+       .remove = ata_platform_remove_one,
        .driver = {
                .name = "ahci",
                .owner = THIS_MODULE,
@@ -335,18 +342,7 @@ static struct platform_driver ahci_driver = {
        },
        .id_table       = ahci_devtype,
 };
-
-static int __init ahci_init(void)
-{
-       return platform_driver_probe(&ahci_driver, ahci_probe);
-}
-module_init(ahci_init);
-
-static void __exit ahci_exit(void)
-{
-       platform_driver_unregister(&ahci_driver);
-}
-module_exit(ahci_exit);
+module_platform_driver(ahci_driver);
 
 MODULE_DESCRIPTION("AHCI SATA platform driver");
 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
index ef773e12af79d2c931e37852e7c31b716a00e51e..acffcf0b3ad3345f00563fbe2a1fdb018e96deaf 100644 (file)
@@ -164,28 +164,6 @@ struct piix_host_priv {
        void __iomem *sidpr;
 };
 
-static int piix_init_one(struct pci_dev *pdev,
-                        const struct pci_device_id *ent);
-static void piix_remove_one(struct pci_dev *pdev);
-static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
-static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
-static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
-static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
-static int ich_pata_cable_detect(struct ata_port *ap);
-static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-static int piix_sidpr_scr_read(struct ata_link *link,
-                              unsigned int reg, u32 *val);
-static int piix_sidpr_scr_write(struct ata_link *link,
-                               unsigned int reg, u32 val);
-static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
-                             unsigned hints);
-static bool piix_irq_check(struct ata_port *ap);
-static int piix_port_start(struct ata_port *ap);
-#ifdef CONFIG_PM
-static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
-static int piix_pci_device_resume(struct pci_dev *pdev);
-#endif
-
 static unsigned int in_module_init = 1;
 
 static const struct pci_device_id piix_pci_tbl[] = {
@@ -342,64 +320,6 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { }     /* terminate list */
 };
 
-static struct pci_driver piix_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = piix_pci_tbl,
-       .probe                  = piix_init_one,
-       .remove                 = piix_remove_one,
-#ifdef CONFIG_PM
-       .suspend                = piix_pci_device_suspend,
-       .resume                 = piix_pci_device_resume,
-#endif
-};
-
-static struct scsi_host_template piix_sht = {
-       ATA_BMDMA_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations piix_sata_ops = {
-       .inherits               = &ata_bmdma32_port_ops,
-       .sff_irq_check          = piix_irq_check,
-       .port_start             = piix_port_start,
-};
-
-static struct ata_port_operations piix_pata_ops = {
-       .inherits               = &piix_sata_ops,
-       .cable_detect           = ata_cable_40wire,
-       .set_piomode            = piix_set_piomode,
-       .set_dmamode            = piix_set_dmamode,
-       .prereset               = piix_pata_prereset,
-};
-
-static struct ata_port_operations piix_vmw_ops = {
-       .inherits               = &piix_pata_ops,
-       .bmdma_status           = piix_vmw_bmdma_status,
-};
-
-static struct ata_port_operations ich_pata_ops = {
-       .inherits               = &piix_pata_ops,
-       .cable_detect           = ich_pata_cable_detect,
-       .set_dmamode            = ich_set_dmamode,
-};
-
-static struct device_attribute *piix_sidpr_shost_attrs[] = {
-       &dev_attr_link_power_management_policy,
-       NULL
-};
-
-static struct scsi_host_template piix_sidpr_sht = {
-       ATA_BMDMA_SHT(DRV_NAME),
-       .shost_attrs            = piix_sidpr_shost_attrs,
-};
-
-static struct ata_port_operations piix_sidpr_sata_ops = {
-       .inherits               = &piix_sata_ops,
-       .hardreset              = sata_std_hardreset,
-       .scr_read               = piix_sidpr_scr_read,
-       .scr_write              = piix_sidpr_scr_write,
-       .set_lpm                = piix_sidpr_set_lpm,
-};
-
 static const struct piix_map_db ich5_map_db = {
        .mask = 0x7,
        .port_enable = 0x3,
@@ -504,147 +424,6 @@ static const struct piix_map_db *piix_map_db_table[] = {
        [ich8_sata_snb]         = &ich8_map_db,
 };
 
-static struct ata_port_info piix_port_info[] = {
-       [piix_pata_mwdma] =     /* PIIX3 MWDMA only */
-       {
-               .flags          = PIIX_PATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-               .port_ops       = &piix_pata_ops,
-       },
-
-       [piix_pata_33] =        /* PIIX4 at 33MHz */
-       {
-               .flags          = PIIX_PATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-               .udma_mask      = ATA_UDMA2,
-               .port_ops       = &piix_pata_ops,
-       },
-
-       [ich_pata_33] =         /* ICH0 - ICH at 33Mhz*/
-       {
-               .flags          = PIIX_PATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */
-               .udma_mask      = ATA_UDMA2,
-               .port_ops       = &ich_pata_ops,
-       },
-
-       [ich_pata_66] =         /* ICH controllers up to 66MHz */
-       {
-               .flags          = PIIX_PATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */
-               .udma_mask      = ATA_UDMA4,
-               .port_ops       = &ich_pata_ops,
-       },
-
-       [ich_pata_100] =
-       {
-               .flags          = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA12_ONLY,
-               .udma_mask      = ATA_UDMA5,
-               .port_ops       = &ich_pata_ops,
-       },
-
-       [ich_pata_100_nomwdma1] =
-       {
-               .flags          = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2_ONLY,
-               .udma_mask      = ATA_UDMA5,
-               .port_ops       = &ich_pata_ops,
-       },
-
-       [ich5_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [ich6_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [ich6m_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [ich8_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [ich8_2port_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [tolapai_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [ich8m_apple_sata] =
-       {
-               .flags          = PIIX_SATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-       [piix_pata_vmw] =
-       {
-               .flags          = PIIX_PATA_FLAGS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-               .udma_mask      = ATA_UDMA2,
-               .port_ops       = &piix_vmw_ops,
-       },
-
-       /*
-        * some Sandybridge chipsets have broken 32 mode up to now,
-        * see https://bugzilla.kernel.org/show_bug.cgi?id=40592
-        */
-       [ich8_sata_snb] =
-       {
-               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &piix_sata_ops,
-       },
-
-};
-
 static struct pci_bits piix_enable_bits[] = {
        { 0x41U, 1U, 0x80UL, 0x80UL },  /* port 0 */
        { 0x43U, 1U, 0x80UL, 0x80UL },  /* port 1 */
@@ -1261,6 +1040,193 @@ static u8 piix_vmw_bmdma_status(struct ata_port *ap)
        return ata_bmdma_status(ap) & ~ATA_DMA_ERR;
 }
 
+static struct scsi_host_template piix_sht = {
+       ATA_BMDMA_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations piix_sata_ops = {
+       .inherits               = &ata_bmdma32_port_ops,
+       .sff_irq_check          = piix_irq_check,
+       .port_start             = piix_port_start,
+};
+
+static struct ata_port_operations piix_pata_ops = {
+       .inherits               = &piix_sata_ops,
+       .cable_detect           = ata_cable_40wire,
+       .set_piomode            = piix_set_piomode,
+       .set_dmamode            = piix_set_dmamode,
+       .prereset               = piix_pata_prereset,
+};
+
+static struct ata_port_operations piix_vmw_ops = {
+       .inherits               = &piix_pata_ops,
+       .bmdma_status           = piix_vmw_bmdma_status,
+};
+
+static struct ata_port_operations ich_pata_ops = {
+       .inherits               = &piix_pata_ops,
+       .cable_detect           = ich_pata_cable_detect,
+       .set_dmamode            = ich_set_dmamode,
+};
+
+static struct device_attribute *piix_sidpr_shost_attrs[] = {
+       &dev_attr_link_power_management_policy,
+       NULL
+};
+
+static struct scsi_host_template piix_sidpr_sht = {
+       ATA_BMDMA_SHT(DRV_NAME),
+       .shost_attrs            = piix_sidpr_shost_attrs,
+};
+
+static struct ata_port_operations piix_sidpr_sata_ops = {
+       .inherits               = &piix_sata_ops,
+       .hardreset              = sata_std_hardreset,
+       .scr_read               = piix_sidpr_scr_read,
+       .scr_write              = piix_sidpr_scr_write,
+       .set_lpm                = piix_sidpr_set_lpm,
+};
+
+static struct ata_port_info piix_port_info[] = {
+       [piix_pata_mwdma] =     /* PIIX3 MWDMA only */
+       {
+               .flags          = PIIX_PATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+               .port_ops       = &piix_pata_ops,
+       },
+
+       [piix_pata_33] =        /* PIIX4 at 33MHz */
+       {
+               .flags          = PIIX_PATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+               .udma_mask      = ATA_UDMA2,
+               .port_ops       = &piix_pata_ops,
+       },
+
+       [ich_pata_33] =         /* ICH0 - ICH at 33Mhz*/
+       {
+               .flags          = PIIX_PATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */
+               .udma_mask      = ATA_UDMA2,
+               .port_ops       = &ich_pata_ops,
+       },
+
+       [ich_pata_66] =         /* ICH controllers up to 66MHz */
+       {
+               .flags          = PIIX_PATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */
+               .udma_mask      = ATA_UDMA4,
+               .port_ops       = &ich_pata_ops,
+       },
+
+       [ich_pata_100] =
+       {
+               .flags          = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA12_ONLY,
+               .udma_mask      = ATA_UDMA5,
+               .port_ops       = &ich_pata_ops,
+       },
+
+       [ich_pata_100_nomwdma1] =
+       {
+               .flags          = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2_ONLY,
+               .udma_mask      = ATA_UDMA5,
+               .port_ops       = &ich_pata_ops,
+       },
+
+       [ich5_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [ich6_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [ich6m_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [ich8_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [ich8_2port_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [tolapai_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [ich8m_apple_sata] =
+       {
+               .flags          = PIIX_SATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
+       [piix_pata_vmw] =
+       {
+               .flags          = PIIX_PATA_FLAGS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+               .udma_mask      = ATA_UDMA2,
+               .port_ops       = &piix_vmw_ops,
+       },
+
+       /*
+        * some Sandybridge chipsets have broken 32 mode up to now,
+        * see https://bugzilla.kernel.org/show_bug.cgi?id=40592
+        */
+       [ich8_sata_snb] =
+       {
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+};
+
 #define AHCI_PCI_BAR 5
 #define AHCI_GLOBAL_CTL 0x04
 #define AHCI_ENABLE (1 << 31)
@@ -1585,12 +1551,31 @@ static void piix_ignore_devices_quirk(struct ata_host *host)
                },
                { }     /* terminate list */
        };
-       const struct dmi_system_id *dmi = dmi_first_match(ignore_hyperv);
+       static const struct dmi_system_id allow_virtual_pc[] = {
+               {
+                       /* In MS Virtual PC guests the DMI ident is nearly
+                        * identical to a Hyper-V guest. One difference is the
+                        * product version which is used here to identify
+                        * a Virtual PC guest. This entry allows ata_piix to
+                        * drive the emulated hardware.
+                        */
+                       .ident = "MS Virtual PC 2007",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR,
+                                               "Microsoft Corporation"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+                               DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
+                       },
+               },
+               { }     /* terminate list */
+       };
+       const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv);
+       const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc);
 
-       if (dmi && prefer_ms_hyperv) {
+       if (ignore && !allow && prefer_ms_hyperv) {
                host->flags |= ATA_HOST_IGNORE_ATA;
                dev_info(host->dev, "%s detected, ATA device ignore set\n",
-                       dmi->ident);
+                       ignore->ident);
        }
 #endif
 }
@@ -1727,6 +1712,17 @@ static void piix_remove_one(struct pci_dev *pdev)
        ata_pci_remove_one(pdev);
 }
 
+static struct pci_driver piix_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = piix_pci_tbl,
+       .probe                  = piix_init_one,
+       .remove                 = piix_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = piix_pci_device_suspend,
+       .resume                 = piix_pci_device_resume,
+#endif
+};
+
 static int __init piix_init(void)
 {
        int rc;
index 4201e535a8c897ce0acf5912f569f6c74448e7ec..320712a7b9eaac3174f3a96de8693b63dee5f1af 100644 (file)
@@ -1384,7 +1384,7 @@ int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
        if (rc == -EIO) {
                irq_sts = readl(port_mmio + PORT_IRQ_STAT);
                if (irq_sts & PORT_IRQ_BAD_PMP) {
-                       ata_link_printk(link, KERN_WARNING,
+                       ata_link_warn(link,
                                        "applying PMP SRST workaround "
                                        "and retrying\n");
                        rc = ahci_do_softreset(link, class, 0, deadline,
index 5b0ba3f20edcfd4603538ce7505d69dd93f8bb29..ef01ac07502e54625cbf02b7ae7ff11322f5c245 100644 (file)
@@ -76,6 +76,9 @@ acpi_handle ata_dev_acpi_handle(struct ata_device *dev)
        acpi_integer adr;
        struct ata_port *ap = dev->link->ap;
 
+       if (dev->flags & ATA_DFLAG_ACPI_DISABLED)
+               return NULL;
+
        if (ap->flags & ATA_FLAG_ACPI_SATA) {
                if (!sata_pmp_attached(ap))
                        adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
@@ -945,6 +948,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
                return rc;
        }
 
+       dev->flags |= ATA_DFLAG_ACPI_DISABLED;
        ata_dev_warn(dev, "ACPI: failed the second time, disabled\n");
 
        /* We can safely continue if no _GTF command has been executed
index f46fbd3bd3fb6b4456032a0255bad894e8fc9cdb..9e8b99af400dc53539ba4e8d45d36696e4818b65 100644 (file)
@@ -67,6 +67,7 @@
 #include <linux/cdrom.h>
 #include <linux/ratelimit.h>
 #include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
 
 #include "libata.h"
 #include "libata-transport.h"
@@ -2560,6 +2561,7 @@ int ata_bus_probe(struct ata_port *ap)
                 * bus as we may be talking too fast.
                 */
                dev->pio_mode = XFER_PIO_0;
+               dev->dma_mode = 0xff;
 
                /* If the controller has a pio mode setup function
                 * then use it to set the chipset to rights. Don't
@@ -6286,8 +6288,7 @@ void ata_host_detach(struct ata_host *host)
  */
 void ata_pci_remove_one(struct pci_dev *pdev)
 {
-       struct device *dev = &pdev->dev;
-       struct ata_host *host = dev_get_drvdata(dev);
+       struct ata_host *host = pci_get_drvdata(pdev);
 
        ata_host_detach(host);
 }
@@ -6356,7 +6357,7 @@ int ata_pci_device_do_resume(struct pci_dev *pdev)
 
 int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
-       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       struct ata_host *host = pci_get_drvdata(pdev);
        int rc = 0;
 
        rc = ata_host_suspend(host, mesg);
@@ -6370,7 +6371,7 @@ int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 
 int ata_pci_device_resume(struct pci_dev *pdev)
 {
-       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       struct ata_host *host = pci_get_drvdata(pdev);
        int rc;
 
        rc = ata_pci_device_do_resume(pdev);
@@ -6382,6 +6383,26 @@ int ata_pci_device_resume(struct pci_dev *pdev)
 
 #endif /* CONFIG_PCI */
 
+/**
+ *     ata_platform_remove_one - Platform layer callback for device removal
+ *     @pdev: Platform device that was removed
+ *
+ *     Platform layer indicates to libata via this hook that hot-unplug or
+ *     module unload event has occurred.  Detach all ports.  Resource
+ *     release is handled via devres.
+ *
+ *     LOCKING:
+ *     Inherited from platform layer (may sleep).
+ */
+int ata_platform_remove_one(struct platform_device *pdev)
+{
+       struct ata_host *host = platform_get_drvdata(pdev);
+
+       ata_host_detach(host);
+
+       return 0;
+}
+
 static int __init ata_parse_force_one(char **cur,
                                      struct ata_force_ent *force_ent,
                                      const char **reason)
@@ -6877,6 +6898,8 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume);
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PCI */
 
+EXPORT_SYMBOL_GPL(ata_platform_remove_one);
+
 EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);
 EXPORT_SYMBOL_GPL(ata_ehi_push_desc);
 EXPORT_SYMBOL_GPL(ata_ehi_clear_desc);
index e60437cd0d192efeb68ffdb93c7e0fd0a0f62423..bf039b0e97b79d7f9c9d2bae803ad84850b181b4 100644 (file)
@@ -2657,6 +2657,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
                 * bus as we may be talking too fast.
                 */
                dev->pio_mode = XFER_PIO_0;
+               dev->dma_mode = 0xff;
 
                /* If the controller has a pio mode setup function
                 * then use it to set the chipset to rights. Don't
index a6df6a351d6e4ce263f717ad52bf1ebb72a1aae0..7c337e754dab30cf63c1b8a8b28c416f535bd86f 100644 (file)
@@ -309,7 +309,8 @@ ata_scsi_activity_show(struct device *dev, struct device_attribute *attr,
        struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct ata_device *atadev = ata_scsi_find_dev(ap, sdev);
 
-       if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY))
+       if (atadev && ap->ops->sw_activity_show &&
+           (ap->flags & ATA_FLAG_SW_ACTIVITY))
                return ap->ops->sw_activity_show(atadev, buf);
        return -EINVAL;
 }
@@ -324,7 +325,8 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,
        enum sw_activity val;
        int rc;
 
-       if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) {
+       if (atadev && ap->ops->sw_activity_store &&
+           (ap->flags & ATA_FLAG_SW_ACTIVITY)) {
                val = simple_strtoul(buf, NULL, 0);
                switch (val) {
                case OFF: case BLINK_ON: case BLINK_OFF:
index 371fd2c698b70ce1b283672c0c2472f8ce6ac263..9764e80f93202bb6d75811885f07bbf98f0f8929 100644 (file)
@@ -674,13 +674,16 @@ void arasan_cf_error_handler(struct ata_port *ap)
 
 static void arasan_cf_dma_start(struct arasan_cf_dev *acdev)
 {
+       struct ata_queued_cmd *qc = acdev->qc;
+       struct ata_port *ap = qc->ap;
+       struct ata_taskfile *tf = &qc->tf;
        u32 xfer_ctr = readl(acdev->vbase + XFER_CTR) & ~XFER_DIR_MASK;
-       u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+       u32 write = tf->flags & ATA_TFLAG_WRITE;
 
        xfer_ctr |= write ? XFER_WRITE : XFER_READ;
        writel(xfer_ctr, acdev->vbase + XFER_CTR);
 
-       acdev->qc->ap->ops->sff_exec_command(acdev->qc->ap, &acdev->qc->tf);
+       ap->ops->sff_exec_command(ap, tf);
        ata_sff_queue_work(&acdev->work);
 }
 
index 7ba01415b676d89dc2e18e68c5f949bd81dd3453..2949cfc2dd31ab9c234c55cf706c09f8e6848573 100644 (file)
@@ -474,14 +474,14 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        /* check for enabled ports */
        pci_read_config_byte(pdev, CNTRL, &reg);
        if (!port_ok)
-               dev_printk(KERN_NOTICE, &pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
+               dev_notice(&pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
        if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
-               dev_printk(KERN_NOTICE, &pdev->dev, "Primary port is disabled\n");
+               dev_notice(&pdev->dev, "Primary port is disabled\n");
                ppi[0] = &ata_dummy_port_info;
 
        }
        if (port_ok && !(reg & CNTRL_CH1)) {
-               dev_printk(KERN_NOTICE, &pdev->dev, "Secondary port is disabled\n");
+               dev_notice(&pdev->dev, "Secondary port is disabled\n");
                ppi[1] = &ata_dummy_port_info;
        }
 
index dec1b6c4b351244b4da8326d982f4c3bd859fec4..0448860a2077526cea30354fc60b6c6c3cacada9 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86_32
 #include <asm/msr.h>
@@ -80,6 +81,21 @@ enum {
        IDE_ETC_UDMA_MASK       = 0xc0,
 };
 
+/* Some Bachmann OT200 devices have a non working UDMA support due a
+ * missing resistor.
+ */
+static const struct dmi_system_id udma_quirk_dmi_table[] = {
+       {
+               .ident = "Bachmann electronic OT200",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Bachmann electronic"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "OT200"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1")
+               },
+       },
+       { }
+};
+
 static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
 {
        if (unlikely(use_msr)) {
@@ -242,9 +258,23 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                .port_ops = &cs5536_port_ops,
        };
 
-       const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+       static const struct ata_port_info no_udma_info = {
+               .flags = ATA_FLAG_SLAVE_POSS,
+               .pio_mask = ATA_PIO4,
+               .port_ops = &cs5536_port_ops,
+       };
+
+
+       const struct ata_port_info *ppi[2];
        u32 cfg;
 
+       if (dmi_check_system(udma_quirk_dmi_table))
+               ppi[0] = &no_udma_info;
+       else
+               ppi[0] = &info;
+
+       ppi[1] = &ata_dummy_port_info;
+
        if (use_msr)
                printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n");
 
index e056406d6a11eb7ed7cf990f962cdc216d1e53d8..3982cef91f3c2da4c7b505c321bb081c98bf9e93 100644 (file)
@@ -822,8 +822,7 @@ static int ep93xx_pata_softreset(struct ata_link *al, unsigned int *classes,
        rc = ep93xx_pata_bus_softreset(ap, devmask, deadline);
        /* if link is ocuppied, -ENODEV too is an error */
        if (rc && (rc != -ENODEV || sata_scr_valid(al))) {
-               ata_link_printk(al, KERN_ERR, "SRST failed (errno=%d)\n",
-                               rc);
+               ata_link_err(al, "SRST failed (errno=%d)\n", rc);
                return rc;
        }
 
@@ -857,8 +856,7 @@ static void ep93xx_pata_drain_fifo(struct ata_queued_cmd *qc)
 
        /* Can become DEBUG later */
        if (count)
-               ata_port_printk(ap, KERN_DEBUG,
-                               "drained %d bytes to clear DRQ.\n", count);
+               ata_port_dbg(ap, "drained %d bytes to clear DRQ.\n", count);
 
 }
 
index 87bb05b3cafc965fd242d228c04c83322a09db32..7d40b526ef118761194e0ea9a428432e9a1668d3 100644 (file)
@@ -60,7 +60,7 @@ static int pata_imx_set_mode(struct ata_link *link, struct ata_device **unused)
                        val &= ~PATA_IMX_ATA_CTRL_IORDY_EN;
                __raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL);
 
-               ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+               ata_dev_info(dev, "configured for PIO\n");
        }
        return 0;
 }
index badb1789a918a21c027ee0d5b0b0610eb7bd2340..0566e67b5e125b744d1a34ff897aef4564175186 100644 (file)
@@ -187,22 +187,13 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
        return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
 }
 
-static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
-{
-       struct ata_host *host = platform_get_drvdata(dev);
-
-       ata_host_detach(host);
-
-       return 0;
-}
-
 static struct platform_driver ixp4xx_pata_platform_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
        },
        .probe          = ixp4xx_pata_probe,
-       .remove         = __devexit_p(ixp4xx_pata_remove),
+       .remove         = ata_platform_remove_one,
 };
 
 module_platform_driver(ixp4xx_pata_platform_driver);
index d2c102fd433062618e4206a3eff778a62a4587a2..ec67f54dc56f5ae4360f27330fe0fa19b0972fe2 100644 (file)
@@ -663,18 +663,6 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
                                 &mpc52xx_ata_sht);
 }
 
-static struct mpc52xx_ata_priv *
-mpc52xx_ata_remove_one(struct device *dev)
-{
-       struct ata_host *host = dev_get_drvdata(dev);
-       struct mpc52xx_ata_priv *priv = host->private_data;
-
-       ata_host_detach(host);
-
-       return priv;
-}
-
-
 /* ======================================================================== */
 /* OF Platform driver                                                       */
 /* ======================================================================== */
@@ -815,11 +803,12 @@ mpc52xx_ata_probe(struct platform_device *op)
 static int
 mpc52xx_ata_remove(struct platform_device *op)
 {
-       struct mpc52xx_ata_priv *priv;
+       struct ata_host *host = platform_get_drvdata(op);
+       struct mpc52xx_ata_priv *priv = host->private_data;
        int task_irq;
 
        /* Deregister the ATA interface */
-       priv = mpc52xx_ata_remove_one(&op->dev);
+       ata_platform_remove_one(op);
 
        /* Clean up DMA */
        task_irq = bcom_get_task_irq(priv->dmatsk);
index 1d61d5d278fa4412130d7dcd1336cd45bc9662aa..4e1194b4c27128a9c6cb0671552ffaba4f97c681 100644 (file)
@@ -5,19 +5,22 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005 - 2009 Cavium Networks
+ * Copyright (C) 2005 - 2012 Cavium Inc.
  * Copyright (C) 2008 Wind River Systems
  */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/libata.h>
-#include <linux/irq.h>
+#include <linux/hrtimer.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
-#include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
 
+#include <asm/byteorder.h>
 #include <asm/octeon/octeon.h>
 
 /*
  */
 
 #define DRV_NAME       "pata_octeon_cf"
-#define DRV_VERSION    "2.1"
+#define DRV_VERSION    "2.2"
+
+/* Poll interval in nS. */
+#define OCTEON_CF_BUSY_POLL_INTERVAL 500000
 
+#define DMA_CFG 0
+#define DMA_TIM 0x20
+#define DMA_INT 0x38
+#define DMA_INT_EN 0x50
 
 struct octeon_cf_port {
-       struct workqueue_struct *wq;
-       struct delayed_work delayed_finish;
+       struct hrtimer delayed_finish;
        struct ata_port *ap;
        int dma_finished;
+       void            *c0;
+       unsigned int cs0;
+       unsigned int cs1;
+       bool is_true_ide;
+       u64 dma_base;
 };
 
 static struct scsi_host_template octeon_cf_sht = {
        ATA_PIO_SHT(DRV_NAME),
 };
 
+static int enable_dma;
+module_param(enable_dma, int, 0444);
+MODULE_PARM_DESC(enable_dma,
+                "Enable use of DMA on interfaces that support it (0=no dma [default], 1=use dma)");
+
 /**
  * Convert nanosecond based time to setting used in the
  * boot bus timing register, based on timing multiple
@@ -66,12 +85,29 @@ static unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs)
        return val;
 }
 
-static void octeon_cf_set_boot_reg_cfg(int cs)
+static void octeon_cf_set_boot_reg_cfg(int cs, unsigned int multiplier)
 {
        union cvmx_mio_boot_reg_cfgx reg_cfg;
+       unsigned int tim_mult;
+
+       switch (multiplier) {
+       case 8:
+               tim_mult = 3;
+               break;
+       case 4:
+               tim_mult = 0;
+               break;
+       case 2:
+               tim_mult = 2;
+               break;
+       default:
+               tim_mult = 1;
+               break;
+       }
+
        reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
        reg_cfg.s.dmack = 0;    /* Don't assert DMACK on access */
-       reg_cfg.s.tim_mult = 2; /* Timing mutiplier 2x */
+       reg_cfg.s.tim_mult = tim_mult;  /* Timing mutiplier */
        reg_cfg.s.rd_dly = 0;   /* Sample on falling edge of BOOT_OE */
        reg_cfg.s.sam = 0;      /* Don't combine write and output enable */
        reg_cfg.s.we_ext = 0;   /* No write enable extension */
@@ -92,12 +128,12 @@ static void octeon_cf_set_boot_reg_cfg(int cs)
  */
 static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
 {
-       struct octeon_cf_data *ocd = ap->dev->platform_data;
+       struct octeon_cf_port *cf_port = ap->private_data;
        union cvmx_mio_boot_reg_timx reg_tim;
-       int cs = ocd->base_region;
        int T;
        struct ata_timing timing;
 
+       unsigned int div;
        int use_iordy;
        int trh;
        int pause;
@@ -106,7 +142,15 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
        int t2;
        int t2i;
 
-       T = (int)(2000000000000LL / octeon_get_clock_rate());
+       /*
+        * A divisor value of four will overflow the timing fields at
+        * clock rates greater than 800MHz
+        */
+       if (octeon_get_io_clock_rate() <= 800000000)
+               div = 4;
+       else
+               div = 8;
+       T = (int)((1000000000000LL * div) / octeon_get_io_clock_rate());
 
        if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T))
                BUG();
@@ -121,23 +165,26 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
        if (t2i)
                t2i--;
 
-       trh = ns_to_tim_reg(2, 20);
+       trh = ns_to_tim_reg(div, 20);
        if (trh)
                trh--;
 
-       pause = timing.cycle - timing.active - timing.setup - trh;
+       pause = (int)timing.cycle - (int)timing.active -
+               (int)timing.setup - trh;
+       if (pause < 0)
+               pause = 0;
        if (pause)
                pause--;
 
-       octeon_cf_set_boot_reg_cfg(cs);
-       if (ocd->dma_engine >= 0)
+       octeon_cf_set_boot_reg_cfg(cf_port->cs0, div);
+       if (cf_port->is_true_ide)
                /* True IDE mode, program both chip selects.  */
-               octeon_cf_set_boot_reg_cfg(cs + 1);
+               octeon_cf_set_boot_reg_cfg(cf_port->cs1, div);
 
 
        use_iordy = ata_pio_need_iordy(dev);
 
-       reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cs));
+       reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0));
        /* Disable page mode */
        reg_tim.s.pagem = 0;
        /* Enable dynamic timing */
@@ -161,20 +208,22 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
        /* How long read enable is asserted */
        reg_tim.s.oe = t2;
        /* Time after CE that read/write starts */
-       reg_tim.s.ce = ns_to_tim_reg(2, 5);
+       reg_tim.s.ce = ns_to_tim_reg(div, 5);
        /* Time before CE that address is valid */
        reg_tim.s.adr = 0;
 
        /* Program the bootbus region timing for the data port chip select. */
-       cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs), reg_tim.u64);
-       if (ocd->dma_engine >= 0)
+       cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0), reg_tim.u64);
+       if (cf_port->is_true_ide)
                /* True IDE mode, program both chip selects.  */
-               cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs + 1), reg_tim.u64);
+               cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs1),
+                              reg_tim.u64);
 }
 
 static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)
 {
-       struct octeon_cf_data *ocd = dev->link->ap->dev->platform_data;
+       struct octeon_cf_port *cf_port = ap->private_data;
+       union cvmx_mio_boot_pin_defs pin_defs;
        union cvmx_mio_boot_dma_timx dma_tim;
        unsigned int oe_a;
        unsigned int oe_n;
@@ -183,6 +232,7 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)
        unsigned int pause;
        unsigned int T0, Tkr, Td;
        unsigned int tim_mult;
+       int c;
 
        const struct ata_timing *timing;
 
@@ -199,13 +249,19 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)
        /* not spec'ed, value in eclocks, not affected by tim_mult */
        dma_arq = 8;
        pause = 25 - dma_arq * 1000 /
-               (octeon_get_clock_rate() / 1000000); /* Tz */
+               (octeon_get_io_clock_rate() / 1000000); /* Tz */
 
        oe_a = Td;
        /* Tkr from cf spec, lengthened to meet T0 */
        oe_n = max(T0 - oe_a, Tkr);
 
-       dma_tim.s.dmack_pi = 1;
+       pin_defs.u64 = cvmx_read_csr(CVMX_MIO_BOOT_PIN_DEFS);
+
+       /* DMA channel number. */
+       c = (cf_port->dma_base & 8) >> 3;
+
+       /* Invert the polarity if the default is 0*/
+       dma_tim.s.dmack_pi = (pin_defs.u64 & (1ull << (11 + c))) ? 0 : 1;
 
        dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n);
        dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a);
@@ -228,14 +284,11 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)
 
        pr_debug("ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60,
                 ns_to_tim_reg(tim_mult, 60));
-       pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: "
-                "%d, dmarq: %d, pause: %d\n",
+       pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: %d, dmarq: %d, pause: %d\n",
                 dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s,
                 dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause);
 
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_TIMX(ocd->dma_engine),
-                      dma_tim.u64);
-
+       cvmx_write_csr(cf_port->dma_base + DMA_TIM, dma_tim.u64);
 }
 
 /**
@@ -489,15 +542,10 @@ static void octeon_cf_exec_command16(struct ata_port *ap,
        ata_wait_idle(ap);
 }
 
-static void octeon_cf_irq_on(struct ata_port *ap)
+static void octeon_cf_ata_port_noaction(struct ata_port *ap)
 {
 }
 
-static void octeon_cf_irq_clear(struct ata_port *ap)
-{
-       return;
-}
-
 static void octeon_cf_dma_setup(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
@@ -519,7 +567,7 @@ static void octeon_cf_dma_setup(struct ata_queued_cmd *qc)
  */
 static void octeon_cf_dma_start(struct ata_queued_cmd *qc)
 {
-       struct octeon_cf_data *ocd = qc->ap->dev->platform_data;
+       struct octeon_cf_port *cf_port = qc->ap->private_data;
        union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg;
        union cvmx_mio_boot_dma_intx mio_boot_dma_int;
        struct scatterlist *sg;
@@ -535,15 +583,16 @@ static void octeon_cf_dma_start(struct ata_queued_cmd *qc)
         */
        mio_boot_dma_int.u64 = 0;
        mio_boot_dma_int.s.done = 1;
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine),
-                      mio_boot_dma_int.u64);
+       cvmx_write_csr(cf_port->dma_base + DMA_INT, mio_boot_dma_int.u64);
 
        /* Enable the interrupt.  */
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine),
-                      mio_boot_dma_int.u64);
+       cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, mio_boot_dma_int.u64);
 
        /* Set the direction of the DMA */
        mio_boot_dma_cfg.u64 = 0;
+#ifdef __LITTLE_ENDIAN
+       mio_boot_dma_cfg.s.endian = 1;
+#endif
        mio_boot_dma_cfg.s.en = 1;
        mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0);
 
@@ -569,8 +618,7 @@ static void octeon_cf_dma_start(struct ata_queued_cmd *qc)
                (mio_boot_dma_cfg.s.rw) ? "write" : "read", sg->length,
                (void *)(unsigned long)mio_boot_dma_cfg.s.adr);
 
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine),
-                      mio_boot_dma_cfg.u64);
+       cvmx_write_csr(cf_port->dma_base + DMA_CFG, mio_boot_dma_cfg.u64);
 }
 
 /**
@@ -583,10 +631,9 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap,
                                        struct ata_queued_cmd *qc)
 {
        struct ata_eh_info *ehi = &ap->link.eh_info;
-       struct octeon_cf_data *ocd = ap->dev->platform_data;
+       struct octeon_cf_port *cf_port = ap->private_data;
        union cvmx_mio_boot_dma_cfgx dma_cfg;
        union cvmx_mio_boot_dma_intx dma_int;
-       struct octeon_cf_port *cf_port;
        u8 status;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
@@ -596,9 +643,7 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap,
        if (ap->hsm_task_state != HSM_ST_LAST)
                return 0;
 
-       cf_port = ap->private_data;
-
-       dma_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine));
+       dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG);
        if (dma_cfg.s.size != 0xfffff) {
                /* Error, the transfer was not complete.  */
                qc->err_mask |= AC_ERR_HOST_BUS;
@@ -608,15 +653,15 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap,
        /* Stop and clear the dma engine.  */
        dma_cfg.u64 = 0;
        dma_cfg.s.size = -1;
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), dma_cfg.u64);
+       cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64);
 
        /* Disable the interrupt.  */
        dma_int.u64 = 0;
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), dma_int.u64);
+       cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64);
 
        /* Clear the DMA complete status */
        dma_int.s.done = 1;
-       cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), dma_int.u64);
+       cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64);
 
        status = ap->ops->sff_check_status(ap);
 
@@ -649,69 +694,68 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance)
                struct ata_queued_cmd *qc;
                union cvmx_mio_boot_dma_intx dma_int;
                union cvmx_mio_boot_dma_cfgx dma_cfg;
-               struct octeon_cf_data *ocd;
 
                ap = host->ports[i];
-               ocd = ap->dev->platform_data;
                cf_port = ap->private_data;
-               dma_int.u64 =
-                       cvmx_read_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine));
-               dma_cfg.u64 =
-                       cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine));
+
+               dma_int.u64 = cvmx_read_csr(cf_port->dma_base + DMA_INT);
+               dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG);
 
                qc = ata_qc_from_tag(ap, ap->link.active_tag);
 
-               if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) {
-                       if (dma_int.s.done && !dma_cfg.s.en) {
-                               if (!sg_is_last(qc->cursg)) {
-                                       qc->cursg = sg_next(qc->cursg);
-                                       handled = 1;
-                                       octeon_cf_dma_start(qc);
-                                       continue;
-                               } else {
-                                       cf_port->dma_finished = 1;
-                               }
-                       }
-                       if (!cf_port->dma_finished)
-                               continue;
-                       status = ioread8(ap->ioaddr.altstatus_addr);
-                       if (status & (ATA_BUSY | ATA_DRQ)) {
-                               /*
-                                * We are busy, try to handle it
-                                * later.  This is the DMA finished
-                                * interrupt, and it could take a
-                                * little while for the card to be
-                                * ready for more commands.
-                                */
-                               /* Clear DMA irq. */
-                               dma_int.u64 = 0;
-                               dma_int.s.done = 1;
-                               cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine),
-                                              dma_int.u64);
-
-                               queue_delayed_work(cf_port->wq,
-                                                  &cf_port->delayed_finish, 1);
+               if (!qc || (qc->tf.flags & ATA_TFLAG_POLLING))
+                       continue;
+
+               if (dma_int.s.done && !dma_cfg.s.en) {
+                       if (!sg_is_last(qc->cursg)) {
+                               qc->cursg = sg_next(qc->cursg);
                                handled = 1;
+                               octeon_cf_dma_start(qc);
+                               continue;
                        } else {
-                               handled |= octeon_cf_dma_finished(ap, qc);
+                               cf_port->dma_finished = 1;
                        }
                }
+               if (!cf_port->dma_finished)
+                       continue;
+               status = ioread8(ap->ioaddr.altstatus_addr);
+               if (status & (ATA_BUSY | ATA_DRQ)) {
+                       /*
+                        * We are busy, try to handle it later.  This
+                        * is the DMA finished interrupt, and it could
+                        * take a little while for the card to be
+                        * ready for more commands.
+                        */
+                       /* Clear DMA irq. */
+                       dma_int.u64 = 0;
+                       dma_int.s.done = 1;
+                       cvmx_write_csr(cf_port->dma_base + DMA_INT,
+                                      dma_int.u64);
+                       hrtimer_start_range_ns(&cf_port->delayed_finish,
+                                              ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL),
+                                              OCTEON_CF_BUSY_POLL_INTERVAL / 5,
+                                              HRTIMER_MODE_REL);
+                       handled = 1;
+               } else {
+                       handled |= octeon_cf_dma_finished(ap, qc);
+               }
        }
        spin_unlock_irqrestore(&host->lock, flags);
        DPRINTK("EXIT\n");
        return IRQ_RETVAL(handled);
 }
 
-static void octeon_cf_delayed_finish(struct work_struct *work)
+static enum hrtimer_restart octeon_cf_delayed_finish(struct hrtimer *hrt)
 {
-       struct octeon_cf_port *cf_port = container_of(work,
+       struct octeon_cf_port *cf_port = container_of(hrt,
                                                      struct octeon_cf_port,
-                                                     delayed_finish.work);
+                                                     delayed_finish);
        struct ata_port *ap = cf_port->ap;
        struct ata_host *host = ap->host;
        struct ata_queued_cmd *qc;
        unsigned long flags;
        u8 status;
+       enum hrtimer_restart rv = HRTIMER_NORESTART;
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -726,15 +770,17 @@ static void octeon_cf_delayed_finish(struct work_struct *work)
        status = ioread8(ap->ioaddr.altstatus_addr);
        if (status & (ATA_BUSY | ATA_DRQ)) {
                /* Still busy, try again. */
-               queue_delayed_work(cf_port->wq,
-                                  &cf_port->delayed_finish, 1);
+               hrtimer_forward_now(hrt,
+                                   ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL));
+               rv = HRTIMER_RESTART;
                goto out;
        }
        qc = ata_qc_from_tag(ap, ap->link.active_tag);
-       if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING))
+       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
                octeon_cf_dma_finished(ap, qc);
 out:
        spin_unlock_irqrestore(&host->lock, flags);
+       return rv;
 }
 
 static void octeon_cf_dev_config(struct ata_device *dev)
@@ -786,8 +832,8 @@ static struct ata_port_operations octeon_cf_ops = {
        .qc_prep                = ata_noop_qc_prep,
        .qc_issue               = octeon_cf_qc_issue,
        .sff_dev_select         = octeon_cf_dev_select,
-       .sff_irq_on             = octeon_cf_irq_on,
-       .sff_irq_clear          = octeon_cf_irq_clear,
+       .sff_irq_on             = octeon_cf_ata_port_noaction,
+       .sff_irq_clear          = octeon_cf_ata_port_noaction,
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = octeon_cf_set_piomode,
        .set_dmamode            = octeon_cf_set_dmamode,
@@ -798,46 +844,113 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
 {
        struct resource *res_cs0, *res_cs1;
 
+       bool is_16bit;
+       const __be32 *cs_num;
+       struct property *reg_prop;
+       int n_addr, n_size, reg_len;
+       struct device_node *node;
+       const void *prop;
        void __iomem *cs0;
        void __iomem *cs1 = NULL;
        struct ata_host *host;
        struct ata_port *ap;
-       struct octeon_cf_data *ocd;
        int irq = 0;
        irq_handler_t irq_handler = NULL;
        void __iomem *base;
        struct octeon_cf_port *cf_port;
-       char version[32];
+       int rv = -ENOMEM;
 
-       res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       if (!res_cs0)
+       node = pdev->dev.of_node;
+       if (node == NULL)
                return -EINVAL;
 
-       ocd = pdev->dev.platform_data;
+       cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL);
+       if (!cf_port)
+               return -ENOMEM;
 
-       cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start,
-                                  resource_size(res_cs0));
+       cf_port->is_true_ide = (of_find_property(node, "cavium,true-ide", NULL) != NULL);
 
-       if (!cs0)
-               return -ENOMEM;
+       prop = of_get_property(node, "cavium,bus-width", NULL);
+       if (prop)
+               is_16bit = (be32_to_cpup(prop) == 16);
+       else
+               is_16bit = false;
 
-       /* Determine from availability of DMA if True IDE mode or not */
-       if (ocd->dma_engine >= 0) {
-               res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               if (!res_cs1)
-                       return -EINVAL;
+       n_addr = of_n_addr_cells(node);
+       n_size = of_n_size_cells(node);
 
+       reg_prop = of_find_property(node, "reg", &reg_len);
+       if (!reg_prop || reg_len < sizeof(__be32)) {
+               rv = -EINVAL;
+               goto free_cf_port;
+       }
+       cs_num = reg_prop->value;
+       cf_port->cs0 = be32_to_cpup(cs_num);
+
+       if (cf_port->is_true_ide) {
+               struct device_node *dma_node;
+               dma_node = of_parse_phandle(node,
+                                           "cavium,dma-engine-handle", 0);
+               if (dma_node) {
+                       struct platform_device *dma_dev;
+                       dma_dev = of_find_device_by_node(dma_node);
+                       if (dma_dev) {
+                               struct resource *res_dma;
+                               int i;
+                               res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0);
+                               if (!res_dma) {
+                                       of_node_put(dma_node);
+                                       rv = -EINVAL;
+                                       goto free_cf_port;
+                               }
+                               cf_port->dma_base = (u64)devm_ioremap_nocache(&pdev->dev, res_dma->start,
+                                                                        resource_size(res_dma));
+
+                               if (!cf_port->dma_base) {
+                                       of_node_put(dma_node);
+                                       rv = -EINVAL;
+                                       goto free_cf_port;
+                               }
+
+                               irq_handler = octeon_cf_interrupt;
+                               i = platform_get_irq(dma_dev, 0);
+                               if (i > 0)
+                                       irq = i;
+                       }
+                       of_node_put(dma_node);
+               }
+               res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               if (!res_cs1) {
+                       rv = -EINVAL;
+                       goto free_cf_port;
+               }
                cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
-                                          resource_size(res_cs1));
+                                          res_cs1->end - res_cs1->start + 1);
 
                if (!cs1)
-                       return -ENOMEM;
+                       goto free_cf_port;
+
+               if (reg_len < (n_addr + n_size + 1) * sizeof(__be32)) {
+                       rv = -EINVAL;
+                       goto free_cf_port;
+               }
+               cs_num += n_addr + n_size;
+               cf_port->cs1 = be32_to_cpup(cs_num);
        }
 
-       cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL);
-       if (!cf_port)
-               return -ENOMEM;
+       res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (!res_cs0) {
+               rv = -EINVAL;
+               goto free_cf_port;
+       }
+
+       cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start,
+                                  resource_size(res_cs0));
+
+       if (!cs0)
+               goto free_cf_port;
 
        /* allocate host */
        host = ata_host_alloc(&pdev->dev, 1);
@@ -846,21 +959,22 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
 
        ap = host->ports[0];
        ap->private_data = cf_port;
+       pdev->dev.platform_data = cf_port;
        cf_port->ap = ap;
        ap->ops = &octeon_cf_ops;
        ap->pio_mask = ATA_PIO6;
        ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
 
-       base = cs0 + ocd->base_region_bias;
-       if (!ocd->is16bit) {
+       if (!is_16bit) {
+               base = cs0 + 0x800;
                ap->ioaddr.cmd_addr     = base;
                ata_sff_std_ports(&ap->ioaddr);
 
                ap->ioaddr.altstatus_addr = base + 0xe;
                ap->ioaddr.ctl_addr     = base + 0xe;
                octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8;
-       } else if (cs1) {
-               /* Presence of cs1 indicates True IDE mode.  */
+       } else if (cf_port->is_true_ide) {
+               base = cs0;
                ap->ioaddr.cmd_addr     = base + (ATA_REG_CMD << 1) + 1;
                ap->ioaddr.data_addr    = base + (ATA_REG_DATA << 1);
                ap->ioaddr.error_addr   = base + (ATA_REG_ERR << 1) + 1;
@@ -876,19 +990,15 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
                ap->ioaddr.ctl_addr     = cs1 + (6 << 1) + 1;
                octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16;
 
-               ap->mwdma_mask  = ATA_MWDMA4;
-               irq = platform_get_irq(pdev, 0);
-               irq_handler = octeon_cf_interrupt;
-
-               /* True IDE mode needs delayed work to poll for not-busy.  */
-               cf_port->wq = create_singlethread_workqueue(DRV_NAME);
-               if (!cf_port->wq)
-                       goto free_cf_port;
-               INIT_DELAYED_WORK(&cf_port->delayed_finish,
-                                 octeon_cf_delayed_finish);
+               ap->mwdma_mask  = enable_dma ? ATA_MWDMA4 : 0;
 
+               /* True IDE mode needs a timer to poll for not-busy.  */
+               hrtimer_init(&cf_port->delayed_finish, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_REL);
+               cf_port->delayed_finish.function = octeon_cf_delayed_finish;
        } else {
                /* 16 bit but not True IDE */
+               base = cs0 + 0x800;
                octeon_cf_ops.sff_data_xfer     = octeon_cf_data_xfer16;
                octeon_cf_ops.softreset         = octeon_cf_softreset16;
                octeon_cf_ops.sff_check_status  = octeon_cf_check_status16;
@@ -902,28 +1012,71 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
                ap->ioaddr.ctl_addr     = base + 0xe;
                ap->ioaddr.altstatus_addr = base + 0xe;
        }
+       cf_port->c0 = ap->ioaddr.ctl_addr;
+
+       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
+       pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
 
        ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
 
 
-       snprintf(version, sizeof(version), "%s %d bit%s",
-                DRV_VERSION,
-                (ocd->is16bit) ? 16 : 8,
-                (cs1) ? ", True IDE" : "");
-       ata_print_version_once(&pdev->dev, version);
+       dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n",
+                is_16bit ? 16 : 8,
+                cf_port->is_true_ide ? ", True IDE" : "");
 
-       return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht);
+       return ata_host_activate(host, irq, irq_handler,
+                                IRQF_SHARED, &octeon_cf_sht);
 
 free_cf_port:
        kfree(cf_port);
-       return -ENOMEM;
+       return rv;
+}
+
+static void octeon_cf_shutdown(struct device *dev)
+{
+       union cvmx_mio_boot_dma_cfgx dma_cfg;
+       union cvmx_mio_boot_dma_intx dma_int;
+
+       struct octeon_cf_port *cf_port = dev->platform_data;
+
+       if (cf_port->dma_base) {
+               /* Stop and clear the dma engine.  */
+               dma_cfg.u64 = 0;
+               dma_cfg.s.size = -1;
+               cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64);
+
+               /* Disable the interrupt.  */
+               dma_int.u64 = 0;
+               cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64);
+
+               /* Clear the DMA complete status */
+               dma_int.s.done = 1;
+               cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64);
+
+               __raw_writeb(0, cf_port->c0);
+               udelay(20);
+               __raw_writeb(ATA_SRST, cf_port->c0);
+               udelay(20);
+               __raw_writeb(0, cf_port->c0);
+               mdelay(100);
+       }
 }
 
+static struct of_device_id octeon_cf_match[] = {
+       {
+               .compatible = "cavium,ebt3000-compact-flash",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, octeon_i2c_match);
+
 static struct platform_driver octeon_cf_driver = {
        .probe          = octeon_cf_probe,
        .driver         = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = octeon_cf_match,
+               .shutdown = octeon_cf_shutdown
        },
 };
 
index 1654dc27e7f8365c104d5c6b1523d88c3927d266..e5b234c370fa8d3482cc748409ea863b6561a2f5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
+#include <linux/libata.h>
 
 static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
 {
@@ -76,11 +77,6 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
                                     reg_shift, pio_mask);
 }
 
-static int __devexit pata_of_platform_remove(struct platform_device *ofdev)
-{
-       return __pata_platform_remove(&ofdev->dev);
-}
-
 static struct of_device_id pata_of_platform_match[] = {
        { .compatible = "ata-generic", },
        { .compatible = "electra-ide", },
@@ -95,7 +91,7 @@ static struct platform_driver pata_of_platform_driver = {
                .of_match_table = pata_of_platform_match,
        },
        .probe          = pata_of_platform_probe,
-       .remove         = __devexit_p(pata_of_platform_remove),
+       .remove         = ata_platform_remove_one,
 };
 
 module_platform_driver(pata_of_platform_driver);
index 5ff31b68135c5c9a01c2b3166ff7f3cfb1a5cd71..f9f79fc04a8fc67001f69ff27d43790ddc0ecb8d 100644 (file)
@@ -111,9 +111,7 @@ err1:
 
 static __devexit int palmld_pata_remove(struct platform_device *dev)
 {
-       struct ata_host *host = platform_get_drvdata(dev);
-
-       ata_host_detach(host);
+       ata_platform_remove_one(dev);
 
        /* power down the HDD */
        gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0);
index f1848aeda78398a5994428719d63aefa207afaa7..f4372d0c7ce603c2db18374cf22cc82cec66a4a2 100644 (file)
@@ -178,23 +178,6 @@ int __devinit __pata_platform_probe(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(__pata_platform_probe);
 
-/**
- *     __pata_platform_remove          -       unplug a platform interface
- *     @dev: device
- *
- *     A platform bus ATA device has been unplugged. Perform the needed
- *     cleanup. Also called on module unload for any active devices.
- */
-int __pata_platform_remove(struct device *dev)
-{
-       struct ata_host *host = dev_get_drvdata(dev);
-
-       ata_host_detach(host);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(__pata_platform_remove);
-
 static int __devinit pata_platform_probe(struct platform_device *pdev)
 {
        struct resource *io_res;
@@ -242,14 +225,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
                                     pio_mask);
 }
 
-static int __devexit pata_platform_remove(struct platform_device *pdev)
-{
-       return __pata_platform_remove(&pdev->dev);
-}
-
 static struct platform_driver pata_platform_driver = {
        .probe          = pata_platform_probe,
-       .remove         = __devexit_p(pata_platform_remove),
+       .remove         = ata_platform_remove_one,
        .driver = {
                .name           = DRV_NAME,
                .owner          = THIS_MODULE,
index 32a3499e83e75af3a6e09b673c1d2764095c62f7..e71f998dd90ddfe4c9101996a5e59011e0a8a1bc 100644 (file)
@@ -327,7 +327,6 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
        struct device *dev = &pdev->dev;
        struct ata_port_info port_info[2];
        const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
-       unsigned long port_flags;
        struct ata_host *host;
        struct rdc_host_priv *hpriv;
        int rc;
@@ -337,8 +336,6 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
        port_info[0] = rdc_port_info;
        port_info[1] = rdc_port_info;
 
-       port_flags = port_info[0].flags;
-
        /* enable device and prepare host */
        rc = pcim_enable_device(pdev);
        if (rc)
old mode 100755 (executable)
new mode 100644 (file)
index 937aeb3..2e39173
@@ -43,6 +43,7 @@
 /* These two are defined in "libata.h" */
 #undef DRV_NAME
 #undef DRV_VERSION
+
 #define DRV_NAME        "sata-dwc"
 #define DRV_VERSION     "1.3"
 
index 400bf1c3e982eac392652d086358858ef903ca82..dc7d78eecb19ce6dd3631e8fcc0393804da359eb 100644 (file)
@@ -213,7 +213,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
 
        /* clear D2H reception area to properly wait for D2H FIS */
        ata_tf_init(link->device, &tf);
-       tf.command = 0x80;
+       tf.command = ATA_BUSY;
        ata_tf_to_fis(&tf, 0, 0, d2h_fis);
 
        do {
@@ -368,16 +368,6 @@ err0:
        return rc;
 }
 
-static int __devexit ahci_highbank_remove(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct ata_host *host = dev_get_drvdata(dev);
-
-       ata_host_detach(host);
-
-       return 0;
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int ahci_highbank_suspend(struct device *dev)
 {
@@ -432,7 +422,7 @@ SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
                  ahci_highbank_suspend, ahci_highbank_resume);
 
 static struct platform_driver ahci_highbank_driver = {
-        .remove = __devexit_p(ahci_highbank_remove),
+       .remove = ata_platform_remove_one,
         .driver = {
                 .name = "highbank-ahci",
                 .owner = THIS_MODULE,
index dc35f4d42b8b0bcb3590ac21ca376dae63ef8d64..1e6827c89429d4bd79b422745d23faf6d8407d9f 100644 (file)
@@ -273,12 +273,10 @@ static void inic_reset_port(void __iomem *port_base)
 static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
 {
        void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
-       void __iomem *addr;
 
        if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
                return -EINVAL;
 
-       addr = scr_addr + scr_map[sc_reg] * 4;
        *val = readl(scr_addr + scr_map[sc_reg] * 4);
 
        /* this controller has stuck DIAG.N, ignore it */
index 489c81768321a26d1921a1ce27424dc3e03e9eb0..fb0dd87f889378a952a339e048faa3629177779d 100644 (file)
@@ -147,6 +147,10 @@ struct pdc_port_priv {
        dma_addr_t              pkt_dma;
 };
 
+struct pdc_host_priv {
+       spinlock_t hard_reset_lock;
+};
+
 static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
 static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
 static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct ata_port *ap)
        void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
        void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1;
        unsigned int ata_no = pdc_ata_port_to_ata_no(ap);
+       struct pdc_host_priv *hpriv = ap->host->private_data;
        u8 tmp;
 
-       spin_lock(&ap->host->lock);
+       spin_lock(&hpriv->hard_reset_lock);
 
        tmp = readb(pcictl_b1_mmio);
        tmp &= ~(0x10 << ata_no);
@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct ata_port *ap)
        writeb(tmp, pcictl_b1_mmio);
        readb(pcictl_b1_mmio); /* flush */
 
-       spin_unlock(&ap->host->lock);
+       spin_unlock(&hpriv->hard_reset_lock);
 }
 
 static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
@@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
        const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
        const struct ata_port_info *ppi[PDC_MAX_PORTS];
        struct ata_host *host;
+       struct pdc_host_priv *hpriv;
        void __iomem *host_mmio;
        int n_ports, i, rc;
        int is_sataii_tx4;
@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
                dev_err(&pdev->dev, "failed to allocate host\n");
                return -ENOMEM;
        }
+       hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL);
+       if (!hpriv)
+               return -ENOMEM;
+       spin_lock_init(&hpriv->hard_reset_lock);
+       host->private_data = hpriv;
        host->iomap = pcim_iomap_table(pdev);
 
        is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
index a5f2a563a26a139993b9c3d58902ccbc73054f87..59f0d630d634c7ff0c993f4780dbc7b55e682aff 100644 (file)
@@ -506,8 +506,6 @@ static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
        void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
 
        if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-               void __iomem *addr;
-               addr = scr_addr + sil24_scr_map[sc_reg] * 4;
                *val = readl(scr_addr + sil24_scr_map[sc_reg] * 4);
                return 0;
        }
@@ -519,8 +517,6 @@ static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
        void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
 
        if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-               void __iomem *addr;
-               addr = scr_addr + sil24_scr_map[sc_reg] * 4;
                writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
                return 0;
        }
index 122605593166d8cf0f47e67db27fe11efb297513..7b7127a58f51de8b848086425a50ce1b78560474 100644 (file)
@@ -315,9 +315,8 @@ static int pdc_port_start(struct ata_port *ap)
        return 0;
 }
 
-static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
-                                  unsigned int portno,
-                                          unsigned int total_len)
+static inline void pdc20621_ata_sg(u8 *buf, unsigned int portno,
+                                  unsigned int total_len)
 {
        u32 addr;
        unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
@@ -337,9 +336,8 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
                buf32[dw], buf32[dw + 1]);
 }
 
-static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
-                                   unsigned int portno,
-                                           unsigned int total_len)
+static inline void pdc20621_host_sg(u8 *buf, unsigned int portno,
+                                   unsigned int total_len)
 {
        u32 addr;
        unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
@@ -486,10 +484,10 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
        /*
         * Build ATA, host DMA packets
         */
-       pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+       pdc20621_host_sg(&pp->dimm_buf[0], portno, total_len);
        pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
 
-       pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+       pdc20621_ata_sg(&pp->dimm_buf[0], portno, total_len);
        i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
 
        if (qc->tf.flags & ATA_TFLAG_LBA48)
index 417913974df813f814208e697de28ffc63130756..a235085e343c47ca2b643f876c31ab70032359b5 100644 (file)
@@ -171,6 +171,27 @@ ssize_t device_show_int(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(device_show_int);
 
+ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t size)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+
+       if (strtobool(buf, ea->var) < 0)
+               return -EINVAL;
+
+       return size;
+}
+EXPORT_SYMBOL_GPL(device_store_bool);
+
+ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(device_show_bool);
+
 /**
  *     device_release - free device structure.
  *     @kobj:  device's kobject.
index 3fbedc75e7c56219d1f0eafeabdebe9e058edc27..0ce39a33b3c2c2faf23746f662d609f22c7cf46b 100644 (file)
@@ -218,6 +218,8 @@ void dmam_release_declared_memory(struct device *dev)
 }
 EXPORT_SYMBOL(dmam_release_declared_memory);
 
+#endif
+
 /*
  * Create scatter-list for the already allocated DMA buffer.
  */
@@ -236,8 +238,6 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
 }
 EXPORT_SYMBOL(dma_common_get_sgtable);
 
-#endif
-
 /*
  * Create userspace mapping for the DMA-coherent memory.
  */
index 294e31626210bc396845ed6c1daba0d57b13e1a8..fac124a7e1c5b0203b4953e6fd30ce9fbfe5c290 100644 (file)
@@ -227,7 +227,7 @@ static node_registration_func_t __hugetlb_unregister_node;
 static inline bool hugetlb_register_node(struct node *node)
 {
        if (__hugetlb_register_node &&
-                       node_state(node->dev.id, N_HIGH_MEMORY)) {
+                       node_state(node->dev.id, N_MEMORY)) {
                __hugetlb_register_node(node);
                return true;
        }
@@ -643,6 +643,9 @@ static struct node_attr node_state_attr[] = {
        [N_NORMAL_MEMORY] = _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
 #ifdef CONFIG_HIGHMEM
        [N_HIGH_MEMORY] = _NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
+#endif
+#ifdef CONFIG_MOVABLE_NODE
+       [N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY),
 #endif
        [N_CPU] = _NODE_ATTR(has_cpu, N_CPU),
 };
@@ -653,6 +656,9 @@ static struct attribute *node_state_attrs[] = {
        &node_state_attr[N_NORMAL_MEMORY].attr.attr,
 #ifdef CONFIG_HIGHMEM
        &node_state_attr[N_HIGH_MEMORY].attr.attr,
+#endif
+#ifdef CONFIG_MOVABLE_NODE
+       &node_state_attr[N_MEMORY].attr.attr,
 #endif
        &node_state_attr[N_CPU].attr.attr,
        NULL
index a533af218368ec7723754a3cf28d8d4cb5d4711a..d7b56a88c9f4d7211317484f441864263e4b0a20 100644 (file)
@@ -65,6 +65,15 @@ config BCMA_DRIVER_GMAC_CMN
 
          If unsure, say N
 
+config BCMA_DRIVER_GPIO
+       bool "BCMA GPIO driver"
+       depends on BCMA
+       select GPIOLIB
+       help
+         Driver to provide access to the GPIO pins of the bcma bus.
+
+         If unsure, say N
+
 config BCMA_DEBUG
        bool "BCMA debugging"
        depends on BCMA
index 8ad42d41b2f24deeb1241f6d88824380105875db..734b32f09c0a21aa7ef734100400a47f13f485ad 100644 (file)
@@ -6,6 +6,7 @@ bcma-y                                  += driver_pci.o
 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)        += driver_pci_host.o
 bcma-$(CONFIG_BCMA_DRIVER_MIPS)                += driver_mips.o
 bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN)    += driver_gmac_cmn.o
+bcma-$(CONFIG_BCMA_DRIVER_GPIO)                += driver_gpio.o
 bcma-$(CONFIG_BCMA_HOST_PCI)           += host_pci.o
 bcma-$(CONFIG_BCMA_HOST_SOC)           += host_soc.o
 obj-$(CONFIG_BCMA)                     += bcma.o
index 537ae53231cdb7a613a99aa1d40f6dd0294527d9..4a2d72ec6d4325f49dd93baa09c99b8baff6d48c 100644 (file)
@@ -91,4 +91,14 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
 void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
 
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+/* driver_gpio.c */
+int bcma_gpio_init(struct bcma_drv_cc *cc);
+#else
+static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
+{
+       return -ENOTSUPP;
+}
+#endif /* CONFIG_BCMA_DRIVER_GPIO */
+
 #endif
index dc96dd8ebff29c573960b475c2a664e359edc2fc..e461ad25fda4825dbc36a632d5781015843eb268 100644 (file)
@@ -114,6 +114,8 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
        if (cc->early_setup_done)
                return;
 
+       spin_lock_init(&cc->gpio_lock);
+
        if (cc->core->id.rev >= 11)
                cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
        cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -202,28 +204,97 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
 
 u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-       return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
+       unsigned long flags;
+       u32 res;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-       return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
+       unsigned long flags;
+       u32 res;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
+/*
+ * If the bit is set to 0, chipcommon controlls this GPIO,
+ * if the bit is set to 1, it is used by some part of the chip and not our code.
+ */
 u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-       return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
+       unsigned long flags;
+       u32 res;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
 
 u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-       return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
+       unsigned long flags;
+       u32 res;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-       return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
+       unsigned long flags;
+       u32 res;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
+}
+
+u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
+{
+       unsigned long flags;
+       u32 res;
+
+       if (cc->core->id.rev < 20)
+               return 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
+}
+
+u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
+{
+       unsigned long flags;
+       u32 res;
+
+       if (cc->core->id.rev < 20)
+               return 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 #ifdef CONFIG_BCMA_DRIVER_MIPS
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
new file mode 100644 (file)
index 0000000..9a6f585
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Broadcom specific AMBA
+ * GPIO driver
+ *
+ * Copyright 2011, Broadcom Corporation
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcma_private.h"
+
+static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
+{
+       return container_of(chip, struct bcma_drv_cc, gpio);
+}
+
+static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+       struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+       return !!bcma_chipco_gpio_in(cc, 1 << gpio);
+}
+
+static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
+                               int value)
+{
+       struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+       bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+       bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
+       return 0;
+}
+
+static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+                                     int value)
+{
+       struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+       bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
+       bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
+       return 0;
+}
+
+static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+       struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+       bcma_chipco_gpio_control(cc, 1 << gpio, 0);
+       /* clear pulldown */
+       bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
+       /* Set pullup */
+       bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
+
+       return 0;
+}
+
+static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+       struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+       /* clear pullup */
+       bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
+}
+
+int bcma_gpio_init(struct bcma_drv_cc *cc)
+{
+       struct gpio_chip *chip = &cc->gpio;
+
+       chip->label             = "bcma_gpio";
+       chip->owner             = THIS_MODULE;
+       chip->request           = bcma_gpio_request;
+       chip->free              = bcma_gpio_free;
+       chip->get               = bcma_gpio_get_value;
+       chip->set               = bcma_gpio_set_value;
+       chip->direction_input   = bcma_gpio_direction_input;
+       chip->direction_output  = bcma_gpio_direction_output;
+       chip->ngpio             = 16;
+       /* There is just one SoC in one device and its GPIO addresses should be
+        * deterministic to address them more easily. The other buses could get
+        * a random base number. */
+       if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
+               chip->base              = 0;
+       else
+               chip->base              = -1;
+
+       return gpiochip_add(chip);
+}
index debd4f142f936b084ff7d92c517188d7728cf332..53ba20ca17e0d00b1fc9087b540b41645c0f64bb 100644 (file)
@@ -164,6 +164,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
                        bcma_err(bus, "Error registering NAND flash\n");
        }
 #endif
+       err = bcma_gpio_init(&bus->drv_cc);
+       if (err == -ENOTSUPP)
+               bcma_debug(bus, "GPIO driver not activated\n");
+       else if (err)
+               bcma_err(bus, "Error registering GPIO driver: %i\n", err);
 
        if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
                err = bcma_chipco_watchdog_register(&bus->drv_cc);
index a0c84bb30856073aa7a46c52690f163789bbd9bc..053201b062a4cffce40422ad1e28c925d4ea5244 100644 (file)
@@ -3789,7 +3789,7 @@ static int handle_one_recv_msg(ipmi_smi_t          intf,
 
        } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
                   && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) {
-               /* It's an asyncronous event. */
+               /* It's an asynchronous event. */
                requeue = handle_read_event_rsp(intf, msg);
        } else {
                /* It's a response from the local BMC. */
index 20ab5b3a89150954cab2ec442b4f8b4ce93234a9..cfdfecd5bc763026762bd9e26b08e4e3c15e7b67 100644 (file)
@@ -155,7 +155,7 @@ enum si_stat_indexes {
        /* Number of watchdog pretimeouts. */
        SI_STAT_watchdog_pretimeouts,
 
-       /* Number of asyncronous messages received. */
+       /* Number of asynchronous messages received. */
        SI_STAT_incoming_messages,
 
 
index d0d824ebf2c187d492f29daef8bbf1043f56d7f1..1cd49241e60eb5024ac2941a5b0787fa46f7c13e 100644 (file)
@@ -251,12 +251,8 @@ static ssize_t pp_write (struct file * file, const char __user * buf,
                        break;
                }
 
-               if (signal_pending (current)) {
-                       if (!bytes_written) {
-                               bytes_written = -EINTR;
-                       }
+               if (signal_pending (current))
                        break;
-               }
 
                cond_resched();
        }
index 823f62d900ba02183bfb2de6daf81175bfb92841..a47e6ee98b8c9798da8ffad462dbc052ef875053 100644 (file)
@@ -64,3 +64,5 @@ config CLK_TWL6040
          as functional clock.
 
 endmenu
+
+source "drivers/clk/mvebu/Kconfig"
index 4e1ccb1e6614940ff4b927642e6881dca19d3350..ee90e87e7675859e4ae80cf0587191732e8b6541 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_PLAT_SPEAR)      += spear/
 obj-$(CONFIG_ARCH_U300)                += clk-u300.o
 obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
 obj-$(CONFIG_ARCH_PRIMA2)      += clk-prima2.o
+obj-$(CONFIG_PLAT_ORION)       += mvebu/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)         += mmp/
 endif
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
new file mode 100644 (file)
index 0000000..57323fd
--- /dev/null
@@ -0,0 +1,8 @@
+config MVEBU_CLK_CORE
+       bool
+
+config MVEBU_CLK_CPU
+       bool
+
+config MVEBU_CLK_GATING
+       bool
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
new file mode 100644 (file)
index 0000000..58df3dc
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MVEBU_CLK_CORE)   += clk.o clk-core.o
+obj-$(CONFIG_MVEBU_CLK_CPU)    += clk-cpu.o
+obj-$(CONFIG_MVEBU_CLK_GATING)         += clk-gating-ctrl.o
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
new file mode 100644 (file)
index 0000000..69056a7
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Marvell EBU clock core handling defined at reset
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include "clk-core.h"
+
+struct core_ratio {
+       int id;
+       const char *name;
+};
+
+struct core_clocks {
+       u32 (*get_tclk_freq)(void __iomem *sar);
+       u32 (*get_cpu_freq)(void __iomem *sar);
+       void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
+       const struct core_ratio *ratios;
+       int num_ratios;
+};
+
+static struct clk_onecell_data clk_data;
+
+static void __init mvebu_clk_core_setup(struct device_node *np,
+                                struct core_clocks *coreclk)
+{
+       const char *tclk_name = "tclk";
+       const char *cpuclk_name = "cpuclk";
+       void __iomem *base;
+       unsigned long rate;
+       int n;
+
+       base = of_iomap(np, 0);
+       if (WARN_ON(!base))
+               return;
+
+       /*
+        * Allocate struct for TCLK, cpu clk, and core ratio clocks
+        */
+       clk_data.clk_num = 2 + coreclk->num_ratios;
+       clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
+                               GFP_KERNEL);
+       if (WARN_ON(!clk_data.clks))
+               return;
+
+       /*
+        * Register TCLK
+        */
+       of_property_read_string_index(np, "clock-output-names", 0,
+                                     &tclk_name);
+       rate = coreclk->get_tclk_freq(base);
+       clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
+                                                  CLK_IS_ROOT, rate);
+       WARN_ON(IS_ERR(clk_data.clks[0]));
+
+       /*
+        * Register CPU clock
+        */
+       of_property_read_string_index(np, "clock-output-names", 1,
+                                     &cpuclk_name);
+       rate = coreclk->get_cpu_freq(base);
+       clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
+                                                  CLK_IS_ROOT, rate);
+       WARN_ON(IS_ERR(clk_data.clks[1]));
+
+       /*
+        * Register fixed-factor clocks derived from CPU clock
+        */
+       for (n = 0; n < coreclk->num_ratios; n++) {
+               const char *rclk_name = coreclk->ratios[n].name;
+               int mult, div;
+
+               of_property_read_string_index(np, "clock-output-names",
+                                             2+n, &rclk_name);
+               coreclk->get_clk_ratio(base, coreclk->ratios[n].id,
+                                      &mult, &div);
+               clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
+                                      cpuclk_name, 0, mult, div);
+               WARN_ON(IS_ERR(clk_data.clks[2+n]));
+       };
+
+       /*
+        * SAR register isn't needed anymore
+        */
+       iounmap(base);
+
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+#ifdef CONFIG_MACH_ARMADA_370_XP
+/*
+ * Armada 370/XP Sample At Reset is a 64 bit bitfiled split in two
+ * register of 32 bits
+ */
+
+#define SARL                               0   /* Low part [0:31] */
+#define            SARL_AXP_PCLK_FREQ_OPT          21
+#define            SARL_AXP_PCLK_FREQ_OPT_MASK     0x7
+#define            SARL_A370_PCLK_FREQ_OPT         11
+#define            SARL_A370_PCLK_FREQ_OPT_MASK    0xF
+#define            SARL_AXP_FAB_FREQ_OPT           24
+#define            SARL_AXP_FAB_FREQ_OPT_MASK      0xF
+#define            SARL_A370_FAB_FREQ_OPT          15
+#define            SARL_A370_FAB_FREQ_OPT_MASK     0x1F
+#define            SARL_A370_TCLK_FREQ_OPT         20
+#define            SARL_A370_TCLK_FREQ_OPT_MASK    0x1
+#define SARH                               4   /* High part [32:63] */
+#define            SARH_AXP_PCLK_FREQ_OPT          (52-32)
+#define            SARH_AXP_PCLK_FREQ_OPT_MASK     0x1
+#define            SARH_AXP_PCLK_FREQ_OPT_SHIFT    3
+#define            SARH_AXP_FAB_FREQ_OPT           (51-32)
+#define            SARH_AXP_FAB_FREQ_OPT_MASK      0x1
+#define            SARH_AXP_FAB_FREQ_OPT_SHIFT     4
+
+static const u32 __initconst armada_370_tclk_frequencies[] = {
+       16600000,
+       20000000,
+};
+
+static u32 __init armada_370_get_tclk_freq(void __iomem *sar)
+{
+       u8 tclk_freq_select = 0;
+
+       tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
+                           SARL_A370_TCLK_FREQ_OPT_MASK);
+       return armada_370_tclk_frequencies[tclk_freq_select];
+}
+
+static const u32 __initconst armada_370_cpu_frequencies[] = {
+       400000000,
+       533000000,
+       667000000,
+       800000000,
+       1000000000,
+       1067000000,
+       1200000000,
+};
+
+static u32 __init armada_370_get_cpu_freq(void __iomem *sar)
+{
+       u32 cpu_freq;
+       u8 cpu_freq_select = 0;
+
+       cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
+                          SARL_A370_PCLK_FREQ_OPT_MASK);
+       if (cpu_freq_select > ARRAY_SIZE(armada_370_cpu_frequencies)) {
+               pr_err("CPU freq select unsuported %d\n", cpu_freq_select);
+               cpu_freq = 0;
+       } else
+               cpu_freq = armada_370_cpu_frequencies[cpu_freq_select];
+
+       return cpu_freq;
+}
+
+enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK };
+
+static const struct core_ratio __initconst armada_370_xp_core_ratios[] = {
+       { .id = A370_XP_NBCLK,   .name = "nbclk" },
+       { .id = A370_XP_HCLK,    .name = "hclk" },
+       { .id = A370_XP_DRAMCLK, .name = "dramclk" },
+};
+
+static const int __initconst armada_370_xp_nbclk_ratios[32][2] = {
+       {0, 1}, {1, 2}, {2, 2}, {2, 2},
+       {1, 2}, {1, 2}, {1, 1}, {2, 3},
+       {0, 1}, {1, 2}, {2, 4}, {0, 1},
+       {1, 2}, {0, 1}, {0, 1}, {2, 2},
+       {0, 1}, {0, 1}, {0, 1}, {1, 1},
+       {2, 3}, {0, 1}, {0, 1}, {0, 1},
+       {0, 1}, {0, 1}, {0, 1}, {1, 1},
+       {0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static const int __initconst armada_370_xp_hclk_ratios[32][2] = {
+       {0, 1}, {1, 2}, {2, 6}, {2, 3},
+       {1, 3}, {1, 4}, {1, 2}, {2, 6},
+       {0, 1}, {1, 6}, {2, 10}, {0, 1},
+       {1, 4}, {0, 1}, {0, 1}, {2, 5},
+       {0, 1}, {0, 1}, {0, 1}, {1, 2},
+       {2, 6}, {0, 1}, {0, 1}, {0, 1},
+       {0, 1}, {0, 1}, {0, 1}, {1, 1},
+       {0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static const int __initconst armada_370_xp_dramclk_ratios[32][2] = {
+       {0, 1}, {1, 2}, {2, 3}, {2, 3},
+       {1, 3}, {1, 2}, {1, 2}, {2, 6},
+       {0, 1}, {1, 3}, {2, 5}, {0, 1},
+       {1, 4}, {0, 1}, {0, 1}, {2, 5},
+       {0, 1}, {0, 1}, {0, 1}, {1, 1},
+       {2, 3}, {0, 1}, {0, 1}, {0, 1},
+       {0, 1}, {0, 1}, {0, 1}, {1, 1},
+       {0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static void __init armada_370_xp_get_clk_ratio(u32 opt,
+       void __iomem *sar, int id, int *mult, int *div)
+{
+       switch (id) {
+       case A370_XP_NBCLK:
+               *mult = armada_370_xp_nbclk_ratios[opt][0];
+               *div = armada_370_xp_nbclk_ratios[opt][1];
+               break;
+       case A370_XP_HCLK:
+               *mult = armada_370_xp_hclk_ratios[opt][0];
+               *div = armada_370_xp_hclk_ratios[opt][1];
+               break;
+       case A370_XP_DRAMCLK:
+               *mult = armada_370_xp_dramclk_ratios[opt][0];
+               *div = armada_370_xp_dramclk_ratios[opt][1];
+               break;
+       }
+}
+
+static void __init armada_370_get_clk_ratio(
+       void __iomem *sar, int id, int *mult, int *div)
+{
+       u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
+               SARL_A370_FAB_FREQ_OPT_MASK);
+
+       armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
+}
+
+
+static const struct core_clocks armada_370_core_clocks = {
+       .get_tclk_freq = armada_370_get_tclk_freq,
+       .get_cpu_freq = armada_370_get_cpu_freq,
+       .get_clk_ratio = armada_370_get_clk_ratio,
+       .ratios = armada_370_xp_core_ratios,
+       .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
+};
+
+static const u32 __initconst armada_xp_cpu_frequencies[] = {
+       1000000000,
+       1066000000,
+       1200000000,
+       1333000000,
+       1500000000,
+       1666000000,
+       1800000000,
+       2000000000,
+       667000000,
+       0,
+       800000000,
+       1600000000,
+};
+
+/* For Armada XP TCLK frequency is fix: 250MHz */
+static u32 __init armada_xp_get_tclk_freq(void __iomem *sar)
+{
+       return 250 * 1000 * 1000;
+}
+
+static u32 __init armada_xp_get_cpu_freq(void __iomem *sar)
+{
+       u32 cpu_freq;
+       u8 cpu_freq_select = 0;
+
+       cpu_freq_select = ((readl(sar) >> SARL_AXP_PCLK_FREQ_OPT) &
+                          SARL_AXP_PCLK_FREQ_OPT_MASK);
+       /*
+        * The upper bit is not contiguous to the other ones and
+        * located in the high part of the SAR registers
+        */
+       cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) &
+                            SARH_AXP_PCLK_FREQ_OPT_MASK)
+                           << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
+       if (cpu_freq_select > ARRAY_SIZE(armada_xp_cpu_frequencies)) {
+               pr_err("CPU freq select unsuported: %d\n", cpu_freq_select);
+               cpu_freq = 0;
+       } else
+               cpu_freq = armada_xp_cpu_frequencies[cpu_freq_select];
+
+       return cpu_freq;
+}
+
+static void __init armada_xp_get_clk_ratio(
+       void __iomem *sar, int id, int *mult, int *div)
+{
+
+       u32 opt = ((readl(sar) >> SARL_AXP_FAB_FREQ_OPT) &
+             SARL_AXP_FAB_FREQ_OPT_MASK);
+       /*
+        * The upper bit is not contiguous to the other ones and
+        * located in the high part of the SAR registers
+        */
+       opt |= (((readl(sar+4) >> SARH_AXP_FAB_FREQ_OPT) &
+               SARH_AXP_FAB_FREQ_OPT_MASK)
+              << SARH_AXP_FAB_FREQ_OPT_SHIFT);
+
+       armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
+}
+
+static const struct core_clocks armada_xp_core_clocks = {
+       .get_tclk_freq = armada_xp_get_tclk_freq,
+       .get_cpu_freq = armada_xp_get_cpu_freq,
+       .get_clk_ratio = armada_xp_get_clk_ratio,
+       .ratios = armada_370_xp_core_ratios,
+       .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
+};
+
+#endif /* CONFIG_MACH_ARMADA_370_XP */
+
+/*
+ * Dove PLL sample-at-reset configuration
+ *
+ * SAR0[8:5]   : CPU frequency
+ *              5  = 1000 MHz
+ *              6  =  933 MHz
+ *              7  =  933 MHz
+ *              8  =  800 MHz
+ *              9  =  800 MHz
+ *              10 =  800 MHz
+ *              11 = 1067 MHz
+ *              12 =  667 MHz
+ *              13 =  533 MHz
+ *              14 =  400 MHz
+ *              15 =  333 MHz
+ *              others reserved.
+ *
+ * SAR0[11:9]  : CPU to L2 Clock divider ratio
+ *              0 = (1/1) * CPU
+ *              2 = (1/2) * CPU
+ *              4 = (1/3) * CPU
+ *              6 = (1/4) * CPU
+ *              others reserved.
+ *
+ * SAR0[15:12] : CPU to DDR DRAM Clock divider ratio
+ *              0  = (1/1) * CPU
+ *              2  = (1/2) * CPU
+ *              3  = (2/5) * CPU
+ *              4  = (1/3) * CPU
+ *              6  = (1/4) * CPU
+ *              8  = (1/5) * CPU
+ *              10 = (1/6) * CPU
+ *              12 = (1/7) * CPU
+ *              14 = (1/8) * CPU
+ *              15 = (1/10) * CPU
+ *              others reserved.
+ *
+ * SAR0[24:23] : TCLK frequency
+ *              0 = 166 MHz
+ *              1 = 125 MHz
+ *              others reserved.
+ */
+#ifdef CONFIG_ARCH_DOVE
+#define SAR_DOVE_CPU_FREQ              5
+#define SAR_DOVE_CPU_FREQ_MASK         0xf
+#define SAR_DOVE_L2_RATIO              9
+#define SAR_DOVE_L2_RATIO_MASK         0x7
+#define SAR_DOVE_DDR_RATIO             12
+#define SAR_DOVE_DDR_RATIO_MASK                0xf
+#define SAR_DOVE_TCLK_FREQ             23
+#define SAR_DOVE_TCLK_FREQ_MASK                0x3
+
+static const u32 __initconst dove_tclk_frequencies[] = {
+       166666667,
+       125000000,
+       0, 0
+};
+
+static u32 __init dove_get_tclk_freq(void __iomem *sar)
+{
+       u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
+               SAR_DOVE_TCLK_FREQ_MASK;
+       return dove_tclk_frequencies[opt];
+}
+
+static const u32 __initconst dove_cpu_frequencies[] = {
+       0, 0, 0, 0, 0,
+       1000000000,
+       933333333, 933333333,
+       800000000, 800000000, 800000000,
+       1066666667,
+       666666667,
+       533333333,
+       400000000,
+       333333333
+};
+
+static u32 __init dove_get_cpu_freq(void __iomem *sar)
+{
+       u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
+               SAR_DOVE_CPU_FREQ_MASK;
+       return dove_cpu_frequencies[opt];
+}
+
+enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
+
+static const struct core_ratio __initconst dove_core_ratios[] = {
+       { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
+       { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
+};
+
+static const int __initconst dove_cpu_l2_ratios[8][2] = {
+       { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
+       { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
+};
+
+static const int __initconst dove_cpu_ddr_ratios[16][2] = {
+       { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
+       { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
+       { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
+       { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
+};
+
+static void __init dove_get_clk_ratio(
+       void __iomem *sar, int id, int *mult, int *div)
+{
+       switch (id) {
+       case DOVE_CPU_TO_L2:
+       {
+               u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
+                       SAR_DOVE_L2_RATIO_MASK;
+               *mult = dove_cpu_l2_ratios[opt][0];
+               *div = dove_cpu_l2_ratios[opt][1];
+               break;
+       }
+       case DOVE_CPU_TO_DDR:
+       {
+               u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
+                       SAR_DOVE_DDR_RATIO_MASK;
+               *mult = dove_cpu_ddr_ratios[opt][0];
+               *div = dove_cpu_ddr_ratios[opt][1];
+               break;
+       }
+       }
+}
+
+static const struct core_clocks dove_core_clocks = {
+       .get_tclk_freq = dove_get_tclk_freq,
+       .get_cpu_freq = dove_get_cpu_freq,
+       .get_clk_ratio = dove_get_clk_ratio,
+       .ratios = dove_core_ratios,
+       .num_ratios = ARRAY_SIZE(dove_core_ratios),
+};
+#endif /* CONFIG_ARCH_DOVE */
+
+/*
+ * Kirkwood PLL sample-at-reset configuration
+ * (6180 has different SAR layout than other Kirkwood SoCs)
+ *
+ * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
+ *     4  =  600 MHz
+ *     6  =  800 MHz
+ *     7  = 1000 MHz
+ *     9  = 1200 MHz
+ *     12 = 1500 MHz
+ *     13 = 1600 MHz
+ *     14 = 1800 MHz
+ *     15 = 2000 MHz
+ *     others reserved.
+ *
+ * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
+ *     1 = (1/2) * CPU
+ *     3 = (1/3) * CPU
+ *     5 = (1/4) * CPU
+ *     others reserved.
+ *
+ * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
+ *     2 = (1/2) * CPU
+ *     4 = (1/3) * CPU
+ *     6 = (1/4) * CPU
+ *     7 = (2/9) * CPU
+ *     8 = (1/5) * CPU
+ *     9 = (1/6) * CPU
+ *     others reserved.
+ *
+ * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
+ *     5 = [CPU =  600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
+ *     6 = [CPU =  800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
+ *     7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
+ *     others reserved.
+ *
+ * SAR0[21] : TCLK frequency
+ *     0 = 200 MHz
+ *     1 = 166 MHz
+ *     others reserved.
+ */
+#ifdef CONFIG_ARCH_KIRKWOOD
+#define SAR_KIRKWOOD_CPU_FREQ(x)       \
+       (((x & (1 <<  1)) >>  1) |      \
+        ((x & (1 << 22)) >> 21) |      \
+        ((x & (3 <<  3)) >>  1))
+#define SAR_KIRKWOOD_L2_RATIO(x)       \
+       (((x & (3 <<  9)) >> 9) |       \
+        (((x & (1 << 19)) >> 17)))
+#define SAR_KIRKWOOD_DDR_RATIO         5
+#define SAR_KIRKWOOD_DDR_RATIO_MASK    0xf
+#define SAR_MV88F6180_CLK              2
+#define SAR_MV88F6180_CLK_MASK         0x7
+#define SAR_KIRKWOOD_TCLK_FREQ         21
+#define SAR_KIRKWOOD_TCLK_FREQ_MASK    0x1
+
+enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
+
+static const struct core_ratio __initconst kirkwood_core_ratios[] = {
+       { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
+       { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
+};
+
+static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
+{
+       u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
+               SAR_KIRKWOOD_TCLK_FREQ_MASK;
+       return (opt) ? 166666667 : 200000000;
+}
+
+static const u32 __initconst kirkwood_cpu_frequencies[] = {
+       0, 0, 0, 0,
+       600000000,
+       0,
+       800000000,
+       1000000000,
+       0,
+       1200000000,
+       0, 0,
+       1500000000,
+       1600000000,
+       1800000000,
+       2000000000
+};
+
+static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
+{
+       u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
+       return kirkwood_cpu_frequencies[opt];
+}
+
+static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
+       { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
+       { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
+};
+
+static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
+       { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
+       { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
+       { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
+       { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
+};
+
+static void __init kirkwood_get_clk_ratio(
+       void __iomem *sar, int id, int *mult, int *div)
+{
+       switch (id) {
+       case KIRKWOOD_CPU_TO_L2:
+       {
+               u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
+               *mult = kirkwood_cpu_l2_ratios[opt][0];
+               *div = kirkwood_cpu_l2_ratios[opt][1];
+               break;
+       }
+       case KIRKWOOD_CPU_TO_DDR:
+       {
+               u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
+                       SAR_KIRKWOOD_DDR_RATIO_MASK;
+               *mult = kirkwood_cpu_ddr_ratios[opt][0];
+               *div = kirkwood_cpu_ddr_ratios[opt][1];
+               break;
+       }
+       }
+}
+
+static const struct core_clocks kirkwood_core_clocks = {
+       .get_tclk_freq = kirkwood_get_tclk_freq,
+       .get_cpu_freq = kirkwood_get_cpu_freq,
+       .get_clk_ratio = kirkwood_get_clk_ratio,
+       .ratios = kirkwood_core_ratios,
+       .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
+};
+
+static const u32 __initconst mv88f6180_cpu_frequencies[] = {
+       0, 0, 0, 0, 0,
+       600000000,
+       800000000,
+       1000000000
+};
+
+static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
+{
+       u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
+       return mv88f6180_cpu_frequencies[opt];
+}
+
+static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
+       { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
+       { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
+};
+
+static void __init mv88f6180_get_clk_ratio(
+       void __iomem *sar, int id, int *mult, int *div)
+{
+       switch (id) {
+       case KIRKWOOD_CPU_TO_L2:
+       {
+               /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
+               *mult = 1;
+               *div = 2;
+               break;
+       }
+       case KIRKWOOD_CPU_TO_DDR:
+       {
+               u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
+                       SAR_MV88F6180_CLK_MASK;
+               *mult = mv88f6180_cpu_ddr_ratios[opt][0];
+               *div = mv88f6180_cpu_ddr_ratios[opt][1];
+               break;
+       }
+       }
+}
+
+static const struct core_clocks mv88f6180_core_clocks = {
+       .get_tclk_freq = kirkwood_get_tclk_freq,
+       .get_cpu_freq = mv88f6180_get_cpu_freq,
+       .get_clk_ratio = mv88f6180_get_clk_ratio,
+       .ratios = kirkwood_core_ratios,
+       .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
+};
+#endif /* CONFIG_ARCH_KIRKWOOD */
+
+static const __initdata struct of_device_id clk_core_match[] = {
+#ifdef CONFIG_MACH_ARMADA_370_XP
+       {
+               .compatible = "marvell,armada-370-core-clock",
+               .data = &armada_370_core_clocks,
+       },
+       {
+               .compatible = "marvell,armada-xp-core-clock",
+               .data = &armada_xp_core_clocks,
+       },
+#endif
+#ifdef CONFIG_ARCH_DOVE
+       {
+               .compatible = "marvell,dove-core-clock",
+               .data = &dove_core_clocks,
+       },
+#endif
+
+#ifdef CONFIG_ARCH_KIRKWOOD
+       {
+               .compatible = "marvell,kirkwood-core-clock",
+               .data = &kirkwood_core_clocks,
+       },
+       {
+               .compatible = "marvell,mv88f6180-core-clock",
+               .data = &mv88f6180_core_clocks,
+       },
+#endif
+
+       { }
+};
+
+void __init mvebu_core_clk_init(void)
+{
+       struct device_node *np;
+
+       for_each_matching_node(np, clk_core_match) {
+               const struct of_device_id *match =
+                       of_match_node(clk_core_match, np);
+               mvebu_clk_core_setup(np, (struct core_clocks *)match->data);
+       }
+}
diff --git a/drivers/clk/mvebu/clk-core.h b/drivers/clk/mvebu/clk-core.h
new file mode 100644 (file)
index 0000000..28b5e02
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  * Marvell EBU clock core handling defined at reset
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_CLK_CORE_H
+#define __MVEBU_CLK_CORE_H
+
+void __init mvebu_core_clk_init(void);
+
+#endif
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
new file mode 100644 (file)
index 0000000..ff00457
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Marvell MVEBU CPU clock handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include "clk-cpu.h"
+
+#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET    0x0
+#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET   0xC
+#define SYS_CTRL_CLK_DIVIDER_MASK          0x3F
+
+#define MAX_CPU            4
+struct cpu_clk {
+       struct clk_hw hw;
+       int cpu;
+       const char *clk_name;
+       const char *parent_name;
+       void __iomem *reg_base;
+};
+
+static struct clk **clks;
+
+static struct clk_onecell_data clk_data;
+
+#define to_cpu_clk(p) container_of(p, struct cpu_clk, hw)
+
+static unsigned long clk_cpu_recalc_rate(struct clk_hw *hwclk,
+                                        unsigned long parent_rate)
+{
+       struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
+       u32 reg, div;
+
+       reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
+       div = (reg >> (cpuclk->cpu * 8)) & SYS_CTRL_CLK_DIVIDER_MASK;
+       return parent_rate / div;
+}
+
+static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
+                              unsigned long *parent_rate)
+{
+       /* Valid ratio are 1:1, 1:2 and 1:3 */
+       u32 div;
+
+       div = *parent_rate / rate;
+       if (div == 0)
+               div = 1;
+       else if (div > 3)
+               div = 3;
+
+       return *parent_rate / div;
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
+                           unsigned long parent_rate)
+{
+       struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
+       u32 reg, div;
+       u32 reload_mask;
+
+       div = parent_rate / rate;
+       reg = (readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET)
+               & (~(SYS_CTRL_CLK_DIVIDER_MASK << (cpuclk->cpu * 8))))
+               | (div << (cpuclk->cpu * 8));
+       writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
+       /* Set clock divider reload smooth bit mask */
+       reload_mask = 1 << (20 + cpuclk->cpu);
+
+       reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
+           | reload_mask;
+       writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+
+       /* Now trigger the clock update */
+       reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
+           | 1 << 24;
+       writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+
+       /* Wait for clocks to settle down then clear reload request */
+       udelay(1000);
+       reg &= ~(reload_mask | 1 << 24);
+       writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+       udelay(1000);
+
+       return 0;
+}
+
+static const struct clk_ops cpu_ops = {
+       .recalc_rate = clk_cpu_recalc_rate,
+       .round_rate = clk_cpu_round_rate,
+       .set_rate = clk_cpu_set_rate,
+};
+
+void __init of_cpu_clk_setup(struct device_node *node)
+{
+       struct cpu_clk *cpuclk;
+       void __iomem *clock_complex_base = of_iomap(node, 0);
+       int ncpus = 0;
+       struct device_node *dn;
+
+       if (clock_complex_base == NULL) {
+               pr_err("%s: clock-complex base register not set\n",
+                       __func__);
+               return;
+       }
+
+       for_each_node_by_type(dn, "cpu")
+               ncpus++;
+
+       cpuclk = kzalloc(ncpus * sizeof(*cpuclk), GFP_KERNEL);
+       if (WARN_ON(!cpuclk))
+               return;
+
+       clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
+       if (WARN_ON(!clks))
+               return;
+
+       for_each_node_by_type(dn, "cpu") {
+               struct clk_init_data init;
+               struct clk *clk;
+               struct clk *parent_clk;
+               char *clk_name = kzalloc(5, GFP_KERNEL);
+               int cpu, err;
+
+               if (WARN_ON(!clk_name))
+                       return;
+
+               err = of_property_read_u32(dn, "reg", &cpu);
+               if (WARN_ON(err))
+                       return;
+
+               sprintf(clk_name, "cpu%d", cpu);
+               parent_clk = of_clk_get(node, 0);
+
+               cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
+               cpuclk[cpu].clk_name = clk_name;
+               cpuclk[cpu].cpu = cpu;
+               cpuclk[cpu].reg_base = clock_complex_base;
+               cpuclk[cpu].hw.init = &init;
+
+               init.name = cpuclk[cpu].clk_name;
+               init.ops = &cpu_ops;
+               init.flags = 0;
+               init.parent_names = &cpuclk[cpu].parent_name;
+               init.num_parents = 1;
+
+               clk = clk_register(NULL, &cpuclk[cpu].hw);
+               if (WARN_ON(IS_ERR(clk)))
+                       goto bail_out;
+               clks[cpu] = clk;
+       }
+       clk_data.clk_num = MAX_CPU;
+       clk_data.clks = clks;
+       of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data);
+
+       return;
+bail_out:
+       kfree(clks);
+       kfree(cpuclk);
+}
+
+static const __initconst struct of_device_id clk_cpu_match[] = {
+       {
+               .compatible = "marvell,armada-xp-cpu-clock",
+               .data = of_cpu_clk_setup,
+       },
+       {
+               /* sentinel */
+       },
+};
+
+void __init mvebu_cpu_clk_init(void)
+{
+       of_clk_init(clk_cpu_match);
+}
diff --git a/drivers/clk/mvebu/clk-cpu.h b/drivers/clk/mvebu/clk-cpu.h
new file mode 100644 (file)
index 0000000..08e2aff
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Marvell MVEBU CPU clock handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_CLK_CPU_H
+#define __MVEBU_CLK_CPU_H
+
+#ifdef CONFIG_MVEBU_CLK_CPU
+void __init mvebu_cpu_clk_init(void);
+#else
+static inline void mvebu_cpu_clk_init(void) {}
+#endif
+
+#endif
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
new file mode 100644 (file)
index 0000000..c6d3c26
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Marvell MVEBU clock gating control.
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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/kernel.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/mvebu.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+struct mvebu_gating_ctrl {
+       spinlock_t lock;
+       struct clk **gates;
+       int num_gates;
+};
+
+struct mvebu_soc_descr {
+       const char *name;
+       const char *parent;
+       int bit_idx;
+};
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+static struct clk __init *mvebu_clk_gating_get_src(
+       struct of_phandle_args *clkspec, void *data)
+{
+       struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
+       int n;
+
+       if (clkspec->args_count < 1)
+               return ERR_PTR(-EINVAL);
+
+       for (n = 0; n < ctrl->num_gates; n++) {
+               struct clk_gate *gate =
+                       to_clk_gate(__clk_get_hw(ctrl->gates[n]));
+               if (clkspec->args[0] == gate->bit_idx)
+                       return ctrl->gates[n];
+       }
+       return ERR_PTR(-ENODEV);
+}
+
+static void __init mvebu_clk_gating_setup(
+       struct device_node *np, const struct mvebu_soc_descr *descr)
+{
+       struct mvebu_gating_ctrl *ctrl;
+       struct clk *clk;
+       void __iomem *base;
+       const char *default_parent = NULL;
+       int n;
+
+       base = of_iomap(np, 0);
+
+       clk = of_clk_get(np, 0);
+       if (!IS_ERR(clk)) {
+               default_parent = __clk_get_name(clk);
+               clk_put(clk);
+       }
+
+       ctrl = kzalloc(sizeof(struct mvebu_gating_ctrl), GFP_KERNEL);
+       if (WARN_ON(!ctrl))
+               return;
+
+       spin_lock_init(&ctrl->lock);
+
+       /*
+        * Count, allocate, and register clock gates
+        */
+       for (n = 0; descr[n].name;)
+               n++;
+
+       ctrl->num_gates = n;
+       ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
+                             GFP_KERNEL);
+       if (WARN_ON(!ctrl->gates)) {
+               kfree(ctrl);
+               return;
+       }
+
+       for (n = 0; n < ctrl->num_gates; n++) {
+               u8 flags = 0;
+               const char *parent =
+                       (descr[n].parent) ? descr[n].parent : default_parent;
+
+               /*
+                * On Armada 370, the DDR clock is a special case: it
+                * isn't taken by any driver, but should anyway be
+                * kept enabled, so we mark it as IGNORE_UNUSED for
+                * now.
+                */
+               if (!strcmp(descr[n].name, "ddr"))
+                       flags |= CLK_IGNORE_UNUSED;
+
+               ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
+                                  flags, base, descr[n].bit_idx, 0, &ctrl->lock);
+               WARN_ON(IS_ERR(ctrl->gates[n]));
+       }
+       of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
+}
+
+/*
+ * SoC specific clock gating control
+ */
+
+#ifdef CONFIG_MACH_ARMADA_370
+static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
+       { "audio", NULL, 0 },
+       { "pex0_en", NULL, 1 },
+       { "pex1_en", NULL,  2 },
+       { "ge1", NULL, 3 },
+       { "ge0", NULL, 4 },
+       { "pex0", NULL, 5 },
+       { "pex1", NULL, 9 },
+       { "sata0", NULL, 15 },
+       { "sdio", NULL, 17 },
+       { "tdm", NULL, 25 },
+       { "ddr", NULL, 28 },
+       { "sata1", NULL, 30 },
+       { }
+};
+#endif
+
+#ifdef CONFIG_MACH_ARMADA_XP
+static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
+       { "audio", NULL, 0 },
+       { "ge3", NULL, 1 },
+       { "ge2", NULL,  2 },
+       { "ge1", NULL, 3 },
+       { "ge0", NULL, 4 },
+       { "pex0", NULL, 5 },
+       { "pex1", NULL, 6 },
+       { "pex2", NULL, 7 },
+       { "pex3", NULL, 8 },
+       { "bp", NULL, 13 },
+       { "sata0lnk", NULL, 14 },
+       { "sata0", "sata0lnk", 15 },
+       { "lcd", NULL, 16 },
+       { "sdio", NULL, 17 },
+       { "usb0", NULL, 18 },
+       { "usb1", NULL, 19 },
+       { "usb2", NULL, 20 },
+       { "xor0", NULL, 22 },
+       { "crypto", NULL, 23 },
+       { "tdm", NULL, 25 },
+       { "xor1", NULL, 28 },
+       { "sata1lnk", NULL, 29 },
+       { "sata1", "sata1lnk", 30 },
+       { }
+};
+#endif
+
+#ifdef CONFIG_ARCH_DOVE
+static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
+       { "usb0", NULL, 0 },
+       { "usb1", NULL, 1 },
+       { "ge", "gephy", 2 },
+       { "sata", NULL, 3 },
+       { "pex0", NULL, 4 },
+       { "pex1", NULL, 5 },
+       { "sdio0", NULL, 8 },
+       { "sdio1", NULL, 9 },
+       { "nand", NULL, 10 },
+       { "camera", NULL, 11 },
+       { "i2s0", NULL, 12 },
+       { "i2s1", NULL, 13 },
+       { "crypto", NULL, 15 },
+       { "ac97", NULL, 21 },
+       { "pdma", NULL, 22 },
+       { "xor0", NULL, 23 },
+       { "xor1", NULL, 24 },
+       { "gephy", NULL, 30 },
+       { }
+};
+#endif
+
+#ifdef CONFIG_ARCH_KIRKWOOD
+static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
+       { "ge0", NULL, 0 },
+       { "pex0", NULL, 2 },
+       { "usb0", NULL, 3 },
+       { "sdio", NULL, 4 },
+       { "tsu", NULL, 5 },
+       { "runit", NULL, 7 },
+       { "xor0", NULL, 8 },
+       { "audio", NULL, 9 },
+       { "sata0", NULL, 14 },
+       { "sata1", NULL, 15 },
+       { "xor1", NULL, 16 },
+       { "crypto", NULL, 17 },
+       { "pex1", NULL, 18 },
+       { "ge1", NULL, 19 },
+       { "tdm", NULL, 20 },
+       { }
+};
+#endif
+
+static const __initdata struct of_device_id clk_gating_match[] = {
+#ifdef CONFIG_MACH_ARMADA_370
+       {
+               .compatible = "marvell,armada-370-gating-clock",
+               .data = armada_370_gating_descr,
+       },
+#endif
+
+#ifdef CONFIG_MACH_ARMADA_XP
+       {
+               .compatible = "marvell,armada-xp-gating-clock",
+               .data = armada_xp_gating_descr,
+       },
+#endif
+
+#ifdef CONFIG_ARCH_DOVE
+       {
+               .compatible = "marvell,dove-gating-clock",
+               .data = dove_gating_descr,
+       },
+#endif
+
+#ifdef CONFIG_ARCH_KIRKWOOD
+       {
+               .compatible = "marvell,kirkwood-gating-clock",
+               .data = kirkwood_gating_descr,
+       },
+#endif
+
+       { }
+};
+
+void __init mvebu_gating_clk_init(void)
+{
+       struct device_node *np;
+
+       for_each_matching_node(np, clk_gating_match) {
+               const struct of_device_id *match =
+                       of_match_node(clk_gating_match, np);
+               mvebu_clk_gating_setup(np,
+                      (const struct mvebu_soc_descr *)match->data);
+       }
+}
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.h b/drivers/clk/mvebu/clk-gating-ctrl.h
new file mode 100644 (file)
index 0000000..9275d1e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Marvell EBU gating clock handling
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_CLK_GATING_H
+#define __MVEBU_CLK_GATING_H
+
+#ifdef CONFIG_MVEBU_CLK_GATING
+void __init mvebu_gating_clk_init(void);
+#else
+void mvebu_gating_clk_init(void) {}
+#endif
+
+#endif
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c
new file mode 100644 (file)
index 0000000..855681b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Marvell EBU SoC clock handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/clk/mvebu.h>
+#include <linux/of.h>
+#include "clk-core.h"
+#include "clk-cpu.h"
+#include "clk-gating-ctrl.h"
+
+void __init mvebu_clocks_init(void)
+{
+       mvebu_core_clk_init();
+       mvebu_gating_clk_init();
+       mvebu_cpu_clk_init();
+}
index 147e25f00405aa4bd0968935bc3be7948ba26715..ed9af4278619a574d41a5489b796caaa7531de8c 100644 (file)
@@ -20,6 +20,7 @@
 #include <mach/spear.h>
 #include "clk.h"
 
+#define VA_SPEAR1310_RAS_BASE                  IOMEM(UL(0xFA400000))
 /* PLL related registers and bit values */
 #define SPEAR1310_PLL_CFG                      (VA_MISC_BASE + 0x210)
        /* PLL_CFG bit values */
index 4674f94957cd35398f8ea7fcb5e13ad6fde38fea..a4605fd7e3039be92612db8e7dffca6372e1ff32 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/timer.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
@@ -167,7 +168,6 @@ void __init armada_370_xp_timer_init(void)
        u32 u;
        struct device_node *np;
        unsigned int timer_clk;
-       int ret;
        np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer");
        timer_base = of_iomap(np, 0);
        WARN_ON(!timer_base);
@@ -179,13 +179,14 @@ void __init armada_370_xp_timer_init(void)
                       timer_base + TIMER_CTRL_OFF);
                timer_clk = 25000000;
        } else {
-               u32 clk = 0;
-               ret = of_property_read_u32(np, "clock-frequency", &clk);
-               WARN_ON(!clk || ret < 0);
+               unsigned long rate = 0;
+               struct clk *clk = of_clk_get(np, 0);
+               WARN_ON(IS_ERR(clk));
+               rate =  clk_get_rate(clk);
                u = readl(timer_base + TIMER_CTRL_OFF);
                writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ),
                       timer_base + TIMER_CTRL_OFF);
-               timer_clk = clk / TIMER_DIVIDER;
+               timer_clk = rate / TIMER_DIVIDER;
        }
 
        /* We use timer 0 as clocksource, and timer 1 for
index f6644f59fd9da1042cec58487791f689d7ed127a..87ec4d027c253714d19bf076e084711788ac9e13 100644 (file)
@@ -254,6 +254,7 @@ config CRYPTO_DEV_OMAP_AES
        tristate "Support for OMAP AES hw engine"
        depends on ARCH_OMAP2 || ARCH_OMAP3
        select CRYPTO_AES
+       select CRYPTO_BLKCIPHER2
        help
          OMAP processors have AES module accelerator. Select this if you
          want to use the OMAP module for AES algorithms.
index 410a03c01ca434065efde5b70e1cf4261c0dd057..c983f869d2b7a58e0a7e7978e294dae6dd0cc5d4 100644 (file)
@@ -1863,6 +1863,7 @@ static int __devexit spacc_remove(struct platform_device *pdev)
 static const struct platform_device_id spacc_id_table[] = {
        { "picochip,spacc-ipsec", },
        { "picochip,spacc-l2", },
+       { }
 };
 
 static struct platform_driver spacc_driver = {
index a22714412cda2061c26ccd5a26fe50a4e5891348..49ad8cbade691049819bc33090b3080f34f4e288 100644 (file)
@@ -30,7 +30,7 @@
 #include <crypto/ctr.h>
 
 #include <plat/cpu.h>
-#include <plat/dma.h>
+#include <mach/dma.h>
 
 #define _SBF(s, v)                      ((v) << (s))
 #define _BIT(b)                         _SBF(b, 1)
index da1112765a4465066ecff9bba2ad52900d19944d..09b184adf31b73902a98651843805e0c129c15b9 100644 (file)
@@ -936,8 +936,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
                sg_count--;
                link_tbl_ptr--;
        }
-       link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len)
-                                       + cryptlen);
+       be16_add_cpu(&link_tbl_ptr->len, cryptlen);
 
        /* tag end of link table */
        link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
index e69f3bc473bede522aa7c31ead313402d8e3640c..eb32fd8cad147eacbaaf115516945736fa37ad7d 100644 (file)
@@ -672,8 +672,10 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
        mutex_lock(&aes_lock);
 
        ret = clk_prepare_enable(dd->aes_clk);
-       if (ret)
+       if (ret) {
+               mutex_unlock(&aes_lock);
                return ret;
+       }
 
        ctx->dd = dd;
        dd->ctx = ctx;
@@ -757,8 +759,10 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
        dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
 
        ret = clk_prepare_enable(dd->aes_clk);
-       if (ret)
+       if (ret) {
+               mutex_unlock(&aes_lock);
                return ret;
+       }
 
        aes_set_key(dd);
 
@@ -1029,7 +1033,7 @@ out:
        if (dd->buf_out)
                dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
                        dd->buf_out, dd->dma_buf_out);
-       if (IS_ERR(dd->aes_clk))
+       if (!IS_ERR(dd->aes_clk))
                clk_put(dd->aes_clk);
        if (aes_wq)
                destroy_workqueue(aes_wq);
index d12ad00da4cbde3e7b9d16ccba3d85061d065822..ac71f555dd729cd0a234f02b473f06271f36ae89 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/platform_device.h>
 #include <linux/memory.h>
 #include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/platform_data/dma-mv_xor.h>
 
 #include "dmaengine.h"
 static void mv_xor_issue_pending(struct dma_chan *chan);
 
 #define to_mv_xor_chan(chan)           \
-       container_of(chan, struct mv_xor_chan, common)
-
-#define to_mv_xor_device(dev)          \
-       container_of(dev, struct mv_xor_device, common)
+       container_of(chan, struct mv_xor_chan, dmachan)
 
 #define to_mv_xor_slot(tx)             \
        container_of(tx, struct mv_xor_desc_slot, async_tx)
 
+#define mv_chan_to_devp(chan)           \
+       ((chan)->dmadev.dev)
+
 static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
 {
        struct mv_xor_desc *hw_desc = desc->hw_desc;
@@ -166,7 +169,7 @@ static int mv_is_err_intr(u32 intr_cause)
 static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
 {
        u32 val = ~(1 << (chan->idx * 16));
-       dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
+       dev_dbg(mv_chan_to_devp(chan), "%s, val 0x%08x\n", __func__, val);
        __raw_writel(val, XOR_INTR_CAUSE(chan));
 }
 
@@ -206,9 +209,9 @@ static void mv_set_mode(struct mv_xor_chan *chan,
                op_mode = XOR_OPERATION_MODE_MEMSET;
                break;
        default:
-               dev_printk(KERN_ERR, chan->device->common.dev,
-                          "error: unsupported operation %d.\n",
-                          type);
+               dev_err(mv_chan_to_devp(chan),
+                       "error: unsupported operation %d.\n",
+                       type);
                BUG();
                return;
        }
@@ -223,7 +226,7 @@ static void mv_chan_activate(struct mv_xor_chan *chan)
 {
        u32 activation;
 
-       dev_dbg(chan->device->common.dev, " activate chan.\n");
+       dev_dbg(mv_chan_to_devp(chan), " activate chan.\n");
        activation = __raw_readl(XOR_ACTIVATION(chan));
        activation |= 0x1;
        __raw_writel(activation, XOR_ACTIVATION(chan));
@@ -251,7 +254,7 @@ static int mv_chan_xor_slot_count(size_t len, int src_cnt)
 static void mv_xor_free_slots(struct mv_xor_chan *mv_chan,
                              struct mv_xor_desc_slot *slot)
 {
-       dev_dbg(mv_chan->device->common.dev, "%s %d slot %p\n",
+       dev_dbg(mv_chan_to_devp(mv_chan), "%s %d slot %p\n",
                __func__, __LINE__, slot);
 
        slot->slots_per_op = 0;
@@ -266,7 +269,7 @@ static void mv_xor_free_slots(struct mv_xor_chan *mv_chan,
 static void mv_xor_start_new_chain(struct mv_xor_chan *mv_chan,
                                   struct mv_xor_desc_slot *sw_desc)
 {
-       dev_dbg(mv_chan->device->common.dev, "%s %d: sw_desc %p\n",
+       dev_dbg(mv_chan_to_devp(mv_chan), "%s %d: sw_desc %p\n",
                __func__, __LINE__, sw_desc);
        if (sw_desc->type != mv_chan->current_type)
                mv_set_mode(mv_chan, sw_desc->type);
@@ -284,7 +287,7 @@ static void mv_xor_start_new_chain(struct mv_xor_chan *mv_chan,
                mv_chan_set_next_descriptor(mv_chan, sw_desc->async_tx.phys);
        }
        mv_chan->pending += sw_desc->slot_cnt;
-       mv_xor_issue_pending(&mv_chan->common);
+       mv_xor_issue_pending(&mv_chan->dmachan);
 }
 
 static dma_cookie_t
@@ -308,8 +311,7 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
                 */
                if (desc->group_head && desc->unmap_len) {
                        struct mv_xor_desc_slot *unmap = desc->group_head;
-                       struct device *dev =
-                               &mv_chan->device->pdev->dev;
+                       struct device *dev = mv_chan_to_devp(mv_chan);
                        u32 len = unmap->unmap_len;
                        enum dma_ctrl_flags flags = desc->async_tx.flags;
                        u32 src_cnt;
@@ -353,7 +355,7 @@ mv_xor_clean_completed_slots(struct mv_xor_chan *mv_chan)
 {
        struct mv_xor_desc_slot *iter, *_iter;
 
-       dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+       dev_dbg(mv_chan_to_devp(mv_chan), "%s %d\n", __func__, __LINE__);
        list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
                                 completed_node) {
 
@@ -369,7 +371,7 @@ static int
 mv_xor_clean_slot(struct mv_xor_desc_slot *desc,
        struct mv_xor_chan *mv_chan)
 {
-       dev_dbg(mv_chan->device->common.dev, "%s %d: desc %p flags %d\n",
+       dev_dbg(mv_chan_to_devp(mv_chan), "%s %d: desc %p flags %d\n",
                __func__, __LINE__, desc, desc->async_tx.flags);
        list_del(&desc->chain_node);
        /* the client is allowed to attach dependent operations
@@ -393,8 +395,8 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
        u32 current_desc = mv_chan_get_current_desc(mv_chan);
        int seen_current = 0;
 
-       dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
-       dev_dbg(mv_chan->device->common.dev, "current_desc %x\n", current_desc);
+       dev_dbg(mv_chan_to_devp(mv_chan), "%s %d\n", __func__, __LINE__);
+       dev_dbg(mv_chan_to_devp(mv_chan), "current_desc %x\n", current_desc);
        mv_xor_clean_completed_slots(mv_chan);
 
        /* free completed slots from the chain starting with
@@ -438,7 +440,7 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
        }
 
        if (cookie > 0)
-               mv_chan->common.completed_cookie = cookie;
+               mv_chan->dmachan.completed_cookie = cookie;
 }
 
 static void
@@ -547,7 +549,7 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
        dma_cookie_t cookie;
        int new_hw_chain = 1;
 
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s sw_desc %p: async_tx %p\n",
                __func__, sw_desc, &sw_desc->async_tx);
 
@@ -570,7 +572,7 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
                if (!mv_can_chain(grp_start))
                        goto submit_done;
 
-               dev_dbg(mv_chan->device->common.dev, "Append to last desc %x\n",
+               dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %x\n",
                        old_chain_tail->async_tx.phys);
 
                /* fix up the hardware chain */
@@ -604,9 +606,7 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
        int idx;
        struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
        struct mv_xor_desc_slot *slot = NULL;
-       struct mv_xor_platform_data *plat_data =
-               mv_chan->device->pdev->dev.platform_data;
-       int num_descs_in_pool = plat_data->pool_size/MV_XOR_SLOT_SIZE;
+       int num_descs_in_pool = MV_XOR_POOL_SIZE/MV_XOR_SLOT_SIZE;
 
        /* Allocate descriptor slots */
        idx = mv_chan->slots_allocated;
@@ -617,7 +617,7 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
                                " %d descriptor slots", idx);
                        break;
                }
-               hw_desc = (char *) mv_chan->device->dma_desc_pool_virt;
+               hw_desc = (char *) mv_chan->dma_desc_pool_virt;
                slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE];
 
                dma_async_tx_descriptor_init(&slot->async_tx, chan);
@@ -625,7 +625,7 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
                INIT_LIST_HEAD(&slot->chain_node);
                INIT_LIST_HEAD(&slot->slot_node);
                INIT_LIST_HEAD(&slot->tx_list);
-               hw_desc = (char *) mv_chan->device->dma_desc_pool;
+               hw_desc = (char *) mv_chan->dma_desc_pool;
                slot->async_tx.phys =
                        (dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE];
                slot->idx = idx++;
@@ -641,7 +641,7 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
                                        struct mv_xor_desc_slot,
                                        slot_node);
 
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "allocated %d descriptor slots last_used: %p\n",
                mv_chan->slots_allocated, mv_chan->last_used);
 
@@ -656,7 +656,7 @@ mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
        struct mv_xor_desc_slot *sw_desc, *grp_start;
        int slot_cnt;
 
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s dest: %x src %x len: %u flags: %ld\n",
                __func__, dest, src, len, flags);
        if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
@@ -680,7 +680,7 @@ mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
        }
        spin_unlock_bh(&mv_chan->lock);
 
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s sw_desc %p async_tx %p\n",
                __func__, sw_desc, sw_desc ? &sw_desc->async_tx : 0);
 
@@ -695,7 +695,7 @@ mv_xor_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
        struct mv_xor_desc_slot *sw_desc, *grp_start;
        int slot_cnt;
 
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s dest: %x len: %u flags: %ld\n",
                __func__, dest, len, flags);
        if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
@@ -718,7 +718,7 @@ mv_xor_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
                sw_desc->unmap_len = len;
        }
        spin_unlock_bh(&mv_chan->lock);
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s sw_desc %p async_tx %p \n",
                __func__, sw_desc, &sw_desc->async_tx);
        return sw_desc ? &sw_desc->async_tx : NULL;
@@ -737,7 +737,7 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
 
        BUG_ON(len > MV_XOR_MAX_BYTE_COUNT);
 
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s src_cnt: %d len: dest %x %u flags: %ld\n",
                __func__, src_cnt, len, dest, flags);
 
@@ -758,7 +758,7 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
                        mv_desc_set_src_addr(grp_start, src_cnt, src[src_cnt]);
        }
        spin_unlock_bh(&mv_chan->lock);
-       dev_dbg(mv_chan->device->common.dev,
+       dev_dbg(mv_chan_to_devp(mv_chan),
                "%s sw_desc %p async_tx %p \n",
                __func__, sw_desc, &sw_desc->async_tx);
        return sw_desc ? &sw_desc->async_tx : NULL;
@@ -791,12 +791,12 @@ static void mv_xor_free_chan_resources(struct dma_chan *chan)
        }
        mv_chan->last_used = NULL;
 
-       dev_dbg(mv_chan->device->common.dev, "%s slots_allocated %d\n",
+       dev_dbg(mv_chan_to_devp(mv_chan), "%s slots_allocated %d\n",
                __func__, mv_chan->slots_allocated);
        spin_unlock_bh(&mv_chan->lock);
 
        if (in_use_descs)
-               dev_err(mv_chan->device->common.dev,
+               dev_err(mv_chan_to_devp(mv_chan),
                        "freeing %d in use descriptors!\n", in_use_descs);
 }
 
@@ -828,42 +828,42 @@ static void mv_dump_xor_regs(struct mv_xor_chan *chan)
        u32 val;
 
        val = __raw_readl(XOR_CONFIG(chan));
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "config       0x%08x.\n", val);
+       dev_err(mv_chan_to_devp(chan),
+               "config       0x%08x.\n", val);
 
        val = __raw_readl(XOR_ACTIVATION(chan));
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "activation   0x%08x.\n", val);
+       dev_err(mv_chan_to_devp(chan),
+               "activation   0x%08x.\n", val);
 
        val = __raw_readl(XOR_INTR_CAUSE(chan));
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "intr cause   0x%08x.\n", val);
+       dev_err(mv_chan_to_devp(chan),
+               "intr cause   0x%08x.\n", val);
 
        val = __raw_readl(XOR_INTR_MASK(chan));
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "intr mask    0x%08x.\n", val);
+       dev_err(mv_chan_to_devp(chan),
+               "intr mask    0x%08x.\n", val);
 
        val = __raw_readl(XOR_ERROR_CAUSE(chan));
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "error cause  0x%08x.\n", val);
+       dev_err(mv_chan_to_devp(chan),
+               "error cause  0x%08x.\n", val);
 
        val = __raw_readl(XOR_ERROR_ADDR(chan));
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "error addr   0x%08x.\n", val);
+       dev_err(mv_chan_to_devp(chan),
+               "error addr   0x%08x.\n", val);
 }
 
 static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan,
                                         u32 intr_cause)
 {
        if (intr_cause & (1 << 4)) {
-            dev_dbg(chan->device->common.dev,
+            dev_dbg(mv_chan_to_devp(chan),
                     "ignore this error\n");
             return;
        }
 
-       dev_printk(KERN_ERR, chan->device->common.dev,
-                  "error on chan %d. intr cause 0x%08x.\n",
-                  chan->idx, intr_cause);
+       dev_err(mv_chan_to_devp(chan),
+               "error on chan %d. intr cause 0x%08x.\n",
+               chan->idx, intr_cause);
 
        mv_dump_xor_regs(chan);
        BUG();
@@ -874,7 +874,7 @@ static irqreturn_t mv_xor_interrupt_handler(int irq, void *data)
        struct mv_xor_chan *chan = data;
        u32 intr_cause = mv_chan_get_intr_cause(chan);
 
-       dev_dbg(chan->device->common.dev, "intr cause %x\n", intr_cause);
+       dev_dbg(mv_chan_to_devp(chan), "intr cause %x\n", intr_cause);
 
        if (mv_is_err_intr(intr_cause))
                mv_xor_err_interrupt_handler(chan, intr_cause);
@@ -901,7 +901,7 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
  */
 #define MV_XOR_TEST_SIZE 2000
 
-static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
+static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 {
        int i;
        void *src, *dest;
@@ -910,7 +910,6 @@ static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
        dma_cookie_t cookie;
        struct dma_async_tx_descriptor *tx;
        int err = 0;
-       struct mv_xor_chan *mv_chan;
 
        src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
        if (!src)
@@ -926,10 +925,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
        for (i = 0; i < MV_XOR_TEST_SIZE; i++)
                ((u8 *) src)[i] = (u8)i;
 
-       /* Start copy, using first DMA channel */
-       dma_chan = container_of(device->common.channels.next,
-                               struct dma_chan,
-                               device_node);
+       dma_chan = &mv_chan->dmachan;
        if (mv_xor_alloc_chan_resources(dma_chan) < 1) {
                err = -ENODEV;
                goto out;
@@ -950,18 +946,17 @@ static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
 
        if (mv_xor_status(dma_chan, cookie, NULL) !=
            DMA_SUCCESS) {
-               dev_printk(KERN_ERR, dma_chan->device->dev,
-                          "Self-test copy timed out, disabling\n");
+               dev_err(dma_chan->device->dev,
+                       "Self-test copy timed out, disabling\n");
                err = -ENODEV;
                goto free_resources;
        }
 
-       mv_chan = to_mv_xor_chan(dma_chan);
-       dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+       dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
                                MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
        if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
-               dev_printk(KERN_ERR, dma_chan->device->dev,
-                          "Self-test copy failed compare, disabling\n");
+               dev_err(dma_chan->device->dev,
+                       "Self-test copy failed compare, disabling\n");
                err = -ENODEV;
                goto free_resources;
        }
@@ -976,7 +971,7 @@ out:
 
 #define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
 static int
-mv_xor_xor_self_test(struct mv_xor_device *device)
+mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
 {
        int i, src_idx;
        struct page *dest;
@@ -989,7 +984,6 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
        u8 cmp_byte = 0;
        u32 cmp_word;
        int err = 0;
-       struct mv_xor_chan *mv_chan;
 
        for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
@@ -1022,9 +1016,7 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
 
        memset(page_address(dest), 0, PAGE_SIZE);
 
-       dma_chan = container_of(device->common.channels.next,
-                               struct dma_chan,
-                               device_node);
+       dma_chan = &mv_chan->dmachan;
        if (mv_xor_alloc_chan_resources(dma_chan) < 1) {
                err = -ENODEV;
                goto out;
@@ -1048,22 +1040,21 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
 
        if (mv_xor_status(dma_chan, cookie, NULL) !=
            DMA_SUCCESS) {
-               dev_printk(KERN_ERR, dma_chan->device->dev,
-                          "Self-test xor timed out, disabling\n");
+               dev_err(dma_chan->device->dev,
+                       "Self-test xor timed out, disabling\n");
                err = -ENODEV;
                goto free_resources;
        }
 
-       mv_chan = to_mv_xor_chan(dma_chan);
-       dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+       dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
                                PAGE_SIZE, DMA_FROM_DEVICE);
        for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
                u32 *ptr = page_address(dest);
                if (ptr[i] != cmp_word) {
-                       dev_printk(KERN_ERR, dma_chan->device->dev,
-                                  "Self-test xor failed compare, disabling."
-                                  " index %d, data %x, expected %x\n", i,
-                                  ptr[i], cmp_word);
+                       dev_err(dma_chan->device->dev,
+                               "Self-test xor failed compare, disabling."
+                               " index %d, data %x, expected %x\n", i,
+                               ptr[i], cmp_word);
                        err = -ENODEV;
                        goto free_resources;
                }
@@ -1079,62 +1070,66 @@ out:
        return err;
 }
 
-static int __devexit mv_xor_remove(struct platform_device *dev)
+/* This driver does not implement any of the optional DMA operations. */
+static int
+mv_xor_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+              unsigned long arg)
+{
+       return -ENOSYS;
+}
+
+static int mv_xor_channel_remove(struct mv_xor_chan *mv_chan)
 {
-       struct mv_xor_device *device = platform_get_drvdata(dev);
        struct dma_chan *chan, *_chan;
-       struct mv_xor_chan *mv_chan;
-       struct mv_xor_platform_data *plat_data = dev->dev.platform_data;
+       struct device *dev = mv_chan->dmadev.dev;
 
-       dma_async_device_unregister(&device->common);
+       dma_async_device_unregister(&mv_chan->dmadev);
 
-       dma_free_coherent(&dev->dev, plat_data->pool_size,
-                       device->dma_desc_pool_virt, device->dma_desc_pool);
+       dma_free_coherent(dev, MV_XOR_POOL_SIZE,
+                         mv_chan->dma_desc_pool_virt, mv_chan->dma_desc_pool);
 
-       list_for_each_entry_safe(chan, _chan, &device->common.channels,
-                               device_node) {
-               mv_chan = to_mv_xor_chan(chan);
+       list_for_each_entry_safe(chan, _chan, &mv_chan->dmadev.channels,
+                                device_node) {
                list_del(&chan->device_node);
        }
 
+       free_irq(mv_chan->irq, mv_chan);
+
        return 0;
 }
 
-static int mv_xor_probe(struct platform_device *pdev)
+static struct mv_xor_chan *
+mv_xor_channel_add(struct mv_xor_device *xordev,
+                  struct platform_device *pdev,
+                  int idx, dma_cap_mask_t cap_mask, int irq)
 {
        int ret = 0;
-       int irq;
-       struct mv_xor_device *adev;
        struct mv_xor_chan *mv_chan;
        struct dma_device *dma_dev;
-       struct mv_xor_platform_data *plat_data = pdev->dev.platform_data;
 
+       mv_chan = devm_kzalloc(&pdev->dev, sizeof(*mv_chan), GFP_KERNEL);
+       if (!mv_chan) {
+               ret = -ENOMEM;
+               goto err_free_dma;
+       }
 
-       adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL);
-       if (!adev)
-               return -ENOMEM;
+       mv_chan->idx = idx;
+       mv_chan->irq = irq;
 
-       dma_dev = &adev->common;
+       dma_dev = &mv_chan->dmadev;
 
        /* allocate coherent memory for hardware descriptors
         * note: writecombine gives slightly better performance, but
         * requires that we explicitly flush the writes
         */
-       adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
-                                                         plat_data->pool_size,
-                                                         &adev->dma_desc_pool,
-                                                         GFP_KERNEL);
-       if (!adev->dma_desc_pool_virt)
-               return -ENOMEM;
-
-       adev->id = plat_data->hw_id;
+       mv_chan->dma_desc_pool_virt =
+         dma_alloc_writecombine(&pdev->dev, MV_XOR_POOL_SIZE,
+                                &mv_chan->dma_desc_pool, GFP_KERNEL);
+       if (!mv_chan->dma_desc_pool_virt)
+               return ERR_PTR(-ENOMEM);
 
        /* discover transaction capabilites from the platform data */
-       dma_dev->cap_mask = plat_data->cap_mask;
-       adev->pdev = pdev;
-       platform_set_drvdata(pdev, adev);
-
-       adev->shared = platform_get_drvdata(plat_data->shared);
+       dma_dev->cap_mask = cap_mask;
 
        INIT_LIST_HEAD(&dma_dev->channels);
 
@@ -1143,6 +1138,7 @@ static int mv_xor_probe(struct platform_device *pdev)
        dma_dev->device_free_chan_resources = mv_xor_free_chan_resources;
        dma_dev->device_tx_status = mv_xor_status;
        dma_dev->device_issue_pending = mv_xor_issue_pending;
+       dma_dev->device_control = mv_xor_control;
        dma_dev->dev = &pdev->dev;
 
        /* set prep routines based on capability */
@@ -1155,15 +1151,7 @@ static int mv_xor_probe(struct platform_device *pdev)
                dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
        }
 
-       mv_chan = devm_kzalloc(&pdev->dev, sizeof(*mv_chan), GFP_KERNEL);
-       if (!mv_chan) {
-               ret = -ENOMEM;
-               goto err_free_dma;
-       }
-       mv_chan->device = adev;
-       mv_chan->idx = plat_data->hw_id;
-       mv_chan->mmr_base = adev->shared->xor_base;
-
+       mv_chan->mmr_base = xordev->xor_base;
        if (!mv_chan->mmr_base) {
                ret = -ENOMEM;
                goto err_free_dma;
@@ -1174,14 +1162,8 @@ static int mv_xor_probe(struct platform_device *pdev)
        /* clear errors before enabling interrupts */
        mv_xor_device_clear_err_status(mv_chan);
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto err_free_dma;
-       }
-       ret = devm_request_irq(&pdev->dev, irq,
-                              mv_xor_interrupt_handler,
-                              0, dev_name(&pdev->dev), mv_chan);
+       ret = request_irq(mv_chan->irq, mv_xor_interrupt_handler,
+                         0, dev_name(&pdev->dev), mv_chan);
        if (ret)
                goto err_free_dma;
 
@@ -1193,26 +1175,26 @@ static int mv_xor_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&mv_chan->chain);
        INIT_LIST_HEAD(&mv_chan->completed_slots);
        INIT_LIST_HEAD(&mv_chan->all_slots);
-       mv_chan->common.device = dma_dev;
-       dma_cookie_init(&mv_chan->common);
+       mv_chan->dmachan.device = dma_dev;
+       dma_cookie_init(&mv_chan->dmachan);
 
-       list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
+       list_add_tail(&mv_chan->dmachan.device_node, &dma_dev->channels);
 
        if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
-               ret = mv_xor_memcpy_self_test(adev);
+               ret = mv_xor_memcpy_self_test(mv_chan);
                dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
                if (ret)
-                       goto err_free_dma;
+                       goto err_free_irq;
        }
 
        if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-               ret = mv_xor_xor_self_test(adev);
+               ret = mv_xor_xor_self_test(mv_chan);
                dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
                if (ret)
-                       goto err_free_dma;
+                       goto err_free_irq;
        }
 
-       dev_printk(KERN_INFO, &pdev->dev, "Marvell XOR: "
+       dev_info(&pdev->dev, "Marvell XOR: "
          "( %s%s%s%s)\n",
          dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
          dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
@@ -1220,20 +1202,21 @@ static int mv_xor_probe(struct platform_device *pdev)
          dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
 
        dma_async_device_register(dma_dev);
-       goto out;
+       return mv_chan;
 
+err_free_irq:
+       free_irq(mv_chan->irq, mv_chan);
  err_free_dma:
-       dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
-                       adev->dma_desc_pool_virt, adev->dma_desc_pool);
- out:
-       return ret;
+       dma_free_coherent(&pdev->dev, MV_XOR_POOL_SIZE,
+                         mv_chan->dma_desc_pool_virt, mv_chan->dma_desc_pool);
+       return ERR_PTR(ret);
 }
 
 static void
-mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
+mv_xor_conf_mbus_windows(struct mv_xor_device *xordev,
                         const struct mbus_dram_target_info *dram)
 {
-       void __iomem *base = msp->xor_base;
+       void __iomem *base = xordev->xor_base;
        u32 win_enable = 0;
        int i;
 
@@ -1258,99 +1241,176 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
 
        writel(win_enable, base + WINDOW_BAR_ENABLE(0));
        writel(win_enable, base + WINDOW_BAR_ENABLE(1));
+       writel(0, base + WINDOW_OVERRIDE_CTRL(0));
+       writel(0, base + WINDOW_OVERRIDE_CTRL(1));
 }
 
-static struct platform_driver mv_xor_driver = {
-       .probe          = mv_xor_probe,
-       .remove         = mv_xor_remove,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = MV_XOR_NAME,
-       },
-};
-
-static int mv_xor_shared_probe(struct platform_device *pdev)
+static int mv_xor_probe(struct platform_device *pdev)
 {
        const struct mbus_dram_target_info *dram;
-       struct mv_xor_shared_private *msp;
+       struct mv_xor_device *xordev;
+       struct mv_xor_platform_data *pdata = pdev->dev.platform_data;
        struct resource *res;
+       int i, ret;
 
-       dev_printk(KERN_NOTICE, &pdev->dev, "Marvell shared XOR driver\n");
+       dev_notice(&pdev->dev, "Marvell XOR driver\n");
 
-       msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
-       if (!msp)
+       xordev = devm_kzalloc(&pdev->dev, sizeof(*xordev), GFP_KERNEL);
+       if (!xordev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENODEV;
 
-       msp->xor_base = devm_ioremap(&pdev->dev, res->start,
-                                    resource_size(res));
-       if (!msp->xor_base)
+       xordev->xor_base = devm_ioremap(&pdev->dev, res->start,
+                                       resource_size(res));
+       if (!xordev->xor_base)
                return -EBUSY;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!res)
                return -ENODEV;
 
-       msp->xor_high_base = devm_ioremap(&pdev->dev, res->start,
-                                         resource_size(res));
-       if (!msp->xor_high_base)
+       xordev->xor_high_base = devm_ioremap(&pdev->dev, res->start,
+                                            resource_size(res));
+       if (!xordev->xor_high_base)
                return -EBUSY;
 
-       platform_set_drvdata(pdev, msp);
+       platform_set_drvdata(pdev, xordev);
 
        /*
         * (Re-)program MBUS remapping windows if we are asked to.
         */
        dram = mv_mbus_dram_info();
        if (dram)
-               mv_xor_conf_mbus_windows(msp, dram);
+               mv_xor_conf_mbus_windows(xordev, dram);
 
        /* Not all platforms can gate the clock, so it is not
         * an error if the clock does not exists.
         */
-       msp->clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(msp->clk))
-               clk_prepare_enable(msp->clk);
+       xordev->clk = clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(xordev->clk))
+               clk_prepare_enable(xordev->clk);
+
+       if (pdev->dev.of_node) {
+               struct device_node *np;
+               int i = 0;
+
+               for_each_child_of_node(pdev->dev.of_node, np) {
+                       dma_cap_mask_t cap_mask;
+                       int irq;
+
+                       dma_cap_zero(cap_mask);
+                       if (of_property_read_bool(np, "dmacap,memcpy"))
+                               dma_cap_set(DMA_MEMCPY, cap_mask);
+                       if (of_property_read_bool(np, "dmacap,xor"))
+                               dma_cap_set(DMA_XOR, cap_mask);
+                       if (of_property_read_bool(np, "dmacap,memset"))
+                               dma_cap_set(DMA_MEMSET, cap_mask);
+                       if (of_property_read_bool(np, "dmacap,interrupt"))
+                               dma_cap_set(DMA_INTERRUPT, cap_mask);
+
+                       irq = irq_of_parse_and_map(np, 0);
+                       if (!irq) {
+                               ret = -ENODEV;
+                               goto err_channel_add;
+                       }
+
+                       xordev->channels[i] =
+                               mv_xor_channel_add(xordev, pdev, i,
+                                                  cap_mask, irq);
+                       if (IS_ERR(xordev->channels[i])) {
+                               ret = PTR_ERR(xordev->channels[i]);
+                               xordev->channels[i] = NULL;
+                               irq_dispose_mapping(irq);
+                               goto err_channel_add;
+                       }
+
+                       i++;
+               }
+       } else if (pdata && pdata->channels) {
+               for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
+                       struct mv_xor_channel_data *cd;
+                       int irq;
+
+                       cd = &pdata->channels[i];
+                       if (!cd) {
+                               ret = -ENODEV;
+                               goto err_channel_add;
+                       }
+
+                       irq = platform_get_irq(pdev, i);
+                       if (irq < 0) {
+                               ret = irq;
+                               goto err_channel_add;
+                       }
+
+                       xordev->channels[i] =
+                               mv_xor_channel_add(xordev, pdev, i,
+                                                  cd->cap_mask, irq);
+                       if (IS_ERR(xordev->channels[i])) {
+                               ret = PTR_ERR(xordev->channels[i]);
+                               goto err_channel_add;
+                       }
+               }
+       }
 
        return 0;
+
+err_channel_add:
+       for (i = 0; i < MV_XOR_MAX_CHANNELS; i++)
+               if (xordev->channels[i]) {
+                       if (pdev->dev.of_node)
+                               irq_dispose_mapping(xordev->channels[i]->irq);
+                       mv_xor_channel_remove(xordev->channels[i]);
+               }
+
+       clk_disable_unprepare(xordev->clk);
+       clk_put(xordev->clk);
+       return ret;
 }
 
-static int mv_xor_shared_remove(struct platform_device *pdev)
+static int mv_xor_remove(struct platform_device *pdev)
 {
-       struct mv_xor_shared_private *msp = platform_get_drvdata(pdev);
+       struct mv_xor_device *xordev = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
+               if (xordev->channels[i])
+                       mv_xor_channel_remove(xordev->channels[i]);
+       }
 
-       if (!IS_ERR(msp->clk)) {
-               clk_disable_unprepare(msp->clk);
-               clk_put(msp->clk);
+       if (!IS_ERR(xordev->clk)) {
+               clk_disable_unprepare(xordev->clk);
+               clk_put(xordev->clk);
        }
 
        return 0;
 }
 
-static struct platform_driver mv_xor_shared_driver = {
-       .probe          = mv_xor_shared_probe,
-       .remove         = mv_xor_shared_remove,
+#ifdef CONFIG_OF
+static struct of_device_id mv_xor_dt_ids[] = {
+       { .compatible = "marvell,orion-xor", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mv_xor_dt_ids);
+#endif
+
+static struct platform_driver mv_xor_driver = {
+       .probe          = mv_xor_probe,
+       .remove         = mv_xor_remove,
        .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = MV_XOR_SHARED_NAME,
+               .owner          = THIS_MODULE,
+               .name           = MV_XOR_NAME,
+               .of_match_table = of_match_ptr(mv_xor_dt_ids),
        },
 };
 
 
 static int __init mv_xor_init(void)
 {
-       int rc;
-
-       rc = platform_driver_register(&mv_xor_shared_driver);
-       if (!rc) {
-               rc = platform_driver_register(&mv_xor_driver);
-               if (rc)
-                       platform_driver_unregister(&mv_xor_shared_driver);
-       }
-       return rc;
+       return platform_driver_register(&mv_xor_driver);
 }
 module_init(mv_xor_init);
 
@@ -1359,7 +1419,6 @@ module_init(mv_xor_init);
 static void __exit mv_xor_exit(void)
 {
        platform_driver_unregister(&mv_xor_driver);
-       platform_driver_unregister(&mv_xor_shared_driver);
        return;
 }
 
index a5b422f5a8abf4e3f4485440da8eeb6e01ebfb1b..c632a4761fcff9836e6fbe9e59f90fa1f9080399 100644 (file)
 #include <linux/interrupt.h>
 
 #define USE_TIMER
+#define MV_XOR_POOL_SIZE               PAGE_SIZE
 #define MV_XOR_SLOT_SIZE               64
 #define MV_XOR_THRESHOLD               1
+#define MV_XOR_MAX_CHANNELS             2
 
 #define XOR_OPERATION_MODE_XOR         0
 #define XOR_OPERATION_MODE_MEMCPY      2
 #define WINDOW_SIZE(w)         (0x270 + ((w) << 2))
 #define WINDOW_REMAP_HIGH(w)   (0x290 + ((w) << 2))
 #define WINDOW_BAR_ENABLE(chan)        (0x240 + ((chan) << 2))
+#define WINDOW_OVERRIDE_CTRL(chan)     (0x2A0 + ((chan) << 2))
 
-struct mv_xor_shared_private {
-       void __iomem    *xor_base;
-       void __iomem    *xor_high_base;
-       struct clk      *clk;
-};
-
-
-/**
- * struct mv_xor_device - internal representation of a XOR device
- * @pdev: Platform device
- * @id: HW XOR Device selector
- * @dma_desc_pool: base of DMA descriptor region (DMA address)
- * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
- * @common: embedded struct dma_device
- */
 struct mv_xor_device {
-       struct platform_device          *pdev;
-       int                             id;
-       dma_addr_t                      dma_desc_pool;
-       void                            *dma_desc_pool_virt;
-       struct dma_device               common;
-       struct mv_xor_shared_private    *shared;
+       void __iomem         *xor_base;
+       void __iomem         *xor_high_base;
+       struct clk           *clk;
+       struct mv_xor_chan   *channels[MV_XOR_MAX_CHANNELS];
 };
 
 /**
@@ -96,11 +82,15 @@ struct mv_xor_chan {
        spinlock_t              lock; /* protects the descriptor slot pool */
        void __iomem            *mmr_base;
        unsigned int            idx;
+       int                     irq;
        enum dma_transaction_type       current_type;
        struct list_head        chain;
        struct list_head        completed_slots;
-       struct mv_xor_device    *device;
-       struct dma_chan         common;
+       dma_addr_t              dma_desc_pool;
+       void                    *dma_desc_pool_virt;
+       size_t                  pool_size;
+       struct dma_device       dmadev;
+       struct dma_chan         dmachan;
        struct mv_xor_desc_slot *last_used;
        struct list_head        all_slots;
        int                     slots_allocated;
index bb82d6be793cdc3a61164008f5d73bdb4356e077..4c6c876d9dc3f0fa949352c89039a00b3c0bc79a 100644 (file)
@@ -7,7 +7,7 @@
 menuconfig EDAC
        bool "EDAC (Error Detection And Correction) reporting"
        depends on HAS_IOMEM
-       depends on X86 || PPC || TILE || ARM
+       depends on X86 || PPC || TILE || ARM || EDAC_SUPPORT
        help
          EDAC is designed to report errors in the core system.
          These are low-level errors that are reported in the CPU or
@@ -27,6 +27,9 @@ menuconfig EDAC
          There is also a mailing list for the EDAC project, which can
          be found via the sourceforge page.
 
+config EDAC_SUPPORT
+       bool
+
 if EDAC
 
 comment "Reporting subsystems"
@@ -316,4 +319,32 @@ config EDAC_HIGHBANK_L2
          Support for error detection and correction on the
          Calxeda Highbank memory controller.
 
+config EDAC_OCTEON_PC
+       tristate "Cavium Octeon Primary Caches"
+       depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the primary caches of
+         the cnMIPS cores of Cavium Octeon family SOCs.
+
+config EDAC_OCTEON_L2C
+       tristate "Cavium Octeon Secondary Caches (L2C)"
+       depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the
+         Cavium Octeon family of SOCs.
+
+config EDAC_OCTEON_LMC
+       tristate "Cavium Octeon DRAM Memory Controller (LMC)"
+       depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the
+         Cavium Octeon family of SOCs.
+
+config EDAC_OCTEON_PCI
+       tristate "Cavium Octeon PCI Controller"
+       depends on EDAC_MM_EDAC && PCI && CPU_CAVIUM_OCTEON
+       help
+         Support for error detection and correction on the
+         Cavium Octeon family of SOCs.
+
 endif # EDAC
index 7e5129a733f8cc6b8afdc7dac91228167949512d..5608a9ba61b7aaf442564feac6e586c6a26588cf 100644 (file)
@@ -58,3 +58,8 @@ obj-$(CONFIG_EDAC_TILE)                       += tile_edac.o
 
 obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o
 obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o
+
+obj-$(CONFIG_EDAC_OCTEON_PC)           += octeon_edac-pc.o
+obj-$(CONFIG_EDAC_OCTEON_L2C)          += octeon_edac-l2c.o
+obj-$(CONFIG_EDAC_OCTEON_LMC)          += octeon_edac-lmc.o
+obj-$(CONFIG_EDAC_OCTEON_PCI)          += octeon_edac-pci.o
diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c
new file mode 100644 (file)
index 0000000..40fde6a
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * 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) 2012 Cavium, Inc.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define EDAC_MOD_STR "octeon-l2c"
+
+static void octeon_l2c_poll_oct1(struct edac_device_ctl_info *l2c)
+{
+       union cvmx_l2t_err l2t_err, l2t_err_reset;
+       union cvmx_l2d_err l2d_err, l2d_err_reset;
+
+       l2t_err_reset.u64 = 0;
+       l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+       if (l2t_err.s.sec_err) {
+               edac_device_handle_ce(l2c, 0, 0,
+                                     "Tag Single bit error (corrected)");
+               l2t_err_reset.s.sec_err = 1;
+       }
+       if (l2t_err.s.ded_err) {
+               edac_device_handle_ue(l2c, 0, 0,
+                                     "Tag Double bit error (detected)");
+               l2t_err_reset.s.ded_err = 1;
+       }
+       if (l2t_err_reset.u64)
+               cvmx_write_csr(CVMX_L2T_ERR, l2t_err_reset.u64);
+
+       l2d_err_reset.u64 = 0;
+       l2d_err.u64 = cvmx_read_csr(CVMX_L2D_ERR);
+       if (l2d_err.s.sec_err) {
+               edac_device_handle_ce(l2c, 0, 1,
+                                     "Data Single bit error (corrected)");
+               l2d_err_reset.s.sec_err = 1;
+       }
+       if (l2d_err.s.ded_err) {
+               edac_device_handle_ue(l2c, 0, 1,
+                                     "Data Double bit error (detected)");
+               l2d_err_reset.s.ded_err = 1;
+       }
+       if (l2d_err_reset.u64)
+               cvmx_write_csr(CVMX_L2D_ERR, l2d_err_reset.u64);
+
+}
+
+static void _octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c, int tad)
+{
+       union cvmx_l2c_err_tdtx err_tdtx, err_tdtx_reset;
+       union cvmx_l2c_err_ttgx err_ttgx, err_ttgx_reset;
+       char buf1[64];
+       char buf2[80];
+
+       err_tdtx_reset.u64 = 0;
+       err_tdtx.u64 = cvmx_read_csr(CVMX_L2C_ERR_TDTX(tad));
+       if (err_tdtx.s.dbe || err_tdtx.s.sbe ||
+           err_tdtx.s.vdbe || err_tdtx.s.vsbe)
+               snprintf(buf1, sizeof(buf1),
+                        "type:%d, syn:0x%x, way:%d",
+                        err_tdtx.s.type, err_tdtx.s.syn, err_tdtx.s.wayidx);
+
+       if (err_tdtx.s.dbe) {
+               snprintf(buf2, sizeof(buf2),
+                        "L2D Double bit error (detected):%s", buf1);
+               err_tdtx_reset.s.dbe = 1;
+               edac_device_handle_ue(l2c, tad, 1, buf2);
+       }
+       if (err_tdtx.s.sbe) {
+               snprintf(buf2, sizeof(buf2),
+                        "L2D Single bit error (corrected):%s", buf1);
+               err_tdtx_reset.s.sbe = 1;
+               edac_device_handle_ce(l2c, tad, 1, buf2);
+       }
+       if (err_tdtx.s.vdbe) {
+               snprintf(buf2, sizeof(buf2),
+                        "VBF Double bit error (detected):%s", buf1);
+               err_tdtx_reset.s.vdbe = 1;
+               edac_device_handle_ue(l2c, tad, 1, buf2);
+       }
+       if (err_tdtx.s.vsbe) {
+               snprintf(buf2, sizeof(buf2),
+                        "VBF Single bit error (corrected):%s", buf1);
+               err_tdtx_reset.s.vsbe = 1;
+               edac_device_handle_ce(l2c, tad, 1, buf2);
+       }
+       if (err_tdtx_reset.u64)
+               cvmx_write_csr(CVMX_L2C_ERR_TDTX(tad), err_tdtx_reset.u64);
+
+       err_ttgx_reset.u64 = 0;
+       err_ttgx.u64 = cvmx_read_csr(CVMX_L2C_ERR_TTGX(tad));
+
+       if (err_ttgx.s.dbe || err_ttgx.s.sbe)
+               snprintf(buf1, sizeof(buf1),
+                        "type:%d, syn:0x%x, way:%d",
+                        err_ttgx.s.type, err_ttgx.s.syn, err_ttgx.s.wayidx);
+
+       if (err_ttgx.s.dbe) {
+               snprintf(buf2, sizeof(buf2),
+                        "Tag Double bit error (detected):%s", buf1);
+               err_ttgx_reset.s.dbe = 1;
+               edac_device_handle_ue(l2c, tad, 0, buf2);
+       }
+       if (err_ttgx.s.sbe) {
+               snprintf(buf2, sizeof(buf2),
+                        "Tag Single bit error (corrected):%s", buf1);
+               err_ttgx_reset.s.sbe = 1;
+               edac_device_handle_ce(l2c, tad, 0, buf2);
+       }
+       if (err_ttgx_reset.u64)
+               cvmx_write_csr(CVMX_L2C_ERR_TTGX(tad), err_ttgx_reset.u64);
+}
+
+static void octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c)
+{
+       int i;
+       for (i = 0; i < l2c->nr_instances; i++)
+               _octeon_l2c_poll_oct2(l2c, i);
+}
+
+static int __devinit octeon_l2c_probe(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *l2c;
+
+       int num_tads = OCTEON_IS_MODEL(OCTEON_CN68XX) ? 4 : 1;
+
+       /* 'Tags' are block 0, 'Data' is block 1*/
+       l2c = edac_device_alloc_ctl_info(0, "l2c", num_tads, "l2c", 2, 0,
+                                        NULL, 0, edac_device_alloc_index());
+       if (!l2c)
+               return -ENOMEM;
+
+       l2c->dev = &pdev->dev;
+       platform_set_drvdata(pdev, l2c);
+       l2c->dev_name = dev_name(&pdev->dev);
+
+       l2c->mod_name = "octeon-l2c";
+       l2c->ctl_name = "octeon_l2c_err";
+
+
+       if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) {
+               union cvmx_l2t_err l2t_err;
+               union cvmx_l2d_err l2d_err;
+
+               l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+               l2t_err.s.sec_intena = 0;       /* We poll */
+               l2t_err.s.ded_intena = 0;
+               cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+
+               l2d_err.u64 = cvmx_read_csr(CVMX_L2D_ERR);
+               l2d_err.s.sec_intena = 0;       /* We poll */
+               l2d_err.s.ded_intena = 0;
+               cvmx_write_csr(CVMX_L2T_ERR, l2d_err.u64);
+
+               l2c->edac_check = octeon_l2c_poll_oct1;
+       } else {
+               /* OCTEON II */
+               l2c->edac_check = octeon_l2c_poll_oct2;
+       }
+
+       if (edac_device_add_device(l2c) > 0) {
+               pr_err("%s: edac_device_add_device() failed\n", __func__);
+               goto err;
+       }
+
+
+       return 0;
+
+err:
+       edac_device_free_ctl_info(l2c);
+
+       return -ENXIO;
+}
+
+static int octeon_l2c_remove(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *l2c = platform_get_drvdata(pdev);
+
+       edac_device_del_device(&pdev->dev);
+       edac_device_free_ctl_info(l2c);
+
+       return 0;
+}
+
+static struct platform_driver octeon_l2c_driver = {
+       .probe = octeon_l2c_probe,
+       .remove = octeon_l2c_remove,
+       .driver = {
+                  .name = "octeon_l2c_edac",
+       }
+};
+module_platform_driver(octeon_l2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
new file mode 100644 (file)
index 0000000..33bca76
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * 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) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-lmcx-defs.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define OCTEON_MAX_MC 4
+
+static void octeon_lmc_edac_poll(struct mem_ctl_info *mci)
+{
+       union cvmx_lmcx_mem_cfg0 cfg0;
+       bool do_clear = false;
+       char msg[64];
+
+       cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mci->mc_idx));
+       if (cfg0.s.sec_err || cfg0.s.ded_err) {
+               union cvmx_lmcx_fadr fadr;
+               fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(mci->mc_idx));
+               snprintf(msg, sizeof(msg),
+                        "DIMM %d rank %d bank %d row %d col %d",
+                        fadr.cn30xx.fdimm, fadr.cn30xx.fbunk,
+                        fadr.cn30xx.fbank, fadr.cn30xx.frow, fadr.cn30xx.fcol);
+       }
+
+       if (cfg0.s.sec_err) {
+               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0,
+                                    -1, -1, -1, msg, "");
+               cfg0.s.sec_err = -1;    /* Done, re-arm */
+               do_clear = true;
+       }
+
+       if (cfg0.s.ded_err) {
+               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
+                                    -1, -1, -1, msg, "");
+               cfg0.s.ded_err = -1;    /* Done, re-arm */
+               do_clear = true;
+       }
+       if (do_clear)
+               cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mci->mc_idx), cfg0.u64);
+}
+
+static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci)
+{
+       union cvmx_lmcx_int int_reg;
+       bool do_clear = false;
+       char msg[64];
+
+       int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx));
+       if (int_reg.s.sec_err || int_reg.s.ded_err) {
+               union cvmx_lmcx_fadr fadr;
+               fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(mci->mc_idx));
+               snprintf(msg, sizeof(msg),
+                        "DIMM %d rank %d bank %d row %d col %d",
+                        fadr.cn61xx.fdimm, fadr.cn61xx.fbunk,
+                        fadr.cn61xx.fbank, fadr.cn61xx.frow, fadr.cn61xx.fcol);
+       }
+
+       if (int_reg.s.sec_err) {
+               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0,
+                                    -1, -1, -1, msg, "");
+               int_reg.s.sec_err = -1; /* Done, re-arm */
+               do_clear = true;
+       }
+
+       if (int_reg.s.ded_err) {
+               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
+                                    -1, -1, -1, msg, "");
+               int_reg.s.ded_err = -1; /* Done, re-arm */
+               do_clear = true;
+       }
+       if (do_clear)
+               cvmx_write_csr(CVMX_LMCX_INT(mci->mc_idx), int_reg.u64);
+}
+
+static int __devinit octeon_lmc_edac_probe(struct platform_device *pdev)
+{
+       struct mem_ctl_info *mci;
+       struct edac_mc_layer layers[1];
+       int mc = pdev->id;
+
+       layers[0].type = EDAC_MC_LAYER_CHANNEL;
+       layers[0].size = 1;
+       layers[0].is_virt_csrow = false;
+
+       if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) {
+               union cvmx_lmcx_mem_cfg0 cfg0;
+
+               cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0));
+               if (!cfg0.s.ecc_ena) {
+                       dev_info(&pdev->dev, "Disabled (ECC not enabled)\n");
+                       return 0;
+               }
+
+               mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, 0);
+               if (!mci)
+                       return -ENXIO;
+
+               mci->pdev = &pdev->dev;
+               mci->dev_name = dev_name(&pdev->dev);
+
+               mci->mod_name = "octeon-lmc";
+               mci->ctl_name = "octeon-lmc-err";
+               mci->edac_check = octeon_lmc_edac_poll;
+
+               if (edac_mc_add_mc(mci)) {
+                       dev_err(&pdev->dev, "edac_mc_add_mc() failed\n");
+                       edac_mc_free(mci);
+                       return -ENXIO;
+               }
+
+               cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc));
+               cfg0.s.intr_ded_ena = 0;        /* We poll */
+               cfg0.s.intr_sec_ena = 0;
+               cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), cfg0.u64);
+       } else {
+               /* OCTEON II */
+               union cvmx_lmcx_int_en en;
+               union cvmx_lmcx_config config;
+
+               config.u64 = cvmx_read_csr(CVMX_LMCX_CONFIG(0));
+               if (!config.s.ecc_ena) {
+                       dev_info(&pdev->dev, "Disabled (ECC not enabled)\n");
+                       return 0;
+               }
+
+               mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, 0);
+               if (!mci)
+                       return -ENXIO;
+
+               mci->pdev = &pdev->dev;
+               mci->dev_name = dev_name(&pdev->dev);
+
+               mci->mod_name = "octeon-lmc";
+               mci->ctl_name = "co_lmc_err";
+               mci->edac_check = octeon_lmc_edac_poll_o2;
+
+               if (edac_mc_add_mc(mci)) {
+                       dev_err(&pdev->dev, "edac_mc_add_mc() failed\n");
+                       edac_mc_free(mci);
+                       return -ENXIO;
+               }
+
+               en.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc));
+               en.s.intr_ded_ena = 0;  /* We poll */
+               en.s.intr_sec_ena = 0;
+               cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), en.u64);
+       }
+       platform_set_drvdata(pdev, mci);
+
+       return 0;
+}
+
+static int octeon_lmc_edac_remove(struct platform_device *pdev)
+{
+       struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+       edac_mc_del_mc(&pdev->dev);
+       edac_mc_free(mci);
+       return 0;
+}
+
+static struct platform_driver octeon_lmc_edac_driver = {
+       .probe = octeon_lmc_edac_probe,
+       .remove = octeon_lmc_edac_remove,
+       .driver = {
+                  .name = "octeon_lmc_edac",
+       }
+};
+module_platform_driver(octeon_lmc_edac_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c
new file mode 100644 (file)
index 0000000..14a5e57
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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) 2012 Cavium, Inc.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#include <asm/octeon/cvmx.h>
+#include <asm/mipsregs.h>
+
+extern int register_co_cache_error_notifier(struct notifier_block *nb);
+extern int unregister_co_cache_error_notifier(struct notifier_block *nb);
+
+extern unsigned long long cache_err_dcache[NR_CPUS];
+
+struct co_cache_error {
+       struct notifier_block notifier;
+       struct edac_device_ctl_info *ed;
+};
+
+/**
+ * EDAC CPU cache error callback
+ *
+ * @event: non-zero if unrecoverable.
+ */
+static int  co_cache_error_event(struct notifier_block *this,
+       unsigned long event, void *ptr)
+{
+       struct co_cache_error *p = container_of(this, struct co_cache_error,
+                                               notifier);
+
+       unsigned int core = cvmx_get_core_num();
+       unsigned int cpu = smp_processor_id();
+       u64 icache_err = read_octeon_c0_icacheerr();
+       u64 dcache_err;
+
+       if (event) {
+               dcache_err = cache_err_dcache[core];
+               cache_err_dcache[core] = 0;
+       } else {
+               dcache_err = read_octeon_c0_dcacheerr();
+       }
+
+       if (icache_err & 1) {
+               edac_device_printk(p->ed, KERN_ERR,
+                                  "CacheErr (Icache):%llx, core %d/cpu %d, cp0_errorepc == %lx\n",
+                                  (unsigned long long)icache_err, core, cpu,
+                                  read_c0_errorepc());
+               write_octeon_c0_icacheerr(0);
+               edac_device_handle_ce(p->ed, cpu, 1, "icache");
+       }
+       if (dcache_err & 1) {
+               edac_device_printk(p->ed, KERN_ERR,
+                                  "CacheErr (Dcache):%llx, core %d/cpu %d, cp0_errorepc == %lx\n",
+                                  (unsigned long long)dcache_err, core, cpu,
+                                  read_c0_errorepc());
+               if (event)
+                       edac_device_handle_ue(p->ed, cpu, 0, "dcache");
+               else
+                       edac_device_handle_ce(p->ed, cpu, 0, "dcache");
+
+               /* Clear the error indication */
+               if (OCTEON_IS_MODEL(OCTEON_FAM_2))
+                       write_octeon_c0_dcacheerr(1);
+               else
+                       write_octeon_c0_dcacheerr(0);
+       }
+
+       return NOTIFY_STOP;
+}
+
+static int __devinit co_cache_error_probe(struct platform_device *pdev)
+{
+       struct co_cache_error *p = devm_kzalloc(&pdev->dev, sizeof(*p),
+                                               GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+
+       p->notifier.notifier_call = co_cache_error_event;
+       platform_set_drvdata(pdev, p);
+
+       p->ed = edac_device_alloc_ctl_info(0, "cpu", num_possible_cpus(),
+                                          "cache", 2, 0, NULL, 0,
+                                          edac_device_alloc_index());
+       if (!p->ed)
+               goto err;
+
+       p->ed->dev = &pdev->dev;
+
+       p->ed->dev_name = dev_name(&pdev->dev);
+
+       p->ed->mod_name = "octeon-cpu";
+       p->ed->ctl_name = "cache";
+
+       if (edac_device_add_device(p->ed)) {
+               pr_err("%s: edac_device_add_device() failed\n", __func__);
+               goto err1;
+       }
+
+       register_co_cache_error_notifier(&p->notifier);
+
+       return 0;
+
+err1:
+       edac_device_free_ctl_info(p->ed);
+err:
+       return -ENXIO;
+}
+
+static int co_cache_error_remove(struct platform_device *pdev)
+{
+       struct co_cache_error *p = platform_get_drvdata(pdev);
+
+       unregister_co_cache_error_notifier(&p->notifier);
+       edac_device_del_device(&pdev->dev);
+       edac_device_free_ctl_info(p->ed);
+       return 0;
+}
+
+static struct platform_driver co_cache_error_driver = {
+       .probe = co_cache_error_probe,
+       .remove = co_cache_error_remove,
+       .driver = {
+                  .name = "octeon_pc_edac",
+       }
+};
+module_platform_driver(co_cache_error_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c
new file mode 100644 (file)
index 0000000..758c1ef
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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) 2012 Cavium, Inc.
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+#include <asm/octeon/octeon.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+static void octeon_pci_poll(struct edac_pci_ctl_info *pci)
+{
+       union cvmx_pci_cfg01 cfg01;
+
+       cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01);
+       if (cfg01.s.dpe) {              /* Detected parity error */
+               edac_pci_handle_pe(pci, pci->ctl_name);
+               cfg01.s.dpe = 1;                /* Reset  */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.sse) {
+               edac_pci_handle_npe(pci, "Signaled System Error");
+               cfg01.s.sse = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.rma) {
+               edac_pci_handle_npe(pci, "Received Master Abort");
+               cfg01.s.rma = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.rta) {
+               edac_pci_handle_npe(pci, "Received Target Abort");
+               cfg01.s.rta = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.sta) {
+               edac_pci_handle_npe(pci, "Signaled Target Abort");
+               cfg01.s.sta = 1;                /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+       if (cfg01.s.mdpe) {
+               edac_pci_handle_npe(pci, "Master Data Parity Error");
+               cfg01.s.mdpe = 1;               /* Reset */
+               octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+       }
+}
+
+static int __devinit octeon_pci_probe(struct platform_device *pdev)
+{
+       struct edac_pci_ctl_info *pci;
+       int res = 0;
+
+       pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err");
+       if (!pci)
+               return -ENOMEM;
+
+       pci->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pci);
+       pci->dev_name = dev_name(&pdev->dev);
+
+       pci->mod_name = "octeon-pci";
+       pci->ctl_name = "octeon_pci_err";
+       pci->edac_check = octeon_pci_poll;
+
+       if (edac_pci_add_device(pci, 0) > 0) {
+               pr_err("%s: edac_pci_add_device() failed\n", __func__);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       edac_pci_free_ctl_info(pci);
+
+       return res;
+}
+
+static int octeon_pci_remove(struct platform_device *pdev)
+{
+       struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
+
+       edac_pci_del_device(&pdev->dev);
+       edac_pci_free_ctl_info(pci);
+
+       return 0;
+}
+
+static struct platform_driver octeon_pci_driver = {
+       .probe = octeon_pci_probe,
+       .remove = octeon_pci_remove,
+       .driver = {
+                  .name = "octeon_pci_edac",
+       }
+};
+module_platform_driver(octeon_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
index 6cbb7a514436fd0b355e38a2d6138a65254f147d..2d864b48a48f81ade5818cffb2f3825628020d6c 100644 (file)
@@ -985,8 +985,8 @@ ISABD00 "Racal-Interlan NP600A Ethernet 16bit"
 ISABD02 "Racal-Interlan NI5210/8 Ethernet"
 ISABD03 "Racal-Interlan NI5210/16 Ethernet"
 ISABE00 "Qua Tech PXB-1608 Parallel Expansion Board"
-ISABE01 "Qua Tech ES-100 8 Channel Asyncronous"
-ISABE02 "Qua Tech QS-100M 4 Channel Asyncronous"
+ISABE01 "Qua Tech ES-100 8 Channel Asynchronous"
+ISABE02 "Qua Tech QS-100M 4 Channel Asynchronous"
 ISABE03 "Qua Tech MXI-100 IEEE 488 GPIB"
 ISABE04 "Qua Tech DS-201 Dual Channel RS-422"
 ISABE05 "Qua Tech PXB-721 Parallel Expansion"
index a9a347adb35351a3b04b2e3a089ff6ecd9f0ef38..2cc89ce745c9b432e87920b5499a0c8f50cd2e0a 100644 (file)
@@ -149,10 +149,10 @@ static inline void __init init_ohci1394_initialize(struct ohci *ohci)
        reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
        reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
 
-       /* Accept asyncronous transfer requests from all nodes for now */
+       /* Accept asynchronous transfer requests from all nodes for now */
        reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
 
-       /* Specify asyncronous transfer retries */
+       /* Specify asynchronous transfer retries */
        reg_write(ohci, OHCI1394_ATRetries,
                  OHCI1394_MAX_AT_REQ_RETRIES |
                  (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
index 08c674957af82dfffef5a8a5a2c2aba8a9fd0193..e7a711f53a6f7cd8f0b1316d324034b1ca2acc1c 100644 (file)
@@ -828,7 +828,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
 {
        struct fwnet_device *dev;
        struct fw_iso_packet packet;
-       struct fw_card *card;
        __be16 *hdr_ptr;
        __be32 *buf_ptr;
        int retval;
@@ -840,7 +839,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
        unsigned long flags;
 
        dev = data;
-       card = dev->card;
        hdr_ptr = header;
        length = be16_to_cpup(hdr_ptr);
 
@@ -861,8 +859,8 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
        if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) {
                buf_ptr += 2;
                length -= IEEE1394_GASP_HDR_SIZE;
-               fwnet_incoming_packet(dev, buf_ptr, length,
-                                     source_node_id, -1, true);
+               fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
+                                     context->card->generation, true);
        }
 
        packet.payload_length = dev->rcv_buffer_size;
@@ -958,7 +956,12 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
                        break;
                }
 
-               skb_pull(skb, ptask->max_payload);
+               if (ptask->dest_node == IEEE1394_ALL_NODES) {
+                       skb_pull(skb,
+                                ptask->max_payload + IEEE1394_GASP_HDR_SIZE);
+               } else {
+                       skb_pull(skb, ptask->max_payload);
+               }
                if (ptask->outstanding_pkts > 1) {
                        fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
                                          dg_size, fg_off, datagram_label);
@@ -1062,7 +1065,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
                smp_rmb();
                node_id = dev->card->node_id;
 
-               p = skb_push(ptask->skb, 8);
+               p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
                put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
                put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
                                                | RFC2734_SW_VERSION, &p[4]);
index f25610bb31489a2ded669112c2b2915f826c4de6..6ce6e07c38c1b3ba038ee816e26225e8b5f9ee4a 100644 (file)
@@ -1281,7 +1281,7 @@ static int at_context_queue_packet(struct context *ctx,
        d[0].res_count = cpu_to_le16(packet->timestamp);
 
        /*
-        * The DMA format for asyncronous link packets is different
+        * The DMA format for asynchronous link packets is different
         * from the IEEE1394 layout, so shift the fields around
         * accordingly.
         */
index bb1b392f5cdacd1194e9af1772469c834e4192dd..1162d6b3bf8561d6ed1cfe399643dff6deb4027b 100644 (file)
@@ -1546,8 +1546,6 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
        struct sbp2_logical_unit *lu = sdev->hostdata;
 
        sdev->use_10_for_rw = 1;
-       sdev->no_report_opcodes = 1;
-       sdev->no_write_same = 1;
 
        if (sbp2_param_exclusive_login)
                sdev->manage_start_stop = 1;
index 6e51c1e81f143bd8f44abe1b01bb1915fb584e93..52c5d8956d7dfa02ea332985e31528648f26fe59 100644 (file)
 #include <linux/slab.h>
 #include <linux/pstore.h>
 
+#include <linux/fs.h>
+#include <linux/ramfs.h>
+#include <linux/pagemap.h>
+
 #include <asm/uaccess.h>
 
 #define EFIVARS_VERSION "0.08"
@@ -92,6 +96,12 @@ MODULE_VERSION(EFIVARS_VERSION);
 
 #define DUMP_NAME_LEN 52
 
+/*
+ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
+ * not including trailing NUL
+ */
+#define GUID_LEN 36
+
 /*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
@@ -108,7 +118,6 @@ struct efi_variable {
        __u32         Attributes;
 } __attribute__((packed));
 
-
 struct efivar_entry {
        struct efivars *efivars;
        struct efi_variable var;
@@ -122,6 +131,9 @@ struct efivar_attribute {
        ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
 };
 
+static struct efivars __efivars;
+static struct efivar_operations ops;
+
 #define PSTORE_EFI_ATTRIBUTES \
        (EFI_VARIABLE_NON_VOLATILE | \
         EFI_VARIABLE_BOOTSERVICE_ACCESS | \
@@ -629,14 +641,482 @@ static struct kobj_type efivar_ktype = {
        .default_attrs = def_attrs,
 };
 
-static struct pstore_info efi_pstore_info;
-
 static inline void
 efivar_unregister(struct efivar_entry *var)
 {
        kobject_put(&var->kobj);
 }
 
+static int efivarfs_file_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static int efi_status_to_err(efi_status_t status)
+{
+       int err;
+
+       switch (status) {
+       case EFI_INVALID_PARAMETER:
+               err = -EINVAL;
+               break;
+       case EFI_OUT_OF_RESOURCES:
+               err = -ENOSPC;
+               break;
+       case EFI_DEVICE_ERROR:
+               err = -EIO;
+               break;
+       case EFI_WRITE_PROTECTED:
+               err = -EROFS;
+               break;
+       case EFI_SECURITY_VIOLATION:
+               err = -EACCES;
+               break;
+       case EFI_NOT_FOUND:
+               err = -ENOENT;
+               break;
+       default:
+               err = -EINVAL;
+       }
+
+       return err;
+}
+
+static ssize_t efivarfs_file_write(struct file *file,
+               const char __user *userbuf, size_t count, loff_t *ppos)
+{
+       struct efivar_entry *var = file->private_data;
+       struct efivars *efivars;
+       efi_status_t status;
+       void *data;
+       u32 attributes;
+       struct inode *inode = file->f_mapping->host;
+       unsigned long datasize = count - sizeof(attributes);
+       unsigned long newdatasize;
+       u64 storage_size, remaining_size, max_size;
+       ssize_t bytes = 0;
+
+       if (count < sizeof(attributes))
+               return -EINVAL;
+
+       if (copy_from_user(&attributes, userbuf, sizeof(attributes)))
+               return -EFAULT;
+
+       if (attributes & ~(EFI_VARIABLE_MASK))
+               return -EINVAL;
+
+       efivars = var->efivars;
+
+       /*
+        * Ensure that the user can't allocate arbitrarily large
+        * amounts of memory. Pick a default size of 64K if
+        * QueryVariableInfo() isn't supported by the firmware.
+        */
+       spin_lock(&efivars->lock);
+
+       if (!efivars->ops->query_variable_info)
+               status = EFI_UNSUPPORTED;
+       else {
+               const struct efivar_operations *fops = efivars->ops;
+               status = fops->query_variable_info(attributes, &storage_size,
+                                                  &remaining_size, &max_size);
+       }
+
+       spin_unlock(&efivars->lock);
+
+       if (status != EFI_SUCCESS) {
+               if (status != EFI_UNSUPPORTED)
+                       return efi_status_to_err(status);
+
+               remaining_size = 65536;
+       }
+
+       if (datasize > remaining_size)
+               return -ENOSPC;
+
+       data = kmalloc(datasize, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
+               bytes = -EFAULT;
+               goto out;
+       }
+
+       if (validate_var(&var->var, data, datasize) == false) {
+               bytes = -EINVAL;
+               goto out;
+       }
+
+       /*
+        * The lock here protects the get_variable call, the conditional
+        * set_variable call, and removal of the variable from the efivars
+        * list (in the case of an authenticated delete).
+        */
+       spin_lock(&efivars->lock);
+
+       status = efivars->ops->set_variable(var->var.VariableName,
+                                           &var->var.VendorGuid,
+                                           attributes, datasize,
+                                           data);
+
+       if (status != EFI_SUCCESS) {
+               spin_unlock(&efivars->lock);
+               kfree(data);
+
+               return efi_status_to_err(status);
+       }
+
+       bytes = count;
+
+       /*
+        * Writing to the variable may have caused a change in size (which
+        * could either be an append or an overwrite), or the variable to be
+        * deleted. Perform a GetVariable() so we can tell what actually
+        * happened.
+        */
+       newdatasize = 0;
+       status = efivars->ops->get_variable(var->var.VariableName,
+                                           &var->var.VendorGuid,
+                                           NULL, &newdatasize,
+                                           NULL);
+
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               spin_unlock(&efivars->lock);
+               mutex_lock(&inode->i_mutex);
+               i_size_write(inode, newdatasize + sizeof(attributes));
+               mutex_unlock(&inode->i_mutex);
+
+       } else if (status == EFI_NOT_FOUND) {
+               list_del(&var->list);
+               spin_unlock(&efivars->lock);
+               efivar_unregister(var);
+               drop_nlink(inode);
+               dput(file->f_dentry);
+
+       } else {
+               spin_unlock(&efivars->lock);
+               pr_warn("efivarfs: inconsistent EFI variable implementation? "
+                               "status = %lx\n", status);
+       }
+
+out:
+       kfree(data);
+
+       return bytes;
+}
+
+static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
+               size_t count, loff_t *ppos)
+{
+       struct efivar_entry *var = file->private_data;
+       struct efivars *efivars = var->efivars;
+       efi_status_t status;
+       unsigned long datasize = 0;
+       u32 attributes;
+       void *data;
+       ssize_t size = 0;
+
+       spin_lock(&efivars->lock);
+       status = efivars->ops->get_variable(var->var.VariableName,
+                                           &var->var.VendorGuid,
+                                           &attributes, &datasize, NULL);
+       spin_unlock(&efivars->lock);
+
+       if (status != EFI_BUFFER_TOO_SMALL)
+               return efi_status_to_err(status);
+
+       data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
+
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock(&efivars->lock);
+       status = efivars->ops->get_variable(var->var.VariableName,
+                                           &var->var.VendorGuid,
+                                           &attributes, &datasize,
+                                           (data + sizeof(attributes)));
+       spin_unlock(&efivars->lock);
+
+       if (status != EFI_SUCCESS) {
+               size = efi_status_to_err(status);
+               goto out_free;
+       }
+
+       memcpy(data, &attributes, sizeof(attributes));
+       size = simple_read_from_buffer(userbuf, count, ppos,
+                                      data, datasize + sizeof(attributes));
+out_free:
+       kfree(data);
+
+       return size;
+}
+
+static void efivarfs_evict_inode(struct inode *inode)
+{
+       clear_inode(inode);
+}
+
+static const struct super_operations efivarfs_ops = {
+       .statfs = simple_statfs,
+       .drop_inode = generic_delete_inode,
+       .evict_inode = efivarfs_evict_inode,
+       .show_options = generic_show_options,
+};
+
+static struct super_block *efivarfs_sb;
+
+static const struct inode_operations efivarfs_dir_inode_operations;
+
+static const struct file_operations efivarfs_file_operations = {
+       .open   = efivarfs_file_open,
+       .read   = efivarfs_file_read,
+       .write  = efivarfs_file_write,
+       .llseek = no_llseek,
+};
+
+static struct inode *efivarfs_get_inode(struct super_block *sb,
+                               const struct inode *dir, int mode, dev_t dev)
+{
+       struct inode *inode = new_inode(sb);
+
+       if (inode) {
+               inode->i_ino = get_next_ino();
+               inode->i_uid = inode->i_gid = 0;
+               inode->i_mode = mode;
+               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               switch (mode & S_IFMT) {
+               case S_IFREG:
+                       inode->i_fop = &efivarfs_file_operations;
+                       break;
+               case S_IFDIR:
+                       inode->i_op = &efivarfs_dir_inode_operations;
+                       inode->i_fop = &simple_dir_operations;
+                       inc_nlink(inode);
+                       break;
+               }
+       }
+       return inode;
+}
+
+static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
+{
+       guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
+       guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]);
+       guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]);
+       guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]);
+       guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]);
+       guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]);
+       guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]);
+       guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]);
+       guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]);
+       guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]);
+       guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]);
+       guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]);
+       guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]);
+       guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]);
+       guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]);
+       guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]);
+}
+
+static int efivarfs_create(struct inode *dir, struct dentry *dentry,
+                         umode_t mode, bool excl)
+{
+       struct inode *inode;
+       struct efivars *efivars = &__efivars;
+       struct efivar_entry *var;
+       int namelen, i = 0, err = 0;
+
+       /*
+        * We need a GUID, plus at least one letter for the variable name,
+        * plus the '-' separator
+        */
+       if (dentry->d_name.len < GUID_LEN + 2)
+               return -EINVAL;
+
+       inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
+       if (!inode)
+               return -ENOMEM;
+
+       var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
+       if (!var) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* length of the variable name itself: remove GUID and separator */
+       namelen = dentry->d_name.len - GUID_LEN - 1;
+
+       efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
+                       &var->var.VendorGuid);
+
+       for (i = 0; i < namelen; i++)
+               var->var.VariableName[i] = dentry->d_name.name[i];
+
+       var->var.VariableName[i] = '\0';
+
+       inode->i_private = var;
+       var->efivars = efivars;
+       var->kobj.kset = efivars->kset;
+
+       err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s",
+                            dentry->d_name.name);
+       if (err)
+               goto out;
+
+       kobject_uevent(&var->kobj, KOBJ_ADD);
+       spin_lock(&efivars->lock);
+       list_add(&var->list, &efivars->list);
+       spin_unlock(&efivars->lock);
+       d_instantiate(dentry, inode);
+       dget(dentry);
+out:
+       if (err) {
+               kfree(var);
+               iput(inode);
+       }
+       return err;
+}
+
+static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+       struct efivar_entry *var = dentry->d_inode->i_private;
+       struct efivars *efivars = var->efivars;
+       efi_status_t status;
+
+       spin_lock(&efivars->lock);
+
+       status = efivars->ops->set_variable(var->var.VariableName,
+                                           &var->var.VendorGuid,
+                                           0, 0, NULL);
+
+       if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) {
+               list_del(&var->list);
+               spin_unlock(&efivars->lock);
+               efivar_unregister(var);
+               drop_nlink(dir);
+               dput(dentry);
+               return 0;
+       }
+
+       spin_unlock(&efivars->lock);
+       return -EINVAL;
+};
+
+static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct inode *inode = NULL;
+       struct dentry *root;
+       struct efivar_entry *entry, *n;
+       struct efivars *efivars = &__efivars;
+       char *name;
+
+       efivarfs_sb = sb;
+
+       sb->s_maxbytes          = MAX_LFS_FILESIZE;
+       sb->s_blocksize         = PAGE_CACHE_SIZE;
+       sb->s_blocksize_bits    = PAGE_CACHE_SHIFT;
+       sb->s_magic             = EFIVARFS_MAGIC;
+       sb->s_op                = &efivarfs_ops;
+       sb->s_time_gran         = 1;
+
+       inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
+       if (!inode)
+               return -ENOMEM;
+       inode->i_op = &efivarfs_dir_inode_operations;
+
+       root = d_make_root(inode);
+       sb->s_root = root;
+       if (!root)
+               return -ENOMEM;
+
+       list_for_each_entry_safe(entry, n, &efivars->list, list) {
+               struct dentry *dentry, *root = efivarfs_sb->s_root;
+               unsigned long size = 0;
+               int len, i;
+
+               inode = NULL;
+
+               len = utf16_strlen(entry->var.VariableName);
+
+               /* name, plus '-', plus GUID, plus NUL*/
+               name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
+               if (!name)
+                       goto fail;
+
+               for (i = 0; i < len; i++)
+                       name[i] = entry->var.VariableName[i] & 0xFF;
+
+               name[len] = '-';
+
+               efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);
+
+               name[len+GUID_LEN+1] = '\0';
+
+               inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
+                                         S_IFREG | 0644, 0);
+               if (!inode)
+                       goto fail_name;
+
+               dentry = d_alloc_name(root, name);
+               if (!dentry)
+                       goto fail_inode;
+
+               /* copied by the above to local storage in the dentry. */
+               kfree(name);
+
+               spin_lock(&efivars->lock);
+               efivars->ops->get_variable(entry->var.VariableName,
+                                          &entry->var.VendorGuid,
+                                          &entry->var.Attributes,
+                                          &size,
+                                          NULL);
+               spin_unlock(&efivars->lock);
+
+               mutex_lock(&inode->i_mutex);
+               inode->i_private = entry;
+               i_size_write(inode, size+4);
+               mutex_unlock(&inode->i_mutex);
+               d_add(dentry, inode);
+       }
+
+       return 0;
+
+fail_inode:
+       iput(inode);
+fail_name:
+       kfree(name);
+fail:
+       return -ENOMEM;
+}
+
+static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
+                                   int flags, const char *dev_name, void *data)
+{
+       return mount_single(fs_type, flags, data, efivarfs_fill_super);
+}
+
+static void efivarfs_kill_sb(struct super_block *sb)
+{
+       kill_litter_super(sb);
+       efivarfs_sb = NULL;
+}
+
+static struct file_system_type efivarfs_type = {
+       .name    = "efivarfs",
+       .mount   = efivarfs_mount,
+       .kill_sb = efivarfs_kill_sb,
+};
+
+static const struct inode_operations efivarfs_dir_inode_operations = {
+       .lookup = simple_lookup,
+       .unlink = efivarfs_unlink,
+       .create = efivarfs_create,
+};
+
+static struct pstore_info efi_pstore_info;
+
 #ifdef CONFIG_PSTORE
 
 static int efi_pstore_open(struct pstore_info *psi)
@@ -1065,11 +1545,18 @@ efivar_create_sysfs_entry(struct efivars *efivars,
                          efi_char16_t *variable_name,
                          efi_guid_t *vendor_guid)
 {
-       int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
+       int i, short_name_size;
        char *short_name;
        struct efivar_entry *new_efivar;
 
-       short_name = kzalloc(short_name_size + 1, GFP_KERNEL);
+       /*
+        * Length of the variable bytes in ASCII, plus the '-' separator,
+        * plus the GUID, plus trailing NUL
+        */
+       short_name_size = variable_name_size / sizeof(efi_char16_t)
+                               + 1 + GUID_LEN + 1;
+
+       short_name = kzalloc(short_name_size, GFP_KERNEL);
        new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
 
        if (!short_name || !new_efivar)  {
@@ -1189,6 +1676,7 @@ void unregister_efivars(struct efivars *efivars)
                sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
        kfree(efivars->new_var);
        kfree(efivars->del_var);
+       kobject_put(efivars->kobject);
        kset_unregister(efivars->kset);
 }
 EXPORT_SYMBOL_GPL(unregister_efivars);
@@ -1220,6 +1708,14 @@ int register_efivars(struct efivars *efivars,
                goto out;
        }
 
+       efivars->kobject = kobject_create_and_add("efivars", parent_kobj);
+       if (!efivars->kobject) {
+               pr_err("efivars: Subsystem registration failed.\n");
+               error = -ENOMEM;
+               kset_unregister(efivars->kset);
+               goto out;
+       }
+
        /*
         * Per EFI spec, the maximum storage allocated for both
         * the variable name and variable data is 1024 bytes.
@@ -1262,6 +1758,8 @@ int register_efivars(struct efivars *efivars,
                pstore_register(&efivars->efi_pstore_info);
        }
 
+       register_filesystem(&efivarfs_type);
+
 out:
        kfree(variable_name);
 
@@ -1269,9 +1767,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(register_efivars);
 
-static struct efivars __efivars;
-static struct efivar_operations ops;
-
 /*
  * For now we register the efi subsystem with the firmware subsystem
  * and the vars subsystem with the efi subsystem.  In the future, it
@@ -1302,6 +1797,7 @@ efivars_init(void)
        ops.set_variable = efi.set_variable;
        ops.get_next_variable = efi.get_next_variable;
        ops.query_variable_info = efi.query_variable_info;
+
        error = register_efivars(&__efivars, &ops, efi_kobj);
        if (error)
                goto err_put;
index a5cbeec6f6db47f84aa5b74d1aad0f88f1aef42f..bf892bd68c1769fa35de808fcaf54e739fb142bc 100644 (file)
@@ -504,7 +504,7 @@ config GPIO_ADNP
        help
          This option enables support for N GPIOs found on Avionic Design
          I2C GPIO expanders. The register space will be extended by powers
-         of two, so the controller will need to accomodate for that. For
+         of two, so the controller will need to accommodate for that. For
          example: if a controller provides 48 pins, 6 registers will be
          enough to represent all pins, but the driver will assume a
          register layout for 64 pins (8 registers).
index 219942c660d7d2129e7c21ac375761dcd5309c9f..5d1d21a6dcdd11b20bb57637a333e83d2382bbbb 100644 (file)
@@ -1650,7 +1650,7 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
        ring->wptr = 0;
        WREG32(CP_RB_WPTR, ring->wptr);
 
-       /* set the wb address wether it's enabled or not */
+       /* set the wb address whether it's enabled or not */
        WREG32(CP_RB_RPTR_ADDR,
               ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
        WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
index 81e6a568c29debcf49bb915c5d3aa19bcc88324e..cda01f808f12664d6226cc71facb64ed396d41cd 100644 (file)
@@ -1059,7 +1059,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 
        WREG32(CP_DEBUG, (1 << 27));
 
-       /* set the wb address wether it's enabled or not */
+       /* set the wb address whether it's enabled or not */
        WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
        WREG32(SCRATCH_UMSK, 0xff);
 
@@ -1076,7 +1076,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 #endif
                WREG32(cp_rb_cntl[i], rb_cntl);
 
-               /* set the wb address wether it's enabled or not */
+               /* set the wb address whether it's enabled or not */
                addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET;
                WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC);
                WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF);
index 47634f27f2e5eca62cc6335d95fc246e13a6deb2..ebd69562ef6c802af7956dd168de29bf27f6f19f 100644 (file)
@@ -459,7 +459,7 @@ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *r
  *
  * @ring: radeon_ring structure holding ring information
  *
- * Reset the driver's copy of the wtpr (all asics).
+ * Reset the driver's copy of the wptr (all asics).
  */
 void radeon_ring_undo(struct radeon_ring *ring)
 {
@@ -503,7 +503,7 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
 }
 
 /**
- * radeon_ring_force_activity - update lockup variables
+ * radeon_ring_lockup_update - update lockup variables
  *
  * @ring: radeon_ring structure holding ring information
  *
index 4422d630b33bc4052ddfdc311ea37944f9d87051..010156dd949f392c9732f7a1b63ef0f67de26bd2 100644 (file)
@@ -2007,7 +2007,7 @@ static int si_cp_resume(struct radeon_device *rdev)
        ring->wptr = 0;
        WREG32(CP_RB0_WPTR, ring->wptr);
 
-       /* set the wb address wether it's enabled or not */
+       /* set the wb address whether it's enabled or not */
        WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
        WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
 
@@ -2040,7 +2040,7 @@ static int si_cp_resume(struct radeon_device *rdev)
        ring->wptr = 0;
        WREG32(CP_RB1_WPTR, ring->wptr);
 
-       /* set the wb address wether it's enabled or not */
+       /* set the wb address whether it's enabled or not */
        WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
        WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
 
@@ -2066,7 +2066,7 @@ static int si_cp_resume(struct radeon_device *rdev)
        ring->wptr = 0;
        WREG32(CP_RB2_WPTR, ring->wptr);
 
-       /* set the wb address wether it's enabled or not */
+       /* set the wb address whether it's enabled or not */
        WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
        WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
 
index f34838839b08c1f6f2eb64b8fde03265a9a96ef3..29437eabe0957d67893808ed7d668f54770c3fd7 100644 (file)
@@ -1,7 +1,7 @@
 config VGA_ARB
        bool "VGA Arbitration" if EXPERT
        default y
-       depends on PCI
+       depends on (PCI && !S390)
        help
          Some "legacy" VGA devices implemented on PCI typically have the same
          hard-decoded addresses as they did on ISA. When multiple PCI devices
index 1630150ad2b19e1cf362881ff91e850c044e72d5..e7d6a13ec6a623ab1d4123d80a4aae37bb76aaa9 100644 (file)
@@ -265,6 +265,15 @@ config HID_GYRATION
        ---help---
        Support for Gyration remote control.
 
+config HID_ICADE
+       tristate "ION iCade arcade controller"
+       depends on BT_HIDP
+       ---help---
+       Support for the ION iCade arcade controller to work as a joystick.
+
+       To compile this driver as a module, choose M here: the
+       module will be called hid-icade.
+
 config HID_TWINHAN
        tristate "Twinhan IR remote control"
        depends on USB_HID
@@ -728,4 +737,6 @@ endif # HID
 
 source "drivers/hid/usbhid/Kconfig"
 
+source "drivers/hid/i2c-hid/Kconfig"
+
 endmenu
index cef68ca859d335e7a58853a7fd55dc898b9c825e..b62215716b2fd66fda16b0084f077927a8c3f02f 100644 (file)
@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION)    += hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtek-kbd.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtekff.o
 obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
+obj-$(CONFIG_HID_ICADE)                += hid-icade.o
 obj-$(CONFIG_HID_KENSINGTON)   += hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)     += hid-keytouch.o
 obj-$(CONFIG_HID_KYE)          += hid-kye.o
@@ -93,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX)      += hid-primax.o
 obj-$(CONFIG_HID_PS3REMOTE)    += hid-ps3remote.o
 obj-$(CONFIG_HID_ROCCAT)       += hid-roccat.o hid-roccat-common.o \
        hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
-       hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
-       hid-roccat-savu.o
+       hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
+       hid-roccat-pyra.o hid-roccat-savu.o
 obj-$(CONFIG_HID_SAITEK)       += hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)      += hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
@@ -118,3 +119,4 @@ obj-$(CONFIG_USB_HID)               += usbhid/
 obj-$(CONFIG_USB_MOUSE)                += usbhid/
 obj-$(CONFIG_USB_KBD)          += usbhid/
 
+obj-$(CONFIG_I2C_HID)          += i2c-hid/
index fd7722aecf77929eea158263af6cc1b601287408..d0f7662aacca05caf3596c9edcc8280dfed675e6 100644 (file)
@@ -439,7 +439,8 @@ static const struct hid_device_id apple_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
-               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
                        APPLE_RDESC_JIS },
index f4109fd657ff7a337761f9029969dde8ee71e3cc..eb2ee11b6412ac43e9baa08596b881d92c8430e3 100644 (file)
@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
 static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
 {
        struct hid_field *field;
+       int i;
 
        if (report->maxfield == HID_MAX_FIELDS) {
                hid_err(report->device, "too many fields in report\n");
@@ -110,6 +111,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
        field->value = (s32 *)(field->usage + usages);
        field->report = report;
 
+       for (i = 0; i < usages; i++)
+               field->usage[i].usage_index = i;
+
        return field;
 }
 
@@ -315,6 +319,7 @@ static s32 item_sdata(struct hid_item *item)
 
 static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 {
+       __u32 raw_value;
        switch (item->tag) {
        case HID_GLOBAL_ITEM_TAG_PUSH:
 
@@ -365,7 +370,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
                return 0;
 
        case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-               parser->global.unit_exponent = item_sdata(item);
+               /* Units exponent negative numbers are given through a
+                * two's complement.
+                * See "6.2.2.7 Global Items" for more information. */
+               raw_value = item_udata(item);
+               if (!(raw_value & 0xfffffff0))
+                       parser->global.unit_exponent = hid_snto32(raw_value, 4);
+               else
+                       parser->global.unit_exponent = raw_value;
                return 0;
 
        case HID_GLOBAL_ITEM_TAG_UNIT:
@@ -713,7 +725,12 @@ static int hid_scan_report(struct hid_device *hid)
                                        hid_scan_usage(hid, u);
                                break;
                        }
-               }
+               } else if (page == HID_UP_SENSOR &&
+                       item.type == HID_ITEM_TYPE_MAIN &&
+                       item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
+                       (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
+                       hid->bus == BUS_USB)
+                       hid->group = HID_GROUP_SENSOR_HUB;
        }
 
        return 0;
@@ -865,6 +882,12 @@ static s32 snto32(__u32 value, unsigned n)
        return value & (1 << (n - 1)) ? value | (-1 << n) : value;
 }
 
+s32 hid_snto32(__u32 value, unsigned n)
+{
+       return snto32(value, n);
+}
+EXPORT_SYMBOL_GPL(hid_snto32);
+
 /*
  * Convert a signed 32-bit integer to a signed n-bit integer.
  */
@@ -1465,6 +1488,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
  * there is a proper autodetection and autoloading in place (based on presence
  * of HID_DG_CONTACTID), so those devices don't need to be added to this list,
  * as we are doing the right thing in hid_scan_usage().
+ *
+ * Autodetection for (USB) HID sensor hubs exists too. If a collection of type
+ * physical is found inside a usage page of type sensor, hid-sensor-hub will be
+ * used as a driver. See hid_scan_report().
  */
 static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
@@ -1538,6 +1565,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
@@ -1571,10 +1599,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_1020) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1658,6 +1683,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
@@ -1672,7 +1698,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_SENSOR_HUB_7014) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
@@ -2150,8 +2175,13 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { }
 };
 
-static bool hid_ignore(struct hid_device *hdev)
+bool hid_ignore(struct hid_device *hdev)
 {
+       if (hdev->quirks & HID_QUIRK_NO_IGNORE)
+               return false;
+       if (hdev->quirks & HID_QUIRK_IGNORE)
+               return true;
+
        switch (hdev->vendor) {
        case USB_VENDOR_ID_CODEMERCS:
                /* ignore all Code Mercenaries IOWarrior devices */
@@ -2188,7 +2218,16 @@ static bool hid_ignore(struct hid_device *hdev)
                if (hdev->product == USB_DEVICE_ID_JESS_YUREX &&
                                hdev->type == HID_TYPE_USBNONE)
                        return true;
-       break;
+               break;
+       case USB_VENDOR_ID_DWAV:
+               /* These are handled by usbtouchscreen. hdev->type is probably
+                * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match
+                * usbtouchscreen. */
+               if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER ||
+                    hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) &&
+                   hdev->type != HID_TYPE_USBMOUSE)
+                       return true;
+               break;
        }
 
        if (hdev->type == HID_TYPE_USBMOUSE &&
@@ -2197,6 +2236,7 @@ static bool hid_ignore(struct hid_device *hdev)
 
        return !!hid_match_id(hdev, hid_ignore_list);
 }
+EXPORT_SYMBOL_GPL(hid_ignore);
 
 int hid_add_device(struct hid_device *hdev)
 {
@@ -2208,8 +2248,7 @@ int hid_add_device(struct hid_device *hdev)
 
        /* we need to kill them here, otherwise they will stay allocated to
         * wait for coming driver */
-       if (!(hdev->quirks & HID_QUIRK_NO_IGNORE)
-            && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
+       if (hid_ignore(hdev))
                return -ENODEV;
 
        /*
diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
new file mode 100644 (file)
index 0000000..1d6565e
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *  ION iCade input driver
+ *
+ *  Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
+ *  Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ *   ↑      A C Y L
+ *  ← →
+ *   ↓      B X Z R
+ *
+ *
+ *  UP ON,OFF  = w,e
+ *  RT ON,OFF  = d,c
+ *  DN ON,OFF  = x,z
+ *  LT ON,OFF  = a,q
+ *  A  ON,OFF  = y,t
+ *  B  ON,OFF  = h,r
+ *  C  ON,OFF  = u,f
+ *  X  ON,OFF  = j,n
+ *  Y  ON,OFF  = i,m
+ *  Z  ON,OFF  = k,p
+ *  L  ON,OFF  = o,g
+ *  R  ON,OFF  = l,v
+ */
+
+/* The translation code uses HID usage instead of input layer
+ * keys. This code generates a lookup table that makes
+ * translation quick.
+ *
+ * #include <linux/input.h>
+ * #include <stdio.h>
+ * #include <assert.h>
+ *
+ * #define unk     KEY_UNKNOWN
+ *
+ * < copy of hid_keyboard[] from hid-input.c >
+ *
+ * struct icade_key_translation {
+ *     int         from;
+ *     const char *to;
+ *     int         press;
+ * };
+ *
+ * static const struct icade_key_translation icade_keys[] = {
+ *    { KEY_W,        "KEY_UP",         1 },
+ *    { KEY_E,        "KEY_UP",         0 },
+ *    { KEY_D,        "KEY_RIGHT",      1 },
+ *    { KEY_C,        "KEY_RIGHT",      0 },
+ *    { KEY_X,        "KEY_DOWN",       1 },
+ *    { KEY_Z,        "KEY_DOWN",       0 },
+ *    { KEY_A,        "KEY_LEFT",       1 },
+ *    { KEY_Q,        "KEY_LEFT",       0 },
+ *    { KEY_Y,        "BTN_A",          1 },
+ *    { KEY_T,        "BTN_A",          0 },
+ *    { KEY_H,        "BTN_B",          1 },
+ *    { KEY_R,        "BTN_B",          0 },
+ *    { KEY_U,        "BTN_C",          1 },
+ *    { KEY_F,        "BTN_C",          0 },
+ *    { KEY_J,        "BTN_X",          1 },
+ *    { KEY_N,        "BTN_X",          0 },
+ *    { KEY_I,        "BTN_Y",          1 },
+ *    { KEY_M,        "BTN_Y",          0 },
+ *    { KEY_K,        "BTN_Z",          1 },
+ *    { KEY_P,        "BTN_Z",          0 },
+ *    { KEY_O,        "BTN_THUMBL",     1 },
+ *    { KEY_G,        "BTN_THUMBL",     0 },
+ *    { KEY_L,        "BTN_THUMBR",     1 },
+ *    { KEY_V,        "BTN_THUMBR",     0 },
+ *
+ *    { }
+ * };
+ *
+ * static int
+ * usage_for_key (int key)
+ * {
+ *     int i;
+ *     for (i = 0; i < 256; i++) {
+ *     if (hid_keyboard[i] == key)
+ *         return i;
+ *     }
+ *     assert(0);
+ * }
+ *
+ * int main (int argc, char **argv)
+ * {
+ *     const struct icade_key_translation *trans;
+ *     int max_usage = 0;
+ *
+ *     for (trans = icade_keys; trans->from; trans++) {
+ *         int usage = usage_for_key (trans->from);
+ *         max_usage = usage > max_usage ? usage : max_usage;
+ *     }
+ *
+ *     printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
+ *     printf ("struct icade_key {\n");
+ *     printf ("\tu16 to;\n");
+ *     printf ("\tu8 press:1;\n");
+ *     printf ("};\n\n");
+ *     printf ("static const struct icade_key "
+ *             "icade_usage_table[%d] = {\n", max_usage + 1);
+ *     for (trans = icade_keys; trans->from; trans++) {
+ *         printf ("\t[%d] = { %s, %d },\n",
+ *                 usage_for_key (trans->from), trans->to, trans->press);
+ *     }
+ *     printf ("};\n");
+ *
+ *     return 0;
+ * }
+ */
+
+#define ICADE_MAX_USAGE 29
+
+struct icade_key {
+       u16 to;
+       u8 press:1;
+};
+
+static const struct icade_key icade_usage_table[30] = {
+       [26] = { KEY_UP, 1 },
+       [8] = { KEY_UP, 0 },
+       [7] = { KEY_RIGHT, 1 },
+       [6] = { KEY_RIGHT, 0 },
+       [27] = { KEY_DOWN, 1 },
+       [29] = { KEY_DOWN, 0 },
+       [4] = { KEY_LEFT, 1 },
+       [20] = { KEY_LEFT, 0 },
+       [28] = { BTN_A, 1 },
+       [23] = { BTN_A, 0 },
+       [11] = { BTN_B, 1 },
+       [21] = { BTN_B, 0 },
+       [24] = { BTN_C, 1 },
+       [9] = { BTN_C, 0 },
+       [13] = { BTN_X, 1 },
+       [17] = { BTN_X, 0 },
+       [12] = { BTN_Y, 1 },
+       [16] = { BTN_Y, 0 },
+       [14] = { BTN_Z, 1 },
+       [19] = { BTN_Z, 0 },
+       [18] = { BTN_THUMBL, 1 },
+       [10] = { BTN_THUMBL, 0 },
+       [15] = { BTN_THUMBR, 1 },
+       [25] = { BTN_THUMBR, 0 },
+};
+
+static const struct icade_key *icade_find_translation(u16 from)
+{
+       if (from < 0 || from > ICADE_MAX_USAGE)
+               return NULL;
+       return &icade_usage_table[from];
+}
+
+static int icade_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       const struct icade_key *trans;
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+                       !usage->type)
+               return 0;
+
+       /* We ignore the fake key up, and act only on key down */
+       if (!value)
+               return 1;
+
+       trans = icade_find_translation(usage->hid & HID_USAGE);
+
+       if (!trans)
+               return 1;
+
+       input_event(field->hidinput->input, usage->type,
+                       trans->to, trans->press);
+
+       return 1;
+}
+
+static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       const struct icade_key *trans;
+
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
+               trans = icade_find_translation(usage->hid & HID_USAGE);
+
+               if (!trans)
+                       return -1;
+
+               hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
+               set_bit(trans->to, hi->input->keybit);
+
+               return 1;
+       }
+
+       /* ignore others */
+       return -1;
+
+}
+
+static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if (usage->type == EV_KEY)
+               set_bit(usage->type, hi->input->evbit);
+
+       return -1;
+}
+
+static const struct hid_device_id icade_devices[] = {
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+
+       { }
+};
+MODULE_DEVICE_TABLE(hid, icade_devices);
+
+static struct hid_driver icade_driver = {
+       .name = "icade",
+       .id_table = icade_devices,
+       .event = icade_event,
+       .input_mapped = icade_input_mapped,
+       .input_mapping = icade_input_mapping,
+};
+
+static int __init icade_init(void)
+{
+       int ret;
+
+       ret = hid_register_driver(&icade_driver);
+       if (ret)
+               pr_err("can't register icade driver\n");
+
+       return ret;
+}
+
+static void __exit icade_exit(void)
+{
+       hid_unregister_driver(&icade_driver);
+}
+
+module_init(icade_init);
+module_exit(icade_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("ION iCade input driver");
index 9d7a42857ea190a9b9fbc12582582b8ae97ebd2a..4dfa605e2d14417203e734c4a68dc2447e86f5c2 100644 (file)
 
 #define USB_VENDOR_ID_DWAV             0x0eef
 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER   0x0001
+#define USB_DEVICE_ID_DWAV_TOUCHCONTROLLER     0x0002
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D      0x480d
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E      0x480e
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207      0x7207
 #define USB_VENDOR_ID_ILITEK           0x222a
 #define USB_DEVICE_ID_ILITEK_MULTITOUCH        0x0001
 
+#define USB_VENDOR_ID_ION              0x15e4
+#define USB_DEVICE_ID_ICADE            0x0132
+
 #define USB_VENDOR_ID_HOLTEK           0x1241
 #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP      0x5015
 
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
 
-#define USB_VENDOR_ID_INTEL_8086       0x8086
-#define USB_VENDOR_ID_INTEL_8087       0x8087
-#define USB_DEVICE_ID_SENSOR_HUB_1020  0x1020
-#define USB_DEVICE_ID_SENSOR_HUB_09FA  0x09FA
-
 #define USB_VENDOR_ID_IRTOUCHSYSTEMS   0x6615
 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB     0x0070
 
 
 #define USB_VENDOR_ID_NOVATEK          0x0603
 #define USB_DEVICE_ID_NOVATEK_PCT      0x0600
+#define USB_DEVICE_ID_NOVATEK_MOUSE    0x1602
 
 #define USB_VENDOR_ID_NTRIG            0x1b96
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN   0x0001
 #define USB_DEVICE_ID_ROCCAT_ISKU      0x319c
 #define USB_DEVICE_ID_ROCCAT_KONE      0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS  0x2d51
+#define USB_DEVICE_ID_ROCCAT_KONEXTD   0x2e22
 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS  0x2d50
+#define USB_DEVICE_ID_ROCCAT_LUA       0x2c2e
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED        0x2c24
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS     0x2cf6
 #define USB_DEVICE_ID_ROCCAT_SAVU      0x2d5a
 #define USB_VENDOR_ID_SIGMA_MICRO      0x1c4f
 #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD     0x0002
 
+#define USB_VENDOR_ID_SIGMATEL         0x066F
+#define USB_DEVICE_ID_SIGMATEL_STMP3780        0x3780
+
 #define USB_VENDOR_ID_SKYCABLE                 0x1223
 #define        USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER       0x3F07
 
 
 #define USB_VENDOR_ID_STANTUM_STM              0x0483
 #define USB_DEVICE_ID_MTP_STM          0x3261
-#define USB_DEVICE_ID_SENSOR_HUB_7014  0x7014
 
 #define USB_VENDOR_ID_STANTUM_SITRONIX         0x1403
 #define USB_DEVICE_ID_MTP_SITRONIX             0x5001
 #define USB_VENDOR_ID_TOUCHPACK                0x1bfd
 #define USB_DEVICE_ID_TOUCHPACK_RTS    0x1688
 
+#define USB_VENDOR_ID_TPV              0x25aa
+#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN  0x8883
+
 #define USB_VENDOR_ID_TURBOX           0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
 #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART        0x7100
index d917c0d536856c80b7b898c7ad950b4728c16db6..21b196c394b197d222e0d1f58ac52f37d65b3e5d 100644 (file)
@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev,
        return -EINVAL;
 }
 
-
 /**
  * hidinput_calc_abs_res - calculate an absolute axis resolution
  * @field: the HID report field to calculate resolution for
@@ -208,7 +207,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
  * Only exponent 1 length units are processed. Centimeters and inches are
  * converted to millimeters. Degrees are converted to radians.
  */
-static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 {
        __s32 unit_exponent = field->unit_exponent;
        __s32 logical_extents = field->logical_maximum -
@@ -229,17 +228,29 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
        case ABS_X:
        case ABS_Y:
        case ABS_Z:
-               if (field->unit == 0x11) {              /* If centimeters */
+       case ABS_MT_POSITION_X:
+       case ABS_MT_POSITION_Y:
+       case ABS_MT_TOOL_X:
+       case ABS_MT_TOOL_Y:
+       case ABS_MT_TOUCH_MAJOR:
+       case ABS_MT_TOUCH_MINOR:
+               if (field->unit & 0xffffff00)           /* Not a length */
+                       return 0;
+               unit_exponent += hid_snto32(field->unit >> 4, 4) - 1;
+               switch (field->unit & 0xf) {
+               case 0x1:                               /* If centimeters */
                        /* Convert to millimeters */
                        unit_exponent += 1;
-               } else if (field->unit == 0x13) {       /* If inches */
+                       break;
+               case 0x3:                               /* If inches */
                        /* Convert to millimeters */
                        prev = physical_extents;
                        physical_extents *= 254;
                        if (physical_extents < prev)
                                return 0;
                        unit_exponent -= 1;
-               } else {
+                       break;
+               default:
                        return 0;
                }
                break;
@@ -281,8 +292,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
        }
 
        /* Calculate resolution */
-       return logical_extents / physical_extents;
+       return DIV_ROUND_CLOSEST(logical_extents, physical_extents);
 }
+EXPORT_SYMBOL_GPL(hidinput_calc_abs_res);
 
 #ifdef CONFIG_HID_BATTERY_STRENGTH
 static enum power_supply_property hidinput_battery_props[] = {
@@ -298,6 +310,9 @@ static enum power_supply_property hidinput_battery_props[] = {
 #define HID_BATTERY_QUIRK_FEATURE      (1 << 1) /* ask for feature report */
 
 static const struct hid_device_id hid_battery_quirks[] = {
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+                       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+       HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
          HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
@@ -502,9 +517,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                if (code <= 0xf)
                                        code += BTN_JOYSTICK;
                                else
-                                       code += BTN_TRIGGER_HAPPY;
+                                       code += BTN_TRIGGER_HAPPY - 0x10;
+                               break;
+               case HID_GD_GAMEPAD:
+                               if (code <= 0xf)
+                                       code += BTN_GAMEPAD;
+                               else
+                                       code += BTN_TRIGGER_HAPPY - 0x10;
                                break;
-               case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
                default:
                        switch (field->physical) {
                        case HID_GD_MOUSE:
@@ -1146,6 +1166,38 @@ static void report_features(struct hid_device *hid)
                        }
 }
 
+static struct hid_input *hidinput_allocate(struct hid_device *hid)
+{
+       struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
+       struct input_dev *input_dev = input_allocate_device();
+       if (!hidinput || !input_dev) {
+               kfree(hidinput);
+               input_free_device(input_dev);
+               hid_err(hid, "Out of memory during hid input probe\n");
+               return NULL;
+       }
+
+       input_set_drvdata(input_dev, hid);
+       input_dev->event = hid->ll_driver->hidinput_input_event;
+       input_dev->open = hidinput_open;
+       input_dev->close = hidinput_close;
+       input_dev->setkeycode = hidinput_setkeycode;
+       input_dev->getkeycode = hidinput_getkeycode;
+
+       input_dev->name = hid->name;
+       input_dev->phys = hid->phys;
+       input_dev->uniq = hid->uniq;
+       input_dev->id.bustype = hid->bus;
+       input_dev->id.vendor  = hid->vendor;
+       input_dev->id.product = hid->product;
+       input_dev->id.version = hid->version;
+       input_dev->dev.parent = hid->dev.parent;
+       hidinput->input = input_dev;
+       list_add_tail(&hidinput->list, &hid->inputs);
+
+       return hidinput;
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -1157,7 +1209,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
        struct hid_driver *drv = hid->driver;
        struct hid_report *report;
        struct hid_input *hidinput = NULL;
-       struct input_dev *input_dev;
        int i, j, k;
 
        INIT_LIST_HEAD(&hid->inputs);
@@ -1188,33 +1239,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                continue;
 
                        if (!hidinput) {
-                               hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
-                               input_dev = input_allocate_device();
-                               if (!hidinput || !input_dev) {
-                                       kfree(hidinput);
-                                       input_free_device(input_dev);
-                                       hid_err(hid, "Out of memory during hid input probe\n");
+                               hidinput = hidinput_allocate(hid);
+                               if (!hidinput)
                                        goto out_unwind;
-                               }
-
-                               input_set_drvdata(input_dev, hid);
-                               input_dev->event =
-                                       hid->ll_driver->hidinput_input_event;
-                               input_dev->open = hidinput_open;
-                               input_dev->close = hidinput_close;
-                               input_dev->setkeycode = hidinput_setkeycode;
-                               input_dev->getkeycode = hidinput_getkeycode;
-
-                               input_dev->name = hid->name;
-                               input_dev->phys = hid->phys;
-                               input_dev->uniq = hid->uniq;
-                               input_dev->id.bustype = hid->bus;
-                               input_dev->id.vendor  = hid->vendor;
-                               input_dev->id.product = hid->product;
-                               input_dev->id.version = hid->version;
-                               input_dev->dev.parent = hid->dev.parent;
-                               hidinput->input = input_dev;
-                               list_add_tail(&hidinput->list, &hid->inputs);
                        }
 
                        for (i = 0; i < report->maxfield; i++)
index 7867d69f0efe1cd734c57e7e4627eb9aaf7a367e..61543c02ea0baf42c58fbfa5518dba229cb22901 100644 (file)
@@ -52,11 +52,14 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_VALID_IS_CONFIDENCE   (1 << 6)
 #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE   (1 << 8)
 #define MT_QUIRK_NO_AREA               (1 << 9)
+#define MT_QUIRK_IGNORE_DUPLICATES     (1 << 10)
+#define MT_QUIRK_HOVERING              (1 << 11)
 
 struct mt_slot {
-       __s32 x, y, p, w, h;
+       __s32 x, y, cx, cy, p, w, h;
        __s32 contactid;        /* the device ContactID assigned to this slot */
        bool touch_state;       /* is the touch valid? */
+       bool inrange_state;     /* is the finger in proximity of the sensor? */
 };
 
 struct mt_class {
@@ -121,6 +124,7 @@ struct mt_device {
 #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS     0x0109
 
 #define MT_DEFAULT_MAXCONTACT  10
+#define MT_MAX_MAXCONTACT      250
 
 #define MT_USB_DEVICE(v, p)    HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
 #define MT_BT_DEVICE(v, p)     HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
@@ -282,11 +286,26 @@ static void mt_feature_mapping(struct hid_device *hdev,
        case HID_DG_CONTACTMAX:
                td->maxcontact_report_id = field->report->id;
                td->maxcontacts = field->value[0];
+               if (!td->maxcontacts &&
+                   field->logical_maximum <= MT_MAX_MAXCONTACT)
+                       td->maxcontacts = field->logical_maximum;
                if (td->mtclass.maxcontacts)
                        /* check if the maxcontacts is given by the class */
                        td->maxcontacts = td->mtclass.maxcontacts;
 
                break;
+       case 0xff0000c5:
+               if (field->report_count == 256 && field->report_size == 8) {
+                       /* Win 8 devices need special quirks */
+                       __s32 *quirks = &td->mtclass.quirks;
+                       *quirks |= MT_QUIRK_ALWAYS_VALID;
+                       *quirks |= MT_QUIRK_IGNORE_DUPLICATES;
+                       *quirks |= MT_QUIRK_HOVERING;
+                       *quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
+                       *quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
+                       *quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
+               }
+               break;
        }
 }
 
@@ -297,6 +316,7 @@ static void set_abs(struct input_dev *input, unsigned int code,
        int fmax = field->logical_maximum;
        int fuzz = snratio ? (fmax - fmin) / snratio : 0;
        input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
+       input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
 }
 
 static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
@@ -317,6 +337,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        struct mt_device *td = hid_get_drvdata(hdev);
        struct mt_class *cls = &td->mtclass;
        int code;
+       struct hid_usage *prev_usage = NULL;
 
        /* Only map fields from TouchScreen or TouchPad collections.
        * We need to ignore fields that belong to other collections
@@ -339,23 +360,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        if (field->physical == HID_DG_STYLUS)
                return -1;
 
+       if (usage->usage_index)
+               prev_usage = &field->usage[usage->usage_index - 1];
+
        switch (usage->hid & HID_USAGE_PAGE) {
 
        case HID_UP_GENDESK:
                switch (usage->hid) {
                case HID_GD_X:
-                       hid_map_usage(hi, usage, bit, max,
+                       if (prev_usage && (prev_usage->hid == usage->hid)) {
+                               hid_map_usage(hi, usage, bit, max,
+                                       EV_ABS, ABS_MT_TOOL_X);
+                               set_abs(hi->input, ABS_MT_TOOL_X, field,
+                                       cls->sn_move);
+                       } else {
+                               hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_POSITION_X);
-                       set_abs(hi->input, ABS_MT_POSITION_X, field,
-                               cls->sn_move);
+                               set_abs(hi->input, ABS_MT_POSITION_X, field,
+                                       cls->sn_move);
+                       }
+
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
                case HID_GD_Y:
-                       hid_map_usage(hi, usage, bit, max,
+                       if (prev_usage && (prev_usage->hid == usage->hid)) {
+                               hid_map_usage(hi, usage, bit, max,
+                                       EV_ABS, ABS_MT_TOOL_Y);
+                               set_abs(hi->input, ABS_MT_TOOL_Y, field,
+                                       cls->sn_move);
+                       } else {
+                               hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_POSITION_Y);
-                       set_abs(hi->input, ABS_MT_POSITION_Y, field,
-                               cls->sn_move);
+                               set_abs(hi->input, ABS_MT_POSITION_Y, field,
+                                       cls->sn_move);
+                       }
+
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
@@ -365,6 +405,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        case HID_UP_DIGITIZER:
                switch (usage->hid) {
                case HID_DG_INRANGE:
+                       if (cls->quirks & MT_QUIRK_HOVERING) {
+                               hid_map_usage(hi, usage, bit, max,
+                                       EV_ABS, ABS_MT_DISTANCE);
+                               input_set_abs_params(hi->input,
+                                       ABS_MT_DISTANCE, 0, 1, 0, 0);
+                       }
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        return 1;
@@ -477,18 +523,26 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
  */
 static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 {
-       if (td->curvalid) {
+       if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
                int slotnum = mt_compute_slot(td, input);
                struct mt_slot *s = &td->curdata;
+               struct input_mt *mt = input->mt;
 
                if (slotnum < 0 || slotnum >= td->maxcontacts)
                        return;
 
+               if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
+                       struct input_mt_slot *slot = &mt->slots[slotnum];
+                       if (input_mt_is_active(slot) &&
+                           input_mt_is_used(mt, slot))
+                               return;
+               }
+
                input_mt_slot(input, slotnum);
                input_mt_report_slot_state(input, MT_TOOL_FINGER,
-                       s->touch_state);
-               if (s->touch_state) {
-                       /* this finger is on the screen */
+                       s->touch_state || s->inrange_state);
+               if (s->touch_state || s->inrange_state) {
+                       /* this finger is in proximity of the sensor */
                        int wide = (s->w > s->h);
                        /* divided by two to match visual scale of touch */
                        int major = max(s->w, s->h) >> 1;
@@ -496,6 +550,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 
                        input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
                        input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+                       input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
+                       input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
+                       input_event(input, EV_ABS, ABS_MT_DISTANCE,
+                               !s->touch_state);
                        input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
                        input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
                        input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
@@ -526,10 +584,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
        if (hid->claimed & HID_CLAIMED_INPUT) {
                switch (usage->hid) {
                case HID_DG_INRANGE:
-                       if (quirks & MT_QUIRK_ALWAYS_VALID)
-                               td->curvalid = true;
-                       else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+                       if (quirks & MT_QUIRK_VALID_IS_INRANGE)
                                td->curvalid = value;
+                       if (quirks & MT_QUIRK_HOVERING)
+                               td->curdata.inrange_state = value;
                        break;
                case HID_DG_TIPSWITCH:
                        if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
@@ -547,10 +605,16 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
                        td->curdata.p = value;
                        break;
                case HID_GD_X:
-                       td->curdata.x = value;
+                       if (usage->code == ABS_MT_TOOL_X)
+                               td->curdata.cx = value;
+                       else
+                               td->curdata.x = value;
                        break;
                case HID_GD_Y:
-                       td->curdata.y = value;
+                       if (usage->code == ABS_MT_TOOL_Y)
+                               td->curdata.cy = value;
+                       else
+                               td->curdata.y = value;
                        break;
                case HID_DG_WIDTH:
                        td->curdata.w = value;
@@ -575,12 +639,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
                        return 0;
                }
 
-               if (usage->hid == td->last_slot_field)
-                       mt_complete_slot(td, field->hidinput->input);
+               if (usage->usage_index + 1 == field->report_count) {
+                       /* we only take into account the last report. */
+                       if (usage->hid == td->last_slot_field)
+                               mt_complete_slot(td, field->hidinput->input);
 
-               if (field->index == td->last_field_index
-                       && td->num_received >= td->num_expected)
-                       mt_sync_frame(td, field->hidinput->input);
+                       if (field->index == td->last_field_index
+                               && td->num_received >= td->num_expected)
+                               mt_sync_frame(td, field->hidinput->input);
+               }
 
        }
 
index 13ca9191b6309a9ff388dbd32dd2f584cb2fffa9..a79e95bb9fb69db2803a9f5c4ee8abccfbfc7f4b 100644 (file)
@@ -116,7 +116,7 @@ int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
 
        rdev->priv             = data;
        rdev->driver_type      = RC_DRIVER_IR_RAW;
-       rdev->allowed_protos   = RC_TYPE_ALL;
+       rdev->allowed_protos   = RC_BIT_ALL;
        rdev->open             = picolcd_cir_open;
        rdev->close            = picolcd_cir_close;
        rdev->input_name       = data->hdev->name;
index 5669916c294309379fc0472f4efe3ada24f60ca3..1219998a02d66e98ca11cecf0c740044b6801deb 100644 (file)
@@ -167,7 +167,7 @@ static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj
                loff_t off, size_t count) \
 { \
        return isku_sysfs_write(fp, kobj, buf, off, count, \
-                       sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \
+                       ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
 }
 
 #define ISKU_SYSFS_R(thingy, THINGY) \
@@ -176,32 +176,32 @@ static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj,
                loff_t off, size_t count) \
 { \
        return isku_sysfs_read(fp, kobj, buf, off, count, \
-                       sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \
+                       ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
 }
 
 #define ISKU_SYSFS_RW(thingy, THINGY) \
 ISKU_SYSFS_R(thingy, THINGY) \
 ISKU_SYSFS_W(thingy, THINGY)
 
-#define ISKU_BIN_ATTR_RW(thingy) \
+#define ISKU_BIN_ATTR_RW(thingy, THINGY) \
 { \
        .attr = { .name = #thingy, .mode = 0660 }, \
-       .size = sizeof(struct isku_ ## thingy), \
+       .size = ISKU_SIZE_ ## THINGY, \
        .read = isku_sysfs_read_ ## thingy, \
        .write = isku_sysfs_write_ ## thingy \
 }
 
-#define ISKU_BIN_ATTR_R(thingy) \
+#define ISKU_BIN_ATTR_R(thingy, THINGY) \
 { \
        .attr = { .name = #thingy, .mode = 0440 }, \
-       .size = sizeof(struct isku_ ## thingy), \
+       .size = ISKU_SIZE_ ## THINGY, \
        .read = isku_sysfs_read_ ## thingy, \
 }
 
-#define ISKU_BIN_ATTR_W(thingy) \
+#define ISKU_BIN_ATTR_W(thingy, THINGY) \
 { \
        .attr = { .name = #thingy, .mode = 0220 }, \
-       .size = sizeof(struct isku_ ## thingy), \
+       .size = ISKU_SIZE_ ## THINGY, \
        .write = isku_sysfs_write_ ## thingy \
 }
 
@@ -218,21 +218,23 @@ ISKU_SYSFS_RW(last_set, LAST_SET)
 ISKU_SYSFS_W(talk, TALK)
 ISKU_SYSFS_R(info, INFO)
 ISKU_SYSFS_W(control, CONTROL)
+ISKU_SYSFS_W(reset, RESET)
 
 static struct bin_attribute isku_bin_attributes[] = {
-       ISKU_BIN_ATTR_RW(macro),
-       ISKU_BIN_ATTR_RW(keys_function),
-       ISKU_BIN_ATTR_RW(keys_easyzone),
-       ISKU_BIN_ATTR_RW(keys_media),
-       ISKU_BIN_ATTR_RW(keys_thumbster),
-       ISKU_BIN_ATTR_RW(keys_macro),
-       ISKU_BIN_ATTR_RW(keys_capslock),
-       ISKU_BIN_ATTR_RW(light),
-       ISKU_BIN_ATTR_RW(key_mask),
-       ISKU_BIN_ATTR_RW(last_set),
-       ISKU_BIN_ATTR_W(talk),
-       ISKU_BIN_ATTR_R(info),
-       ISKU_BIN_ATTR_W(control),
+       ISKU_BIN_ATTR_RW(macro, MACRO),
+       ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
+       ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
+       ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
+       ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
+       ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
+       ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
+       ISKU_BIN_ATTR_RW(light, LIGHT),
+       ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
+       ISKU_BIN_ATTR_RW(last_set, LAST_SET),
+       ISKU_BIN_ATTR_W(talk, TALK),
+       ISKU_BIN_ATTR_R(info, INFO),
+       ISKU_BIN_ATTR_W(control, CONTROL),
+       ISKU_BIN_ATTR_W(reset, RESET),
        __ATTR_NULL
 };
 
index 605b3ce21638da5723e8f6ee50d9109ead4c2602..cf6896c838679d7ec5527a7cb94037e16c1fd78a 100644 (file)
 
 #include <linux/types.h>
 
+enum {
+       ISKU_SIZE_CONTROL = 0x03,
+       ISKU_SIZE_INFO = 0x06,
+       ISKU_SIZE_KEY_MASK = 0x06,
+       ISKU_SIZE_KEYS_FUNCTION = 0x29,
+       ISKU_SIZE_KEYS_EASYZONE = 0x41,
+       ISKU_SIZE_KEYS_MEDIA = 0x1d,
+       ISKU_SIZE_KEYS_THUMBSTER = 0x17,
+       ISKU_SIZE_KEYS_MACRO = 0x23,
+       ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
+       ISKU_SIZE_LAST_SET = 0x14,
+       ISKU_SIZE_LIGHT = 0x0a,
+       ISKU_SIZE_MACRO = 0x823,
+       ISKU_SIZE_RESET = 0x03,
+       ISKU_SIZE_TALK = 0x10,
+};
+
 enum {
        ISKU_PROFILE_NUM = 5,
        ISKU_USB_INTERFACE_PROTOCOL = 0,
 };
 
-struct isku_control {
-       uint8_t command; /* ISKU_COMMAND_CONTROL */
-       uint8_t value;
-       uint8_t request;
-} __packed;
-
 struct isku_actual_profile {
        uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */
        uint8_t size; /* always 3 */
        uint8_t actual_profile;
 } __packed;
 
-struct isku_key_mask {
-       uint8_t command; /* ISKU_COMMAND_KEY_MASK */
-       uint8_t size; /* 6 */
-       uint8_t profile_number; /* 0-4 */
-       uint8_t mask;
-       uint16_t checksum;
-} __packed;
-
-struct isku_keys_function {
-       uint8_t data[0x29];
-} __packed;
-
-struct isku_keys_easyzone {
-       uint8_t data[0x41];
-} __packed;
-
-struct isku_keys_media {
-       uint8_t data[0x1d];
-} __packed;
-
-struct isku_keys_thumbster {
-       uint8_t data[0x17];
-} __packed;
-
-struct isku_keys_macro {
-       uint8_t data[0x23];
-} __packed;
-
-struct isku_keys_capslock {
-       uint8_t data[0x6];
-} __packed;
-
-struct isku_macro {
-       uint8_t data[0x823];
-} __packed;
-
-struct isku_light {
-       uint8_t data[0xa];
-} __packed;
-
-struct isku_info {
-       uint8_t data[2];
-       uint8_t firmware_version;
-       uint8_t unknown[3];
-} __packed;
-
-struct isku_talk {
-       uint8_t data[0x10];
-} __packed;
-
-struct isku_last_set {
-       uint8_t data[0x14];
-} __packed;
-
 enum isku_commands {
        ISKU_COMMAND_CONTROL = 0x4,
        ISKU_COMMAND_ACTUAL_PROFILE = 0x5,
@@ -97,6 +54,7 @@ enum isku_commands {
        ISKU_COMMAND_MACRO = 0xe,
        ISKU_COMMAND_INFO = 0xf,
        ISKU_COMMAND_LIGHT = 0x10,
+       ISKU_COMMAND_RESET = 0x11,
        ISKU_COMMAND_KEYS_CAPSLOCK = 0x13,
        ISKU_COMMAND_LAST_SET = 0x14,
        ISKU_COMMAND_15 = 0x15,
index f5602fec48655016ca0fabdad1b743f71c17ae52..6a48fa3c7da913e487e5aa0b1538ba5aff19bbb1 100644 (file)
@@ -14,6 +14,7 @@
 /*
  * Roccat Kone[+] is an updated/improved version of the Kone with more memory
  * and functionality and without the non-standard behaviours the Kone had.
+ * KoneXTD has same capabilities but updated sensor.
  */
 
 #include <linux/device.h>
@@ -55,56 +56,6 @@ static int koneplus_send_control(struct usb_device *usb_dev, uint value,
                        &control, sizeof(struct roccat_common2_control));
 }
 
-static int koneplus_get_info(struct usb_device *usb_dev,
-               struct koneplus_info *buf)
-{
-       return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
-                       buf, sizeof(struct koneplus_info));
-}
-
-static int koneplus_get_profile_settings(struct usb_device *usb_dev,
-               struct koneplus_profile_settings *buf, uint number)
-{
-       int retval;
-
-       retval = koneplus_send_control(usb_dev, number,
-                       KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
-       if (retval)
-               return retval;
-
-       return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
-                       buf, sizeof(struct koneplus_profile_settings));
-}
-
-static int koneplus_set_profile_settings(struct usb_device *usb_dev,
-               struct koneplus_profile_settings const *settings)
-{
-       return roccat_common2_send_with_status(usb_dev,
-                       KONEPLUS_COMMAND_PROFILE_SETTINGS,
-                       settings, sizeof(struct koneplus_profile_settings));
-}
-
-static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
-               struct koneplus_profile_buttons *buf, int number)
-{
-       int retval;
-
-       retval = koneplus_send_control(usb_dev, number,
-                       KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
-       if (retval)
-               return retval;
-
-       return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
-                       buf, sizeof(struct koneplus_profile_buttons));
-}
-
-static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
-               struct koneplus_profile_buttons const *buttons)
-{
-       return roccat_common2_send_with_status(usb_dev,
-                       KONEPLUS_COMMAND_PROFILE_BUTTONS,
-                       buttons, sizeof(struct koneplus_profile_buttons));
-}
 
 /* retval is 0-4 on success, < 0 on error */
 static int koneplus_get_actual_profile(struct usb_device *usb_dev)
@@ -113,7 +64,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev)
        int retval;
 
        retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
-                       &buf, sizeof(struct koneplus_actual_profile));
+                       &buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
 
        return retval ? retval : buf.actual_profile;
 }
@@ -124,12 +75,12 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev,
        struct koneplus_actual_profile buf;
 
        buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE;
-       buf.size = sizeof(struct koneplus_actual_profile);
+       buf.size = KONEPLUS_SIZE_ACTUAL_PROFILE;
        buf.actual_profile = new_profile;
 
        return roccat_common2_send_with_status(usb_dev,
                        KONEPLUS_COMMAND_ACTUAL_PROFILE,
-                       &buf, sizeof(struct koneplus_actual_profile));
+                       &buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
 }
 
 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -182,111 +133,77 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
        return real_size;
 }
 
-static ssize_t koneplus_sysfs_write_talk(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       return koneplus_sysfs_write(fp, kobj, buf, off, count,
-                       sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK);
+#define KONEPLUS_SYSFS_W(thingy, THINGY) \
+static ssize_t koneplus_sysfs_write_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return koneplus_sysfs_write(fp, kobj, buf, off, count, \
+                       KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
 }
 
-static ssize_t koneplus_sysfs_write_macro(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       return koneplus_sysfs_write(fp, kobj, buf, off, count,
-                       sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO);
+#define KONEPLUS_SYSFS_R(thingy, THINGY) \
+static ssize_t koneplus_sysfs_read_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return koneplus_sysfs_read(fp, kobj, buf, off, count, \
+                       KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
 }
 
-static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       return koneplus_sysfs_read(fp, kobj, buf, off, count,
-                       sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
-}
+#define KONEPLUS_SYSFS_RW(thingy, THINGY) \
+KONEPLUS_SYSFS_W(thingy, THINGY) \
+KONEPLUS_SYSFS_R(thingy, THINGY)
 
-static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       return koneplus_sysfs_write(fp, kobj, buf, off, count,
-                       sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
+#define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0660 }, \
+       .size = KONEPLUS_SIZE_ ## THINGY, \
+       .read = koneplus_sysfs_read_ ## thingy, \
+       .write = koneplus_sysfs_write_ ## thingy \
 }
 
-static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       return koneplus_sysfs_write(fp, kobj, buf, off, count,
-                       sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
+#define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0440 }, \
+       .size = KONEPLUS_SIZE_ ## THINGY, \
+       .read = koneplus_sysfs_read_ ## thingy, \
 }
 
-static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       return koneplus_sysfs_read(fp, kobj, buf, off, count,
-                       sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU);
+#define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0220 }, \
+       .size = KONEPLUS_SIZE_ ## THINGY, \
+       .write = koneplus_sysfs_write_ ## thingy \
 }
 
-static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       struct device *dev =
-                       container_of(kobj, struct device, kobj)->parent->parent;
-       struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
-
-       if (off >= sizeof(struct koneplus_profile_settings))
-               return 0;
+KONEPLUS_SYSFS_W(control, CONTROL)
+KONEPLUS_SYSFS_RW(info, INFO)
+KONEPLUS_SYSFS_W(talk, TALK)
+KONEPLUS_SYSFS_W(macro, MACRO)
+KONEPLUS_SYSFS_RW(sensor, SENSOR)
+KONEPLUS_SYSFS_RW(tcu, TCU)
+KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE)
+KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
 
-       if (off + count > sizeof(struct koneplus_profile_settings))
-               count = sizeof(struct koneplus_profile_settings) - off;
-
-       mutex_lock(&koneplus->koneplus_lock);
-       memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
-                       count);
-       mutex_unlock(&koneplus->koneplus_lock);
-
-       return count;
-}
-
-static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp,
+static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
                loff_t off, size_t count)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
-       struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-       int retval = 0;
-       int difference;
-       int profile_number;
-       struct koneplus_profile_settings *profile_settings;
-
-       if (off != 0 || count != sizeof(struct koneplus_profile_settings))
-               return -EINVAL;
-
-       profile_number = ((struct koneplus_profile_settings const *)buf)->number;
-       profile_settings = &koneplus->profile_settings[profile_number];
-
-       mutex_lock(&koneplus->koneplus_lock);
-       difference = memcmp(buf, profile_settings,
-                       sizeof(struct koneplus_profile_settings));
-       if (difference) {
-               retval = koneplus_set_profile_settings(usb_dev,
-                               (struct koneplus_profile_settings const *)buf);
-               if (!retval)
-                       memcpy(profile_settings, buf,
-                                       sizeof(struct koneplus_profile_settings));
-       }
-       mutex_unlock(&koneplus->koneplus_lock);
+       ssize_t retval;
 
+       retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
+                       KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
        if (retval)
                return retval;
 
-       return sizeof(struct koneplus_profile_settings);
+       return koneplus_sysfs_read(fp, kobj, buf, off, count,
+                       KONEPLUS_SIZE_PROFILE_SETTINGS,
+                       KONEPLUS_COMMAND_PROFILE_SETTINGS);
 }
 
 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
@@ -295,57 +212,17 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
-       struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
-
-       if (off >= sizeof(struct koneplus_profile_buttons))
-               return 0;
-
-       if (off + count > sizeof(struct koneplus_profile_buttons))
-               count = sizeof(struct koneplus_profile_buttons) - off;
-
-       mutex_lock(&koneplus->koneplus_lock);
-       memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
-                       count);
-       mutex_unlock(&koneplus->koneplus_lock);
-
-       return count;
-}
-
-static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       struct device *dev =
-                       container_of(kobj, struct device, kobj)->parent->parent;
-       struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-       int retval = 0;
-       int difference;
-       uint profile_number;
-       struct koneplus_profile_buttons *profile_buttons;
-
-       if (off != 0 || count != sizeof(struct koneplus_profile_buttons))
-               return -EINVAL;
-
-       profile_number = ((struct koneplus_profile_buttons const *)buf)->number;
-       profile_buttons = &koneplus->profile_buttons[profile_number];
-
-       mutex_lock(&koneplus->koneplus_lock);
-       difference = memcmp(buf, profile_buttons,
-                       sizeof(struct koneplus_profile_buttons));
-       if (difference) {
-               retval = koneplus_set_profile_buttons(usb_dev,
-                               (struct koneplus_profile_buttons const *)buf);
-               if (!retval)
-                       memcpy(profile_buttons, buf,
-                                       sizeof(struct koneplus_profile_buttons));
-       }
-       mutex_unlock(&koneplus->koneplus_lock);
+       ssize_t retval;
 
+       retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
+                       KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
        if (retval)
                return retval;
 
-       return sizeof(struct koneplus_profile_buttons);
+       return koneplus_sysfs_read(fp, kobj, buf, off, count,
+                       KONEPLUS_SIZE_PROFILE_BUTTONS,
+                       KONEPLUS_COMMAND_PROFILE_BUTTONS);
 }
 
 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
@@ -401,9 +278,20 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       struct koneplus_device *koneplus =
-                       hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version);
+       struct koneplus_device *koneplus;
+       struct usb_device *usb_dev;
+       struct koneplus_info info;
+
+       dev = dev->parent->parent;
+       koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+       usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+       mutex_lock(&koneplus->koneplus_lock);
+       roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
+                       &info, KONEPLUS_SIZE_INFO);
+       mutex_unlock(&koneplus->koneplus_lock);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
 
 static struct device_attribute koneplus_attributes[] = {
@@ -419,132 +307,85 @@ static struct device_attribute koneplus_attributes[] = {
 };
 
 static struct bin_attribute koneplus_bin_attributes[] = {
-       {
-               .attr = { .name = "sensor", .mode = 0660 },
-               .size = sizeof(struct koneplus_sensor),
-               .read = koneplus_sysfs_read_sensor,
-               .write = koneplus_sysfs_write_sensor
-       },
-       {
-               .attr = { .name = "tcu", .mode = 0220 },
-               .size = sizeof(struct koneplus_tcu),
-               .write = koneplus_sysfs_write_tcu
-       },
-       {
-               .attr = { .name = "tcu_image", .mode = 0440 },
-               .size = sizeof(struct koneplus_tcu_image),
-               .read = koneplus_sysfs_read_tcu_image
-       },
-       {
-               .attr = { .name = "profile_settings", .mode = 0220 },
-               .size = sizeof(struct koneplus_profile_settings),
-               .write = koneplus_sysfs_write_profile_settings
-       },
+       KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
+       KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO),
+       KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK),
+       KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO),
+       KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR),
+       KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU),
+       KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
+       KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+       KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
        {
                .attr = { .name = "profile1_settings", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_settings),
+               .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
                .read = koneplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[0]
        },
        {
                .attr = { .name = "profile2_settings", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_settings),
+               .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
                .read = koneplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[1]
        },
        {
                .attr = { .name = "profile3_settings", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_settings),
+               .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
                .read = koneplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[2]
        },
        {
                .attr = { .name = "profile4_settings", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_settings),
+               .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
                .read = koneplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[3]
        },
        {
                .attr = { .name = "profile5_settings", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_settings),
+               .size = KONEPLUS_SIZE_PROFILE_SETTINGS,
                .read = koneplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[4]
        },
-       {
-               .attr = { .name = "profile_buttons", .mode = 0220 },
-               .size = sizeof(struct koneplus_profile_buttons),
-               .write = koneplus_sysfs_write_profile_buttons
-       },
        {
                .attr = { .name = "profile1_buttons", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_buttons),
+               .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
                .read = koneplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[0]
        },
        {
                .attr = { .name = "profile2_buttons", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_buttons),
+               .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
                .read = koneplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[1]
        },
        {
                .attr = { .name = "profile3_buttons", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_buttons),
+               .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
                .read = koneplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[2]
        },
        {
                .attr = { .name = "profile4_buttons", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_buttons),
+               .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
                .read = koneplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[3]
        },
        {
                .attr = { .name = "profile5_buttons", .mode = 0440 },
-               .size = sizeof(struct koneplus_profile_buttons),
+               .size = KONEPLUS_SIZE_PROFILE_BUTTONS,
                .read = koneplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[4]
        },
-       {
-               .attr = { .name = "macro", .mode = 0220 },
-               .size = sizeof(struct koneplus_macro),
-               .write = koneplus_sysfs_write_macro
-       },
-       {
-               .attr = { .name = "talk", .mode = 0220 },
-               .size = sizeof(struct koneplus_talk),
-               .write = koneplus_sysfs_write_talk
-       },
        __ATTR_NULL
 };
 
 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
                struct koneplus_device *koneplus)
 {
-       int retval, i;
-       static uint wait = 200;
+       int retval;
 
        mutex_init(&koneplus->koneplus_lock);
 
-       retval = koneplus_get_info(usb_dev, &koneplus->info);
-       if (retval)
-               return retval;
-
-       for (i = 0; i < 5; ++i) {
-               msleep(wait);
-               retval = koneplus_get_profile_settings(usb_dev,
-                               &koneplus->profile_settings[i], i);
-               if (retval)
-                       return retval;
-
-               msleep(wait);
-               retval = koneplus_get_profile_buttons(usb_dev,
-                               &koneplus->profile_buttons[i], i);
-               if (retval)
-                       return retval;
-       }
-
-       msleep(wait);
        retval = koneplus_get_actual_profile(usb_dev);
        if (retval < 0)
                return retval;
@@ -709,6 +550,7 @@ static int koneplus_raw_event(struct hid_device *hdev,
 
 static const struct hid_device_id koneplus_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) },
        { }
 };
 
@@ -749,5 +591,5 @@ module_init(koneplus_init);
 module_exit(koneplus_exit);
 
 MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Kone[+] driver");
+MODULE_DESCRIPTION("USB Roccat Kone[+]/XTD driver");
 MODULE_LICENSE("GPL v2");
index 7074b2a4b94b26b955dc20b47cd570866a358cb7..af7f57e8cf3b38743892b0365bde4dfa61b07682 100644 (file)
 
 #include <linux/types.h>
 
-struct koneplus_talk {
-       uint8_t command; /* KONEPLUS_COMMAND_TALK */
-       uint8_t size; /* always 0x10 */
-       uint8_t data[14];
-} __packed;
+enum {
+       KONEPLUS_SIZE_ACTUAL_PROFILE = 0x03,
+       KONEPLUS_SIZE_CONTROL = 0x03,
+       KONEPLUS_SIZE_FIRMWARE_WRITE = 0x0402,
+       KONEPLUS_SIZE_INFO = 0x06,
+       KONEPLUS_SIZE_MACRO = 0x0822,
+       KONEPLUS_SIZE_PROFILE_SETTINGS = 0x2b,
+       KONEPLUS_SIZE_PROFILE_BUTTONS = 0x4d,
+       KONEPLUS_SIZE_SENSOR = 0x06,
+       KONEPLUS_SIZE_TALK = 0x10,
+       KONEPLUS_SIZE_TCU = 0x04,
+       KONEPLUS_SIZE_TCU_IMAGE = 0x0404,
+};
 
 enum koneplus_control_requests {
        KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
@@ -31,45 +39,6 @@ struct koneplus_actual_profile {
        uint8_t actual_profile; /* Range 0-4! */
 } __attribute__ ((__packed__));
 
-struct koneplus_profile_settings {
-       uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */
-       uint8_t size; /* always 43 */
-       uint8_t number; /* range 0-4 */
-       uint8_t advanced_sensitivity;
-       uint8_t sensitivity_x;
-       uint8_t sensitivity_y;
-       uint8_t cpi_levels_enabled;
-       uint8_t cpi_levels_x[5];
-       uint8_t cpi_startup_level; /* range 0-4 */
-       uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */
-       uint8_t unknown1;
-       uint8_t polling_rate;
-       uint8_t lights_enabled;
-       uint8_t light_effect_mode;
-       uint8_t color_flow_effect;
-       uint8_t light_effect_type;
-       uint8_t light_effect_speed;
-       uint8_t lights[16];
-       uint16_t checksum;
-} __attribute__ ((__packed__));
-
-struct koneplus_profile_buttons {
-       uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */
-       uint8_t size; /* always 77 */
-       uint8_t number; /* range 0-4 */
-       uint8_t data[72];
-       uint16_t checksum;
-} __attribute__ ((__packed__));
-
-struct koneplus_macro {
-       uint8_t command; /* KONEPLUS_COMMAND_MACRO */
-       uint16_t size; /* always 0x822 little endian */
-       uint8_t profile; /* range 0-4 */
-       uint8_t button; /* range 0-23 */
-       uint8_t data[2075];
-       uint16_t checksum;
-} __attribute__ ((__packed__));
-
 struct koneplus_info {
        uint8_t command; /* KONEPLUS_COMMAND_INFO */
        uint8_t size; /* always 6 */
@@ -77,51 +46,15 @@ struct koneplus_info {
        uint8_t unknown[3];
 } __attribute__ ((__packed__));
 
-struct koneplus_e {
-       uint8_t command; /* KONEPLUS_COMMAND_E */
-       uint8_t size; /* always 3 */
-       uint8_t unknown; /* TODO 1; 0 before firmware update */
-} __attribute__ ((__packed__));
-
-struct koneplus_sensor {
-       uint8_t command;  /* KONEPLUS_COMMAND_SENSOR */
-       uint8_t size; /* always 6 */
-       uint8_t data[4];
-} __attribute__ ((__packed__));
-
-struct koneplus_firmware_write {
-       uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */
-       uint8_t unknown[1025];
-} __attribute__ ((__packed__));
-
-struct koneplus_firmware_write_control {
-       uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */
-       /*
-        * value is 1 on success
-        * 3 means "not finished yet"
-        */
-       uint8_t value;
-       uint8_t unknown; /* always 0x75 */
-} __attribute__ ((__packed__));
-
-struct koneplus_tcu {
-       uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
-       uint8_t data[2];
-} __attribute__ ((__packed__));
-
-struct koneplus_tcu_image {
-       uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
-       uint8_t data[1024];
-       uint16_t checksum;
-} __attribute__ ((__packed__));
-
 enum koneplus_commands {
        KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+       KONEPLUS_COMMAND_CONTROL = 0x4,
        KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
        KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
        KONEPLUS_COMMAND_MACRO = 0x8,
        KONEPLUS_COMMAND_INFO = 0x9,
        KONEPLUS_COMMAND_TCU = 0xc,
+       KONEPLUS_COMMAND_TCU_IMAGE = 0xc,
        KONEPLUS_COMMAND_E = 0xe,
        KONEPLUS_COMMAND_SENSOR = 0xf,
        KONEPLUS_COMMAND_TALK = 0x10,
@@ -187,10 +120,6 @@ struct koneplus_device {
        int chrdev_minor;
 
        struct mutex koneplus_lock;
-
-       struct koneplus_info info;
-       struct koneplus_profile_settings profile_settings[5];
-       struct koneplus_profile_buttons profile_buttons[5];
 };
 
 #endif
index ca6527ac655dbbe6808c2f1a5e6521eefe7099f9..b8b37789b864bbeb3c4de24047658172518b25ec 100644 (file)
@@ -70,13 +70,6 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
        return kovaplus_send_control(usb_dev, number, request);
 }
 
-static int kovaplus_get_info(struct usb_device *usb_dev,
-               struct kovaplus_info *buf)
-{
-       return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
-                       buf, sizeof(struct kovaplus_info));
-}
-
 static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
                struct kovaplus_profile_settings *buf, uint number)
 {
@@ -88,15 +81,7 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
                return retval;
 
        return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
-                       buf, sizeof(struct kovaplus_profile_settings));
-}
-
-static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
-               struct kovaplus_profile_settings const *settings)
-{
-       return roccat_common2_send_with_status(usb_dev,
-                       KOVAPLUS_COMMAND_PROFILE_SETTINGS,
-                       settings, sizeof(struct kovaplus_profile_settings));
+                       buf, KOVAPLUS_SIZE_PROFILE_SETTINGS);
 }
 
 static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -110,15 +95,7 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
                return retval;
 
        return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
-                       buf, sizeof(struct kovaplus_profile_buttons));
-}
-
-static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
-               struct kovaplus_profile_buttons const *buttons)
-{
-       return roccat_common2_send_with_status(usb_dev,
-                       KOVAPLUS_COMMAND_PROFILE_BUTTONS,
-                       buttons, sizeof(struct kovaplus_profile_buttons));
+                       buf, KOVAPLUS_SIZE_PROFILE_BUTTONS);
 }
 
 /* retval is 0-4 on success, < 0 on error */
@@ -147,122 +124,141 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
                        &buf, sizeof(struct kovaplus_actual_profile));
 }
 
-static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
+static ssize_t kovaplus_sysfs_read(struct file *fp, struct kobject *kobj,
+               char *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
        struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
 
-       if (off >= sizeof(struct kovaplus_profile_settings))
+       if (off >= real_size)
                return 0;
 
-       if (off + count > sizeof(struct kovaplus_profile_settings))
-               count = sizeof(struct kovaplus_profile_settings) - off;
+       if (off != 0 || count != real_size)
+               return -EINVAL;
 
        mutex_lock(&kovaplus->kovaplus_lock);
-       memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off,
-                       count);
+       retval = roccat_common2_receive(usb_dev, command, buf, real_size);
        mutex_unlock(&kovaplus->kovaplus_lock);
 
-       return count;
+       if (retval)
+               return retval;
+
+       return real_size;
 }
 
-static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
+static ssize_t kovaplus_sysfs_write(struct file *fp, struct kobject *kobj,
+               void const *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
        struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-       int retval = 0;
-       int difference;
-       int profile_index;
-       struct kovaplus_profile_settings *profile_settings;
+       int retval;
 
-       if (off != 0 || count != sizeof(struct kovaplus_profile_settings))
+       if (off != 0 || count != real_size)
                return -EINVAL;
 
-       profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index;
-       profile_settings = &kovaplus->profile_settings[profile_index];
-
        mutex_lock(&kovaplus->kovaplus_lock);
-       difference = memcmp(buf, profile_settings,
-                       sizeof(struct kovaplus_profile_settings));
-       if (difference) {
-               retval = kovaplus_set_profile_settings(usb_dev,
-                               (struct kovaplus_profile_settings const *)buf);
-               if (!retval)
-                       memcpy(profile_settings, buf,
-                                       sizeof(struct kovaplus_profile_settings));
-       }
+       retval = roccat_common2_send_with_status(usb_dev, command,
+                       buf, real_size);
        mutex_unlock(&kovaplus->kovaplus_lock);
 
        if (retval)
                return retval;
 
-       return sizeof(struct kovaplus_profile_settings);
+       return real_size;
 }
 
-static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       struct device *dev =
-                       container_of(kobj, struct device, kobj)->parent->parent;
-       struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+#define KOVAPLUS_SYSFS_W(thingy, THINGY) \
+static ssize_t kovaplus_sysfs_write_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return kovaplus_sysfs_write(fp, kobj, buf, off, count, \
+                       KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
+}
 
-       if (off >= sizeof(struct kovaplus_profile_buttons))
-               return 0;
+#define KOVAPLUS_SYSFS_R(thingy, THINGY) \
+static ssize_t kovaplus_sysfs_read_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return kovaplus_sysfs_read(fp, kobj, buf, off, count, \
+                       KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
+}
 
-       if (off + count > sizeof(struct kovaplus_profile_buttons))
-               count = sizeof(struct kovaplus_profile_buttons) - off;
+#define KOVAPLUS_SYSFS_RW(thingy, THINGY) \
+KOVAPLUS_SYSFS_W(thingy, THINGY) \
+KOVAPLUS_SYSFS_R(thingy, THINGY)
 
-       mutex_lock(&kovaplus->kovaplus_lock);
-       memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off,
-                       count);
-       mutex_unlock(&kovaplus->kovaplus_lock);
+#define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0660 }, \
+       .size = KOVAPLUS_SIZE_ ## THINGY, \
+       .read = kovaplus_sysfs_read_ ## thingy, \
+       .write = kovaplus_sysfs_write_ ## thingy \
+}
+
+#define KOVAPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0440 }, \
+       .size = KOVAPLUS_SIZE_ ## THINGY, \
+       .read = kovaplus_sysfs_read_ ## thingy, \
+}
 
-       return count;
+#define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0220 }, \
+       .size = KOVAPLUS_SIZE_ ## THINGY, \
+       .write = kovaplus_sysfs_write_ ## thingy \
 }
 
-static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp,
+KOVAPLUS_SYSFS_W(control, CONTROL)
+KOVAPLUS_SYSFS_RW(info, INFO)
+KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+
+static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
                loff_t off, size_t count)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
-       struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-       int retval = 0;
-       int difference;
-       uint profile_index;
-       struct kovaplus_profile_buttons *profile_buttons;
+       ssize_t retval;
 
-       if (off != 0 || count != sizeof(struct kovaplus_profile_buttons))
-               return -EINVAL;
+       retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
+                       KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
+       if (retval)
+               return retval;
 
-       profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index;
-       profile_buttons = &kovaplus->profile_buttons[profile_index];
+       return kovaplus_sysfs_read(fp, kobj, buf, off, count,
+                       KOVAPLUS_SIZE_PROFILE_SETTINGS,
+                       KOVAPLUS_COMMAND_PROFILE_SETTINGS);
+}
 
-       mutex_lock(&kovaplus->kovaplus_lock);
-       difference = memcmp(buf, profile_buttons,
-                       sizeof(struct kovaplus_profile_buttons));
-       if (difference) {
-               retval = kovaplus_set_profile_buttons(usb_dev,
-                               (struct kovaplus_profile_buttons const *)buf);
-               if (!retval)
-                       memcpy(profile_buttons, buf,
-                                       sizeof(struct kovaplus_profile_buttons));
-       }
-       mutex_unlock(&kovaplus->kovaplus_lock);
+static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
+               struct kobject *kobj, struct bin_attribute *attr, char *buf,
+               loff_t off, size_t count)
+{
+       struct device *dev =
+                       container_of(kobj, struct device, kobj)->parent->parent;
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       ssize_t retval;
 
+       retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
+                       KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
        if (retval)
                return retval;
 
-       return sizeof(struct kovaplus_profile_buttons);
+       return kovaplus_sysfs_read(fp, kobj, buf, off, count,
+                       KOVAPLUS_SIZE_PROFILE_BUTTONS,
+                       KOVAPLUS_COMMAND_PROFILE_BUTTONS);
 }
 
 static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
@@ -342,9 +338,20 @@ static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
 static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       struct kovaplus_device *kovaplus =
-                       hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version);
+       struct kovaplus_device *kovaplus;
+       struct usb_device *usb_dev;
+       struct kovaplus_info info;
+
+       dev = dev->parent->parent;
+       kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+       usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+       mutex_lock(&kovaplus->kovaplus_lock);
+       roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
+                       &info, KOVAPLUS_SIZE_INFO);
+       mutex_unlock(&kovaplus->kovaplus_lock);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
 
 static struct device_attribute kovaplus_attributes[] = {
@@ -363,73 +370,67 @@ static struct device_attribute kovaplus_attributes[] = {
 };
 
 static struct bin_attribute kovaplus_bin_attributes[] = {
-       {
-               .attr = { .name = "profile_settings", .mode = 0220 },
-               .size = sizeof(struct kovaplus_profile_settings),
-               .write = kovaplus_sysfs_write_profile_settings
-       },
+       KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
+       KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO),
+       KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+       KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
        {
                .attr = { .name = "profile1_settings", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_settings),
+               .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
                .read = kovaplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[0]
        },
        {
                .attr = { .name = "profile2_settings", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_settings),
+               .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
                .read = kovaplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[1]
        },
        {
                .attr = { .name = "profile3_settings", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_settings),
+               .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
                .read = kovaplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[2]
        },
        {
                .attr = { .name = "profile4_settings", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_settings),
+               .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
                .read = kovaplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[3]
        },
        {
                .attr = { .name = "profile5_settings", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_settings),
+               .size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
                .read = kovaplus_sysfs_read_profilex_settings,
                .private = &profile_numbers[4]
        },
-       {
-               .attr = { .name = "profile_buttons", .mode = 0220 },
-               .size = sizeof(struct kovaplus_profile_buttons),
-               .write = kovaplus_sysfs_write_profile_buttons
-       },
        {
                .attr = { .name = "profile1_buttons", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_buttons),
+               .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
                .read = kovaplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[0]
        },
        {
                .attr = { .name = "profile2_buttons", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_buttons),
+               .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
                .read = kovaplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[1]
        },
        {
                .attr = { .name = "profile3_buttons", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_buttons),
+               .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
                .read = kovaplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[2]
        },
        {
                .attr = { .name = "profile4_buttons", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_buttons),
+               .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
                .read = kovaplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[3]
        },
        {
                .attr = { .name = "profile5_buttons", .mode = 0440 },
-               .size = sizeof(struct kovaplus_profile_buttons),
+               .size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
                .read = kovaplus_sysfs_read_profilex_buttons,
                .private = &profile_numbers[4]
        },
@@ -444,10 +445,6 @@ static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
 
        mutex_init(&kovaplus->kovaplus_lock);
 
-       retval = kovaplus_get_info(usb_dev, &kovaplus->info);
-       if (retval)
-               return retval;
-
        for (i = 0; i < 5; ++i) {
                msleep(wait);
                retval = kovaplus_get_profile_settings(usb_dev,
index f82daa1cdcb949cafb20cdceed4c757880565f4c..fbb7a16a7e542fbc843fc9cb4b40b04995175231 100644 (file)
 
 #include <linux/types.h>
 
+enum {
+       KOVAPLUS_SIZE_CONTROL = 0x03,
+       KOVAPLUS_SIZE_INFO = 0x06,
+       KOVAPLUS_SIZE_PROFILE_SETTINGS = 0x10,
+       KOVAPLUS_SIZE_PROFILE_BUTTONS = 0x17,
+};
+
 enum kovaplus_control_requests {
        /* write; value = profile number range 0-4 */
        KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
@@ -53,15 +60,9 @@ struct kovaplus_info {
        uint8_t unknown[3];
 } __packed;
 
-/* writes 1 on plugin */
-struct kovaplus_a {
-       uint8_t command; /* KOVAPLUS_COMMAND_A */
-       uint8_t size; /* 3 */
-       uint8_t unknown;
-} __packed;
-
 enum kovaplus_commands {
        KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+       KOVAPLUS_COMMAND_CONTROL = 0x4,
        KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
        KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
        KOVAPLUS_COMMAND_INFO = 0x9,
@@ -125,7 +126,6 @@ struct kovaplus_device {
        int roccat_claimed;
        int chrdev_minor;
        struct mutex kovaplus_lock;
-       struct kovaplus_info info;
        struct kovaplus_profile_settings profile_settings[5];
        struct kovaplus_profile_buttons profile_buttons[5];
 };
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
new file mode 100644 (file)
index 0000000..5084fb4
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Roccat Lua driver for Linux
+ *
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * Roccat Lua is a gamer mouse which cpi, button and light settings can be
+ * configured.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-lua.h"
+
+static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
+               char *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
+
+       if (off >= real_size)
+               return 0;
+
+       if (off != 0 || count != real_size)
+               return -EINVAL;
+
+       mutex_lock(&lua->lua_lock);
+       retval = roccat_common2_receive(usb_dev, command, buf, real_size);
+       mutex_unlock(&lua->lua_lock);
+
+       return retval ? retval : real_size;
+}
+
+static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
+               void const *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
+
+       if (off != 0 || count != real_size)
+               return -EINVAL;
+
+       mutex_lock(&lua->lua_lock);
+       retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
+       mutex_unlock(&lua->lua_lock);
+
+       return retval ? retval : real_size;
+}
+
+#define LUA_SYSFS_W(thingy, THINGY) \
+static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, \
+               char *buf, loff_t off, size_t count) \
+{ \
+       return lua_sysfs_write(fp, kobj, buf, off, count, \
+                       LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_SYSFS_R(thingy, THINGY) \
+static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, \
+               char *buf, loff_t off, size_t count) \
+{ \
+       return lua_sysfs_read(fp, kobj, buf, off, count, \
+                       LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+LUA_SYSFS_W(thingy, THINGY) \
+LUA_SYSFS_R(thingy, THINGY) \
+static struct bin_attribute lua_ ## thingy ## _attr = { \
+       .attr = { .name = #thingy, .mode = 0660 }, \
+       .size = LUA_SIZE_ ## THINGY, \
+       .read = lua_sysfs_read_ ## thingy, \
+       .write = lua_sysfs_write_ ## thingy \
+};
+
+LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
+
+static int lua_create_sysfs_attributes(struct usb_interface *intf)
+{
+       return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static void lua_remove_sysfs_attributes(struct usb_interface *intf)
+{
+       sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static int lua_init_lua_device_struct(struct usb_device *usb_dev,
+               struct lua_device *lua)
+{
+       mutex_init(&lua->lua_lock);
+
+       return 0;
+}
+
+static int lua_init_specials(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct lua_device *lua;
+       int retval;
+
+       lua = kzalloc(sizeof(*lua), GFP_KERNEL);
+       if (!lua) {
+               hid_err(hdev, "can't alloc device descriptor\n");
+               return -ENOMEM;
+       }
+       hid_set_drvdata(hdev, lua);
+
+       retval = lua_init_lua_device_struct(usb_dev, lua);
+       if (retval) {
+               hid_err(hdev, "couldn't init struct lua_device\n");
+               goto exit;
+       }
+
+       retval = lua_create_sysfs_attributes(intf);
+       if (retval) {
+               hid_err(hdev, "cannot create sysfs files\n");
+               goto exit;
+       }
+
+       return 0;
+exit:
+       kfree(lua);
+       return retval;
+}
+
+static void lua_remove_specials(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct lua_device *lua;
+
+       lua_remove_sysfs_attributes(intf);
+
+       lua = hid_get_drvdata(hdev);
+       kfree(lua);
+}
+
+static int lua_probe(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       int retval;
+
+       retval = hid_parse(hdev);
+       if (retval) {
+               hid_err(hdev, "parse failed\n");
+               goto exit;
+       }
+
+       retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (retval) {
+               hid_err(hdev, "hw start failed\n");
+               goto exit;
+       }
+
+       retval = lua_init_specials(hdev);
+       if (retval) {
+               hid_err(hdev, "couldn't install mouse\n");
+               goto exit_stop;
+       }
+
+       return 0;
+
+exit_stop:
+       hid_hw_stop(hdev);
+exit:
+       return retval;
+}
+
+static void lua_remove(struct hid_device *hdev)
+{
+       lua_remove_specials(hdev);
+       hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lua_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(hid, lua_devices);
+
+static struct hid_driver lua_driver = {
+               .name = "lua",
+               .id_table = lua_devices,
+               .probe = lua_probe,
+               .remove = lua_remove
+};
+
+static int __init lua_init(void)
+{
+       return hid_register_driver(&lua_driver);
+}
+
+static void __exit lua_exit(void)
+{
+       hid_unregister_driver(&lua_driver);
+}
+
+module_init(lua_init);
+module_exit(lua_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Lua driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-lua.h b/drivers/hid/hid-roccat-lua.h
new file mode 100644 (file)
index 0000000..547d77a
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __HID_ROCCAT_LUA_H
+#define __HID_ROCCAT_LUA_H
+
+/*
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * 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/types.h>
+
+enum {
+       LUA_SIZE_CONTROL = 8,
+};
+
+enum lua_commands {
+       LUA_COMMAND_CONTROL = 3,
+};
+
+struct lua_device {
+       struct mutex lua_lock;
+};
+
+#endif
index 1317c177a3e281404b2387f88f1decca40fa6ecc..d4f1e3bee5909eed76861acff408b582985462af 100644 (file)
@@ -66,48 +66,14 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
        if (retval)
                return retval;
        return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
-                       buf, sizeof(struct pyra_profile_settings));
-}
-
-static int pyra_get_profile_buttons(struct usb_device *usb_dev,
-               struct pyra_profile_buttons *buf, int number)
-{
-       int retval;
-       retval = pyra_send_control(usb_dev, number,
-                       PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
-       if (retval)
-               return retval;
-       return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS,
-                       buf, sizeof(struct pyra_profile_buttons));
+                       buf, PYRA_SIZE_PROFILE_SETTINGS);
 }
 
 static int pyra_get_settings(struct usb_device *usb_dev,
                struct pyra_settings *buf)
 {
        return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
-                       buf, sizeof(struct pyra_settings));
-}
-
-static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
-{
-       return roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
-                       buf, sizeof(struct pyra_info));
-}
-
-static int pyra_set_profile_settings(struct usb_device *usb_dev,
-               struct pyra_profile_settings const *settings)
-{
-       return roccat_common2_send_with_status(usb_dev,
-                       PYRA_COMMAND_PROFILE_SETTINGS, settings,
-                       sizeof(struct pyra_profile_settings));
-}
-
-static int pyra_set_profile_buttons(struct usb_device *usb_dev,
-               struct pyra_profile_buttons const *buttons)
-{
-       return roccat_common2_send_with_status(usb_dev,
-                       PYRA_COMMAND_PROFILE_BUTTONS, buttons,
-                       sizeof(struct pyra_profile_buttons));
+                       buf, PYRA_SIZE_SETTINGS);
 }
 
 static int pyra_set_settings(struct usb_device *usb_dev,
@@ -115,146 +81,144 @@ static int pyra_set_settings(struct usb_device *usb_dev,
 {
        return roccat_common2_send_with_status(usb_dev,
                        PYRA_COMMAND_SETTINGS, settings,
-                       sizeof(struct pyra_settings));
+                       PYRA_SIZE_SETTINGS);
 }
 
-static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
+static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj,
+               char *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
        struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
 
-       if (off >= sizeof(struct pyra_profile_settings))
+       if (off >= real_size)
                return 0;
 
-       if (off + count > sizeof(struct pyra_profile_settings))
-               count = sizeof(struct pyra_profile_settings) - off;
+       if (off != 0 || count != real_size)
+               return -EINVAL;
 
        mutex_lock(&pyra->pyra_lock);
-       memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off,
-                       count);
+       retval = roccat_common2_receive(usb_dev, command, buf, real_size);
        mutex_unlock(&pyra->pyra_lock);
 
-       return count;
+       if (retval)
+               return retval;
+
+       return real_size;
 }
 
-static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
+static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj,
+               void const *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
        struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
 
-       if (off >= sizeof(struct pyra_profile_buttons))
-               return 0;
-
-       if (off + count > sizeof(struct pyra_profile_buttons))
-               count = sizeof(struct pyra_profile_buttons) - off;
+       if (off != 0 || count != real_size)
+               return -EINVAL;
 
        mutex_lock(&pyra->pyra_lock);
-       memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off,
-                       count);
+       retval = roccat_common2_send_with_status(usb_dev, command, (void *)buf, real_size);
        mutex_unlock(&pyra->pyra_lock);
 
-       return count;
+       if (retval)
+               return retval;
+
+       return real_size;
 }
 
-static ssize_t pyra_sysfs_write_profile_settings(struct file *fp,
-               struct kobject *kobj, struct bin_attribute *attr, char *buf,
-               loff_t off, size_t count)
-{
-       struct device *dev =
-                       container_of(kobj, struct device, kobj)->parent->parent;
-       struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
-       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-       int retval = 0;
-       int difference;
-       int profile_number;
-       struct pyra_profile_settings *profile_settings;
+#define PYRA_SYSFS_W(thingy, THINGY) \
+static ssize_t pyra_sysfs_write_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return pyra_sysfs_write(fp, kobj, buf, off, count, \
+                       PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
+}
 
-       if (off != 0 || count != sizeof(struct pyra_profile_settings))
-               return -EINVAL;
+#define PYRA_SYSFS_R(thingy, THINGY) \
+static ssize_t pyra_sysfs_read_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return pyra_sysfs_read(fp, kobj, buf, off, count, \
+                       PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
+}
 
-       profile_number = ((struct pyra_profile_settings const *)buf)->number;
-       profile_settings = &pyra->profile_settings[profile_number];
+#define PYRA_SYSFS_RW(thingy, THINGY) \
+PYRA_SYSFS_W(thingy, THINGY) \
+PYRA_SYSFS_R(thingy, THINGY)
 
-       mutex_lock(&pyra->pyra_lock);
-       difference = memcmp(buf, profile_settings,
-                       sizeof(struct pyra_profile_settings));
-       if (difference) {
-               retval = pyra_set_profile_settings(usb_dev,
-                               (struct pyra_profile_settings const *)buf);
-               if (!retval)
-                       memcpy(profile_settings, buf,
-                                       sizeof(struct pyra_profile_settings));
-       }
-       mutex_unlock(&pyra->pyra_lock);
+#define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0660 }, \
+       .size = PYRA_SIZE_ ## THINGY, \
+       .read = pyra_sysfs_read_ ## thingy, \
+       .write = pyra_sysfs_write_ ## thingy \
+}
 
-       if (retval)
-               return retval;
+#define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0440 }, \
+       .size = PYRA_SIZE_ ## THINGY, \
+       .read = pyra_sysfs_read_ ## thingy, \
+}
 
-       return sizeof(struct pyra_profile_settings);
+#define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0220 }, \
+       .size = PYRA_SIZE_ ## THINGY, \
+       .write = pyra_sysfs_write_ ## thingy \
 }
 
-static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp,
+PYRA_SYSFS_W(control, CONTROL)
+PYRA_SYSFS_RW(info, INFO)
+PYRA_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+PYRA_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+PYRA_SYSFS_R(settings, SETTINGS)
+
+static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
                loff_t off, size_t count)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
-       struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-       int retval = 0;
-       int difference;
-       int profile_number;
-       struct pyra_profile_buttons *profile_buttons;
-
-       if (off != 0 || count != sizeof(struct pyra_profile_buttons))
-               return -EINVAL;
-
-       profile_number = ((struct pyra_profile_buttons const *)buf)->number;
-       profile_buttons = &pyra->profile_buttons[profile_number];
-
-       mutex_lock(&pyra->pyra_lock);
-       difference = memcmp(buf, profile_buttons,
-                       sizeof(struct pyra_profile_buttons));
-       if (difference) {
-               retval = pyra_set_profile_buttons(usb_dev,
-                               (struct pyra_profile_buttons const *)buf);
-               if (!retval)
-                       memcpy(profile_buttons, buf,
-                                       sizeof(struct pyra_profile_buttons));
-       }
-       mutex_unlock(&pyra->pyra_lock);
+       ssize_t retval;
 
+       retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
+                       PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
        if (retval)
                return retval;
 
-       return sizeof(struct pyra_profile_buttons);
+       return pyra_sysfs_read(fp, kobj, buf, off, count,
+                       PYRA_SIZE_PROFILE_SETTINGS,
+                       PYRA_COMMAND_PROFILE_SETTINGS);
 }
 
-static ssize_t pyra_sysfs_read_settings(struct file *fp,
+static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
                struct kobject *kobj, struct bin_attribute *attr, char *buf,
                loff_t off, size_t count)
 {
        struct device *dev =
                        container_of(kobj, struct device, kobj)->parent->parent;
-       struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
-
-       if (off >= sizeof(struct pyra_settings))
-               return 0;
-
-       if (off + count > sizeof(struct pyra_settings))
-               count = sizeof(struct pyra_settings) - off;
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       ssize_t retval;
 
-       mutex_lock(&pyra->pyra_lock);
-       memcpy(buf, ((char const *)&pyra->settings) + off, count);
-       mutex_unlock(&pyra->pyra_lock);
+       retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
+                       PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
+       if (retval)
+               return retval;
 
-       return count;
+       return pyra_sysfs_read(fp, kobj, buf, off, count,
+                       PYRA_SIZE_PROFILE_BUTTONS,
+                       PYRA_COMMAND_PROFILE_BUTTONS);
 }
 
 static ssize_t pyra_sysfs_write_settings(struct file *fp,
@@ -266,35 +230,32 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
        struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
        int retval = 0;
-       int difference;
        struct pyra_roccat_report roccat_report;
+       struct pyra_settings const *settings;
 
-       if (off != 0 || count != sizeof(struct pyra_settings))
+       if (off != 0 || count != PYRA_SIZE_SETTINGS)
                return -EINVAL;
 
        mutex_lock(&pyra->pyra_lock);
-       difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings));
-       if (difference) {
-               retval = pyra_set_settings(usb_dev,
-                               (struct pyra_settings const *)buf);
-               if (retval) {
-                       mutex_unlock(&pyra->pyra_lock);
-                       return retval;
-               }
-
-               memcpy(&pyra->settings, buf,
-                               sizeof(struct pyra_settings));
 
-               profile_activated(pyra, pyra->settings.startup_profile);
+       settings = (struct pyra_settings const *)buf;
 
-               roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
-               roccat_report.value = pyra->settings.startup_profile + 1;
-               roccat_report.key = 0;
-               roccat_report_event(pyra->chrdev_minor,
-                               (uint8_t const *)&roccat_report);
+       retval = pyra_set_settings(usb_dev, settings);
+       if (retval) {
+               mutex_unlock(&pyra->pyra_lock);
+               return retval;
        }
+
+       profile_activated(pyra, settings->startup_profile);
+
+       roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
+       roccat_report.value = settings->startup_profile + 1;
+       roccat_report.key = 0;
+       roccat_report_event(pyra->chrdev_minor,
+                       (uint8_t const *)&roccat_report);
+
        mutex_unlock(&pyra->pyra_lock);
-       return sizeof(struct pyra_settings);
+       return PYRA_SIZE_SETTINGS;
 }
 
 
@@ -311,23 +272,34 @@ static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
 {
        struct pyra_device *pyra =
                        hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile);
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       struct pyra_settings settings;
+
+       mutex_lock(&pyra->pyra_lock);
+       roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
+                       &settings, PYRA_SIZE_SETTINGS);
+       mutex_unlock(&pyra->pyra_lock);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile);
 }
 
 static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       struct pyra_device *pyra =
-                       hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version);
-}
+       struct pyra_device *pyra;
+       struct usb_device *usb_dev;
+       struct pyra_info info;
 
-static ssize_t pyra_sysfs_show_startup_profile(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct pyra_device *pyra =
-                       hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-       return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile);
+       dev = dev->parent->parent;
+       pyra = hid_get_drvdata(dev_get_drvdata(dev));
+       usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+       mutex_lock(&pyra->pyra_lock);
+       roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
+                       &info, PYRA_SIZE_INFO);
+       mutex_unlock(&pyra->pyra_lock);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
 
 static struct device_attribute pyra_attributes[] = {
@@ -336,105 +308,88 @@ static struct device_attribute pyra_attributes[] = {
        __ATTR(firmware_version, 0440,
                        pyra_sysfs_show_firmware_version, NULL),
        __ATTR(startup_profile, 0440,
-                       pyra_sysfs_show_startup_profile, NULL),
+                       pyra_sysfs_show_actual_profile, NULL),
        __ATTR_NULL
 };
 
 static struct bin_attribute pyra_bin_attributes[] = {
-       {
-               .attr = { .name = "profile_settings", .mode = 0220 },
-               .size = sizeof(struct pyra_profile_settings),
-               .write = pyra_sysfs_write_profile_settings
-       },
+       PYRA_BIN_ATTRIBUTE_W(control, CONTROL),
+       PYRA_BIN_ATTRIBUTE_RW(info, INFO),
+       PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+       PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
+       PYRA_BIN_ATTRIBUTE_RW(settings, SETTINGS),
        {
                .attr = { .name = "profile1_settings", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_settings),
+               .size = PYRA_SIZE_PROFILE_SETTINGS,
                .read = pyra_sysfs_read_profilex_settings,
                .private = &profile_numbers[0]
        },
        {
                .attr = { .name = "profile2_settings", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_settings),
+               .size = PYRA_SIZE_PROFILE_SETTINGS,
                .read = pyra_sysfs_read_profilex_settings,
                .private = &profile_numbers[1]
        },
        {
                .attr = { .name = "profile3_settings", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_settings),
+               .size = PYRA_SIZE_PROFILE_SETTINGS,
                .read = pyra_sysfs_read_profilex_settings,
                .private = &profile_numbers[2]
        },
        {
                .attr = { .name = "profile4_settings", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_settings),
+               .size = PYRA_SIZE_PROFILE_SETTINGS,
                .read = pyra_sysfs_read_profilex_settings,
                .private = &profile_numbers[3]
        },
        {
                .attr = { .name = "profile5_settings", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_settings),
+               .size = PYRA_SIZE_PROFILE_SETTINGS,
                .read = pyra_sysfs_read_profilex_settings,
                .private = &profile_numbers[4]
        },
-       {
-               .attr = { .name = "profile_buttons", .mode = 0220 },
-               .size = sizeof(struct pyra_profile_buttons),
-               .write = pyra_sysfs_write_profile_buttons
-       },
        {
                .attr = { .name = "profile1_buttons", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_buttons),
+               .size = PYRA_SIZE_PROFILE_BUTTONS,
                .read = pyra_sysfs_read_profilex_buttons,
                .private = &profile_numbers[0]
        },
        {
                .attr = { .name = "profile2_buttons", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_buttons),
+               .size = PYRA_SIZE_PROFILE_BUTTONS,
                .read = pyra_sysfs_read_profilex_buttons,
                .private = &profile_numbers[1]
        },
        {
                .attr = { .name = "profile3_buttons", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_buttons),
+               .size = PYRA_SIZE_PROFILE_BUTTONS,
                .read = pyra_sysfs_read_profilex_buttons,
                .private = &profile_numbers[2]
        },
        {
                .attr = { .name = "profile4_buttons", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_buttons),
+               .size = PYRA_SIZE_PROFILE_BUTTONS,
                .read = pyra_sysfs_read_profilex_buttons,
                .private = &profile_numbers[3]
        },
        {
                .attr = { .name = "profile5_buttons", .mode = 0440 },
-               .size = sizeof(struct pyra_profile_buttons),
+               .size = PYRA_SIZE_PROFILE_BUTTONS,
                .read = pyra_sysfs_read_profilex_buttons,
                .private = &profile_numbers[4]
        },
-       {
-               .attr = { .name = "settings", .mode = 0660 },
-               .size = sizeof(struct pyra_settings),
-               .read = pyra_sysfs_read_settings,
-               .write = pyra_sysfs_write_settings
-       },
        __ATTR_NULL
 };
 
 static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
                struct pyra_device *pyra)
 {
-       struct pyra_info info;
+       struct pyra_settings settings;
        int retval, i;
 
        mutex_init(&pyra->pyra_lock);
 
-       retval = pyra_get_info(usb_dev, &info);
-       if (retval)
-               return retval;
-
-       pyra->firmware_version = info.firmware_version;
-
-       retval = pyra_get_settings(usb_dev, &pyra->settings);
+       retval = pyra_get_settings(usb_dev, &settings);
        if (retval)
                return retval;
 
@@ -443,14 +398,9 @@ static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
                                &pyra->profile_settings[i], i);
                if (retval)
                        return retval;
-
-               retval = pyra_get_profile_buttons(usb_dev,
-                               &pyra->profile_buttons[i], i);
-               if (retval)
-                       return retval;
        }
 
-       profile_activated(pyra, pyra->settings.startup_profile);
+       profile_activated(pyra, settings.startup_profile);
 
        return 0;
 }
index eada7830fa996242f417805e852b0f838080da08..beedcf001ceb5f9f23e5a3991c1974815bdd4aee 100644 (file)
 
 #include <linux/types.h>
 
-struct pyra_b {
-       uint8_t command; /* PYRA_COMMAND_B */
-       uint8_t size; /* always 3 */
-       uint8_t unknown; /* 1 */
-} __attribute__ ((__packed__));
+enum {
+       PYRA_SIZE_CONTROL = 0x03,
+       PYRA_SIZE_INFO = 0x06,
+       PYRA_SIZE_PROFILE_SETTINGS = 0x0d,
+       PYRA_SIZE_PROFILE_BUTTONS = 0x13,
+       PYRA_SIZE_SETTINGS = 0x03,
+};
 
 enum pyra_control_requests {
        PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
@@ -46,14 +48,6 @@ struct pyra_profile_settings {
        uint16_t checksum; /* byte sum */
 } __attribute__ ((__packed__));
 
-struct pyra_profile_buttons {
-       uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
-       uint8_t size; /* always 0x13 */
-       uint8_t number; /* Range 0-4 */
-       uint8_t buttons[14];
-       uint16_t checksum; /* byte sum */
-} __attribute__ ((__packed__));
-
 struct pyra_info {
        uint8_t command; /* PYRA_COMMAND_INFO */
        uint8_t size; /* always 6 */
@@ -64,6 +58,7 @@ struct pyra_info {
 } __attribute__ ((__packed__));
 
 enum pyra_commands {
+       PYRA_COMMAND_CONTROL = 0x4,
        PYRA_COMMAND_SETTINGS = 0x5,
        PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
        PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
@@ -148,13 +143,10 @@ struct pyra_roccat_report {
 struct pyra_device {
        int actual_profile;
        int actual_cpi;
-       int firmware_version;
        int roccat_claimed;
        int chrdev_minor;
        struct mutex pyra_lock;
-       struct pyra_settings settings;
        struct pyra_profile_settings profile_settings[5];
-       struct pyra_profile_buttons profile_buttons[5];
 };
 
 #endif
index 014afba407e02dbe18d8b47426eebd6f5cbdb0e4..31747a29c09348a9d7ad5b45021b12800832e087 100644 (file)
@@ -120,7 +120,7 @@ SAVU_SYSFS_RW(profile, PROFILE)
 SAVU_SYSFS_RW(general, GENERAL)
 SAVU_SYSFS_RW(buttons, BUTTONS)
 SAVU_SYSFS_RW(macro, MACRO)
-SAVU_SYSFS_R(info, INFO)
+SAVU_SYSFS_RW(info, INFO)
 SAVU_SYSFS_RW(sensor, SENSOR)
 
 static struct bin_attribute savu_bin_attributes[] = {
@@ -129,7 +129,7 @@ static struct bin_attribute savu_bin_attributes[] = {
        SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
        SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
        SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
-       SAVU_BIN_ATTRIBUTE_R(info, INFO),
+       SAVU_BIN_ATTRIBUTE_RW(info, INFO),
        SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
        __ATTR_NULL
 };
index d9d73e9163ebb4f2e8956746b88e1c6e0b575877..0bc58bd8d4f5a9e496187310326aff7e031e74f0 100644 (file)
@@ -82,23 +82,6 @@ struct hid_sensor_hub_callbacks_list {
        void *priv;
 };
 
-static int sensor_hub_check_for_sensor_page(struct hid_device *hdev)
-{
-       int i;
-       int ret = -EINVAL;
-
-       for (i = 0; i < hdev->maxcollection; i++) {
-               struct hid_collection *col = &hdev->collection[i];
-               if (col->type == HID_COLLECTION_PHYSICAL &&
-                  (col->usage & HID_USAGE_PAGE) == HID_UP_SENSOR) {
-                       ret = 0;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
 static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
                                                int dir)
 {
@@ -437,9 +420,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
        ptr = raw_data;
        ptr++; /*Skip report id*/
 
-       if (!report)
-               goto err_report;
-
        spin_lock_irqsave(&pdata->lock, flags);
 
        for (i = 0; i < report->maxfield; ++i) {
@@ -485,7 +465,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
                                callback->pdev);
        spin_unlock_irqrestore(&pdata->lock, flags);
 
-err_report:
        return 1;
 }
 
@@ -524,10 +503,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
                hid_err(hdev, "parse failed\n");
                goto err_free;
        }
-       if (sensor_hub_check_for_sensor_page(hdev) < 0) {
-               hid_err(hdev, "sensor page not found\n");
-               goto err_free;
-       }
        INIT_LIST_HEAD(&hdev->inputs);
 
        ret = hid_hw_start(hdev, 0);
@@ -630,16 +605,7 @@ static void sensor_hub_remove(struct hid_device *hdev)
 }
 
 static const struct hid_device_id sensor_hub_devices[] = {
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
-                       USB_DEVICE_ID_SENSOR_HUB_1020) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
-                       USB_DEVICE_ID_SENSOR_HUB_1020) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
-                       USB_DEVICE_ID_SENSOR_HUB_09FA) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
-                       USB_DEVICE_ID_SENSOR_HUB_09FA) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
-                       USB_DEVICE_ID_SENSOR_HUB_7014) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, sensor_hub_devices);
index 7c47fc3f7b2b0b28f27021c75bb3b8d8f3771c4d..413a73187d33d9f0313444f8c20288408cd001b9 100644 (file)
@@ -57,10 +57,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
                        set_current_state(TASK_INTERRUPTIBLE);
 
                        while (list->head == list->tail) {
-                               if (file->f_flags & O_NONBLOCK) {
-                                       ret = -EAGAIN;
-                                       break;
-                               }
                                if (signal_pending(current)) {
                                        ret = -ERESTARTSYS;
                                        break;
@@ -69,6 +65,10 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
                                        ret = -EIO;
                                        break;
                                }
+                               if (file->f_flags & O_NONBLOCK) {
+                                       ret = -EAGAIN;
+                                       break;
+                               }
 
                                /* allow O_NONBLOCK to work well from other threads */
                                mutex_unlock(&list->read_mutex);
@@ -295,6 +295,13 @@ out:
 
 }
 
+static int hidraw_fasync(int fd, struct file *file, int on)
+{
+       struct hidraw_list *list = file->private_data;
+
+       return fasync_helper(fd, file, on, &list->fasync);
+}
+
 static int hidraw_release(struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
@@ -438,6 +445,7 @@ static const struct file_operations hidraw_ops = {
        .open =         hidraw_open,
        .release =      hidraw_release,
        .unlocked_ioctl = hidraw_ioctl,
+       .fasync =       hidraw_fasync,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = hidraw_ioctl,
 #endif
diff --git a/drivers/hid/i2c-hid/Kconfig b/drivers/hid/i2c-hid/Kconfig
new file mode 100644 (file)
index 0000000..b66617a
--- /dev/null
@@ -0,0 +1,18 @@
+menu "I2C HID support"
+       depends on I2C
+
+config I2C_HID
+       tristate "HID over I2C transport layer"
+       default n
+       depends on I2C && INPUT
+       select HID
+       ---help---
+         Say Y here if you use a keyboard, a touchpad, a touchscreen, or any
+         other HID based devices which is connected to your computer via I2C.
+
+         If unsure, say N.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-hid.
+
+endmenu
diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
new file mode 100644 (file)
index 0000000..832d8f9
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the I2C input drivers
+#
+
+obj-$(CONFIG_I2C_HID)                          += i2c-hid.o
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
new file mode 100644 (file)
index 0000000..9ef2224
--- /dev/null
@@ -0,0 +1,979 @@
+/*
+ * HID over I2C protocol implementation
+ *
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
+ * Copyright (c) 2012 Red Hat, Inc
+ *
+ * This code is partly based on "USB HID support for Linux":
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2007-2008 Oliver Neukum
+ *  Copyright (c) 2006-2010 Jiri Kosina
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/hid.h>
+#include <linux/mutex.h>
+
+#include <linux/i2c/i2c-hid.h>
+
+/* flags */
+#define I2C_HID_STARTED                (1 << 0)
+#define I2C_HID_RESET_PENDING  (1 << 1)
+#define I2C_HID_READ_PENDING   (1 << 2)
+
+#define I2C_HID_PWR_ON         0x00
+#define I2C_HID_PWR_SLEEP      0x01
+
+/* debug option */
+static bool debug;
+module_param(debug, bool, 0444);
+MODULE_PARM_DESC(debug, "print a lot of debug information");
+
+#define i2c_hid_dbg(ihid, fmt, arg...)                                   \
+do {                                                                     \
+       if (debug)                                                        \
+               dev_printk(KERN_DEBUG, &(ihid)->client->dev, fmt, ##arg); \
+} while (0)
+
+struct i2c_hid_desc {
+       __le16 wHIDDescLength;
+       __le16 bcdVersion;
+       __le16 wReportDescLength;
+       __le16 wReportDescRegister;
+       __le16 wInputRegister;
+       __le16 wMaxInputLength;
+       __le16 wOutputRegister;
+       __le16 wMaxOutputLength;
+       __le16 wCommandRegister;
+       __le16 wDataRegister;
+       __le16 wVendorID;
+       __le16 wProductID;
+       __le16 wVersionID;
+       __le32 reserved;
+} __packed;
+
+struct i2c_hid_cmd {
+       unsigned int registerIndex;
+       __u8 opcode;
+       unsigned int length;
+       bool wait;
+};
+
+union command {
+       u8 data[0];
+       struct cmd {
+               __le16 reg;
+               __u8 reportTypeID;
+               __u8 opcode;
+       } __packed c;
+};
+
+#define I2C_HID_CMD(opcode_) \
+       .opcode = opcode_, .length = 4, \
+       .registerIndex = offsetof(struct i2c_hid_desc, wCommandRegister)
+
+/* fetch HID descriptor */
+static const struct i2c_hid_cmd hid_descr_cmd = { .length = 2 };
+/* fetch report descriptors */
+static const struct i2c_hid_cmd hid_report_descr_cmd = {
+               .registerIndex = offsetof(struct i2c_hid_desc,
+                       wReportDescRegister),
+               .opcode = 0x00,
+               .length = 2 };
+/* commands */
+static const struct i2c_hid_cmd hid_reset_cmd =                { I2C_HID_CMD(0x01),
+                                                         .wait = true };
+static const struct i2c_hid_cmd hid_get_report_cmd =   { I2C_HID_CMD(0x02) };
+static const struct i2c_hid_cmd hid_set_report_cmd =   { I2C_HID_CMD(0x03) };
+static const struct i2c_hid_cmd hid_set_power_cmd =    { I2C_HID_CMD(0x08) };
+
+/*
+ * These definitions are not used here, but are defined by the spec.
+ * Keeping them here for documentation purposes.
+ *
+ * static const struct i2c_hid_cmd hid_get_idle_cmd = { I2C_HID_CMD(0x04) };
+ * static const struct i2c_hid_cmd hid_set_idle_cmd = { I2C_HID_CMD(0x05) };
+ * static const struct i2c_hid_cmd hid_get_protocol_cmd = { I2C_HID_CMD(0x06) };
+ * static const struct i2c_hid_cmd hid_set_protocol_cmd = { I2C_HID_CMD(0x07) };
+ */
+
+static DEFINE_MUTEX(i2c_hid_open_mut);
+
+/* The main device structure */
+struct i2c_hid {
+       struct i2c_client       *client;        /* i2c client */
+       struct hid_device       *hid;   /* pointer to corresponding HID dev */
+       union {
+               __u8 hdesc_buffer[sizeof(struct i2c_hid_desc)];
+               struct i2c_hid_desc hdesc;      /* the HID Descriptor */
+       };
+       __le16                  wHIDDescRegister; /* location of the i2c
+                                                  * register of the HID
+                                                  * descriptor. */
+       unsigned int            bufsize;        /* i2c buffer size */
+       char                    *inbuf;         /* Input buffer */
+       char                    *cmdbuf;        /* Command buffer */
+       char                    *argsbuf;       /* Command arguments buffer */
+
+       unsigned long           flags;          /* device flags */
+
+       wait_queue_head_t       wait;           /* For waiting the interrupt */
+};
+
+static int __i2c_hid_command(struct i2c_client *client,
+               const struct i2c_hid_cmd *command, u8 reportID,
+               u8 reportType, u8 *args, int args_len,
+               unsigned char *buf_recv, int data_len)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       union command *cmd = (union command *)ihid->cmdbuf;
+       int ret;
+       struct i2c_msg msg[2];
+       int msg_num = 1;
+
+       int length = command->length;
+       bool wait = command->wait;
+       unsigned int registerIndex = command->registerIndex;
+
+       /* special case for hid_descr_cmd */
+       if (command == &hid_descr_cmd) {
+               cmd->c.reg = ihid->wHIDDescRegister;
+       } else {
+               cmd->data[0] = ihid->hdesc_buffer[registerIndex];
+               cmd->data[1] = ihid->hdesc_buffer[registerIndex + 1];
+       }
+
+       if (length > 2) {
+               cmd->c.opcode = command->opcode;
+               cmd->c.reportTypeID = reportID | reportType << 4;
+       }
+
+       memcpy(cmd->data + length, args, args_len);
+       length += args_len;
+
+       i2c_hid_dbg(ihid, "%s: cmd=%*ph\n", __func__, length, cmd->data);
+
+       msg[0].addr = client->addr;
+       msg[0].flags = client->flags & I2C_M_TEN;
+       msg[0].len = length;
+       msg[0].buf = cmd->data;
+       if (data_len > 0) {
+               msg[1].addr = client->addr;
+               msg[1].flags = client->flags & I2C_M_TEN;
+               msg[1].flags |= I2C_M_RD;
+               msg[1].len = data_len;
+               msg[1].buf = buf_recv;
+               msg_num = 2;
+               set_bit(I2C_HID_READ_PENDING, &ihid->flags);
+       }
+
+       if (wait)
+               set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+
+       ret = i2c_transfer(client->adapter, msg, msg_num);
+
+       if (data_len > 0)
+               clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
+
+       if (ret != msg_num)
+               return ret < 0 ? ret : -EIO;
+
+       ret = 0;
+
+       if (wait) {
+               i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
+               if (!wait_event_timeout(ihid->wait,
+                               !test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
+                               msecs_to_jiffies(5000)))
+                       ret = -ENODATA;
+               i2c_hid_dbg(ihid, "%s: finished.\n", __func__);
+       }
+
+       return ret;
+}
+
+static int i2c_hid_command(struct i2c_client *client,
+               const struct i2c_hid_cmd *command,
+               unsigned char *buf_recv, int data_len)
+{
+       return __i2c_hid_command(client, command, 0, 0, NULL, 0,
+                               buf_recv, data_len);
+}
+
+static int i2c_hid_get_report(struct i2c_client *client, u8 reportType,
+               u8 reportID, unsigned char *buf_recv, int data_len)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       u8 args[3];
+       int ret;
+       int args_len = 0;
+       u16 readRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+
+       i2c_hid_dbg(ihid, "%s\n", __func__);
+
+       if (reportID >= 0x0F) {
+               args[args_len++] = reportID;
+               reportID = 0x0F;
+       }
+
+       args[args_len++] = readRegister & 0xFF;
+       args[args_len++] = readRegister >> 8;
+
+       ret = __i2c_hid_command(client, &hid_get_report_cmd, reportID,
+               reportType, args, args_len, buf_recv, data_len);
+       if (ret) {
+               dev_err(&client->dev,
+                       "failed to retrieve report from device.\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
+               u8 reportID, unsigned char *buf, size_t data_len)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       u8 *args = ihid->argsbuf;
+       int ret;
+       u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+
+       /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
+       u16 size =      2                       /* size */ +
+                       (reportID ? 1 : 0)      /* reportID */ +
+                       data_len                /* buf */;
+       int args_len =  (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
+                       2                       /* dataRegister */ +
+                       size                    /* args */;
+       int index = 0;
+
+       i2c_hid_dbg(ihid, "%s\n", __func__);
+
+       if (reportID >= 0x0F) {
+               args[index++] = reportID;
+               reportID = 0x0F;
+       }
+
+       args[index++] = dataRegister & 0xFF;
+       args[index++] = dataRegister >> 8;
+
+       args[index++] = size & 0xFF;
+       args[index++] = size >> 8;
+
+       if (reportID)
+               args[index++] = reportID;
+
+       memcpy(&args[index], buf, data_len);
+
+       ret = __i2c_hid_command(client, &hid_set_report_cmd, reportID,
+               reportType, args, args_len, NULL, 0);
+       if (ret) {
+               dev_err(&client->dev, "failed to set a report to device.\n");
+               return ret;
+       }
+
+       return data_len;
+}
+
+static int i2c_hid_set_power(struct i2c_client *client, int power_state)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       int ret;
+
+       i2c_hid_dbg(ihid, "%s\n", __func__);
+
+       ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
+               0, NULL, 0, NULL, 0);
+       if (ret)
+               dev_err(&client->dev, "failed to change power setting.\n");
+
+       return ret;
+}
+
+static int i2c_hid_hwreset(struct i2c_client *client)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       int ret;
+
+       i2c_hid_dbg(ihid, "%s\n", __func__);
+
+       ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+       if (ret)
+               return ret;
+
+       i2c_hid_dbg(ihid, "resetting...\n");
+
+       ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
+       if (ret) {
+               dev_err(&client->dev, "failed to reset device.\n");
+               i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void i2c_hid_get_input(struct i2c_hid *ihid)
+{
+       int ret, ret_size;
+       int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
+
+       ret = i2c_master_recv(ihid->client, ihid->inbuf, size);
+       if (ret != size) {
+               if (ret < 0)
+                       return;
+
+               dev_err(&ihid->client->dev, "%s: got %d data instead of %d\n",
+                       __func__, ret, size);
+               return;
+       }
+
+       ret_size = ihid->inbuf[0] | ihid->inbuf[1] << 8;
+
+       if (!ret_size) {
+               /* host or device initiated RESET completed */
+               if (test_and_clear_bit(I2C_HID_RESET_PENDING, &ihid->flags))
+                       wake_up(&ihid->wait);
+               return;
+       }
+
+       if (ret_size > size) {
+               dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+                       __func__, size, ret_size);
+               return;
+       }
+
+       i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
+
+       if (test_bit(I2C_HID_STARTED, &ihid->flags))
+               hid_input_report(ihid->hid, HID_INPUT_REPORT, ihid->inbuf + 2,
+                               ret_size - 2, 1);
+
+       return;
+}
+
+static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
+{
+       struct i2c_hid *ihid = dev_id;
+
+       if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
+               return IRQ_HANDLED;
+
+       i2c_hid_get_input(ihid);
+
+       return IRQ_HANDLED;
+}
+
+static int i2c_hid_get_report_length(struct hid_report *report)
+{
+       return ((report->size - 1) >> 3) + 1 +
+               report->device->report_enum[report->type].numbered + 2;
+}
+
+static void i2c_hid_init_report(struct hid_report *report, u8 *buffer,
+       size_t bufsize)
+{
+       struct hid_device *hid = report->device;
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       unsigned int size, ret_size;
+
+       size = i2c_hid_get_report_length(report);
+       if (i2c_hid_get_report(client,
+                       report->type == HID_FEATURE_REPORT ? 0x03 : 0x01,
+                       report->id, buffer, size))
+               return;
+
+       i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, ihid->inbuf);
+
+       ret_size = buffer[0] | (buffer[1] << 8);
+
+       if (ret_size != size) {
+               dev_err(&client->dev, "error in %s size:%d / ret_size:%d\n",
+                       __func__, size, ret_size);
+               return;
+       }
+
+       /* hid->driver_lock is held as we are in probe function,
+        * we just need to setup the input fields, so using
+        * hid_report_raw_event is safe. */
+       hid_report_raw_event(hid, report->type, buffer + 2, size - 2, 1);
+}
+
+/*
+ * Initialize all reports
+ */
+static void i2c_hid_init_reports(struct hid_device *hid)
+{
+       struct hid_report *report;
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       u8 *inbuf = kzalloc(ihid->bufsize, GFP_KERNEL);
+
+       if (!inbuf) {
+               dev_err(&client->dev, "can not retrieve initial reports\n");
+               return;
+       }
+
+       list_for_each_entry(report,
+               &hid->report_enum[HID_INPUT_REPORT].report_list, list)
+               i2c_hid_init_report(report, inbuf, ihid->bufsize);
+
+       list_for_each_entry(report,
+               &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
+               i2c_hid_init_report(report, inbuf, ihid->bufsize);
+
+       kfree(inbuf);
+}
+
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type,
+               unsigned int *max)
+{
+       struct hid_report *report;
+       unsigned int size;
+
+       /* We should not rely on wMaxInputLength, as some devices may set it to
+        * a wrong length. */
+       list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+               size = i2c_hid_get_report_length(report);
+               if (*max < size)
+                       *max = size;
+       }
+}
+
+static void i2c_hid_free_buffers(struct i2c_hid *ihid)
+{
+       kfree(ihid->inbuf);
+       kfree(ihid->argsbuf);
+       kfree(ihid->cmdbuf);
+       ihid->inbuf = NULL;
+       ihid->cmdbuf = NULL;
+       ihid->argsbuf = NULL;
+       ihid->bufsize = 0;
+}
+
+static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size)
+{
+       /* the worst case is computed from the set_report command with a
+        * reportID > 15 and the maximum report length */
+       int args_len = sizeof(__u8) + /* optional ReportID byte */
+                      sizeof(__u16) + /* data register */
+                      sizeof(__u16) + /* size of the report */
+                      report_size; /* report */
+
+       ihid->inbuf = kzalloc(report_size, GFP_KERNEL);
+       ihid->argsbuf = kzalloc(args_len, GFP_KERNEL);
+       ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL);
+
+       if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) {
+               i2c_hid_free_buffers(ihid);
+               return -ENOMEM;
+       }
+
+       ihid->bufsize = report_size;
+
+       return 0;
+}
+
+static int i2c_hid_get_raw_report(struct hid_device *hid,
+               unsigned char report_number, __u8 *buf, size_t count,
+               unsigned char report_type)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       size_t ret_count, ask_count;
+       int ret;
+
+       if (report_type == HID_OUTPUT_REPORT)
+               return -EINVAL;
+
+       /* +2 bytes to include the size of the reply in the query buffer */
+       ask_count = min(count + 2, (size_t)ihid->bufsize);
+
+       ret = i2c_hid_get_report(client,
+                       report_type == HID_FEATURE_REPORT ? 0x03 : 0x01,
+                       report_number, ihid->inbuf, ask_count);
+
+       if (ret < 0)
+               return ret;
+
+       ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8);
+
+       if (ret_count <= 2)
+               return 0;
+
+       ret_count = min(ret_count, ask_count);
+
+       /* The query buffer contains the size, dropping it in the reply */
+       count = min(count, ret_count - 2);
+       memcpy(buf, ihid->inbuf + 2, count);
+
+       return count;
+}
+
+static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
+               size_t count, unsigned char report_type)
+{
+       struct i2c_client *client = hid->driver_data;
+       int report_id = buf[0];
+
+       if (report_type == HID_INPUT_REPORT)
+               return -EINVAL;
+
+       return i2c_hid_set_report(client,
+                               report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
+                               report_id, buf, count);
+}
+
+static int i2c_hid_parse(struct hid_device *hid)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       struct i2c_hid_desc *hdesc = &ihid->hdesc;
+       unsigned int rsize;
+       char *rdesc;
+       int ret;
+       int tries = 3;
+
+       i2c_hid_dbg(ihid, "entering %s\n", __func__);
+
+       rsize = le16_to_cpu(hdesc->wReportDescLength);
+       if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
+               dbg_hid("weird size of report descriptor (%u)\n", rsize);
+               return -EINVAL;
+       }
+
+       do {
+               ret = i2c_hid_hwreset(client);
+               if (ret)
+                       msleep(1000);
+       } while (tries-- > 0 && ret);
+
+       if (ret)
+               return ret;
+
+       rdesc = kzalloc(rsize, GFP_KERNEL);
+
+       if (!rdesc) {
+               dbg_hid("couldn't allocate rdesc memory\n");
+               return -ENOMEM;
+       }
+
+       i2c_hid_dbg(ihid, "asking HID report descriptor\n");
+
+       ret = i2c_hid_command(client, &hid_report_descr_cmd, rdesc, rsize);
+       if (ret) {
+               hid_err(hid, "reading report descriptor failed\n");
+               kfree(rdesc);
+               return -EIO;
+       }
+
+       i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
+
+       ret = hid_parse_report(hid, rdesc, rsize);
+       kfree(rdesc);
+       if (ret) {
+               dbg_hid("parsing report descriptor failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int i2c_hid_start(struct hid_device *hid)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       int ret;
+       unsigned int bufsize = HID_MIN_BUFFER_SIZE;
+
+       i2c_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize);
+       i2c_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize);
+       i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize);
+
+       if (bufsize > ihid->bufsize) {
+               i2c_hid_free_buffers(ihid);
+
+               ret = i2c_hid_alloc_buffers(ihid, bufsize);
+
+               if (ret)
+                       return ret;
+       }
+
+       if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
+               i2c_hid_init_reports(hid);
+
+       return 0;
+}
+
+static void i2c_hid_stop(struct hid_device *hid)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+       hid->claimed = 0;
+
+       i2c_hid_free_buffers(ihid);
+}
+
+static int i2c_hid_open(struct hid_device *hid)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       int ret = 0;
+
+       mutex_lock(&i2c_hid_open_mut);
+       if (!hid->open++) {
+               ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+               if (ret) {
+                       hid->open--;
+                       goto done;
+               }
+               set_bit(I2C_HID_STARTED, &ihid->flags);
+       }
+done:
+       mutex_unlock(&i2c_hid_open_mut);
+       return ret;
+}
+
+static void i2c_hid_close(struct hid_device *hid)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+       /* protecting hid->open to make sure we don't restart
+        * data acquistion due to a resumption we no longer
+        * care about
+        */
+       mutex_lock(&i2c_hid_open_mut);
+       if (!--hid->open) {
+               clear_bit(I2C_HID_STARTED, &ihid->flags);
+
+               /* Save some power */
+               i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+       }
+       mutex_unlock(&i2c_hid_open_mut);
+}
+
+static int i2c_hid_power(struct hid_device *hid, int lvl)
+{
+       struct i2c_client *client = hid->driver_data;
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       int ret = 0;
+
+       i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
+
+       switch (lvl) {
+       case PM_HINT_FULLON:
+               ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+               break;
+       case PM_HINT_NORMAL:
+               ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               break;
+       }
+       return ret;
+}
+
+static int i2c_hid_hidinput_input_event(struct input_dev *dev,
+               unsigned int type, unsigned int code, int value)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct hid_field *field;
+       int offset;
+
+       if (type == EV_FF)
+               return input_ff_event(dev, type, code, value);
+
+       if (type != EV_LED)
+               return -1;
+
+       offset = hidinput_find_field(hid, type, code, &field);
+
+       if (offset == -1) {
+               hid_warn(dev, "event field not found\n");
+               return -1;
+       }
+
+       return hid_set_field(field, offset, value);
+}
+
+static struct hid_ll_driver i2c_hid_ll_driver = {
+       .parse = i2c_hid_parse,
+       .start = i2c_hid_start,
+       .stop = i2c_hid_stop,
+       .open = i2c_hid_open,
+       .close = i2c_hid_close,
+       .power = i2c_hid_power,
+       .hidinput_input_event = i2c_hid_hidinput_input_event,
+};
+
+static int __devinit i2c_hid_init_irq(struct i2c_client *client)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       int ret;
+
+       dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq);
+
+       ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq,
+                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                       client->name, ihid);
+       if (ret < 0) {
+               dev_warn(&client->dev,
+                       "Could not register for %s interrupt, irq = %d,"
+                       " ret = %d\n",
+                       client->name, client->irq, ret);
+
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devinit i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
+{
+       struct i2c_client *client = ihid->client;
+       struct i2c_hid_desc *hdesc = &ihid->hdesc;
+       unsigned int dsize;
+       int ret;
+
+       /* Fetch the length of HID description, retrieve the 4 first bytes:
+        * bytes 0-1 -> length
+        * bytes 2-3 -> bcdVersion (has to be 1.00) */
+       ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
+
+       i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n",
+                       __func__, 4, ihid->hdesc_buffer);
+
+       if (ret) {
+               dev_err(&client->dev,
+                       "unable to fetch the size of HID descriptor (ret=%d)\n",
+                       ret);
+               return -ENODEV;
+       }
+
+       dsize = le16_to_cpu(hdesc->wHIDDescLength);
+       /*
+        * the size of the HID descriptor should at least contain
+        * its size and the bcdVersion (4 bytes), and should not be greater
+        * than sizeof(struct i2c_hid_desc) as we directly fill this struct
+        * through i2c_hid_command.
+        */
+       if (dsize < 4 || dsize > sizeof(struct i2c_hid_desc)) {
+               dev_err(&client->dev, "weird size of HID descriptor (%u)\n",
+                       dsize);
+               return -ENODEV;
+       }
+
+       /* check bcdVersion == 1.0 */
+       if (le16_to_cpu(hdesc->bcdVersion) != 0x0100) {
+               dev_err(&client->dev,
+                       "unexpected HID descriptor bcdVersion (0x%04hx)\n",
+                       le16_to_cpu(hdesc->bcdVersion));
+               return -ENODEV;
+       }
+
+       i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
+
+       ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
+                               dsize);
+       if (ret) {
+               dev_err(&client->dev, "hid_descr_cmd Fail\n");
+               return -ENODEV;
+       }
+
+       i2c_hid_dbg(ihid, "HID Descriptor: %*ph\n", dsize, ihid->hdesc_buffer);
+
+       return 0;
+}
+
+static int __devinit i2c_hid_probe(struct i2c_client *client,
+               const struct i2c_device_id *dev_id)
+{
+       int ret;
+       struct i2c_hid *ihid;
+       struct hid_device *hid;
+       __u16 hidRegister;
+       struct i2c_hid_platform_data *platform_data = client->dev.platform_data;
+
+       dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
+
+       if (!platform_data) {
+               dev_err(&client->dev, "HID register address not provided\n");
+               return -EINVAL;
+       }
+
+       if (!client->irq) {
+               dev_err(&client->dev,
+                       "HID over i2c has not been provided an Int IRQ\n");
+               return -EINVAL;
+       }
+
+       ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
+       if (!ihid)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, ihid);
+
+       ihid->client = client;
+
+       hidRegister = platform_data->hid_descriptor_address;
+       ihid->wHIDDescRegister = cpu_to_le16(hidRegister);
+
+       init_waitqueue_head(&ihid->wait);
+
+       /* we need to allocate the command buffer without knowing the maximum
+        * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the
+        * real computation later. */
+       ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE);
+       if (ret < 0)
+               goto err;
+
+       ret = i2c_hid_fetch_hid_descriptor(ihid);
+       if (ret < 0)
+               goto err;
+
+       ret = i2c_hid_init_irq(client);
+       if (ret < 0)
+               goto err;
+
+       hid = hid_allocate_device();
+       if (IS_ERR(hid)) {
+               ret = PTR_ERR(hid);
+               goto err_irq;
+       }
+
+       ihid->hid = hid;
+
+       hid->driver_data = client;
+       hid->ll_driver = &i2c_hid_ll_driver;
+       hid->hid_get_raw_report = i2c_hid_get_raw_report;
+       hid->hid_output_raw_report = i2c_hid_output_raw_report;
+       hid->dev.parent = &client->dev;
+       hid->bus = BUS_I2C;
+       hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
+       hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
+       hid->product = le16_to_cpu(ihid->hdesc.wProductID);
+
+       snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
+                client->name, hid->vendor, hid->product);
+
+       ret = hid_add_device(hid);
+       if (ret) {
+               if (ret != -ENODEV)
+                       hid_err(client, "can't add hid device: %d\n", ret);
+               goto err_mem_free;
+       }
+
+       return 0;
+
+err_mem_free:
+       hid_destroy_device(hid);
+
+err_irq:
+       free_irq(client->irq, ihid);
+
+err:
+       i2c_hid_free_buffers(ihid);
+       kfree(ihid);
+       return ret;
+}
+
+static int __devexit i2c_hid_remove(struct i2c_client *client)
+{
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
+       struct hid_device *hid;
+
+       hid = ihid->hid;
+       hid_destroy_device(hid);
+
+       free_irq(client->irq, ihid);
+
+       if (ihid->bufsize)
+               i2c_hid_free_buffers(ihid);
+
+       kfree(ihid);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int i2c_hid_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       if (device_may_wakeup(&client->dev))
+               enable_irq_wake(client->irq);
+
+       /* Save some power */
+       i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+
+       return 0;
+}
+
+static int i2c_hid_resume(struct device *dev)
+{
+       int ret;
+       struct i2c_client *client = to_i2c_client(dev);
+
+       ret = i2c_hid_hwreset(client);
+       if (ret)
+               return ret;
+
+       if (device_may_wakeup(&client->dev))
+               disable_irq_wake(client->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume);
+
+static const struct i2c_device_id i2c_hid_id_table[] = {
+       { "hid", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table);
+
+
+static struct i2c_driver i2c_hid_driver = {
+       .driver = {
+               .name   = "i2c_hid",
+               .owner  = THIS_MODULE,
+               .pm     = &i2c_hid_pm,
+       },
+
+       .probe          = i2c_hid_probe,
+       .remove         = __devexit_p(i2c_hid_remove),
+
+       .id_table       = i2c_hid_id_table,
+};
+
+module_i2c_driver(i2c_hid_driver);
+
+MODULE_DESCRIPTION("HID over I2C core driver");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
+MODULE_LICENSE("GPL");
index 11c7932dc7e6c5628f940d141b50366ca57008ad..ac9e35228254f0e6a942845520bb542752ca0921 100644 (file)
@@ -72,6 +72,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
@@ -79,9 +80,11 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
index 14599e25679181cc00223675a7d4170cdff70174..87bd64959a91b4bed5e3745751e237f78ac4470a 100644 (file)
@@ -361,10 +361,6 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
                        prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
 
                        while (list->head == list->tail) {
-                               if (file->f_flags & O_NONBLOCK) {
-                                       retval = -EAGAIN;
-                                       break;
-                               }
                                if (signal_pending(current)) {
                                        retval = -ERESTARTSYS;
                                        break;
@@ -373,6 +369,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
                                        retval = -EIO;
                                        break;
                                }
+                               if (file->f_flags & O_NONBLOCK) {
+                                       retval = -EAGAIN;
+                                       break;
+                               }
 
                                /* let O_NONBLOCK tasks run */
                                mutex_unlock(&list->thread_lock);
@@ -625,7 +625,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                break;
 
        case HIDIOCAPPLICATION:
-               if (arg < 0 || arg >= hid->maxapplication)
+               if (arg >= hid->maxapplication)
                        break;
 
                for (i = 0; i < hid->maxcollection; i++)
index f41502ef3f55086db9f87610b95d2acb07d72434..a23b91b0b7383829d7d6427f93e4e6dccace5069 100644 (file)
@@ -304,7 +304,7 @@ retry_write:
 
        case STATE_READ:
                /* we have a byte of data in the data register, do
-                * something with it, and then work out wether we are
+                * something with it, and then work out whether we are
                 * going to do any more read/write
                 */
 
index 9d902725bac94f28c91aa26ec57615988cd96e77..b33d95ebc890aa9667d64f01a66fb961244fbe88 100644 (file)
@@ -208,7 +208,7 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
        if (msg->flags & I2C_M_REV_DIR_ADDR)
                addr ^= 1;
 
-       /* todo - check for wether ack wanted or not */
+       /* todo - check for whether ack wanted or not */
        s3c24xx_i2c_enable_ack(i2c);
 
        iiccon = readl(i2c->regs + S3C2410_IICCON);
@@ -397,7 +397,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
 
        case STATE_READ:
                /* we have a byte of data in the data register, do
-                * something with it, and then work out wether we are
+                * something with it, and then work out whether we are
                 * going to do any more read/write
                 */
 
index a7568c34a1aa624c505f2a7a8d0235e9f2ccd21f..d789eea32168788439e378edcdc33d75c4ce693f 100644 (file)
@@ -345,17 +345,17 @@ static int find_gid_port(struct ib_device *device, union ib_gid *gid, u8 port_nu
 
        err = ib_query_port(device, port_num, &props);
        if (err)
-               return 1;
+               return err;
 
        for (i = 0; i < props.gid_tbl_len; ++i) {
                err = ib_query_gid(device, port_num, i, &tmp);
                if (err)
-                       return 1;
+                       return err;
                if (!memcmp(&tmp, gid, sizeof tmp))
                        return 0;
        }
 
-       return -EAGAIN;
+       return -EADDRNOTAVAIL;
 }
 
 static int cma_acquire_dev(struct rdma_id_private *id_priv)
@@ -388,8 +388,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
                                if (!ret) {
                                        id_priv->id.port_num = port;
                                        goto out;
-                               } else if (ret == 1)
-                                       break;
+                               }
                        }
                }
        }
index 32d34e88d5cf70a99f5bfa717ad4b47c76b53d73..706cf97cbe8f4e963581f322d47b76e1b78739b4 100644 (file)
@@ -311,6 +311,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
                if (cq->ibcq.event_handler)
                        cq->ibcq.event_handler(&ib_event,
                                               cq->ibcq.cq_context);
+               break;
        }
 
        default:
index aaf88ef9409cddfabef4fb90c88347e27887d464..3e094cd6a0e345e1e239c96348e162cc53184fa7 100644 (file)
@@ -128,9 +128,8 @@ static void stop_ep_timer(struct iwch_ep *ep)
 {
        PDBG("%s ep %p\n", __func__, ep);
        if (!timer_pending(&ep->timer)) {
-               printk(KERN_ERR "%s timer stopped when its not running!  ep %p state %u\n",
+               WARN(1, "%s timer stopped when its not running!  ep %p state %u\n",
                        __func__, ep, ep->com.state);
-               WARN_ON(1);
                return;
        }
        del_timer_sync(&ep->timer);
@@ -1756,9 +1755,8 @@ static void ep_timeout(unsigned long arg)
                __state_set(&ep->com, ABORTING);
                break;
        default:
-               printk(KERN_ERR "%s unexpected state ep %p state %u\n",
+               WARN(1, "%s unexpected state ep %p state %u\n",
                        __func__, ep, ep->com.state);
-               WARN_ON(1);
                abort = 0;
        }
        spin_unlock_irqrestore(&ep->com.lock, flags);
index 6cfd4d8fd0bd8e240dd1311698a2cf603fcfed15..5de86968379d265e1c1046b6742efb6c36978328 100644 (file)
@@ -151,9 +151,8 @@ static void stop_ep_timer(struct c4iw_ep *ep)
 {
        PDBG("%s ep %p\n", __func__, ep);
        if (!timer_pending(&ep->timer)) {
-               printk(KERN_ERR "%s timer stopped when its not running! "
+               WARN(1, "%s timer stopped when its not running! "
                       "ep %p state %u\n", __func__, ep, ep->com.state);
-               WARN_ON(1);
                return;
        }
        del_timer_sync(&ep->timer);
@@ -2551,9 +2550,8 @@ static void process_timeout(struct c4iw_ep *ep)
                __state_set(&ep->com, ABORTING);
                break;
        default:
-               printk(KERN_ERR "%s unexpected state ep %p tid %u state %u\n",
+               WARN(1, "%s unexpected state ep %p tid %u state %u\n",
                        __func__, ep, ep->hwtid, ep->com.state);
-               WARN_ON(1);
                abort = 0;
        }
        mutex_unlock(&ep->com.mutex);
index 49b09c697c7c8462800a9737dc6de591879dd5a2..be2a60e142b00b0e9af8e2eed5172700d731fbf2 100644 (file)
@@ -718,16 +718,6 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
        if (ret)
                goto done;
 
-       /*
-        * we ignore most issues after reporting them, but have to specially
-        * handle hardware-disabled chips.
-        */
-       if (ret == 2) {
-               /* unique error, known to ipath_init_one */
-               ret = -EPERM;
-               goto done;
-       }
-
        /*
         * We could bump this to allow for full rcvegrcnt + rcvtidcnt,
         * but then it no longer nicely fits power of two, and since
index 80079e5a2e30f47da6e781d6d5932cab519571d4..dbc99d41605cf5aeba7c883bec270b053fdea3da 100644 (file)
@@ -268,15 +268,15 @@ static void schedule_delayed(struct ib_device *ibdev, struct id_map_entry *id)
        struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
        unsigned long flags;
 
-       spin_lock_irqsave(&sriov->going_down_lock, flags);
        spin_lock(&sriov->id_map_lock);
+       spin_lock_irqsave(&sriov->going_down_lock, flags);
        /*make sure that there is no schedule inside the scheduled work.*/
        if (!sriov->is_going_down) {
                id->scheduled_delete = 1;
                schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT);
        }
-       spin_unlock(&sriov->id_map_lock);
        spin_unlock_irqrestore(&sriov->going_down_lock, flags);
+       spin_unlock(&sriov->id_map_lock);
 }
 
 int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id,
index c9eb6a6815ce2f14b62b215d226cda91f98ae3cf..ae67df35dd4d6910945bf728fbd3dde8bca587f0 100644 (file)
@@ -66,7 +66,7 @@ static void mlx4_ib_cq_event(struct mlx4_cq *cq, enum mlx4_event type)
 
 static void *get_cqe_from_buf(struct mlx4_ib_cq_buf *buf, int n)
 {
-       return mlx4_buf_offset(&buf->buf, n * sizeof (struct mlx4_cqe));
+       return mlx4_buf_offset(&buf->buf, n * buf->entry_size);
 }
 
 static void *get_cqe(struct mlx4_ib_cq *cq, int n)
@@ -77,8 +77,9 @@ static void *get_cqe(struct mlx4_ib_cq *cq, int n)
 static void *get_sw_cqe(struct mlx4_ib_cq *cq, int n)
 {
        struct mlx4_cqe *cqe = get_cqe(cq, n & cq->ibcq.cqe);
+       struct mlx4_cqe *tcqe = ((cq->buf.entry_size == 64) ? (cqe + 1) : cqe);
 
-       return (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
+       return (!!(tcqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
                !!(n & (cq->ibcq.cqe + 1))) ? NULL : cqe;
 }
 
@@ -99,12 +100,13 @@ static int mlx4_ib_alloc_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *
 {
        int err;
 
-       err = mlx4_buf_alloc(dev->dev, nent * sizeof(struct mlx4_cqe),
+       err = mlx4_buf_alloc(dev->dev, nent * dev->dev->caps.cqe_size,
                             PAGE_SIZE * 2, &buf->buf);
 
        if (err)
                goto out;
 
+       buf->entry_size = dev->dev->caps.cqe_size;
        err = mlx4_mtt_init(dev->dev, buf->buf.npages, buf->buf.page_shift,
                                    &buf->mtt);
        if (err)
@@ -120,8 +122,7 @@ err_mtt:
        mlx4_mtt_cleanup(dev->dev, &buf->mtt);
 
 err_buf:
-       mlx4_buf_free(dev->dev, nent * sizeof(struct mlx4_cqe),
-                             &buf->buf);
+       mlx4_buf_free(dev->dev, nent * buf->entry_size, &buf->buf);
 
 out:
        return err;
@@ -129,7 +130,7 @@ out:
 
 static void mlx4_ib_free_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int cqe)
 {
-       mlx4_buf_free(dev->dev, (cqe + 1) * sizeof(struct mlx4_cqe), &buf->buf);
+       mlx4_buf_free(dev->dev, (cqe + 1) * buf->entry_size, &buf->buf);
 }
 
 static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *context,
@@ -137,8 +138,9 @@ static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *cont
                               u64 buf_addr, int cqe)
 {
        int err;
+       int cqe_size = dev->dev->caps.cqe_size;
 
-       *umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
+       *umem = ib_umem_get(context, buf_addr, cqe * cqe_size,
                            IB_ACCESS_LOCAL_WRITE, 1);
        if (IS_ERR(*umem))
                return PTR_ERR(*umem);
@@ -331,16 +333,23 @@ static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq)
 {
        struct mlx4_cqe *cqe, *new_cqe;
        int i;
+       int cqe_size = cq->buf.entry_size;
+       int cqe_inc = cqe_size == 64 ? 1 : 0;
 
        i = cq->mcq.cons_index;
        cqe = get_cqe(cq, i & cq->ibcq.cqe);
+       cqe += cqe_inc;
+
        while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) {
                new_cqe = get_cqe_from_buf(&cq->resize_buf->buf,
                                           (i + 1) & cq->resize_buf->cqe);
-               memcpy(new_cqe, get_cqe(cq, i & cq->ibcq.cqe), sizeof(struct mlx4_cqe));
+               memcpy(new_cqe, get_cqe(cq, i & cq->ibcq.cqe), cqe_size);
+               new_cqe += cqe_inc;
+
                new_cqe->owner_sr_opcode = (cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK) |
                        (((i + 1) & (cq->resize_buf->cqe + 1)) ? MLX4_CQE_OWNER_MASK : 0);
                cqe = get_cqe(cq, ++i & cq->ibcq.cqe);
+               cqe += cqe_inc;
        }
        ++cq->mcq.cons_index;
 }
@@ -438,6 +447,7 @@ err_buf:
 
 out:
        mutex_unlock(&cq->resize_mutex);
+
        return err;
 }
 
@@ -586,6 +596,9 @@ repoll:
        if (!cqe)
                return -EAGAIN;
 
+       if (cq->buf.entry_size == 64)
+               cqe++;
+
        ++cq->mcq.cons_index;
 
        /*
@@ -807,6 +820,7 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
        int nfreed = 0;
        struct mlx4_cqe *cqe, *dest;
        u8 owner_bit;
+       int cqe_inc = cq->buf.entry_size == 64 ? 1 : 0;
 
        /*
         * First we need to find the current producer index, so we
@@ -825,12 +839,16 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
         */
        while ((int) --prod_index - (int) cq->mcq.cons_index >= 0) {
                cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
+               cqe += cqe_inc;
+
                if ((be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_QPN_MASK) == qpn) {
                        if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))
                                mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index));
                        ++nfreed;
                } else if (nfreed) {
                        dest = get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe);
+                       dest += cqe_inc;
+
                        owner_bit = dest->owner_sr_opcode & MLX4_CQE_OWNER_MASK;
                        memcpy(dest, cqe, sizeof *cqe);
                        dest->owner_sr_opcode = owner_bit |
index 718ec6b2bad24e5cbee875834739604d2dd0308d..e7d81c0d1ac59ad94b9172b429a2c186d4ee2b23 100644 (file)
@@ -563,15 +563,24 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev,
 {
        struct mlx4_ib_dev *dev = to_mdev(ibdev);
        struct mlx4_ib_ucontext *context;
+       struct mlx4_ib_alloc_ucontext_resp_v3 resp_v3;
        struct mlx4_ib_alloc_ucontext_resp resp;
        int err;
 
        if (!dev->ib_active)
                return ERR_PTR(-EAGAIN);
 
-       resp.qp_tab_size      = dev->dev->caps.num_qps;
-       resp.bf_reg_size      = dev->dev->caps.bf_reg_size;
-       resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
+       if (ibdev->uverbs_abi_ver == MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION) {
+               resp_v3.qp_tab_size      = dev->dev->caps.num_qps;
+               resp_v3.bf_reg_size      = dev->dev->caps.bf_reg_size;
+               resp_v3.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
+       } else {
+               resp.dev_caps         = dev->dev->caps.userspace_caps;
+               resp.qp_tab_size      = dev->dev->caps.num_qps;
+               resp.bf_reg_size      = dev->dev->caps.bf_reg_size;
+               resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
+               resp.cqe_size         = dev->dev->caps.cqe_size;
+       }
 
        context = kmalloc(sizeof *context, GFP_KERNEL);
        if (!context)
@@ -586,7 +595,11 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev,
        INIT_LIST_HEAD(&context->db_page_list);
        mutex_init(&context->db_page_mutex);
 
-       err = ib_copy_to_udata(udata, &resp, sizeof resp);
+       if (ibdev->uverbs_abi_ver == MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION)
+               err = ib_copy_to_udata(udata, &resp_v3, sizeof(resp_v3));
+       else
+               err = ib_copy_to_udata(udata, &resp, sizeof(resp));
+
        if (err) {
                mlx4_uar_free(to_mdev(ibdev)->dev, &context->uar);
                kfree(context);
@@ -1342,7 +1355,11 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.num_comp_vectors  = dev->caps.num_comp_vectors;
        ibdev->ib_dev.dma_device        = &dev->pdev->dev;
 
-       ibdev->ib_dev.uverbs_abi_ver    = MLX4_IB_UVERBS_ABI_VERSION;
+       if (dev->caps.userspace_caps)
+               ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION;
+       else
+               ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION;
+
        ibdev->ib_dev.uverbs_cmd_mask   =
                (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
                (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
index e04cbc9a54a53ee68863c06f3440bf2be877df7e..dcd845bc30f03e59bb7ddee4143aff2633d1ad25 100644 (file)
@@ -90,6 +90,7 @@ struct mlx4_ib_xrcd {
 struct mlx4_ib_cq_buf {
        struct mlx4_buf         buf;
        struct mlx4_mtt         mtt;
+       int                     entry_size;
 };
 
 struct mlx4_ib_cq_resize {
index 13beedeeef9f7aebfb805b4d405490614c019e76..07e6769ef43bc8fb5b38af0d5c86a712a7ef6638 100644 (file)
@@ -40,7 +40,9 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MLX4_IB_UVERBS_ABI_VERSION     3
+
+#define MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION 3
+#define MLX4_IB_UVERBS_ABI_VERSION             4
 
 /*
  * Make sure that all structs defined in this file remain laid out so
  * instead.
  */
 
+struct mlx4_ib_alloc_ucontext_resp_v3 {
+       __u32   qp_tab_size;
+       __u16   bf_reg_size;
+       __u16   bf_regs_per_page;
+};
+
 struct mlx4_ib_alloc_ucontext_resp {
+       __u32   dev_caps;
        __u32   qp_tab_size;
        __u16   bf_reg_size;
        __u16   bf_regs_per_page;
+       __u32   cqe_size;
 };
 
 struct mlx4_ib_alloc_pd_resp {
index 5cac29e6bc1c73b50dc5fdb113cf5d377a64fbb8..33cc58941a3ea32923b3d6ecfbe3480b617e308d 100644 (file)
@@ -532,6 +532,7 @@ void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *);
 int nes_destroy_cqp(struct nes_device *);
 int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
 void nes_recheck_link_status(struct work_struct *work);
+void nes_terminate_timeout(unsigned long context);
 
 /* nes_nic.c */
 struct net_device *nes_netdev_init(struct nes_device *, void __iomem *);
index cfaacaf6bf5f9c8e11ce0bb5c0dce62c54e15ae4..22ea67eea5dceb7dfc9ccc136efef805273fe4c2 100644 (file)
@@ -629,11 +629,9 @@ static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_a
 
        case SEND_RDMA_READ_ZERO:
        default:
-               if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
-                       printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
-                                __func__, __LINE__, cm_node->send_rdma0_op);
-                       WARN_ON(1);
-               }
+               if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO)
+                       WARN(1, "Unsupported RDMA0 len operation=%u\n",
+                            cm_node->send_rdma0_op);
                nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
                wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
                        cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
@@ -671,7 +669,6 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
        struct nes_cm_core *cm_core = cm_node->cm_core;
        struct nes_timer_entry *new_send;
        int ret = 0;
-       u32 was_timer_set;
 
        new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);
        if (!new_send)
@@ -723,12 +720,8 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
                }
        }
 
-       was_timer_set = timer_pending(&cm_core->tcp_timer);
-
-       if (!was_timer_set) {
-               cm_core->tcp_timer.expires = new_send->timetosend;
-               add_timer(&cm_core->tcp_timer);
-       }
+       if (!timer_pending(&cm_core->tcp_timer))
+               mod_timer(&cm_core->tcp_timer, new_send->timetosend);
 
        return ret;
 }
@@ -946,10 +939,8 @@ static void nes_cm_timer_tick(unsigned long pass)
        }
 
        if (settimer) {
-               if (!timer_pending(&cm_core->tcp_timer)) {
-                       cm_core->tcp_timer.expires = nexttimeout;
-                       add_timer(&cm_core->tcp_timer);
-               }
+               if (!timer_pending(&cm_core->tcp_timer))
+                       mod_timer(&cm_core->tcp_timer, nexttimeout);
        }
 }
 
@@ -1314,8 +1305,6 @@ static int mini_cm_del_listen(struct nes_cm_core *cm_core,
 static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
                                      struct nes_cm_node *cm_node)
 {
-       u32 was_timer_set;
-
        cm_node->accelerated = 1;
 
        if (cm_node->accept_pend) {
@@ -1325,11 +1314,8 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
                BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
        }
 
-       was_timer_set = timer_pending(&cm_core->tcp_timer);
-       if (!was_timer_set) {
-               cm_core->tcp_timer.expires = jiffies + NES_SHORT_TIME;
-               add_timer(&cm_core->tcp_timer);
-       }
+       if (!timer_pending(&cm_core->tcp_timer))
+               mod_timer(&cm_core->tcp_timer, (jiffies + NES_SHORT_TIME));
 
        return 0;
 }
index fe7965ee40968fa2cedba5e77a774ae348fcf02d..67647e264611ecc7d6f7e54b602683d93ed3bd5c 100644 (file)
@@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 static void process_critical_error(struct nes_device *nesdev);
 static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
 static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
-static void nes_terminate_timeout(unsigned long context);
 static void nes_terminate_start_timer(struct nes_qp *nesqp);
 
 #ifdef CONFIG_INFINIBAND_NES_DEBUG
@@ -3520,7 +3519,7 @@ static void nes_terminate_received(struct nes_device *nesdev,
 }
 
 /* Timeout routine in case terminate fails to complete */
-static void nes_terminate_timeout(unsigned long context)
+void nes_terminate_timeout(unsigned long context)
 {
        struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context;
 
@@ -3530,11 +3529,7 @@ static void nes_terminate_timeout(unsigned long context)
 /* Set a timer in case hw cannot complete the terminate sequence */
 static void nes_terminate_start_timer(struct nes_qp *nesqp)
 {
-       init_timer(&nesqp->terminate_timer);
-       nesqp->terminate_timer.function = nes_terminate_timeout;
-       nesqp->terminate_timer.expires = jiffies + HZ;
-       nesqp->terminate_timer.data = (unsigned long)nesqp;
-       add_timer(&nesqp->terminate_timer);
+       mod_timer(&nesqp->terminate_timer, (jiffies + HZ));
 }
 
 /**
index 3ba7be36945207bce1448d2edb24cab2783bfa88..416645259b0f84b6a444596e7c8acc85189d6c84 100644 (file)
@@ -210,6 +210,9 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp
        }
 
        while (1) {
+               if (skb_queue_empty(&nesqp->pau_list))
+                       goto out;
+
                seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
                if (seq == nextseq) {
                        if (skb->len || processacks)
@@ -218,14 +221,13 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp
                        goto out;
                }
 
-               if (skb->next == (struct sk_buff *)&nesqp->pau_list)
-                       goto out;
-
                old_skb = skb;
                skb = skb->next;
                skb_unlink(old_skb, &nesqp->pau_list);
                nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
                nes_rem_ref_cm_node(nesqp->cm_node);
+               if (skb == (struct sk_buff *)&nesqp->pau_list)
+                       goto out;
        }
        return skb;
 
@@ -245,7 +247,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
        struct nes_rskb_cb *cb;
        struct pau_fpdu_info *fpdu_info = NULL;
        struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
-       unsigned long flags;
        u32 fpdu_len = 0;
        u32 tmp_len;
        int frag_cnt = 0;
@@ -260,12 +261,10 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 
        *pau_fpdu_info = NULL;
 
-       spin_lock_irqsave(&nesqp->pau_lock, flags);
        skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
-       if (!skb) {
-               spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+       if (!skb)
                goto out;
-       }
+
        cb = (struct nes_rskb_cb *)&skb->cb[0];
        if (skb->len) {
                fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
@@ -290,10 +289,9 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 
                        skb = nes_get_next_skb(nesdev, nesqp, skb,
                                               nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
-                       if (!skb) {
-                               spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+                       if (!skb)
                                goto out;
-                       } else if (rst_rcvd) {
+                       if (rst_rcvd) {
                                /* rst received in the middle of fpdu */
                                for (; i >= 0; i--) {
                                        skb_unlink(frags[i].skb, &nesqp->pau_list);
@@ -320,8 +318,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
                frag_cnt = 1;
        }
 
-       spin_unlock_irqrestore(&nesqp->pau_lock, flags);
-
        /* Found one */
        fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
        if (fpdu_info == NULL) {
@@ -383,9 +379,8 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 
                if (frags[i].skb->len == 0) {
                        /* Pull skb off the list - it will be freed in the callback */
-                       spin_lock_irqsave(&nesqp->pau_lock, flags);
-                       skb_unlink(frags[i].skb, &nesqp->pau_list);
-                       spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+                       if (!skb_queue_empty(&nesqp->pau_list))
+                               skb_unlink(frags[i].skb, &nesqp->pau_list);
                } else {
                        /* Last skb still has data so update the seq */
                        iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
@@ -414,14 +409,18 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
        struct pau_fpdu_info *fpdu_info;
        struct nes_hw_cqp_wqe *cqp_wqe;
        struct nes_cqp_request *cqp_request;
+       unsigned long flags;
        u64 u64tmp;
        u32 u32tmp;
        int rc;
 
        while (1) {
+               spin_lock_irqsave(&nesqp->pau_lock, flags);
                rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
-               if (fpdu_info == NULL)
+               if (rc || (fpdu_info == NULL)) {
+                       spin_unlock_irqrestore(&nesqp->pau_lock, flags);
                        return rc;
+               }
 
                cqp_request = fpdu_info->cqp_request;
                cqp_wqe = &cqp_request->cqp_wqe;
@@ -447,7 +446,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
                set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
                                    lower_32_bits(u64tmp));
                set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
-                                   upper_32_bits(u64tmp >> 32));
+                                   upper_32_bits(u64tmp));
 
                set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
                                    lower_32_bits(fpdu_info->frags[0].physaddr));
@@ -475,6 +474,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
 
                atomic_set(&cqp_request->refcount, 1);
                nes_post_cqp_request(nesdev, cqp_request);
+               spin_unlock_irqrestore(&nesqp->pau_lock, flags);
        }
 
        return 0;
@@ -649,11 +649,9 @@ static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request
        nesqp = qh_chg->nesqp;
 
        /* Should we handle the bad completion */
-       if (cqp_request->major_code) {
-               printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n",
+       if (cqp_request->major_code)
+               WARN(1, PFX "Invalid cqp_request major_code=0x%x\n",
                       cqp_request->major_code);
-               WARN_ON(1);
-       }
 
        switch (nesqp->pau_state) {
        case PAU_DEL_QH:
index 0564be757d82740842ca6e6582f8eeead8bf1d9a..9542e1644a5c1beff7559da4096d734912193209 100644 (file)
@@ -944,12 +944,13 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
                                          addr,
                                          perfect_filter_register_address+(mc_index * 8),
                                          mc_nic_index);
-                               macaddr_high  = ((u16) addr[0]) << 8;
-                               macaddr_high += (u16) addr[1];
-                               macaddr_low   = ((u32) addr[2]) << 24;
-                               macaddr_low  += ((u32) addr[3]) << 16;
-                               macaddr_low  += ((u32) addr[4]) << 8;
-                               macaddr_low  += (u32) addr[5];
+                               macaddr_high  = ((u8) addr[0]) << 8;
+                               macaddr_high += (u8) addr[1];
+                               macaddr_low   = ((u8) addr[2]) << 24;
+                               macaddr_low  += ((u8) addr[3]) << 16;
+                               macaddr_low  += ((u8) addr[4]) << 8;
+                               macaddr_low  += (u8) addr[5];
+
                                nes_write_indexed(nesdev,
                                                perfect_filter_register_address+(mc_index * 8),
                                                macaddr_low);
index cd0ecb215cca01c5be942da3bf4c07bcc3895c5f..07e4fbad987ab66f2d1a80af52e6c76dfb315910 100644 (file)
@@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
        }
 
        nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR);
+       init_timer(&nesqp->terminate_timer);
+       nesqp->terminate_timer.function = nes_terminate_timeout;
+       nesqp->terminate_timer.data = (unsigned long)nesqp;
 
        /* update the QP table */
        nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;
@@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
        return &nesqp->ibqp;
 }
 
-
 /**
  * nes_clean_cq
  */
@@ -2559,6 +2561,11 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
                        return ibmr;
                case IWNES_MEMREG_TYPE_QP:
                case IWNES_MEMREG_TYPE_CQ:
+                       if (!region->length) {
+                               nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n");
+                               ib_umem_release(region);
+                               return ERR_PTR(-EINVAL);
+                       }
                        nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL);
                        if (!nespbl) {
                                nes_debug(NES_DBG_MR, "Unable to allocate PBL\n");
index 922d845f76b0a25b0090d581efeef35578fdd868..d5088ce78290ac41c867df9e667131d47af734aa 100644 (file)
@@ -222,27 +222,29 @@ static int srp_new_cm_id(struct srp_target_port *target)
 static int srp_create_target_ib(struct srp_target_port *target)
 {
        struct ib_qp_init_attr *init_attr;
+       struct ib_cq *recv_cq, *send_cq;
+       struct ib_qp *qp;
        int ret;
 
        init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
        if (!init_attr)
                return -ENOMEM;
 
-       target->recv_cq = ib_create_cq(target->srp_host->srp_dev->dev,
-                                      srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0);
-       if (IS_ERR(target->recv_cq)) {
-               ret = PTR_ERR(target->recv_cq);
+       recv_cq = ib_create_cq(target->srp_host->srp_dev->dev,
+                              srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0);
+       if (IS_ERR(recv_cq)) {
+               ret = PTR_ERR(recv_cq);
                goto err;
        }
 
-       target->send_cq = ib_create_cq(target->srp_host->srp_dev->dev,
-                                      srp_send_completion, NULL, target, SRP_SQ_SIZE, 0);
-       if (IS_ERR(target->send_cq)) {
-               ret = PTR_ERR(target->send_cq);
+       send_cq = ib_create_cq(target->srp_host->srp_dev->dev,
+                              srp_send_completion, NULL, target, SRP_SQ_SIZE, 0);
+       if (IS_ERR(send_cq)) {
+               ret = PTR_ERR(send_cq);
                goto err_recv_cq;
        }
 
-       ib_req_notify_cq(target->recv_cq, IB_CQ_NEXT_COMP);
+       ib_req_notify_cq(recv_cq, IB_CQ_NEXT_COMP);
 
        init_attr->event_handler       = srp_qp_event;
        init_attr->cap.max_send_wr     = SRP_SQ_SIZE;
@@ -251,30 +253,41 @@ static int srp_create_target_ib(struct srp_target_port *target)
        init_attr->cap.max_send_sge    = 1;
        init_attr->sq_sig_type         = IB_SIGNAL_ALL_WR;
        init_attr->qp_type             = IB_QPT_RC;
-       init_attr->send_cq             = target->send_cq;
-       init_attr->recv_cq             = target->recv_cq;
+       init_attr->send_cq             = send_cq;
+       init_attr->recv_cq             = recv_cq;
 
-       target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
-       if (IS_ERR(target->qp)) {
-               ret = PTR_ERR(target->qp);
+       qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
                goto err_send_cq;
        }
 
-       ret = srp_init_qp(target, target->qp);
+       ret = srp_init_qp(target, qp);
        if (ret)
                goto err_qp;
 
+       if (target->qp)
+               ib_destroy_qp(target->qp);
+       if (target->recv_cq)
+               ib_destroy_cq(target->recv_cq);
+       if (target->send_cq)
+               ib_destroy_cq(target->send_cq);
+
+       target->qp = qp;
+       target->recv_cq = recv_cq;
+       target->send_cq = send_cq;
+
        kfree(init_attr);
        return 0;
 
 err_qp:
-       ib_destroy_qp(target->qp);
+       ib_destroy_qp(qp);
 
 err_send_cq:
-       ib_destroy_cq(target->send_cq);
+       ib_destroy_cq(send_cq);
 
 err_recv_cq:
-       ib_destroy_cq(target->recv_cq);
+       ib_destroy_cq(recv_cq);
 
 err:
        kfree(init_attr);
@@ -289,6 +302,9 @@ static void srp_free_target_ib(struct srp_target_port *target)
        ib_destroy_cq(target->send_cq);
        ib_destroy_cq(target->recv_cq);
 
+       target->qp = NULL;
+       target->send_cq = target->recv_cq = NULL;
+
        for (i = 0; i < SRP_RQ_SIZE; ++i)
                srp_free_iu(target->srp_host, target->rx_ring[i]);
        for (i = 0; i < SRP_SQ_SIZE; ++i)
@@ -428,34 +444,50 @@ static int srp_send_req(struct srp_target_port *target)
        return status;
 }
 
-static void srp_disconnect_target(struct srp_target_port *target)
+static bool srp_queue_remove_work(struct srp_target_port *target)
 {
-       /* XXX should send SRP_I_LOGOUT request */
+       bool changed = false;
 
-       init_completion(&target->done);
-       if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
-               shost_printk(KERN_DEBUG, target->scsi_host,
-                            PFX "Sending CM DREQ failed\n");
-               return;
+       spin_lock_irq(&target->lock);
+       if (target->state != SRP_TARGET_REMOVED) {
+               target->state = SRP_TARGET_REMOVED;
+               changed = true;
        }
-       wait_for_completion(&target->done);
+       spin_unlock_irq(&target->lock);
+
+       if (changed)
+               queue_work(system_long_wq, &target->remove_work);
+
+       return changed;
 }
 
-static bool srp_change_state(struct srp_target_port *target,
-                           enum srp_target_state old,
-                           enum srp_target_state new)
+static bool srp_change_conn_state(struct srp_target_port *target,
+                                 bool connected)
 {
        bool changed = false;
 
        spin_lock_irq(&target->lock);
-       if (target->state == old) {
-               target->state = new;
+       if (target->connected != connected) {
+               target->connected = connected;
                changed = true;
        }
        spin_unlock_irq(&target->lock);
+
        return changed;
 }
 
+static void srp_disconnect_target(struct srp_target_port *target)
+{
+       if (srp_change_conn_state(target, false)) {
+               /* XXX should send SRP_I_LOGOUT request */
+
+               if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
+                       shost_printk(KERN_DEBUG, target->scsi_host,
+                                    PFX "Sending CM DREQ failed\n");
+               }
+       }
+}
+
 static void srp_free_req_data(struct srp_target_port *target)
 {
        struct ib_device *ibdev = target->srp_host->srp_dev->dev;
@@ -489,32 +521,50 @@ static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
                device_remove_file(&shost->shost_dev, *attr);
 }
 
-static void srp_remove_work(struct work_struct *work)
+static void srp_remove_target(struct srp_target_port *target)
 {
-       struct srp_target_port *target =
-               container_of(work, struct srp_target_port, work);
-
-       if (!srp_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED))
-               return;
-
-       spin_lock(&target->srp_host->target_lock);
-       list_del(&target->list);
-       spin_unlock(&target->srp_host->target_lock);
+       WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
 
        srp_del_scsi_host_attr(target->scsi_host);
        srp_remove_host(target->scsi_host);
        scsi_remove_host(target->scsi_host);
+       srp_disconnect_target(target);
        ib_destroy_cm_id(target->cm_id);
        srp_free_target_ib(target);
        srp_free_req_data(target);
        scsi_host_put(target->scsi_host);
 }
 
+static void srp_remove_work(struct work_struct *work)
+{
+       struct srp_target_port *target =
+               container_of(work, struct srp_target_port, remove_work);
+
+       WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
+
+       spin_lock(&target->srp_host->target_lock);
+       list_del(&target->list);
+       spin_unlock(&target->srp_host->target_lock);
+
+       srp_remove_target(target);
+}
+
+static void srp_rport_delete(struct srp_rport *rport)
+{
+       struct srp_target_port *target = rport->lld_data;
+
+       srp_queue_remove_work(target);
+}
+
 static int srp_connect_target(struct srp_target_port *target)
 {
        int retries = 3;
        int ret;
 
+       WARN_ON_ONCE(target->connected);
+
+       target->qp_in_error = false;
+
        ret = srp_lookup_path(target);
        if (ret)
                return ret;
@@ -534,6 +584,7 @@ static int srp_connect_target(struct srp_target_port *target)
                 */
                switch (target->status) {
                case 0:
+                       srp_change_conn_state(target, true);
                        return 0;
 
                case SRP_PORT_REDIRECT:
@@ -646,13 +697,14 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re
 
 static int srp_reconnect_target(struct srp_target_port *target)
 {
-       struct ib_qp_attr qp_attr;
-       struct ib_wc wc;
+       struct Scsi_Host *shost = target->scsi_host;
        int i, ret;
 
-       if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING))
+       if (target->state != SRP_TARGET_LIVE)
                return -EAGAIN;
 
+       scsi_target_block(&shost->shost_gendev);
+
        srp_disconnect_target(target);
        /*
         * Now get a new local CM ID so that we avoid confusing the
@@ -660,21 +712,11 @@ static int srp_reconnect_target(struct srp_target_port *target)
         */
        ret = srp_new_cm_id(target);
        if (ret)
-               goto err;
+               goto unblock;
 
-       qp_attr.qp_state = IB_QPS_RESET;
-       ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
-       if (ret)
-               goto err;
-
-       ret = srp_init_qp(target, target->qp);
+       ret = srp_create_target_ib(target);
        if (ret)
-               goto err;
-
-       while (ib_poll_cq(target->recv_cq, 1, &wc) > 0)
-               ; /* nothing */
-       while (ib_poll_cq(target->send_cq, 1, &wc) > 0)
-               ; /* nothing */
+               goto unblock;
 
        for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
                struct srp_request *req = &target->req_ring[i];
@@ -686,13 +728,16 @@ static int srp_reconnect_target(struct srp_target_port *target)
        for (i = 0; i < SRP_SQ_SIZE; ++i)
                list_add(&target->tx_ring[i]->list, &target->free_tx);
 
-       target->qp_in_error = 0;
        ret = srp_connect_target(target);
+
+unblock:
+       scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING :
+                           SDEV_TRANSPORT_OFFLINE);
+
        if (ret)
                goto err;
 
-       if (!srp_change_state(target, SRP_TARGET_CONNECTING, SRP_TARGET_LIVE))
-               ret = -EAGAIN;
+       shost_printk(KERN_INFO, target->scsi_host, PFX "reconnect succeeded\n");
 
        return ret;
 
@@ -705,17 +750,8 @@ err:
         * However, we have to defer the real removal because we
         * are in the context of the SCSI error handler now, which
         * will deadlock if we call scsi_remove_host().
-        *
-        * Schedule our work inside the lock to avoid a race with
-        * the flush_scheduled_work() in srp_remove_one().
         */
-       spin_lock_irq(&target->lock);
-       if (target->state == SRP_TARGET_CONNECTING) {
-               target->state = SRP_TARGET_DEAD;
-               INIT_WORK(&target->work, srp_remove_work);
-               queue_work(ib_wq, &target->work);
-       }
-       spin_unlock_irq(&target->lock);
+       srp_queue_remove_work(target);
 
        return ret;
 }
@@ -1262,6 +1298,19 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
                             PFX "Recv failed with error code %d\n", res);
 }
 
+static void srp_handle_qp_err(enum ib_wc_status wc_status,
+                             enum ib_wc_opcode wc_opcode,
+                             struct srp_target_port *target)
+{
+       if (target->connected && !target->qp_in_error) {
+               shost_printk(KERN_ERR, target->scsi_host,
+                            PFX "failed %s status %d\n",
+                            wc_opcode & IB_WC_RECV ? "receive" : "send",
+                            wc_status);
+       }
+       target->qp_in_error = true;
+}
+
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
 {
        struct srp_target_port *target = target_ptr;
@@ -1269,15 +1318,11 @@ static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
 
        ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
        while (ib_poll_cq(cq, 1, &wc) > 0) {
-               if (wc.status) {
-                       shost_printk(KERN_ERR, target->scsi_host,
-                                    PFX "failed receive status %d\n",
-                                    wc.status);
-                       target->qp_in_error = 1;
-                       break;
+               if (likely(wc.status == IB_WC_SUCCESS)) {
+                       srp_handle_recv(target, &wc);
+               } else {
+                       srp_handle_qp_err(wc.status, wc.opcode, target);
                }
-
-               srp_handle_recv(target, &wc);
        }
 }
 
@@ -1288,16 +1333,12 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
        struct srp_iu *iu;
 
        while (ib_poll_cq(cq, 1, &wc) > 0) {
-               if (wc.status) {
-                       shost_printk(KERN_ERR, target->scsi_host,
-                                    PFX "failed send status %d\n",
-                                    wc.status);
-                       target->qp_in_error = 1;
-                       break;
+               if (likely(wc.status == IB_WC_SUCCESS)) {
+                       iu = (struct srp_iu *) (uintptr_t) wc.wr_id;
+                       list_add(&iu->list, &target->free_tx);
+               } else {
+                       srp_handle_qp_err(wc.status, wc.opcode, target);
                }
-
-               iu = (struct srp_iu *) (uintptr_t) wc.wr_id;
-               list_add(&iu->list, &target->free_tx);
        }
 }
 
@@ -1311,16 +1352,6 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
        unsigned long flags;
        int len;
 
-       if (target->state == SRP_TARGET_CONNECTING)
-               goto err;
-
-       if (target->state == SRP_TARGET_DEAD ||
-           target->state == SRP_TARGET_REMOVED) {
-               scmnd->result = DID_BAD_TARGET << 16;
-               scmnd->scsi_done(scmnd);
-               return 0;
-       }
-
        spin_lock_irqsave(&target->lock, flags);
        iu = __srp_get_tx_iu(target, SRP_IU_CMD);
        if (!iu)
@@ -1377,7 +1408,6 @@ err_iu:
 err_unlock:
        spin_unlock_irqrestore(&target->lock, flags);
 
-err:
        return SCSI_MLQUEUE_HOST_BUSY;
 }
 
@@ -1419,6 +1449,33 @@ err:
        return -ENOMEM;
 }
 
+static uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
+{
+       uint64_t T_tr_ns, max_compl_time_ms;
+       uint32_t rq_tmo_jiffies;
+
+       /*
+        * According to section 11.2.4.2 in the IBTA spec (Modify Queue Pair,
+        * table 91), both the QP timeout and the retry count have to be set
+        * for RC QP's during the RTR to RTS transition.
+        */
+       WARN_ON_ONCE((attr_mask & (IB_QP_TIMEOUT | IB_QP_RETRY_CNT)) !=
+                    (IB_QP_TIMEOUT | IB_QP_RETRY_CNT));
+
+       /*
+        * Set target->rq_tmo_jiffies to one second more than the largest time
+        * it can take before an error completion is generated. See also
+        * C9-140..142 in the IBTA spec for more information about how to
+        * convert the QP Local ACK Timeout value to nanoseconds.
+        */
+       T_tr_ns = 4096 * (1ULL << qp_attr->timeout);
+       max_compl_time_ms = qp_attr->retry_cnt * 4 * T_tr_ns;
+       do_div(max_compl_time_ms, NSEC_PER_MSEC);
+       rq_tmo_jiffies = msecs_to_jiffies(max_compl_time_ms + 1000);
+
+       return rq_tmo_jiffies;
+}
+
 static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
                               struct srp_login_rsp *lrsp,
                               struct srp_target_port *target)
@@ -1478,6 +1535,8 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
        if (ret)
                goto error_free;
 
+       target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
+
        ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
        if (ret)
                goto error_free;
@@ -1599,6 +1658,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
        case IB_CM_DREQ_RECEIVED:
                shost_printk(KERN_WARNING, target->scsi_host,
                             PFX "DREQ received - connection closed\n");
+               srp_change_conn_state(target, false);
                if (ib_send_cm_drep(cm_id, NULL, 0))
                        shost_printk(KERN_ERR, target->scsi_host,
                                     PFX "Sending CM DREP failed\n");
@@ -1608,7 +1668,6 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                shost_printk(KERN_ERR, target->scsi_host,
                             PFX "connection closed\n");
 
-               comp = 1;
                target->status = 0;
                break;
 
@@ -1636,10 +1695,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
        struct srp_iu *iu;
        struct srp_tsk_mgmt *tsk_mgmt;
 
-       if (target->state == SRP_TARGET_DEAD ||
-           target->state == SRP_TARGET_REMOVED)
-               return -1;
-
        init_completion(&target->tsk_mgmt_done);
 
        spin_lock_irq(&target->lock);
@@ -1729,6 +1784,21 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
        return ret;
 }
 
+static int srp_slave_configure(struct scsi_device *sdev)
+{
+       struct Scsi_Host *shost = sdev->host;
+       struct srp_target_port *target = host_to_target(shost);
+       struct request_queue *q = sdev->request_queue;
+       unsigned long timeout;
+
+       if (sdev->type == TYPE_DISK) {
+               timeout = max_t(unsigned, 30 * HZ, target->rq_tmo_jiffies);
+               blk_queue_rq_timeout(q, timeout);
+       }
+
+       return 0;
+}
+
 static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
                           char *buf)
 {
@@ -1861,6 +1931,7 @@ static struct scsi_host_template srp_template = {
        .module                         = THIS_MODULE,
        .name                           = "InfiniBand SRP initiator",
        .proc_name                      = DRV_NAME,
+       .slave_configure                = srp_slave_configure,
        .info                           = srp_target_info,
        .queuecommand                   = srp_queuecommand,
        .eh_abort_handler               = srp_abort,
@@ -1894,11 +1965,14 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
                return PTR_ERR(rport);
        }
 
+       rport->lld_data = target;
+
        spin_lock(&host->target_lock);
        list_add_tail(&target->list, &host->target_list);
        spin_unlock(&host->target_lock);
 
        target->state = SRP_TARGET_LIVE;
+       target->connected = false;
 
        scsi_scan_target(&target->scsi_host->shost_gendev,
                         0, target->scsi_id, SCAN_WILD_CARD, 0);
@@ -2188,6 +2262,7 @@ static ssize_t srp_create_target(struct device *dev,
                             sizeof (struct srp_indirect_buf) +
                             target->cmd_sg_cnt * sizeof (struct srp_direct_buf);
 
+       INIT_WORK(&target->remove_work, srp_remove_work);
        spin_lock_init(&target->lock);
        INIT_LIST_HEAD(&target->free_tx);
        INIT_LIST_HEAD(&target->free_reqs);
@@ -2232,7 +2307,6 @@ static ssize_t srp_create_target(struct device *dev,
        if (ret)
                goto err_free_ib;
 
-       target->qp_in_error = 0;
        ret = srp_connect_target(target);
        if (ret) {
                shost_printk(KERN_ERR, target->scsi_host,
@@ -2422,8 +2496,7 @@ static void srp_remove_one(struct ib_device *device)
 {
        struct srp_device *srp_dev;
        struct srp_host *host, *tmp_host;
-       LIST_HEAD(target_list);
-       struct srp_target_port *target, *tmp_target;
+       struct srp_target_port *target;
 
        srp_dev = ib_get_client_data(device, &srp_client);
 
@@ -2436,35 +2509,17 @@ static void srp_remove_one(struct ib_device *device)
                wait_for_completion(&host->released);
 
                /*
-                * Mark all target ports as removed, so we stop queueing
-                * commands and don't try to reconnect.
+                * Remove all target ports.
                 */
                spin_lock(&host->target_lock);
-               list_for_each_entry(target, &host->target_list, list) {
-                       spin_lock_irq(&target->lock);
-                       target->state = SRP_TARGET_REMOVED;
-                       spin_unlock_irq(&target->lock);
-               }
+               list_for_each_entry(target, &host->target_list, list)
+                       srp_queue_remove_work(target);
                spin_unlock(&host->target_lock);
 
                /*
-                * Wait for any reconnection tasks that may have
-                * started before we marked our target ports as
-                * removed, and any target port removal tasks.
+                * Wait for target port removal tasks.
                 */
-               flush_workqueue(ib_wq);
-
-               list_for_each_entry_safe(target, tmp_target,
-                                        &host->target_list, list) {
-                       srp_del_scsi_host_attr(target->scsi_host);
-                       srp_remove_host(target->scsi_host);
-                       scsi_remove_host(target->scsi_host);
-                       srp_disconnect_target(target);
-                       ib_destroy_cm_id(target->cm_id);
-                       srp_free_target_ib(target);
-                       srp_free_req_data(target);
-                       scsi_host_put(target->scsi_host);
-               }
+               flush_workqueue(system_long_wq);
 
                kfree(host);
        }
@@ -2478,6 +2533,7 @@ static void srp_remove_one(struct ib_device *device)
 }
 
 static struct srp_function_template ib_srp_transport_functions = {
+       .rport_delete            = srp_rport_delete,
 };
 
 static int __init srp_init_module(void)
index 020caf0c3789ed0d6bd14fa95708132a3bdb8c94..de2d0b3c0bfe4c976e82844361a7b04ec6e64a7d 100644 (file)
@@ -80,9 +80,7 @@ enum {
 
 enum srp_target_state {
        SRP_TARGET_LIVE,
-       SRP_TARGET_CONNECTING,
-       SRP_TARGET_DEAD,
-       SRP_TARGET_REMOVED
+       SRP_TARGET_REMOVED,
 };
 
 enum srp_iu_type {
@@ -163,6 +161,9 @@ struct srp_target_port {
        struct ib_sa_query     *path_query;
        int                     path_query_id;
 
+       u32                     rq_tmo_jiffies;
+       bool                    connected;
+
        struct ib_cm_id        *cm_id;
 
        int                     max_ti_iu_len;
@@ -173,12 +174,12 @@ struct srp_target_port {
        struct srp_iu          *rx_ring[SRP_RQ_SIZE];
        struct srp_request      req_ring[SRP_CMD_SQ_SIZE];
 
-       struct work_struct      work;
+       struct work_struct      remove_work;
 
        struct list_head        list;
        struct completion       done;
        int                     status;
-       int                     qp_in_error;
+       bool                    qp_in_error;
 
        struct completion       tsk_mgmt_done;
        u8                      tsk_mgmt_status;
index 1abbc170d8b77f302154323a0ea944474bfd5d37..8c4b50fd9a79b59fcb15ce254d6fa835aa9eb4d9 100644 (file)
@@ -251,7 +251,7 @@ void input_mt_sync_frame(struct input_dev *dev)
 
        if (mt->flags & INPUT_MT_DROP_UNUSED) {
                for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
-                       if (s->frame == mt->frame)
+                       if (input_mt_is_used(mt, s))
                                continue;
                        input_mt_slot(dev, s - mt->slots);
                        input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
index 7c0f1ecfdd7a3ff88fed02671e1cf0fba5847b24..104a7c3153c0c4ce5fd695403bfb8a263da992d7 100644 (file)
@@ -72,6 +72,16 @@ config INPUT_AD714X_SPI
          To compile this driver as a module, choose M here: the
          module will be called ad714x-spi.
 
+config INPUT_ARIZONA_HAPTICS
+       tristate "Arizona haptics support"
+       depends on MFD_ARIZONA && SND_SOC
+       select INPUT_FF_MEMLESS
+       help
+         Say Y to enable support for the haptics module in Arizona CODECs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called arizona-haptics.
+
 config INPUT_BMA150
        tristate "BMA150/SMB380 acceleration sensor support"
        depends on I2C
index 83fe6f5b77d120e9b3194325f0fc83879a474a0a..5ea769eda999ff1fa35954bdc6bf467c22ebbf99 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X)           += adxl34x.o
 obj-$(CONFIG_INPUT_ADXL34X_I2C)                += adxl34x-i2c.o
 obj-$(CONFIG_INPUT_ADXL34X_SPI)                += adxl34x-spi.o
 obj-$(CONFIG_INPUT_APANEL)             += apanel.o
+obj-$(CONFIG_INPUT_ARIZONA_HAPTICS)    += arizona-haptics.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)                += ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)         += atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)                += bfin_rotary.o
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
new file mode 100644 (file)
index 0000000..7a04f54
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Arizona haptics driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_haptics {
+       struct arizona *arizona;
+       struct input_dev *input_dev;
+       struct work_struct work;
+
+       struct mutex mutex;
+       u8 intensity;
+};
+
+static void arizona_haptics_work(struct work_struct *work)
+{
+       struct arizona_haptics *haptics = container_of(work,
+                                                      struct arizona_haptics,
+                                                      work);
+       struct arizona *arizona = haptics->arizona;
+       struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
+       int ret;
+
+       if (!haptics->arizona->dapm) {
+               dev_err(arizona->dev, "No DAPM context\n");
+               return;
+       }
+
+       if (haptics->intensity) {
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_PHASE_2_INTENSITY,
+                                        ARIZONA_PHASE2_INTENSITY_MASK,
+                                        haptics->intensity);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to set intensity: %d\n",
+                               ret);
+                       return;
+               }
+
+               /* This enable sequence will be a noop if already enabled */
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_CONTROL_1,
+                                        ARIZONA_HAP_CTRL_MASK,
+                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to start haptics: %d\n",
+                               ret);
+                       return;
+               }
+
+               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+               ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               ret = snd_soc_dapm_sync(arizona->dapm);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               mutex_unlock(dapm_mutex);
+
+       } else {
+               /* This disable sequence will be a noop if already enabled */
+               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+               ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               ret = snd_soc_dapm_sync(arizona->dapm);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               mutex_unlock(dapm_mutex);
+
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_CONTROL_1,
+                                        ARIZONA_HAP_CTRL_MASK,
+                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to stop haptics: %d\n",
+                               ret);
+                       return;
+               }
+       }
+}
+
+static int arizona_haptics_play(struct input_dev *input, void *data,
+                               struct ff_effect *effect)
+{
+       struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct arizona *arizona = haptics->arizona;
+
+       if (!arizona->dapm) {
+               dev_err(arizona->dev, "No DAPM context\n");
+               return -EBUSY;
+       }
+
+       if (effect->u.rumble.strong_magnitude) {
+               /* Scale the magnitude into the range the device supports */
+               if (arizona->pdata.hap_act) {
+                       haptics->intensity =
+                               effect->u.rumble.strong_magnitude >> 9;
+                       if (effect->direction < 0x8000)
+                               haptics->intensity += 0x7f;
+               } else {
+                       haptics->intensity =
+                               effect->u.rumble.strong_magnitude >> 8;
+               }
+       } else {
+               haptics->intensity = 0;
+       }
+
+       schedule_work(&haptics->work);
+
+       return 0;
+}
+
+static void arizona_haptics_close(struct input_dev *input)
+{
+       struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
+
+       cancel_work_sync(&haptics->work);
+
+       mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       if (haptics->arizona->dapm)
+               snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+
+       mutex_unlock(dapm_mutex);
+}
+
+static int arizona_haptics_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct arizona_haptics *haptics;
+       int ret;
+
+       haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
+       if (!haptics)
+               return -ENOMEM;
+
+       haptics->arizona = arizona;
+
+       ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
+                                ARIZONA_HAP_ACT, arizona->pdata.hap_act);
+       if (ret != 0) {
+               dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
+                       ret);
+               return ret;
+       }
+
+       INIT_WORK(&haptics->work, arizona_haptics_work);
+
+       haptics->input_dev = input_allocate_device();
+       if (haptics->input_dev == NULL) {
+               dev_err(arizona->dev, "Failed to allocate input device\n");
+               return -ENOMEM;
+       }
+
+       input_set_drvdata(haptics->input_dev, haptics);
+
+       haptics->input_dev->name = "arizona:haptics";
+       haptics->input_dev->dev.parent = pdev->dev.parent;
+       haptics->input_dev->close = arizona_haptics_close;
+       __set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
+
+       ret = input_ff_create_memless(haptics->input_dev, NULL,
+                                     arizona_haptics_play);
+       if (ret < 0) {
+               dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
+                       ret);
+               goto err_ialloc;
+       }
+
+       ret = input_register_device(haptics->input_dev);
+       if (ret < 0) {
+               dev_err(arizona->dev, "couldn't register input device: %d\n",
+                       ret);
+               goto err_iff;
+       }
+
+       platform_set_drvdata(pdev, haptics);
+
+       return 0;
+
+err_iff:
+       if (haptics->input_dev)
+               input_ff_destroy(haptics->input_dev);
+err_ialloc:
+       input_free_device(haptics->input_dev);
+
+       return ret;
+}
+
+static int arizona_haptics_remove(struct platform_device *pdev)
+{
+       struct arizona_haptics *haptics = platform_get_drvdata(pdev);
+
+       input_unregister_device(haptics->input_dev);
+
+       return 0;
+}
+
+static struct platform_driver arizona_haptics_driver = {
+       .probe          = arizona_haptics_probe,
+       .remove         = arizona_haptics_remove,
+       .driver         = {
+               .name   = "arizona-haptics",
+               .owner  = THIS_MODULE,
+       },
+};
+module_platform_driver(arizona_haptics_driver);
+
+MODULE_ALIAS("platform:arizona-haptics");
+MODULE_DESCRIPTION("Arizona haptics driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index 02bd37a6187fe679dae49f8afe0fe1f7ea44e37d..bf4609a5bd9d527c582f839127f5bad899f04cea 100644 (file)
@@ -1,3 +1,4 @@
-obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
-obj-$(CONFIG_ARCH_SUNXI)   += irq-sunxi.o
-obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
+obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2835.o
+obj-$(CONFIG_ARCH_SUNXI)               += irq-sunxi.o
+obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
+obj-$(CONFIG_ARCH_SPEAR3XX)            += spear-shirq.o
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
new file mode 100644 (file)
index 0000000..80e1d2f
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * SPEAr platform shared irq layer source file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.com>
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/spear-shirq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(lock);
+
+/* spear300 shared irq registers offsets and masks */
+#define SPEAR300_INT_ENB_MASK_REG      0x54
+#define SPEAR300_INT_STS_MASK_REG      0x58
+
+static struct spear_shirq spear300_shirq_ras1 = {
+       .irq_nr = 9,
+       .irq_bit_off = 0,
+       .regs = {
+               .enb_reg = SPEAR300_INT_ENB_MASK_REG,
+               .status_reg = SPEAR300_INT_STS_MASK_REG,
+               .clear_reg = -1,
+       },
+};
+
+static struct spear_shirq *spear300_shirq_blocks[] = {
+       &spear300_shirq_ras1,
+};
+
+/* spear310 shared irq registers offsets and masks */
+#define SPEAR310_INT_STS_MASK_REG      0x04
+
+static struct spear_shirq spear310_shirq_ras1 = {
+       .irq_nr = 8,
+       .irq_bit_off = 0,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR310_INT_STS_MASK_REG,
+               .clear_reg = -1,
+       },
+};
+
+static struct spear_shirq spear310_shirq_ras2 = {
+       .irq_nr = 5,
+       .irq_bit_off = 8,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR310_INT_STS_MASK_REG,
+               .clear_reg = -1,
+       },
+};
+
+static struct spear_shirq spear310_shirq_ras3 = {
+       .irq_nr = 1,
+       .irq_bit_off = 13,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR310_INT_STS_MASK_REG,
+               .clear_reg = -1,
+       },
+};
+
+static struct spear_shirq spear310_shirq_intrcomm_ras = {
+       .irq_nr = 3,
+       .irq_bit_off = 14,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR310_INT_STS_MASK_REG,
+               .clear_reg = -1,
+       },
+};
+
+static struct spear_shirq *spear310_shirq_blocks[] = {
+       &spear310_shirq_ras1,
+       &spear310_shirq_ras2,
+       &spear310_shirq_ras3,
+       &spear310_shirq_intrcomm_ras,
+};
+
+/* spear320 shared irq registers offsets and masks */
+#define SPEAR320_INT_STS_MASK_REG              0x04
+#define SPEAR320_INT_CLR_MASK_REG              0x04
+#define SPEAR320_INT_ENB_MASK_REG              0x08
+
+static struct spear_shirq spear320_shirq_ras1 = {
+       .irq_nr = 3,
+       .irq_bit_off = 7,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR320_INT_STS_MASK_REG,
+               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
+               .reset_to_clear = 1,
+       },
+};
+
+static struct spear_shirq spear320_shirq_ras2 = {
+       .irq_nr = 1,
+       .irq_bit_off = 10,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR320_INT_STS_MASK_REG,
+               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
+               .reset_to_clear = 1,
+       },
+};
+
+static struct spear_shirq spear320_shirq_ras3 = {
+       .irq_nr = 3,
+       .irq_bit_off = 0,
+       .invalid_irq = 1,
+       .regs = {
+               .enb_reg = SPEAR320_INT_ENB_MASK_REG,
+               .reset_to_enb = 1,
+               .status_reg = SPEAR320_INT_STS_MASK_REG,
+               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
+               .reset_to_clear = 1,
+       },
+};
+
+static struct spear_shirq spear320_shirq_intrcomm_ras = {
+       .irq_nr = 11,
+       .irq_bit_off = 11,
+       .regs = {
+               .enb_reg = -1,
+               .status_reg = SPEAR320_INT_STS_MASK_REG,
+               .clear_reg = SPEAR320_INT_CLR_MASK_REG,
+               .reset_to_clear = 1,
+       },
+};
+
+static struct spear_shirq *spear320_shirq_blocks[] = {
+       &spear320_shirq_ras3,
+       &spear320_shirq_ras1,
+       &spear320_shirq_ras2,
+       &spear320_shirq_intrcomm_ras,
+};
+
+static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
+{
+       struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+       u32 val, offset = d->irq - shirq->irq_base;
+       unsigned long flags;
+
+       if (shirq->regs.enb_reg == -1)
+               return;
+
+       spin_lock_irqsave(&lock, flags);
+       val = readl(shirq->base + shirq->regs.enb_reg);
+
+       if (mask ^ shirq->regs.reset_to_enb)
+               val &= ~(0x1 << shirq->irq_bit_off << offset);
+       else
+               val |= 0x1 << shirq->irq_bit_off << offset;
+
+       writel(val, shirq->base + shirq->regs.enb_reg);
+       spin_unlock_irqrestore(&lock, flags);
+
+}
+
+static void shirq_irq_mask(struct irq_data *d)
+{
+       shirq_irq_mask_unmask(d, 1);
+}
+
+static void shirq_irq_unmask(struct irq_data *d)
+{
+       shirq_irq_mask_unmask(d, 0);
+}
+
+static struct irq_chip shirq_chip = {
+       .name           = "spear-shirq",
+       .irq_ack        = shirq_irq_mask,
+       .irq_mask       = shirq_irq_mask,
+       .irq_unmask     = shirq_irq_unmask,
+};
+
+static void shirq_handler(unsigned irq, struct irq_desc *desc)
+{
+       u32 i, j, val, mask, tmp;
+       struct irq_chip *chip;
+       struct spear_shirq *shirq = irq_get_handler_data(irq);
+
+       chip = irq_get_chip(irq);
+       chip->irq_ack(&desc->irq_data);
+
+       mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off;
+       while ((val = readl(shirq->base + shirq->regs.status_reg) &
+                               mask)) {
+
+               val >>= shirq->irq_bit_off;
+               for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) {
+
+                       if (!(j & val))
+                               continue;
+
+                       generic_handle_irq(shirq->irq_base + i);
+
+                       /* clear interrupt */
+                       if (shirq->regs.clear_reg == -1)
+                               continue;
+
+                       tmp = readl(shirq->base + shirq->regs.clear_reg);
+                       if (shirq->regs.reset_to_clear)
+                               tmp &= ~(j << shirq->irq_bit_off);
+                       else
+                               tmp |= (j << shirq->irq_bit_off);
+                       writel(tmp, shirq->base + shirq->regs.clear_reg);
+               }
+       }
+       chip->irq_unmask(&desc->irq_data);
+}
+
+static void __init spear_shirq_register(struct spear_shirq *shirq)
+{
+       int i;
+
+       if (shirq->invalid_irq)
+               return;
+
+       irq_set_chained_handler(shirq->irq, shirq_handler);
+       for (i = 0; i < shirq->irq_nr; i++) {
+               irq_set_chip_and_handler(shirq->irq_base + i,
+                                        &shirq_chip, handle_simple_irq);
+               set_irq_flags(shirq->irq_base + i, IRQF_VALID);
+               irq_set_chip_data(shirq->irq_base + i, shirq);
+       }
+
+       irq_set_handler_data(shirq->irq, shirq);
+}
+
+static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
+               struct device_node *np)
+{
+       int i, irq_base, hwirq = 0, irq_nr = 0;
+       static struct irq_domain *shirq_domain;
+       void __iomem *base;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_err("%s: failed to map shirq registers\n", __func__);
+               return -ENXIO;
+       }
+
+       for (i = 0; i < block_nr; i++)
+               irq_nr += shirq_blocks[i]->irq_nr;
+
+       irq_base = irq_alloc_descs(-1, 0, irq_nr, 0);
+       if (IS_ERR_VALUE(irq_base)) {
+               pr_err("%s: irq desc alloc failed\n", __func__);
+               goto err_unmap;
+       }
+
+       shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0,
+                       &irq_domain_simple_ops, NULL);
+       if (WARN_ON(!shirq_domain)) {
+               pr_warn("%s: irq domain init failed\n", __func__);
+               goto err_free_desc;
+       }
+
+       for (i = 0; i < block_nr; i++) {
+               shirq_blocks[i]->base = base;
+               shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain,
+                               hwirq);
+               shirq_blocks[i]->irq = irq_of_parse_and_map(np, i);
+
+               spear_shirq_register(shirq_blocks[i]);
+               hwirq += shirq_blocks[i]->irq_nr;
+       }
+
+       return 0;
+
+err_free_desc:
+       irq_free_descs(irq_base, irq_nr);
+err_unmap:
+       iounmap(base);
+       return -ENXIO;
+}
+
+int __init spear300_shirq_of_init(struct device_node *np,
+               struct device_node *parent)
+{
+       return shirq_init(spear300_shirq_blocks,
+                       ARRAY_SIZE(spear300_shirq_blocks), np);
+}
+
+int __init spear310_shirq_of_init(struct device_node *np,
+               struct device_node *parent)
+{
+       return shirq_init(spear310_shirq_blocks,
+                       ARRAY_SIZE(spear310_shirq_blocks), np);
+}
+
+int __init spear320_shirq_of_init(struct device_node *np,
+               struct device_node *parent)
+{
+       return shirq_init(spear320_shirq_blocks,
+                       ARRAY_SIZE(spear320_shirq_blocks), np);
+}
index 89342f7e0c5b700eb302484ba5eb556ccadacef9..525471e776a76dfe468be16a9d714011ea27546b 100644 (file)
@@ -628,7 +628,7 @@ Amd7930_l1hw(struct PStack *st, int pr, void *arg)
                if ((cs->dc.amd7930.ph_state == 8)) {
                        /* b-channels off, PH-AR cleared
                         * change to F3 */
-                       Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
+                       Amd7930_ph_command(cs, 0x20, "HW_RESET REQUEST"); //LMR1 bit 5
                        spin_unlock_irqrestore(&cs->lock, flags);
                } else {
                        Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
index ff5e139f48503c54e695144d6061be65ad1e1e95..7fdf34704fe5d3469f815f7c44b79f6fb8e15e35 100644 (file)
@@ -1417,7 +1417,7 @@ modeisar(struct BCState *bcs, int mode, int bc)
                                                   &bcs->hw.isar.reg->Flags))
                                bcs->hw.isar.dpath = 1;
                        else {
-                               printk(KERN_WARNING"isar modeisar both pathes in use\n");
+                               printk(KERN_WARNING"isar modeisar both paths in use\n");
                                return (1);
                        }
                        break;
index 48cce18e9d6d5d8c97e89ab953b586e5107a75e0..a20752f562bce37315c984f914660691c14ec0d0 100644 (file)
@@ -211,7 +211,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
        led_trigger_set_default(led_cdev);
 #endif
 
-       printk(KERN_DEBUG "Registered led device: %s\n",
+       dev_dbg(parent, "Registered led device: %s\n",
                        led_cdev->name);
 
        return 0;
index 262eb41937102c7814ad95c685393981057d6453..3c972b2f989335e4df54aa8436cbd99a7f19ba09 100644 (file)
@@ -166,6 +166,19 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
 }
 EXPORT_SYMBOL_GPL(led_trigger_set_default);
 
+void led_trigger_rename_static(const char *name, struct led_trigger *trig)
+{
+       /* new name must be on a temporary string to prevent races */
+       BUG_ON(name == trig->name);
+
+       down_write(&triggers_list_lock);
+       /* this assumes that trig->name was originaly allocated to
+        * non constant storage */
+       strcpy((char *)trig->name, name);
+       up_write(&triggers_list_lock);
+}
+EXPORT_SYMBOL_GPL(led_trigger_rename_static);
+
 /* LED Trigger Interface */
 
 int led_trigger_register(struct led_trigger *trig)
@@ -300,13 +313,13 @@ void led_trigger_register_simple(const char *name, struct led_trigger **tp)
                if (err < 0) {
                        kfree(trig);
                        trig = NULL;
-                       printk(KERN_WARNING "LED trigger %s failed to register"
-                               " (%d)\n", name, err);
+                       pr_warn("LED trigger %s failed to register (%d)\n",
+                               name, err);
                }
-       } else
-               printk(KERN_WARNING "LED trigger %s failed to register"
-                       " (no memory)\n", name);
-
+       } else {
+               pr_warn("LED trigger %s failed to register (no memory)\n",
+                       name);
+       }
        *tp = trig;
 }
 EXPORT_SYMBOL_GPL(led_trigger_register_simple);
index b7e8cc0957fcb65328fe300fffccfe3fc937a96b..6be2edd41173e7e72766e37f5878f71e1e4ea0b1 100644 (file)
@@ -165,15 +165,13 @@ static int pm860x_led_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control");
        if (!res) {
                dev_err(&pdev->dev, "No REG resource for control\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_control = res->start;
        res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink");
        if (!res) {
                dev_err(&pdev->dev, "No REG resource for blink\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
        data->reg_blink = res->start;
        memset(data->name, 0, MFD_NAME_SIZE);
@@ -224,9 +222,6 @@ static int pm860x_led_probe(struct platform_device *pdev)
        }
        pm860x_led_set(&data->cdev, 0);
        return 0;
-out:
-       devm_kfree(&pdev->dev, data);
-       return ret;
 }
 
 static int pm860x_led_remove(struct platform_device *pdev)
index dcd9128a51a9d630f4af6f6e5df9f0a76ae0dc09..e8072abe76e5fb81e1e155ac25c9a7d8481b0673 100644 (file)
@@ -5,10 +5,10 @@
  *
  * Loosely derived from leds-da903x:
  * Copyright (C) 2008 Compulab, Ltd.
- *     Mike Rapoport <mike@compulab.co.il>
+ *     Mike Rapoport <mike@compulab.co.il>
  *
  * Copyright (C) 2006-2008 Marvell International Ltd.
- *     Eric Miao <eric.miao@marvell.com>
+ *     Eric Miao <eric.miao@marvell.com>
  *
  * Licensed under the GPL-2 or later.
  */
index 9abe8de40edd1db4712c06ac4ac32ca9e21d4d77..851517030cc1ec37109761b16cb637b9b373e49f 100644 (file)
@@ -26,8 +26,8 @@
 #define BD2802_LED_OFFSET              0xa
 #define BD2802_COLOR_OFFSET            0x3
 
-#define BD2802_REG_CLKSETUP            0x00
-#define BD2802_REG_CONTROL             0x01
+#define BD2802_REG_CLKSETUP            0x00
+#define BD2802_REG_CONTROL             0x01
 #define BD2802_REG_HOURSETUP           0x02
 #define BD2802_REG_CURRENT1SETUP       0x03
 #define BD2802_REG_CURRENT2SETUP       0x04
@@ -93,7 +93,7 @@ struct bd2802_led {
         * In ADF mode, user can set registers of BD2802GU directly,
         * therefore BD2802GU doesn't enter reset state.
         */
-       int                             adf_on;
+       int                             adf_on;
 
        enum led_ids                    led_id;
        enum led_colors                 color;
@@ -328,7 +328,7 @@ static ssize_t bd2802_store_reg##reg_addr(struct device *dev,               \
        int ret;                                                        \
        if (!count)                                                     \
                return -EINVAL;                                         \
-       ret = strict_strtoul(buf, 16, &val);                            \
+       ret = kstrtoul(buf, 16, &val);                                  \
        if (ret)                                                        \
                return ret;                                             \
        down_write(&led->rwsem);                                        \
@@ -492,7 +492,7 @@ static ssize_t bd2802_store_##attr_name(struct device *dev,         \
        int ret;                                                        \
        if (!count)                                                     \
                return -EINVAL;                                         \
-       ret = strict_strtoul(buf, 16, &val);                            \
+       ret = kstrtoul(buf, 16, &val);                                  \
        if (ret)                                                        \
                return ret;                                             \
        down_write(&led->rwsem);                                        \
index b02547052e12b3914c64542f865b281c3cb9f110..6a8405df76a3dd7200983a04f8ec8832734cd4ea 100644 (file)
@@ -1,3 +1,4 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 
@@ -26,7 +27,7 @@ static struct platform_device *pdev;
 
 static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
 {
-       printk(KERN_INFO KBUILD_MODNAME ": '%s' found\n", id->ident);
+       pr_info("'%s' found\n", id->ident);
        return 1;
 }
 
@@ -135,8 +136,7 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev,
                status = 0;
 
        } else {
-               printk(KERN_DEBUG KBUILD_MODNAME
-                      ": clevo_mail_led_blink(..., %lu, %lu),"
+               pr_debug("clevo_mail_led_blink(..., %lu, %lu),"
                       " returning -EINVAL (unsupported)\n",
                       *delay_on, *delay_off);
        }
@@ -183,7 +183,7 @@ static int __init clevo_mail_led_init(void)
                count = dmi_check_system(clevo_mail_led_dmi_table);
        } else {
                count = 1;
-               printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
+               pr_err("Skipping DMI detection. "
                       "If the driver works on your hardware please "
                       "report model and the output of dmidecode in tracker "
                       "at http://sourceforge.net/projects/clevo-mailled/\n");
@@ -197,8 +197,7 @@ static int __init clevo_mail_led_init(void)
                error = platform_driver_probe(&clevo_mail_led_driver,
                                              clevo_mail_led_probe);
                if (error) {
-                       printk(KERN_ERR KBUILD_MODNAME
-                              ": Can't probe platform driver\n");
+                       pr_err("Can't probe platform driver\n");
                        platform_device_unregister(pdev);
                }
        } else
index ffa99303b629143877a09ce0d4ba828967a72f0f..8abcb66db01c2c587f7e85c91e296e324947027e 100644 (file)
@@ -43,7 +43,7 @@ static int cobalt_qube_led_probe(struct platform_device *pdev)
        if (!res)
                return -EBUSY;
 
-       led_port = ioremap(res->start, resource_size(res));
+       led_port = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!led_port)
                return -ENOMEM;
 
@@ -52,12 +52,11 @@ static int cobalt_qube_led_probe(struct platform_device *pdev)
 
        retval = led_classdev_register(&pdev->dev, &qube_front_led);
        if (retval)
-               goto err_iounmap;
+               goto err_null;
 
        return 0;
 
-err_iounmap:
-       iounmap(led_port);
+err_null:
        led_port = NULL;
 
        return retval;
@@ -67,10 +66,8 @@ static int cobalt_qube_led_remove(struct platform_device *pdev)
 {
        led_classdev_unregister(&qube_front_led);
 
-       if (led_port) {
-               iounmap(led_port);
+       if (led_port)
                led_port = NULL;
-       }
 
        return 0;
 }
index d52e47de396fb97d06aefb7f4be916a576598826..001088b31373f6ddf8e52614c4d5e10001649978 100644 (file)
@@ -85,13 +85,13 @@ static int cobalt_raq_led_probe(struct platform_device *pdev)
        if (!res)
                return -EBUSY;
 
-       led_port = ioremap(res->start, resource_size(res));
+       led_port = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!led_port)
                return -ENOMEM;
 
        retval = led_classdev_register(&pdev->dev, &raq_power_off_led);
        if (retval)
-               goto err_iounmap;
+               goto err_null;
 
        retval = led_classdev_register(&pdev->dev, &raq_web_led);
        if (retval)
@@ -102,8 +102,7 @@ static int cobalt_raq_led_probe(struct platform_device *pdev)
 err_unregister:
        led_classdev_unregister(&raq_power_off_led);
 
-err_iounmap:
-       iounmap(led_port);
+err_null:
        led_port = NULL;
 
        return retval;
@@ -114,10 +113,8 @@ static int cobalt_raq_led_remove(struct platform_device *pdev)
        led_classdev_unregister(&raq_power_off_led);
        led_classdev_unregister(&raq_web_led);
 
-       if (led_port) {
-               iounmap(led_port);
+       if (led_port)
                led_port = NULL;
-       }
 
        return 0;
 }
index 6f31b776765b154b79f6fd422cd55134f5407340..c263a21db8298d057ca1cf5b9b28196d0af8e864 100644 (file)
@@ -2,10 +2,10 @@
  * LEDs driver for Dialog Semiconductor DA9030/DA9034
  *
  * Copyright (C) 2008 Compulab, Ltd.
- *     Mike Rapoport <mike@compulab.co.il>
+ *     Mike Rapoport <mike@compulab.co.il>
  *
  * Copyright (C) 2006-2008 Marvell International Ltd.
- *     Eric Miao <eric.miao@marvell.com>
+ *     Eric Miao <eric.miao@marvell.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
@@ -85,7 +85,7 @@ static void da903x_led_set(struct led_classdev *led_cdev,
                           enum led_brightness value)
 {
        struct da903x_led *led;
-       
+
        led = container_of(led_cdev, struct da903x_led, cdev);
        led->new_brightness = value;
        schedule_work(&led->work);
@@ -156,7 +156,7 @@ static struct platform_driver da903x_led_driver = {
 module_platform_driver(da903x_led_driver);
 
 MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
-             "Mike Rapoport <mike@compulab.co.il>");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:da903x-led");
index b9053fa6e2534312495217164c4a5f4e1eeb403d..b4d5a44cc41b11e1223c28e77a002753c8f5ba91 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
 
 #define FSG_LED_WLAN_BIT       0
 #define FSG_LED_WAN_BIT                1
@@ -149,11 +149,10 @@ static int fsg_led_probe(struct platform_device *pdev)
        int ret;
 
        /* Map the LED chip select address space */
-       latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
-       if (!latch_address) {
-               ret = -ENOMEM;
-               goto failremap;
-       }
+       latch_address = (unsigned short *) devm_ioremap(&pdev->dev,
+                                               IXP4XX_EXP_BUS_BASE(2), 512);
+       if (!latch_address)
+               return -ENOMEM;
 
        latch_value = 0xffff;
        *latch_address = latch_value;
@@ -195,8 +194,6 @@ static int fsg_led_probe(struct platform_device *pdev)
  failwan:
        led_classdev_unregister(&fsg_wlan_led);
  failwlan:
-       iounmap(latch_address);
- failremap:
 
        return ret;
 }
@@ -210,8 +207,6 @@ static int fsg_led_remove(struct platform_device *pdev)
        led_classdev_unregister(&fsg_sync_led);
        led_classdev_unregister(&fsg_ring_led);
 
-       iounmap(latch_address);
-
        return 0;
 }
 
index 291c20797ca08539044e678cee04f5b179f2cce6..1885a26776b1b38256756d202639dc5a25a75f5a 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
 
 struct gpio_led_data {
        struct led_classdev cdev;
@@ -101,15 +102,11 @@ static int create_gpio_led(const struct gpio_led *template,
 
        /* skip leds that aren't available */
        if (!gpio_is_valid(template->gpio)) {
-               printk(KERN_INFO "Skipping unavailable LED gpio %d (%s)\n",
+               dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
                                template->gpio, template->name);
                return 0;
        }
 
-       ret = gpio_request(template->gpio, template->name);
-       if (ret < 0)
-               return ret;
-
        led_dat->cdev.name = template->name;
        led_dat->cdev.default_trigger = template->default_trigger;
        led_dat->gpio = template->gpio;
@@ -129,20 +126,19 @@ static int create_gpio_led(const struct gpio_led *template,
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-       ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
+       ret = devm_gpio_request_one(parent, template->gpio,
+                       GPIOF_DIR_OUT | (led_dat->active_low ^ state),
+                       template->name);
        if (ret < 0)
-               goto err;
-               
+               return ret;
+
        INIT_WORK(&led_dat->work, gpio_led_work);
 
        ret = led_classdev_register(parent, &led_dat->cdev);
        if (ret < 0)
-               goto err;
+               return ret;
 
        return 0;
-err:
-       gpio_free(led_dat->gpio);
-       return ret;
 }
 
 static void delete_gpio_led(struct gpio_led_data *led)
@@ -151,7 +147,6 @@ static void delete_gpio_led(struct gpio_led_data *led)
                return;
        led_classdev_unregister(&led->cdev);
        cancel_work_sync(&led->work);
-       gpio_free(led->gpio);
 }
 
 struct gpio_leds_priv {
@@ -176,12 +171,16 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
        /* count LEDs in this device, so we know how much to allocate */
        count = of_get_child_count(np);
        if (!count)
-               return NULL;
+               return ERR_PTR(-ENODEV);
+
+       for_each_child_of_node(np, child)
+               if (of_get_gpio(child, 0) == -EPROBE_DEFER)
+                       return ERR_PTR(-EPROBE_DEFER);
 
        priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
                        GFP_KERNEL);
        if (!priv)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        for_each_child_of_node(np, child) {
                struct gpio_led led = {};
@@ -216,7 +215,7 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 err:
        for (count = priv->num_leds - 2; count >= 0; count--)
                delete_gpio_led(&priv->leds[count]);
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static const struct of_device_id of_gpio_leds_match[] = {
@@ -226,7 +225,7 @@ static const struct of_device_id of_gpio_leds_match[] = {
 #else /* CONFIG_OF_GPIO */
 static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 #endif /* CONFIG_OF_GPIO */
 
@@ -264,8 +263,8 @@ static int gpio_led_probe(struct platform_device *pdev)
                }
        } else {
                priv = gpio_leds_create_of(pdev);
-               if (!priv)
-                       return -ENODEV;
+               if (IS_ERR(priv))
+                       return PTR_ERR(priv);
        }
 
        platform_set_drvdata(pdev, priv);
index b13ce03719182615126eb8a28f2b1fcc7739a442..65d79284c48851fb6bebbbb437bb87899b9c583f 100644 (file)
@@ -408,10 +408,10 @@ static ssize_t lm3556_indicator_pattern_store(struct device *dev,
        return size;
 out:
        dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
-       return size;
+       return ret;
 }
 
-static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
+static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
 
 static const struct regmap_config lm355x_regmap = {
        .reg_bits = 8,
index 215a7c1e56cc7a2b8b5b6d9007844c7566e12eb2..07b3dde9061335759233e90824cf3c1ede85d503 100644 (file)
@@ -201,13 +201,13 @@ static ssize_t lm3642_torch_pin_store(struct device *dev,
        return size;
 out:
        dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
-       return size;
+       return ret;
 out_strtoint:
        dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
-       return size;
+       return ret;
 }
 
-static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store);
+static DEVICE_ATTR(torch_pin, S_IWUSR, NULL, lm3642_torch_pin_store);
 
 static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
 {
@@ -258,13 +258,13 @@ static ssize_t lm3642_strobe_pin_store(struct device *dev,
        return size;
 out:
        dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
-       return size;
+       return ret;
 out_strtoint:
        dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
-       return size;
+       return ret;
 }
 
-static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store);
+static DEVICE_ATTR(strobe_pin, S_IWUSR, NULL, lm3642_strobe_pin_store);
 
 static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
 {
index b081f67e1dea6de2db0830ae696427a2e3f4e237..0c4386e656c162fcea462743d618638037094124 100644 (file)
@@ -86,7 +86,7 @@ static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value)
 
        tmp = i2c_smbus_read_byte_data(client, reg);
        if (tmp < 0)
-               return -EINVAL;
+               return tmp;
 
        *value = tmp;
 
index 966f158a07dbfa2910cf611f6726b748107f0e18..cb8a5220200b37bd10a0df71f04783175e3697d7 100644 (file)
@@ -152,7 +152,7 @@ static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf)
 
        ret = i2c_smbus_read_byte_data(client, reg);
        if (ret < 0)
-               return -EIO;
+               return ret;
 
        *buf = ret;
        return 0;
@@ -616,7 +616,7 @@ static ssize_t store_led_pattern(struct device *dev,
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(buf, 16, &val);
+       ret = kstrtoul(buf, 16, &val);
        if (ret)
                return ret;
 
@@ -788,10 +788,17 @@ static int lp5521_probe(struct i2c_client *client,
         * LP5521_REG_ENABLE register will not have any effect - strange!
         */
        ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
-       if (ret || buf != LP5521_REG_R_CURR_DEFAULT) {
+       if (ret) {
                dev_err(&client->dev, "error in resetting chip\n");
                goto fail2;
        }
+       if (buf != LP5521_REG_R_CURR_DEFAULT) {
+               dev_err(&client->dev,
+                       "unexpected data in register (expected 0x%x got 0x%x)\n",
+                       LP5521_REG_R_CURR_DEFAULT, buf);
+               ret = -EINVAL;
+               goto fail2;
+       }
        usleep_range(10000, 20000);
 
        ret = lp5521_detect(client);
index 7e304b7ff7796e006c7a99ddde95e4c74f81e6a6..7f5be8948cde0a2acf4717141d2bb7fd8949dd3a 100644 (file)
@@ -171,7 +171,7 @@ static int lp5523_read(struct i2c_client *client, u8 reg, u8 *buf)
        s32 ret = i2c_smbus_read_byte_data(client, reg);
 
        if (ret < 0)
-               return -EIO;
+               return ret;
 
        *buf = ret;
        return 0;
@@ -248,7 +248,10 @@ static int lp5523_configure(struct i2c_client *client)
 
        /* Let the programs run for couple of ms and check the engine status */
        usleep_range(3000, 6000);
-       lp5523_read(client, LP5523_REG_STATUS, &status);
+       ret = lp5523_read(client, LP5523_REG_STATUS, &status);
+       if (ret < 0)
+               return ret;
+
        status &= LP5523_ENG_STATUS_MASK;
 
        if (status == LP5523_ENG_STATUS_MASK) {
@@ -464,10 +467,16 @@ static ssize_t lp5523_selftest(struct device *dev,
                                    LP5523_EN_LEDTEST | 16);
        usleep_range(3000, 6000); /* ADC conversion time is typically 2.7 ms */
        ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
+       if (ret < 0)
+               goto fail;
+
        if (!(status & LP5523_LEDTEST_DONE))
                usleep_range(3000, 6000); /* Was not ready. Wait little bit */
 
-       ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
+       ret = lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
+       if (ret < 0)
+               goto fail;
+
        vdd--;  /* There may be some fluctuation in measurement */
 
        for (i = 0; i < LP5523_LEDS; i++) {
@@ -489,9 +498,14 @@ static ssize_t lp5523_selftest(struct device *dev,
                /* ADC conversion time is 2.7 ms typically */
                usleep_range(3000, 6000);
                ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
+               if (ret < 0)
+                       goto fail;
+
                if (!(status & LP5523_LEDTEST_DONE))
                        usleep_range(3000, 6000);/* Was not ready. Wait. */
-               ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
+               ret = lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
+               if (ret < 0)
+                       goto fail;
 
                if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM)
                        pos += sprintf(buf + pos, "LED %d FAIL\n", i);
@@ -696,7 +710,7 @@ static ssize_t store_current(struct device *dev,
        ssize_t ret;
        unsigned long curr;
 
-       if (strict_strtoul(buf, 0, &curr))
+       if (kstrtoul(buf, 0, &curr))
                return -EINVAL;
 
        if (curr > led->max_current)
index 34b3ba4376fc6744b8f6aaa8323c366a5bf75fcd..c9b9e1fec58758714a309998440822fe912360ac 100644 (file)
@@ -89,15 +89,11 @@ static int create_lt3593_led(const struct gpio_led *template,
 
        /* skip leds on GPIOs that aren't available */
        if (!gpio_is_valid(template->gpio)) {
-               printk(KERN_INFO "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
+               dev_info(parent, "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
                                KBUILD_MODNAME, template->gpio, template->name);
                return 0;
        }
 
-       ret = gpio_request(template->gpio, template->name);
-       if (ret < 0)
-               return ret;
-
        led_dat->cdev.name = template->name;
        led_dat->cdev.default_trigger = template->default_trigger;
        led_dat->gpio = template->gpio;
@@ -110,24 +106,21 @@ static int create_lt3593_led(const struct gpio_led *template,
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-       ret = gpio_direction_output(led_dat->gpio, state);
+       ret = devm_gpio_request_one(parent, template->gpio,
+                                   GPIOF_DIR_OUT | state, template->name);
        if (ret < 0)
-               goto err;
+               return ret;
 
        INIT_WORK(&led_dat->work, lt3593_led_work);
 
        ret = led_classdev_register(parent, &led_dat->cdev);
        if (ret < 0)
-               goto err;
+               return ret;
 
-       printk(KERN_INFO "%s: registered LT3593 LED '%s' at GPIO %d\n",
+       dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n",
                KBUILD_MODNAME, template->name, template->gpio);
 
        return 0;
-
-err:
-       gpio_free(led_dat->gpio);
-       return ret;
 }
 
 static void delete_lt3593_led(struct lt3593_led_data *led)
@@ -137,7 +130,6 @@ static void delete_lt3593_led(struct lt3593_led_data *led)
 
        led_classdev_unregister(&led->cdev);
        cancel_work_sync(&led->work);
-       gpio_free(led->gpio);
 }
 
 static int lt3593_led_probe(struct platform_device *pdev)
index f117f7326c5b632a356b37661775dc1e96f6a101..27d06c52824615567970260e1a6fa9b4657f0e50 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/err.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/nsc_gpio.h>
 #include <linux/scx200_gpio.h>
 #include <linux/module.h>
index 58a800b17dc706ecc9c75fff00aff68b7a74b534..c61c5ebcc08e824e4bea68e3184aabf191632a02 100644 (file)
@@ -243,7 +243,7 @@ static ssize_t netxbig_led_sata_store(struct device *dev,
        int mode_val;
        int ret;
 
-       ret = strict_strtoul(buff, 10, &enable);
+       ret = kstrtoul(buff, 10, &enable);
        if (ret < 0)
                return ret;
 
index 7b75affb308aed1aa286a08c5a60877fe42f8d5a..d978171c25b4da1b8bcfb6804e508b374549acdc 100644 (file)
@@ -150,7 +150,7 @@ static ssize_t ns2_led_sata_store(struct device *dev,
        unsigned long enable;
        enum ns2_led_modes mode;
 
-       ret = strict_strtoul(buff, 10, &enable);
+       ret = kstrtoul(buff, 10, &enable);
        if (ret < 0)
                return ret;
 
@@ -192,29 +192,22 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
        int ret;
        enum ns2_led_modes mode;
 
-       ret = gpio_request(template->cmd, template->name);
-       if (ret == 0) {
-               ret = gpio_direction_output(template->cmd,
-                                           gpio_get_value(template->cmd));
-               if (ret)
-                       gpio_free(template->cmd);
-       }
+       ret = devm_gpio_request_one(&pdev->dev, template->cmd,
+                       GPIOF_DIR_OUT | gpio_get_value(template->cmd),
+                       template->name);
        if (ret) {
                dev_err(&pdev->dev, "%s: failed to setup command GPIO\n",
                        template->name);
+               return ret;
        }
 
-       ret = gpio_request(template->slow, template->name);
-       if (ret == 0) {
-               ret = gpio_direction_output(template->slow,
-                                           gpio_get_value(template->slow));
-               if (ret)
-                       gpio_free(template->slow);
-       }
+       ret = devm_gpio_request_one(&pdev->dev, template->slow,
+                       GPIOF_DIR_OUT | gpio_get_value(template->slow),
+                       template->name);
        if (ret) {
                dev_err(&pdev->dev, "%s: failed to setup slow GPIO\n",
                        template->name);
-               goto err_free_cmd;
+               return ret;
        }
 
        rwlock_init(&led_dat->rw_lock);
@@ -229,7 +222,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 
        ret = ns2_led_get_mode(led_dat, &mode);
        if (ret < 0)
-               goto err_free_slow;
+               return ret;
 
        /* Set LED initial state. */
        led_dat->sata = (mode == NS_V2_LED_SATA) ? 1 : 0;
@@ -238,7 +231,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 
        ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
        if (ret < 0)
-               goto err_free_slow;
+               return ret;
 
        ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
        if (ret < 0)
@@ -248,11 +241,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 
 err_free_cdev:
        led_classdev_unregister(&led_dat->cdev);
-err_free_slow:
-       gpio_free(led_dat->slow);
-err_free_cmd:
-       gpio_free(led_dat->cmd);
-
        return ret;
 }
 
@@ -260,8 +248,6 @@ static void delete_ns2_led(struct ns2_led_data *led_dat)
 {
        device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
        led_classdev_unregister(&led_dat->cdev);
-       gpio_free(led_dat->cmd);
-       gpio_free(led_dat->slow);
 }
 
 #ifdef CONFIG_OF_GPIO
index 706791af8fc8a29da026019597ae52de12be132b..edf485b773c8730960e0923615d0f8aba348ba04 100644 (file)
@@ -277,7 +277,7 @@ static int pca955x_probe(struct i2c_client *client,
                return -ENODEV;
        }
 
-       printk(KERN_INFO "leds-pca955x: Using %s %d-bit LED driver at "
+       dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at "
                        "slave address 0x%02x\n",
                        id->name, chip->bits, client->addr);
 
index e51ff7a3cd8856ee46c9dd2054316fc8ce8548b9..2157524f277c2d7818713f1774726c27069d60b6 100644 (file)
@@ -26,7 +26,7 @@
 struct led_pwm_data {
        struct led_classdev     cdev;
        struct pwm_device       *pwm;
-       unsigned int            active_low;
+       unsigned int            active_low;
        unsigned int            period;
 };
 
index 9ebdd5011a7c2b547bded1a429b60f1d54de0ffe..2e746d257b0228b7d4a024620215c5a8bb09651f 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/mach-rc32434/rb.h>
 
 static void rb532_led_set(struct led_classdev *cdev,
-                          enum led_brightness brightness)
+                         enum led_brightness brightness)
 {
        if (brightness)
                set_latch_u5(LO_ULED, 0);
index bc8984795a3ebc43f0513fbb2bbfd87e8c2ed489..e0fff1ca59238063f088bfd8792da85f7bde9d84 100644 (file)
@@ -204,10 +204,10 @@ static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
        if (p->pin_state == R_TPU_PIN_GPIO_FN)
                gpio_free(cfg->pin_gpio_fn);
 
-       if (new_state == R_TPU_PIN_GPIO) {
-               gpio_request(cfg->pin_gpio, cfg->name);
-               gpio_direction_output(cfg->pin_gpio, !!brightness);
-       }
+       if (new_state == R_TPU_PIN_GPIO)
+               gpio_request_one(cfg->pin_gpio, GPIOF_DIR_OUT | !!brightness,
+                               cfg->name);
+
        if (new_state == R_TPU_PIN_GPIO_FN)
                gpio_request(cfg->pin_gpio_fn, cfg->name);
 
@@ -263,18 +263,18 @@ static int r_tpu_probe(struct platform_device *pdev)
        }
 
        /* map memory, let mapbase point to our channel */
-       p->mapbase = ioremap_nocache(res->start, resource_size(res));
+       p->mapbase = devm_ioremap_nocache(&pdev->dev, res->start,
+                                       resource_size(res));
        if (p->mapbase == NULL) {
                dev_err(&pdev->dev, "failed to remap I/O memory\n");
                return -ENXIO;
        }
 
        /* get hold of clock */
-       p->clk = clk_get(&pdev->dev, NULL);
+       p->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(p->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
-               ret = PTR_ERR(p->clk);
-               goto err0;
+               return PTR_ERR(p->clk);
        }
 
        p->pdev = pdev;
@@ -293,7 +293,7 @@ static int r_tpu_probe(struct platform_device *pdev)
        p->ldev.flags |= LED_CORE_SUSPENDRESUME;
        ret = led_classdev_register(&pdev->dev, &p->ldev);
        if (ret < 0)
-               goto err1;
+               goto err0;
 
        /* max_brightness may be updated by the LED core code */
        p->min_rate = p->ldev.max_brightness * p->refresh_rate;
@@ -301,11 +301,8 @@ static int r_tpu_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        return 0;
 
- err1:
-       r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
-       clk_put(p->clk);
  err0:
-       iounmap(p->mapbase);
+       r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
        return ret;
 }
 
@@ -320,9 +317,7 @@ static int r_tpu_remove(struct platform_device *pdev)
        r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
 
        pm_runtime_disable(&pdev->dev);
-       clk_put(p->clk);
 
-       iounmap(p->mapbase);
        return 0;
 }
 
index 6469849e8266fdf1d9630bebda70f1e4cd3bcc5d..ec9b287ecfbf1f0bf07d73d0511b170dd8f20645 100644 (file)
@@ -459,7 +459,7 @@ static ssize_t nas_led_blink_store(struct device *dev,
        struct led_classdev *led = dev_get_drvdata(dev);
        unsigned long blink_state;
 
-       ret = strict_strtoul(buf, 10, &blink_state);
+       ret = kstrtoul(buf, 10, &blink_state);
        if (ret)
                return ret;
 
index 88f23f845595e614c9164b3c1520375d77314521..ed15157c8f6cbec8f7c721e29564da3de805b3a9 100644 (file)
@@ -216,13 +216,13 @@ static int wm8350_led_probe(struct platform_device *pdev)
 
        isink = devm_regulator_get(&pdev->dev, "led_isink");
        if (IS_ERR(isink)) {
-               printk(KERN_ERR "%s: can't get ISINK\n", __func__);
+               dev_err(&pdev->dev, "%s: can't get ISINK\n", __func__);
                return PTR_ERR(isink);
        }
 
        dcdc = devm_regulator_get(&pdev->dev, "led_vcc");
        if (IS_ERR(dcdc)) {
-               printk(KERN_ERR "%s: can't get DCDC\n", __func__);
+               dev_err(&pdev->dev, "%s: can't get DCDC\n", __func__);
                return PTR_ERR(dcdc);
        }
 
index 6e21e654bb0281ba9e0bca0b5c62731c25c1a8fb..b358cc05eff54dc1df66efc800e01311c7d0c540 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/err.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/scx200_gpio.h>
 #include <linux/module.h>
 
index b941685f222740970911b5fbbf93161304e76a37..027a2b15d7d873d09b510209bdf95dcf72a45ddd 100644 (file)
@@ -40,7 +40,7 @@ static int fb_notifier_callback(struct notifier_block *p,
        int new_status = *blank ? BLANK : UNBLANK;
 
        switch (event) {
-       case FB_EVENT_BLANK :
+       case FB_EVENT_BLANK:
                if (new_status == n->old_status)
                        break;
 
@@ -76,7 +76,7 @@ static ssize_t bl_trig_invert_store(struct device *dev,
        unsigned long invert;
        int ret;
 
-       ret = strict_strtoul(buf, 10, &invert);
+       ret = kstrtoul(buf, 10, &invert);
        if (ret < 0)
                return ret;
 
index ba215dc42f9861ad41db278a970e37a6aedeceae..72e3ebfc281f2fb18b8223b6ae0936f378f40c7b 100644 (file)
@@ -110,7 +110,7 @@ static ssize_t gpio_trig_inverted_store(struct device *dev,
        unsigned long inverted;
        int ret;
 
-       ret = strict_strtoul(buf, 10, &inverted);
+       ret = kstrtoul(buf, 10, &inverted);
        if (ret < 0)
                return ret;
 
index 61200717687b85b3fed040f9599ffd1987b8842d..bd8bf0953fe38db2d071cd6ef0110f6b03271e0b 100644 (file)
@@ -4124,7 +4124,7 @@ static struct md_sysfs_entry md_size =
 __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store);
 
 
-/* Metdata version.
+/* Metadata version.
  * This is one of
  *   'none' for arrays with no metadata (good luck...)
  *   'external' for arrays with externally managed metadata,
index 5ba277768d9914c3dd6364f3d990feef55b67c92..a3ae09124a67f786c19f1e426c12ca77a06c3963 100644 (file)
@@ -25,7 +25,7 @@
  * may be held at once.  This is just an implementation detail.
  *
  * ii) Recursive locking attempts are detected and return EINVAL.  A stack
- * trace is also emitted for the previous lock aquisition.
+ * trace is also emitted for the previous lock acquisition.
  *
  * iii) Priority is given to write locks.
  */
@@ -109,7 +109,7 @@ static int __check_holder(struct block_lock *lock)
                        DMERR("previously held here:");
                        print_stack_trace(lock->traces + i, 4);
 
-                       DMERR("subsequent aquisition attempted here:");
+                       DMERR("subsequent acquisition attempted here:");
                        t.nr_entries = 0;
                        t.max_entries = MAX_STACK;
                        t.entries = entries;
index ae02c84410ff5c04325444f6660125c87335dd3d..a2cd50441ca1a5805bb60c5a03bac573c0b38664 100644 (file)
@@ -35,7 +35,7 @@ struct dm_transaction_manager;
  */
 
 /*
- * Infomation about the values stored within the btree.
+ * Information about the values stored within the btree.
  */
 struct dm_btree_value_type {
        void *context;
index a4502686e7a8763fb5aeded988f026b2a9dd1c99..3380372c0393e7262b95a611c92aa7da659d997b 100644 (file)
@@ -1576,7 +1576,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
         * This happens in stages:
         * 1/ create a new kmem_cache and allocate the required number of
         *    stripe_heads.
-        * 2/ gather all the old stripe_heads and tranfer the pages across
+        * 2/ gather all the old stripe_heads and transfer the pages across
         *    to the new stripe_heads.  This will have the side effect of
         *    freezing the array as once all stripe_heads have been collected,
         *    no IO will be possible.  Old stripe heads are freed once their
index 121b0110af3c525055e426bb7e206c02f2389c04..d2a436ce77f8c6098ceff2ce4f4d3c974f41b35b 100644 (file)
@@ -1,3 +1,10 @@
+# Used by common drivers, when they need to ask questions
+config MEDIA_COMMON_OPTIONS
+       bool
+
+comment "common driver options"
+       depends on MEDIA_COMMON_OPTIONS
+
 source "drivers/media/common/b2c2/Kconfig"
 source "drivers/media/common/saa7146/Kconfig"
 source "drivers/media/common/siano/Kconfig"
index 1df9e578daa5c5309fa5ee3db19df3de6da83857..a8c6cdfaa2f5b7dac8b204b1b37d29cfd34cd615 100644 (file)
@@ -17,11 +17,6 @@ config DVB_B2C2_FLEXCOP
        select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
        select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT
-       help
-         Support for the digital TV receiver chip made by B2C2 Inc. included in
-         Technisats PCI cards and USB boxes.
-
-         Say Y if you own such a device and want to use it.
 
 # Selected via the PCI or USB flexcop drivers
 config DVB_B2C2_FLEXCOP_DEBUG
index 425aeadfb49dea3f3727bfb5f4c27abf7212cba5..68f0f604678ecd33e197539001c0097b6156fd43 100644 (file)
@@ -4,14 +4,16 @@
 
 config SMS_SIANO_MDTV
        tristate
-       depends on DVB_CORE && RC_CORE && HAS_DMA
+       depends on DVB_CORE && HAS_DMA
+       depends on !RC_CORE || RC_CORE
        depends on SMS_USB_DRV || SMS_SDIO_DRV
        default y
-       ---help---
-         Choose Y or M here if you have MDTV receiver with a Siano chipset.
-
-         To compile this driver as a module, choose M here
-         (The module will be called smsmdtv).
 
-         Further documentation on this driver can be found on the WWW
-         at http://www.siano-ms.com/
+config SMS_SIANO_RC
+       bool "Enable Remote Controller support for Siano devices"
+       depends on SMS_SIANO_MDTV && RC_CORE
+       depends on SMS_USB_DRV || SMS_SDIO_DRV
+       depends on MEDIA_COMMON_OPTIONS
+       default y
+       ---help---
+         Choose Y to select Remote Controller support for Siano driver.
index 2a09279e0648edd912897140084e001820cbbbb0..81b1e985bea526d843ad233ee406ddd390811cf4 100644 (file)
@@ -1,7 +1,11 @@
-smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
+smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o
 
 obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
 
+ifeq ($(CONFIG_SMS_SIANO_RC),y)
+  smsmdtv-objs += smsir.o
+endif
+
 ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 
index 9cc55546cc30b138660ddc5cdcb4f857003caf5d..1842e64e63383c0a87bb0b557d3a0fd7fad0250e 100644 (file)
@@ -1092,7 +1092,7 @@ EXPORT_SYMBOL_GPL(smscore_onresponse);
  * @return pointer to descriptor on success, NULL on error.
  */
 
-struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
+static struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
 {
        struct smscore_buffer_t *cb = NULL;
        unsigned long flags;
index 37bc5c4b8ad87541e568a3c968635d0b8a289318..b8c5cad78537209b2409e687a4a5eb23b4c51b93 100644 (file)
@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 
        dev->priv = coredev;
        dev->driver_type = RC_DRIVER_IR_RAW;
-       dev->allowed_protos = RC_TYPE_ALL;
+       dev->allowed_protos = RC_BIT_ALL;
        dev->map_name = sms_get_board(board_id)->rc_codes;
        dev->driver_name = MODULE_NAME;
 
index ae92b3a8587e5d4a32e7d5f2a8b35b047f71f2d8..69b59b9eee28efc5b79237ac751ddd37da2ee566 100644 (file)
@@ -46,10 +46,19 @@ struct ir_t {
        u32 controller;
 };
 
+#ifdef CONFIG_SMS_SIANO_RC
 int sms_ir_init(struct smscore_device_t *coredev);
 void sms_ir_exit(struct smscore_device_t *coredev);
 void sms_ir_event(struct smscore_device_t *coredev,
                        const char *buf, int len);
+#else
+inline static int sms_ir_init(struct smscore_device_t *coredev) {
+       return 0;
+}
+inline static void sms_ir_exit(struct smscore_device_t *coredev) {};
+inline static void sms_ir_event(struct smscore_device_t *coredev,
+                       const char *buf, int len) {};
+#endif
 
 #endif /* __SMS_IR_H__ */
 
index 889c9c16c6df81ec7e2175a3d4c1f858ef4f61c2..d81dbb22aa814fd0b92f8e9c089a9c2f2550ce16 100644 (file)
@@ -877,7 +877,7 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
        dvb_dmxdev_filter_stop(dmxdevfilter);
        dvb_dmxdev_filter_reset(dmxdevfilter);
 
-       if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
+       if ((unsigned)params->pes_type > DMX_PES_OTHER)
                return -EINVAL;
 
        dmxdevfilter->type = DMXDEV_TYPE_PES;
index 02ebe28f830d811b9ea7079ad450cc626a6b3863..48c6cf92ab994c896d9e0f2d155e532c0aa5c500 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
+#include <linux/time.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/fs.h>
index 58e0220447c012a5b9fc7bee807bda26468fb087..388c2eb4d7476b208f7c24c84d9aad96e6bbaa3b 100644 (file)
 #define USB_PID_TERRATEC_T3                            0x10a0
 #define USB_PID_TERRATEC_T5                            0x10a1
 #define USB_PID_NOXON_DAB_STICK                                0x00b3
+#define USB_PID_NOXON_DAB_STICK_REV2                   0x00e0
 #define USB_PID_PINNACLE_EXPRESSCARD_320CX             0x022e
 #define USB_PID_PINNACLE_PCTV2000E                     0x022c
 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH              0x0228
index 7e92793260f0deffbf6bdb0a3024a95f3bf59ff5..49d95040096a42589627d7e3446df5f470c2f919 100644 (file)
@@ -1029,12 +1029,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        /* Get */
        _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
        _DTV_CMD(DTV_API_VERSION, 0, 0),
-       _DTV_CMD(DTV_CODE_RATE_HP, 0, 0),
-       _DTV_CMD(DTV_CODE_RATE_LP, 0, 0),
-       _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0),
-       _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0),
-       _DTV_CMD(DTV_HIERARCHY, 0, 0),
-       _DTV_CMD(DTV_INTERLEAVING, 0, 0),
 
        _DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
 
@@ -1042,13 +1036,11 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
 
        _DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
-       _DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0),
        _DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
        _DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
        _DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
        _DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
        _DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
-       _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0),
        _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
        _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
        _DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
@@ -1056,8 +1048,6 @@ 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)
index f2a90f990ce330548079b7e5ce8e9b74f1a034c9..3d399d9a6343cb0d841d026ad27ca77dee96880b 100644 (file)
@@ -139,7 +139,7 @@ static int cx22700_set_tps(struct cx22700_state *state,
        if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5)
                return -EINVAL;
 
-       if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+       if ((int)p->guard_interval < GUARD_INTERVAL_1_32 ||
            p->guard_interval > GUARD_INTERVAL_1_4)
                return -EINVAL;
 
@@ -152,7 +152,7 @@ static int cx22700_set_tps(struct cx22700_state *state,
            p->modulation != QAM_64)
                return -EINVAL;
 
-       if (p->hierarchy < HIERARCHY_NONE ||
+       if ((int)p->hierarchy < HIERARCHY_NONE ||
            p->hierarchy > HIERARCHY_4)
                return -EINVAL;
 
index 7e28b4ee7d4febb9f815ea569fbfc14f38764b6a..68c88ab58e712a342d482dc7016bd984216090bb 100644 (file)
@@ -338,7 +338,7 @@ static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
 {
        u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
 
-       if ((fec < FEC_NONE) || (fec > FEC_AUTO))
+       if (((int)fec < FEC_NONE) || (fec > FEC_AUTO))
                fec = FEC_AUTO;
 
        /* Set the soft decision threshold */
index b5781a48034c0979bf65ee0ae188200747dfa863..de1cc91fd83317252d2b06ab0b5f9ae6e9b6c461 100644 (file)
@@ -97,7 +97,7 @@ static inline int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb
        return -ENODEV;
 }
 
-int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
+static inline int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return -ENODEV;
index 6d9853750d2b6dd96080dc68fb0dc1496626ddf4..e71cc60851e7ad1391bb4f5e13695bfbf27640c6 100644 (file)
@@ -1748,7 +1748,8 @@ static int DRX_Stop(struct drxd_state *state)
        return status;
 }
 
-int SetOperationMode(struct drxd_state *state, int oMode)
+#if 0  /* Currently unused */
+static int SetOperationMode(struct drxd_state *state, int oMode)
 {
        int status;
 
@@ -1788,6 +1789,7 @@ int SetOperationMode(struct drxd_state *state, int oMode)
                state->operation_mode = oMode;
        return status;
 }
+#endif
 
 static int StartDiversity(struct drxd_state *state)
 {
@@ -2612,7 +2614,7 @@ static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency)
        return 0;
 }
 
-int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
+static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size)
 {
        int status = 0;
        u32 driverVersion;
@@ -2774,7 +2776,7 @@ int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
        return status;
 }
 
-int DRXD_status(struct drxd_state *state, u32 * pLockStatus)
+static int DRXD_status(struct drxd_state *state, u32 *pLockStatus)
 {
        DRX_GetLockStatus(state, pLockStatus);
 
index 8b4c6d5f8f3694d330dfd50d36ae9ef870af4339..c2fc7da0d6bf9de76ac14e0cf128e3c89cd091af 100644 (file)
@@ -65,16 +65,6 @@ static bool IsQAM(struct drxk_state *state)
            state->m_OperationMode == OM_QAM_ITU_C;
 }
 
-bool IsA1WithPatchCode(struct drxk_state *state)
-{
-       return state->m_DRXK_A1_PATCH_CODE;
-}
-
-bool IsA1WithRomCode(struct drxk_state *state)
-{
-       return state->m_DRXK_A1_ROM_CODE;
-}
-
 #define NOA1ROM 0
 
 #define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
@@ -189,7 +179,7 @@ static inline u32 MulDiv32(u32 a, u32 b, u32 c)
        return (u32) tmp64;
 }
 
-inline u32 Frac28a(u32 a, u32 c)
+static inline u32 Frac28a(u32 a, u32 c)
 {
        int i = 0;
        u32 Q1 = 0;
@@ -587,7 +577,7 @@ static int write_block(struct drxk_state *state, u32 Address,
 #define DRXK_MAX_RETRIES_POWERUP 20
 #endif
 
-int PowerUpDevice(struct drxk_state *state)
+static int PowerUpDevice(struct drxk_state *state)
 {
        int status;
        u8 data = 0;
@@ -720,11 +710,6 @@ static int init_state(struct drxk_state *state)
 
        state->m_bPowerDown = (ulPowerDown != 0);
 
-       state->m_DRXK_A1_PATCH_CODE = false;
-       state->m_DRXK_A1_ROM_CODE = false;
-       state->m_DRXK_A2_ROM_CODE = false;
-       state->m_DRXK_A3_ROM_CODE = false;
-       state->m_DRXK_A2_PATCH_CODE = false;
        state->m_DRXK_A3_PATCH_CODE = false;
 
        /* Init AGC and PGA parameters */
@@ -921,7 +906,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
        status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
        if (status < 0)
                goto error;
-       status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+       status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
        if (status < 0)
                goto error;
        status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg);
@@ -948,7 +933,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
                state->m_oscClockFreq = 20250;
                break;
        default:
-               printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n");
+               printk(KERN_ERR "drxk: Clock Frequency is unknown\n");
                return -EINVAL;
        }
        /*
@@ -1217,7 +1202,7 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
                goto error;
 
        /*  MPEG TS pad configuration */
-       status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+       status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
        if (status < 0)
                goto error;
 
@@ -5461,6 +5446,7 @@ static int QAMDemodulatorCommand(struct drxk_state *state,
        } else {
                printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
                        "count %d\n", numberOfParameters);
+               status = -EINVAL;
        }
 
 error:
index 6bb9fc4a7b96cbeeb6a082503499fbff18feb4d2..d18a896a983542f13dccc4269db3478c4b5ea61e 100644 (file)
@@ -320,11 +320,7 @@ struct drxk_state {
 
        u8               *m_microcode;
        int               m_microcode_length;
-       bool              m_DRXK_A1_PATCH_CODE;
-       bool              m_DRXK_A1_ROM_CODE;
-       bool              m_DRXK_A2_ROM_CODE;
-       bool              m_DRXK_A3_ROM_CODE;
-       bool              m_DRXK_A2_PATCH_CODE;
+       bool              m_DRXK_A3_ROM_CODE;
        bool              m_DRXK_A3_PATCH_CODE;
 
        bool              m_rfmirror;
index 5b639087ce45623f7a2f1be7e1b6216c1bc686a8..60a529e3833fdbba325da8bd035d18ca67231331 100644 (file)
@@ -30,7 +30,6 @@
 #include "ds3000.h"
 
 static int debug;
-static int force_fw_upload;
 
 #define dprintk(args...) \
        do { \
@@ -234,7 +233,6 @@ struct ds3000_state {
        struct i2c_adapter *i2c;
        const struct ds3000_config *config;
        struct dvb_frontend frontend;
-       u8 skip_fw_load;
        /* previous uncorrected block counter for DVB-S2 */
        u16 prevUCBS2;
 };
@@ -397,9 +395,6 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
        if (ret < 0)
                return ret;
 
-       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__,
@@ -413,9 +408,6 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
                return ret;
        }
 
-       /* Make sure we don't recurse back through here during loading */
-       state->skip_fw_load = 1;
-
        ret = ds3000_load_firmware(fe, fw);
        if (ret)
                printk("%s: Writing firmware to device failed\n", __func__);
@@ -425,9 +417,6 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
        dprintk("%s: Firmware upload %s\n", __func__,
                        ret == 0 ? "complete" : "failed");
 
-       /* Ensure firmware is always loaded if required */
-       state->skip_fw_load = 0;
-
        return ret;
 }
 
@@ -1309,10 +1298,8 @@ 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");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(DS3000_DEFAULT_FIRMWARE);
index 36fcf559e3619147da5dde357aba6267213357fa..ddf866c46f8b170c066352dc39aeb9112adf52bb 100644 (file)
@@ -180,11 +180,11 @@ static int apply_frontend_param(struct dvb_frontend *fe)
            p->transmission_mode != TRANSMISSION_MODE_8K)
                return -EINVAL;
 
-       if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+       if ((int)p->guard_interval < GUARD_INTERVAL_1_32 ||
            p->guard_interval > GUARD_INTERVAL_1_4)
                return -EINVAL;
 
-       if (p->hierarchy < HIERARCHY_NONE ||
+       if ((int)p->hierarchy < HIERARCHY_NONE ||
            p->hierarchy > HIERARCHY_4)
                return -EINVAL;
 
index e20bf13aa860bb03f2d07945bf04497c6981eb2f..ec388c1d6913c73c9458d43695793ff833fcbd67 100644 (file)
@@ -549,7 +549,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe)
            || (p->frequency > fe->ops.info.frequency_max))
                return -EINVAL;
 
-       if ((p->inversion < INVERSION_OFF)
+       if (((int)p->inversion < INVERSION_OFF)
            || (p->inversion > INVERSION_ON))
                return -EINVAL;
 
@@ -557,7 +557,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe)
            || (p->symbol_rate > fe->ops.info.symbol_rate_max))
                return -EINVAL;
 
-       if ((p->fec_inner < FEC_NONE)
+       if (((int)p->fec_inner < FEC_NONE)
            || (p->fec_inner > FEC_AUTO))
                return -EINVAL;
 
index b0f6ec03d1eb0e4b1e10444e63b482ca945d5a6c..362d26d11e82a4d1f975db097679c7d4bb7ddb97 100644 (file)
@@ -130,7 +130,7 @@ static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
 }
 
 /* write single register with mask */
-int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
+static int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
 {
        int ret;
        u8 tmp;
@@ -150,7 +150,7 @@ int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
 }
 
 /* read single register with mask */
-int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
+static int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
 {
        int ret, i;
        u8 tmp;
@@ -256,7 +256,7 @@ static int rtl2830_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-int rtl2830_get_tune_settings(struct dvb_frontend *fe,
+static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
        struct dvb_frontend_tune_settings *s)
 {
        s->min_delay_ms = 500;
index 80c8e5f1182fdc377a7e6ac83ff3e2efc8e523c8..73887690b0464b2f046c92028873ebc18341d041 100644 (file)
@@ -265,7 +265,7 @@ static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
        return rtl2832_rd_regs(priv, reg, page, val, 1);
 }
 
-int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
+static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
 {
        int ret;
 
@@ -305,7 +305,7 @@ err:
 
 }
 
-int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
+static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
 {
        int ret, i;
        u8 len;
@@ -510,7 +510,7 @@ static int rtl2832_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-int rtl2832_get_tune_settings(struct dvb_frontend *fe,
+static int rtl2832_get_tune_settings(struct dvb_frontend *fe,
        struct dvb_frontend_tune_settings *s)
 {
        struct rtl2832_priv *priv = fe->demodulator_priv;
index 79e29de87fb7b50feb4f2fd65bed5e00c6b6ac8d..cc278b3d6d5a4338e7c97685f4e59c94f8e351cb 100644 (file)
@@ -1260,7 +1260,7 @@ static inline void CONVERT32(u32 x, char *str)
        *str    = '\0';
 }
 
-int stb0899_get_dev_id(struct stb0899_state *state)
+static int stb0899_get_dev_id(struct stb0899_state *state)
 {
        u8 chip_id, release;
        u16 id;
index 2a8aaeb1112dc10ef1267531c36eb14bbd1c8989..0c8e45949b11f018b9850ce387a6ddb2b2b4aeaf 100644 (file)
@@ -879,7 +879,8 @@ static u8 stv0367_readbits(struct stv0367_state *state, u32 label)
        return val;
 }
 
-u8 stv0367_getbits(u8 reg, u32 label)
+#if 0 /* Currently, unused */
+static u8 stv0367_getbits(u8 reg, u32 label)
 {
        u8 mask, pos;
 
@@ -887,7 +888,7 @@ u8 stv0367_getbits(u8 reg, u32 label)
 
        return (reg & mask) >> pos;
 }
-
+#endif
 static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        struct stv0367_state *state = fe->demodulator_priv;
@@ -1263,8 +1264,8 @@ stv0367_ter_signal_type stv0367ter_check_cpamp(struct stv0367_state *state,
        return CPAMPStatus;
 }
 
-enum
-stv0367_ter_signal_type stv0367ter_lock_algo(struct stv0367_state *state)
+static enum stv0367_ter_signal_type
+stv0367ter_lock_algo(struct stv0367_state *state)
 {
        enum stv0367_ter_signal_type ret_flag;
        short int wd, tempo;
@@ -1528,7 +1529,7 @@ static int stv0367ter_sleep(struct dvb_frontend *fe)
        return stv0367ter_standby(fe, 1);
 }
 
-int stv0367ter_init(struct dvb_frontend *fe)
+static int stv0367ter_init(struct dvb_frontend *fe)
 {
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367ter_state *ter_state = state->ter_state;
@@ -2378,9 +2379,9 @@ static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz)
        return ADCClk_Hz;
 }
 
-enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
-                                       u32 SymbolRate,
-                                       enum stv0367cab_mod QAMSize)
+static enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
+                                                u32 SymbolRate,
+                                                enum stv0367cab_mod QAMSize)
 {
        /* Set QAM size */
        stv0367_writebits(state, F367CAB_QAM_MODE, QAMSize);
@@ -2762,7 +2763,7 @@ static int stv0367cab_sleep(struct dvb_frontend *fe)
        return stv0367cab_standby(fe, 1);
 }
 
-int stv0367cab_init(struct dvb_frontend *fe)
+static int stv0367cab_init(struct dvb_frontend *fe)
 {
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367cab_state *cab_state = state->cab_state;
index a83bf680234529a8504b6e3439e6b5f21fa3824b..16a4bc54dbe79acefc0c63789c05c6f21d0d977b 100644 (file)
@@ -96,7 +96,8 @@ static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
 }
 
 /* write single register with mask */
-int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
+static int tda10071_wr_reg_mask(struct tda10071_priv *priv,
+                               u8 reg, u8 val, u8 mask)
 {
        int ret;
        u8 tmp;
@@ -116,7 +117,8 @@ int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
 }
 
 /* read single register with mask */
-int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
+static int tda10071_rd_reg_mask(struct tda10071_priv *priv,
+                               u8 reg, u8 *val, u8 mask)
 {
        int ret, i;
        u8 tmp;
index ad7c72e8f517728539f93adde89f63ddf980d137..d281f77d5c2898e7d5da365afea9ca5e7bba8a7e 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
+#include "tda18271c2dd.h"
 
 struct SStandardParam {
        s32   m_IFFrequency;
index 4fdcd8cb753010416bbbf1d7c271208541b4b157..c2ba085e0d20d10717adb63c362028b320d25007 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef _FIREDTV_H
 #define _FIREDTV_H
 
+#include <linux/time.h>
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
 #include <linux/list.h>
index 18a38b38fcb8c9796b16549b2707c8551b6f86fa..df163800c8e1e5ec7f7ffe035e8888552da8cc1f 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008--2011 Nokia Corporation
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * Contributors:
- *     Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *     Sakari Ailus <sakari.ailus@iki.fi>
  *     Tuukka Toivonen <tuukkat76@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
index e1d4c89d7140ec6360a823116b15f49b776424e3..10c3c1db4cdd1a473232027c602de8b3513ecb58 100644 (file)
@@ -681,18 +681,7 @@ static struct i2c_driver adv7183_driver = {
        .id_table       = adv7183_id,
 };
 
-static __init int adv7183_init(void)
-{
-       return i2c_add_driver(&adv7183_driver);
-}
-
-static __exit void adv7183_exit(void)
-{
-       i2c_del_driver(&adv7183_driver);
-}
-
-module_init(adv7183_init);
-module_exit(adv7183_exit);
+module_i2c_driver(adv7183_driver);
 
 MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver");
 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
index 05f8950f6f91b54cbad5f195fcfecd3cc6a784c1..f47555b1000aa13238e07b94a8116f080ca90f79 100644 (file)
@@ -486,9 +486,19 @@ static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
        struct i2c_client *client = state->i2c_edid;
        u8 msgbuf0[1] = { 0 };
        u8 msgbuf1[256];
-       struct i2c_msg msg[2] = { { client->addr, 0, 1, msgbuf0 },
-                                 { client->addr, 0 | I2C_M_RD, len, msgbuf1 }
-                               };
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = client->addr,
+                       .len = 1,
+                       .buf = msgbuf0
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = msgbuf1
+               },
+       };
 
        if (i2c_transfer(client->adapter, msg, 2) < 0)
                return -EIO;
index 2cee69e34184304b7824752aadfd14d4b1d205b8..f4149eb4d7b4f545e647321f79344786d743a17a 100644 (file)
@@ -2065,7 +2065,7 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
 #define DIF_BPF_COEFF3435      (0x38c)
 #define DIF_BPF_COEFF36                (0x390)
 
-void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
+static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
 {
        u64 pll_freq;
        u32 pll_freq_word;
index 04f192a0398a2d025faa504fd890deeac84473c6..08ae067b2b6f19f503e46bf186105dbea61a9194 100644 (file)
@@ -284,7 +284,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        char *ir_codes = NULL;
        const char *name = NULL;
-       u64 rc_type = RC_TYPE_UNKNOWN;
+       u64 rc_type = RC_BIT_UNKNOWN;
        struct IR_i2c *ir;
        struct rc_dev *rc = NULL;
        struct i2c_adapter *adap = client->adapter;
@@ -303,7 +303,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
        case 0x64:
                name        = "Pixelview";
                ir->get_key = get_key_pixelview;
-               rc_type     = RC_TYPE_OTHER;
+               rc_type     = RC_BIT_OTHER;
                ir_codes    = RC_MAP_EMPTY;
                break;
        case 0x18:
@@ -311,31 +311,31 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
        case 0x1a:
                name        = "Hauppauge";
                ir->get_key = get_key_haup;
-               rc_type     = RC_TYPE_RC5;
+               rc_type     = RC_BIT_RC5;
                ir_codes    = RC_MAP_HAUPPAUGE;
                break;
        case 0x30:
                name        = "KNC One";
                ir->get_key = get_key_knc1;
-               rc_type     = RC_TYPE_OTHER;
+               rc_type     = RC_BIT_OTHER;
                ir_codes    = RC_MAP_EMPTY;
                break;
        case 0x6b:
                name        = "FusionHDTV";
                ir->get_key = get_key_fusionhdtv;
-               rc_type     = RC_TYPE_RC5;
+               rc_type     = RC_BIT_RC5;
                ir_codes    = RC_MAP_FUSIONHDTV_MCE;
                break;
        case 0x40:
                name        = "AVerMedia Cardbus remote";
                ir->get_key = get_key_avermedia_cardbus;
-               rc_type     = RC_TYPE_OTHER;
+               rc_type     = RC_BIT_OTHER;
                ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
                break;
        case 0x71:
                name        = "Hauppauge/Zilog Z8";
                ir->get_key = get_key_haup_xvr;
-               rc_type     = RC_TYPE_RC5;
+               rc_type     = RC_BIT_RC5;
                ir_codes    = RC_MAP_HAUPPAUGE;
                break;
        }
index 49c1b3abb4252c33fc8635f215ba080b640a73d1..2750de63427059ce3d286d1bc27905abeed95542 100644 (file)
@@ -343,7 +343,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
        }
        regs_num = le32_to_cpu(get_unaligned_le32(fw->data));
 
-       v4l2_dbg(3, debug, sd, "FW: %s size %d register sets %d\n",
+       v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
                 S5K4ECGX_FIRMWARE, fw->size, regs_num);
 
        regs_num++; /* Add header */
index a577614bd84f53113470c085e4e1cd221d761a14..d8d5da7c52dbb50759915ea7c76ca9c56c41a923 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -58,7 +58,7 @@ static int bounds_check(struct device *dev, uint32_t val,
        if (val >= min && val <= max)
                return 0;
 
-       dev_warn(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
+       dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
 
        return -EINVAL;
 }
@@ -87,14 +87,14 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
        dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
 }
 
-int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
-                        struct smiapp_pll *pll)
+static int __smiapp_pll_calculate(struct device *dev,
+                                 const struct smiapp_pll_limits *limits,
+                                 struct smiapp_pll *pll, uint32_t mul,
+                                 uint32_t div, uint32_t lane_op_clock_ratio)
 {
        uint32_t sys_div;
        uint32_t best_pix_div = INT_MAX >> 1;
        uint32_t vt_op_binning_div;
-       uint32_t lane_op_clock_ratio;
-       uint32_t mul, div;
        uint32_t more_mul_min, more_mul_max;
        uint32_t more_mul_factor;
        uint32_t min_vt_div, max_vt_div, vt_div;
@@ -102,54 +102,6 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
        unsigned int i;
        int rval;
 
-       if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
-               lane_op_clock_ratio = pll->lanes;
-       else
-               lane_op_clock_ratio = 1;
-       dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
-
-       dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
-               pll->binning_vertical);
-
-       /* CSI transfers 2 bits per clock per lane; thus times 2 */
-       pll->pll_op_clk_freq_hz = pll->link_freq * 2
-               * (pll->lanes / lane_op_clock_ratio);
-
-       /* Figure out limits for pre-pll divider based on extclk */
-       dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
-               limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
-       limits->max_pre_pll_clk_div =
-               min_t(uint16_t, limits->max_pre_pll_clk_div,
-                     clk_div_even(pll->ext_clk_freq_hz /
-                                  limits->min_pll_ip_freq_hz));
-       limits->min_pre_pll_clk_div =
-               max_t(uint16_t, limits->min_pre_pll_clk_div,
-                     clk_div_even_up(
-                             DIV_ROUND_UP(pll->ext_clk_freq_hz,
-                                          limits->max_pll_ip_freq_hz)));
-       dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
-               limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
-
-       i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
-       mul = div_u64(pll->pll_op_clk_freq_hz, i);
-       div = pll->ext_clk_freq_hz / i;
-       dev_dbg(dev, "mul %d / div %d\n", mul, div);
-
-       limits->min_pre_pll_clk_div =
-               max_t(uint16_t, limits->min_pre_pll_clk_div,
-                     clk_div_even_up(
-                             DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
-                                          limits->max_pll_op_freq_hz)));
-       dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
-               limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
-
-       if (limits->min_pre_pll_clk_div > limits->max_pre_pll_clk_div) {
-               dev_err(dev, "unable to compute pre_pll divisor\n");
-               return -EINVAL;
-       }
-
-       pll->pre_pll_clk_div = limits->min_pre_pll_clk_div;
-
        /*
         * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
         * too high.
@@ -162,7 +114,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
                more_mul_max);
        /* Don't go above max pll op frequency. */
        more_mul_max =
-               min_t(int,
+               min_t(uint32_t,
                      more_mul_max,
                      limits->max_pll_op_freq_hz
                      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
@@ -170,7 +122,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
                more_mul_max);
        /* Don't go above the division capability of op sys clock divider. */
        more_mul_max = min(more_mul_max,
-                          limits->max_op_sys_clk_div * pll->pre_pll_clk_div
+                          limits->op.max_sys_clk_div * pll->pre_pll_clk_div
                           / div);
        dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
                more_mul_max);
@@ -193,14 +145,14 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
                more_mul_min);
 
        if (more_mul_min > more_mul_max) {
-               dev_warn(dev,
-                        "unable to compute more_mul_min and more_mul_max");
+               dev_dbg(dev,
+                       "unable to compute more_mul_min and more_mul_max\n");
                return -EINVAL;
        }
 
        more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
        dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
-       more_mul_factor = lcm(more_mul_factor, limits->min_op_sys_clk_div);
+       more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
        dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
                more_mul_factor);
        i = roundup(more_mul_min, more_mul_factor);
@@ -209,7 +161,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 
        dev_dbg(dev, "final more_mul: %d\n", i);
        if (i > more_mul_max) {
-               dev_warn(dev, "final more_mul is bad, max %d", more_mul_max);
+               dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
                return -EINVAL;
        }
 
@@ -268,19 +220,19 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
        dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
        min_vt_div = max(min_vt_div,
                         DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-                                     limits->max_vt_pix_clk_freq_hz));
+                                     limits->vt.max_pix_clk_freq_hz));
        dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
                min_vt_div);
        min_vt_div = max_t(uint32_t, min_vt_div,
-                          limits->min_vt_pix_clk_div
-                          * limits->min_vt_sys_clk_div);
+                          limits->vt.min_pix_clk_div
+                          * limits->vt.min_sys_clk_div);
        dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
 
-       max_vt_div = limits->max_vt_sys_clk_div * limits->max_vt_pix_clk_div;
+       max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
        dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
        max_vt_div = min(max_vt_div,
                         DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-                                     limits->min_vt_pix_clk_freq_hz));
+                                     limits->vt.min_pix_clk_freq_hz));
        dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
                max_vt_div);
 
@@ -288,28 +240,28 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
         * Find limitsits for sys_clk_div. Not all values are possible
         * with all values of pix_clk_div.
         */
-       min_sys_div = limits->min_vt_sys_clk_div;
+       min_sys_div = limits->vt.min_sys_clk_div;
        dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
        min_sys_div = max(min_sys_div,
                          DIV_ROUND_UP(min_vt_div,
-                                      limits->max_vt_pix_clk_div));
+                                      limits->vt.max_pix_clk_div));
        dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
        min_sys_div = max(min_sys_div,
                          pll->pll_op_clk_freq_hz
-                         / limits->max_vt_sys_clk_freq_hz);
+                         / limits->vt.max_sys_clk_freq_hz);
        dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
        min_sys_div = clk_div_even_up(min_sys_div);
        dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
 
-       max_sys_div = limits->max_vt_sys_clk_div;
+       max_sys_div = limits->vt.max_sys_clk_div;
        dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
        max_sys_div = min(max_sys_div,
                          DIV_ROUND_UP(max_vt_div,
-                                      limits->min_vt_pix_clk_div));
+                                      limits->vt.min_pix_clk_div));
        dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
        max_sys_div = min(max_sys_div,
                          DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-                                      limits->min_vt_pix_clk_freq_hz));
+                                      limits->vt.min_pix_clk_freq_hz));
        dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
 
        /*
@@ -322,15 +274,15 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
                for (sys_div = min_sys_div;
                     sys_div <= max_sys_div;
                     sys_div += 2 - (sys_div & 1)) {
-                       int pix_div = DIV_ROUND_UP(vt_div, sys_div);
+                       uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
 
-                       if (pix_div < limits->min_vt_pix_clk_div
-                           || pix_div > limits->max_vt_pix_clk_div) {
+                       if (pix_div < limits->vt.min_pix_clk_div
+                           || pix_div > limits->vt.max_pix_clk_div) {
                                dev_dbg(dev,
                                        "pix_div %d too small or too big (%d--%d)\n",
                                        pix_div,
-                                       limits->min_vt_pix_clk_div,
-                                       limits->max_vt_pix_clk_div);
+                                       limits->vt.min_pix_clk_div,
+                                       limits->vt.max_pix_clk_div);
                                continue;
                        }
 
@@ -354,16 +306,10 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
        pll->pixel_rate_csi =
                pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
 
-       print_pll(dev, pll);
-
-       rval = bounds_check(dev, pll->pre_pll_clk_div,
-                           limits->min_pre_pll_clk_div,
-                           limits->max_pre_pll_clk_div, "pre_pll_clk_div");
-       if (!rval)
-               rval = bounds_check(
-                       dev, pll->pll_ip_clk_freq_hz,
-                       limits->min_pll_ip_freq_hz, limits->max_pll_ip_freq_hz,
-                       "pll_ip_clk_freq_hz");
+       rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
+                           limits->min_pll_ip_freq_hz,
+                           limits->max_pll_ip_freq_hz,
+                           "pll_ip_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
                        dev, pll->pll_multiplier,
@@ -377,42 +323,121 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
        if (!rval)
                rval = bounds_check(
                        dev, pll->op_sys_clk_div,
-                       limits->min_op_sys_clk_div, limits->max_op_sys_clk_div,
+                       limits->op.min_sys_clk_div, limits->op.max_sys_clk_div,
                        "op_sys_clk_div");
        if (!rval)
                rval = bounds_check(
                        dev, pll->op_pix_clk_div,
-                       limits->min_op_pix_clk_div, limits->max_op_pix_clk_div,
+                       limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
                        "op_pix_clk_div");
        if (!rval)
                rval = bounds_check(
                        dev, pll->op_sys_clk_freq_hz,
-                       limits->min_op_sys_clk_freq_hz,
-                       limits->max_op_sys_clk_freq_hz,
+                       limits->op.min_sys_clk_freq_hz,
+                       limits->op.max_sys_clk_freq_hz,
                        "op_sys_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
                        dev, pll->op_pix_clk_freq_hz,
-                       limits->min_op_pix_clk_freq_hz,
-                       limits->max_op_pix_clk_freq_hz,
+                       limits->op.min_pix_clk_freq_hz,
+                       limits->op.max_pix_clk_freq_hz,
                        "op_pix_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
                        dev, pll->vt_sys_clk_freq_hz,
-                       limits->min_vt_sys_clk_freq_hz,
-                       limits->max_vt_sys_clk_freq_hz,
+                       limits->vt.min_sys_clk_freq_hz,
+                       limits->vt.max_sys_clk_freq_hz,
                        "vt_sys_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
                        dev, pll->vt_pix_clk_freq_hz,
-                       limits->min_vt_pix_clk_freq_hz,
-                       limits->max_vt_pix_clk_freq_hz,
+                       limits->vt.min_pix_clk_freq_hz,
+                       limits->vt.max_pix_clk_freq_hz,
                        "vt_pix_clk_freq_hz");
 
        return rval;
 }
+
+int smiapp_pll_calculate(struct device *dev,
+                        const struct smiapp_pll_limits *limits,
+                        struct smiapp_pll *pll)
+{
+       uint16_t min_pre_pll_clk_div;
+       uint16_t max_pre_pll_clk_div;
+       uint32_t lane_op_clock_ratio;
+       uint32_t mul, div;
+       unsigned int i;
+       int rval = -EINVAL;
+
+       if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
+               lane_op_clock_ratio = pll->csi2.lanes;
+       else
+               lane_op_clock_ratio = 1;
+       dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
+
+       dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
+               pll->binning_vertical);
+
+       switch (pll->bus_type) {
+       case SMIAPP_PLL_BUS_TYPE_CSI2:
+               /* CSI transfers 2 bits per clock per lane; thus times 2 */
+               pll->pll_op_clk_freq_hz = pll->link_freq * 2
+                       * (pll->csi2.lanes / lane_op_clock_ratio);
+               break;
+       case SMIAPP_PLL_BUS_TYPE_PARALLEL:
+               pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel
+                       / DIV_ROUND_UP(pll->bits_per_pixel,
+                                      pll->parallel.bus_width);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Figure out limits for pre-pll divider based on extclk */
+       dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
+               limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
+       max_pre_pll_clk_div =
+               min_t(uint16_t, limits->max_pre_pll_clk_div,
+                     clk_div_even(pll->ext_clk_freq_hz /
+                                  limits->min_pll_ip_freq_hz));
+       min_pre_pll_clk_div =
+               max_t(uint16_t, limits->min_pre_pll_clk_div,
+                     clk_div_even_up(
+                             DIV_ROUND_UP(pll->ext_clk_freq_hz,
+                                          limits->max_pll_ip_freq_hz)));
+       dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
+               min_pre_pll_clk_div, max_pre_pll_clk_div);
+
+       i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
+       mul = div_u64(pll->pll_op_clk_freq_hz, i);
+       div = pll->ext_clk_freq_hz / i;
+       dev_dbg(dev, "mul %d / div %d\n", mul, div);
+
+       min_pre_pll_clk_div =
+               max_t(uint16_t, min_pre_pll_clk_div,
+                     clk_div_even_up(
+                             DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
+                                          limits->max_pll_op_freq_hz)));
+       dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
+               min_pre_pll_clk_div, max_pre_pll_clk_div);
+
+       for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
+            pll->pre_pll_clk_div <= max_pre_pll_clk_div;
+            pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
+               rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
+                                             lane_op_clock_ratio);
+               if (rval)
+                       continue;
+
+               print_pll(dev, pll);
+               return 0;
+       }
+
+       dev_info(dev, "unable to compute pre_pll divisor\n");
+       return rval;
+}
 EXPORT_SYMBOL_GPL(smiapp_pll_calculate);
 
-MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
 MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator");
 MODULE_LICENSE("GPL");
index cb2d2db5d02def416e10e3d638df33079655500f..a4a649834a18a685ff0902c54cfb224870dc4bee 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 
 #include <linux/device.h>
 
+/* CSI-2 or CCP-2 */
+#define SMIAPP_PLL_BUS_TYPE_CSI2                               0x00
+#define SMIAPP_PLL_BUS_TYPE_PARALLEL                           0x01
+
+/* op pix clock is for all lanes in total normally */
+#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE                  (1 << 0)
+#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS                           (1 << 1)
+
 struct smiapp_pll {
-       uint8_t lanes;
+       /* input values */
+       uint8_t bus_type;
+       union {
+               struct {
+                       uint8_t lanes;
+               } csi2;
+               struct {
+                       uint8_t bus_width;
+               } parallel;
+       };
+       uint8_t flags;
        uint8_t binning_horizontal;
        uint8_t binning_vertical;
        uint8_t scale_m;
        uint8_t scale_n;
        uint8_t bits_per_pixel;
-       uint16_t flags;
        uint32_t link_freq;
 
+       /* output values */
        uint16_t pre_pll_clk_div;
        uint16_t pll_multiplier;
        uint16_t op_sys_clk_div;
@@ -55,6 +73,17 @@ struct smiapp_pll {
        uint32_t pixel_rate_csi;
 };
 
+struct smiapp_pll_branch_limits {
+       uint16_t min_sys_clk_div;
+       uint16_t max_sys_clk_div;
+       uint32_t min_sys_clk_freq_hz;
+       uint32_t max_sys_clk_freq_hz;
+       uint16_t min_pix_clk_div;
+       uint16_t max_pix_clk_div;
+       uint32_t min_pix_clk_freq_hz;
+       uint32_t max_pix_clk_freq_hz;
+};
+
 struct smiapp_pll_limits {
        /* Strict PLL limits */
        uint32_t min_ext_clk_freq_hz;
@@ -68,36 +97,18 @@ struct smiapp_pll_limits {
        uint32_t min_pll_op_freq_hz;
        uint32_t max_pll_op_freq_hz;
 
-       uint16_t min_vt_sys_clk_div;
-       uint16_t max_vt_sys_clk_div;
-       uint32_t min_vt_sys_clk_freq_hz;
-       uint32_t max_vt_sys_clk_freq_hz;
-       uint16_t min_vt_pix_clk_div;
-       uint16_t max_vt_pix_clk_div;
-       uint32_t min_vt_pix_clk_freq_hz;
-       uint32_t max_vt_pix_clk_freq_hz;
-
-       uint16_t min_op_sys_clk_div;
-       uint16_t max_op_sys_clk_div;
-       uint32_t min_op_sys_clk_freq_hz;
-       uint32_t max_op_sys_clk_freq_hz;
-       uint16_t min_op_pix_clk_div;
-       uint16_t max_op_pix_clk_div;
-       uint32_t min_op_pix_clk_freq_hz;
-       uint32_t max_op_pix_clk_freq_hz;
+       struct smiapp_pll_branch_limits vt;
+       struct smiapp_pll_branch_limits op;
 
        /* Other relevant limits */
        uint32_t min_line_length_pck_bin;
        uint32_t min_line_length_pck;
 };
 
-/* op pix clock is for all lanes in total normally */
-#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE                  (1 << 0)
-#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS                           (1 << 1)
-
 struct device;
 
-int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
+int smiapp_pll_calculate(struct device *dev,
+                        const struct smiapp_pll_limits *limits,
                         struct smiapp_pll *pll);
 
 #endif /* SMIAPP_PLL_H */
index e08e588ad24b5f90808279629bf9c80a2c22aecc..83c7ed7ffcc2c7b7b8d94d82e42a84879410b10a 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2010--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * Based on smiapp driver by Vimarsh Zutshi
  * Based on jt8ev1.c by Vimarsh Zutshi
@@ -252,23 +252,23 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
                .min_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ],
                .max_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ],
 
-               .min_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
-               .max_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
-               .min_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
-               .max_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
-               .min_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
-               .max_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
-               .min_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
-               .max_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
-
-               .min_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
-               .max_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
-               .min_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
-               .max_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
-               .min_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
-               .max_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
-               .min_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
-               .max_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
+               .op.min_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
+               .op.max_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
+               .op.min_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
+               .op.max_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
+               .op.min_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
+               .op.max_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
+               .op.min_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
+               .op.max_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
+
+               .vt.min_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
+               .vt.max_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
+               .vt.min_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
+               .vt.max_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
+               .vt.min_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
+               .vt.max_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
+               .vt.min_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
+               .vt.max_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
 
                .min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
                .min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
@@ -276,11 +276,6 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
        struct smiapp_pll *pll = &sensor->pll;
        int rval;
 
-       memset(&sensor->pll, 0, sizeof(sensor->pll));
-
-       pll->lanes = sensor->platform_data->lanes;
-       pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
-
        if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
                /*
                 * Fill in operational clock divisors limits from the
@@ -288,28 +283,14 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
                 * requirements regarding them are essentially the
                 * same as on VT ones.
                 */
-               lim.min_op_sys_clk_div = lim.min_vt_sys_clk_div;
-               lim.max_op_sys_clk_div = lim.max_vt_sys_clk_div;
-               lim.min_op_pix_clk_div = lim.min_vt_pix_clk_div;
-               lim.max_op_pix_clk_div = lim.max_vt_pix_clk_div;
-               lim.min_op_sys_clk_freq_hz = lim.min_vt_sys_clk_freq_hz;
-               lim.max_op_sys_clk_freq_hz = lim.max_vt_sys_clk_freq_hz;
-               lim.min_op_pix_clk_freq_hz = lim.min_vt_pix_clk_freq_hz;
-               lim.max_op_pix_clk_freq_hz = lim.max_vt_pix_clk_freq_hz;
-               /* Profile 0 sensors have no separate OP clock branch. */
-               pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+               lim.op = lim.vt;
        }
 
-       if (smiapp_needs_quirk(sensor,
-                              SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
-               pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
-
        pll->binning_horizontal = sensor->binning_horizontal;
        pll->binning_vertical = sensor->binning_vertical;
        pll->link_freq =
                sensor->link_freq->qmenu_int[sensor->link_freq->val];
        pll->scale_m = sensor->scale_m;
-       pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
        pll->bits_per_pixel = sensor->csi_format->compressed;
 
        rval = smiapp_pll_calculate(&client->dev, &lim, pll);
@@ -1010,7 +991,7 @@ static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)
         * do not change, or if you do at least know what you're
         * doing. :-)
         *
-        * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 2010-10-25
+        * Sakari Ailus <sakari.ailus@iki.fi> 2010-10-25
         *
         * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl
         *      / EXTCLK freq [Hz]) * flash_strobe_adjustment
@@ -2369,6 +2350,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
        struct i2c_client *client = v4l2_get_subdevdata(subdev);
+       struct smiapp_pll *pll = &sensor->pll;
        struct smiapp_subdev *last = NULL;
        u32 tmp;
        unsigned int i;
@@ -2635,6 +2617,18 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
        if (rval < 0)
                goto out_nvm_release;
 
+       /* prepare PLL configuration input values */
+       pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
+       pll->csi2.lanes = sensor->platform_data->lanes;
+       pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+       /* Profile 0 sensors have no separate OP clock branch. */
+       if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
+               pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+       if (smiapp_needs_quirk(sensor,
+                              SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
+               pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+       pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+
        rval = smiapp_update_mode(sensor);
        if (rval) {
                dev_err(&client->dev, "update mode failed\n");
@@ -2893,6 +2887,6 @@ static struct i2c_driver smiapp_i2c_driver = {
 
 module_i2c_driver(smiapp_i2c_driver);
 
-MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
 MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver");
 MODULE_LICENSE("GPL");
index fb2f81ad8c3b39f56d7507e740f5cd9dc9fd4da2..847cb235e198dae31b31f29a578534823e6f154a 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 9ae765e23ea53b20ca3176ce1070205821a4b1f0..343e9c3827fc022bcf51a341d2b38bcf1f2eb066 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 725cf62836c632f4bbf2c536b97f6d0384497cf4..bb8c506e0e3d94fc6116065c3581ed930d839774 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 86fd3e8bfb0fe0e3e78a116ad93100b6c4ff0013..504a6d80ced5da6833c66a4836751e8cfcb3a39e 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index defa7c5adebf0e07fbd51d4f5d4963baf87d52e0..3aa0ca948d87bcdf5d4ae6d4f6340aa914ad346a 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 54568ca2fe6d987c79c477c4262988ff6dcfbf4d..b0dcbb8fa5e2d62983705ad9d9be3db5b84da3dc 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 70e0d8db01301d56388ab452c318db728151e35b..4fac32cfcb3f1ef67ca893083b02babe2bb1da67 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 7f9013b47971586155ccce3fe8c26e88e7805cc7..eefc6c84d5fefca42b77dfd54f79c719e3f66f38 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 4182a695ab53913e540cf230f2a5abdb0b810a38..7cc5aae662fda5e0ef1ed6ba0b3534fafb4378c4 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2010--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 333ef178d6fbfe1d5622fd161c01856182b01871..d40a8858be01919ba5c85374a3ea6d61ffae10ae 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/log2.h>
 #include <linux/module.h>
 
+#include <media/mt9v022.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
@@ -50,6 +51,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_PIXEL_OPERATION_MODE   0x0f
 #define MT9V022_LED_OUT_CONTROL                0x1b
 #define MT9V022_ADC_MODE_CONTROL       0x1c
+#define MT9V022_REG32                  0x20
 #define MT9V022_ANALOG_GAIN            0x35
 #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
 #define MT9V022_PIXCLK_FV_LV           0x74
@@ -71,7 +73,15 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_COLUMN_SKIP            1
 #define MT9V022_ROW_SKIP               4
 
-#define is_mt9v024(id) (id == 0x1324)
+#define MT9V022_HORIZONTAL_BLANKING_MIN        43
+#define MT9V022_HORIZONTAL_BLANKING_MAX        1023
+#define MT9V022_HORIZONTAL_BLANKING_DEF        94
+#define MT9V022_VERTICAL_BLANKING_MIN  2
+#define MT9V022_VERTICAL_BLANKING_MAX  3000
+#define MT9V022_VERTICAL_BLANKING_DEF  45
+
+#define is_mt9v022_rev3(id)    (id == 0x1313)
+#define is_mt9v024(id)         (id == 0x1324)
 
 /* MT9V022 has only one fixed colorspace per pixelcode */
 struct mt9v022_datafmt {
@@ -136,6 +146,8 @@ struct mt9v022 {
                struct v4l2_ctrl *autogain;
                struct v4l2_ctrl *gain;
        };
+       struct v4l2_ctrl *hblank;
+       struct v4l2_ctrl *vblank;
        struct v4l2_rect rect;  /* Sensor window */
        const struct mt9v022_datafmt *fmt;
        const struct mt9v022_datafmt *fmts;
@@ -143,6 +155,7 @@ struct mt9v022 {
        int num_fmts;
        int model;      /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
        u16 chip_control;
+       u16 chip_version;
        unsigned short y_skip_top;      /* Lines to skip at the top */
 };
 
@@ -225,12 +238,32 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9v022 *mt9v022 = to_mt9v022(client);
 
-       if (enable)
+       if (enable) {
                /* Switch to master "normal" mode */
                mt9v022->chip_control &= ~0x10;
-       else
+               if (is_mt9v022_rev3(mt9v022->chip_version) ||
+                   is_mt9v024(mt9v022->chip_version)) {
+                       /*
+                        * Unset snapshot mode specific settings: clear bit 9
+                        * and bit 2 in reg. 0x20 when in normal mode.
+                        */
+                       if (reg_clear(client, MT9V022_REG32, 0x204))
+                               return -EIO;
+               }
+       } else {
                /* Switch to snapshot mode */
                mt9v022->chip_control |= 0x10;
+               if (is_mt9v022_rev3(mt9v022->chip_version) ||
+                   is_mt9v024(mt9v022->chip_version)) {
+                       /*
+                        * Required settings for snapshot mode: set bit 9
+                        * (RST enable) and bit 2 (CR enable) in reg. 0x20
+                        * See TechNote TN0960 or TN-09-225.
+                        */
+                       if (reg_set(client, MT9V022_REG32, 0x204))
+                               return -EIO;
+               }
+       }
 
        if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0)
                return -EIO;
@@ -282,11 +315,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
                 * Default 94, Phytec driver says:
                 * "width + horizontal blank >= 660"
                 */
-               ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
-                               rect.width > 660 - 43 ? 43 :
-                               660 - rect.width);
+               ret = v4l2_ctrl_s_ctrl(mt9v022->hblank,
+                               rect.width > 660 - 43 ? 43 : 660 - rect.width);
        if (!ret)
-               ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
+               ret = v4l2_ctrl_s_ctrl(mt9v022->vblank, 45);
        if (!ret)
                ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
        if (!ret)
@@ -509,6 +541,18 @@ static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
                range = exp->maximum - exp->minimum;
                exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
                return 0;
+       case V4L2_CID_HBLANK:
+               data = reg_read(client, MT9V022_HORIZONTAL_BLANKING);
+               if (data < 0)
+                       return -EIO;
+               ctrl->val = data;
+               return 0;
+       case V4L2_CID_VBLANK:
+               data = reg_read(client, MT9V022_VERTICAL_BLANKING);
+               if (data < 0)
+                       return -EIO;
+               ctrl->val = data;
+               return 0;
        }
        return -EINVAL;
 }
@@ -590,6 +634,16 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
                                return -EIO;
                }
                return 0;
+       case V4L2_CID_HBLANK:
+               if (reg_write(client, MT9V022_HORIZONTAL_BLANKING,
+                               ctrl->val) < 0)
+                       return -EIO;
+               return 0;
+       case V4L2_CID_VBLANK:
+               if (reg_write(client, MT9V022_VERTICAL_BLANKING,
+                               ctrl->val) < 0)
+                       return -EIO;
+               return 0;
        }
        return -EINVAL;
 }
@@ -621,6 +675,8 @@ static int mt9v022_video_probe(struct i2c_client *client)
                goto ei2c;
        }
 
+       mt9v022->chip_version = data;
+
        mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
                        &mt9v022_register;
 
@@ -819,6 +875,7 @@ static int mt9v022_probe(struct i2c_client *client,
        struct mt9v022 *mt9v022;
        struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct mt9v022_platform_data *pdata = icl->priv;
        int ret;
 
        if (!icl) {
@@ -857,10 +914,21 @@ static int mt9v022_probe(struct i2c_client *client,
        mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
                        V4L2_CID_EXPOSURE, 1, 255, 1, 255);
 
+       mt9v022->hblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_HBLANK, MT9V022_HORIZONTAL_BLANKING_MIN,
+                       MT9V022_HORIZONTAL_BLANKING_MAX, 1,
+                       MT9V022_HORIZONTAL_BLANKING_DEF);
+
+       mt9v022->vblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_VBLANK, MT9V022_VERTICAL_BLANKING_MIN,
+                       MT9V022_VERTICAL_BLANKING_MAX, 1,
+                       MT9V022_VERTICAL_BLANKING_DEF);
+
        mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
        if (mt9v022->hdl.error) {
                int err = mt9v022->hdl.error;
 
+               dev_err(&client->dev, "control initialisation err %d\n", err);
                kfree(mt9v022);
                return err;
        }
@@ -871,10 +939,10 @@ static int mt9v022_probe(struct i2c_client *client,
        mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
 
        /*
-        * MT9V022 _really_ corrupts the first read out line.
-        * TODO: verify on i.MX31
+        * On some platforms the first read out line is corrupted.
+        * Workaround it by skipping if indicated by platform data.
         */
-       mt9v022->y_skip_top     = 1;
+       mt9v022->y_skip_top     = pdata ? pdata->y_skip_top : 0;
        mt9v022->rect.left      = MT9V022_COLUMN_SKIP;
        mt9v022->rect.top       = MT9V022_ROW_SKIP;
        mt9v022->rect.width     = MT9V022_MAX_WIDTH;
index d2d298b6354e8038d95076fdc6a9bd8a68f256d4..66698a83bda2453cdd8c5de7480b94f5ca540a1c 100644 (file)
@@ -586,9 +586,20 @@ static const struct regval_list ov2640_format_change_preamble_regs[] = {
        ENDMARKER,
 };
 
-static const struct regval_list ov2640_yuv422_regs[] = {
+static const struct regval_list ov2640_yuyv_regs[] = {
+       { IMAGE_MODE, IMAGE_MODE_YUV422 },
+       { 0xd7, 0x03 },
+       { 0x33, 0xa0 },
+       { 0xe5, 0x1f },
+       { 0xe1, 0x67 },
+       { RESET,  0x00 },
+       { R_BYPASS, R_BYPASS_USE_DSP },
+       ENDMARKER,
+};
+
+static const struct regval_list ov2640_uyvy_regs[] = {
        { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },
-       { 0xD7, 0x01 },
+       { 0xd7, 0x01 },
        { 0x33, 0xa0 },
        { 0xe1, 0x67 },
        { RESET,  0x00 },
@@ -596,7 +607,15 @@ static const struct regval_list ov2640_yuv422_regs[] = {
        ENDMARKER,
 };
 
-static const struct regval_list ov2640_rgb565_regs[] = {
+static const struct regval_list ov2640_rgb565_be_regs[] = {
+       { IMAGE_MODE, IMAGE_MODE_RGB565 },
+       { 0xd7, 0x03 },
+       { RESET,  0x00 },
+       { R_BYPASS, R_BYPASS_USE_DSP },
+       ENDMARKER,
+};
+
+static const struct regval_list ov2640_rgb565_le_regs[] = {
        { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },
        { 0xd7, 0x03 },
        { RESET,  0x00 },
@@ -605,7 +624,9 @@ static const struct regval_list ov2640_rgb565_regs[] = {
 };
 
 static enum v4l2_mbus_pixelcode ov2640_codes[] = {
+       V4L2_MBUS_FMT_YUYV8_2X8,
        V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_RGB565_2X8_BE,
        V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
@@ -787,14 +808,22 @@ static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
        /* select format */
        priv->cfmt_code = 0;
        switch (code) {
+       case V4L2_MBUS_FMT_RGB565_2X8_BE:
+               dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
+               selected_cfmt_regs = ov2640_rgb565_be_regs;
+               break;
        case V4L2_MBUS_FMT_RGB565_2X8_LE:
-               dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__);
-               selected_cfmt_regs = ov2640_rgb565_regs;
+               dev_dbg(&client->dev, "%s: Selected cfmt RGB565 LE", __func__);
+               selected_cfmt_regs = ov2640_rgb565_le_regs;
+               break;
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+               dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);
+               selected_cfmt_regs = ov2640_yuyv_regs;
                break;
        default:
        case V4L2_MBUS_FMT_UYVY8_2X8:
-               dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__);
-               selected_cfmt_regs = ov2640_yuv422_regs;
+               dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);
+               selected_cfmt_regs = ov2640_uyvy_regs;
        }
 
        /* reset hardware */
@@ -859,10 +888,12 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd,
        mf->code        = priv->cfmt_code;
 
        switch (mf->code) {
+       case V4L2_MBUS_FMT_RGB565_2X8_BE:
        case V4L2_MBUS_FMT_RGB565_2X8_LE:
                mf->colorspace = V4L2_COLORSPACE_SRGB;
                break;
        default:
+       case V4L2_MBUS_FMT_YUYV8_2X8:
        case V4L2_MBUS_FMT_UYVY8_2X8:
                mf->colorspace = V4L2_COLORSPACE_JPEG;
        }
@@ -879,11 +910,13 @@ static int ov2640_s_fmt(struct v4l2_subdev *sd,
 
 
        switch (mf->code) {
+       case V4L2_MBUS_FMT_RGB565_2X8_BE:
        case V4L2_MBUS_FMT_RGB565_2X8_LE:
                mf->colorspace = V4L2_COLORSPACE_SRGB;
                break;
        default:
                mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+       case V4L2_MBUS_FMT_YUYV8_2X8:
        case V4L2_MBUS_FMT_UYVY8_2X8:
                mf->colorspace = V4L2_COLORSPACE_JPEG;
        }
@@ -896,21 +929,21 @@ static int ov2640_s_fmt(struct v4l2_subdev *sd,
 static int ov2640_try_fmt(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *mf)
 {
-       const struct ov2640_win_size *win;
-
        /*
-        * select suitable win
+        * select suitable win, but don't store it
         */
-       win = ov2640_select_win(&mf->width, &mf->height);
+       ov2640_select_win(&mf->width, &mf->height);
 
        mf->field       = V4L2_FIELD_NONE;
 
        switch (mf->code) {
+       case V4L2_MBUS_FMT_RGB565_2X8_BE:
        case V4L2_MBUS_FMT_RGB565_2X8_LE:
                mf->colorspace = V4L2_COLORSPACE_SRGB;
                break;
        default:
                mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+       case V4L2_MBUS_FMT_YUYV8_2X8:
        case V4L2_MBUS_FMT_UYVY8_2X8:
                mf->colorspace = V4L2_COLORSPACE_JPEG;
        }
index 42ae9dc9c574e3c11a97d137a2ce779d25899a7d..f434a19b9bcbb43fcbdb4d9e48f240fe9d2ae372 100644 (file)
@@ -910,18 +910,7 @@ static struct i2c_driver vs6624_driver = {
        .id_table       = vs6624_id,
 };
 
-static __init int vs6624_init(void)
-{
-       return i2c_add_driver(&vs6624_driver);
-}
-
-static __exit void vs6624_exit(void)
-{
-       i2c_del_driver(&vs6624_driver);
-}
-
-module_init(vs6624_init);
-module_exit(vs6624_exit);
+module_i2c_driver(vs6624_driver);
 
 MODULE_DESCRIPTION("VS6624 sensor driver");
 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
index fa62475be3bf865f730f47e7eef5761ffe6e9522..aa05ad3c1ccbedee60bcbece92e4acda8322ee17 100644 (file)
@@ -4,7 +4,8 @@
 
 config SMS_SDIO_DRV
        tristate "Siano SMS1xxx based MDTV via SDIO interface"
-       depends on DVB_CORE && RC_CORE && HAS_DMA
+       depends on DVB_CORE && HAS_DMA
        depends on MMC
+       select MEDIA_COMMON_OPTIONS
        ---help---
          Choose if you would like to have Siano's support for SDIO interface
index 56c6c77793d726f48c50eefbe6cb399a46b19ffe..de6f41f19187dd584be669baadc0398910e71b2b 100644 (file)
@@ -200,7 +200,7 @@ static void flush_request_modules(struct bttv *dev)
 }
 #else
 #define request_modules(dev)
-#define flush_request_modules(dev)
+#define flush_request_modules(dev) do {} while(0)
 #endif /* CONFIG_MODULES */
 
 
@@ -301,11 +301,10 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* totalwidth */ 1135,
                        /* sqwidth */ 944,
                        /* vdelay */ 0x20,
-                       /* sheight */ 576,
-                       /* videostart0 */ 23)
                /* bt878 (and bt848?) can capture another
                   line below active video. */
-               .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
+                       /* sheight */ (576 + 2) + 0x20 - 2,
+                       /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
                .name           = "NTSC",
index 6d2a98246b6d3b30c0896c533f9e332d40c708db..8e971ff605884b45184aae191c90bbeb40027021 100644 (file)
@@ -197,7 +197,7 @@ err_exit:
        return ret;
 }
 
-int cx18_alsa_load(struct cx18 *cx)
+static int __init cx18_alsa_load(struct cx18 *cx)
 {
        struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
        struct cx18_stream *s;
index 7a5b84a86bb39e931d2400d81dfdecaee3e4a5ee..180077c49123fe11159ec3cd8480995586cf7fbf 100644 (file)
@@ -37,6 +37,7 @@
 #include "cx18-streams.h"
 #include "cx18-fileops.h"
 #include "cx18-alsa.h"
+#include "cx18-alsa-pcm.h"
 
 static unsigned int pcm_debug;
 module_param(pcm_debug, int, 0644);
index 51609d5c88ce7962d765f0e5a3ea66e74bd69946..4908eb7bcf6c2396df57838c7351822afae14a34 100644 (file)
@@ -98,7 +98,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
        case CX18_HW_Z8F0811_IR_RX_HAUP:
                init_data->ir_codes = RC_MAP_HAUPPAUGE;
                init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-               init_data->type = RC_TYPE_RC5;
+               init_data->type = RC_BIT_RC5;
                init_data->name = cx->card_name;
                info.platform_data = init_data;
                break;
index 72af9b5c2d7dd2fcc2f37c27d568f4292a7b30ec..843c62b2f482fdd905909dfb6cf4e382433bcbc9 100644 (file)
@@ -97,7 +97,7 @@ static struct {
 };
 
 
-void cx18_dma_free(struct videobuf_queue *q,
+static void cx18_dma_free(struct videobuf_queue *q,
        struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
 {
        videobuf_waiton(q, &buf->vb, 0, 0);
index 495781ee47113e88e792199d2ce4181e8bf1b953..2926f7fadccdcdeba7ca6b3a5cd5e99ba84e4bb7 100644 (file)
@@ -263,7 +263,7 @@ static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,
 }
 
 /* flag - mem/io, read - read/write */
-int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+static int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
                                u8 flag, u8 read, int addr, u8 val)
 {
 
@@ -298,31 +298,32 @@ int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
        return mem;
 }
 
-int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr)
+static int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                       int slot, int addr)
 {
        return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);
 }
 
-int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr, u8 data)
+static int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                        int slot, int addr, u8 data)
 {
        return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);
 }
 
-int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+static int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
+                                 int slot, u8 addr)
 {
        return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,
                                                NETUP_CI_FLG_RD, addr, 0);
 }
 
-int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
-                                               u8 addr, u8 data)
+static int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+                                  u8 addr, u8 data)
 {
        return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);
 }
 
-int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+static int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
 {
        struct altera_ci_state *state = en50221->data;
        struct fpga_internal *inter = state->internal;
@@ -365,13 +366,13 @@ int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
        return 0;
 }
 
-int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+static int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
 {
        /* not implemented */
        return 0;
 }
 
-int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+static int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
 {
        struct altera_ci_state *state = en50221->data;
        struct fpga_internal *inter = state->internal;
@@ -448,8 +449,8 @@ int altera_ci_irq(void *dev)
 }
 EXPORT_SYMBOL(altera_ci_irq);
 
-int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
-                                                               int open)
+static int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+                                     int slot, int open)
 {
        struct altera_ci_state *state = en50221->data;
 
@@ -459,7 +460,7 @@ int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
        return state->status;
 }
 
-void altera_hw_filt_release(void *main_dev, int filt_nr)
+static void altera_hw_filt_release(void *main_dev, int filt_nr)
 {
        struct fpga_inode *temp_int = find_inode(main_dev);
        struct netup_hw_pid_filter *pid_filt = NULL;
@@ -581,7 +582,7 @@ static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,
        mutex_unlock(&inter->fpga_mutex);
 }
 
-int altera_pid_feed_control(void *demux_dev, int filt_nr,
+static int altera_pid_feed_control(void *demux_dev, int filt_nr,
                struct dvb_demux_feed *feed, int onoff)
 {
        struct fpga_inode *temp_int = find_dinode(demux_dev);
@@ -603,41 +604,41 @@ int altera_pid_feed_control(void *demux_dev, int filt_nr,
 }
 EXPORT_SYMBOL(altera_pid_feed_control);
 
-int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
+static int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
 {
        altera_pid_feed_control(feed->demux, num, feed, 1);
 
        return 0;
 }
 
-int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
+static int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
 {
        altera_pid_feed_control(feed->demux, num, feed, 0);
 
        return 0;
 }
 
-int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
+static int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
 {
        return altera_ci_start_feed(feed, 1);
 }
 
-int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
+static int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
 {
        return altera_ci_stop_feed(feed, 1);
 }
 
-int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
+static int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
 {
        return altera_ci_start_feed(feed, 2);
 }
 
-int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
+static int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
 {
        return altera_ci_stop_feed(feed, 2);
 }
 
-int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
+static int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
 {
        struct netup_hw_pid_filter *pid_filt = NULL;
        struct fpga_inode *temp_int = find_inode(config->dev);
index 6617774a326a38f98bd611816003a4907e596aff..7344849183a77bc51e3a072dc31875dcba8fee90 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include "cx23885.h"
+#include "cimax2.h"
 #include "dvb_ca_en50221.h"
 /**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
   bits 31-16
@@ -87,7 +88,7 @@ struct netup_ci_state {
 };
 
 
-int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+static int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
                                                u8 *buf, int len)
 {
        int ret;
@@ -120,7 +121,7 @@ int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
        return 0;
 }
 
-int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+static int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
                                                u8 *buf, int len)
 {
        int ret;
@@ -147,7 +148,7 @@ int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
        return 0;
 }
 
-int netup_ci_get_mem(struct cx23885_dev *dev)
+static int netup_ci_get_mem(struct cx23885_dev *dev)
 {
        int mem;
        unsigned long timeout = jiffies + msecs_to_jiffies(1);
@@ -166,7 +167,7 @@ int netup_ci_get_mem(struct cx23885_dev *dev)
        return mem & 0xff;
 }
 
-int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+static int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
                                u8 flag, u8 read, int addr, u8 data)
 {
        struct netup_ci_state *state = en50221->data;
@@ -248,7 +249,8 @@ int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
        return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
 }
 
-int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+                                u8 addr)
 {
        return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
                                                        NETUP_CI_RD, addr, 0);
@@ -295,7 +297,7 @@ int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
        return 0;
 }
 
-int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
+static int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
 {
        struct netup_ci_state *state = en50221->data;
        int ret;
@@ -399,7 +401,8 @@ int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
        return 1;
 }
 
-int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
+int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+                                    int slot, int open)
 {
        struct netup_ci_state *state = en50221->data;
 
index 795169237e70aa3298763c34d393ae7c75b463d1..c6c9bd58f8be87426ed63200cfc729428e7b417b 100644 (file)
 
 #define AUDIO_SRAM_CHANNEL     SRAM_CH07
 
-#define dprintk(level, fmt, arg...)    if (audio_debug >= level) \
-       printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+#define dprintk(level, fmt, arg...) do {                               \
+       if (audio_debug + 1 > level)                                    \
+               printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg); \
+} while(0)
 
 #define dprintk_core(level, fmt, arg...)       if (audio_debug >= level) \
        printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
index 134ebddd860fef8e6fae5196b8f79a464680518e..e958a01fd554c27ec8b8be330bffbc0749ebb044 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "cx23885.h"
+#include "cx23885-av.h"
 
 void cx23885_av_work_handler(struct work_struct *work)
 {
index 5acdf954ff6bcdadec1c1dfe248012f5a3bf7f84..6277e145f0b831809367019d3ae2886d6440dcc1 100644 (file)
@@ -1427,7 +1427,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
        }
 }
 
-int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
+static int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
 {
        int data;
        int tdo = 0;
index 697728f0943037d2aed76a6a0eba841083b63c17..065ecd54bda3d6127b4ff0ab8e846c41924b3d96 100644 (file)
@@ -303,7 +303,7 @@ static struct sram_channel cx23887_sram_channels[] = {
        },
 };
 
-void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
+static void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
 {
        unsigned long flags;
        spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
@@ -1516,8 +1516,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
                        buf = list_entry(q->queued.next, struct cx23885_buffer,
                                         vb.queue);
                        if (NULL == prev) {
-                               list_del(&buf->vb.queue);
-                               list_add_tail(&buf->vb.queue, &q->active);
+                               list_move_tail(&buf->vb.queue, &q->active);
                                cx23885_start_dma(port, q, buf);
                                buf->vb.state = VIDEOBUF_ACTIVE;
                                buf->count    = q->count++;
@@ -1528,8 +1527,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
                        } else if (prev->vb.width  == buf->vb.width  &&
                                   prev->vb.height == buf->vb.height &&
                                   prev->fmt       == buf->fmt) {
-                               list_del(&buf->vb.queue);
-                               list_add_tail(&buf->vb.queue, &q->active);
+                               list_move_tail(&buf->vb.queue, &q->active);
                                buf->vb.state = VIDEOBUF_ACTIVE;
                                buf->count    = q->count++;
                                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
index 4379d8a6dad5f6d4f8376f7d3d1f4dc68bc97b59..2f5b902e63ae07f71847e89bbbc70a2907ed24fa 100644 (file)
@@ -659,7 +659,7 @@ static struct mt2063_config terratec_mt2063_config[] = {
        },
 };
 
-int netup_altera_fpga_rw(void *device, int flag, int data, int read)
+static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
        struct cx23885_dev *dev = (struct cx23885_dev *)device;
        unsigned long timeout = jiffies + msecs_to_jiffies(1);
index 93998f2209865e8dc5affaaef86758606e3df91c..5444cc526008706d1a6b7a4c87e4aa0da923a22f 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "cx23885.h"
+#include "cx23885-f300.h"
 
 #define F300_DATA      GPIO_0
 #define F300_RESET     GPIO_1
index 2c925f77cf2aa4baeb8288efba0b660448747cb8..4f1055a194b51d9446747d52361f7334eef8a51c 100644 (file)
@@ -40,6 +40,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "cx23885.h"
+#include "cx23885-input.h"
 
 #define MODULE_NAME "cx23885"
 
@@ -270,21 +271,21 @@ int cx23885_input_init(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
                /* Integrated CX2388[58] IR controller */
                driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = RC_TYPE_ALL;
+               allowed_protos = RC_BIT_ALL;
                /* The grey Hauppauge RC-5 remote */
                rc_map = RC_MAP_HAUPPAUGE;
                break;
        case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
                /* Integrated CX23885 IR controller */
                driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = RC_TYPE_NEC;
+               allowed_protos = RC_BIT_NEC;
                /* The grey Terratec remote with orange buttons */
                rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
                break;
        case CX23885_BOARD_TEVII_S470:
                /* Integrated CX23885 IR controller */
                driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = RC_TYPE_ALL;
+               allowed_protos = RC_BIT_ALL;
                /* A guess at the remote */
                rc_map = RC_MAP_TEVII_NEC;
                break;
index 75ef15d3f5235209365ae49d02fc68b2c24323e1..87dc44e69977e2d38fb9c168711a0bf04c54f671 100644 (file)
@@ -23,7 +23,7 @@
 
 #ifndef _CX23885_INPUT_H_
 #define _CX23885_INPUT_H_
-int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
+void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
 
 int cx23885_input_init(struct cx23885_dev *dev);
 void cx23885_input_fini(struct cx23885_dev *dev);
index 44812ca788992d6a511e12354464df0d85eb64e1..ea9a614f3bbf713c9b485043991e75656e2b9fdb 100644 (file)
@@ -22,6 +22,8 @@
  */
 
 #include "cx23885.h"
+#include "cx23885-ioctl.h"
+
 #include <media/v4l2-chip-ident.h>
 
 int cx23885_g_chip_ident(struct file *file, void *fh,
index 7125247dd25558678c823ee3262675570c9aa630..bfef193592916dd46ed734dac478ac03e1eab653 100644 (file)
@@ -24,6 +24,7 @@
 #include <media/v4l2-device.h>
 
 #include "cx23885.h"
+#include "cx23885-ir.h"
 #include "cx23885-input.h"
 
 #define CX23885_IR_RX_FIFO_SERVICE_REQ         0
index c2bc39c58f82e8fef59a500d1ce9c8746bcf8ad9..c4bd1e95d33fb950da950821a5e5c5f06ba0efee 100644 (file)
@@ -29,6 +29,7 @@
 #include <media/rc-core.h>
 
 #include "cx23885.h"
+#include "cx23888-ir.h"
 
 static unsigned int ir_888_debug;
 module_param(ir_888_debug, int, 0644);
index f4893e69cd895aa3fb6b6e59d860f5ab3cb0208b..0044fef7ca24e2adac4d08f55f6d32bc9b08ed5d 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include "cx23885.h"
+#include "netup-init.h"
 
 static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val)
 {
index 8b2a99975c23f0a4deabdc6e69f46b402c95776e..87491ca05ee556fc9b7b4fc4c2112684fc997604 100644 (file)
@@ -44,7 +44,7 @@ MODULE_LICENSE("GPL");
 static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
                        FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
 
-int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+static int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
                                              struct sram_channel *ch,
                                              unsigned int bpl, u32 risc)
 {
@@ -133,7 +133,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
        return rp;
 }
 
-int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+static int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
                                       struct pci_dev *pci,
                                       unsigned int bpl, unsigned int lines)
 {
@@ -197,7 +197,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
        return 0;
 }
 
-void cx25821_free_memory_audio(struct cx25821_dev *dev)
+static void cx25821_free_memory_audio(struct cx25821_dev *dev)
 {
        if (dev->_risc_virt_addr) {
                pci_free_consistent(dev->pci, dev->_audiorisc_size,
@@ -256,7 +256,7 @@ void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
        cx25821_free_memory_audio(dev);
 }
 
-int cx25821_get_audio_data(struct cx25821_dev *dev,
+static int cx25821_get_audio_data(struct cx25821_dev *dev,
                           struct sram_channel *sram_ch)
 {
        struct file *myfile;
@@ -351,7 +351,7 @@ static void cx25821_audioups_handler(struct work_struct *work)
                        sram_channels);
 }
 
-int cx25821_openfile_audio(struct cx25821_dev *dev,
+static int cx25821_openfile_audio(struct cx25821_dev *dev,
                           struct sram_channel *sram_ch)
 {
        struct file *myfile;
@@ -490,7 +490,7 @@ error:
        return ret;
 }
 
-int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+static int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
                               u32 status)
 {
        int i = 0;
@@ -634,8 +634,8 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
 
 }
 
-int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
-                                    struct sram_channel *sram_ch)
+static int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+                                           struct sram_channel *sram_ch)
 {
        u32 tmp = 0;
        int err = 0;
@@ -700,9 +700,7 @@ fail_irq:
 int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 {
        struct sram_channel *sram_ch;
-       int retval = 0;
        int err = 0;
-       int str_length = 0;
 
        if (dev->_audio_is_running) {
                pr_warn("Audio Channel is still running so return!\n");
@@ -731,27 +729,29 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
        _line_size = AUDIO_LINE_SIZE;
 
        if (dev->input_audiofilename) {
-               str_length = strlen(dev->input_audiofilename);
-               dev->_audiofilename = kmemdup(dev->input_audiofilename,
-                                             str_length + 1, GFP_KERNEL);
+               dev->_audiofilename = kstrdup(dev->input_audiofilename,
+                                             GFP_KERNEL);
 
-               if (!dev->_audiofilename)
+               if (!dev->_audiofilename) {
+                       err = -ENOMEM;
                        goto error;
+               }
 
                /* Default if filename is empty string */
                if (strcmp(dev->input_audiofilename, "") == 0)
                        dev->_audiofilename = "/root/audioGOOD.wav";
        } else {
-               str_length = strlen(_defaultAudioName);
-               dev->_audiofilename = kmemdup(_defaultAudioName,
-                                             str_length + 1, GFP_KERNEL);
+               dev->_audiofilename = kstrdup(_defaultAudioName,
+                                             GFP_KERNEL);
 
-               if (!dev->_audiofilename)
+               if (!dev->_audiofilename) {
+                       err = -ENOMEM;
                        goto error;
+               }
        }
 
-       retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
-                                                       _line_size, 0);
+       cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
+                                                 _line_size, 0);
 
        dev->audio_upstream_riscbuf_size =
                AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
@@ -759,9 +759,9 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
        dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
 
        /* Allocating buffers and prepare RISC program */
-       retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
+       err = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
                                                        _line_size);
-       if (retval < 0) {
+       if (err < 0) {
                pr_err("%s: Failed to set up Audio upstream buffers!\n",
                        dev->name);
                goto error;
index 9326a7c729ec3e0713e741a577c35da2df99d1fc..937f5a70fb7a8d8d032759a937ca889a45f11f64 100644 (file)
 
 #define SetBit(Bit)  (1 << Bit)
 
-inline u8 getBit(u32 sample, u8 index)
+static inline u8 getBit(u32 sample, u8 index)
 {
        return (u8) ((sample >> index) & 1);
 }
 
-inline u32 clearBitAtPos(u32 value, u8 bit)
+static inline u32 clearBitAtPos(u32 value, u8 bit)
 {
        return value & ~(1 << bit);
 }
 
-inline u32 setBitAtPos(u32 sample, u8 bit)
+static inline u32 setBitAtPos(u32 sample, u8 bit)
 {
        sample |= (1 << bit);
        return sample;
index 9844549764c96a8c10e288513149baf60908c2c7..a8dc945bbe1797f015a25e505719a5c34b8fba5b 100644 (file)
@@ -329,7 +329,8 @@ int cx25821_i2c_unregister(struct cx25821_i2c *bus)
        return 0;
 }
 
-void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+#if 0 /* Currently unused */
+static void cx25821_av_clk(struct cx25821_dev *dev, int enable)
 {
        /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
        char buffer[3];
@@ -351,6 +352,7 @@ void cx25821_av_clk(struct cx25821_dev *dev, int enable)
 
        i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
 }
+#endif
 
 int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
 {
index d33fc1a2303087ccb416ed158708c31c9ddec4d3..cf2723c7197f1071b49ad9a9b148216e022f4b02 100644 (file)
@@ -123,10 +123,11 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
        return rp;
 }
 
-int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
-                                    struct pci_dev *pci,
-                                    unsigned int top_offset, unsigned int bpl,
-                                    unsigned int lines)
+static int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+                                           struct pci_dev *pci,
+                                           unsigned int top_offset,
+                                           unsigned int bpl,
+                                           unsigned int lines)
 {
        __le32 *rp;
        int fifo_enable = 0;
@@ -255,7 +256,8 @@ void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
        }
 }
 
-int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_get_frame_ch2(struct cx25821_dev *dev,
+                                struct sram_channel *sram_ch)
 {
        struct file *myfile;
        int frame_index_temp = dev->_frame_index_ch2;
@@ -360,7 +362,8 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work)
                        _channel2_upstream_select].sram_channels);
 }
 
-int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_openfile_ch2(struct cx25821_dev *dev,
+                               struct sram_channel *sram_ch)
 {
        struct file *myfile;
        int i = 0, j = 0;
@@ -507,8 +510,9 @@ error:
        return ret;
 }
 
-int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
-                                  u32 status)
+static int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev,
+                                         int chan_num,
+                                         u32 status)
 {
        u32 int_msk_tmp;
        struct sram_channel *channel = dev->channels[chan_num].sram_channels;
@@ -647,8 +651,8 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
        cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
 }
 
-int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
-                                        struct sram_channel *sram_ch)
+static int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+                                               struct sram_channel *sram_ch)
 {
        u32 tmp = 0;
        int err = 0;
@@ -704,11 +708,9 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
 {
        struct sram_channel *sram_ch;
        u32 tmp;
-       int retval = 0;
        int err = 0;
        int data_frame_size = 0;
        int risc_buffer_size = 0;
-       int str_length = 0;
 
        if (dev->_is_running_ch2) {
                pr_info("Video Channel is still running so return!\n");
@@ -744,20 +746,16 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
        risc_buffer_size = dev->_isNTSC_ch2 ?
                NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
 
-       if (dev->input_filename_ch2) {
-               str_length = strlen(dev->input_filename_ch2);
-               dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
-                                            str_length + 1, GFP_KERNEL);
-
-               if (!dev->_filename_ch2)
-                       goto error;
-       } else {
-               str_length = strlen(dev->_defaultname_ch2);
-               dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
-                                            str_length + 1, GFP_KERNEL);
+       if (dev->input_filename_ch2)
+               dev->_filename_ch2 = kstrdup(dev->input_filename_ch2,
+                                                               GFP_KERNEL);
+       else
+               dev->_filename_ch2 = kstrdup(dev->_defaultname_ch2,
+                                                               GFP_KERNEL);
 
-               if (!dev->_filename_ch2)
-                       goto error;
+       if (!dev->_filename_ch2) {
+               err = -ENOENT;
+               goto error;
        }
 
        /* Default if filename is empty string */
@@ -773,7 +771,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
                }
        }
 
-       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+       err = cx25821_sram_channel_setup_upstream(dev, sram_ch,
                                                dev->_line_size_ch2, 0);
 
        /* setup fifo + format */
@@ -783,9 +781,9 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
        dev->upstream_databuf_size_ch2 = data_frame_size * 2;
 
        /* Allocating buffers and prepare RISC program */
-       retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+       err = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
                                                dev->_line_size_ch2);
-       if (retval < 0) {
+       if (err < 0) {
                pr_err("%s: Failed to set up Video upstream buffers!\n",
                       dev->name);
                goto error;
index 6759fff8eb640b57b4b9048bb48f3ef0dfa777c8..7fc97110d973eabee2e70b1132810f892f799106 100644 (file)
@@ -173,10 +173,10 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
        return rp;
 }
 
-int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
-                                struct pci_dev *pci,
-                                unsigned int top_offset,
-                                unsigned int bpl, unsigned int lines)
+static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+                                       struct pci_dev *pci,
+                                       unsigned int top_offset,
+                                       unsigned int bpl, unsigned int lines)
 {
        __le32 *rp;
        int fifo_enable = 0;
@@ -300,7 +300,8 @@ void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
        }
 }
 
-int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_get_frame(struct cx25821_dev *dev,
+                            struct sram_channel *sram_ch)
 {
        struct file *myfile;
        int frame_index_temp = dev->_frame_index;
@@ -405,7 +406,8 @@ static void cx25821_vidups_handler(struct work_struct *work)
                        sram_channels);
 }
 
-int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_openfile(struct cx25821_dev *dev,
+                           struct sram_channel *sram_ch)
 {
        struct file *myfile;
        int i = 0, j = 0;
@@ -486,8 +488,9 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
        return 0;
 }
 
-int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
-                                   struct sram_channel *sram_ch, int bpl)
+static int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+                                          struct sram_channel *sram_ch,
+                                          int bpl)
 {
        int ret = 0;
        dma_addr_t dma_addr;
@@ -548,8 +551,8 @@ error:
        return ret;
 }
 
-int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
-                              u32 status)
+static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+                                     u32 status)
 {
        u32 int_msk_tmp;
        struct sram_channel *channel = dev->channels[chan_num].sram_channels;
@@ -664,8 +667,9 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
        return IRQ_RETVAL(handled);
 }
 
-void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
-                            int pix_format)
+static void cx25821_set_pixelengine(struct cx25821_dev *dev,
+                                   struct sram_channel *ch,
+                                   int pix_format)
 {
        int width = WIDTH_D1;
        int height = dev->_lines_count;
@@ -696,8 +700,8 @@ void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
        cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
 }
 
-int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
-                                    struct sram_channel *sram_ch)
+static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+                                           struct sram_channel *sram_ch)
 {
        u32 tmp = 0;
        int err = 0;
@@ -753,7 +757,6 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
 {
        struct sram_channel *sram_ch;
        u32 tmp;
-       int retval = 0;
        int err = 0;
        int data_frame_size = 0;
        int risc_buffer_size = 0;
@@ -796,15 +799,19 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
                dev->_filename = kmemdup(dev->input_filename, str_length + 1,
                                         GFP_KERNEL);
 
-               if (!dev->_filename)
+               if (!dev->_filename) {
+                       err = -ENOENT;
                        goto error;
+               }
        } else {
                str_length = strlen(dev->_defaultname);
                dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
                                         GFP_KERNEL);
 
-               if (!dev->_filename)
+               if (!dev->_filename) {
+                       err = -ENOENT;
                        goto error;
+               }
        }
 
        /* Default if filename is empty string */
@@ -828,7 +835,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
        dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
                (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
 
-       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+       err = cx25821_sram_channel_setup_upstream(dev, sram_ch,
                        dev->_line_size, 0);
 
        /* setup fifo + format */
@@ -838,8 +845,8 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
        dev->upstream_databuf_size = data_frame_size * 2;
 
        /* Allocating buffers and prepare RISC program */
-       retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
-       if (retval < 0) {
+       err = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+       if (err < 0) {
                pr_err("%s: Failed to set up Video upstream buffers!\n",
                       dev->name);
                goto error;
index 0a80245165d0d8d6e51f876494c1f886893dd43f..53b16dd7032054a0afce16de3037350e012214c6 100644 (file)
@@ -291,9 +291,9 @@ int cx25821_start_video_dma(struct cx25821_dev *dev,
        return 0;
 }
 
-int cx25821_restart_video_queue(struct cx25821_dev *dev,
-                               struct cx25821_dmaqueue *q,
-                               struct sram_channel *channel)
+static int cx25821_restart_video_queue(struct cx25821_dev *dev,
+                                      struct cx25821_dmaqueue *q,
+                                      struct sram_channel *channel)
 {
        struct cx25821_buffer *buf, *prev;
        struct list_head *item;
@@ -342,7 +342,7 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev,
        }
 }
 
-void cx25821_vid_timeout(unsigned long data)
+static void cx25821_vid_timeout(unsigned long data)
 {
        struct cx25821_data *timeout_data = (struct cx25821_data *)data;
        struct cx25821_dev *dev = timeout_data->dev;
index 3aa6856ead3b2f13f71db61ee9ea329808c01be4..d2de1a913e1978343937682689f2096320169f41 100644 (file)
 #include "cx88.h"
 #include "cx88-reg.h"
 
-#define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
-
-#define dprintk_core(level,fmt, arg...)        if (debug >= level) \
-       printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
+#define dprintk(level, fmt, arg...) do {                               \
+       if (debug + 1 > level)                                          \
+               printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg);\
+} while(0)
+
+#define dprintk_core(level, fmt, arg...) do {                          \
+       if (debug + 1 > level)                                          \
+               printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg);\
+} while(0)
 
 /****************************************************************************
        Data type declarations - Can be moded to a header file later
index 62184eb919e5d7563ab0c8d4a9c286c45131c92b..a6ff8a6f4fc09f90e1ffce5027839e575d41515a 100644 (file)
@@ -53,9 +53,10 @@ static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
 
-#define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
-
+#define dprintk(level, fmt, arg...) do {                                     \
+       if (debug + 1 > level)                                                \
+               printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg); \
+} while(0)
 
 /* ------------------------------------------------------------------ */
 
index c97b174be3ab6313e9810c0c27b13b97ce2f3384..19a58754c6e14ee3d91152738464382edf16ab30 100644 (file)
@@ -646,22 +646,22 @@ int cx88_reset(struct cx88_core *core)
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int inline norm_swidth(v4l2_std_id norm)
+static inline unsigned int norm_swidth(v4l2_std_id norm)
 {
        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 }
 
-static unsigned int inline norm_hdelay(v4l2_std_id norm)
+static inline unsigned int norm_hdelay(v4l2_std_id norm)
 {
        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 }
 
-static unsigned int inline norm_vdelay(v4l2_std_id norm)
+static inline unsigned int norm_vdelay(v4l2_std_id norm)
 {
        return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
 }
 
-static unsigned int inline norm_fsc8(v4l2_std_id norm)
+static inline unsigned int norm_fsc8(v4l2_std_id norm)
 {
        if (norm & V4L2_STD_PAL_M)
                return 28604892;      // 3.575611 MHz
@@ -681,7 +681,7 @@ static unsigned int inline norm_fsc8(v4l2_std_id norm)
        return 35468950;      // 4.43361875 MHz +/- 5 Hz
 }
 
-static unsigned int inline norm_htotal(v4l2_std_id norm)
+static inline unsigned int norm_htotal(v4l2_std_id norm)
 {
 
        unsigned int fsc4=norm_fsc8(norm)/2;
@@ -692,7 +692,7 @@ static unsigned int inline norm_htotal(v4l2_std_id norm)
                                ((fsc4+262)/525*1001+15000)/30000;
 }
 
-static unsigned int inline norm_vbipack(v4l2_std_id norm)
+static inline unsigned int norm_vbipack(v4l2_std_id norm)
 {
        return (norm & V4L2_STD_625_50) ? 511 : 400;
 }
index ebf448c48ca3335ce6cdb0a0091270fcdb96bd57..f29e18c72f44ffa6462c09ae870445a67326431b 100644 (file)
@@ -248,7 +248,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        struct cx88_IR *ir;
        struct rc_dev *dev;
        char *ir_codes = NULL;
-       u64 rc_type = RC_TYPE_OTHER;
+       u64 rc_type = RC_BIT_OTHER;
        int err = -ENOMEM;
        u32 hardware_mask = 0;  /* For devices with a hardware mask, when
                                 * used with a full-code IR table
@@ -416,7 +416,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                break;
        case CX88_BOARD_TWINHAN_VP1027_DVBS:
                ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
-               rc_type          = RC_TYPE_NEC;
+               rc_type          = RC_BIT_NEC;
                ir->sampling     = 0xff00; /* address */
                break;
        }
@@ -592,7 +592,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
        case CX88_BOARD_LEADTEK_PVR2000:
                addr_list = pvr2000_addr_list;
                core->init_data.name = "cx88 Leadtek PVR 2000 remote";
-               core->init_data.type = RC_TYPE_UNKNOWN;
+               core->init_data.type = RC_BIT_UNKNOWN;
                core->init_data.get_key = get_key_pvr2000;
                core->init_data.ir_codes = RC_MAP_EMPTY;
                break;
@@ -613,7 +613,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
                        /* Hauppauge XVR */
                        core->init_data.name = "cx88 Hauppauge XVR remote";
                        core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-                       core->init_data.type = RC_TYPE_RC5;
+                       core->init_data.type = RC_BIT_RC5;
                        core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 
                        info.platform_data = &core->init_data;
index d154bc19735688de10c35e47e65b719d71dbfecd..d46b008a46b86f4d2e2684cba33b650d2b12ff44 100644 (file)
@@ -45,11 +45,15 @@ static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
 
-#define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
+#define dprintk(level, fmt, arg...) do {                                      \
+       if (debug + 1 > level)                                                 \
+               printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg); \
+} while(0)
 
-#define mpeg_dbg(level,fmt, arg...)    if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
+#define mpeg_dbg(level, fmt, arg...) do {                                \
+       if (debug + 1 > level)                                            \
+               printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg); \
+} while(0)
 
 #if defined(CONFIG_MODULES) && defined(MODULE)
 static void request_module_async(struct work_struct *work)
@@ -217,8 +221,7 @@ static int cx8802_restart_queue(struct cx8802_dev    *dev,
                                return 0;
                        buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
                        if (NULL == prev) {
-                               list_del(&buf->vb.queue);
-                               list_add_tail(&buf->vb.queue,&q->active);
+                               list_move_tail(&buf->vb.queue, &q->active);
                                cx8802_start_dma(dev, q, buf);
                                buf->vb.state = VIDEOBUF_ACTIVE;
                                buf->count    = q->count++;
@@ -229,8 +232,7 @@ static int cx8802_restart_queue(struct cx8802_dev    *dev,
                        } else if (prev->vb.width  == buf->vb.width  &&
                                   prev->vb.height == buf->vb.height &&
                                   prev->fmt       == buf->fmt) {
-                               list_del(&buf->vb.queue);
-                               list_add_tail(&buf->vb.queue,&q->active);
+                               list_move_tail(&buf->vb.queue, &q->active);
                                buf->vb.state = VIDEOBUF_ACTIVE;
                                buf->count    = q->count++;
                                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
index 44ffc8b3d45f9f7a586404a0b37e8520ae804fa0..ba0dba4a4d224881fb8f953fcba75aa21e620afb 100644 (file)
@@ -94,13 +94,13 @@ enum cx8802_board_access {
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
-static unsigned int inline norm_maxw(v4l2_std_id norm)
+static inline unsigned int norm_maxw(v4l2_std_id norm)
 {
        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
 }
 
 
-static unsigned int inline norm_maxh(v4l2_std_id norm)
+static inline unsigned int norm_maxh(v4l2_std_id norm)
 {
        return (norm & V4L2_STD_625_50) ? 576 : 480;
 }
index a609b3a9b14695bfff2a3e53a387c241e4b38107..f288ffcc4b6bb9004941d75830c2b90e393d2565 100644 (file)
@@ -736,7 +736,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
+static int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
 {
        struct rc_dev *dev;
        int err = -ENOMEM;
@@ -776,7 +776,7 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
        return 0;
 }
 
-void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
+static void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
 {
        rc_unregister_device(dm1105->ir.dev);
 }
@@ -1128,8 +1128,10 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
        INIT_WORK(&dev->work, dm1105_dmx_buffer);
        sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
        dev->wq = create_singlethread_workqueue(dev->wqn);
-       if (!dev->wq)
+       if (!dev->wq) {
+               ret = -ENOMEM;
                goto err_dvb_net;
+       }
 
        ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED,
                                                DRIVER_NAME, dev);
index 8deab1629b3baca0d7b5999c43ef0f6869beaca7..4a221c693995e858b1d08cdcbc47fed6b0ec7e57 100644 (file)
@@ -205,7 +205,7 @@ err_exit:
        return ret;
 }
 
-int ivtv_alsa_load(struct ivtv *itv)
+static int __init ivtv_alsa_load(struct ivtv *itv)
 {
        struct v4l2_device *v4l2_dev = &itv->v4l2_dev;
        struct ivtv_stream *s;
index f7022bd58ffddcc5ffe3c137bf834b9b0437d66a..e1863dbf4edcaca3376321b116d58b2606e2252c 100644 (file)
@@ -37,6 +37,7 @@
 #include "ivtv-streams.h"
 #include "ivtv-fileops.h"
 #include "ivtv-alsa.h"
+#include "ivtv-alsa-pcm.h"
 
 static unsigned int pcm_debug;
 module_param(pcm_debug, int, 0644);
@@ -69,8 +70,9 @@ static struct snd_pcm_hardware snd_ivtv_hw_capture = {
        .periods_max = 98,              /* 12544, */
 };
 
-void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc, u8 *pcm_data,
-                                size_t num_bytes)
+static void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc,
+                                       u8 *pcm_data,
+                                       size_t num_bytes)
 {
        struct snd_pcm_substream *substream;
        struct snd_pcm_runtime *runtime;
index 5ab18319ea4db5ab3d6df28a8e634994e0068c10..23dfe0d124004c1c6bf693caedb967b7991c5c7a 100644 (file)
@@ -21,7 +21,3 @@
  */
 
 int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc);
-
-/* Used by ivtv driver to announce the PCM data to the module */
-void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *card, u8 *pcm_data,
-                                size_t num_bytes);
index 6ec7705af55592015ed8ca07fc8e311866077d69..68387d4369d66f5260f9582db11f0f76dc8b6ccc 100644 (file)
@@ -276,7 +276,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
 }
 
 /* Try to restart the card & restore previous settings */
-int ivtv_firmware_restart(struct ivtv *itv)
+static int ivtv_firmware_restart(struct ivtv *itv)
 {
        int rc = 0;
        v4l2_std_id std;
index d47f41a0ef66482dde6eec7437120b8ec462862e..46e262becb6728615fad39494aea4bf48b978f2c 100644 (file)
@@ -200,21 +200,21 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
                init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
                init_data->internal_get_key_func =
                                        IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
-               init_data->type = RC_TYPE_OTHER;
+               init_data->type = RC_BIT_OTHER;
                init_data->name = "AVerMedia AVerTV card";
                break;
        case IVTV_HW_I2C_IR_RX_HAUP_EXT:
        case IVTV_HW_I2C_IR_RX_HAUP_INT:
                init_data->ir_codes = RC_MAP_HAUPPAUGE;
                init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-               init_data->type = RC_TYPE_RC5;
+               init_data->type = RC_BIT_RC5;
                init_data->name = itv->card_name;
                break;
        case IVTV_HW_Z8F0811_IR_RX_HAUP:
                /* Default to grey remote */
                init_data->ir_codes = RC_MAP_HAUPPAUGE;
                init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-               init_data->type = RC_TYPE_RC5;
+               init_data->type = RC_BIT_RC5;
                init_data->name = itv->card_name;
                break;
        case IVTV_HW_I2C_IR_RX_ADAPTEC:
@@ -222,7 +222,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
                init_data->name = itv->card_name;
                /* FIXME: The protocol and RC_MAP needs to be corrected */
                init_data->ir_codes = RC_MAP_EMPTY;
-               init_data->type = RC_TYPE_UNKNOWN;
+               init_data->type = RC_BIT_UNKNOWN;
                break;
        }
 
index 949ae230e119b80caae93490186613d51bd5e151..7a8b0d0b6127aefbc1281e30108c2ef1050e9e79 100644 (file)
@@ -993,7 +993,7 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
        v4l2_std_id std;
        int i;
 
-       if (inp < 0 || inp >= itv->nof_inputs)
+       if (inp >= itv->nof_inputs)
                return -EINVAL;
 
        if (inp == itv->active_input) {
@@ -1168,7 +1168,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
        }
 }
 
-int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
 {
        struct ivtv *itv = fh2id(fh)->itv;
 
index db6d54d3fec0497ddaf61cfda0d092bf1ffc2e02..0e5252e5c0ef86e1a0ce4af1d25ee9d52dc7aa42 100644 (file)
@@ -18,6 +18,8 @@
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#if 0 /* Currently unused */
+
 #include <media/rc-core.h>
 #include <linux/pci.h>
 
@@ -150,10 +152,11 @@ out:
        return err;
 }
 
-int mantis_exit(struct mantis_pci *mantis)
+int mantis_init_exit(struct mantis_pci *mantis)
 {
        rc_unregister_device(mantis->rc);
        rc_map_unregister(&ir_mantis_map);
        return 0;
 }
 
+#endif
index 85e977861b4a68a8bbb44d76c9b6a010ec250c3f..a7071921863194d07b5542c5564c4f26c4af6cda 100644 (file)
@@ -61,7 +61,7 @@ static struct {
 
 #define UART_MAX_BUF                   16
 
-int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
+static int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
 {
        struct mantis_hwconfig *config = mantis->hwconfig;
        u32 stat = 0, i;
index ad013e93ed11d7bd05638ebf7eb5a398c4631244..115003e8d19d453f30a2db59664d3a561c614116 100644 (file)
@@ -83,7 +83,7 @@ u8 lgtdqcs001f_inittab[] = {
 #define MANTIS_MODEL_NAME      "VP-1033"
 #define MANTIS_DEV_TYPE                "DVB-S/DSS"
 
-int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
+static int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mantis_pci *mantis       = fe->dvb->priv;
@@ -115,8 +115,8 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
        return 0;
 }
 
-int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
-                               u32 srate, u32 ratio)
+static int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
+                                      u32 srate, u32 ratio)
 {
        u8 aclk = 0;
        u8 bclk = 0;
index e5a76da860816897ff7740b905f16015d71aadc0..ae7d32027bf726e0e73499880a61a07187fa6744 100644 (file)
@@ -1945,7 +1945,7 @@ static struct pci_driver meye_driver = {
 static int __init meye_init(void)
 {
        gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
-       if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE)
+       if (gbufsize > MEYE_MAX_BUFSIZE)
                gbufsize = MEYE_MAX_BUFSIZE;
        gbufsize = PAGE_ALIGN(gbufsize);
        printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
index 96a13ed197d0856389a1bd9f7cbde4ca895dfbd8..b38bce529566cdaa02b87b2855674ba5a03dd90e 100644 (file)
@@ -425,8 +425,10 @@ static int ReadEEProm(struct i2c_adapter *adapter,
                status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
                if (!status) {
                        *pLength = EETag[2];
+#if 0
                        if (Length < EETag[2])
-                               ; /*status=STATUS_BUFFER_OVERFLOW; */
+                               status = STATUS_BUFFER_OVERFLOW;
+#endif
                }
        }
        return status;
index c8e0d5b99d4c0d106bd02078ab1b678176d57b0d..8eeec4f50ccb4103d2db272b3c1bc6d7b2608f18 100644 (file)
@@ -752,8 +752,8 @@ void set_transfer(struct ngene_channel *chan, int state)
                if (chan->mode & NGENE_IO_TSIN)
                        chan->pBufferExchange = tsin_exchange;
                spin_unlock_irq(&chan->state_lock);
-       } else
-               ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+       }
+               /* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
                           ngreadl(0x9310)); */
 
        ret = ngene_command_stream_control(dev, chan->number,
@@ -1691,7 +1691,8 @@ int __devinit ngene_probe(struct pci_dev *pci_dev,
        dev->i2c_current_bus = -1;
 
        /* Register DVB adapters and devices for both channels */
-       if (init_channels(dev) < 0)
+       stat = init_channels(dev);
+       if (stat < 0)
                goto fail2;
 
        return 0;
index f2b37e05b96479e7f534537a3208d120b408f661..8976d0e65813d26d7c2761d7172fd7549899d1d4 100644 (file)
@@ -944,8 +944,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 
        /* board config */
        dev->board = pci_id->driver_data;
-       if (card[dev->nr] >= 0 &&
-           card[dev->nr] < saa7134_bcount)
+       if ((unsigned)card[dev->nr] < saa7134_bcount)
                dev->board = card[dev->nr];
        if (SAA7134_BOARD_UNKNOWN == dev->board)
                must_configure_manually(0);
index 0f78f5e537e22723a26d1a8036e69ed3e5cdd5e3..e761262f74750efe089cfd163d87eb0b2188909e 100644 (file)
@@ -990,7 +990,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
                dev->init_data.name = "BeholdTV";
                dev->init_data.get_key = get_key_beholdm6xx;
                dev->init_data.ir_codes = RC_MAP_BEHOLD;
-               dev->init_data.type = RC_TYPE_NEC;
+               dev->init_data.type = RC_BIT_NEC;
                info.addr = 0x2d;
                break;
        case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
index 4a77124ee70e2cbda80a414413a85346b7a832c3..3abf52711e132cfa24e8b4e16bf198eb5cc35cc3 100644 (file)
@@ -2511,7 +2511,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
        /* sanitycheck insmod options */
        if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
                gbuffers = 2;
-       if (gbufsize < 0 || gbufsize > gbufsize_max)
+       if (gbufsize > gbufsize_max)
                gbufsize = gbufsize_max;
        gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
 
index eff7135cf0e8999beb790f0c406f0d7fdd1d772e..e042963d377d0c8dc9b7c6d94225f1ccb5983549 100644 (file)
@@ -165,7 +165,7 @@ int saa7164_api_set_vbi_format(struct saa7164_port *port)
        return ret;
 }
 
-int saa7164_api_set_gop_size(struct saa7164_port *port)
+static int saa7164_api_set_gop_size(struct saa7164_port *port)
 {
        struct saa7164_dev *dev = port->dev;
        struct tmComResEncVideoGopStructure gs;
@@ -619,7 +619,7 @@ int saa7164_api_get_videomux(struct saa7164_port *port)
        return ret;
 }
 
-int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
+static int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
 {
        struct saa7164_dev *dev = port->dev;
 
@@ -822,8 +822,8 @@ int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
                &reg[0], 128, buf);
 }
 
-int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
-       struct saa7164_port *port)
+static int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
+                                         struct saa7164_port *port)
 {
        struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc;
 
@@ -858,9 +858,10 @@ int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
        return 0;
 }
 
-int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
-       struct saa7164_port *port,
-       struct tmComResTSFormatDescrHeader *tsfmt)
+static int
+saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
+                                  struct saa7164_port *port,
+                                  struct tmComResTSFormatDescrHeader *tsfmt)
 {
        dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
        dprintk(DBGLVL_API, "    bDataOffset  = 0x%x\n", tsfmt->bDataOffset);
@@ -892,9 +893,10 @@ int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
        return 0;
 }
 
-int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
-       struct saa7164_port *port,
-       struct tmComResPSFormatDescrHeader *fmt)
+static int
+saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
+                                  struct saa7164_port *port,
+                                  struct tmComResPSFormatDescrHeader *fmt)
 {
        dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", fmt->bFormatIndex);
        dprintk(DBGLVL_API, "    wPacketLength= 0x%x\n", fmt->wPacketLength);
@@ -925,7 +927,7 @@ int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
        return 0;
 }
 
-int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
+static int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
 {
        struct saa7164_port *tsport = NULL;
        struct saa7164_port *encport = NULL;
@@ -1486,7 +1488,7 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
        return ret == SAA_OK ? 0 : -EIO;
 }
 
-int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
+static int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
        u8 pin, u8 state)
 {
        int ret;
index a7f58a9987522c06a45dfcaf3f45ab138f8c3699..5f6f3094c44ecc36a23cb64eba4f38f939a36cb5 100644 (file)
@@ -81,7 +81,7 @@ void saa7164_bus_dump(struct saa7164_dev *dev)
 }
 
 /* Intensionally throw a BUG() if the state of the message bus looks corrupt */
-void saa7164_bus_verify(struct saa7164_dev *dev)
+static void saa7164_bus_verify(struct saa7164_dev *dev)
 {
        struct tmComResBusInfo *b = &dev->bus;
        int bug = 0;
@@ -106,8 +106,8 @@ void saa7164_bus_verify(struct saa7164_dev *dev)
        }
 }
 
-void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m,
-       void *buf)
+static void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo *m,
+                               void *buf)
 {
        dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
        dprintk(DBGLVL_BUS, " .id               = %d\n",   m->id);
index 62fac7f9d04e14201fe140a20468a283fcb7afa9..cfabcbacc33dd26982c41d28ddebd9ebfaf103b7 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "saa7164.h"
 
-int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
+static int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
 {
        int i, ret = -1;
 
@@ -42,7 +42,7 @@ int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
        return ret;
 }
 
-void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
+static void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
 {
        mutex_lock(&dev->lock);
        if ((dev->cmds[seqno].inuse == 1) &&
@@ -54,7 +54,7 @@ void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
        mutex_unlock(&dev->lock);
 }
 
-void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
+static void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
 {
        mutex_lock(&dev->lock);
        if ((dev->cmds[seqno].inuse == 1) &&
@@ -64,7 +64,7 @@ void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
        mutex_unlock(&dev->lock);
 }
 
-u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
+static u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
 {
        int ret = 0;
 
@@ -132,7 +132,7 @@ int saa7164_irq_dequeue(struct saa7164_dev *dev)
 
 /* Commands to the f/w get marshelled to/from this code then onto the PCI
  * -bus/c running buffer. */
-int saa7164_cmd_dequeue(struct saa7164_dev *dev)
+static int saa7164_cmd_dequeue(struct saa7164_dev *dev)
 {
        int loop = 1;
        int ret;
@@ -186,8 +186,8 @@ int saa7164_cmd_dequeue(struct saa7164_dev *dev)
        return SAA_OK;
 }
 
-int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
-       void *buf)
+static int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
+                          void *buf)
 {
        struct tmComResBusInfo *bus = &dev->bus;
        u8 cmd_sent;
@@ -259,7 +259,7 @@ out:
 /* Wait for a signal event, without holding a mutex. Either return TIMEOUT if
  * the event never occurred, or SAA_OK if it was signaled during the wait.
  */
-int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
+static int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
 {
        wait_queue_head_t *q = NULL;
        int ret = SAA_BUS_TIMEOUT;
index 2c9ad878bef3dedab9c91a19019d7443d151affb..063047f567669f1bdc6c33bcfdca33528d56f5a3 100644 (file)
@@ -410,7 +410,7 @@ static void saa7164_work_enchandler(struct work_struct *w)
                } else
                        rp = (port->last_svc_rp + 1) % 8;
 
-               if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
+               if (rp > (port->hwcfg.buffercount - 1)) {
                        printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
                        break;
                }
@@ -486,7 +486,7 @@ static void saa7164_work_vbihandler(struct work_struct *w)
                } else
                        rp = (port->last_svc_rp + 1) % 8;
 
-               if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
+               if (rp > (port->hwcfg.buffercount - 1)) {
                        printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
                        break;
                }
index a9ed686ad08a55acd270675359215f203f24d9c8..994018e2d0d611d0d2a34947b80469ce4448068e 100644 (file)
@@ -1101,7 +1101,8 @@ static int fops_release(struct file *file)
        return 0;
 }
 
-struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
+static struct
+saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
 {
        struct saa7164_user_buffer *ubuf = NULL;
        struct saa7164_dev *dev = port->dev;
@@ -1287,8 +1288,8 @@ static const struct v4l2_file_operations mpeg_fops = {
        .unlocked_ioctl = video_ioctl2,
 };
 
-int saa7164_g_chip_ident(struct file *file, void *fh,
-       struct v4l2_dbg_chip_ident *chip)
+static int saa7164_g_chip_ident(struct file *file, void *fh,
+                               struct v4l2_dbg_chip_ident *chip)
 {
        struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
        struct saa7164_dev *dev = port->dev;
@@ -1297,8 +1298,8 @@ int saa7164_g_chip_ident(struct file *file, void *fh,
        return 0;
 }
 
-int saa7164_g_register(struct file *file, void *fh,
-       struct v4l2_dbg_register *reg)
+static int saa7164_g_register(struct file *file, void *fh,
+                             struct v4l2_dbg_register *reg)
 {
        struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
        struct saa7164_dev *dev = port->dev;
@@ -1310,8 +1311,8 @@ int saa7164_g_register(struct file *file, void *fh,
        return 0;
 }
 
-int saa7164_s_register(struct file *file, void *fh,
-       struct v4l2_dbg_register *reg)
+static int saa7164_s_register(struct file *file, void *fh,
+                             struct v4l2_dbg_register *reg)
 {
        struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
        struct saa7164_dev *dev = port->dev;
index a266bf0169e6a7d339dd7e946f536a25a3915918..86763203d61dba58d19c0eaba9ab87bb7de237c6 100644 (file)
@@ -37,7 +37,7 @@ struct fw_header {
        u32     version;
 };
 
-int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
+static int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
 {
        u32 timeout = SAA_DEVICE_TIMEOUT;
        while ((saa7164_readl(reg) & 0x01) == 0) {
@@ -53,7 +53,7 @@ int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
        return 0;
 }
 
-int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
+static int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
 {
        u32 timeout = SAA_DEVICE_TIMEOUT;
        while (saa7164_readl(reg) & 0x01) {
@@ -71,8 +71,8 @@ int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
 
 /* TODO: move dlflags into dev-> and change to write/readl/b */
 /* TODO: Excessive levels of debug */
-int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
-       u32 dlflags, u8 *dst, u32 dstsize)
+static int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
+                                u32 dlflags, u8 *dst, u32 dstsize)
 {
        u32 reg, timeout, offset;
        u8 *srcbuf = NULL;
index d8e6c8f1407928cad755ddb2418ad53e610ba820..b4532299c0edf54247e6d7065ef9db03a23ce9c3 100644 (file)
@@ -984,7 +984,8 @@ out:
        return ret;
 }
 
-int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
+static int saa7164_vbi_fmt(struct file *file, void *priv,
+                          struct v4l2_format *f)
 {
        /* ntsc */
        f->fmt.vbi.samples_per_line = 1600;
@@ -1047,7 +1048,8 @@ static int fops_release(struct file *file)
        return 0;
 }
 
-struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
+static struct
+saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
 {
        struct saa7164_user_buffer *ubuf = NULL;
        struct saa7164_dev *dev = port->dev;
index 88b3b2d6cc0e9dbcbf04d50987e40b0576b9c6ae..a378662b1dcfce4450f3d0834f72901ac0a63c4c 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/netdevice.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/time.h>
 
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
index 12ddb53c58dcedf00f5229e229f484238dec363e..1f8b1bb0bf9fb39b9881d9bec07e9c604d913e9f 100644 (file)
@@ -1477,8 +1477,8 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
 
        if (saa7113_init(budget_av) == 0) {
                budget_av->has_saa7113 = 1;
-
-               if (0 != saa7146_vv_init(dev, &vv_data)) {
+               err = saa7146_vv_init(dev, &vv_data);
+               if (err != 0) {
                        /* fixme: proper cleanup here */
                        ERR("cannot init vv subsystem\n");
                        return err;
index 181c7686e412aa485e755867d8fad8e7f5f13bf8..3dcfea612c42975615e7d95f5f613918d8d547d1 100644 (file)
@@ -109,6 +109,18 @@ config VIDEO_OMAP3_DEBUG
        ---help---
          Enable debug messages on OMAP 3 camera controller driver.
 
+config VIDEO_S3C_CAMIF
+       tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       depends on (PLAT_S3C64XX || PLAT_S3C24XX) && PM_RUNTIME
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         This is a v4l2 driver for s3c24xx and s3c64xx SoC series camera
+         host interface (CAMIF).
+
+         To compile this driver as a module, choose M here: the module
+         will be called s3c-camif.
+
 source "drivers/media/platform/soc_camera/Kconfig"
 source "drivers/media/platform/s5p-fimc/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
index baaa55026c8ea7b71d7821fd97606ecb75dc9dfb..4817d280217162ec01b545bcd0164daa1db66b0e 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_VIDEO_CODA)              += coda.o
 
 obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)        += m2m-deinterlace.o
 
+obj-$(CONFIG_VIDEO_S3C_CAMIF)          += s3c-camif/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC)   += s5p-fimc/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)   += s5p-jpeg/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)    += s5p-mfc/
index cb2eb26850b179738b49975ea47d82cada2d0d11..ec476ef5b709bbe8c56e354e6fecb5d3c70902d5 100644 (file)
@@ -1050,19 +1050,7 @@ static struct platform_driver bcap_driver = {
        .probe = bcap_probe,
        .remove = __devexit_p(bcap_remove),
 };
-
-static __init int bcap_init(void)
-{
-       return platform_driver_register(&bcap_driver);
-}
-
-static __exit void bcap_exit(void)
-{
-       platform_driver_unregister(&bcap_driver);
-}
-
-module_init(bcap_init);
-module_exit(bcap_exit);
+module_platform_driver(bcap_driver);
 
 MODULE_DESCRIPTION("Analog Devices blackfin video capture driver");
 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
index cd04ae252c301991d73eebfeb2727e6752d7b9e8..7b8b547f2d51867115f9bf5a510495e6c35baebb 100644 (file)
@@ -1540,7 +1540,7 @@ static irqreturn_t coda_irq_handler(int irq, void *data)
        u32 wr_ptr, start_ptr;
        struct coda_ctx *ctx;
 
-       __cancel_delayed_work(&dev->timeout);
+       cancel_delayed_work(&dev->timeout);
 
        /* read status register to attend the IRQ */
        coda_read(dev, CODA_REG_BIT_INT_STATUS);
@@ -1877,7 +1877,7 @@ static const struct coda_devtype coda_devdata[] = {
 
 static struct platform_device_id coda_platform_ids[] = {
        { .name = "coda-imx27", .driver_data = CODA_IMX27 },
-       { .name = "coda-imx53", .driver_data = CODA_7541 },
+       { .name = "coda-imx53", .driver_data = CODA_IMX53 },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(platform, coda_platform_ids);
index 78e26d24f63754b857d923c727c628b3ee9e5596..3c56037c82fce5e711469b585dbd157da79b01c2 100644 (file)
@@ -101,7 +101,7 @@ config VIDEO_DM644X_VPBE
        tristate "DM644X VPBE HW module"
        depends on ARCH_DAVINCI_DM644x
        select VIDEO_VPSS_SYSTEM
-       select VIDEOBUF_DMA_CONTIG
+       select VIDEOBUF2_DMA_CONTIG
        help
            Enables VPBE modules used for display on a DM644x
            SoC.
index ce0e4131c0672ba882c6a45b819ed7dfe2b960ae..030950dcfb1628d56d0a640e264750da0ea62f45 100644 (file)
@@ -1003,7 +1003,7 @@ static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
                status = PTR_ERR(ccdc_cfg.mclk);
                goto fail_nomap;
        }
-       if (clk_enable(ccdc_cfg.mclk)) {
+       if (clk_prepare_enable(ccdc_cfg.mclk)) {
                status = -ENODEV;
                goto fail_mclk;
        }
@@ -1014,7 +1014,7 @@ static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
                status = PTR_ERR(ccdc_cfg.sclk);
                goto fail_mclk;
        }
-       if (clk_enable(ccdc_cfg.sclk)) {
+       if (clk_prepare_enable(ccdc_cfg.sclk)) {
                status = -ENODEV;
                goto fail_sclk;
        }
@@ -1034,8 +1034,10 @@ static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
        printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
        return 0;
 fail_sclk:
+       clk_disable_unprepare(ccdc_cfg.sclk);
        clk_put(ccdc_cfg.sclk);
 fail_mclk:
+       clk_disable_unprepare(ccdc_cfg.mclk);
        clk_put(ccdc_cfg.mclk);
 fail_nomap:
        iounmap(ccdc_cfg.base_addr);
@@ -1050,6 +1052,8 @@ static int dm355_ccdc_remove(struct platform_device *pdev)
 {
        struct resource *res;
 
+       clk_disable_unprepare(ccdc_cfg.sclk);
+       clk_disable_unprepare(ccdc_cfg.mclk);
        clk_put(ccdc_cfg.mclk);
        clk_put(ccdc_cfg.sclk);
        iounmap(ccdc_cfg.base_addr);
index ee7942b1996ed2fdb11f201891178d29c10317f3..0215ab6ebc909d3ae4b4042aa4c8880223b0beb4 100644 (file)
@@ -994,7 +994,7 @@ static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
                status = PTR_ERR(ccdc_cfg.mclk);
                goto fail_nomap;
        }
-       if (clk_enable(ccdc_cfg.mclk)) {
+       if (clk_prepare_enable(ccdc_cfg.mclk)) {
                status = -ENODEV;
                goto fail_mclk;
        }
@@ -1005,7 +1005,7 @@ static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
                status = PTR_ERR(ccdc_cfg.sclk);
                goto fail_mclk;
        }
-       if (clk_enable(ccdc_cfg.sclk)) {
+       if (clk_prepare_enable(ccdc_cfg.sclk)) {
                status = -ENODEV;
                goto fail_sclk;
        }
@@ -1013,8 +1013,10 @@ static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
        printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
        return 0;
 fail_sclk:
+       clk_disable_unprepare(ccdc_cfg.sclk);
        clk_put(ccdc_cfg.sclk);
 fail_mclk:
+       clk_disable_unprepare(ccdc_cfg.mclk);
        clk_put(ccdc_cfg.mclk);
 fail_nomap:
        iounmap(ccdc_cfg.base_addr);
@@ -1029,6 +1031,8 @@ static int dm644x_ccdc_remove(struct platform_device *pdev)
 {
        struct resource *res;
 
+       clk_disable_unprepare(ccdc_cfg.mclk);
+       clk_disable_unprepare(ccdc_cfg.sclk);
        clk_put(ccdc_cfg.mclk);
        clk_put(ccdc_cfg.sclk);
        iounmap(ccdc_cfg.base_addr);
@@ -1046,8 +1050,8 @@ static int dm644x_ccdc_suspend(struct device *dev)
        /* Disable CCDC */
        ccdc_enable(0);
        /* Disable both master and slave clock */
-       clk_disable(ccdc_cfg.mclk);
-       clk_disable(ccdc_cfg.sclk);
+       clk_disable_unprepare(ccdc_cfg.mclk);
+       clk_disable_unprepare(ccdc_cfg.sclk);
 
        return 0;
 }
@@ -1055,8 +1059,8 @@ static int dm644x_ccdc_suspend(struct device *dev)
 static int dm644x_ccdc_resume(struct device *dev)
 {
        /* Enable both master and slave clock */
-       clk_enable(ccdc_cfg.mclk);
-       clk_enable(ccdc_cfg.sclk);
+       clk_prepare_enable(ccdc_cfg.mclk);
+       clk_prepare_enable(ccdc_cfg.sclk);
        /* Restore CCDC context */
        ccdc_restore_context();
 
index b99d5423e3a8dc16d115c244e6e391f870924c79..2c26c3e1837eb05b974a8e071f62640354264407 100644 (file)
@@ -1053,7 +1053,7 @@ static int __devinit isif_probe(struct platform_device *pdev)
                status = PTR_ERR(isif_cfg.mclk);
                goto fail_mclk;
        }
-       if (clk_enable(isif_cfg.mclk)) {
+       if (clk_prepare_enable(isif_cfg.mclk)) {
                status = -ENODEV;
                goto fail_mclk;
        }
@@ -1125,6 +1125,7 @@ fail_nobase_res:
                i--;
        }
 fail_mclk:
+       clk_disable_unprepare(isif_cfg.mclk);
        clk_put(isif_cfg.mclk);
        vpfe_unregister_ccdc_device(&isif_hw_dev);
        return status;
@@ -1145,6 +1146,8 @@ static int isif_remove(struct platform_device *pdev)
                i++;
        }
        vpfe_unregister_ccdc_device(&isif_hw_dev);
+       clk_disable_unprepare(isif_cfg.mclk);
+       clk_put(isif_cfg.mclk);
        return 0;
 }
 
index 69d7a58c92c3e81191adcd3d227f7352a9e5d4d0..7f5cf9b347b2c40e22f5056a0fe062a31cfabf86 100644 (file)
@@ -612,7 +612,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                        ret =  PTR_ERR(vpbe_dev->dac_clk);
                        goto fail_mutex_unlock;
                }
-               if (clk_enable(vpbe_dev->dac_clk)) {
+               if (clk_prepare_enable(vpbe_dev->dac_clk)) {
                        ret =  -ENODEV;
                        goto fail_mutex_unlock;
                }
@@ -759,8 +759,10 @@ fail_kfree_encoders:
 fail_dev_unregister:
        v4l2_device_unregister(&vpbe_dev->v4l2_dev);
 fail_clk_put:
-       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
+       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
+               clk_disable_unprepare(vpbe_dev->dac_clk);
                clk_put(vpbe_dev->dac_clk);
+       }
 fail_mutex_unlock:
        mutex_unlock(&vpbe_dev->lock);
        return ret;
@@ -777,8 +779,10 @@ fail_mutex_unlock:
 static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
 {
        v4l2_device_unregister(&vpbe_dev->v4l2_dev);
-       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
+       if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
+               clk_disable_unprepare(vpbe_dev->dac_clk);
                clk_put(vpbe_dev->dac_clk);
+       }
 
        kfree(vpbe_dev->amp);
        kfree(vpbe_dev->encoders);
index 161c77650e2f88ea13fedd063c43ef306a734d67..2bfde7958fefb700d948d9635a32ae9c4888ab88 100644 (file)
@@ -47,6 +47,9 @@ static int debug;
 
 module_param(debug, int, 0644);
 
+static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
+                       struct vpbe_layer *layer);
+
 static int venc_is_second_field(struct vpbe_display *disp_dev)
 {
        struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
@@ -73,10 +76,11 @@ static void vpbe_isr_even_field(struct vpbe_display *disp_obj,
        if (layer->cur_frm == layer->next_frm)
                return;
        ktime_get_ts(&timevalue);
-       layer->cur_frm->ts.tv_sec = timevalue.tv_sec;
-       layer->cur_frm->ts.tv_usec = timevalue.tv_nsec / NSEC_PER_USEC;
-       layer->cur_frm->state = VIDEOBUF_DONE;
-       wake_up_interruptible(&layer->cur_frm->done);
+       layer->cur_frm->vb.v4l2_buf.timestamp.tv_sec =
+               timevalue.tv_sec;
+       layer->cur_frm->vb.v4l2_buf.timestamp.tv_usec =
+               timevalue.tv_nsec / NSEC_PER_USEC;
+       vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_DONE);
        /* Make cur_frm pointing to next_frm */
        layer->cur_frm = layer->next_frm;
 }
@@ -99,16 +103,14 @@ static void vpbe_isr_odd_field(struct vpbe_display *disp_obj,
         * otherwise hold on current frame
         * Get next from the buffer queue
         */
-       layer->next_frm = list_entry(
-                               layer->dma_queue.next,
-                               struct  videobuf_buffer,
-                               queue);
+       layer->next_frm = list_entry(layer->dma_queue.next,
+                         struct  vpbe_disp_buffer, list);
        /* Remove that from the buffer queue */
-       list_del(&layer->next_frm->queue);
+       list_del(&layer->next_frm->list);
        spin_unlock(&disp_obj->dma_queue_lock);
        /* Mark state of the frame to active */
-       layer->next_frm->state = VIDEOBUF_ACTIVE;
-       addr = videobuf_to_dma_contig(layer->next_frm);
+       layer->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+       addr = vb2_dma_contig_plane_dma_addr(&layer->next_frm->vb, 0);
        osd_device->ops.start_layer(osd_device,
                        layer->layer_info.id,
                        addr,
@@ -199,39 +201,29 @@ static irqreturn_t venc_isr(int irq, void *arg)
 
 /*
  * vpbe_buffer_prepare()
- * This is the callback function called from videobuf_qbuf() function
+ * This is the callback function called from vb2_qbuf() function
  * the buffer is prepared and user space virtual address is converted into
  * physical address
  */
-static int vpbe_buffer_prepare(struct videobuf_queue *q,
-                                 struct videobuf_buffer *vb,
-                                 enum v4l2_field field)
+static int vpbe_buffer_prepare(struct vb2_buffer *vb)
 {
-       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_queue *q = vb->vb2_queue;
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        unsigned long addr;
-       int ret;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
                                "vpbe_buffer_prepare\n");
 
-       /* If buffer is not initialized, initialize it */
-       if (VIDEOBUF_NEEDS_INIT == vb->state) {
-               vb->width = layer->pix_fmt.width;
-               vb->height = layer->pix_fmt.height;
-               vb->size = layer->pix_fmt.sizeimage;
-               vb->field = field;
-
-               ret = videobuf_iolock(q, vb, NULL);
-               if (ret < 0) {
-                       v4l2_err(&vpbe_dev->v4l2_dev, "Failed to map \
-                               user address\n");
+       if (vb->state != VB2_BUF_STATE_ACTIVE &&
+               vb->state != VB2_BUF_STATE_PREPARED) {
+               vb2_set_plane_payload(vb, 0, layer->pix_fmt.sizeimage);
+               if (vb2_plane_vaddr(vb, 0) &&
+               vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
                        return -EINVAL;
-               }
-
-               addr = videobuf_to_dma_contig(vb);
 
+               addr = vb2_dma_contig_plane_dma_addr(vb, 0);
                if (q->streaming) {
                        if (!IS_ALIGNED(addr, 8)) {
                                v4l2_err(&vpbe_dev->v4l2_dev,
@@ -240,7 +232,6 @@ static int vpbe_buffer_prepare(struct videobuf_queue *q,
                                return -EINVAL;
                        }
                }
-               vb->state = VIDEOBUF_PREPARED;
        }
        return 0;
 }
@@ -249,22 +240,26 @@ static int vpbe_buffer_prepare(struct videobuf_queue *q,
  * vpbe_buffer_setup()
  * This function allocates memory for the buffers
  */
-static int vpbe_buffer_setup(struct videobuf_queue *q,
-                               unsigned int *count,
-                               unsigned int *size)
+static int
+vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                       unsigned int *nbuffers, unsigned int *nplanes,
+                       unsigned int sizes[], void *alloc_ctxs[])
+
 {
        /* Get the file handle object and layer object */
-       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_fh *fh = vb2_get_drv_priv(vq);
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n");
 
-       *size = layer->pix_fmt.sizeimage;
-
        /* Store number of buffers allocated in numbuffer member */
-       if (*count < VPBE_DEFAULT_NUM_BUFS)
-               *count = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
+       if (*nbuffers < VPBE_DEFAULT_NUM_BUFS)
+               *nbuffers = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
+
+       *nplanes = 1;
+       sizes[0] = layer->pix_fmt.sizeimage;
+       alloc_ctxs[0] = layer->alloc_ctx;
 
        return 0;
 }
@@ -273,11 +268,12 @@ static int vpbe_buffer_setup(struct videobuf_queue *q,
  * vpbe_buffer_queue()
  * This function adds the buffer to DMA queue
  */
-static void vpbe_buffer_queue(struct videobuf_queue *q,
-                                struct videobuf_buffer *vb)
+static void vpbe_buffer_queue(struct vb2_buffer *vb)
 {
        /* Get the file handle object and layer object */
-       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+       struct vpbe_disp_buffer *buf = container_of(vb,
+                               struct vpbe_disp_buffer, vb);
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_display *disp = fh->disp_dev;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
@@ -288,39 +284,125 @@ static void vpbe_buffer_queue(struct videobuf_queue *q,
 
        /* add the buffer to the DMA queue */
        spin_lock_irqsave(&disp->dma_queue_lock, flags);
-       list_add_tail(&vb->queue, &layer->dma_queue);
+       list_add_tail(&buf->list, &layer->dma_queue);
        spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
-       /* Change state of the buffer */
-       vb->state = VIDEOBUF_QUEUED;
 }
 
 /*
- * vpbe_buffer_release()
- * This function is called from the videobuf layer to free memory allocated to
+ * vpbe_buf_cleanup()
+ * This function is called from the vb2 layer to free memory allocated to
  * the buffers
  */
-static void vpbe_buffer_release(struct videobuf_queue *q,
-                                  struct videobuf_buffer *vb)
+static void vpbe_buf_cleanup(struct vb2_buffer *vb)
 {
        /* Get the file handle object and layer object */
-       struct vpbe_fh *fh = q->priv_data;
+       struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       struct vpbe_disp_buffer *buf = container_of(vb,
+                                       struct vpbe_disp_buffer, vb);
+       unsigned long flags;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
-                       "vpbe_buffer_release\n");
+                       "vpbe_buf_cleanup\n");
+
+       spin_lock_irqsave(&layer->irqlock, flags);
+       if (vb->state == VB2_BUF_STATE_ACTIVE)
+               list_del_init(&buf->list);
+       spin_unlock_irqrestore(&layer->irqlock, flags);
+}
+
+static void vpbe_wait_prepare(struct vb2_queue *vq)
+{
+       struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpbe_layer *layer = fh->layer;
+
+       mutex_unlock(&layer->opslock);
+}
+
+static void vpbe_wait_finish(struct vb2_queue *vq)
+{
+       struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpbe_layer *layer = fh->layer;
+
+       mutex_lock(&layer->opslock);
+}
+
+static int vpbe_buffer_init(struct vb2_buffer *vb)
+{
+       struct vpbe_disp_buffer *buf = container_of(vb,
+                                       struct vpbe_disp_buffer, vb);
+
+       INIT_LIST_HEAD(&buf->list);
+       return 0;
+}
+
+static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpbe_layer *layer = fh->layer;
+       struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
+
+       /* If buffer queue is empty, return error */
+       if (list_empty(&layer->dma_queue)) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n");
+               return -EINVAL;
+       }
+       /* Get the next frame from the buffer queue */
+       layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
+                               struct vpbe_disp_buffer, list);
+       /* Remove buffer from the buffer queue */
+       list_del(&layer->cur_frm->list);
+       /* Mark state of the current frame to active */
+       layer->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+       /* Initialize field_id and started member */
+       layer->field_id = 0;
+
+       /* Set parameters in OSD and VENC */
+       ret = vpbe_set_osd_display_params(fh->disp_dev, layer);
+       if (ret < 0)
+               return ret;
 
-       if (V4L2_MEMORY_USERPTR != layer->memory)
-               videobuf_dma_contig_free(q, vb);
+       /*
+        * if request format is yuv420 semiplanar, need to
+        * enable both video windows
+        */
+       layer->started = 1;
+       layer->layer_first_int = 1;
+
+       return ret;
+}
+
+static int vpbe_stop_streaming(struct vb2_queue *vq)
+{
+       struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+       struct vpbe_layer *layer = fh->layer;
+
+       if (!vb2_is_streaming(vq))
+               return 0;
+
+       /* release all active buffers */
+       while (!list_empty(&layer->dma_queue)) {
+               layer->next_frm = list_entry(layer->dma_queue.next,
+                                               struct vpbe_disp_buffer, list);
+               list_del(&layer->next_frm->list);
+               vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR);
+       }
 
-       vb->state = VIDEOBUF_NEEDS_INIT;
+       return 0;
 }
 
-static struct videobuf_queue_ops video_qops = {
-       .buf_setup = vpbe_buffer_setup,
+static struct vb2_ops video_qops = {
+       .queue_setup = vpbe_buffer_queue_setup,
+       .wait_prepare = vpbe_wait_prepare,
+       .wait_finish = vpbe_wait_finish,
+       .buf_init = vpbe_buffer_init,
        .buf_prepare = vpbe_buffer_prepare,
+       .start_streaming = vpbe_start_streaming,
+       .stop_streaming = vpbe_stop_streaming,
+       .buf_cleanup = vpbe_buf_cleanup,
        .buf_queue = vpbe_buffer_queue,
-       .buf_release = vpbe_buffer_release,
 };
 
 static
@@ -345,7 +427,7 @@ static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
        unsigned long addr;
        int ret;
 
-       addr = videobuf_to_dma_contig(layer->cur_frm);
+       addr = vb2_dma_contig_plane_dma_addr(&layer->cur_frm->vb, 0);
        /* Set address in the display registers */
        osd_device->ops.start_layer(osd_device,
                                    layer->layer_info.id,
@@ -620,9 +702,12 @@ static int vpbe_display_querycap(struct file *file, void  *priv,
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
        cap->version = VPBE_DISPLAY_VERSION_CODE;
-       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, VPBE_DISPLAY_DRIVER, 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(vpbe_dev->pdev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpbe_dev->pdev));
        strlcpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card));
 
        return 0;
@@ -1161,7 +1246,7 @@ static int vpbe_display_streamoff(struct file *file, void *priv,
        osd_device->ops.disable_layer(osd_device,
                        layer->layer_info.id);
        layer->started = 0;
-       ret = videobuf_streamoff(&layer->buffer_queue);
+       ret = vb2_streamoff(&layer->buffer_queue, buf_type);
 
        return ret;
 }
@@ -1199,46 +1284,15 @@ static int vpbe_display_streamon(struct file *file, void *priv,
        }
 
        /*
-        * Call videobuf_streamon to start streaming
+        * Call vb2_streamon to start streaming
         * in videobuf
         */
-       ret = videobuf_streamon(&layer->buffer_queue);
+       ret = vb2_streamon(&layer->buffer_queue, buf_type);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-               "error in videobuf_streamon\n");
+               "error in vb2_streamon\n");
                return ret;
        }
-       /* If buffer queue is empty, return error */
-       if (list_empty(&layer->dma_queue)) {
-               v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n");
-               goto streamoff;
-       }
-       /* Get the next frame from the buffer queue */
-       layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
-                               struct videobuf_buffer, queue);
-       /* Remove buffer from the buffer queue */
-       list_del(&layer->cur_frm->queue);
-       /* Mark state of the current frame to active */
-       layer->cur_frm->state = VIDEOBUF_ACTIVE;
-       /* Initialize field_id and started member */
-       layer->field_id = 0;
-
-       /* Set parameters in OSD and VENC */
-       ret = vpbe_set_osd_display_params(disp_dev, layer);
-       if (ret < 0)
-               goto streamoff;
-
-       /*
-        * if request format is yuv420 semiplanar, need to
-        * enable both video windows
-        */
-       layer->started = 1;
-
-       layer->layer_first_int = 1;
-
-       return ret;
-streamoff:
-       ret = videobuf_streamoff(&layer->buffer_queue);
        return ret;
 }
 
@@ -1265,10 +1319,10 @@ static int vpbe_display_dqbuf(struct file *file, void *priv,
        }
        if (file->f_flags & O_NONBLOCK)
                /* Call videobuf_dqbuf for non blocking mode */
-               ret = videobuf_dqbuf(&layer->buffer_queue, buf, 1);
+               ret = vb2_dqbuf(&layer->buffer_queue, buf, 1);
        else
                /* Call videobuf_dqbuf for blocking mode */
-               ret = videobuf_dqbuf(&layer->buffer_queue, buf, 0);
+               ret = vb2_dqbuf(&layer->buffer_queue, buf, 0);
 
        return ret;
 }
@@ -1295,7 +1349,7 @@ static int vpbe_display_qbuf(struct file *file, void *priv,
                return -EACCES;
        }
 
-       return videobuf_qbuf(&layer->buffer_queue, p);
+       return vb2_qbuf(&layer->buffer_queue, p);
 }
 
 static int vpbe_display_querybuf(struct file *file, void *priv,
@@ -1304,7 +1358,6 @@ static int vpbe_display_querybuf(struct file *file, void *priv,
        struct vpbe_fh *fh = file->private_data;
        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_QUERYBUF, layer id = %d\n",
@@ -1314,11 +1367,8 @@ static int vpbe_display_querybuf(struct file *file, void *priv,
                v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
                return -EINVAL;
        }
-
-       /* Call videobuf_querybuf to get information */
-       ret = videobuf_querybuf(&layer->buffer_queue, buf);
-
-       return ret;
+       /* Call vb2_querybuf to get information */
+       return vb2_querybuf(&layer->buffer_queue, buf);
 }
 
 static int vpbe_display_reqbufs(struct file *file, void *priv,
@@ -1327,8 +1377,8 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
        struct vpbe_fh *fh = file->private_data;
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       struct vb2_queue *q;
        int ret;
-
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_reqbufs\n");
 
        if (V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
@@ -1342,15 +1392,26 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
                return -EBUSY;
        }
        /* Initialize videobuf queue as per the buffer type */
-       videobuf_queue_dma_contig_init(&layer->buffer_queue,
-                               &video_qops,
-                               vpbe_dev->pdev,
-                               &layer->irqlock,
-                               V4L2_BUF_TYPE_VIDEO_OUTPUT,
-                               layer->pix_fmt.field,
-                               sizeof(struct videobuf_buffer),
-                               fh, NULL);
+       layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev);
+       if (!layer->alloc_ctx) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n");
+               return -EINVAL;
+       }
+       q = &layer->buffer_queue;
+       memset(q, 0, sizeof(*q));
+       q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       q->io_modes = VB2_MMAP | VB2_USERPTR;
+       q->drv_priv = fh;
+       q->ops = &video_qops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
 
+       ret = vb2_queue_init(q);
+       if (ret) {
+               v4l2_err(&vpbe_dev->v4l2_dev, "vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(layer->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed = 1;
        /* Increment io usrs member of layer object to 1 */
@@ -1360,9 +1421,7 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
        /* Initialize buffer queue */
        INIT_LIST_HEAD(&layer->dma_queue);
        /* Allocate buffers */
-       ret = videobuf_reqbufs(&layer->buffer_queue, req_buf);
-
-       return ret;
+       return vb2_reqbufs(q, req_buf);
 }
 
 /*
@@ -1381,7 +1440,7 @@ static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
 
        if (mutex_lock_interruptible(&layer->opslock))
                return -ERESTARTSYS;
-       ret = videobuf_mmap_mapper(&layer->buffer_queue, vma);
+       ret = vb2_mmap(&layer->buffer_queue, vma);
        mutex_unlock(&layer->opslock);
        return ret;
 }
@@ -1398,7 +1457,7 @@ static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
        if (layer->started) {
                mutex_lock(&layer->opslock);
-               err = videobuf_poll_stream(filep, &layer->buffer_queue, wait);
+               err = vb2_poll(&layer->buffer_queue, filep, wait);
                mutex_unlock(&layer->opslock);
        }
        return err;
@@ -1488,8 +1547,8 @@ static int vpbe_display_release(struct file *file)
                                layer->layer_info.id);
                layer->started = 0;
                /* Free buffers allocated */
-               videobuf_queue_cancel(&layer->buffer_queue);
-               videobuf_mmap_free(&layer->buffer_queue);
+               vb2_queue_release(&layer->buffer_queue);
+               vb2_dma_contig_cleanup_ctx(&layer->buffer_queue);
        }
 
        /* Decrement layer usrs counter */
index bba299dbf3967c6e7e708f9631eb9853912d1833..707f243f810d806fcc5efc04a13b66bd2a47ca63 100644 (file)
@@ -62,7 +62,7 @@ static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset)
 {
        struct osd_state *osd = sd;
 
-       u32 addr = osd->osd_base + offset;
+       void __iomem *addr = osd->osd_base + offset;
        u32 val = readl(addr) | mask;
 
        writel(val, addr);
@@ -74,7 +74,7 @@ static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset)
 {
        struct osd_state *osd = sd;
 
-       u32 addr = osd->osd_base + offset;
+       void __iomem *addr = osd->osd_base + offset;
        u32 val = readl(addr) & ~mask;
 
        writel(val, addr);
@@ -87,7 +87,7 @@ static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val,
 {
        struct osd_state *osd = sd;
 
-       u32 addr = osd->osd_base + offset;
+       void __iomem *addr = osd->osd_base + offset;
        u32 new_val = (readl(addr) & ~mask) | (val & mask);
 
        writel(new_val, addr);
@@ -1559,8 +1559,7 @@ static int osd_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto free_mem;
        }
-       osd->osd_base = (unsigned long)ioremap_nocache(res->start,
-                                                       osd->osd_size);
+       osd->osd_base = ioremap_nocache(res->start, osd->osd_size);
        if (!osd->osd_base) {
                dev_err(osd->dev, "Unable to map the OSD region\n");
                ret = -ENODEV;
index cff3c0ab501f6751c745fbdf9461a3dc745f837e..0d6cc8e4deb28889ea2286b0e84cb8a194475dd2 100644 (file)
@@ -444,7 +444,7 @@ static int __devinit vpif_probe(struct platform_device *pdev)
                status = PTR_ERR(vpif_clk);
                goto clk_fail;
        }
-       clk_enable(vpif_clk);
+       clk_prepare_enable(vpif_clk);
 
        spin_lock_init(&vpif_lock);
        dev_info(&pdev->dev, "vpif probe success\n");
@@ -460,7 +460,7 @@ fail:
 static int __devexit vpif_remove(struct platform_device *pdev)
 {
        if (vpif_clk) {
-               clk_disable(vpif_clk);
+               clk_disable_unprepare(vpif_clk);
                clk_put(vpif_clk);
        }
 
@@ -472,13 +472,13 @@ static int __devexit vpif_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int vpif_suspend(struct device *dev)
 {
-       clk_disable(vpif_clk);
+       clk_disable_unprepare(vpif_clk);
        return 0;
 }
 
 static int vpif_resume(struct device *dev)
 {
-       clk_enable(vpif_clk);
+       clk_prepare_enable(vpif_clk);
        return 0;
 }
 
index fcabc023885d06c66b33db117d5c744f138a2e45..a409ccefb38073ec2c67d74d96ea53079bc6f38a 100644 (file)
@@ -201,13 +201,16 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)
        struct vpif_cap_buffer *buf = container_of(vb,
                                struct vpif_cap_buffer, vb);
        struct common_obj *common;
+       unsigned long flags;
 
        common = &ch->common[VPIF_VIDEO_INDEX];
 
        vpif_dbg(2, debug, "vpif_buffer_queue\n");
 
+       spin_lock_irqsave(&common->irqlock, flags);
        /* add the buffer to the DMA queue */
        list_add_tail(&buf->list, &common->dma_queue);
+       spin_unlock_irqrestore(&common->irqlock, flags);
 }
 
 /**
@@ -278,10 +281,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
        struct vpif_params *vpif = &ch->vpifparams;
        unsigned long addr = 0;
+       unsigned long flags;
        int ret;
 
-               /* If buffer queue is empty, return error */
+       /* If buffer queue is empty, return error */
+       spin_lock_irqsave(&common->irqlock, flags);
        if (list_empty(&common->dma_queue)) {
+               spin_unlock_irqrestore(&common->irqlock, flags);
                vpif_dbg(1, debug, "buffer queue is empty\n");
                return -EIO;
        }
@@ -291,6 +297,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                                    struct vpif_cap_buffer, list);
        /* Remove buffer from the buffer queue */
        list_del(&common->cur_frm->list);
+       spin_unlock_irqrestore(&common->irqlock, flags);
        /* Mark state of the current frame to active */
        common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
        /* Initialize field_id and started member */
@@ -362,6 +369,7 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
        struct vpif_fh *fh = vb2_get_drv_priv(vq);
        struct channel_obj *ch = fh->channel;
        struct common_obj *common;
+       unsigned long flags;
 
        if (!vb2_is_streaming(vq))
                return 0;
@@ -369,12 +377,14 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
        common = &ch->common[VPIF_VIDEO_INDEX];
 
        /* release all active buffers */
+       spin_lock_irqsave(&common->irqlock, flags);
        while (!list_empty(&common->dma_queue)) {
                common->next_frm = list_entry(common->dma_queue.next,
                                                struct vpif_cap_buffer, list);
                list_del(&common->next_frm->list);
                vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
        }
+       spin_unlock_irqrestore(&common->irqlock, flags);
 
        return 0;
 }
@@ -420,10 +430,12 @@ static void vpif_schedule_next_buffer(struct common_obj *common)
 {
        unsigned long addr = 0;
 
+       spin_lock(&common->irqlock);
        common->next_frm = list_entry(common->dma_queue.next,
                                     struct vpif_cap_buffer, list);
        /* Remove that buffer from the buffer queue */
        list_del(&common->next_frm->list);
+       spin_unlock(&common->irqlock);
        common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
        addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0);
 
@@ -468,8 +480,12 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
                /* Check the field format */
                if (1 == ch->vpifparams.std_info.frm_fmt) {
                        /* Progressive mode */
-                       if (list_empty(&common->dma_queue))
+                       spin_lock(&common->irqlock);
+                       if (list_empty(&common->dma_queue)) {
+                               spin_unlock(&common->irqlock);
                                continue;
+                       }
+                       spin_unlock(&common->irqlock);
 
                        if (!channel_first_int[i][channel_id])
                                vpif_process_buffer_complete(common);
@@ -513,9 +529,13 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
                                vpif_process_buffer_complete(common);
                        } else if (1 == fid) {
                                /* odd field */
+                               spin_lock(&common->irqlock);
                                if (list_empty(&common->dma_queue) ||
-                                   (common->cur_frm != common->next_frm))
+                                   (common->cur_frm != common->next_frm)) {
+                                       spin_unlock(&common->irqlock);
                                        continue;
+                               }
+                               spin_unlock(&common->irqlock);
 
                                vpif_schedule_next_buffer(common);
                        }
@@ -1004,9 +1024,9 @@ static int vpif_reqbufs(struct file *file, void *priv,
 
        /* Initialize videobuf2 queue as per the buffer type */
        common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev);
-       if (!common->alloc_ctx) {
+       if (IS_ERR(common->alloc_ctx)) {
                vpif_err("Failed to get the context\n");
-               return -EINVAL;
+               return PTR_ERR(common->alloc_ctx);
        }
        q = &common->buffer_queue;
        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1715,7 +1735,7 @@ vpif_enum_dv_timings(struct file *file, void *priv,
        int ret;
 
        ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
                return -EINVAL;
        return ret;
 }
@@ -1735,7 +1755,7 @@ vpif_query_dv_timings(struct file *file, void *priv,
        int ret;
 
        ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
                return -ENODATA;
        return ret;
 }
index b716fbd4241f8599f90c8dbf7caf4b99e0f338bb..9f2b603be9c9b319d56b72bd99c3028df07632aa 100644 (file)
@@ -177,11 +177,14 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)
                                struct vpif_disp_buffer, vb);
        struct channel_obj *ch = fh->channel;
        struct common_obj *common;
+       unsigned long flags;
 
        common = &ch->common[VPIF_VIDEO_INDEX];
 
        /* add the buffer to the DMA queue */
+       spin_lock_irqsave(&common->irqlock, flags);
        list_add_tail(&buf->list, &common->dma_queue);
+       spin_unlock_irqrestore(&common->irqlock, flags);
 }
 
 /*
@@ -246,10 +249,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
        struct vpif_params *vpif = &ch->vpifparams;
        unsigned long addr = 0;
+       unsigned long flags;
        int ret;
 
        /* If buffer queue is empty, return error */
+       spin_lock_irqsave(&common->irqlock, flags);
        if (list_empty(&common->dma_queue)) {
+               spin_unlock_irqrestore(&common->irqlock, flags);
                vpif_err("buffer queue is empty\n");
                return -EIO;
        }
@@ -260,6 +266,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                                       struct vpif_disp_buffer, list);
 
        list_del(&common->cur_frm->list);
+       spin_unlock_irqrestore(&common->irqlock, flags);
        /* Mark state of the current frame to active */
        common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
 
@@ -330,6 +337,7 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
        struct vpif_fh *fh = vb2_get_drv_priv(vq);
        struct channel_obj *ch = fh->channel;
        struct common_obj *common;
+       unsigned long flags;
 
        if (!vb2_is_streaming(vq))
                return 0;
@@ -337,12 +345,14 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
        common = &ch->common[VPIF_VIDEO_INDEX];
 
        /* release all active buffers */
+       spin_lock_irqsave(&common->irqlock, flags);
        while (!list_empty(&common->dma_queue)) {
                common->next_frm = list_entry(common->dma_queue.next,
                                                struct vpif_disp_buffer, list);
                list_del(&common->next_frm->list);
                vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
        }
+       spin_unlock_irqrestore(&common->irqlock, flags);
 
        return 0;
 }
@@ -363,11 +373,13 @@ static void process_progressive_mode(struct common_obj *common)
 {
        unsigned long addr = 0;
 
+       spin_lock(&common->irqlock);
        /* Get the next buffer from buffer queue */
        common->next_frm = list_entry(common->dma_queue.next,
                                struct vpif_disp_buffer, list);
        /* Remove that buffer from the buffer queue */
        list_del(&common->next_frm->list);
+       spin_unlock(&common->irqlock);
        /* Mark status of the buffer as active */
        common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
 
@@ -398,16 +410,18 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
                common->cur_frm = common->next_frm;
 
        } else if (1 == fid) {  /* odd field */
+               spin_lock(&common->irqlock);
                if (list_empty(&common->dma_queue)
                    || (common->cur_frm != common->next_frm)) {
+                       spin_unlock(&common->irqlock);
                        return;
                }
+               spin_unlock(&common->irqlock);
                /* one field is displayed configure the next
                 * frame if it is available else hold on current
                 * frame */
                /* Get next from the buffer queue */
                process_progressive_mode(common);
-
        }
 }
 
@@ -437,8 +451,12 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
                        continue;
 
                if (1 == ch->vpifparams.std_info.frm_fmt) {
-                       if (list_empty(&common->dma_queue))
+                       spin_lock(&common->irqlock);
+                       if (list_empty(&common->dma_queue)) {
+                               spin_unlock(&common->irqlock);
                                continue;
+                       }
+                       spin_unlock(&common->irqlock);
 
                        /* Progressive mode */
                        if (!channel_first_int[i][channel_id]) {
@@ -972,9 +990,9 @@ static int vpif_reqbufs(struct file *file, void *priv,
        }
        /* Initialize videobuf2 queue as per the buffer type */
        common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev);
-       if (!common->alloc_ctx) {
+       if (IS_ERR(common->alloc_ctx)) {
                vpif_err("Failed to get the context\n");
-               return -EINVAL;
+               return PTR_ERR(common->alloc_ctx);
        }
        q = &common->buffer_queue;
        q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
@@ -1380,7 +1398,7 @@ vpif_enum_dv_timings(struct file *file, void *priv,
        int ret;
 
        ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
                return -EINVAL;
        return ret;
 }
index 19cbb12a12a2c814424a32b8db8ae2b30074d687..cc7b218d047cffb5e48e0e031eaae6ae7a0bbffb 100644 (file)
@@ -982,7 +982,7 @@ static void *gsc_get_drv_data(struct platform_device *pdev)
                match = of_match_node(of_match_ptr(exynos_gsc_match),
                                        pdev->dev.of_node);
                if (match)
-                       driver_data =  match->data;
+                       driver_data = (struct gsc_driverdata *)match->data;
        } else {
                driver_data = (struct gsc_driverdata *)
                        platform_get_device_id(pdev)->driver_data;
index c065d040ed944630b9d3a4b569fcfc0c5db5f4f4..c267c57c76fdeec23c6fb51c0609929f630c0e91 100644 (file)
@@ -122,7 +122,7 @@ static void gsc_m2m_device_run(void *priv)
        struct gsc_ctx *ctx = priv;
        struct gsc_dev *gsc;
        unsigned long flags;
-       u32 ret;
+       int ret;
        bool is_set = false;
 
        if (WARN(!ctx, "null hardware context\n"))
index 31ac4dc692475a5b5f1339941617569fd936f43e..a8ddb0cacab82cc7d81e5c3f17b6d4d5f29d9a2a 100644 (file)
@@ -352,8 +352,7 @@ static int restart_video_queue(struct viu_dmaqueue *vidq)
                        return 0;
                buf = list_entry(vidq->queued.next, struct viu_buf, vb.queue);
                if (prev == NULL) {
-                       list_del(&buf->vb.queue);
-                       list_add_tail(&buf->vb.queue, &vidq->active);
+                       list_move_tail(&buf->vb.queue, &vidq->active);
 
                        dprintk(1, "Restarting video dma\n");
                        viu_stop_dma(vidq->dev);
@@ -367,8 +366,7 @@ static int restart_video_queue(struct viu_dmaqueue *vidq)
                } else if (prev->vb.width  == buf->vb.width  &&
                           prev->vb.height == buf->vb.height &&
                           prev->fmt       == buf->fmt) {
-                       list_del(&buf->vb.queue);
-                       list_add_tail(&buf->vb.queue, &vidq->active);
+                       list_move_tail(&buf->vb.queue, &vidq->active);
                        buf->vb.state = VIDEOBUF_ACTIVE;
                        dprintk(2, "[%p/%d] restart_queue - move to active\n",
                                buf, buf->vb.i);
index 45164c4f8452975d2bbd12978b3c6d9ff8229118..05c560f2ef062c8f21ba44a943fe004942de0e81 100644 (file)
@@ -218,15 +218,14 @@ static void dma_callback(void *data)
 static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
                                  int do_callback)
 {
-       struct deinterlace_q_data *s_q_data, *d_q_data;
+       struct deinterlace_q_data *s_q_data;
        struct vb2_buffer *src_buf, *dst_buf;
        struct deinterlace_dev *pcdev = ctx->dev;
        struct dma_chan *chan = pcdev->dma_chan;
        struct dma_device *dmadev = chan->device;
        struct dma_async_tx_descriptor *tx;
        unsigned int s_width, s_height;
-       unsigned int d_width, d_height;
-       unsigned int d_size, s_size;
+       unsigned int s_size;
        dma_addr_t p_in, p_out;
        enum dma_ctrl_flags flags;
 
@@ -238,11 +237,6 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
        s_height = s_q_data->height;
        s_size = s_width * s_height;
 
-       d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       d_width = d_q_data->width;
-       d_height = d_q_data->height;
-       d_size = d_width * d_height;
-
        p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
        p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
        if (!p_in || !p_out) {
@@ -1108,17 +1102,5 @@ static struct platform_driver deinterlace_pdrv = {
                .owner  = THIS_MODULE,
        },
 };
-
-static void __exit deinterlace_exit(void)
-{
-       platform_driver_unregister(&deinterlace_pdrv);
-}
-
-static int __init deinterlace_init(void)
-{
-       return platform_driver_register(&deinterlace_pdrv);
-}
-
-module_init(deinterlace_init);
-module_exit(deinterlace_exit);
+module_platform_driver(deinterlace_pdrv);
 
index 2e2121e98133d0ff56f7510c79a06cac8b9182d8..7487d7208dea0d8370620ab8a932cb5e6c4d95a4 100644 (file)
@@ -839,7 +839,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
        int ret;
 
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       src_vq->io_modes = VB2_MMAP;
+       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
        src_vq->drv_priv = ctx;
        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        src_vq->ops = &m2mtest_qops;
@@ -850,7 +850,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
                return ret;
 
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       dst_vq->io_modes = VB2_MMAP;
+       dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
        dst_vq->drv_priv = ctx;
        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        dst_vq->ops = &m2mtest_qops;
index 8f22ce543cf704315399b751371d79f8dfbd2c6e..6b155d7be8e0d3c23e419fc3d6d2cdc6601fcd0e 100644 (file)
@@ -371,7 +371,7 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data)
        if (!curr_ctx->aborting) {
                if ((irqst & PRP_INTR_ST_RDERR) ||
                (irqst & PRP_INTR_ST_CH2WERR)) {
-                       pr_err("PrP bus error ocurred, this transfer is probably corrupted\n");
+                       pr_err("PrP bus error occurred, this transfer is probably corrupted\n");
                        writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
                } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
                        src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
@@ -1013,16 +1013,4 @@ static struct platform_driver emmaprp_pdrv = {
                .owner  = THIS_MODULE,
        },
 };
-
-static void __exit emmaprp_exit(void)
-{
-       platform_driver_unregister(&emmaprp_pdrv);
-}
-
-static int __init emmaprp_init(void)
-{
-       return platform_driver_register(&emmaprp_pdrv);
-}
-
-module_init(emmaprp_init);
-module_exit(emmaprp_exit);
+module_platform_driver(emmaprp_pdrv);
index 993504015963bf8789f910b4532c2320ff653231..35cc526e6c9379626a647dfeb36e22c58d7bfd56 100644 (file)
@@ -44,8 +44,6 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <plat/cpu.h>
-#include <linux/omap-dma.h>
 #include <video/omapvrfb.h>
 #include <video/omapdss.h>
 
@@ -1174,13 +1172,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
        /* set default crop and win */
        omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
 
-       /* Save the changes in the overlay strcuture */
-       ret = omapvid_init(vout, 0);
-       if (ret) {
-               v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
-               goto s_fmt_vid_out_exit;
-       }
-
        ret = 0;
 
 s_fmt_vid_out_exit:
@@ -1684,20 +1675,6 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
 
        omap_dispc_register_isr(omap_vout_isr, vout, mask);
 
-       for (j = 0; j < ovid->num_overlays; j++) {
-               struct omap_overlay *ovl = ovid->overlays[j];
-
-               if (ovl->get_device(ovl)) {
-                       struct omap_overlay_info info;
-                       ovl->get_overlay_info(ovl, &info);
-                       info.paddr = addr;
-                       if (ovl->set_overlay_info(ovl, &info)) {
-                               ret = -EINVAL;
-                               goto streamon_err1;
-                       }
-               }
-       }
-
        /* First save the configuration in ovelray structure */
        ret = omapvid_init(vout, addr);
        if (ret)
@@ -2064,7 +2041,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
                vout->vid_info.id = k + 1;
 
                /* Set VRFB as rotation_type for omap2 and omap3 */
-               if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
                        vout->vid_info.rotation_type = VOUT_ROT_VRFB;
 
                /* Setup the default configuration for the video devices
@@ -2094,11 +2071,12 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
                }
                video_set_drvdata(vfd, vout);
 
-               /* Configure the overlay structure */
-               ret = omapvid_init(vid_dev->vouts[k], 0);
-               if (!ret)
-                       goto success;
+               dev_info(&pdev->dev, ": registered and initialized"
+                               " video device %d\n", vfd->minor);
+               if (k == (pdev->num_resources - 1))
+                       return 0;
 
+               continue;
 error2:
                if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
                        omap_vout_release_vrfb(vout);
@@ -2108,12 +2086,6 @@ error1:
 error:
                kfree(vout);
                return ret;
-
-success:
-               dev_info(&pdev->dev, ": registered and initialized"
-                               " video device %d\n", vfd->minor);
-               if (k == (pdev->num_resources - 1))
-                       return 0;
        }
 
        return -ENODEV;
@@ -2186,14 +2158,23 @@ static int __init omap_vout_probe(struct platform_device *pdev)
        struct omap_dss_device *def_display;
        struct omap2video_device *vid_dev = NULL;
 
+       ret = omapdss_compat_init();
+       if (ret) {
+               dev_err(&pdev->dev, "failed to init dss\n");
+               return ret;
+       }
+
        if (pdev->num_resources == 0) {
                dev_err(&pdev->dev, "probed for an unknown device\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_dss_init;
        }
 
        vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
-       if (vid_dev == NULL)
-               return -ENOMEM;
+       if (vid_dev == NULL) {
+               ret = -ENOMEM;
+               goto err_dss_init;
+       }
 
        vid_dev->num_displays = 0;
        for_each_dss_dev(dssdev) {
@@ -2288,6 +2269,8 @@ probe_err1:
        }
 probe_err0:
        kfree(vid_dev);
+err_dss_init:
+       omapdss_compat_uninit();
        return ret;
 }
 
index 115408b9274f0c40370321fd86daa5b576e5e5e7..80b0d88f125ce5a61b6da09473b1acb991faf4fc 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <linux/dma-mapping.h>
 
-#include <plat/cpu.h>
+#include <video/omapdss.h>
 
 #include "omap_voutlib.h"
 
@@ -124,7 +124,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
        win->chromakey = new_win->chromakey;
 
        /* Adjust the cropping window to allow for resizing limitation */
-       if (cpu_is_omap24xx()) {
+       if (omap_vout_dss_omap24xx()) {
                /* For 24xx limit is 8x to 1/2x scaling. */
                if ((crop->height/win->w.height) >= 2)
                        crop->height = win->w.height * 2;
@@ -140,7 +140,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
                        if (crop->height != win->w.height)
                                crop->width = 768;
                }
-       } else if (cpu_is_omap34xx()) {
+       } else if (omap_vout_dss_omap34xx()) {
                /* For 34xx limit is 8x to 1/4x scaling. */
                if ((crop->height/win->w.height) >= 4)
                        crop->height = win->w.height * 4;
@@ -196,7 +196,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
        if (try_crop.width <= 0 || try_crop.height <= 0)
                return -EINVAL;
 
-       if (cpu_is_omap24xx()) {
+       if (omap_vout_dss_omap24xx()) {
                if (try_crop.height != win->w.height) {
                        /* If we're resizing vertically, we can't support a
                         * crop width wider than 768 pixels.
@@ -207,9 +207,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
        }
        /* vertical resizing */
        vresize = (1024 * try_crop.height) / win->w.height;
-       if (cpu_is_omap24xx() && (vresize > 2048))
+       if (omap_vout_dss_omap24xx() && (vresize > 2048))
                vresize = 2048;
-       else if (cpu_is_omap34xx() && (vresize > 4096))
+       else if (omap_vout_dss_omap34xx() && (vresize > 4096))
                vresize = 4096;
 
        win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
@@ -226,9 +226,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
        }
        /* horizontal resizing */
        hresize = (1024 * try_crop.width) / win->w.width;
-       if (cpu_is_omap24xx() && (hresize > 2048))
+       if (omap_vout_dss_omap24xx() && (hresize > 2048))
                hresize = 2048;
-       else if (cpu_is_omap34xx() && (hresize > 4096))
+       else if (omap_vout_dss_omap34xx() && (hresize > 4096))
                hresize = 4096;
 
        win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
@@ -243,7 +243,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
                if (try_crop.width == 0)
                        try_crop.width = 2;
        }
-       if (cpu_is_omap24xx()) {
+       if (omap_vout_dss_omap24xx()) {
                if ((try_crop.height/win->w.height) >= 2)
                        try_crop.height = win->w.height * 2;
 
@@ -258,7 +258,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
                        if (try_crop.height != win->w.height)
                                try_crop.width = 768;
                }
-       } else if (cpu_is_omap34xx()) {
+       } else if (omap_vout_dss_omap34xx()) {
                if ((try_crop.height/win->w.height) >= 4)
                        try_crop.height = win->w.height * 4;
 
@@ -337,3 +337,21 @@ void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
        }
        free_pages((unsigned long) virtaddr, order);
 }
+
+bool omap_vout_dss_omap24xx(void)
+{
+       return omapdss_get_version() == OMAPDSS_VER_OMAP24xx;
+}
+
+bool omap_vout_dss_omap34xx(void)
+{
+       switch (omapdss_get_version()) {
+       case OMAPDSS_VER_OMAP34xx_ES1:
+       case OMAPDSS_VER_OMAP34xx_ES3:
+       case OMAPDSS_VER_OMAP3630:
+       case OMAPDSS_VER_AM35xx:
+               return true;
+       default:
+               return false;
+       }
+}
index e51750a597e3a426aabb0917c0b8920666b59d51..f9d1c0779f338723fe2256db7fa66162c0b337ab 100644 (file)
@@ -32,5 +32,8 @@ void omap_vout_new_format(struct v4l2_pix_format *pix,
                struct v4l2_window *win);
 unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
 void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
+
+bool omap_vout_dss_omap24xx(void);
+bool omap_vout_dss_omap34xx(void);
 #endif /* #ifndef OMAP_VOUTLIB_H */
 
index 7f182f0ff3daaacfd578a2590d4ec06db24f0e2a..a9f6de5b69d85949fdda469d9ed2e9aaafa8cdd5 100644 (file)
@@ -103,7 +103,8 @@ static const struct isp_res_mapping isp_res_maps[] = {
                       1 << OMAP3_ISP_IOMEM_RESZ |
                       1 << OMAP3_ISP_IOMEM_SBL |
                       1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
-                      1 << OMAP3_ISP_IOMEM_CSIPHY2,
+                      1 << OMAP3_ISP_IOMEM_CSIPHY2 |
+                      1 << OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
        },
        {
                .isp_rev = ISP_REVISION_15_0,
@@ -120,7 +121,8 @@ static const struct isp_res_mapping isp_res_maps[] = {
                       1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
                       1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
                       1 << OMAP3_ISP_IOMEM_CSIPHY1 |
-                      1 << OMAP3_ISP_IOMEM_CSI2C_REGS2,
+                      1 << OMAP3_ISP_IOMEM_CSI2C_REGS2 |
+                      1 << OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
        },
 };
 
@@ -1331,7 +1333,8 @@ void omap3isp_subclk_disable(struct isp_device *isp,
  * isp_enable_clocks - Enable ISP clocks
  * @isp: OMAP3 ISP device
  *
- * Return 0 if successful, or clk_enable return value if any of tthem fails.
+ * Return 0 if successful, or clk_prepare_enable return value if any of them
+ * fails.
  */
 static int isp_enable_clocks(struct isp_device *isp)
 {
@@ -1348,14 +1351,11 @@ static int isp_enable_clocks(struct isp_device *isp)
         * has to be twice of what is set on OMAP3430 to get
         * the required value for cam_mclk
         */
-       if (cpu_is_omap3630())
-               divisor = 1;
-       else
-               divisor = 2;
+       divisor = isp->revision == ISP_REVISION_15_0 ? 1 : 2;
 
-       r = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
+       r = clk_prepare_enable(isp->clock[ISP_CLK_CAM_ICK]);
        if (r) {
-               dev_err(isp->dev, "clk_enable cam_ick failed\n");
+               dev_err(isp->dev, "failed to enable cam_ick clock\n");
                goto out_clk_enable_ick;
        }
        r = clk_set_rate(isp->clock[ISP_CLK_DPLL4_M5_CK],
@@ -1364,9 +1364,9 @@ static int isp_enable_clocks(struct isp_device *isp)
                dev_err(isp->dev, "clk_set_rate for dpll4_m5_ck failed\n");
                goto out_clk_enable_mclk;
        }
-       r = clk_enable(isp->clock[ISP_CLK_CAM_MCLK]);
+       r = clk_prepare_enable(isp->clock[ISP_CLK_CAM_MCLK]);
        if (r) {
-               dev_err(isp->dev, "clk_enable cam_mclk failed\n");
+               dev_err(isp->dev, "failed to enable cam_mclk clock\n");
                goto out_clk_enable_mclk;
        }
        rate = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
@@ -1374,17 +1374,17 @@ static int isp_enable_clocks(struct isp_device *isp)
                dev_warn(isp->dev, "unexpected cam_mclk rate:\n"
                                   " expected : %d\n"
                                   " actual   : %ld\n", CM_CAM_MCLK_HZ, rate);
-       r = clk_enable(isp->clock[ISP_CLK_CSI2_FCK]);
+       r = clk_prepare_enable(isp->clock[ISP_CLK_CSI2_FCK]);
        if (r) {
-               dev_err(isp->dev, "clk_enable csi2_fck failed\n");
+               dev_err(isp->dev, "failed to enable csi2_fck clock\n");
                goto out_clk_enable_csi2_fclk;
        }
        return 0;
 
 out_clk_enable_csi2_fclk:
-       clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
+       clk_disable_unprepare(isp->clock[ISP_CLK_CAM_MCLK]);
 out_clk_enable_mclk:
-       clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
+       clk_disable_unprepare(isp->clock[ISP_CLK_CAM_ICK]);
 out_clk_enable_ick:
        return r;
 }
@@ -1395,9 +1395,9 @@ out_clk_enable_ick:
  */
 static void isp_disable_clocks(struct isp_device *isp)
 {
-       clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
-       clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
-       clk_disable(isp->clock[ISP_CLK_CSI2_FCK]);
+       clk_disable_unprepare(isp->clock[ISP_CLK_CAM_ICK]);
+       clk_disable_unprepare(isp->clock[ISP_CLK_CAM_MCLK]);
+       clk_disable_unprepare(isp->clock[ISP_CLK_CSI2_FCK]);
 }
 
 static const char *isp_clocks[] = {
@@ -1678,7 +1678,7 @@ isp_register_subdev_group(struct isp_device *isp,
 
                adapter = i2c_get_adapter(board_info->i2c_adapter_id);
                if (adapter == NULL) {
-                       printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
+                       dev_err(isp->dev, "%s: Unable to get I2C adapter %d for "
                                "device %s\n", __func__,
                                board_info->i2c_adapter_id,
                                board_info->board_info->type);
@@ -1688,7 +1688,7 @@ isp_register_subdev_group(struct isp_device *isp,
                subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
                                board_info->board_info, NULL);
                if (subdev == NULL) {
-                       printk(KERN_ERR "%s: Unable to register subdev %s\n",
+                       dev_err(isp->dev, "%s: Unable to register subdev %s\n",
                                __func__, board_info->board_info->type);
                        continue;
                }
@@ -1713,7 +1713,7 @@ static int isp_register_entities(struct isp_device *isp)
        isp->media_dev.link_notify = isp_pipeline_link_notify;
        ret = media_device_register(&isp->media_dev);
        if (ret < 0) {
-               printk(KERN_ERR "%s: Media device registration failed (%d)\n",
+               dev_err(isp->dev, "%s: Media device registration failed (%d)\n",
                        __func__, ret);
                return ret;
        }
@@ -1721,7 +1721,7 @@ static int isp_register_entities(struct isp_device *isp)
        isp->v4l2_dev.mdev = &isp->media_dev;
        ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
        if (ret < 0) {
-               printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
+               dev_err(isp->dev, "%s: V4L2 device registration failed (%d)\n",
                        __func__, ret);
                goto done;
        }
@@ -1766,6 +1766,7 @@ static int isp_register_entities(struct isp_device *isp)
                struct media_entity *input;
                unsigned int flags;
                unsigned int pad;
+               unsigned int i;
 
                sensor = isp_register_subdev_group(isp, subdevs->subdevs);
                if (sensor == NULL)
@@ -1807,13 +1808,25 @@ static int isp_register_entities(struct isp_device *isp)
                        break;
 
                default:
-                       printk(KERN_ERR "%s: invalid interface type %u\n",
-                              __func__, subdevs->interface);
+                       dev_err(isp->dev, "%s: invalid interface type %u\n",
+                               __func__, subdevs->interface);
+                       ret = -EINVAL;
+                       goto done;
+               }
+
+               for (i = 0; i < sensor->entity.num_pads; i++) {
+                       if (sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
+                               break;
+               }
+               if (i == sensor->entity.num_pads) {
+                       dev_err(isp->dev,
+                               "%s: no source pad in external entity\n",
+                               __func__);
                        ret = -EINVAL;
                        goto done;
                }
 
-               ret = media_entity_create_link(&sensor->entity, 0, input, pad,
+               ret = media_entity_create_link(&sensor->entity, i, input, pad,
                                               flags);
                if (ret < 0)
                        goto done;
@@ -2096,7 +2109,11 @@ static int __devinit isp_probe(struct platform_device *pdev)
        isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
        isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
 
-       /* Clocks */
+       /* Clocks
+        *
+        * The ISP clock tree is revision-dependent. We thus need to enable ICLK
+        * manually to read the revision before calling __omap3isp_get().
+        */
        ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
        if (ret < 0)
                goto error;
@@ -2105,6 +2122,16 @@ static int __devinit isp_probe(struct platform_device *pdev)
        if (ret < 0)
                goto error;
 
+       ret = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
+       if (ret < 0)
+               goto error;
+
+       isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
+       dev_info(isp->dev, "Revision %d.%d found\n",
+                (isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
+
+       clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
+
        if (__omap3isp_get(isp, false) == NULL) {
                ret = -ENODEV;
                goto error;
@@ -2115,10 +2142,6 @@ static int __devinit isp_probe(struct platform_device *pdev)
                goto error_isp;
 
        /* Memory resources */
-       isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
-       dev_info(isp->dev, "Revision %d.%d found\n",
-                (isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
-
        for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
                if (isp->revision == isp_res_maps[m].isp_rev)
                        break;
index 8d6866942b85a2b1266a0fbfa3a692c6437d6e4b..517d348ce32b1b4871315d5a7d367cd3c475087c 100644 (file)
@@ -70,6 +70,8 @@ enum isp_mem_resources {
        OMAP3_ISP_IOMEM_CSI2C_REGS1,
        OMAP3_ISP_IOMEM_CSIPHY1,
        OMAP3_ISP_IOMEM_CSI2C_REGS2,
+       OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
+       OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
        OMAP3_ISP_IOMEM_LAST
 };
 
@@ -125,9 +127,6 @@ struct isp_reg {
 
 struct isp_platform_callback {
        u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
-       int (*csiphy_config)(struct isp_csiphy *phy,
-                            struct isp_csiphy_dphy_cfg *dphy,
-                            struct isp_csiphy_lanes_cfg *lanes);
 };
 
 /*
index 6a3ff792af7d6a3b07042bc2d7c582b9f9ba5b95..783f4b05b153703ef1a7504743102f0d41617803 100644 (file)
@@ -517,7 +517,7 @@ int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
        } while (soft_reset_retries < 5);
 
        if (soft_reset_retries == 5) {
-               printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
+               dev_err(isp->dev, "CSI2: Soft reset try count exceeded!\n");
                return -EBUSY;
        }
 
@@ -535,8 +535,8 @@ int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
        } while (--i > 0);
 
        if (i == 0) {
-               printk(KERN_ERR
-                      "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
+               dev_err(isp->dev,
+                       "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
                return -EBUSY;
        }
 
index 348f67ebbbc9278e67dfe9dfcfc0a77f115db2cc..3d56b33f85e867147e3df83b3670c2daa3644238 100644 (file)
 #include "ispreg.h"
 #include "ispcsiphy.h"
 
-/*
- * csiphy_lanes_config - Configuration of CSIPHY lanes.
- *
- * Updates HW configuration.
- * Called with phy->mutex taken.
- */
-static void csiphy_lanes_config(struct isp_csiphy *phy)
+static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, u32 iface,
+                                   bool ccp2_strobe)
 {
-       unsigned int i;
-       u32 reg;
+       u32 reg = isp_reg_readl(
+               phy->isp, OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0);
+       u32 shift, mode;
+
+       switch (iface) {
+       case ISP_INTERFACE_CCP2B_PHY1:
+               reg &= ~OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2;
+               shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT;
+               break;
+       case ISP_INTERFACE_CSI2C_PHY1:
+               shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT;
+               mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY;
+               break;
+       case ISP_INTERFACE_CCP2B_PHY2:
+               reg |= OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2;
+               shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT;
+               break;
+       case ISP_INTERFACE_CSI2A_PHY2:
+               shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT;
+               mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY;
+               break;
+       }
 
-       reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
+       /* Select data/clock or data/strobe mode for CCP2 */
+       switch (iface) {
+       case ISP_INTERFACE_CCP2B_PHY1:
+       case ISP_INTERFACE_CCP2B_PHY2:
+               if (ccp2_strobe)
+                       mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE;
+               else
+                       mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_CLOCK;
+       }
 
-       for (i = 0; i < phy->num_data_lanes; i++) {
-               reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
-                        ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
-               reg |= (phy->lanes.data[i].pol <<
-                       ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
-               reg |= (phy->lanes.data[i].pos <<
-                       ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
+       reg &= ~(OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK << shift);
+       reg |= mode << shift;
+
+       isp_reg_writel(phy->isp, reg,
+                      OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0);
+}
+
+static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on,
+                                   bool ccp2_strobe)
+{
+       u32 csirxfe = OMAP343X_CONTROL_CSIRXFE_PWRDNZ
+               | OMAP343X_CONTROL_CSIRXFE_RESET;
+
+       /* Only the CCP2B on PHY1 is configurable. */
+       if (iface != ISP_INTERFACE_CCP2B_PHY1)
+               return;
+
+       if (!on) {
+               isp_reg_writel(phy->isp, 0,
+                              OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0);
+               return;
        }
 
-       reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
-                ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
-       reg |= phy->lanes.clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
-       reg |= phy->lanes.clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
+       if (ccp2_strobe)
+               csirxfe |= OMAP343X_CONTROL_CSIRXFE_SELFORM;
 
-       isp_reg_writel(phy->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
+       isp_reg_writel(phy->isp, csirxfe,
+                      OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0);
+}
+
+/*
+ * Configure OMAP 3 CSI PHY routing.
+ * @phy: relevant phy device
+ * @iface: ISP_INTERFACE_*
+ * @on: power on or off
+ * @ccp2_strobe: false: data/clock, true: data/strobe
+ *
+ * Note that the underlying routing configuration registers are part of the
+ * control (SCM) register space and part of the CORE power domain on both 3430
+ * and 3630, so they will not hold their contents in off-mode. This isn't an
+ * issue since the MPU power domain is forced on whilst the ISP is in use.
+ */
+static void csiphy_routing_cfg(struct isp_csiphy *phy, u32 iface, bool on,
+                              bool ccp2_strobe)
+{
+       if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL]
+           && on)
+               return csiphy_routing_cfg_3630(phy, iface, ccp2_strobe);
+       if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE])
+               return csiphy_routing_cfg_3430(phy, iface, on, ccp2_strobe);
 }
 
 /*
@@ -99,7 +157,7 @@ static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
        } while ((reg != power >> 2) && (retry_count < 100));
 
        if (retry_count == 100) {
-               printk(KERN_ERR "CSI2 CIO set power failed!\n");
+               dev_err(phy->isp->dev, "CSI2 CIO set power failed!\n");
                return -EBUSY;
        }
 
@@ -107,43 +165,28 @@ static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
 }
 
 /*
- * csiphy_dphy_config - Configure CSI2 D-PHY parameters.
- *
- * Called with phy->mutex taken.
+ * TCLK values are OK at their reset values
  */
-static void csiphy_dphy_config(struct isp_csiphy *phy)
-{
-       u32 reg;
-
-       /* Set up ISPCSIPHY_REG0 */
-       reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG0);
-
-       reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
-                ISPCSIPHY_REG0_THS_SETTLE_MASK);
-       reg |= phy->dphy.ths_term << ISPCSIPHY_REG0_THS_TERM_SHIFT;
-       reg |= phy->dphy.ths_settle << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
-
-       isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
-
-       /* Set up ISPCSIPHY_REG1 */
-       reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG1);
-
-       reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
-                ISPCSIPHY_REG1_TCLK_MISS_MASK |
-                ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
-       reg |= phy->dphy.tclk_term << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
-       reg |= phy->dphy.tclk_miss << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
-       reg |= phy->dphy.tclk_settle << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
-
-       isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
-}
+#define TCLK_TERM      0
+#define TCLK_MISS      1
+#define TCLK_SETTLE    14
 
-static int csiphy_config(struct isp_csiphy *phy,
-                        struct isp_csiphy_dphy_cfg *dphy,
-                        struct isp_csiphy_lanes_cfg *lanes)
+static int omap3isp_csiphy_config(struct isp_csiphy *phy)
 {
+       struct isp_csi2_device *csi2 = phy->csi2;
+       struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
+       struct isp_v4l2_subdevs_group *subdevs = pipe->external->host_priv;
+       struct isp_csiphy_lanes_cfg *lanes;
+       int csi2_ddrclk_khz;
        unsigned int used_lanes = 0;
        unsigned int i;
+       u32 reg;
+
+       if (subdevs->interface == ISP_INTERFACE_CCP2B_PHY1
+           || subdevs->interface == ISP_INTERFACE_CCP2B_PHY2)
+               lanes = &subdevs->bus.ccp2.lanecfg;
+       else
+               lanes = &subdevs->bus.csi2.lanecfg;
 
        /* Clock and data lanes verification */
        for (i = 0; i < phy->num_data_lanes; i++) {
@@ -162,10 +205,61 @@ static int csiphy_config(struct isp_csiphy *phy,
        if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
                return -EINVAL;
 
-       mutex_lock(&phy->mutex);
-       phy->dphy = *dphy;
-       phy->lanes = *lanes;
-       mutex_unlock(&phy->mutex);
+       /*
+        * The PHY configuration is lost in off mode, that's not an
+        * issue since the MPU power domain is forced on whilst the
+        * ISP is in use.
+        */
+       csiphy_routing_cfg(phy, subdevs->interface, true,
+                          subdevs->bus.ccp2.phy_layer);
+
+       /* DPHY timing configuration */
+       /* CSI-2 is DDR and we only count used lanes. */
+       csi2_ddrclk_khz = pipe->external_rate / 1000
+               / (2 * hweight32(used_lanes)) * pipe->external_width;
+
+       reg = isp_reg_readl(csi2->isp, phy->phy_regs, ISPCSIPHY_REG0);
+
+       reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
+                ISPCSIPHY_REG0_THS_SETTLE_MASK);
+       /* THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1. */
+       reg |= (DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1)
+               << ISPCSIPHY_REG0_THS_TERM_SHIFT;
+       /* THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3. */
+       reg |= (DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3)
+               << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
+
+       isp_reg_writel(csi2->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
+
+       reg = isp_reg_readl(csi2->isp, phy->phy_regs, ISPCSIPHY_REG1);
+
+       reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
+                ISPCSIPHY_REG1_TCLK_MISS_MASK |
+                ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
+       reg |= TCLK_TERM << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
+       reg |= TCLK_MISS << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
+       reg |= TCLK_SETTLE << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
+
+       isp_reg_writel(csi2->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
+
+       /* DPHY lane configuration */
+       reg = isp_reg_readl(csi2->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
+
+       for (i = 0; i < phy->num_data_lanes; i++) {
+               reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
+                        ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
+               reg |= (lanes->data[i].pol <<
+                       ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
+               reg |= (lanes->data[i].pos <<
+                       ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
+       }
+
+       reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
+                ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
+       reg |= lanes->clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
+       reg |= lanes->clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
+
+       isp_reg_writel(csi2->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
 
        return 0;
 }
@@ -190,8 +284,9 @@ int omap3isp_csiphy_acquire(struct isp_csiphy *phy)
        if (rval < 0)
                goto done;
 
-       csiphy_dphy_config(phy);
-       csiphy_lanes_config(phy);
+       rval = omap3isp_csiphy_config(phy);
+       if (rval < 0)
+               goto done;
 
        rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
        if (rval) {
@@ -211,6 +306,14 @@ void omap3isp_csiphy_release(struct isp_csiphy *phy)
 {
        mutex_lock(&phy->mutex);
        if (phy->phy_in_use) {
+               struct isp_csi2_device *csi2 = phy->csi2;
+               struct isp_pipeline *pipe =
+                       to_isp_pipeline(&csi2->subdev.entity);
+               struct isp_v4l2_subdevs_group *subdevs =
+                       pipe->external->host_priv;
+
+               csiphy_routing_cfg(phy, subdevs->interface, false,
+                                  subdevs->bus.ccp2.phy_layer);
                csiphy_power_autoswitch_enable(phy, false);
                csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
                regulator_disable(phy->vdd);
@@ -227,8 +330,6 @@ int omap3isp_csiphy_init(struct isp_device *isp)
        struct isp_csiphy *phy1 = &isp->isp_csiphy1;
        struct isp_csiphy *phy2 = &isp->isp_csiphy2;
 
-       isp->platform_cb.csiphy_config = csiphy_config;
-
        phy2->isp = isp;
        phy2->csi2 = &isp->isp_csi2a;
        phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;
index e93a661e65d99af981fb541ae7f7cdd39b47706b..14551fd7769780d3f319c6d5d146ed4742b291ac 100644 (file)
 struct isp_csi2_device;
 struct regulator;
 
-struct isp_csiphy_dphy_cfg {
-       u8 ths_term;
-       u8 ths_settle;
-       u8 tclk_term;
-       unsigned tclk_miss:1;
-       u8 tclk_settle;
-};
-
 struct isp_csiphy {
        struct isp_device *isp;
        struct mutex mutex;     /* serialize csiphy configuration */
@@ -52,8 +44,6 @@ struct isp_csiphy {
        unsigned int phy_regs;
 
        u8 num_data_lanes;      /* number of CSI2 Data Lanes supported */
-       struct isp_csiphy_lanes_cfg lanes;
-       struct isp_csiphy_dphy_cfg dphy;
 };
 
 int omap3isp_csiphy_acquire(struct isp_csiphy *phy);
index e7f9c4292cc61b40190dee390731faa75c73f9d8..2d759c56f37c33f4f4b09362acf8125344a34937 100644 (file)
@@ -74,11 +74,14 @@ static void hist_reset_mem(struct ispstat *hist)
 
 static void hist_dma_config(struct ispstat *hist)
 {
+       struct isp_device *isp = hist->isp;
+
        hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
        hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
        hist->dma_config.frame_count = 1;
        hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
-       hist->dma_config.src_start = OMAP3ISP_HIST_REG_BASE + ISPHIST_DATA;
+       hist->dma_config.src_start = isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST]
+                                  + ISPHIST_DATA;
        hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
        hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
 }
@@ -479,6 +482,8 @@ int omap3isp_hist_init(struct isp_device *isp)
                return -ENOMEM;
 
        memset(hist, 0, sizeof(*hist));
+       hist->isp = isp;
+
        if (HIST_CONFIG_DMA)
                ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
                                       hist_dma_cb, hist, &hist->dma_ch);
@@ -496,7 +501,6 @@ int omap3isp_hist_init(struct isp_device *isp)
        hist->ops = &hist_ops;
        hist->priv = hist_cfg;
        hist->event_type = V4L2_EVENT_OMAP3ISP_HIST;
-       hist->isp = isp;
 
        ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
        if (ret) {
index 1ae1c0909ed1c5f5302dd21982f32ec39f19044e..691b92a3c3e7c18bc8b95f1d57e99c6fc9606043 100644 (file)
@@ -200,10 +200,10 @@ static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable)
 
        if (enable)
                isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
+                           ISPPRV_PCR_INVALAW);
        else
                isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
+                           ISPPRV_PCR_INVALAW);
 }
 
 /*
@@ -1014,7 +1014,7 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
 /*
  * preview_config_input_format - Configure the input format
  * @prev: The preview engine
- * @format: Format on the preview engine sink pad
+ * @info: Sink pad format information
  *
  * Enable and configure CFA interpolation for Bayer formats and disable it for
  * greyscale formats.
@@ -1025,22 +1025,29 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
  * reordered to support non-GRBG Bayer patterns.
  */
 static void preview_config_input_format(struct isp_prev_device *prev,
-                                       const struct v4l2_mbus_framefmt *format)
+                                       const struct isp_format_info *info)
 {
        struct isp_device *isp = to_isp_device(prev);
        struct prev_params *params;
 
-       switch (format->code) {
-       case V4L2_MBUS_FMT_SGRBG10_1X10:
+       if (info->width == 8)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_WIDTH);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_WIDTH);
+
+       switch (info->flavor) {
+       case V4L2_MBUS_FMT_SGRBG8_1X8:
                prev->params.cfa_order = 0;
                break;
-       case V4L2_MBUS_FMT_SRGGB10_1X10:
+       case V4L2_MBUS_FMT_SRGGB8_1X8:
                prev->params.cfa_order = 1;
                break;
-       case V4L2_MBUS_FMT_SBGGR10_1X10:
+       case V4L2_MBUS_FMT_SBGGR8_1X8:
                prev->params.cfa_order = 2;
                break;
-       case V4L2_MBUS_FMT_SGBRG10_1X10:
+       case V4L2_MBUS_FMT_SGBRG8_1X8:
                prev->params.cfa_order = 3;
                break;
        default:
@@ -1081,7 +1088,8 @@ static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
        unsigned int elv = prev->crop.top + prev->crop.height - 1;
        u32 features;
 
-       if (format->code != V4L2_MBUS_FMT_Y10_1X10) {
+       if (format->code != V4L2_MBUS_FMT_Y8_1X8 &&
+           format->code != V4L2_MBUS_FMT_Y10_1X10) {
                sph -= 2;
                eph += 2;
                slv -= 2;
@@ -1389,6 +1397,7 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
 static void preview_configure(struct isp_prev_device *prev)
 {
        struct isp_device *isp = to_isp_device(prev);
+       const struct isp_format_info *info;
        struct v4l2_mbus_framefmt *format;
        unsigned long flags;
        u32 update;
@@ -1402,17 +1411,18 @@ static void preview_configure(struct isp_prev_device *prev)
 
        /* PREV_PAD_SINK */
        format = &prev->formats[PREV_PAD_SINK];
+       info = omap3isp_video_format_info(format->code);
 
        preview_adjust_bandwidth(prev);
 
-       preview_config_input_format(prev, format);
+       preview_config_input_format(prev, info);
        preview_config_input_size(prev, active);
 
        if (prev->input == PREVIEW_INPUT_CCDC)
                preview_config_inlineoffset(prev, 0);
        else
-               preview_config_inlineoffset(prev,
-                               ALIGN(format->width, 0x20) * 2);
+               preview_config_inlineoffset(prev, ALIGN(format->width, 0x20) *
+                                           info->bpp);
 
        preview_setup_hw(prev, update, active);
 
@@ -1709,6 +1719,11 @@ __preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
 
 /* previewer format descriptions */
 static const unsigned int preview_input_fmts[] = {
+       V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_SGRBG8_1X8,
+       V4L2_MBUS_FMT_SRGGB8_1X8,
+       V4L2_MBUS_FMT_SBGGR8_1X8,
+       V4L2_MBUS_FMT_SGBRG8_1X8,
        V4L2_MBUS_FMT_Y10_1X10,
        V4L2_MBUS_FMT_SGRBG10_1X10,
        V4L2_MBUS_FMT_SRGGB10_1X10,
index e2c57f334c5d4a4da780069bf5869eb383f4b4a0..b7d90e6fb01dc043c240a20bd27ae444dd96fc79 100644 (file)
 
 #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))
-
-#define OMAP3ISP_CCP2_REG_OFFSET       0x0400
-#define OMAP3ISP_CCP2_REG_BASE         (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_CCP2_REG_OFFSET)
-#define OMAP3ISP_CCP2_REG(offset)      (OMAP3ISP_CCP2_REG_BASE + (offset))
-
-#define OMAP3ISP_CCDC_REG_OFFSET       0x0600
-#define OMAP3ISP_CCDC_REG_BASE         (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_CCDC_REG_OFFSET)
-#define OMAP3ISP_CCDC_REG(offset)      (OMAP3ISP_CCDC_REG_BASE + (offset))
-
-#define OMAP3ISP_HIST_REG_OFFSET       0x0A00
-#define OMAP3ISP_HIST_REG_BASE         (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_HIST_REG_OFFSET)
-#define OMAP3ISP_HIST_REG(offset)      (OMAP3ISP_HIST_REG_BASE + (offset))
-
-#define OMAP3ISP_H3A_REG_OFFSET                0x0C00
-#define OMAP3ISP_H3A_REG_BASE          (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_H3A_REG_OFFSET)
-#define OMAP3ISP_H3A_REG(offset)       (OMAP3ISP_H3A_REG_BASE + (offset))
-
-#define OMAP3ISP_PREV_REG_OFFSET       0x0E00
-#define OMAP3ISP_PREV_REG_BASE         (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_PREV_REG_OFFSET)
-#define OMAP3ISP_PREV_REG(offset)      (OMAP3ISP_PREV_REG_BASE + (offset))
-
-#define OMAP3ISP_RESZ_REG_OFFSET       0x1000
-#define OMAP3ISP_RESZ_REG_BASE         (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_RESZ_REG_OFFSET)
-#define OMAP3ISP_RESZ_REG(offset)      (OMAP3ISP_RESZ_REG_BASE + (offset))
-
-#define OMAP3ISP_SBL_REG_OFFSET                0x1200
-#define OMAP3ISP_SBL_REG_BASE          (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_SBL_REG_OFFSET)
-#define OMAP3ISP_SBL_REG(offset)       (OMAP3ISP_SBL_REG_BASE + (offset))
-
-#define OMAP3ISP_CSI2A_REGS1_REG_OFFSET        0x1800
-#define OMAP3ISP_CSI2A_REGS1_REG_BASE  (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_CSI2A_REGS1_REG_OFFSET)
-#define OMAP3ISP_CSI2A_REGS1_REG(offset)                               \
-                               (OMAP3ISP_CSI2A_REGS1_REG_BASE + (offset))
-
-#define OMAP3ISP_CSIPHY2_REG_OFFSET    0x1970
-#define OMAP3ISP_CSIPHY2_REG_BASE      (OMAP3ISP_REG_BASE +    \
-                                        OMAP3ISP_CSIPHY2_REG_OFFSET)
-#define OMAP3ISP_CSIPHY2_REG(offset)   (OMAP3ISP_CSIPHY2_REG_BASE + (offset))
-
-#define OMAP3ISP_CSI2A_REGS2_REG_OFFSET        0x19C0
-#define OMAP3ISP_CSI2A_REGS2_REG_BASE  (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_CSI2A_REGS2_REG_OFFSET)
-#define OMAP3ISP_CSI2A_REGS2_REG(offset)                               \
-                               (OMAP3ISP_CSI2A_REGS2_REG_BASE + (offset))
-
-#define OMAP3ISP_CSI2C_REGS1_REG_OFFSET        0x1C00
-#define OMAP3ISP_CSI2C_REGS1_REG_BASE  (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_CSI2C_REGS1_REG_OFFSET)
-#define OMAP3ISP_CSI2C_REGS1_REG(offset)                               \
-                               (OMAP3ISP_CSI2C_REGS1_REG_BASE + (offset))
-
-#define OMAP3ISP_CSIPHY1_REG_OFFSET    0x1D70
-#define OMAP3ISP_CSIPHY1_REG_BASE      (OMAP3ISP_REG_BASE +    \
-                                        OMAP3ISP_CSIPHY1_REG_OFFSET)
-#define OMAP3ISP_CSIPHY1_REG(offset)   (OMAP3ISP_CSIPHY1_REG_BASE + (offset))
-
-#define OMAP3ISP_CSI2C_REGS2_REG_OFFSET        0x1DC0
-#define OMAP3ISP_CSI2C_REGS2_REG_BASE  (OMAP3ISP_REG_BASE +            \
-                                        OMAP3ISP_CSI2C_REGS2_REG_OFFSET)
-#define OMAP3ISP_CSI2C_REGS2_REG(offset)                               \
-                               (OMAP3ISP_CSI2C_REGS2_REG_BASE + (offset))
-
 /* ISP module register offset */
 
 #define ISP_REVISION                   (0x000)
 #define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_MASK          \
        (0x7fffff << ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT)
 
+/* -----------------------------------------------------------------------------
+ * CONTROL registers for CSI-2 phy routing
+ */
+
+/* OMAP343X_CONTROL_CSIRXFE */
+#define OMAP343X_CONTROL_CSIRXFE_CSIB_INV      (1 << 7)
+#define OMAP343X_CONTROL_CSIRXFE_RESENABLE     (1 << 8)
+#define OMAP343X_CONTROL_CSIRXFE_SELFORM       (1 << 10)
+#define OMAP343X_CONTROL_CSIRXFE_PWRDNZ                (1 << 12)
+#define OMAP343X_CONTROL_CSIRXFE_RESET         (1 << 13)
+
+/* OMAP3630_CONTROL_CAMERA_PHY_CTRL */
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT    2
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT    0
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY          0x0
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE 0x1
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_CLOCK 0x2
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_GPI           0x3
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK          0x3
+/* CCP2B: set to receive data from PHY2 instead of PHY1 */
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2      (1 << 4)
+
 #endif /* OMAP3_ISP_REG_H */
index e7939869bda76c1037366223e6691fc456ca6876..61e17f9bd8b92148457a45e973aefdb0487dbcec 100644 (file)
@@ -257,7 +257,7 @@ static int isp_stat_buf_queue(struct ispstat *stat)
        if (!stat->active_buf)
                return STAT_NO_BUF;
 
-       do_gettimeofday(&stat->active_buf->ts);
+       ktime_get_ts(&stat->active_buf->ts);
 
        stat->active_buf->buf_size = stat->buf_size;
        if (isp_stat_buf_check_magic(stat, stat->active_buf)) {
@@ -537,7 +537,8 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,
                return PTR_ERR(buf);
        }
 
-       data->ts = buf->ts;
+       data->ts.tv_sec = buf->ts.tv_sec;
+       data->ts.tv_usec = buf->ts.tv_nsec / NSEC_PER_USEC;
        data->config_counter = buf->config_counter;
        data->frame_number = buf->frame_number;
        data->buf_size = buf->buf_size;
index fd15094de34aa45005076bea18dd0025cd048e2e..9a047c929b9f95d47a758267cc341c92bd4f5c8c 100644 (file)
@@ -50,7 +50,7 @@ struct ispstat_buffer {
        struct iovm_struct *iovm;
        void *virt_addr;
        dma_addr_t dma_addr;
-       struct timeval ts;
+       struct timespec ts;
        u32 buf_size;
        u32 frame_number;
        u16 config_counter;
index 3311d6bb3456f7d62329bdc8ad9016fc88c65a48..e0d73a642186d34ae63d841cabe3f42c57604acd 100644 (file)
@@ -1392,7 +1392,8 @@ int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
 
        ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
        if (ret < 0)
-               printk(KERN_ERR "%s: could not register video device (%d)\n",
+               dev_err(video->isp->dev,
+                       "%s: could not register video device (%d)\n",
                        __func__, ret);
 
        return ret;
diff --git a/drivers/media/platform/s3c-camif/Makefile b/drivers/media/platform/s3c-camif/Makefile
new file mode 100644 (file)
index 0000000..50bf8c5
--- /dev/null
@@ -0,0 +1,5 @@
+# Makefile for s3c244x/s3c64xx CAMIF driver
+
+s3c-camif-objs := camif-core.o camif-capture.o camif-regs.o
+
+obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif.o
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
new file mode 100644 (file)
index 0000000..a55793c
--- /dev/null
@@ -0,0 +1,1672 @@
+/*
+ * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
+ *
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+ * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Based on drivers/media/platform/s5p-fimc,
+ * Copyright (C) 2010 - 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "camif-core.h"
+#include "camif-regs.h"
+
+static int debug;
+module_param(debug, int, 0644);
+
+/* Locking: called with vp->camif->slock spinlock held */
+static void camif_cfg_video_path(struct camif_vp *vp)
+{
+       WARN_ON(s3c_camif_get_scaler_config(vp, &vp->scaler));
+       camif_hw_set_scaler(vp);
+       camif_hw_set_flip(vp);
+       camif_hw_set_target_format(vp);
+       camif_hw_set_output_dma(vp);
+}
+
+static void camif_prepare_dma_offset(struct camif_vp *vp)
+{
+       struct camif_frame *f = &vp->out_frame;
+
+       f->dma_offset.initial = f->rect.top * f->f_width + f->rect.left;
+       f->dma_offset.line = f->f_width - (f->rect.left + f->rect.width);
+
+       pr_debug("dma_offset: initial: %d, line: %d\n",
+                f->dma_offset.initial, f->dma_offset.line);
+}
+
+/* Locking: called with camif->slock spinlock held */
+static int s3c_camif_hw_init(struct camif_dev *camif, struct camif_vp *vp)
+{
+       const struct s3c_camif_variant *variant = camif->variant;
+
+       if (camif->sensor.sd == NULL || vp->out_fmt == NULL)
+               return -EINVAL;
+
+       if (variant->ip_revision == S3C244X_CAMIF_IP_REV)
+               camif_hw_clear_fifo_overflow(vp);
+       camif_hw_set_camera_bus(camif);
+       camif_hw_set_source_format(camif);
+       camif_hw_set_camera_crop(camif);
+       camif_hw_set_test_pattern(camif, camif->test_pattern);
+       if (variant->has_img_effect)
+               camif_hw_set_effect(camif, camif->colorfx,
+                               camif->colorfx_cb, camif->colorfx_cr);
+       if (variant->ip_revision == S3C6410_CAMIF_IP_REV)
+               camif_hw_set_input_path(vp);
+       camif_cfg_video_path(vp);
+       vp->state &= ~ST_VP_CONFIG;
+
+       return 0;
+}
+
+/*
+ * Initialize the video path, only up from the scaler stage. The camera
+ * input interface set up is skipped. This is useful to enable one of the
+ * video paths when the other is already running.
+ * Locking: called with camif->slock spinlock held.
+ */
+static int s3c_camif_hw_vp_init(struct camif_dev *camif, struct camif_vp *vp)
+{
+       unsigned int ip_rev = camif->variant->ip_revision;
+
+       if (vp->out_fmt == NULL)
+               return -EINVAL;
+
+       camif_prepare_dma_offset(vp);
+       if (ip_rev == S3C244X_CAMIF_IP_REV)
+               camif_hw_clear_fifo_overflow(vp);
+       camif_cfg_video_path(vp);
+       vp->state &= ~ST_VP_CONFIG;
+       return 0;
+}
+
+static int sensor_set_power(struct camif_dev *camif, int on)
+{
+       struct cam_sensor *sensor = &camif->sensor;
+       int err = 0;
+
+       if (!on == camif->sensor.power_count)
+               err = v4l2_subdev_call(sensor->sd, core, s_power, on);
+       if (!err)
+               sensor->power_count += on ? 1 : -1;
+
+       pr_debug("on: %d, power_count: %d, err: %d\n",
+                on, sensor->power_count, err);
+
+       return err;
+}
+
+static int sensor_set_streaming(struct camif_dev *camif, int on)
+{
+       struct cam_sensor *sensor = &camif->sensor;
+       int err = 0;
+
+       if (!on == camif->sensor.stream_count)
+               err = v4l2_subdev_call(sensor->sd, video, s_stream, on);
+       if (!err)
+               sensor->stream_count += on ? 1 : -1;
+
+       pr_debug("on: %d, stream_count: %d, err: %d\n",
+                on, sensor->stream_count, err);
+
+       return err;
+}
+
+/*
+ * Reinitialize the driver so it is ready to start streaming again.
+ * Return any buffers to vb2, perform CAMIF software reset and
+ * turn off streaming at the data pipeline (sensor) if required.
+ */
+static int camif_reinitialize(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       struct camif_buffer *buf;
+       unsigned long flags;
+       bool streaming;
+
+       spin_lock_irqsave(&camif->slock, flags);
+       streaming = vp->state & ST_VP_SENSOR_STREAMING;
+
+       vp->state &= ~(ST_VP_PENDING | ST_VP_RUNNING | ST_VP_OFF |
+                      ST_VP_ABORTING | ST_VP_STREAMING |
+                      ST_VP_SENSOR_STREAMING | ST_VP_LASTIRQ);
+
+       /* Release unused buffers */
+       while (!list_empty(&vp->pending_buf_q)) {
+               buf = camif_pending_queue_pop(vp);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       }
+
+       while (!list_empty(&vp->active_buf_q)) {
+               buf = camif_active_queue_pop(vp);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       }
+
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       if (!streaming)
+               return 0;
+
+       return sensor_set_streaming(camif, 0);
+}
+
+static bool s3c_vp_active(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       unsigned long flags;
+       bool ret;
+
+       spin_lock_irqsave(&camif->slock, flags);
+       ret = (vp->state & ST_VP_RUNNING) || (vp->state & ST_VP_PENDING);
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       return ret;
+}
+
+static bool camif_is_streaming(struct camif_dev *camif)
+{
+       unsigned long flags;
+       bool status;
+
+       spin_lock_irqsave(&camif->slock, flags);
+       status = camif->stream_count > 0;
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       return status;
+}
+
+static int camif_stop_capture(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       unsigned long flags;
+       int ret;
+
+       if (!s3c_vp_active(vp))
+               return 0;
+
+       spin_lock_irqsave(&camif->slock, flags);
+       vp->state &= ~(ST_VP_OFF | ST_VP_LASTIRQ);
+       vp->state |= ST_VP_ABORTING;
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       ret = wait_event_timeout(vp->irq_queue,
+                          !(vp->state & ST_VP_ABORTING),
+                          msecs_to_jiffies(CAMIF_STOP_TIMEOUT));
+
+       spin_lock_irqsave(&camif->slock, flags);
+
+       if (ret == 0 && !(vp->state & ST_VP_OFF)) {
+               /* Timed out, forcibly stop capture */
+               vp->state &= ~(ST_VP_OFF | ST_VP_ABORTING |
+                              ST_VP_LASTIRQ);
+
+               camif_hw_disable_capture(vp);
+               camif_hw_enable_scaler(vp, false);
+       }
+
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       return camif_reinitialize(vp);
+}
+
+static int camif_prepare_addr(struct camif_vp *vp, struct vb2_buffer *vb,
+                             struct camif_addr *paddr)
+{
+       struct camif_frame *frame = &vp->out_frame;
+       u32 pix_size;
+
+       if (vb == NULL || frame == NULL)
+               return -EINVAL;
+
+       pix_size = frame->rect.width * frame->rect.height;
+
+       pr_debug("colplanes: %d, pix_size: %u\n",
+                vp->out_fmt->colplanes, pix_size);
+
+       paddr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       switch (vp->out_fmt->colplanes) {
+       case 1:
+               paddr->cb = 0;
+               paddr->cr = 0;
+               break;
+       case 2:
+               /* decompose Y into Y/Cb */
+               paddr->cb = (u32)(paddr->y + pix_size);
+               paddr->cr = 0;
+               break;
+       case 3:
+               paddr->cb = (u32)(paddr->y + pix_size);
+               /* decompose Y into Y/Cb/Cr */
+               if (vp->out_fmt->color == IMG_FMT_YCBCR422P)
+                       paddr->cr = (u32)(paddr->cb + (pix_size >> 1));
+               else /* 420 */
+                       paddr->cr = (u32)(paddr->cb + (pix_size >> 2));
+
+               if (vp->out_fmt->color == IMG_FMT_YCRCB420)
+                       swap(paddr->cb, paddr->cr);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       pr_debug("DMA address: y: %#x  cb: %#x cr: %#x\n",
+                paddr->y, paddr->cb, paddr->cr);
+
+       return 0;
+}
+
+irqreturn_t s3c_camif_irq_handler(int irq, void *priv)
+{
+       struct camif_vp *vp = priv;
+       struct camif_dev *camif = vp->camif;
+       unsigned int ip_rev = camif->variant->ip_revision;
+       unsigned int status;
+
+       spin_lock(&camif->slock);
+
+       if (ip_rev == S3C6410_CAMIF_IP_REV)
+               camif_hw_clear_pending_irq(vp);
+
+       status = camif_hw_get_status(vp);
+
+       if (ip_rev == S3C244X_CAMIF_IP_REV && (status & CISTATUS_OVF_MASK)) {
+               camif_hw_clear_fifo_overflow(vp);
+               goto unlock;
+       }
+
+       if (vp->state & ST_VP_ABORTING) {
+               if (vp->state & ST_VP_OFF) {
+                       /* Last IRQ */
+                       vp->state &= ~(ST_VP_OFF | ST_VP_ABORTING |
+                                      ST_VP_LASTIRQ);
+                       wake_up(&vp->irq_queue);
+                       goto unlock;
+               } else if (vp->state & ST_VP_LASTIRQ) {
+                       camif_hw_disable_capture(vp);
+                       camif_hw_enable_scaler(vp, false);
+                       camif_hw_set_lastirq(vp, false);
+                       vp->state |= ST_VP_OFF;
+               } else {
+                       /* Disable capture, enable last IRQ */
+                       camif_hw_set_lastirq(vp, true);
+                       vp->state |= ST_VP_LASTIRQ;
+               }
+       }
+
+       if (!list_empty(&vp->pending_buf_q) && (vp->state & ST_VP_RUNNING) &&
+           !list_empty(&vp->active_buf_q)) {
+               unsigned int index;
+               struct camif_buffer *vbuf;
+               struct timeval *tv;
+               struct timespec ts;
+               /*
+                * Get previous DMA write buffer index:
+                * 0 => DMA buffer 0, 2;
+                * 1 => DMA buffer 1, 3.
+                */
+               index = (CISTATUS_FRAMECNT(status) + 2) & 1;
+
+               ktime_get_ts(&ts);
+               vbuf = camif_active_queue_peek(vp, index);
+
+               if (!WARN_ON(vbuf == NULL)) {
+                       /* Dequeue a filled buffer */
+                       tv = &vbuf->vb.v4l2_buf.timestamp;
+                       tv->tv_sec = ts.tv_sec;
+                       tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+                       vbuf->vb.v4l2_buf.sequence = vp->frame_sequence++;
+                       vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
+
+                       /* Set up an empty buffer at the DMA engine */
+                       vbuf = camif_pending_queue_pop(vp);
+                       vbuf->index = index;
+                       camif_hw_set_output_addr(vp, &vbuf->paddr, index);
+                       camif_hw_set_output_addr(vp, &vbuf->paddr, index + 2);
+
+                       /* Scheduled in H/W, add to the queue */
+                       camif_active_queue_add(vp, vbuf);
+               }
+       } else if (!(vp->state & ST_VP_ABORTING) &&
+                  (vp->state & ST_VP_PENDING))  {
+               vp->state |= ST_VP_RUNNING;
+       }
+
+       if (vp->state & ST_VP_CONFIG) {
+               camif_prepare_dma_offset(vp);
+               camif_hw_set_camera_crop(camif);
+               camif_hw_set_scaler(vp);
+               camif_hw_set_flip(vp);
+               camif_hw_set_test_pattern(camif, camif->test_pattern);
+               if (camif->variant->has_img_effect)
+                       camif_hw_set_effect(camif, camif->colorfx,
+                                   camif->colorfx_cb, camif->colorfx_cr);
+               vp->state &= ~ST_VP_CONFIG;
+       }
+unlock:
+       spin_unlock(&camif->slock);
+       return IRQ_HANDLED;
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct camif_vp *vp = vb2_get_drv_priv(vq);
+       struct camif_dev *camif = vp->camif;
+       unsigned long flags;
+       int ret;
+
+       /*
+        * We assume the codec capture path is always activated
+        * first, before the preview path starts streaming.
+        * This is required to avoid internal FIFO overflow and
+        * a need for CAMIF software reset.
+        */
+       spin_lock_irqsave(&camif->slock, flags);
+
+       if (camif->stream_count == 0) {
+               camif_hw_reset(camif);
+               ret = s3c_camif_hw_init(camif, vp);
+       } else {
+               ret = s3c_camif_hw_vp_init(camif, vp);
+       }
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       if (ret < 0) {
+               camif_reinitialize(vp);
+               return ret;
+       }
+
+       spin_lock_irqsave(&camif->slock, flags);
+       vp->frame_sequence = 0;
+       vp->state |= ST_VP_PENDING;
+
+       if (!list_empty(&vp->pending_buf_q) &&
+           (!(vp->state & ST_VP_STREAMING) ||
+            !(vp->state & ST_VP_SENSOR_STREAMING))) {
+
+               camif_hw_enable_scaler(vp, vp->scaler.enable);
+               camif_hw_enable_capture(vp);
+               vp->state |= ST_VP_STREAMING;
+
+               if (!(vp->state & ST_VP_SENSOR_STREAMING)) {
+                       vp->state |= ST_VP_SENSOR_STREAMING;
+                       spin_unlock_irqrestore(&camif->slock, flags);
+                       ret = sensor_set_streaming(camif, 1);
+                       if (ret)
+                               v4l2_err(&vp->vdev, "Sensor s_stream failed\n");
+                       if (debug)
+                               camif_hw_dump_regs(camif, __func__);
+
+                       return ret;
+               }
+       }
+
+       spin_unlock_irqrestore(&camif->slock, flags);
+       return 0;
+}
+
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct camif_vp *vp = vb2_get_drv_priv(vq);
+       return camif_stop_capture(vp);
+}
+
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+                      unsigned int *num_buffers, unsigned int *num_planes,
+                      unsigned int sizes[], void *allocators[])
+{
+       const struct v4l2_pix_format *pix = NULL;
+       struct camif_vp *vp = vb2_get_drv_priv(vq);
+       struct camif_dev *camif = vp->camif;
+       struct camif_frame *frame = &vp->out_frame;
+       const struct camif_fmt *fmt = vp->out_fmt;
+       unsigned int size;
+
+       if (pfmt) {
+               pix = &pfmt->fmt.pix;
+               fmt = s3c_camif_find_format(vp, &pix->pixelformat, -1);
+               size = (pix->width * pix->height * fmt->depth) / 8;
+       } else {
+               size = (frame->f_width * frame->f_height * fmt->depth) / 8;
+       }
+
+       if (fmt == NULL)
+               return -EINVAL;
+       *num_planes = 1;
+
+       if (pix)
+               sizes[0] = max(size, pix->sizeimage);
+       else
+               sizes[0] = size;
+       allocators[0] = camif->alloc_ctx;
+
+       pr_debug("size: %u\n", sizes[0]);
+       return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+       struct camif_vp *vp = vb2_get_drv_priv(vb->vb2_queue);
+
+       if (vp->out_fmt == NULL)
+               return -EINVAL;
+
+       if (vb2_plane_size(vb, 0) < vp->payload) {
+               v4l2_err(&vp->vdev, "buffer too small: %lu, required: %u\n",
+                        vb2_plane_size(vb, 0), vp->payload);
+               return -EINVAL;
+       }
+       vb2_set_plane_payload(vb, 0, vp->payload);
+
+       return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       struct camif_buffer *buf = container_of(vb, struct camif_buffer, vb);
+       struct camif_vp *vp = vb2_get_drv_priv(vb->vb2_queue);
+       struct camif_dev *camif = vp->camif;
+       unsigned long flags;
+
+       spin_lock_irqsave(&camif->slock, flags);
+       WARN_ON(camif_prepare_addr(vp, &buf->vb, &buf->paddr));
+
+       if (!(vp->state & ST_VP_STREAMING) && vp->active_buffers < 2) {
+               /* Schedule an empty buffer in H/W */
+               buf->index = vp->buf_index;
+
+               camif_hw_set_output_addr(vp, &buf->paddr, buf->index);
+               camif_hw_set_output_addr(vp, &buf->paddr, buf->index + 2);
+
+               camif_active_queue_add(vp, buf);
+               vp->buf_index = !vp->buf_index;
+       } else {
+               camif_pending_queue_add(vp, buf);
+       }
+
+       if (vb2_is_streaming(&vp->vb_queue) && !list_empty(&vp->pending_buf_q)
+               && !(vp->state & ST_VP_STREAMING)) {
+
+               vp->state |= ST_VP_STREAMING;
+               camif_hw_enable_scaler(vp, vp->scaler.enable);
+               camif_hw_enable_capture(vp);
+               spin_unlock_irqrestore(&camif->slock, flags);
+
+               if (!(vp->state & ST_VP_SENSOR_STREAMING)) {
+                       if (sensor_set_streaming(camif, 1) == 0)
+                               vp->state |= ST_VP_SENSOR_STREAMING;
+                       else
+                               v4l2_err(&vp->vdev, "Sensor s_stream failed\n");
+
+                       if (debug)
+                               camif_hw_dump_regs(camif, __func__);
+               }
+               return;
+       }
+       spin_unlock_irqrestore(&camif->slock, flags);
+}
+
+static void camif_lock(struct vb2_queue *vq)
+{
+       struct camif_vp *vp = vb2_get_drv_priv(vq);
+       mutex_lock(&vp->camif->lock);
+}
+
+static void camif_unlock(struct vb2_queue *vq)
+{
+       struct camif_vp *vp = vb2_get_drv_priv(vq);
+       mutex_unlock(&vp->camif->lock);
+}
+
+static const struct vb2_ops s3c_camif_qops = {
+       .queue_setup     = queue_setup,
+       .buf_prepare     = buffer_prepare,
+       .buf_queue       = buffer_queue,
+       .wait_prepare    = camif_unlock,
+       .wait_finish     = camif_lock,
+       .start_streaming = start_streaming,
+       .stop_streaming  = stop_streaming,
+};
+
+static int s3c_camif_open(struct file *file)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_dev *camif = vp->camif;
+       int ret;
+
+       pr_debug("[vp%d] state: %#x,  owner: %p, pid: %d\n", vp->id,
+                vp->state, vp->owner, task_pid_nr(current));
+
+       if (mutex_lock_interruptible(&camif->lock))
+               return -ERESTARTSYS;
+
+       ret = v4l2_fh_open(file);
+       if (ret < 0)
+               goto unlock;
+
+       ret = pm_runtime_get_sync(camif->dev);
+       if (ret < 0)
+               goto err_pm;
+
+       ret = sensor_set_power(camif, 1);
+       if (!ret)
+               goto unlock;
+
+       pm_runtime_put(camif->dev);
+err_pm:
+       v4l2_fh_release(file);
+unlock:
+       mutex_unlock(&camif->lock);
+       return ret;
+}
+
+static int s3c_camif_close(struct file *file)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_dev *camif = vp->camif;
+       int ret;
+
+       pr_debug("[vp%d] state: %#x, owner: %p, pid: %d\n", vp->id,
+                vp->state, vp->owner, task_pid_nr(current));
+
+       mutex_lock(&camif->lock);
+
+       if (vp->owner == file->private_data) {
+               camif_stop_capture(vp);
+               vb2_queue_release(&vp->vb_queue);
+               vp->owner = NULL;
+       }
+
+       sensor_set_power(camif, 0);
+
+       pm_runtime_put(camif->dev);
+       ret = v4l2_fh_release(file);
+
+       mutex_unlock(&camif->lock);
+       return ret;
+}
+
+static unsigned int s3c_camif_poll(struct file *file,
+                                  struct poll_table_struct *wait)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_dev *camif = vp->camif;
+       int ret;
+
+       mutex_lock(&camif->lock);
+       if (vp->owner && vp->owner != file->private_data)
+               ret = -EBUSY;
+       else
+               ret = vb2_poll(&vp->vb_queue, file, wait);
+
+       mutex_unlock(&camif->lock);
+       return ret;
+}
+
+static int s3c_camif_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       int ret;
+
+       if (vp->owner && vp->owner != file->private_data)
+               ret = -EBUSY;
+       else
+               ret = vb2_mmap(&vp->vb_queue, vma);
+
+       return ret;
+}
+
+static const struct v4l2_file_operations s3c_camif_fops = {
+       .owner          = THIS_MODULE,
+       .open           = s3c_camif_open,
+       .release        = s3c_camif_close,
+       .poll           = s3c_camif_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = s3c_camif_mmap,
+};
+
+/*
+ * Video node IOCTLs
+ */
+
+static int s3c_camif_vidioc_querycap(struct file *file, void *priv,
+                                    struct v4l2_capability *cap)
+{
+       struct camif_vp *vp = video_drvdata(file);
+
+       strlcpy(cap->driver, S3C_CAMIF_DRIVER_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, S3C_CAMIF_DRIVER_NAME, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s.%d",
+                dev_name(vp->camif->dev), vp->id);
+
+       cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int s3c_camif_vidioc_enum_input(struct file *file, void *priv,
+                                      struct v4l2_input *input)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct v4l2_subdev *sensor = vp->camif->sensor.sd;
+
+       if (input->index || sensor == NULL)
+               return -EINVAL;
+
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       strlcpy(input->name, sensor->name, sizeof(input->name));
+       return 0;
+}
+
+static int s3c_camif_vidioc_s_input(struct file *file, void *priv,
+                                   unsigned int i)
+{
+       return i == 0 ? 0 : -EINVAL;
+}
+
+static int s3c_camif_vidioc_g_input(struct file *file, void *priv,
+                                   unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int s3c_camif_vidioc_enum_fmt(struct file *file, void *priv,
+                                    struct v4l2_fmtdesc *f)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       const struct camif_fmt *fmt;
+
+       fmt = s3c_camif_find_format(vp, NULL, f->index);
+       if (!fmt)
+               return -EINVAL;
+
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->fourcc;
+
+       pr_debug("fmt(%d): %s\n", f->index, f->description);
+       return 0;
+}
+
+static int s3c_camif_vidioc_g_fmt(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct camif_frame *frame = &vp->out_frame;
+       const struct camif_fmt *fmt = vp->out_fmt;
+
+       pix->bytesperline = frame->f_width * fmt->ybpp;
+       pix->sizeimage = vp->payload;
+
+       pix->pixelformat = fmt->fourcc;
+       pix->width = frame->f_width;
+       pix->height = frame->f_height;
+       pix->field = V4L2_FIELD_NONE;
+       pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+       return 0;
+}
+
+static int __camif_video_try_format(struct camif_vp *vp,
+                                   struct v4l2_pix_format *pix,
+                                   const struct camif_fmt **ffmt)
+{
+       struct camif_dev *camif = vp->camif;
+       struct v4l2_rect *crop = &camif->camif_crop;
+       unsigned int wmin, hmin, sc_hrmax, sc_vrmax;
+       const struct vp_pix_limits *pix_lim;
+       const struct camif_fmt *fmt;
+
+       fmt = s3c_camif_find_format(vp, &pix->pixelformat, 0);
+
+       if (WARN_ON(fmt == NULL))
+               return -EINVAL;
+
+       if (ffmt)
+               *ffmt = fmt;
+
+       pix_lim = &camif->variant->vp_pix_limits[vp->id];
+
+       pr_debug("fmt: %ux%u, crop: %ux%u, bytesperline: %u\n",
+                pix->width, pix->height, crop->width, crop->height,
+                pix->bytesperline);
+       /*
+        * Calculate minimum width and height according to the configured
+        * camera input interface crop rectangle and the resizer's capabilities.
+        */
+       sc_hrmax = min(SCALER_MAX_RATIO, 1 << (ffs(crop->width) - 3));
+       sc_vrmax = min(SCALER_MAX_RATIO, 1 << (ffs(crop->height) - 1));
+
+       wmin = max_t(u32, pix_lim->min_out_width, crop->width / sc_hrmax);
+       wmin = round_up(wmin, pix_lim->out_width_align);
+       hmin = max_t(u32, 8, crop->height / sc_vrmax);
+       hmin = round_up(hmin, 8);
+
+       v4l_bound_align_image(&pix->width, wmin, pix_lim->max_sc_out_width,
+                             ffs(pix_lim->out_width_align) - 1,
+                             &pix->height, hmin, pix_lim->max_height, 0, 0);
+
+       pix->bytesperline = pix->width * fmt->ybpp;
+       pix->sizeimage = (pix->width * pix->height * fmt->depth) / 8;
+       pix->pixelformat = fmt->fourcc;
+       pix->colorspace = V4L2_COLORSPACE_JPEG;
+       pix->field = V4L2_FIELD_NONE;
+
+       pr_debug("%ux%u, wmin: %d, hmin: %d, sc_hrmax: %d, sc_vrmax: %d\n",
+                pix->width, pix->height, wmin, hmin, sc_hrmax, sc_vrmax);
+
+       return 0;
+}
+
+static int s3c_camif_vidioc_try_fmt(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       return __camif_video_try_format(vp, &f->fmt.pix, NULL);
+}
+
+static int s3c_camif_vidioc_s_fmt(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_frame *out_frame = &vp->out_frame;
+       const struct camif_fmt *fmt = NULL;
+       int ret;
+
+       pr_debug("[vp%d]\n", vp->id);
+
+       if (vb2_is_busy(&vp->vb_queue))
+               return -EBUSY;
+
+       ret = __camif_video_try_format(vp, &f->fmt.pix, &fmt);
+       if (ret < 0)
+               return ret;
+
+       vp->out_fmt = fmt;
+       vp->payload = pix->sizeimage;
+       out_frame->f_width = pix->width;
+       out_frame->f_height = pix->height;
+
+       /* Reset composition rectangle */
+       out_frame->rect.width = pix->width;
+       out_frame->rect.height = pix->height;
+       out_frame->rect.left = 0;
+       out_frame->rect.top = 0;
+
+       if (vp->owner == NULL)
+               vp->owner = priv;
+
+       pr_debug("%ux%u. payload: %u. fmt: %s. %d %d. sizeimage: %d. bpl: %d\n",
+               out_frame->f_width, out_frame->f_height, vp->payload, fmt->name,
+               pix->width * pix->height * fmt->depth, fmt->depth,
+               pix->sizeimage, pix->bytesperline);
+
+       return 0;
+}
+
+/* Only check pixel formats at the sensor and the camif subdev pads */
+static int camif_pipeline_validate(struct camif_dev *camif)
+{
+       struct v4l2_subdev_format src_fmt;
+       struct media_pad *pad;
+       int ret;
+
+       /* Retrieve format at the sensor subdev source pad */
+       pad = media_entity_remote_source(&camif->pads[0]);
+       if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+               return -EPIPE;
+
+       src_fmt.pad = pad->index;
+       src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(camif->sensor.sd, pad, get_fmt, NULL, &src_fmt);
+       if (ret < 0 && ret != -ENOIOCTLCMD)
+               return -EPIPE;
+
+       if (src_fmt.format.width != camif->mbus_fmt.width ||
+           src_fmt.format.height != camif->mbus_fmt.height ||
+           src_fmt.format.code != camif->mbus_fmt.code)
+               return -EPIPE;
+
+       return 0;
+}
+
+static int s3c_camif_streamon(struct file *file, void *priv,
+                             enum v4l2_buf_type type)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_dev *camif = vp->camif;
+       struct media_entity *sensor = &camif->sensor.sd->entity;
+       int ret;
+
+       pr_debug("[vp%d]\n", vp->id);
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (vp->owner && vp->owner != priv)
+               return -EBUSY;
+
+       if (s3c_vp_active(vp))
+               return 0;
+
+       ret = media_entity_pipeline_start(sensor, camif->m_pipeline);
+       if (ret < 0)
+               return ret;
+
+       ret = camif_pipeline_validate(camif);
+       if (ret < 0) {
+               media_entity_pipeline_stop(sensor);
+               return ret;
+       }
+
+       return vb2_streamon(&vp->vb_queue, type);
+}
+
+static int s3c_camif_streamoff(struct file *file, void *priv,
+                              enum v4l2_buf_type type)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_dev *camif = vp->camif;
+       int ret;
+
+       pr_debug("[vp%d]\n", vp->id);
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (vp->owner && vp->owner != priv)
+               return -EBUSY;
+
+       ret = vb2_streamoff(&vp->vb_queue, type);
+       if (ret == 0)
+               media_entity_pipeline_stop(&camif->sensor.sd->entity);
+       return ret;
+}
+
+static int s3c_camif_reqbufs(struct file *file, void *priv,
+                            struct v4l2_requestbuffers *rb)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       int ret;
+
+       pr_debug("[vp%d] rb count: %d, owner: %p, priv: %p\n",
+                vp->id, rb->count, vp->owner, priv);
+
+       if (vp->owner && vp->owner != priv)
+               return -EBUSY;
+
+       if (rb->count)
+               rb->count = max_t(u32, CAMIF_REQ_BUFS_MIN, rb->count);
+       else
+               vp->owner = NULL;
+
+       ret = vb2_reqbufs(&vp->vb_queue, rb);
+       if (!ret) {
+               vp->reqbufs_count = rb->count;
+               if (vp->owner == NULL && rb->count > 0)
+                       vp->owner = priv;
+       }
+
+       return ret;
+}
+
+static int s3c_camif_querybuf(struct file *file, void *priv,
+                             struct v4l2_buffer *buf)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       return vb2_querybuf(&vp->vb_queue, buf);
+}
+
+static int s3c_camif_qbuf(struct file *file, void *priv,
+                         struct v4l2_buffer *buf)
+{
+       struct camif_vp *vp = video_drvdata(file);
+
+       pr_debug("[vp%d]\n", vp->id);
+
+       if (vp->owner && vp->owner != priv)
+               return -EBUSY;
+
+       return vb2_qbuf(&vp->vb_queue, buf);
+}
+
+static int s3c_camif_dqbuf(struct file *file, void *priv,
+                          struct v4l2_buffer *buf)
+{
+       struct camif_vp *vp = video_drvdata(file);
+
+       pr_debug("[vp%d] sequence: %d\n", vp->id, vp->frame_sequence);
+
+       if (vp->owner && vp->owner != priv)
+               return -EBUSY;
+
+       return vb2_dqbuf(&vp->vb_queue, buf, file->f_flags & O_NONBLOCK);
+}
+
+static int s3c_camif_create_bufs(struct file *file, void *priv,
+                                struct v4l2_create_buffers *create)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       int ret;
+
+       if (vp->owner && vp->owner != priv)
+               return -EBUSY;
+
+       create->count = max_t(u32, 1, create->count);
+       ret = vb2_create_bufs(&vp->vb_queue, create);
+
+       if (!ret && vp->owner == NULL)
+               vp->owner = priv;
+
+       return ret;
+}
+
+static int s3c_camif_prepare_buf(struct file *file, void *priv,
+                                struct v4l2_buffer *b)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       return vb2_prepare_buf(&vp->vb_queue, b);
+}
+
+static int s3c_camif_g_selection(struct file *file, void *priv,
+                                struct v4l2_selection *sel)
+{
+       struct camif_vp *vp = video_drvdata(file);
+
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = vp->out_frame.f_width;
+               sel->r.height = vp->out_frame.f_height;
+               return 0;
+
+       case V4L2_SEL_TGT_COMPOSE:
+               sel->r = vp->out_frame.rect;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static void __camif_try_compose(struct camif_dev *camif, struct camif_vp *vp,
+                               struct v4l2_rect *r)
+{
+       /* s3c244x doesn't support composition */
+       if (camif->variant->ip_revision == S3C244X_CAMIF_IP_REV) {
+               *r = vp->out_frame.rect;
+               return;
+       }
+
+       /* TODO: s3c64xx */
+}
+
+static int s3c_camif_s_selection(struct file *file, void *priv,
+                                struct v4l2_selection *sel)
+{
+       struct camif_vp *vp = video_drvdata(file);
+       struct camif_dev *camif = vp->camif;
+       struct v4l2_rect rect = sel->r;
+       unsigned long flags;
+
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           sel->target != V4L2_SEL_TGT_COMPOSE)
+               return -EINVAL;
+
+       __camif_try_compose(camif, vp, &rect);
+
+       sel->r = rect;
+       spin_lock_irqsave(&camif->slock, flags);
+       vp->out_frame.rect = rect;
+       vp->state |= ST_VP_CONFIG;
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       pr_debug("type: %#x, target: %#x, flags: %#x, (%d,%d)/%dx%d\n",
+               sel->type, sel->target, sel->flags,
+               sel->r.left, sel->r.top, sel->r.width, sel->r.height);
+
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops s3c_camif_ioctl_ops = {
+       .vidioc_querycap          = s3c_camif_vidioc_querycap,
+       .vidioc_enum_input        = s3c_camif_vidioc_enum_input,
+       .vidioc_g_input           = s3c_camif_vidioc_g_input,
+       .vidioc_s_input           = s3c_camif_vidioc_s_input,
+       .vidioc_enum_fmt_vid_cap  = s3c_camif_vidioc_enum_fmt,
+       .vidioc_try_fmt_vid_cap   = s3c_camif_vidioc_try_fmt,
+       .vidioc_s_fmt_vid_cap     = s3c_camif_vidioc_s_fmt,
+       .vidioc_g_fmt_vid_cap     = s3c_camif_vidioc_g_fmt,
+       .vidioc_g_selection       = s3c_camif_g_selection,
+       .vidioc_s_selection       = s3c_camif_s_selection,
+       .vidioc_reqbufs           = s3c_camif_reqbufs,
+       .vidioc_querybuf          = s3c_camif_querybuf,
+       .vidioc_prepare_buf       = s3c_camif_prepare_buf,
+       .vidioc_create_bufs       = s3c_camif_create_bufs,
+       .vidioc_qbuf              = s3c_camif_qbuf,
+       .vidioc_dqbuf             = s3c_camif_dqbuf,
+       .vidioc_streamon          = s3c_camif_streamon,
+       .vidioc_streamoff         = s3c_camif_streamoff,
+       .vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+       .vidioc_log_status        = v4l2_ctrl_log_status,
+};
+
+/*
+ * Video node controls
+ */
+static int s3c_camif_video_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct camif_vp *vp = ctrl->priv;
+       struct camif_dev *camif = vp->camif;
+       unsigned long flags;
+
+       pr_debug("[vp%d] ctrl: %s, value: %d\n", vp->id,
+                ctrl->name, ctrl->val);
+
+       spin_lock_irqsave(&camif->slock, flags);
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               vp->hflip = ctrl->val;
+               break;
+
+       case V4L2_CID_VFLIP:
+               vp->vflip = ctrl->val;
+               break;
+       }
+
+       vp->state |= ST_VP_CONFIG;
+       spin_unlock_irqrestore(&camif->slock, flags);
+       return 0;
+}
+
+/* Codec and preview video node control ops */
+static const struct v4l2_ctrl_ops s3c_camif_video_ctrl_ops = {
+       .s_ctrl = s3c_camif_video_s_ctrl,
+};
+
+int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
+{
+       struct camif_vp *vp = &camif->vp[idx];
+       struct vb2_queue *q = &vp->vb_queue;
+       struct video_device *vfd = &vp->vdev;
+       struct v4l2_ctrl *ctrl;
+       int ret;
+
+       memset(vfd, 0, sizeof(*vfd));
+       snprintf(vfd->name, sizeof(vfd->name), "camif-%s",
+                vp->id == 0 ? "codec" : "preview");
+
+       vfd->fops = &s3c_camif_fops;
+       vfd->ioctl_ops = &s3c_camif_ioctl_ops;
+       vfd->v4l2_dev = &camif->v4l2_dev;
+       vfd->minor = -1;
+       vfd->release = video_device_release_empty;
+       vfd->lock = &camif->lock;
+       vp->reqbufs_count = 0;
+
+       INIT_LIST_HEAD(&vp->pending_buf_q);
+       INIT_LIST_HEAD(&vp->active_buf_q);
+
+       memset(q, 0, sizeof(*q));
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_MMAP | VB2_USERPTR;
+       q->ops = &s3c_camif_qops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct camif_buffer);
+       q->drv_priv = vp;
+
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_vd_rel;
+
+       vp->pad.flags = MEDIA_PAD_FL_SINK;
+       ret = media_entity_init(&vfd->entity, 1, &vp->pad, 0);
+       if (ret)
+               goto err_vd_rel;
+
+       video_set_drvdata(vfd, vp);
+       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+
+       v4l2_ctrl_handler_init(&vp->ctrl_handler, 1);
+       ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops,
+                                V4L2_CID_HFLIP, 0, 1, 1, 0);
+       if (ctrl)
+               ctrl->priv = vp;
+       ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops,
+                                V4L2_CID_VFLIP, 0, 1, 1, 0);
+       if (ctrl)
+               ctrl->priv = vp;
+
+       ret = vp->ctrl_handler.error;
+       if (ret < 0)
+               goto err_me_cleanup;
+
+       vfd->ctrl_handler = &vp->ctrl_handler;
+
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+       if (ret)
+               goto err_ctrlh_free;
+
+       v4l2_info(&camif->v4l2_dev, "registered %s as /dev/%s\n",
+                 vfd->name, video_device_node_name(vfd));
+       return 0;
+
+err_ctrlh_free:
+       v4l2_ctrl_handler_free(&vp->ctrl_handler);
+err_me_cleanup:
+       media_entity_cleanup(&vfd->entity);
+err_vd_rel:
+       video_device_release(vfd);
+       return ret;
+}
+
+void s3c_camif_unregister_video_node(struct camif_dev *camif, int idx)
+{
+       struct video_device *vfd = &camif->vp[idx].vdev;
+
+       if (video_is_registered(vfd)) {
+               video_unregister_device(vfd);
+               media_entity_cleanup(&vfd->entity);
+               v4l2_ctrl_handler_free(vfd->ctrl_handler);
+       }
+}
+
+/* Media bus pixel formats supported at the camif input */
+static const enum v4l2_mbus_pixelcode camif_mbus_formats[] = {
+       V4L2_MBUS_FMT_YUYV8_2X8,
+       V4L2_MBUS_FMT_YVYU8_2X8,
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_VYUY8_2X8,
+};
+
+/*
+ *  Camera input interface subdev operations
+ */
+
+static int s3c_camif_subdev_enum_mbus_code(struct v4l2_subdev *sd,
+                                       struct v4l2_subdev_fh *fh,
+                                       struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->index >= ARRAY_SIZE(camif_mbus_formats))
+               return -EINVAL;
+
+       code->code = camif_mbus_formats[code->index];
+       return 0;
+}
+
+static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
+                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_format *fmt)
+{
+       struct camif_dev *camif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *mf = &fmt->format;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               fmt->format = *mf;
+               return 0;
+       }
+
+       mutex_lock(&camif->lock);
+
+       switch (fmt->pad) {
+       case CAMIF_SD_PAD_SINK:
+               /* full camera input pixel size */
+               *mf = camif->mbus_fmt;
+               break;
+
+       case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+               /* crop rectangle at camera interface input */
+               mf->width = camif->camif_crop.width;
+               mf->height = camif->camif_crop.height;
+               mf->code = camif->mbus_fmt.code;
+               break;
+       }
+
+       mutex_unlock(&camif->lock);
+       mf->colorspace = V4L2_COLORSPACE_JPEG;
+       return 0;
+}
+
+static void __camif_subdev_try_format(struct camif_dev *camif,
+                               struct v4l2_mbus_framefmt *mf, int pad)
+{
+       const struct s3c_camif_variant *variant = camif->variant;
+       const struct vp_pix_limits *pix_lim;
+       int i = ARRAY_SIZE(camif_mbus_formats);
+
+       /* FIXME: constraints against codec or preview path ? */
+       pix_lim = &variant->vp_pix_limits[VP_CODEC];
+
+       while (i-- >= 0)
+               if (camif_mbus_formats[i] == mf->code)
+                       break;
+
+       mf->code = camif_mbus_formats[i];
+
+       if (pad == CAMIF_SD_PAD_SINK) {
+               v4l_bound_align_image(&mf->width, 8, CAMIF_MAX_PIX_WIDTH,
+                                     ffs(pix_lim->out_width_align) - 1,
+                                     &mf->height, 8, CAMIF_MAX_PIX_HEIGHT, 0,
+                                     0);
+       } else {
+               struct v4l2_rect *crop = &camif->camif_crop;
+               v4l_bound_align_image(&mf->width, 8, crop->width,
+                                     ffs(pix_lim->out_width_align) - 1,
+                                     &mf->height, 8, crop->height,
+                                     0, 0);
+       }
+
+       v4l2_dbg(1, debug, &camif->subdev, "%ux%u\n", mf->width, mf->height);
+}
+
+static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
+                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_format *fmt)
+{
+       struct camif_dev *camif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *mf = &fmt->format;
+       struct v4l2_rect *crop = &camif->camif_crop;
+       int i;
+
+       v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %ux%u\n",
+                fmt->pad, mf->code, mf->width, mf->height);
+
+       mf->colorspace = V4L2_COLORSPACE_JPEG;
+       mutex_lock(&camif->lock);
+
+       /*
+        * No pixel format change at the camera input is allowed
+        * while streaming.
+        */
+       if (vb2_is_busy(&camif->vp[VP_CODEC].vb_queue) ||
+           vb2_is_busy(&camif->vp[VP_PREVIEW].vb_queue)) {
+               mutex_unlock(&camif->lock);
+               return -EBUSY;
+       }
+
+       __camif_subdev_try_format(camif, mf, fmt->pad);
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               *mf = fmt->format;
+               mutex_unlock(&camif->lock);
+               return 0;
+       }
+
+       switch (fmt->pad) {
+       case CAMIF_SD_PAD_SINK:
+               camif->mbus_fmt = *mf;
+               /* Reset sink crop rectangle. */
+               crop->width = mf->width;
+               crop->height = mf->height;
+               crop->left = 0;
+               crop->top = 0;
+               /*
+                * Reset source format (the camif's crop rectangle)
+                * and the video output resolution.
+                */
+               for (i = 0; i < CAMIF_VP_NUM; i++) {
+                       struct camif_frame *frame = &camif->vp[i].out_frame;
+                       frame->rect = *crop;
+                       frame->f_width = mf->width;
+                       frame->f_height = mf->height;
+               }
+               break;
+
+       case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+               /* Pixel format can be only changed on the sink pad. */
+               mf->code = camif->mbus_fmt.code;
+               mf->width = crop->width;
+               mf->height = crop->height;
+               break;
+       }
+
+       mutex_unlock(&camif->lock);
+       return 0;
+}
+
+static int s3c_camif_subdev_get_selection(struct v4l2_subdev *sd,
+                                         struct v4l2_subdev_fh *fh,
+                                         struct v4l2_subdev_selection *sel)
+{
+       struct camif_dev *camif = v4l2_get_subdevdata(sd);
+       struct v4l2_rect *crop = &camif->camif_crop;
+       struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
+
+       if ((sel->target != V4L2_SEL_TGT_CROP &&
+           sel->target != V4L2_SEL_TGT_CROP_BOUNDS) ||
+           sel->pad != CAMIF_SD_PAD_SINK)
+               return -EINVAL;
+
+       if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
+               sel->r = *v4l2_subdev_get_try_crop(fh, sel->pad);
+               return 0;
+       }
+
+       mutex_lock(&camif->lock);
+
+       if (sel->target == V4L2_SEL_TGT_CROP) {
+               sel->r = *crop;
+       } else { /* crop bounds */
+               sel->r.width = mf->width;
+               sel->r.height = mf->height;
+               sel->r.left = 0;
+               sel->r.top = 0;
+       }
+
+       mutex_unlock(&camif->lock);
+
+       v4l2_dbg(1, debug, sd, "%s: crop: (%d,%d) %dx%d, size: %ux%u\n",
+                __func__, crop->left, crop->top, crop->width,
+                crop->height, mf->width, mf->height);
+
+       return 0;
+}
+
+static void __camif_try_crop(struct camif_dev *camif, struct v4l2_rect *r)
+{
+       struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
+       const struct camif_pix_limits *pix_lim = &camif->variant->pix_limits;
+       unsigned int left = 2 * r->left;
+       unsigned int top = 2 * r->top;
+
+       /*
+        * Following constraints must be met:
+        *  - r->width + 2 * r->left = mf->width;
+        *  - r->height + 2 * r->top = mf->height;
+        *  - crop rectangle size and position must be aligned
+        *    to 8 or 2 pixels, depending on SoC version.
+        */
+       v4l_bound_align_image(&r->width, 0, mf->width,
+                             ffs(pix_lim->win_hor_offset_align) - 1,
+                             &r->height, 0, mf->height, 1, 0);
+
+       v4l_bound_align_image(&left, 0, mf->width - r->width,
+                             ffs(pix_lim->win_hor_offset_align),
+                             &top, 0, mf->height - r->height, 2, 0);
+
+       r->left = left / 2;
+       r->top = top / 2;
+       r->width = mf->width - left;
+       r->height = mf->height - top;
+       /*
+        * Make sure we either downscale or upscale both the pixel
+        * width and height. Just return current crop rectangle if
+        * this scaler constraint is not met.
+        */
+       if (camif->variant->ip_revision == S3C244X_CAMIF_IP_REV &&
+           camif_is_streaming(camif)) {
+               unsigned int i;
+
+               for (i = 0; i < CAMIF_VP_NUM; i++) {
+                       struct v4l2_rect *or = &camif->vp[i].out_frame.rect;
+                       if ((or->width > r->width) == (or->height > r->height))
+                               continue;
+                       *r = camif->camif_crop;
+                       pr_debug("Width/height scaling direction limitation\n");
+                       break;
+               }
+       }
+
+       v4l2_dbg(1, debug, &camif->v4l2_dev, "crop: (%d,%d)/%dx%d, fmt: %ux%u\n",
+                r->left, r->top, r->width, r->height, mf->width, mf->height);
+}
+
+static int s3c_camif_subdev_set_selection(struct v4l2_subdev *sd,
+                                         struct v4l2_subdev_fh *fh,
+                                         struct v4l2_subdev_selection *sel)
+{
+       struct camif_dev *camif = v4l2_get_subdevdata(sd);
+       struct v4l2_rect *crop = &camif->camif_crop;
+       struct camif_scaler scaler;
+
+       if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != CAMIF_SD_PAD_SINK)
+               return -EINVAL;
+
+       mutex_lock(&camif->lock);
+       __camif_try_crop(camif, &sel->r);
+
+       if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
+               *v4l2_subdev_get_try_crop(fh, sel->pad) = sel->r;
+       } else {
+               unsigned long flags;
+               unsigned int i;
+
+               spin_lock_irqsave(&camif->slock, flags);
+               *crop = sel->r;
+
+               for (i = 0; i < CAMIF_VP_NUM; i++) {
+                       struct camif_vp *vp = &camif->vp[i];
+                       scaler = vp->scaler;
+                       if (s3c_camif_get_scaler_config(vp, &scaler))
+                               continue;
+                       vp->scaler = scaler;
+                       vp->state |= ST_VP_CONFIG;
+               }
+
+               spin_unlock_irqrestore(&camif->slock, flags);
+       }
+       mutex_unlock(&camif->lock);
+
+       v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %u, f_h: %u\n",
+                __func__, crop->left, crop->top, crop->width, crop->height,
+                camif->mbus_fmt.width, camif->mbus_fmt.height);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_pad_ops s3c_camif_subdev_pad_ops = {
+       .enum_mbus_code = s3c_camif_subdev_enum_mbus_code,
+       .get_selection = s3c_camif_subdev_get_selection,
+       .set_selection = s3c_camif_subdev_set_selection,
+       .get_fmt = s3c_camif_subdev_get_fmt,
+       .set_fmt = s3c_camif_subdev_set_fmt,
+};
+
+static struct v4l2_subdev_ops s3c_camif_subdev_ops = {
+       .pad = &s3c_camif_subdev_pad_ops,
+};
+
+static int s3c_camif_subdev_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct camif_dev *camif = container_of(ctrl->handler, struct camif_dev,
+                                              ctrl_handler);
+       unsigned long flags;
+
+       spin_lock_irqsave(&camif->slock, flags);
+
+       switch (ctrl->id) {
+       case V4L2_CID_COLORFX:
+               camif->colorfx = camif->ctrl_colorfx->val;
+               /* Set Cb, Cr */
+               switch (ctrl->val) {
+               case V4L2_COLORFX_SEPIA:
+                       camif->colorfx_cb = 115;
+                       camif->colorfx_cr = 145;
+                       break;
+               case V4L2_COLORFX_SET_CBCR:
+                       camif->colorfx_cb = camif->ctrl_colorfx_cbcr->val >> 8;
+                       camif->colorfx_cr = camif->ctrl_colorfx_cbcr->val & 0xff;
+                       break;
+               default:
+                       /* for V4L2_COLORFX_BW and others */
+                       camif->colorfx_cb = 128;
+                       camif->colorfx_cr = 128;
+               }
+               break;
+       case V4L2_CID_TEST_PATTERN:
+               camif->test_pattern = camif->ctrl_test_pattern->val;
+               break;
+       default:
+               WARN_ON(1);
+       }
+
+       camif->vp[VP_CODEC].state |= ST_VP_CONFIG;
+       camif->vp[VP_PREVIEW].state |= ST_VP_CONFIG;
+       spin_unlock_irqrestore(&camif->slock, flags);
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops s3c_camif_subdev_ctrl_ops = {
+       .s_ctrl = s3c_camif_subdev_s_ctrl,
+};
+
+static const char * const s3c_camif_test_pattern_menu[] = {
+       "Disabled",
+       "Color bars",
+       "Horizontal increment",
+       "Vertical increment",
+};
+
+int s3c_camif_create_subdev(struct camif_dev *camif)
+{
+       struct v4l2_ctrl_handler *handler = &camif->ctrl_handler;
+       struct v4l2_subdev *sd = &camif->subdev;
+       int ret;
+
+       v4l2_subdev_init(sd, &s3c_camif_subdev_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       strlcpy(sd->name, "S3C-CAMIF", sizeof(sd->name));
+
+       camif->pads[CAMIF_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       camif->pads[CAMIF_SD_PAD_SOURCE_C].flags = MEDIA_PAD_FL_SOURCE;
+       camif->pads[CAMIF_SD_PAD_SOURCE_P].flags = MEDIA_PAD_FL_SOURCE;
+
+       ret = media_entity_init(&sd->entity, CAMIF_SD_PADS_NUM,
+                               camif->pads, 0);
+       if (ret)
+               return ret;
+
+       v4l2_ctrl_handler_init(handler, 3);
+       camif->ctrl_test_pattern = v4l2_ctrl_new_std_menu_items(handler,
+                       &s3c_camif_subdev_ctrl_ops, V4L2_CID_TEST_PATTERN,
+                       ARRAY_SIZE(s3c_camif_test_pattern_menu) - 1, 0, 0,
+                       s3c_camif_test_pattern_menu);
+
+       camif->ctrl_colorfx = v4l2_ctrl_new_std_menu(handler,
+                               &s3c_camif_subdev_ctrl_ops,
+                               V4L2_CID_COLORFX, V4L2_COLORFX_SET_CBCR,
+                               ~0x981f, V4L2_COLORFX_NONE);
+
+       camif->ctrl_colorfx_cbcr = v4l2_ctrl_new_std(handler,
+                               &s3c_camif_subdev_ctrl_ops,
+                               V4L2_CID_COLORFX_CBCR, 0, 0xffff, 1, 0);
+       if (handler->error) {
+               v4l2_ctrl_handler_free(handler);
+               media_entity_cleanup(&sd->entity);
+               return handler->error;
+       }
+
+       v4l2_ctrl_auto_cluster(2, &camif->ctrl_colorfx,
+                              V4L2_COLORFX_SET_CBCR, false);
+       if (!camif->variant->has_img_effect) {
+               camif->ctrl_colorfx->flags |= V4L2_CTRL_FLAG_DISABLED;
+               camif->ctrl_colorfx_cbcr->flags |= V4L2_CTRL_FLAG_DISABLED;
+       }
+       sd->ctrl_handler = handler;
+       v4l2_set_subdevdata(sd, camif);
+
+       return 0;
+}
+
+void s3c_camif_unregister_subdev(struct camif_dev *camif)
+{
+       struct v4l2_subdev *sd = &camif->subdev;
+
+       /* Return if not registered */
+       if (v4l2_get_subdevdata(sd) == NULL)
+               return;
+
+       v4l2_device_unregister_subdev(sd);
+       media_entity_cleanup(&sd->entity);
+       v4l2_ctrl_handler_free(&camif->ctrl_handler);
+       v4l2_set_subdevdata(sd, NULL);
+}
+
+int s3c_camif_set_defaults(struct camif_dev *camif)
+{
+       unsigned int ip_rev = camif->variant->ip_revision;
+       int i;
+
+       for (i = 0; i < CAMIF_VP_NUM; i++) {
+               struct camif_vp *vp = &camif->vp[i];
+               struct camif_frame *f = &vp->out_frame;
+
+               vp->camif = camif;
+               vp->id = i;
+               vp->offset = camif->variant->vp_offset;
+
+               if (ip_rev == S3C244X_CAMIF_IP_REV)
+                       vp->fmt_flags = i ? FMT_FL_S3C24XX_PREVIEW :
+                                       FMT_FL_S3C24XX_CODEC;
+               else
+                       vp->fmt_flags = FMT_FL_S3C64XX;
+
+               vp->out_fmt = s3c_camif_find_format(vp, NULL, 0);
+               BUG_ON(vp->out_fmt == NULL);
+
+               memset(f, 0, sizeof(*f));
+               f->f_width = CAMIF_DEF_WIDTH;
+               f->f_height = CAMIF_DEF_HEIGHT;
+               f->rect.width = CAMIF_DEF_WIDTH;
+               f->rect.height = CAMIF_DEF_HEIGHT;
+
+               /* Scaler is always enabled */
+               vp->scaler.enable = 1;
+
+               vp->payload = (f->f_width * f->f_height *
+                              vp->out_fmt->depth) / 8;
+       }
+
+       memset(&camif->mbus_fmt, 0, sizeof(camif->mbus_fmt));
+       camif->mbus_fmt.width = CAMIF_DEF_WIDTH;
+       camif->mbus_fmt.height = CAMIF_DEF_HEIGHT;
+       camif->mbus_fmt.code  = camif_mbus_formats[0];
+
+       memset(&camif->camif_crop, 0, sizeof(camif->camif_crop));
+       camif->camif_crop.width = CAMIF_DEF_WIDTH;
+       camif->camif_crop.height = CAMIF_DEF_HEIGHT;
+
+       return 0;
+}
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
new file mode 100644 (file)
index 0000000..0dd6537
--- /dev/null
@@ -0,0 +1,662 @@
+/*
+ * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
+ *
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+ * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ */
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "camif-core.h"
+
+static char *camif_clocks[CLK_MAX_NUM] = {
+       /* HCLK CAMIF clock */
+       [CLK_GATE]      = "camif",
+       /* CAMIF / external camera sensor master clock */
+       [CLK_CAM]       = "camera",
+};
+
+static const struct camif_fmt camif_formats[] = {
+       {
+               .name           = "YUV 4:2:2 planar, Y/Cb/Cr",
+               .fourcc         = V4L2_PIX_FMT_YUV422P,
+               .depth          = 16,
+               .ybpp           = 1,
+               .color          = IMG_FMT_YCBCR422P,
+               .colplanes      = 3,
+               .flags          = FMT_FL_S3C24XX_CODEC |
+                                 FMT_FL_S3C64XX,
+       }, {
+               .name           = "YUV 4:2:0 planar, Y/Cb/Cr",
+               .fourcc         = V4L2_PIX_FMT_YUV420,
+               .depth          = 12,
+               .ybpp           = 1,
+               .color          = IMG_FMT_YCBCR420,
+               .colplanes      = 3,
+               .flags          = FMT_FL_S3C24XX_CODEC |
+                                 FMT_FL_S3C64XX,
+       }, {
+               .name           = "YVU 4:2:0 planar, Y/Cr/Cb",
+               .fourcc         = V4L2_PIX_FMT_YVU420,
+               .depth          = 12,
+               .ybpp           = 1,
+               .color          = IMG_FMT_YCRCB420,
+               .colplanes      = 3,
+               .flags          = FMT_FL_S3C24XX_CODEC |
+                                 FMT_FL_S3C64XX,
+       }, {
+               .name           = "RGB565, 16 bpp",
+               .fourcc         = V4L2_PIX_FMT_RGB565X,
+               .depth          = 16,
+               .ybpp           = 2,
+               .color          = IMG_FMT_RGB565,
+               .colplanes      = 1,
+               .flags          = FMT_FL_S3C24XX_PREVIEW |
+                                 FMT_FL_S3C64XX,
+       }, {
+               .name           = "XRGB8888, 32 bpp",
+               .fourcc         = V4L2_PIX_FMT_RGB32,
+               .depth          = 32,
+               .ybpp           = 4,
+               .color          = IMG_FMT_XRGB8888,
+               .colplanes      = 1,
+               .flags          = FMT_FL_S3C24XX_PREVIEW |
+                                 FMT_FL_S3C64XX,
+       }, {
+               .name           = "BGR666",
+               .fourcc         = V4L2_PIX_FMT_BGR666,
+               .depth          = 32,
+               .ybpp           = 4,
+               .color          = IMG_FMT_RGB666,
+               .colplanes      = 1,
+               .flags          = FMT_FL_S3C64XX,
+       }
+};
+
+/**
+ * s3c_camif_find_format() - lookup camif color format by fourcc or an index
+ * @pixelformat: fourcc to match, ignored if null
+ * @index: index to the camif_formats array, ignored if negative
+ */
+const struct camif_fmt *s3c_camif_find_format(struct camif_vp *vp,
+                                             const u32 *pixelformat,
+                                             int index)
+{
+       const struct camif_fmt *fmt, *def_fmt = NULL;
+       unsigned int i;
+       int id = 0;
+
+       if (index >= (int)ARRAY_SIZE(camif_formats))
+               return NULL;
+
+       for (i = 0; i < ARRAY_SIZE(camif_formats); ++i) {
+               fmt = &camif_formats[i];
+               if (vp && !(vp->fmt_flags & fmt->flags))
+                       continue;
+               if (pixelformat && fmt->fourcc == *pixelformat)
+                       return fmt;
+               if (index == id)
+                       def_fmt = fmt;
+               id++;
+       }
+       return def_fmt;
+}
+
+static int camif_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
+{
+       unsigned int sh = 6;
+
+       if (src >= 64 * tar)
+               return -EINVAL;
+
+       while (sh--) {
+               unsigned int tmp = 1 << sh;
+               if (src >= tar * tmp) {
+                       *shift = sh, *ratio = tmp;
+                       return 0;
+               }
+       }
+       *shift = 0, *ratio = 1;
+       return 0;
+}
+
+int s3c_camif_get_scaler_config(struct camif_vp *vp,
+                               struct camif_scaler *scaler)
+{
+       struct v4l2_rect *camif_crop = &vp->camif->camif_crop;
+       int source_x = camif_crop->width;
+       int source_y = camif_crop->height;
+       int target_x = vp->out_frame.rect.width;
+       int target_y = vp->out_frame.rect.height;
+       int ret;
+
+       if (vp->rotation == 90 || vp->rotation == 270)
+               swap(target_x, target_y);
+
+       ret = camif_get_scaler_factor(source_x, target_x, &scaler->pre_h_ratio,
+                                     &scaler->h_shift);
+       if (ret < 0)
+               return ret;
+
+       ret = camif_get_scaler_factor(source_y, target_y, &scaler->pre_v_ratio,
+                                     &scaler->v_shift);
+       if (ret < 0)
+               return ret;
+
+       scaler->pre_dst_width = source_x / scaler->pre_h_ratio;
+       scaler->pre_dst_height = source_y / scaler->pre_v_ratio;
+
+       scaler->main_h_ratio = (source_x << 8) / (target_x << scaler->h_shift);
+       scaler->main_v_ratio = (source_y << 8) / (target_y << scaler->v_shift);
+
+       scaler->scaleup_h = (target_x >= source_x);
+       scaler->scaleup_v = (target_y >= source_y);
+
+       scaler->copy = 0;
+
+       pr_debug("H: ratio: %u, shift: %u. V: ratio: %u, shift: %u.\n",
+                scaler->pre_h_ratio, scaler->h_shift,
+                scaler->pre_v_ratio, scaler->v_shift);
+
+       pr_debug("Source: %dx%d, Target: %dx%d, scaleup_h/v: %d/%d\n",
+                source_x, source_y, target_x, target_y,
+                scaler->scaleup_h, scaler->scaleup_v);
+
+       return 0;
+}
+
+static int camif_register_sensor(struct camif_dev *camif)
+{
+       struct s3c_camif_sensor_info *sensor = &camif->pdata.sensor;
+       struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
+       struct i2c_adapter *adapter;
+       struct v4l2_subdev_format format;
+       struct v4l2_subdev *sd;
+       int ret;
+
+       camif->sensor.sd = NULL;
+
+       if (sensor->i2c_board_info.addr == 0)
+               return -EINVAL;
+
+       adapter = i2c_get_adapter(sensor->i2c_bus_num);
+       if (adapter == NULL) {
+               v4l2_warn(v4l2_dev, "failed to get I2C adapter %d\n",
+                         sensor->i2c_bus_num);
+               return -EPROBE_DEFER;
+       }
+
+       sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter,
+                                      &sensor->i2c_board_info, NULL);
+       if (sd == NULL) {
+               i2c_put_adapter(adapter);
+               v4l2_warn(v4l2_dev, "failed to acquire subdev %s\n",
+                         sensor->i2c_board_info.type);
+               return -EPROBE_DEFER;
+       }
+       camif->sensor.sd = sd;
+
+       v4l2_info(v4l2_dev, "registered sensor subdevice %s\n", sd->name);
+
+       /* Get initial pixel format and set it at the camif sink pad */
+       format.pad = 0;
+       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
+
+       if (ret < 0)
+               return 0;
+
+       format.pad = CAMIF_SD_PAD_SINK;
+       v4l2_subdev_call(&camif->subdev, pad, set_fmt, NULL, &format);
+
+       v4l2_info(sd, "Initial format from sensor: %dx%d, %#x\n",
+                 format.format.width, format.format.height,
+                 format.format.code);
+       return 0;
+}
+
+static void camif_unregister_sensor(struct camif_dev *camif)
+{
+       struct v4l2_subdev *sd = camif->sensor.sd;
+       struct i2c_client *client = sd ? v4l2_get_subdevdata(sd) : NULL;
+       struct i2c_adapter *adapter;
+
+       if (client == NULL)
+               return;
+
+       adapter = client->adapter;
+       v4l2_device_unregister_subdev(sd);
+       camif->sensor.sd = NULL;
+       i2c_unregister_device(client);
+       if (adapter)
+               i2c_put_adapter(adapter);
+}
+
+static int camif_create_media_links(struct camif_dev *camif)
+{
+       int i, ret;
+
+       ret = media_entity_create_link(&camif->sensor.sd->entity, 0,
+                               &camif->subdev.entity, CAMIF_SD_PAD_SINK,
+                               MEDIA_LNK_FL_IMMUTABLE |
+                               MEDIA_LNK_FL_ENABLED);
+       if (ret)
+               return ret;
+
+       for (i = 1; i < CAMIF_SD_PADS_NUM && !ret; i++) {
+               ret = media_entity_create_link(&camif->subdev.entity, i,
+                               &camif->vp[i - 1].vdev.entity, 0,
+                               MEDIA_LNK_FL_IMMUTABLE |
+                               MEDIA_LNK_FL_ENABLED);
+       }
+
+       return ret;
+}
+
+static int camif_register_video_nodes(struct camif_dev *camif)
+{
+       int ret = s3c_camif_register_video_node(camif, VP_CODEC);
+       if (ret < 0)
+               return ret;
+
+       return s3c_camif_register_video_node(camif, VP_PREVIEW);
+}
+
+static void camif_unregister_video_nodes(struct camif_dev *camif)
+{
+       s3c_camif_unregister_video_node(camif, VP_CODEC);
+       s3c_camif_unregister_video_node(camif, VP_PREVIEW);
+}
+
+static void camif_unregister_media_entities(struct camif_dev *camif)
+{
+       camif_unregister_video_nodes(camif);
+       camif_unregister_sensor(camif);
+       s3c_camif_unregister_subdev(camif);
+}
+
+/*
+ * Media device
+ */
+static int camif_media_dev_register(struct camif_dev *camif)
+{
+       struct media_device *md = &camif->media_dev;
+       struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
+       unsigned int ip_rev = camif->variant->ip_revision;
+       int ret;
+
+       memset(md, 0, sizeof(*md));
+       snprintf(md->model, sizeof(md->model), "SAMSUNG S3C%s CAMIF",
+                ip_rev == S3C6410_CAMIF_IP_REV ? "6410" : "244X");
+       strlcpy(md->bus_info, "platform", sizeof(md->bus_info));
+       md->hw_revision = ip_rev;
+       md->driver_version = KERNEL_VERSION(1, 0, 0);
+
+       md->dev = camif->dev;
+
+       strlcpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name));
+       v4l2_dev->mdev = md;
+
+       ret = v4l2_device_register(camif->dev, v4l2_dev);
+       if (ret < 0)
+               return ret;
+
+       ret = media_device_register(md);
+       if (ret < 0)
+               v4l2_device_unregister(v4l2_dev);
+
+       return ret;
+}
+
+static void camif_clk_put(struct camif_dev *camif)
+{
+       int i;
+
+       for (i = 0; i < CLK_MAX_NUM; i++) {
+               if (IS_ERR_OR_NULL(camif->clock[i]))
+                       continue;
+               clk_unprepare(camif->clock[i]);
+               clk_put(camif->clock[i]);
+       }
+}
+
+static int camif_clk_get(struct camif_dev *camif)
+{
+       int ret, i;
+
+       for (i = 0; i < CLK_MAX_NUM; i++) {
+               camif->clock[i] = clk_get(camif->dev, camif_clocks[i]);
+               if (IS_ERR(camif->clock[i])) {
+                       ret = PTR_ERR(camif->clock[i]);
+                       goto err;
+               }
+               ret = clk_prepare(camif->clock[i]);
+               if (ret < 0) {
+                       clk_put(camif->clock[i]);
+                       camif->clock[i] = NULL;
+                       goto err;
+               }
+       }
+       return 0;
+err:
+       camif_clk_put(camif);
+       dev_err(camif->dev, "failed to get clock: %s\n",
+               camif_clocks[i]);
+       return ret;
+}
+
+/*
+ * The CAMIF device has two relatively independent data processing paths
+ * that can source data from memory or the common camera input frontend.
+ * Register interrupts for each data processing path (camif_vp).
+ */
+static int camif_request_irqs(struct platform_device *pdev,
+                             struct camif_dev *camif)
+{
+       int irq, ret, i;
+
+       for (i = 0; i < CAMIF_VP_NUM; i++) {
+               struct camif_vp *vp = &camif->vp[i];
+
+               init_waitqueue_head(&vp->irq_queue);
+
+               irq = platform_get_irq(pdev, i);
+               if (irq <= 0) {
+                       dev_err(&pdev->dev, "failed to get IRQ %d\n", i);
+                       return -ENXIO;
+               }
+
+               ret = devm_request_irq(&pdev->dev, irq, s3c_camif_irq_handler,
+                                      0, dev_name(&pdev->dev), vp);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to install IRQ: %d\n", ret);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int s3c_camif_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct s3c_camif_plat_data *pdata = dev->platform_data;
+       struct s3c_camif_drvdata *drvdata;
+       struct camif_dev *camif;
+       struct resource *mres;
+       int ret = 0;
+
+       camif = devm_kzalloc(dev, sizeof(*camif), GFP_KERNEL);
+       if (!camif)
+               return -ENOMEM;
+
+       spin_lock_init(&camif->slock);
+       mutex_init(&camif->lock);
+
+       camif->dev = dev;
+
+       if (!pdata || !pdata->gpio_get || !pdata->gpio_put) {
+               dev_err(dev, "wrong platform data\n");
+               return -EINVAL;
+       }
+
+       camif->pdata = *pdata;
+       drvdata = (void *)platform_get_device_id(pdev)->driver_data;
+       camif->variant = drvdata->variant;
+
+       mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       camif->io_base = devm_request_and_ioremap(dev, mres);
+       if (!camif->io_base) {
+               dev_err(dev, "failed to obtain I/O memory\n");
+               return -ENOENT;
+       }
+
+       ret = camif_request_irqs(pdev, camif);
+       if (ret < 0)
+               return ret;
+
+       ret = pdata->gpio_get();
+       if (ret < 0)
+               return ret;
+
+       ret = s3c_camif_create_subdev(camif);
+       if (ret < 0)
+               goto err_sd;
+
+       ret = camif_clk_get(camif);
+       if (ret < 0)
+               goto err_clk;
+
+       platform_set_drvdata(pdev, camif);
+       clk_set_rate(camif->clock[CLK_CAM],
+                       camif->pdata.sensor.clock_frequency);
+
+       dev_info(dev, "sensor clock frequency: %lu\n",
+                clk_get_rate(camif->clock[CLK_CAM]));
+       /*
+        * Set initial pixel format, resolution and crop rectangle.
+        * Must be done before a sensor subdev is registered as some
+        * settings are overrode with values from sensor subdev.
+        */
+       s3c_camif_set_defaults(camif);
+
+       pm_runtime_enable(dev);
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               goto err_pm;
+
+       /* Initialize contiguous memory allocator */
+       camif->alloc_ctx = vb2_dma_contig_init_ctx(dev);
+       if (IS_ERR(camif->alloc_ctx)) {
+               ret = PTR_ERR(camif->alloc_ctx);
+               goto err_alloc;
+       }
+
+       ret = camif_media_dev_register(camif);
+       if (ret < 0)
+               goto err_mdev;
+
+       ret = camif_register_sensor(camif);
+       if (ret < 0)
+               goto err_sens;
+
+       ret = v4l2_device_register_subdev(&camif->v4l2_dev, &camif->subdev);
+       if (ret < 0)
+               goto err_sens;
+
+       mutex_lock(&camif->media_dev.graph_mutex);
+
+       ret = v4l2_device_register_subdev_nodes(&camif->v4l2_dev);
+       if (ret < 0)
+               goto err_unlock;
+
+       ret = camif_register_video_nodes(camif);
+       if (ret < 0)
+               goto err_unlock;
+
+       ret = camif_create_media_links(camif);
+       if (ret < 0)
+               goto err_unlock;
+
+       mutex_unlock(&camif->media_dev.graph_mutex);
+       pm_runtime_put(dev);
+       return 0;
+
+err_unlock:
+       mutex_unlock(&camif->media_dev.graph_mutex);
+err_sens:
+       v4l2_device_unregister(&camif->v4l2_dev);
+       media_device_unregister(&camif->media_dev);
+       camif_unregister_media_entities(camif);
+err_mdev:
+       vb2_dma_contig_cleanup_ctx(camif->alloc_ctx);
+err_alloc:
+       pm_runtime_put(dev);
+       pm_runtime_disable(dev);
+err_pm:
+       camif_clk_put(camif);
+err_clk:
+       s3c_camif_unregister_subdev(camif);
+err_sd:
+       pdata->gpio_put();
+       return ret;
+}
+
+static int __devexit s3c_camif_remove(struct platform_device *pdev)
+{
+       struct camif_dev *camif = platform_get_drvdata(pdev);
+       struct s3c_camif_plat_data *pdata = &camif->pdata;
+
+       media_device_unregister(&camif->media_dev);
+       camif_unregister_media_entities(camif);
+       v4l2_device_unregister(&camif->v4l2_dev);
+
+       pm_runtime_disable(&pdev->dev);
+       camif_clk_put(camif);
+       pdata->gpio_put();
+
+       return 0;
+}
+
+static int s3c_camif_runtime_resume(struct device *dev)
+{
+       struct camif_dev *camif = dev_get_drvdata(dev);
+
+       clk_enable(camif->clock[CLK_GATE]);
+       /* null op on s3c244x */
+       clk_enable(camif->clock[CLK_CAM]);
+       return 0;
+}
+
+static int s3c_camif_runtime_suspend(struct device *dev)
+{
+       struct camif_dev *camif = dev_get_drvdata(dev);
+
+       /* null op on s3c244x */
+       clk_disable(camif->clock[CLK_CAM]);
+
+       clk_disable(camif->clock[CLK_GATE]);
+       return 0;
+}
+
+static const struct s3c_camif_variant s3c244x_camif_variant = {
+       .vp_pix_limits = {
+               [VP_CODEC] = {
+                       .max_out_width          = 4096,
+                       .max_sc_out_width       = 2048,
+                       .out_width_align        = 16,
+                       .min_out_width          = 16,
+                       .max_height             = 4096,
+               },
+               [VP_PREVIEW] = {
+                       .max_out_width          = 640,
+                       .max_sc_out_width       = 640,
+                       .out_width_align        = 16,
+                       .min_out_width          = 16,
+                       .max_height             = 480,
+               }
+       },
+       .pix_limits = {
+               .win_hor_offset_align   = 8,
+       },
+       .ip_revision = S3C244X_CAMIF_IP_REV,
+};
+
+static struct s3c_camif_drvdata s3c244x_camif_drvdata = {
+       .variant        = &s3c244x_camif_variant,
+       .bus_clk_freq   = 24000000UL,
+};
+
+static const struct s3c_camif_variant s3c6410_camif_variant = {
+       .vp_pix_limits = {
+               [VP_CODEC] = {
+                       .max_out_width          = 4096,
+                       .max_sc_out_width       = 2048,
+                       .out_width_align        = 16,
+                       .min_out_width          = 16,
+                       .max_height             = 4096,
+               },
+               [VP_PREVIEW] = {
+                       .max_out_width          = 4096,
+                       .max_sc_out_width       = 720,
+                       .out_width_align        = 16,
+                       .min_out_width          = 16,
+                       .max_height             = 4096,
+               }
+       },
+       .pix_limits = {
+               .win_hor_offset_align   = 8,
+       },
+       .ip_revision = S3C6410_CAMIF_IP_REV,
+       .has_img_effect = 1,
+       .vp_offset = 0x20,
+};
+
+static struct s3c_camif_drvdata s3c6410_camif_drvdata = {
+       .variant        = &s3c6410_camif_variant,
+       .bus_clk_freq   = 133000000UL,
+};
+
+static struct platform_device_id s3c_camif_driver_ids[] = {
+       {
+               .name           = "s3c2440-camif",
+               .driver_data    = (unsigned long)&s3c244x_camif_drvdata,
+       }, {
+               .name           = "s3c6410-camif",
+               .driver_data    = (unsigned long)&s3c6410_camif_drvdata,
+       },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, s3c_camif_driver_ids);
+
+static const struct dev_pm_ops s3c_camif_pm_ops = {
+       .runtime_suspend        = s3c_camif_runtime_suspend,
+       .runtime_resume         = s3c_camif_runtime_resume,
+};
+
+static struct platform_driver s3c_camif_driver = {
+       .probe          = s3c_camif_probe,
+       .remove         = __devexit_p(s3c_camif_remove),
+       .id_table       = s3c_camif_driver_ids,
+       .driver = {
+               .name   = S3C_CAMIF_DRIVER_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &s3c_camif_pm_ops,
+       }
+};
+
+module_platform_driver(s3c_camif_driver);
+
+MODULE_AUTHOR("Sylwester Nawrocki <sylvester.nawrocki@gmail.com>");
+MODULE_AUTHOR("Tomasz Figa <tomasz.figa@gmail.com>");
+MODULE_DESCRIPTION("S3C24XX/S3C64XX SoC camera interface driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h
new file mode 100644 (file)
index 0000000..261134b
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
+ *
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+ * Copyright (C) 2012 Tomasz Figa <tomasz.figa@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.
+*/
+
+#ifndef CAMIF_CORE_H_
+#define CAMIF_CORE_H_
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/videobuf2-core.h>
+#include <media/s3c_camif.h>
+
+#define S3C_CAMIF_DRIVER_NAME  "s3c-camif"
+#define CAMIF_REQ_BUFS_MIN     3
+#define CAMIF_MAX_OUT_BUFS     4
+#define CAMIF_MAX_PIX_WIDTH    4096
+#define CAMIF_MAX_PIX_HEIGHT   4096
+#define SCALER_MAX_RATIO       64
+#define CAMIF_DEF_WIDTH                640
+#define CAMIF_DEF_HEIGHT       480
+#define CAMIF_STOP_TIMEOUT     1500 /* ms */
+
+#define S3C244X_CAMIF_IP_REV   0x20 /* 2.0 */
+#define S3C2450_CAMIF_IP_REV   0x30 /* 3.0 - not implemented, not tested */
+#define S3C6400_CAMIF_IP_REV   0x31 /* 3.1 - not implemented, not tested */
+#define S3C6410_CAMIF_IP_REV   0x32 /* 3.2 */
+
+/* struct camif_vp::state */
+
+#define ST_VP_PENDING          (1 << 0)
+#define ST_VP_RUNNING          (1 << 1)
+#define ST_VP_STREAMING                (1 << 2)
+#define ST_VP_SENSOR_STREAMING (1 << 3)
+
+#define ST_VP_ABORTING         (1 << 4)
+#define ST_VP_OFF              (1 << 5)
+#define ST_VP_LASTIRQ          (1 << 6)
+
+#define ST_VP_CONFIG           (1 << 8)
+
+#define CAMIF_SD_PAD_SINK      0
+#define CAMIF_SD_PAD_SOURCE_C  1
+#define CAMIF_SD_PAD_SOURCE_P  2
+#define CAMIF_SD_PADS_NUM      3
+
+enum img_fmt {
+       IMG_FMT_RGB565 = 0x0010,
+       IMG_FMT_RGB666,
+       IMG_FMT_XRGB8888,
+       IMG_FMT_YCBCR420 = 0x0020,
+       IMG_FMT_YCRCB420,
+       IMG_FMT_YCBCR422P,
+       IMG_FMT_YCBYCR422 = 0x0040,
+       IMG_FMT_YCRYCB422,
+       IMG_FMT_CBYCRY422,
+       IMG_FMT_CRYCBY422,
+};
+
+#define img_fmt_is_rgb(x) ((x) & 0x10)
+#define img_fmt_is_ycbcr(x) ((x) & 0x60)
+
+/* Possible values for struct camif_fmt::flags */
+#define FMT_FL_S3C24XX_CODEC   (1 << 0)
+#define FMT_FL_S3C24XX_PREVIEW (1 << 1)
+#define FMT_FL_S3C64XX         (1 << 2)
+
+/**
+ * struct camif_fmt - pixel format description
+ * @fourcc:    fourcc code for this format, 0 if not applicable
+ * @color:     a corresponding enum img_fmt
+ * @colplanes: number of physically contiguous data planes
+ * @flags:     indicate for which SoCs revisions this format is valid
+ * @depth:     bits per pixel (total)
+ * @ybpp:      number of luminance bytes per pixel
+ */
+struct camif_fmt {
+       char *name;
+       u32 fourcc;
+       u32 color;
+       u16 colplanes;
+       u16 flags;
+       u8 depth;
+       u8 ybpp;
+};
+
+/**
+ * struct camif_dma_offset - pixel offset information for DMA
+ * @initial: offset (in pixels) to first pixel
+ * @line: offset (in pixels) from end of line to start of next line
+ */
+struct camif_dma_offset {
+       int     initial;
+       int     line;
+};
+
+/**
+ * struct camif_frame - source/target frame properties
+ * @f_width: full pixel width
+ * @f_height: full pixel height
+ * @rect: crop/composition rectangle
+ * @dma_offset: DMA offset configuration
+ */
+struct camif_frame {
+       u16 f_width;
+       u16 f_height;
+       struct v4l2_rect rect;
+       struct camif_dma_offset dma_offset;
+};
+
+/* CAMIF clocks enumeration */
+enum {
+       CLK_GATE,
+       CLK_CAM,
+       CLK_MAX_NUM,
+};
+
+struct vp_pix_limits {
+       u16 max_out_width;
+       u16 max_sc_out_width;
+       u16 out_width_align;
+       u16 max_height;
+       u8 min_out_width;
+       u16 out_hor_offset_align;
+};
+
+struct camif_pix_limits {
+       u16 win_hor_offset_align;
+};
+
+/**
+ * struct s3c_camif_variant - CAMIF variant structure
+ * @vp_pix_limits:    pixel limits for the codec and preview paths
+ * @camif_pix_limits: pixel limits for the camera input interface
+ * @ip_revision:      the CAMIF IP revision: 0x20 for s3c244x, 0x32 for s3c6410
+ */
+struct s3c_camif_variant {
+       struct vp_pix_limits vp_pix_limits[2];
+       struct camif_pix_limits pix_limits;
+       u8 ip_revision;
+       u8 has_img_effect;
+       unsigned int vp_offset;
+};
+
+struct s3c_camif_drvdata {
+       const struct s3c_camif_variant *variant;
+       unsigned long bus_clk_freq;
+};
+
+struct camif_scaler {
+       u8 scaleup_h;
+       u8 scaleup_v;
+       u8 copy;
+       u8 enable;
+       u32 h_shift;
+       u32 v_shift;
+       u32 pre_h_ratio;
+       u32 pre_v_ratio;
+       u32 pre_dst_width;
+       u32 pre_dst_height;
+       u32 main_h_ratio;
+       u32 main_v_ratio;
+};
+
+struct camif_dev;
+
+/**
+ * struct camif_vp - CAMIF data processing path structure (codec/preview)
+ * @irq_queue:     interrupt handling waitqueue
+ * @irq:           interrupt number for this data path
+ * @camif:         pointer to the camif structure
+ * @pad:           media pad for the video node
+ * @vdev            video device
+ * @ctrl_handler:   video node controls handler
+ * @owner:         file handle that own the streaming
+ * @pending_buf_q:  pending (empty) buffers queue head
+ * @active_buf_q:   active (being written) buffers queue head
+ * @active_buffers: counter of buffer set up at the DMA engine
+ * @buf_index:     identifier of a last empty buffer set up in H/W
+ * @frame_sequence: image frame sequence counter
+ * @reqbufs_count:  the number of buffers requested
+ * @scaler:        the scaler structure
+ * @out_fmt:       pixel format at this video path output
+ * @payload:       the output data frame payload size
+ * @out_frame:     the output pixel resolution
+ * @state:         the video path's state
+ * @fmt_flags:     flags determining supported pixel formats
+ * @id:                    CAMIF id, 0 - codec, 1 - preview
+ * @rotation:      current image rotation value
+ * @hflip:         apply horizontal flip if set
+ * @vflip:         apply vertical flip if set
+ */
+struct camif_vp {
+       wait_queue_head_t       irq_queue;
+       int                     irq;
+       struct camif_dev        *camif;
+       struct media_pad        pad;
+       struct video_device     vdev;
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct v4l2_fh          *owner;
+       struct vb2_queue        vb_queue;
+       struct list_head        pending_buf_q;
+       struct list_head        active_buf_q;
+       unsigned int            active_buffers;
+       unsigned int            buf_index;
+       unsigned int            frame_sequence;
+       unsigned int            reqbufs_count;
+       struct camif_scaler     scaler;
+       const struct camif_fmt  *out_fmt;
+       unsigned int            payload;
+       struct camif_frame      out_frame;
+       unsigned int            state;
+       u16                     fmt_flags;
+       u8                      id;
+       u8                      rotation;
+       u8                      hflip;
+       u8                      vflip;
+       unsigned int            offset;
+};
+
+/* Video processing path enumeration */
+#define VP_CODEC       0
+#define VP_PREVIEW     1
+#define CAMIF_VP_NUM   2
+
+/**
+ * struct camif_dev - the CAMIF driver private data structure
+ * @media_dev:    top-level media device structure
+ * @v4l2_dev:    root v4l2_device
+ * @subdev:       camera interface ("catchcam") subdev
+ * @mbus_fmt:    camera input media bus format
+ * @camif_crop:   camera input interface crop rectangle
+ * @pads:        the camif subdev's media pads
+ * @stream_count: the camera interface streaming reference counter
+ * @sensor:       image sensor data structure
+ * @m_pipeline:          video entity pipeline description
+ * @ctrl_handler: v4l2 control handler (owned by @subdev)
+ * @test_pattern: test pattern controls
+ * @vp:           video path (DMA) description (codec/preview)
+ * @alloc_ctx:    memory buffer allocator context
+ * @variant:      variant information for this device
+ * @dev:         pointer to the CAMIF device struct
+ * @pdata:       a copy of the driver's platform data
+ * @clock:       clocks required for the CAMIF operation
+ * @lock:        mutex protecting this data structure
+ * @slock:       spinlock protecting CAMIF registers
+ * @io_base:     start address of the mmaped CAMIF registers
+ */
+struct camif_dev {
+       struct media_device             media_dev;
+       struct v4l2_device              v4l2_dev;
+       struct v4l2_subdev              subdev;
+       struct v4l2_mbus_framefmt       mbus_fmt;
+       struct v4l2_rect                camif_crop;
+       struct media_pad                pads[CAMIF_SD_PADS_NUM];
+       int                             stream_count;
+
+       struct cam_sensor {
+               struct v4l2_subdev      *sd;
+               short                   power_count;
+               short                   stream_count;
+       } sensor;
+       struct media_pipeline           *m_pipeline;
+
+       struct v4l2_ctrl_handler        ctrl_handler;
+       struct v4l2_ctrl                *ctrl_test_pattern;
+       struct {
+               struct v4l2_ctrl        *ctrl_colorfx;
+               struct v4l2_ctrl        *ctrl_colorfx_cbcr;
+       };
+       u8                              test_pattern;
+       u8                              colorfx;
+       u8                              colorfx_cb;
+       u8                              colorfx_cr;
+
+       struct camif_vp                 vp[CAMIF_VP_NUM];
+       struct vb2_alloc_ctx            *alloc_ctx;
+
+       const struct s3c_camif_variant  *variant;
+       struct device                   *dev;
+       struct s3c_camif_plat_data      pdata;
+       struct clk                      *clock[CLK_MAX_NUM];
+       struct mutex                    lock;
+       spinlock_t                      slock;
+       void __iomem                    *io_base;
+};
+
+/**
+ * struct camif_addr - Y/Cb/Cr DMA start address structure
+ * @y:  luminance plane dma address
+ * @cb:         Cb plane dma address
+ * @cr:         Cr plane dma address
+ */
+struct camif_addr {
+       dma_addr_t y;
+       dma_addr_t cb;
+       dma_addr_t cr;
+};
+
+/**
+ * struct camif_buffer - the camif video buffer structure
+ * @vb:    vb2 buffer
+ * @list:  list head for the buffers queue
+ * @paddr: DMA start addresses
+ * @index: an identifier of this buffer at the DMA engine
+ */
+struct camif_buffer {
+       struct vb2_buffer vb;
+       struct list_head list;
+       struct camif_addr paddr;
+       unsigned int index;
+};
+
+const struct camif_fmt *s3c_camif_find_format(struct camif_vp *vp,
+             const u32 *pixelformat, int index);
+int s3c_camif_register_video_node(struct camif_dev *camif, int idx);
+void s3c_camif_unregister_video_node(struct camif_dev *camif, int idx);
+irqreturn_t s3c_camif_irq_handler(int irq, void *priv);
+int s3c_camif_create_subdev(struct camif_dev *camif);
+void s3c_camif_unregister_subdev(struct camif_dev *camif);
+int s3c_camif_set_defaults(struct camif_dev *camif);
+int s3c_camif_get_scaler_config(struct camif_vp *vp,
+                               struct camif_scaler *scaler);
+
+static inline void camif_active_queue_add(struct camif_vp *vp,
+                                         struct camif_buffer *buf)
+{
+       list_add_tail(&buf->list, &vp->active_buf_q);
+       vp->active_buffers++;
+}
+
+static inline struct camif_buffer *camif_active_queue_pop(
+                                       struct camif_vp *vp)
+{
+       struct camif_buffer *buf = list_first_entry(&vp->active_buf_q,
+                                             struct camif_buffer, list);
+       list_del(&buf->list);
+       vp->active_buffers--;
+       return buf;
+}
+
+static inline struct camif_buffer *camif_active_queue_peek(
+                          struct camif_vp *vp, int index)
+{
+       struct camif_buffer *tmp, *buf;
+
+       if (WARN_ON(list_empty(&vp->active_buf_q)))
+               return NULL;
+
+       list_for_each_entry_safe(buf, tmp, &vp->active_buf_q, list) {
+               if (buf->index == index) {
+                       list_del(&buf->list);
+                       vp->active_buffers--;
+                       return buf;
+               }
+       }
+
+       return NULL;
+}
+
+static inline void camif_pending_queue_add(struct camif_vp *vp,
+                                          struct camif_buffer *buf)
+{
+       list_add_tail(&buf->list, &vp->pending_buf_q);
+}
+
+static inline struct camif_buffer *camif_pending_queue_pop(
+                                       struct camif_vp *vp)
+{
+       struct camif_buffer *buf = list_first_entry(&vp->pending_buf_q,
+                                             struct camif_buffer, list);
+       list_del(&buf->list);
+       return buf;
+}
+
+#endif /* CAMIF_CORE_H_ */
diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c
new file mode 100644 (file)
index 0000000..1a3b4fc
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * Samsung s3c24xx/s3c64xx SoC CAMIF driver
+ *
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+ * Copyright (C) 2012 Tomasz Figa <tomasz.figa@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.
+*/
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/delay.h>
+#include "camif-regs.h"
+
+#define camif_write(_camif, _off, _val)        writel(_val, (_camif)->io_base + (_off))
+#define camif_read(_camif, _off)       readl((_camif)->io_base + (_off))
+
+void camif_hw_reset(struct camif_dev *camif)
+{
+       u32 cfg;
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
+       cfg |= CISRCFMT_ITU601_8BIT;
+       camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
+
+       /* S/W reset */
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
+       cfg |= CIGCTRL_SWRST;
+       if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
+               cfg |= CIGCTRL_IRQ_LEVEL;
+       camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
+       udelay(10);
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
+       cfg &= ~CIGCTRL_SWRST;
+       camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
+       udelay(10);
+}
+
+void camif_hw_clear_pending_irq(struct camif_vp *vp)
+{
+       u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_CIGCTRL);
+       cfg |= CIGCTRL_IRQ_CLR(vp->id);
+       camif_write(vp->camif, S3C_CAMIF_REG_CIGCTRL, cfg);
+}
+
+/*
+ * Sets video test pattern (off, color bar, horizontal or vertical gradient).
+ * External sensor pixel clock must be active for the test pattern to work.
+ */
+void camif_hw_set_test_pattern(struct camif_dev *camif, unsigned int pattern)
+{
+       u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
+       cfg &= ~CIGCTRL_TESTPATTERN_MASK;
+       cfg |= (pattern << 27);
+       camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
+}
+
+void camif_hw_set_effect(struct camif_dev *camif, unsigned int effect,
+                       unsigned int cr, unsigned int cb)
+{
+       static const struct v4l2_control colorfx[] = {
+               { V4L2_COLORFX_NONE,            CIIMGEFF_FIN_BYPASS },
+               { V4L2_COLORFX_BW,              CIIMGEFF_FIN_ARBITRARY },
+               { V4L2_COLORFX_SEPIA,           CIIMGEFF_FIN_ARBITRARY },
+               { V4L2_COLORFX_NEGATIVE,        CIIMGEFF_FIN_NEGATIVE },
+               { V4L2_COLORFX_ART_FREEZE,      CIIMGEFF_FIN_ARTFREEZE },
+               { V4L2_COLORFX_EMBOSS,          CIIMGEFF_FIN_EMBOSSING },
+               { V4L2_COLORFX_SILHOUETTE,      CIIMGEFF_FIN_SILHOUETTE },
+               { V4L2_COLORFX_SET_CBCR,        CIIMGEFF_FIN_ARBITRARY },
+       };
+       unsigned int i, cfg;
+
+       for (i = 0; i < ARRAY_SIZE(colorfx); i++)
+               if (colorfx[i].id == effect)
+                       break;
+
+       if (i == ARRAY_SIZE(colorfx))
+               return;
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset));
+       /* Set effect */
+       cfg &= ~CIIMGEFF_FIN_MASK;
+       cfg |= colorfx[i].value;
+       /* Set both paths */
+       if (camif->variant->ip_revision >= S3C6400_CAMIF_IP_REV) {
+               if (effect == V4L2_COLORFX_NONE)
+                       cfg &= ~CIIMGEFF_IE_ENABLE_MASK;
+               else
+                       cfg |= CIIMGEFF_IE_ENABLE_MASK;
+       }
+       cfg &= ~CIIMGEFF_PAT_CBCR_MASK;
+       cfg |= cr | (cb << 13);
+       camif_write(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset), cfg);
+}
+
+static const u32 src_pixfmt_map[8][2] = {
+       { V4L2_MBUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
+       { V4L2_MBUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
+       { V4L2_MBUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
+       { V4L2_MBUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
+};
+
+/* Set camera input pixel format and resolution */
+void camif_hw_set_source_format(struct camif_dev *camif)
+{
+       struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
+       unsigned int i = ARRAY_SIZE(src_pixfmt_map);
+       u32 cfg;
+
+       while (i-- >= 0) {
+               if (src_pixfmt_map[i][0] == mf->code)
+                       break;
+       }
+
+       if (i == 0 && src_pixfmt_map[i][0] != mf->code) {
+               dev_err(camif->dev,
+                       "Unsupported pixel code, falling back to %#08x\n",
+                       src_pixfmt_map[i][0]);
+       }
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
+       cfg &= ~(CISRCFMT_ORDER422_MASK | CISRCFMT_SIZE_CAM_MASK);
+       cfg |= (mf->width << 16) | mf->height;
+       cfg |= src_pixfmt_map[i][1];
+       camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
+}
+
+/* Set the camera host input window offsets (cropping) */
+void camif_hw_set_camera_crop(struct camif_dev *camif)
+{
+       struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
+       struct v4l2_rect *crop = &camif->camif_crop;
+       u32 hoff2, voff2;
+       u32 cfg;
+
+       /* Note: s3c244x requirement: left = f_width - rect.width / 2 */
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
+       cfg &= ~(CIWDOFST_OFST_MASK | CIWDOFST_WINOFSEN);
+       cfg |= (crop->left << 16) | crop->top;
+       if (crop->left != 0 || crop->top != 0)
+               cfg |= CIWDOFST_WINOFSEN;
+       camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
+
+       if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
+               hoff2 = mf->width - crop->width - crop->left;
+               voff2 = mf->height - crop->height - crop->top;
+               cfg = (hoff2 << 16) | voff2;
+               camif_write(camif, S3C_CAMIF_REG_CIWDOFST2, cfg);
+       }
+}
+
+void camif_hw_clear_fifo_overflow(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       u32 cfg;
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
+       if (vp->id == 0)
+               cfg |= (CIWDOFST_CLROVCOFIY | CIWDOFST_CLROVCOFICB |
+                       CIWDOFST_CLROVCOFICR);
+       else
+               cfg |= (/* CIWDOFST_CLROVPRFIY | */ CIWDOFST_CLROVPRFICB |
+                       CIWDOFST_CLROVPRFICR);
+       camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
+}
+
+/* Set video bus signals polarity */
+void camif_hw_set_camera_bus(struct camif_dev *camif)
+{
+       unsigned int flags = camif->pdata.sensor.flags;
+
+       u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
+
+       cfg &= ~(CIGCTRL_INVPOLPCLK | CIGCTRL_INVPOLVSYNC |
+                CIGCTRL_INVPOLHREF | CIGCTRL_INVPOLFIELD);
+
+       if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+               cfg |= CIGCTRL_INVPOLPCLK;
+
+       if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+               cfg |= CIGCTRL_INVPOLVSYNC;
+       /*
+        * HREF is normally high during frame active data
+        * transmission and low during horizontal synchronization
+        * period. Thus HREF active high means HSYNC active low.
+        */
+       if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+               cfg |= CIGCTRL_INVPOLHREF; /* HREF active low */
+
+       if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
+               if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
+                       cfg |= CIGCTRL_INVPOLFIELD;
+               cfg |= CIGCTRL_FIELDMODE;
+       }
+
+       pr_debug("Setting CIGCTRL to: %#x\n", cfg);
+
+       camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
+}
+
+void camif_hw_set_output_addr(struct camif_vp *vp,
+                             struct camif_addr *paddr, int i)
+{
+       struct camif_dev *camif = vp->camif;
+
+       camif_write(camif, S3C_CAMIF_REG_CIYSA(vp->id, i), paddr->y);
+       if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV
+               || vp->id == VP_CODEC) {
+               camif_write(camif, S3C_CAMIF_REG_CICBSA(vp->id, i),
+                                                               paddr->cb);
+               camif_write(camif, S3C_CAMIF_REG_CICRSA(vp->id, i),
+                                                               paddr->cr);
+       }
+
+       pr_debug("dst_buf[%d]: %#X, cb: %#X, cr: %#X\n",
+                i, paddr->y, paddr->cb, paddr->cr);
+}
+
+static void camif_hw_set_out_dma_size(struct camif_vp *vp)
+{
+       struct camif_frame *frame = &vp->out_frame;
+       u32 cfg;
+
+       cfg = camif_read(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
+       cfg &= ~CITRGFMT_TARGETSIZE_MASK;
+       cfg |= (frame->f_width << 16) | frame->f_height;
+       camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
+}
+
+static void camif_get_dma_burst(u32 width, u32 ybpp, u32 *mburst, u32 *rburst)
+{
+       unsigned int nwords = width * ybpp / 4;
+       unsigned int div, rem;
+
+       if (WARN_ON(width < 8 || (width * ybpp) & 7))
+               return;
+
+       for (div = 16; div >= 2; div /= 2) {
+               if (nwords < div)
+                       continue;
+
+               rem = nwords & (div - 1);
+               if (rem == 0) {
+                       *mburst = div;
+                       *rburst = div;
+                       break;
+               }
+               if (rem == div / 2 || rem == div / 4) {
+                       *mburst = div;
+                       *rburst = rem;
+                       break;
+               }
+       }
+}
+
+void camif_hw_set_output_dma(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       struct camif_frame *frame = &vp->out_frame;
+       const struct camif_fmt *fmt = vp->out_fmt;
+       unsigned int ymburst = 0, yrburst = 0;
+       u32 cfg;
+
+       camif_hw_set_out_dma_size(vp);
+
+       if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
+               struct camif_dma_offset *offset = &frame->dma_offset;
+               /* Set the input dma offsets. */
+               cfg = S3C_CISS_OFFS_INITIAL(offset->initial);
+               cfg |= S3C_CISS_OFFS_LINE(offset->line);
+               camif_write(camif, S3C_CAMIF_REG_CISSY(vp->id), cfg);
+               camif_write(camif, S3C_CAMIF_REG_CISSCB(vp->id), cfg);
+               camif_write(camif, S3C_CAMIF_REG_CISSCR(vp->id), cfg);
+       }
+
+       /* Configure DMA burst values */
+       camif_get_dma_burst(frame->rect.width, fmt->ybpp, &ymburst, &yrburst);
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset));
+       cfg &= ~CICTRL_BURST_MASK;
+
+       cfg |= CICTRL_YBURST1(ymburst) | CICTRL_YBURST2(yrburst);
+       cfg |= CICTRL_CBURST1(ymburst / 2) | CICTRL_CBURST2(yrburst / 2);
+
+       camif_write(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset), cfg);
+
+       pr_debug("ymburst: %u, yrburst: %u\n", ymburst, yrburst);
+}
+
+void camif_hw_set_input_path(struct camif_vp *vp)
+{
+       u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id));
+       cfg &= ~MSCTRL_SEL_DMA_CAM;
+       camif_write(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id), cfg);
+}
+
+void camif_hw_set_target_format(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       struct camif_frame *frame = &vp->out_frame;
+       u32 cfg;
+
+       pr_debug("fw: %d, fh: %d color: %d\n", frame->f_width,
+                frame->f_height, vp->out_fmt->color);
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
+       cfg &= ~CITRGFMT_TARGETSIZE_MASK;
+
+       if (camif->variant->ip_revision == S3C244X_CAMIF_IP_REV) {
+               /* We currently support only YCbCr 4:2:2 at the camera input */
+               cfg |= CITRGFMT_IN422;
+               cfg &= ~CITRGFMT_OUT422;
+               if (vp->out_fmt->color == IMG_FMT_YCBCR422P)
+                       cfg |= CITRGFMT_OUT422;
+       } else {
+               cfg &= ~CITRGFMT_OUTFORMAT_MASK;
+               switch (vp->out_fmt->color) {
+               case IMG_FMT_RGB565...IMG_FMT_XRGB8888:
+                       cfg |= CITRGFMT_OUTFORMAT_RGB;
+                       break;
+               case IMG_FMT_YCBCR420...IMG_FMT_YCRCB420:
+                       cfg |= CITRGFMT_OUTFORMAT_YCBCR420;
+                       break;
+               case IMG_FMT_YCBCR422P:
+                       cfg |= CITRGFMT_OUTFORMAT_YCBCR422;
+                       break;
+               case IMG_FMT_YCBYCR422...IMG_FMT_CRYCBY422:
+                       cfg |= CITRGFMT_OUTFORMAT_YCBCR422I;
+                       break;
+               }
+       }
+
+       /* Rotation is only supported by s3c64xx */
+       if (vp->rotation == 90 || vp->rotation == 270)
+               cfg |= (frame->f_height << 16) | frame->f_width;
+       else
+               cfg |= (frame->f_width << 16) | frame->f_height;
+       camif_write(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
+
+       /* Target area, output pixel width * height */
+       cfg = camif_read(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset));
+       cfg &= ~CITAREA_MASK;
+       cfg |= (frame->f_width * frame->f_height);
+       camif_write(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset), cfg);
+}
+
+void camif_hw_set_flip(struct camif_vp *vp)
+{
+       u32 cfg = camif_read(vp->camif,
+                               S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
+
+       cfg &= ~CITRGFMT_FLIP_MASK;
+
+       if (vp->hflip)
+               cfg |= CITRGFMT_FLIP_Y_MIRROR;
+       if (vp->vflip)
+               cfg |= CITRGFMT_FLIP_X_MIRROR;
+
+       camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
+}
+
+static void camif_hw_set_prescaler(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       struct camif_scaler *sc = &vp->scaler;
+       u32 cfg, shfactor, addr;
+
+       addr = S3C_CAMIF_REG_CISCPRERATIO(vp->id, vp->offset);
+
+       shfactor = 10 - (sc->h_shift + sc->v_shift);
+       cfg = shfactor << 28;
+
+       cfg |= (sc->pre_h_ratio << 16) | sc->pre_v_ratio;
+       camif_write(camif, addr, cfg);
+
+       cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
+       camif_write(camif, S3C_CAMIF_REG_CISCPREDST(vp->id, vp->offset), cfg);
+}
+
+void camif_s3c244x_hw_set_scaler(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       struct camif_scaler *scaler = &vp->scaler;
+       unsigned int color = vp->out_fmt->color;
+       u32 cfg;
+
+       camif_hw_set_prescaler(vp);
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
+
+       cfg &= ~(CISCCTRL_SCALEUP_MASK | CISCCTRL_SCALERBYPASS |
+                CISCCTRL_MAIN_RATIO_MASK | CIPRSCCTRL_RGB_FORMAT_24BIT);
+
+       if (scaler->enable) {
+               if (scaler->scaleup_h) {
+                       if (vp->id == VP_CODEC)
+                               cfg |= CISCCTRL_SCALEUP_H;
+                       else
+                               cfg |= CIPRSCCTRL_SCALEUP_H;
+               }
+               if (scaler->scaleup_v) {
+                       if (vp->id == VP_CODEC)
+                               cfg |= CISCCTRL_SCALEUP_V;
+                       else
+                               cfg |= CIPRSCCTRL_SCALEUP_V;
+               }
+       } else {
+               if (vp->id == VP_CODEC)
+                       cfg |= CISCCTRL_SCALERBYPASS;
+       }
+
+       cfg |= ((scaler->main_h_ratio & 0x1ff) << 16);
+       cfg |= scaler->main_v_ratio & 0x1ff;
+
+       if (vp->id == VP_PREVIEW) {
+               if (color == IMG_FMT_XRGB8888)
+                       cfg |= CIPRSCCTRL_RGB_FORMAT_24BIT;
+               cfg |= CIPRSCCTRL_SAMPLE;
+       }
+
+       camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
+
+       pr_debug("main: h_ratio: %#x, v_ratio: %#x",
+                scaler->main_h_ratio, scaler->main_v_ratio);
+}
+
+void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       struct camif_scaler *scaler = &vp->scaler;
+       unsigned int color = vp->out_fmt->color;
+       u32 cfg;
+
+       camif_hw_set_prescaler(vp);
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
+
+       cfg &= ~(CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE
+               | CISCCTRL_SCALEUP_H | CISCCTRL_SCALEUP_V
+               | CISCCTRL_SCALERBYPASS | CISCCTRL_ONE2ONE
+               | CISCCTRL_INRGB_FMT_MASK | CISCCTRL_OUTRGB_FMT_MASK
+               | CISCCTRL_INTERLACE | CISCCTRL_EXTRGB_EXTENSION
+               | CISCCTRL_MAIN_RATIO_MASK);
+
+       cfg |= (CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE);
+
+       if (!scaler->enable) {
+               cfg |= CISCCTRL_SCALERBYPASS;
+       } else {
+               if (scaler->scaleup_h)
+                       cfg |= CISCCTRL_SCALEUP_H;
+               if (scaler->scaleup_v)
+                       cfg |= CISCCTRL_SCALEUP_V;
+               if (scaler->copy)
+                       cfg |= CISCCTRL_ONE2ONE;
+       }
+
+       switch (color) {
+       case IMG_FMT_RGB666:
+               cfg |= CISCCTRL_OUTRGB_FMT_RGB666;
+               break;
+       case IMG_FMT_XRGB8888:
+               cfg |= CISCCTRL_OUTRGB_FMT_RGB888;
+               break;
+       }
+
+       cfg |= (scaler->main_h_ratio & 0x1ff) << 16;
+       cfg |= scaler->main_v_ratio & 0x1ff;
+
+       camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
+
+       pr_debug("main: h_ratio: %#x, v_ratio: %#x",
+                scaler->main_h_ratio, scaler->main_v_ratio);
+}
+
+void camif_hw_set_scaler(struct camif_vp *vp)
+{
+       unsigned int ip_rev = vp->camif->variant->ip_revision;
+
+       if (ip_rev == S3C244X_CAMIF_IP_REV)
+               camif_s3c244x_hw_set_scaler(vp);
+       else
+               camif_s3c64xx_hw_set_scaler(vp);
+}
+
+void camif_hw_enable_scaler(struct camif_vp *vp, bool on)
+{
+       u32 addr = S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset);
+       u32 cfg;
+
+       cfg = camif_read(vp->camif, addr);
+       if (on)
+               cfg |= CISCCTRL_SCALERSTART;
+       else
+               cfg &= ~CISCCTRL_SCALERSTART;
+       camif_write(vp->camif, addr, cfg);
+}
+
+void camif_hw_set_lastirq(struct camif_vp *vp, int enable)
+{
+       u32 addr = S3C_CAMIF_REG_CICTRL(vp->id, vp->offset);
+       u32 cfg;
+
+       cfg = camif_read(vp->camif, addr);
+       if (enable)
+               cfg |= CICTRL_LASTIRQ_ENABLE;
+       else
+               cfg &= ~CICTRL_LASTIRQ_ENABLE;
+       camif_write(vp->camif, addr, cfg);
+}
+
+void camif_hw_enable_capture(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       u32 cfg;
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
+       camif->stream_count++;
+
+       if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
+               cfg |= CIIMGCPT_CPT_FREN_ENABLE(vp->id);
+
+       if (vp->scaler.enable)
+               cfg |= CIIMGCPT_IMGCPTEN_SC(vp->id);
+
+       if (camif->stream_count == 1)
+               cfg |= CIIMGCPT_IMGCPTEN;
+
+       camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
+
+       pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
+                cfg, camif->stream_count);
+}
+
+void camif_hw_disable_capture(struct camif_vp *vp)
+{
+       struct camif_dev *camif = vp->camif;
+       u32 cfg;
+
+       cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
+       cfg &= ~CIIMGCPT_IMGCPTEN_SC(vp->id);
+
+       if (WARN_ON(--(camif->stream_count) < 0))
+               camif->stream_count = 0;
+
+       if (camif->stream_count == 0)
+               cfg &= ~CIIMGCPT_IMGCPTEN;
+
+       pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
+                cfg, camif->stream_count);
+
+       camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
+}
+
+void camif_hw_dump_regs(struct camif_dev *camif, const char *label)
+{
+       struct {
+               u32 offset;
+               const char * const name;
+       } registers[] = {
+               { S3C_CAMIF_REG_CISRCFMT,               "CISRCFMT" },
+               { S3C_CAMIF_REG_CIWDOFST,               "CIWDOFST" },
+               { S3C_CAMIF_REG_CIGCTRL,                "CIGCTRL" },
+               { S3C_CAMIF_REG_CIWDOFST2,              "CIWDOFST2" },
+               { S3C_CAMIF_REG_CIYSA(0, 0),            "CICOYSA0" },
+               { S3C_CAMIF_REG_CICBSA(0, 0),           "CICOCBSA0" },
+               { S3C_CAMIF_REG_CICRSA(0, 0),           "CICOCRSA0" },
+               { S3C_CAMIF_REG_CIYSA(0, 1),            "CICOYSA1" },
+               { S3C_CAMIF_REG_CICBSA(0, 1),           "CICOCBSA1" },
+               { S3C_CAMIF_REG_CICRSA(0, 1),           "CICOCRSA1" },
+               { S3C_CAMIF_REG_CIYSA(0, 2),            "CICOYSA2" },
+               { S3C_CAMIF_REG_CICBSA(0, 2),           "CICOCBSA2" },
+               { S3C_CAMIF_REG_CICRSA(0, 2),           "CICOCRSA2" },
+               { S3C_CAMIF_REG_CIYSA(0, 3),            "CICOYSA3" },
+               { S3C_CAMIF_REG_CICBSA(0, 3),           "CICOCBSA3" },
+               { S3C_CAMIF_REG_CICRSA(0, 3),           "CICOCRSA3" },
+               { S3C_CAMIF_REG_CIYSA(1, 0),            "CIPRYSA0" },
+               { S3C_CAMIF_REG_CIYSA(1, 1),            "CIPRYSA1" },
+               { S3C_CAMIF_REG_CIYSA(1, 2),            "CIPRYSA2" },
+               { S3C_CAMIF_REG_CIYSA(1, 3),            "CIPRYSA3" },
+               { S3C_CAMIF_REG_CITRGFMT(0, 0),         "CICOTRGFMT" },
+               { S3C_CAMIF_REG_CITRGFMT(1, 0),         "CIPRTRGFMT" },
+               { S3C_CAMIF_REG_CICTRL(0, 0),           "CICOCTRL" },
+               { S3C_CAMIF_REG_CICTRL(1, 0),           "CIPRCTRL" },
+               { S3C_CAMIF_REG_CISCPREDST(0, 0),       "CICOSCPREDST" },
+               { S3C_CAMIF_REG_CISCPREDST(1, 0),       "CIPRSCPREDST" },
+               { S3C_CAMIF_REG_CISCPRERATIO(0, 0),     "CICOSCPRERATIO" },
+               { S3C_CAMIF_REG_CISCPRERATIO(1, 0),     "CIPRSCPRERATIO" },
+               { S3C_CAMIF_REG_CISCCTRL(0, 0),         "CICOSCCTRL" },
+               { S3C_CAMIF_REG_CISCCTRL(1, 0),         "CIPRSCCTRL" },
+               { S3C_CAMIF_REG_CITAREA(0, 0),          "CICOTAREA" },
+               { S3C_CAMIF_REG_CITAREA(1, 0),          "CIPRTAREA" },
+               { S3C_CAMIF_REG_CISTATUS(0, 0),         "CICOSTATUS" },
+               { S3C_CAMIF_REG_CISTATUS(1, 0),         "CIPRSTATUS" },
+               { S3C_CAMIF_REG_CIIMGCPT(0),            "CIIMGCPT" },
+       };
+       u32 i;
+
+       pr_info("--- %s ---\n", label);
+       for (i = 0; i < ARRAY_SIZE(registers); i++) {
+               u32 cfg = readl(camif->io_base + registers[i].offset);
+               printk(KERN_INFO "%s:\t0x%08x\n", registers[i].name, cfg);
+       }
+}
diff --git a/drivers/media/platform/s3c-camif/camif-regs.h b/drivers/media/platform/s3c-camif/camif-regs.h
new file mode 100644 (file)
index 0000000..af2d472
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Register definition file for s3c24xx/s3c64xx SoC CAMIF driver
+ *
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+ * Copyright (C) 2012 Tomasz Figa <tomasz.figa@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.
+*/
+
+#ifndef CAMIF_REGS_H_
+#define CAMIF_REGS_H_
+
+#include "camif-core.h"
+#include <media/s3c_camif.h>
+
+/*
+ * The id argument indicates the processing path:
+ * id = 0 - codec (FIMC C), 1 - preview (FIMC P).
+ */
+
+/* Camera input format */
+#define S3C_CAMIF_REG_CISRCFMT                 0x00
+#define  CISRCFMT_ITU601_8BIT                  (1 << 31)
+#define  CISRCFMT_ITU656_8BIT                  (0 << 31)
+#define  CISRCFMT_ORDER422_YCBYCR              (0 << 14)
+#define  CISRCFMT_ORDER422_YCRYCB              (1 << 14)
+#define  CISRCFMT_ORDER422_CBYCRY              (2 << 14)
+#define  CISRCFMT_ORDER422_CRYCBY              (3 << 14)
+#define  CISRCFMT_ORDER422_MASK                        (3 << 14)
+#define  CISRCFMT_SIZE_CAM_MASK                        (0x1fff << 16 | 0x1fff)
+
+/* Window offset */
+#define S3C_CAMIF_REG_CIWDOFST                 0x04
+#define  CIWDOFST_WINOFSEN                     (1 << 31)
+#define  CIWDOFST_CLROVCOFIY                   (1 << 30)
+#define  CIWDOFST_CLROVRLB_PR                  (1 << 28)
+/* #define  CIWDOFST_CLROVPRFIY                        (1 << 27) */
+#define  CIWDOFST_CLROVCOFICB                  (1 << 15)
+#define  CIWDOFST_CLROVCOFICR                  (1 << 14)
+#define  CIWDOFST_CLROVPRFICB                  (1 << 13)
+#define  CIWDOFST_CLROVPRFICR                  (1 << 12)
+#define  CIWDOFST_OFST_MASK                    (0x7ff << 16 | 0x7ff)
+
+/* Window offset 2 */
+#define S3C_CAMIF_REG_CIWDOFST2                        0x14
+#define  CIWDOFST2_OFST2_MASK                  (0xfff << 16 | 0xfff)
+
+/* Global control */
+#define S3C_CAMIF_REG_CIGCTRL                  0x08
+#define  CIGCTRL_SWRST                         (1 << 31)
+#define  CIGCTRL_CAMRST                                (1 << 30)
+#define  CIGCTRL_TESTPATTERN_NORMAL            (0 << 27)
+#define  CIGCTRL_TESTPATTERN_COLOR_BAR         (1 << 27)
+#define  CIGCTRL_TESTPATTERN_HOR_INC           (2 << 27)
+#define  CIGCTRL_TESTPATTERN_VER_INC           (3 << 27)
+#define  CIGCTRL_TESTPATTERN_MASK              (3 << 27)
+#define  CIGCTRL_INVPOLPCLK                    (1 << 26)
+#define  CIGCTRL_INVPOLVSYNC                   (1 << 25)
+#define  CIGCTRL_INVPOLHREF                    (1 << 24)
+#define  CIGCTRL_IRQ_OVFEN                     (1 << 22)
+#define  CIGCTRL_HREF_MASK                     (1 << 21)
+#define  CIGCTRL_IRQ_LEVEL                     (1 << 20)
+/* IRQ_CLR_C, IRQ_CLR_P */
+#define  CIGCTRL_IRQ_CLR(id)                   (1 << (19 - (id)))
+#define  CIGCTRL_FIELDMODE                     (1 << 2)
+#define  CIGCTRL_INVPOLFIELD                   (1 << 1)
+#define  CIGCTRL_CAM_INTERLACE                 (1 << 0)
+
+/* Y DMA output frame start address. n = 0..3. */
+#define S3C_CAMIF_REG_CIYSA(id, n)             (0x18 + (id) * 0x54 + (n) * 4)
+/* Cb plane output DMA start address. n = 0..3. Only codec path. */
+#define S3C_CAMIF_REG_CICBSA(id, n)            (0x28 + (id) * 0x54 + (n) * 4)
+/* Cr plane output DMA start address. n = 0..3. Only codec path. */
+#define S3C_CAMIF_REG_CICRSA(id, n)            (0x38 + (id) * 0x54 + (n) * 4)
+
+/* CICOTRGFMT, CIPRTRGFMT - Target format */
+#define S3C_CAMIF_REG_CITRGFMT(id, _offs)      (0x48 + (id) * (0x34 + (_offs)))
+#define  CITRGFMT_IN422                                (1 << 31) /* only for s3c24xx */
+#define  CITRGFMT_OUT422                       (1 << 30) /* only for s3c24xx */
+#define  CITRGFMT_OUTFORMAT_YCBCR420           (0 << 29) /* only for s3c6410 */
+#define  CITRGFMT_OUTFORMAT_YCBCR422           (1 << 29) /* only for s3c6410 */
+#define  CITRGFMT_OUTFORMAT_YCBCR422I          (2 << 29) /* only for s3c6410 */
+#define  CITRGFMT_OUTFORMAT_RGB                        (3 << 29) /* only for s3c6410 */
+#define  CITRGFMT_OUTFORMAT_MASK               (3 << 29) /* only for s3c6410 */
+#define  CITRGFMT_TARGETHSIZE(x)               ((x) << 16)
+#define  CITRGFMT_FLIP_NORMAL                  (0 << 14)
+#define  CITRGFMT_FLIP_X_MIRROR                        (1 << 14)
+#define  CITRGFMT_FLIP_Y_MIRROR                        (2 << 14)
+#define  CITRGFMT_FLIP_180                     (3 << 14)
+#define  CITRGFMT_FLIP_MASK                    (3 << 14)
+/* Preview path only */
+#define  CITRGFMT_ROT90_PR                     (1 << 13)
+#define  CITRGFMT_TARGETVSIZE(x)               ((x) << 0)
+#define  CITRGFMT_TARGETSIZE_MASK              ((0x1fff << 16) | 0x1fff)
+
+/* CICOCTRL, CIPRCTRL. Output DMA control. */
+#define S3C_CAMIF_REG_CICTRL(id, _offs)                (0x4c + (id) * (0x34 + (_offs)))
+#define  CICTRL_BURST_MASK                     (0xfffff << 4)
+/* xBURSTn - 5-bits width */
+#define  CICTRL_YBURST1(x)                     ((x) << 19)
+#define  CICTRL_YBURST2(x)                     ((x) << 14)
+#define  CICTRL_RGBBURST1(x)                   ((x) << 19)
+#define  CICTRL_RGBBURST2(x)                   ((x) << 14)
+#define  CICTRL_CBURST1(x)                     ((x) << 9)
+#define  CICTRL_CBURST2(x)                     ((x) << 4)
+#define  CICTRL_LASTIRQ_ENABLE                 (1 << 2)
+#define  CICTRL_ORDER422_MASK                  (3 << 0)
+
+/* CICOSCPRERATIO, CIPRSCPRERATIO. Pre-scaler control 1. */
+#define S3C_CAMIF_REG_CISCPRERATIO(id, _offs)  (0x50 + (id) * (0x34 + (_offs)))
+
+/* CICOSCPREDST, CIPRSCPREDST. Pre-scaler control 2. */
+#define S3C_CAMIF_REG_CISCPREDST(id, _offs)    (0x54 + (id) * (0x34 + (_offs)))
+
+/* CICOSCCTRL, CIPRSCCTRL. Main scaler control. */
+#define S3C_CAMIF_REG_CISCCTRL(id, _offs)      (0x58 + (id) * (0x34 + (_offs)))
+#define  CISCCTRL_SCALERBYPASS                 (1 << 31)
+/* s3c244x preview path only, s3c64xx both */
+#define  CIPRSCCTRL_SAMPLE                     (1 << 31)
+/* 0 - 16-bit RGB, 1 - 24-bit RGB */
+#define  CIPRSCCTRL_RGB_FORMAT_24BIT           (1 << 30) /* only for s3c244x */
+#define  CIPRSCCTRL_SCALEUP_H                  (1 << 29) /* only for s3c244x */
+#define  CIPRSCCTRL_SCALEUP_V                  (1 << 28) /* only for s3c244x */
+/* s3c64xx */
+#define  CISCCTRL_SCALEUP_H                    (1 << 30)
+#define  CISCCTRL_SCALEUP_V                    (1 << 29)
+#define  CISCCTRL_SCALEUP_MASK                 (0x3 << 29)
+#define  CISCCTRL_CSCR2Y_WIDE                  (1 << 28)
+#define  CISCCTRL_CSCY2R_WIDE                  (1 << 27)
+#define  CISCCTRL_LCDPATHEN_FIFO               (1 << 26)
+#define  CISCCTRL_INTERLACE                    (1 << 25)
+#define  CISCCTRL_SCALERSTART                  (1 << 15)
+#define  CISCCTRL_INRGB_FMT_RGB565             (0 << 13)
+#define  CISCCTRL_INRGB_FMT_RGB666             (1 << 13)
+#define  CISCCTRL_INRGB_FMT_RGB888             (2 << 13)
+#define  CISCCTRL_INRGB_FMT_MASK               (3 << 13)
+#define  CISCCTRL_OUTRGB_FMT_RGB565            (0 << 11)
+#define  CISCCTRL_OUTRGB_FMT_RGB666            (1 << 11)
+#define  CISCCTRL_OUTRGB_FMT_RGB888            (2 << 11)
+#define  CISCCTRL_OUTRGB_FMT_MASK              (3 << 11)
+#define  CISCCTRL_EXTRGB_EXTENSION             (1 << 10)
+#define  CISCCTRL_ONE2ONE                      (1 << 9)
+#define  CISCCTRL_MAIN_RATIO_MASK              (0x1ff << 16 | 0x1ff)
+
+/* CICOTAREA, CIPRTAREA. Target area for DMA (Hsize x Vsize). */
+#define S3C_CAMIF_REG_CITAREA(id, _offs)       (0x5c + (id) * (0x34 + (_offs)))
+#define CITAREA_MASK                           0xfffffff
+
+/* Codec (id = 0) or preview (id = 1) path status. */
+#define S3C_CAMIF_REG_CISTATUS(id, _offs)      (0x64 + (id) * (0x34 + (_offs)))
+#define  CISTATUS_OVFIY_STATUS                 (1 << 31)
+#define  CISTATUS_OVFICB_STATUS                        (1 << 30)
+#define  CISTATUS_OVFICR_STATUS                        (1 << 29)
+#define  CISTATUS_OVF_MASK                     (0x7 << 29)
+#define  CIPRSTATUS_OVF_MASK                   (0x3 << 30)
+#define  CISTATUS_VSYNC_STATUS                 (1 << 28)
+#define  CISTATUS_FRAMECNT_MASK                        (3 << 26)
+#define  CISTATUS_FRAMECNT(__reg)              (((__reg) >> 26) & 0x3)
+#define  CISTATUS_WINOFSTEN_STATUS             (1 << 25)
+#define  CISTATUS_IMGCPTEN_STATUS              (1 << 22)
+#define  CISTATUS_IMGCPTENSC_STATUS            (1 << 21)
+#define  CISTATUS_VSYNC_A_STATUS               (1 << 20)
+#define  CISTATUS_FRAMEEND_STATUS              (1 << 19) /* 17 on s3c64xx */
+
+/* Image capture enable */
+#define S3C_CAMIF_REG_CIIMGCPT(_offs)          (0xa0 + (_offs))
+#define  CIIMGCPT_IMGCPTEN                     (1 << 31)
+#define  CIIMGCPT_IMGCPTEN_SC(id)              (1 << (30 - (id)))
+/* Frame control: 1 - one-shot, 0 - free run */
+#define  CIIMGCPT_CPT_FREN_ENABLE(id)          (1 << (25 - (id)))
+#define  CIIMGCPT_CPT_FRMOD_ENABLE             (0 << 18)
+#define  CIIMGCPT_CPT_FRMOD_CNT                        (1 << 18)
+
+/* Capture sequence */
+#define S3C_CAMIF_REG_CICPTSEQ                 0xc4
+
+/* Image effects */
+#define S3C_CAMIF_REG_CIIMGEFF(_offs)          (0xb0 + (_offs))
+#define  CIIMGEFF_IE_ENABLE(id)                        (1 << (30 + (id)))
+#define  CIIMGEFF_IE_ENABLE_MASK               (3 << 30)
+/* Image effect: 1 - after scaler, 0 - before scaler */
+#define  CIIMGEFF_IE_AFTER_SC                  (1 << 29)
+#define  CIIMGEFF_FIN_MASK                     (7 << 26)
+#define  CIIMGEFF_FIN_BYPASS                   (0 << 26)
+#define  CIIMGEFF_FIN_ARBITRARY                        (1 << 26)
+#define  CIIMGEFF_FIN_NEGATIVE                 (2 << 26)
+#define  CIIMGEFF_FIN_ARTFREEZE                        (3 << 26)
+#define  CIIMGEFF_FIN_EMBOSSING                        (4 << 26)
+#define  CIIMGEFF_FIN_SILHOUETTE               (5 << 26)
+#define  CIIMGEFF_PAT_CBCR_MASK                        ((0xff << 13) | 0xff)
+#define  CIIMGEFF_PAT_CB(x)                    ((x) << 13)
+#define  CIIMGEFF_PAT_CR(x)                    (x)
+
+/* MSCOY0SA, MSPRY0SA. Y/Cb/Cr frame start address for input DMA. */
+#define S3C_CAMIF_REG_MSY0SA(id)               (0xd4 + ((id) * 0x2c))
+#define S3C_CAMIF_REG_MSCB0SA(id)              (0xd8 + ((id) * 0x2c))
+#define S3C_CAMIF_REG_MSCR0SA(id)              (0xdc + ((id) * 0x2c))
+
+/* MSCOY0END, MSCOY0END. Y/Cb/Cr frame end address for input DMA. */
+#define S3C_CAMIF_REG_MSY0END(id)              (0xe0 + ((id) * 0x2c))
+#define S3C_CAMIF_REG_MSCB0END(id)             (0xe4 + ((id) * 0x2c))
+#define S3C_CAMIF_REG_MSCR0END(id)             (0xe8 + ((id) * 0x2c))
+
+/* MSPRYOFF, MSPRYOFF. Y/Cb/Cr offset. n: 0 - codec, 1 - preview. */
+#define S3C_CAMIF_REG_MSYOFF(id)               (0x118 + ((id) * 0x2c))
+#define S3C_CAMIF_REG_MSCBOFF(id)              (0x11c + ((id) * 0x2c))
+#define S3C_CAMIF_REG_MSCROFF(id)              (0x120 + ((id) * 0x2c))
+
+/* Real input DMA data size. n = 0 - codec, 1 - preview. */
+#define S3C_CAMIF_REG_MSWIDTH(id)              (0xf8 + (id) * 0x2c)
+#define  AUTOLOAD_ENABLE                       (1 << 31)
+#define  ADDR_CH_DIS                           (1 << 30)
+#define  MSHEIGHT(x)                           (((x) & 0x3ff) << 16)
+#define  MSWIDTH(x)                            ((x) & 0x3ff)
+
+/* Input DMA control. n = 0 - codec, 1 - preview */
+#define S3C_CAMIF_REG_MSCTRL(id)               (0xfc + (id) * 0x2c)
+#define  MSCTRL_ORDER422_M_YCBYCR              (0 << 4)
+#define  MSCTRL_ORDER422_M_YCRYCB              (1 << 4)
+#define  MSCTRL_ORDER422_M_CBYCRY              (2 << 4)
+#define  MSCTRL_ORDER422_M_CRYCBY              (3 << 4)
+/* 0 - camera, 1 - DMA */
+#define  MSCTRL_SEL_DMA_CAM                    (1 << 3)
+#define  MSCTRL_INFORMAT_M_YCBCR420            (0 << 1)
+#define  MSCTRL_INFORMAT_M_YCBCR422            (1 << 1)
+#define  MSCTRL_INFORMAT_M_YCBCR422I           (2 << 1)
+#define  MSCTRL_INFORMAT_M_RGB                 (3 << 1)
+#define  MSCTRL_ENVID_M                                (1 << 0)
+
+/* CICOSCOSY, CIPRSCOSY. Scan line Y/Cb/Cr offset. */
+#define S3C_CAMIF_REG_CISSY(id)                        (0x12c + (id) * 0x0c)
+#define S3C_CAMIF_REG_CISSCB(id)               (0x130 + (id) * 0x0c)
+#define S3C_CAMIF_REG_CISSCR(id)               (0x134 + (id) * 0x0c)
+#define S3C_CISS_OFFS_INITIAL(x)               ((x) << 16)
+#define S3C_CISS_OFFS_LINE(x)                  ((x) << 0)
+
+/* ------------------------------------------------------------------ */
+
+void camif_hw_reset(struct camif_dev *camif);
+void camif_hw_clear_pending_irq(struct camif_vp *vp);
+void camif_hw_clear_fifo_overflow(struct camif_vp *vp);
+void camif_hw_set_lastirq(struct camif_vp *vp, int enable);
+void camif_hw_set_input_path(struct camif_vp *vp);
+void camif_hw_enable_scaler(struct camif_vp *vp, bool on);
+void camif_hw_enable_capture(struct camif_vp *vp);
+void camif_hw_disable_capture(struct camif_vp *vp);
+void camif_hw_set_camera_bus(struct camif_dev *camif);
+void camif_hw_set_source_format(struct camif_dev *camif);
+void camif_hw_set_camera_crop(struct camif_dev *camif);
+void camif_hw_set_scaler(struct camif_vp *vp);
+void camif_hw_set_flip(struct camif_vp *vp);
+void camif_hw_set_output_dma(struct camif_vp *vp);
+void camif_hw_set_target_format(struct camif_vp *vp);
+void camif_hw_set_test_pattern(struct camif_dev *camif, unsigned int pattern);
+void camif_hw_set_effect(struct camif_dev *camif, unsigned int effect,
+                       unsigned int cr, unsigned int cb);
+void camif_hw_set_output_addr(struct camif_vp *vp, struct camif_addr *paddr,
+                             int index);
+void camif_hw_dump_regs(struct camif_dev *camif, const char *label);
+
+static inline u32 camif_hw_get_status(struct camif_vp *vp)
+{
+       return readl(vp->camif->io_base + S3C_CAMIF_REG_CISTATUS(vp->id,
+                                                               vp->offset));
+}
+
+#endif /* CAMIF_REGS_H_ */
index 891ee873c62b8c281cf83f74cf1b29b1925a0f55..fdb6740248a73f58bd2c7ab42c72f03991d907f0 100644 (file)
@@ -1230,6 +1230,14 @@ static int fimc_cap_qbuf(struct file *file, void *priv,
        return vb2_qbuf(&fimc->vid_cap.vbq, buf);
 }
 
+static int fimc_cap_expbuf(struct file *file, void *priv,
+                         struct v4l2_exportbuffer *eb)
+{
+       struct fimc_dev *fimc = video_drvdata(file);
+
+       return vb2_expbuf(&fimc->vid_cap.vbq, eb);
+}
+
 static int fimc_cap_dqbuf(struct file *file, void *priv,
                           struct v4l2_buffer *buf)
 {
@@ -1354,6 +1362,7 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
 
        .vidioc_qbuf                    = fimc_cap_qbuf,
        .vidioc_dqbuf                   = fimc_cap_dqbuf,
+       .vidioc_expbuf                  = fimc_cap_expbuf,
 
        .vidioc_prepare_buf             = fimc_cap_prepare_buf,
        .vidioc_create_bufs             = fimc_cap_create_bufs,
@@ -1729,7 +1738,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
        q = &fimc->vid_cap.vbq;
        memset(q, 0, sizeof(*q));
        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       q->io_modes = VB2_MMAP | VB2_USERPTR;
+       q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
        q->drv_priv = fimc->vid_cap.ctx;
        q->ops = &fimc_capture_qops;
        q->mem_ops = &vb2_dma_contig_memops;
index 62afed3162eaec518d74cd0a72b5c26a8725987a..1d21da4bd24be130dbcdd2b15032ff198390804a 100644 (file)
@@ -105,7 +105,7 @@ static void fimc_device_run(void *priv)
        struct fimc_frame *sf, *df;
        struct fimc_dev *fimc;
        unsigned long flags;
-       u32 ret;
+       int ret;
 
        if (WARN(!ctx, "Null context\n"))
                return;
@@ -439,6 +439,15 @@ static int fimc_m2m_dqbuf(struct file *file, void *fh,
        return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 }
 
+static int fimc_m2m_expbuf(struct file *file, void *fh,
+                           struct v4l2_exportbuffer *eb)
+{
+       struct fimc_ctx *ctx = fh_to_ctx(fh);
+
+       return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
+}
+
+
 static int fimc_m2m_streamon(struct file *file, void *fh,
                             enum v4l2_buf_type type)
 {
@@ -607,6 +616,7 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
        .vidioc_querybuf                = fimc_m2m_querybuf,
        .vidioc_qbuf                    = fimc_m2m_qbuf,
        .vidioc_dqbuf                   = fimc_m2m_dqbuf,
+       .vidioc_expbuf                  = fimc_m2m_expbuf,
        .vidioc_streamon                = fimc_m2m_streamon,
        .vidioc_streamoff               = fimc_m2m_streamoff,
        .vidioc_g_crop                  = fimc_m2m_g_crop,
@@ -622,7 +632,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        int ret;
 
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
        src_vq->drv_priv = ctx;
        src_vq->ops = &fimc_qops;
        src_vq->mem_ops = &vb2_dma_contig_memops;
@@ -633,7 +643,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
                return ret;
 
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
        dst_vq->drv_priv = ctx;
        dst_vq->ops = &fimc_qops;
        dst_vq->mem_ops = &vb2_dma_contig_memops;
index 0531ab70a94c42e512165d4bd3cfb5f117973d19..1bd5678cfeb9d13f4bfd4b1dc0f7ffccac5ce33b 100644 (file)
@@ -213,7 +213,7 @@ static int fimc_pipeline_close(struct fimc_pipeline *p)
  * @pipeline: video pipeline structure
  * @on: passed as the s_stream call argument
  */
-int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
+static int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
 {
        int i, ret;
 
@@ -547,7 +547,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
                if (ret)
                        break;
 
-               v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
+               v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n",
                          source->name, flags ? '=' : '-', sink->name);
 
                if (flags == 0 || sensor == NULL)
index eb6a70b0f8213285a888ee867e3346d8ca9c5770..6dad9a74f61c8bb0778a3ce12c11f0134e1a62ab 100644 (file)
@@ -636,6 +636,19 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
        return -EINVAL;
 }
 
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *eb)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_expbuf(&ctx->vq_src, eb);
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_expbuf(&ctx->vq_dst, eb);
+       return -EINVAL;
+}
+
 /* Stream on */
 static int vidioc_streamon(struct file *file, void *priv,
                           enum v4l2_buf_type type)
@@ -813,6 +826,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
        .vidioc_querybuf = vidioc_querybuf,
        .vidioc_qbuf = vidioc_qbuf,
        .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_expbuf = vidioc_expbuf,
        .vidioc_streamon = vidioc_streamon,
        .vidioc_streamoff = vidioc_streamoff,
        .vidioc_g_crop = vidioc_g_crop,
index 2af6d522f4acf3b94b142281c22edd2ce7c53c44..f92f6ddd739fc1f4cbf982ca41e9ab9a7005530d 100644 (file)
@@ -1165,6 +1165,19 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
        return ret;
 }
 
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *eb)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_expbuf(&ctx->vq_src, eb);
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_expbuf(&ctx->vq_dst, eb);
+       return -EINVAL;
+}
+
 /* Stream on */
 static int vidioc_streamon(struct file *file, void *priv,
                           enum v4l2_buf_type type)
@@ -1542,7 +1555,7 @@ int vidioc_encoder_cmd(struct file *file, void *priv,
 }
 
 static int vidioc_subscribe_event(struct v4l2_fh *fh,
-                                       struct v4l2_event_subscription *sub)
+                                 const struct v4l2_event_subscription *sub)
 {
        switch (sub->type) {
        case V4L2_EVENT_EOS:
@@ -1568,6 +1581,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
        .vidioc_querybuf = vidioc_querybuf,
        .vidioc_qbuf = vidioc_qbuf,
        .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_expbuf = vidioc_expbuf,
        .vidioc_streamon = vidioc_streamon,
        .vidioc_streamoff = vidioc_streamoff,
        .vidioc_s_parm = vidioc_s_parm,
index 367db755228932f410c6157e06f67d8ac00b477f..2895333866fcfcbda0e74ab905ac921681f17845 100644 (file)
@@ -28,7 +28,7 @@ static struct s5p_mfc_pm *pm;
 static struct s5p_mfc_dev *p_dev;
 
 #ifdef CLK_DEBUG
-atomic_t clk_ref;
+static atomic_t clk_ref;
 #endif
 
 int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
index 0c1cd895ff660453dfff91f5ac40feea5d67535d..7379e77bf4e1daf1b89ae7a3b66ba24322c18942 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/videodev2.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/timer.h>
 #include <media/videobuf2-dma-contig.h>
 
@@ -698,6 +697,15 @@ static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
        return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK);
 }
 
+static int mxr_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *eb)
+{
+       struct mxr_layer *layer = video_drvdata(file);
+
+       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       return vb2_expbuf(&layer->vb_queue, eb);
+}
+
 static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
        struct mxr_layer *layer = video_drvdata(file);
@@ -725,6 +733,7 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
        .vidioc_querybuf = mxr_querybuf,
        .vidioc_qbuf = mxr_qbuf,
        .vidioc_dqbuf = mxr_dqbuf,
+       .vidioc_expbuf = mxr_expbuf,
        /* Streaming control */
        .vidioc_streamon = mxr_streamon,
        .vidioc_streamoff = mxr_streamoff,
@@ -1093,7 +1102,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
 
        layer->vb_queue = (struct vb2_queue) {
                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
-               .io_modes = VB2_MMAP | VB2_USERPTR,
+               .io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF,
                .drv_priv = layer,
                .buf_struct_size = sizeof(struct mxr_buffer),
                .ops = &mxr_video_qops,
index 9afe1e7bde748a6b238ed45d99da4d6bdb1b7ecb..cb6791e62bd46fd26274f802100f497fa9bfc678 100644 (file)
@@ -19,6 +19,7 @@ config MX1_VIDEO
 
 config VIDEO_MX1
        tristate "i.MX1/i.MXL CMOS Sensor Interface driver"
+       depends on BROKEN
        depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA
        select FIQ
        select VIDEOBUF_DMA_CONTIG
index d3f0b84e2d7086e24b4e75a863e34d23464cda15..4e3735679f172fa3daf9620e3364a26987649da3 100644 (file)
@@ -645,11 +645,17 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
        struct soc_camera_device *icd = file->private_data;
-       int err = -EINVAL;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+       dev_dbg(icd->pdev, "read called, buf %p\n", buf);
+
+       if (ici->ops->init_videobuf2 && icd->vb2_vidq.io_modes & VB2_READ)
+               return vb2_read(&icd->vb2_vidq, buf, count, ppos,
+                               file->f_flags & O_NONBLOCK);
 
        dev_err(icd->pdev, "camera device read not implemented\n");
 
-       return err;
+       return -EINVAL;
 }
 
 static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1048,10 +1054,8 @@ static void scan_add_host(struct soc_camera_host *ici)
 
        list_for_each_entry(icd, &devices, list) {
                if (icd->iface == ici->nr) {
-                       int ret;
-
                        icd->parent = ici->v4l2_dev.dev;
-                       ret = soc_camera_probe(icd);
+                       soc_camera_probe(icd);
                }
        }
 
index b366b050a3dd487473345d1ddaee013b2740513f..0d59b9db83cb90b4d2ec1f38482111cdadbb77f5 100644 (file)
@@ -39,7 +39,6 @@
 /* Wake up at about 30 fps */
 #define WAKE_NUMERATOR 30
 #define WAKE_DENOMINATOR 1001
-#define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
 
 #define MAX_WIDTH 1920
 #define MAX_HEIGHT 1200
@@ -352,11 +351,6 @@ static void precalculate_bars(struct vivi_dev *dev)
        }
 }
 
-#define TSTAMP_MIN_Y   24
-#define TSTAMP_MAX_Y   (TSTAMP_MIN_Y + 15)
-#define TSTAMP_INPUT_X 10
-#define TSTAMP_MIN_X   (54 + TSTAMP_INPUT_X)
-
 /* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
 static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
 {
@@ -1308,7 +1302,7 @@ static int __init vivi_create_instance(int inst)
        /* initialize queue */
        q = &dev->vb_vidq;
        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+       q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
        q->drv_priv = dev;
        q->buf_struct_size = sizeof(struct vivi_buffer);
        q->ops = &vivi_video_qops;
index 12c70e876f5863587359e5da742139e8a78a6ebd..a739ad492e7b3dbbe9976f00ee27b3ec27e77f0d 100644 (file)
@@ -82,7 +82,7 @@ static struct radio_isa_card *rtrack_alloc(void)
 #define AIMS_BIT_VOL_UP                (1 << 6)        /* active low */
 #define AIMS_BIT_VOL_DN                (1 << 7)        /* active low */
 
-void rtrack_set_pins(void *handle, u8 pins)
+static void rtrack_set_pins(void *handle, u8 pins)
 {
        struct radio_isa_card *isa = handle;
        struct rtrack *rt = container_of(isa, struct rtrack, isa);
index 697a421c99406faa84df2906d41e3d4492c8bd48..643d80ac28fb1269b70942d2a53ccb7303c266b7 100644 (file)
@@ -645,7 +645,8 @@ static int __init cadet_init(void)
        set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
        video_set_drvdata(&dev->vdev, dev);
 
-       if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
+       res = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
+       if (res < 0)
                goto err_hdl;
        v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io);
        return 0;
index 3c0067de4324281537d951cf8e216eae140c04db..84b7b9f4385e7b9d9af85c810793ed5e4ef4a416 100644 (file)
@@ -191,7 +191,7 @@ static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io)
        return false;
 }
 
-struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
+static struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
                                struct device *pdev)
 {
        struct v4l2_device *v4l2_dev;
@@ -207,8 +207,9 @@ struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
        return isa;
 }
 
-int radio_isa_common_probe(struct radio_isa_card *isa, struct device *pdev,
-                               int radio_nr, unsigned region_size)
+static int radio_isa_common_probe(struct radio_isa_card *isa,
+                                 struct device *pdev,
+                                 int radio_nr, unsigned region_size)
 {
        const struct radio_isa_driver *drv = isa->drv;
        const struct radio_isa_ops *ops = drv->ops;
@@ -287,7 +288,8 @@ err_dev_reg:
        return res;
 }
 
-int radio_isa_common_remove(struct radio_isa_card *isa, unsigned region_size)
+static int radio_isa_common_remove(struct radio_isa_card *isa,
+                                  unsigned region_size)
 {
        const struct radio_isa_ops *ops = isa->drv->ops;
 
index 227dcdb54df358235111f42518686b404317b76a..c260a2a354b1d0ab7eabaa3c0166c44df1682c67 100644 (file)
@@ -64,7 +64,7 @@ bool pnp_attached;
 #define FMI_BIT_VOL_SW         (1 << 3)
 #define FMI_BIT_TUN_STRQ       (1 << 4)
 
-void fmi_set_pins(void *handle, u8 pins)
+static void fmi_set_pins(void *handle, u8 pins)
 {
        struct fmi *fmi = handle;
        u8 bits = FMI_BIT_TUN_STRQ;
index d0c905310071e9cb0eba764bef1cc5787720fbd8..36aec575e0ecd37e3ad7ddab10735684ad1c951b 100644 (file)
@@ -145,7 +145,7 @@ struct tea5764_device {
 };
 
 /* I2C code related */
-int tea5764_i2c_read(struct tea5764_device *radio)
+static int tea5764_i2c_read(struct tea5764_device *radio)
 {
        int i;
        u16 *p = (u16 *) &radio->regs;
@@ -165,7 +165,7 @@ int tea5764_i2c_read(struct tea5764_device *radio)
        return 0;
 }
 
-int tea5764_i2c_write(struct tea5764_device *radio)
+static int tea5764_i2c_write(struct tea5764_device *radio)
 {
        struct tea5764_write_regs wr;
        struct tea5764_regs *r = &radio->regs;
index e3079c142c5f87af79ee9e11a4268b7ae46c5283..bd61b3bd0ca316a05d339b12a77d02c45c1a8cd6 100644 (file)
@@ -1769,7 +1769,7 @@ exit:
 }
 
 /* si4713_ioctl - deal with private ioctls (only rnl for now) */
-long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
        struct si4713_device *sdev = to_si4713_device(sd);
        struct si4713_rnl *rnl = arg;
index d84ad9dad323c25bea0e7b0972c1e3f72295ff28..aac0f025f7678c582a08fa5a8592f53091f6124b 100644 (file)
@@ -60,7 +60,7 @@
 #define fmdbg(format, ...) \
        printk(KERN_DEBUG "fmdrv: " format, ## __VA_ARGS__)
 #else /* DEBUG */
-#define fmdbg(format, ...)
+#define fmdbg(format, ...) do {} while(0)
 #endif
 enum {
        FM_MODE_OFF,
index bf867a6b5ea0b5c745bf6684a75183e25b354843..602ef7ac8c243a62249acb0e9ead0ff7f6768f13 100644 (file)
@@ -742,7 +742,7 @@ static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *fmdev)
                if ((meta_data & FM_RDS_STATUS_ERR_MASK) != 0)
                        break;
 
-               if (blk_idx < FM_RDS_BLK_IDX_A || blk_idx > FM_RDS_BLK_IDX_D) {
+               if (blk_idx > FM_RDS_BLK_IDX_D) {
                        fmdbg("Block sequence mismatch\n");
                        rds->last_blk_idx = -1;
                        break;
index 3dd9fc097c473f5974034fdce141079e242e915e..ebf09a3927deea0f34070d54aa6e3c65b7bd1742 100644 (file)
@@ -305,7 +305,7 @@ int fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
 
-       if (vol_to_set < FM_RX_VOLUME_MIN || vol_to_set > FM_RX_VOLUME_MAX) {
+       if (vol_to_set > FM_RX_VOLUME_MAX) {
                fmerr("Volume is not within(%d-%d) range\n",
                           FM_RX_VOLUME_MIN, FM_RX_VOLUME_MAX);
                return -EINVAL;
index 49bb356ed14cabb56a2af7c5b9df9dfcb3cd1674..2d6fb26a017094a1fa23828b7ce5c546a2cdad80 100644 (file)
@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote)
 
        rdev->priv = ati_remote;
        rdev->driver_type = RC_DRIVER_SCANCODE;
-       rdev->allowed_protos = RC_TYPE_OTHER;
+       rdev->allowed_protos = RC_BIT_OTHER;
        rdev->driver_name = "ati_remote";
 
        rdev->open = ati_remote_rc_open;
index d05ac15b5de48673cafbd9825afa8925c3a3c5e7..22231dd4f62b9432039bc41fdf954c86d60415b0 100644 (file)
@@ -329,7 +329,7 @@ static int ene_rx_get_sample_reg(struct ene_device *dev)
 }
 
 /* Sense current received carrier */
-void ene_rx_sense_carrier(struct ene_device *dev)
+static void ene_rx_sense_carrier(struct ene_device *dev)
 {
        DEFINE_IR_RAW_EVENT(ev);
 
@@ -1003,7 +1003,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
        dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
        rdev = rc_allocate_device();
        if (!dev || !rdev)
-               goto error1;
+               goto failure;
 
        /* validate resources */
        error = -ENODEV;
@@ -1014,10 +1014,10 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 
        if (!pnp_port_valid(pnp_dev, 0) ||
            pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
-               goto error;
+               goto failure;
 
        if (!pnp_irq_valid(pnp_dev, 0))
-               goto error;
+               goto failure;
 
        spin_lock_init(&dev->hw_lock);
 
@@ -1033,7 +1033,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
        /* detect hardware version and features */
        error = ene_hw_detect(dev);
        if (error)
-               goto error;
+               goto failure;
 
        if (!dev->hw_learning_and_tx_capable && txsim) {
                dev->hw_learning_and_tx_capable = true;
@@ -1046,7 +1046,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
                learning_mode_force = false;
 
        rdev->driver_type = RC_DRIVER_IR_RAW;
-       rdev->allowed_protos = RC_TYPE_ALL;
+       rdev->allowed_protos = RC_BIT_ALL;
        rdev->priv = dev;
        rdev->open = ene_open;
        rdev->close = ene_close;
@@ -1078,30 +1078,27 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
        /* claim the resources */
        error = -EBUSY;
        if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
-               dev->hw_io = -1;
-               dev->irq = -1;
-               goto error;
+               goto failure;
        }
 
        dev->irq = pnp_irq(pnp_dev, 0);
        if (request_irq(dev->irq, ene_isr,
                        IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
-               dev->irq = -1;
-               goto error;
+               goto failure2;
        }
 
        error = rc_register_device(rdev);
        if (error < 0)
-               goto error;
+               goto failure3;
 
        pr_notice("driver has been successfully loaded\n");
        return 0;
-error:
-       if (dev && dev->irq >= 0)
-               free_irq(dev->irq, dev);
-       if (dev && dev->hw_io >= 0)
-               release_region(dev->hw_io, ENE_IO_SIZE);
-error1:
+
+failure3:
+       free_irq(dev->irq, dev);
+failure2:
+       release_region(dev->hw_io, ENE_IO_SIZE);
+failure:
        rc_free_device(rdev);
        kfree(dev);
        return error;
index 52fd7696b1ba8c7e5bccc9321fd8bd7f4a8fd105..936c3f79b62cba500b8e53ba4adffb899bfda007 100644 (file)
@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
        /* Set up the rc device */
        rdev->priv = fintek;
        rdev->driver_type = RC_DRIVER_IR_RAW;
-       rdev->allowed_protos = RC_TYPE_ALL;
+       rdev->allowed_protos = RC_BIT_ALL;
        rdev->open = fintek_open;
        rdev->close = fintek_close;
        rdev->input_name = FINTEK_DESCRIPTION;
@@ -684,12 +684,12 @@ static struct pnp_driver fintek_driver = {
        .shutdown       = fintek_shutdown,
 };
 
-int fintek_init(void)
+static int fintek_init(void)
 {
        return pnp_register_driver(&fintek_driver);
 }
 
-void fintek_exit(void)
+static void fintek_exit(void)
 {
        pnp_unregister_driver(&fintek_driver);
 }
index 04cb272db16a37fb11e2cd2cdeadb75b3d7b3760..ba1a1eb356cf765d47d48b0e829f37b0133b5259 100644 (file)
@@ -95,7 +95,7 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
        if (pdata->allowed_protos)
                rcdev->allowed_protos = pdata->allowed_protos;
        else
-               rcdev->allowed_protos = RC_TYPE_ALL;
+               rcdev->allowed_protos = RC_BIT_ALL;
        rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
 
        gpio_dev->rcdev = rcdev;
index 51d7057aca0443414f8325e119a1da81a2e03840..5a9163da63c36c2fbf8527996d9b24134d5ba79e 100644 (file)
@@ -499,7 +499,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        usb_to_input_id(ir->udev, &rc->input_id);
        rc->dev.parent = &intf->dev;
        rc->driver_type = RC_DRIVER_IR_RAW;
-       rc->allowed_protos = RC_TYPE_ALL;
+       rc->allowed_protos = RC_BIT_ALL;
        rc->priv = ir;
        rc->open = iguanair_open;
        rc->close = iguanair_close;
index 5dd0386604f0514d7421fe0b47f3b9097d6554df..8f6a28921ed413c718c0efea9ea70e437d2ac9d7 100644 (file)
@@ -1001,7 +1001,7 @@ static void imon_touch_display_timeout(unsigned long data)
  * it is not, so we must acquire it prior to calling send_packet, which
  * requires that the lock is held.
  */
-static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
        int retval;
        struct imon_context *ictx = rc->priv;
@@ -1010,31 +1010,27 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
        unsigned char ir_proto_packet[] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
-       if (rc_type && !(rc_type & rc->allowed_protos))
+       if (*rc_type && !(*rc_type & rc->allowed_protos))
                dev_warn(dev, "Looks like you're trying to use an IR protocol "
                         "this device does not support\n");
 
-       switch (rc_type) {
-       case RC_TYPE_RC6:
+       if (*rc_type & RC_BIT_RC6_MCE) {
                dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
                ir_proto_packet[0] = 0x01;
-               break;
-       case RC_TYPE_UNKNOWN:
-       case RC_TYPE_OTHER:
+               *rc_type = RC_BIT_RC6_MCE;
+       } else if (*rc_type & RC_BIT_OTHER) {
                dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
                if (!pad_stabilize)
                        dev_dbg(dev, "PAD stabilize functionality disabled\n");
                /* ir_proto_packet[0] = 0x00; // already the default */
-               rc_type = RC_TYPE_OTHER;
-               break;
-       default:
+               *rc_type = RC_BIT_OTHER;
+       } else {
                dev_warn(dev, "Unsupported IR protocol specified, overriding "
                         "to iMON IR protocol\n");
                if (!pad_stabilize)
                        dev_dbg(dev, "PAD stabilize functionality disabled\n");
                /* ir_proto_packet[0] = 0x00; // already the default */
-               rc_type = RC_TYPE_OTHER;
-               break;
+               *rc_type = RC_BIT_OTHER;
        }
 
        memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
@@ -1048,7 +1044,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
        if (retval)
                goto out;
 
-       ictx->rc_type = rc_type;
+       ictx->rc_type = *rc_type;
        ictx->pad_mouse = false;
 
 out:
@@ -1323,7 +1319,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
                rel_x = buf[2];
                rel_y = buf[3];
 
-               if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+               if (ictx->rc_type == RC_BIT_OTHER && pad_stabilize) {
                        if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
                                dir = stabilize((int)rel_x, (int)rel_y,
                                                timeout, threshold);
@@ -1390,7 +1386,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
                buf[0] = 0x01;
                buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
 
-               if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+               if (ictx->rc_type == RC_BIT_OTHER && pad_stabilize) {
                        dir = stabilize((int)rel_x, (int)rel_y,
                                        timeout, threshold);
                        if (!dir) {
@@ -1511,7 +1507,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
                kc = imon_panel_key_lookup(scancode);
        } else {
                scancode = be32_to_cpu(*((u32 *)buf));
-               if (ictx->rc_type == RC_TYPE_RC6) {
+               if (ictx->rc_type == RC_BIT_RC6_MCE) {
                        ktype = IMON_KEY_IMON;
                        if (buf[0] == 0x80)
                                ktype = IMON_KEY_MCE;
@@ -1744,7 +1740,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 {
        u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
        u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
-       u64 allowed_protos = RC_TYPE_OTHER;
+       u64 allowed_protos = RC_BIT_OTHER;
 
        switch (ffdc_cfg_byte) {
        /* iMON Knob, no display, iMON IR + vol knob */
@@ -1775,13 +1771,13 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
        case 0x9e:
                dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
                detected_display_type = IMON_DISPLAY_TYPE_VFD;
-               allowed_protos = RC_TYPE_RC6;
+               allowed_protos = RC_BIT_RC6_MCE;
                break;
        /* iMON LCD, MCE IR */
        case 0x9f:
                dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
                detected_display_type = IMON_DISPLAY_TYPE_LCD;
-               allowed_protos = RC_TYPE_RC6;
+               allowed_protos = RC_BIT_RC6_MCE;
                break;
        default:
                dev_info(ictx->dev, "Unknown 0xffdc device, "
@@ -1789,7 +1785,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
                detected_display_type = IMON_DISPLAY_TYPE_VFD;
                /* We don't know which one it is, allow user to set the
                 * RC6 one from userspace if OTHER wasn't correct. */
-               allowed_protos |= RC_TYPE_RC6;
+               allowed_protos |= RC_BIT_RC6_MCE;
                break;
        }
 
@@ -1875,7 +1871,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
 
        rdev->priv = ictx;
        rdev->driver_type = RC_DRIVER_SCANCODE;
-       rdev->allowed_protos = RC_TYPE_OTHER | RC_TYPE_RC6; /* iMON PAD or MCE */
+       rdev->allowed_protos = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
        rdev->change_protocol = imon_ir_change_protocol;
        rdev->driver_name = MOD_NAME;
 
@@ -1893,7 +1889,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
 
        imon_set_display_type(ictx);
 
-       if (ictx->rc_type == RC_TYPE_RC6)
+       if (ictx->rc_type == RC_BIT_RC6_MCE)
                rdev->map_name = RC_MAP_IMON_MCE;
        else
                rdev->map_name = RC_MAP_IMON_PAD;
index 035668e27f6b7798000428b4d2351c4908b93acc..69edffb9fe9af29056e74c843b5149d629071cb1 100644 (file)
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
        struct jvc_dec *data = &dev->raw->jvc;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_JVC))
+       if (!(dev->raw->enabled_protocols & RC_BIT_JVC))
                return 0;
 
        if (!is_timing_event(ev)) {
@@ -174,7 +174,7 @@ out:
 }
 
 static struct ir_raw_handler jvc_handler = {
-       .protocols      = RC_TYPE_JVC,
+       .protocols      = RC_BIT_JVC,
        .decode         = ir_jvc_decode,
 };
 
index 870c93052fd0a0a97dc2138f1f5694d52507feba..9945e5e7f61a6d58d94105c6f5a6a3c9555d93fb 100644 (file)
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
        struct lirc_codec *lirc = &dev->raw->lirc;
        int sample;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_LIRC))
+       if (!(dev->raw->enabled_protocols & RC_BIT_LIRC))
                return 0;
 
        if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
@@ -408,7 +408,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler lirc_handler = {
-       .protocols      = RC_TYPE_LIRC,
+       .protocols      = RC_BIT_LIRC,
        .decode         = ir_lirc_decode,
        .raw_register   = ir_lirc_register,
        .raw_unregister = ir_lirc_unregister,
index 3784ebf80ec7d9e162b95aab58434ef40d9d21c8..33fafa4cf7cb472643a5fa682b78d326e28aea6a 100644 (file)
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u32 scancode;
        unsigned long delay;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_MCE_KBD))
+       if (!(dev->raw->enabled_protocols & RC_BIT_MCE_KBD))
                return 0;
 
        if (!is_timing_event(ev)) {
@@ -422,7 +422,7 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler mce_kbd_handler = {
-       .protocols      = RC_TYPE_MCE_KBD,
+       .protocols      = RC_BIT_MCE_KBD,
        .decode         = ir_mce_kbd_decode,
        .raw_register   = ir_mce_kbd_register,
        .raw_unregister = ir_mce_kbd_unregister,
index 2ca509e6e16b6c73cc09b0bc84616b8b1b1beafe..a47ee36349694aeef38c0e64a2b1a6d27440db25 100644 (file)
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u8 address, not_address, command, not_command;
        bool send_32bits = false;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
+       if (!(dev->raw->enabled_protocols & RC_BIT_NEC))
                return 0;
 
        if (!is_timing_event(ev)) {
@@ -201,7 +201,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 }
 
 static struct ir_raw_handler nec_handler = {
-       .protocols      = RC_TYPE_NEC,
+       .protocols      = RC_BIT_NEC,
        .decode         = ir_nec_decode,
 };
 
index 9ab663a507a4b7e13b216b9604d47f3692840ea5..5b4d1ddeac4ec30cffa5c78f97f9049bdca75dcc 100644 (file)
@@ -52,8 +52,8 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u8 toggle;
        u32 scancode;
 
-        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5))
-                return 0;
+       if (!(dev->raw->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
+               return 0;
 
        if (!is_timing_event(ev)) {
                if (ev.reset)
@@ -128,6 +128,10 @@ again:
                if (data->wanted_bits == RC5X_NBITS) {
                        /* RC5X */
                        u8 xdata, command, system;
+                       if (!(dev->raw->enabled_protocols & RC_BIT_RC5X)) {
+                               data->state = STATE_INACTIVE;
+                               return 0;
+                       }
                        xdata    = (data->bits & 0x0003F) >> 0;
                        command  = (data->bits & 0x00FC0) >> 6;
                        system   = (data->bits & 0x1F000) >> 12;
@@ -141,6 +145,10 @@ again:
                } else {
                        /* RC5 */
                        u8 command, system;
+                       if (!(dev->raw->enabled_protocols & RC_BIT_RC5)) {
+                               data->state = STATE_INACTIVE;
+                               return 0;
+                       }
                        command  = (data->bits & 0x0003F) >> 0;
                        system   = (data->bits & 0x007C0) >> 6;
                        toggle   = (data->bits & 0x00800) ? 1 : 0;
@@ -164,7 +172,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_handler = {
-       .protocols      = RC_TYPE_RC5,
+       .protocols      = RC_BIT_RC5 | RC_BIT_RC5X,
        .decode         = ir_rc5_decode,
 };
 
index ec8d4a2e2c5a1d215920ab69f797c7bc39fa5fce..fd807a8308d8e4ff917dbf74bb7bbca60a519320 100644 (file)
@@ -48,8 +48,8 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u8 toggle, command, system;
        u32 scancode;
 
-        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5_SZ))
-                return 0;
+       if (!(dev->raw->enabled_protocols & RC_BIT_RC5_SZ))
+               return 0;
 
        if (!is_timing_event(ev)) {
                if (ev.reset)
@@ -128,7 +128,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_sz_handler = {
-       .protocols      = RC_TYPE_RC5_SZ,
+       .protocols      = RC_BIT_RC5_SZ,
        .decode         = ir_rc5_sz_decode,
 };
 
index 4cfdd7fa4bbd56b7d04f130b78020f8977ebaec6..e19072ffb36ca4b873e11b70507b559fc9035a35 100644 (file)
@@ -89,7 +89,9 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u32 scancode;
        u8 toggle;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_RC6))
+       if (!(dev->raw->enabled_protocols &
+             (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
+              RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
                return 0;
 
        if (!is_timing_event(ev)) {
@@ -271,7 +273,9 @@ out:
 }
 
 static struct ir_raw_handler rc6_handler = {
-       .protocols      = RC_TYPE_RC6,
+       .protocols      = RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
+                         RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
+                         RC_BIT_RC6_MCE,
        .decode         = ir_rc6_decode,
 };
 
index 82e6c1e282d5e6a72784f1fa57489553d4d82e9b..9e76c7b40af2f63430d69f25299307164b7daf17 100644 (file)
@@ -479,18 +479,7 @@ struct platform_driver lirc_rx51_platform_driver = {
                .owner  = THIS_MODULE,
        },
 };
-
-static int __init lirc_rx51_init(void)
-{
-       return platform_driver_register(&lirc_rx51_platform_driver);
-}
-module_init(lirc_rx51_init);
-
-static void __exit lirc_rx51_exit(void)
-{
-       platform_driver_unregister(&lirc_rx51_platform_driver);
-}
-module_exit(lirc_rx51_exit);
+module_platform_driver(lirc_rx51_platform_driver);
 
 MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51");
 MODULE_AUTHOR("Nokia Corporation");
index 7e54ec57bcf9cd3fec378d36dd32b4ed6a800240..7e69a3b653700105c6e4a6c7c775655f83d57e86 100644 (file)
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u32 scancode;
        u8 address, command, not_command;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO))
+       if (!(dev->raw->enabled_protocols & RC_BIT_SANYO))
                return 0;
 
        if (!is_timing_event(ev)) {
@@ -179,7 +179,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 }
 
 static struct ir_raw_handler sanyo_handler = {
-       .protocols      = RC_TYPE_SANYO,
+       .protocols      = RC_BIT_SANYO,
        .decode         = ir_sanyo_decode,
 };
 
index dab98b37621a06f5b19f88f00b1bef51c03954f1..fb914342cf4db3f2f0f56035ed0fbb78de0872aa 100644 (file)
@@ -45,7 +45,8 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u32 scancode;
        u8 device, subdevice, function;
 
-       if (!(dev->raw->enabled_protocols & RC_TYPE_SONY))
+       if (!(dev->raw->enabled_protocols &
+             (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
                return 0;
 
        if (!is_timing_event(ev)) {
@@ -123,16 +124,28 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 
                switch (data->count) {
                case 12:
+                       if (!(dev->raw->enabled_protocols & RC_BIT_SONY12)) {
+                               data->state = STATE_INACTIVE;
+                               return 0;
+                       }
                        device    = bitrev8((data->bits <<  3) & 0xF8);
                        subdevice = 0;
                        function  = bitrev8((data->bits >>  4) & 0xFE);
                        break;
                case 15:
+                       if (!(dev->raw->enabled_protocols & RC_BIT_SONY15)) {
+                               data->state = STATE_INACTIVE;
+                               return 0;
+                       }
                        device    = bitrev8((data->bits >>  0) & 0xFF);
                        subdevice = 0;
                        function  = bitrev8((data->bits >>  7) & 0xFE);
                        break;
                case 20:
+                       if (!(dev->raw->enabled_protocols & RC_BIT_SONY20)) {
+                               data->state = STATE_INACTIVE;
+                               return 0;
+                       }
                        device    = bitrev8((data->bits >>  5) & 0xF8);
                        subdevice = bitrev8((data->bits >>  0) & 0xFF);
                        function  = bitrev8((data->bits >> 12) & 0xFE);
@@ -157,7 +170,7 @@ out:
 }
 
 static struct ir_raw_handler sony_handler = {
-       .protocols      = RC_TYPE_SONY,
+       .protocols      = RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
        .decode         = ir_sony_decode,
 };
 
index 24c77a42fc3645c2297688878396ae992ab9dc6b..5e5a7f2b8184cc992fab2bf0e3e90cb09c65c154 100644 (file)
@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        /* set up ir-core props */
        rdev->priv = itdev;
        rdev->driver_type = RC_DRIVER_IR_RAW;
-       rdev->allowed_protos = RC_TYPE_ALL;
+       rdev->allowed_protos = RC_BIT_ALL;
        rdev->open = ite_open;
        rdev->close = ite_close;
        rdev->s_idle = ite_s_idle;
@@ -1708,12 +1708,12 @@ static struct pnp_driver ite_driver = {
        .shutdown       = ite_shutdown,
 };
 
-int ite_init(void)
+static int ite_init(void)
 {
        return pnp_register_driver(&ite_driver);
 }
 
-void ite_exit(void)
+static void ite_exit(void)
 {
        pnp_unregister_driver(&ite_driver);
 }
index 124c7228ba8cb4e69faf664af4acadad22da111c..f0da960560b010e6fb05edd8643b4ff746745894 100644 (file)
@@ -121,7 +121,7 @@ static struct rc_map_list imon_mce_map = {
                .scan    = imon_mce,
                .size    = ARRAY_SIZE(imon_mce),
                /* its RC6, but w/a hardware decoder */
-               .rc_type = RC_TYPE_RC6,
+               .rc_type = RC_TYPE_RC6_MCE,
                .name    = RC_MAP_IMON_MCE,
        }
 };
index 753e43ec787ba10d09f35fbd4d5a33457319477a..ef4006fe4de0a6ca48d7bb3b6fa059bfa5af59fd 100644 (file)
@@ -97,7 +97,7 @@ static struct rc_map_list rc6_mce_map = {
        .map = {
                .scan    = rc6_mce,
                .size    = ARRAY_SIZE(rc6_mce),
-               .rc_type = RC_TYPE_RC6,
+               .rc_type = RC_TYPE_RC6_MCE,
                .name    = RC_MAP_RC6_MCE,
        }
 };
index 850547fe711c25131ca84b748b35de2c35b8b5ae..b2146cd99fd8a74f65a57c7b11886b27764f8272 100644 (file)
@@ -1205,7 +1205,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
        rc->dev.parent = dev;
        rc->priv = ir;
        rc->driver_type = RC_DRIVER_IR_RAW;
-       rc->allowed_protos = RC_TYPE_ALL;
+       rc->allowed_protos = RC_BIT_ALL;
        rc->timeout = MS_TO_NS(100);
        if (!ir->flags.no_tx) {
                rc->s_tx_mask = mceusb_set_tx_mask;
index 2ea913a44ae887b8cfe48503e68c707201ae2a88..e4ea89a11eed451efd967b36a41a4fbbf5a7edf0 100644 (file)
@@ -472,6 +472,7 @@ static void nvt_enable_wake(struct nvt_dev *nvt)
        nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
 }
 
+#if 0 /* Currently unused */
 /* rx carrier detect only works in learning mode, must be called w/nvt_lock */
 static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
 {
@@ -504,7 +505,7 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
 
        return carrier;
 }
-
+#endif
 /*
  * set carrier frequency
  *
@@ -620,7 +621,6 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt)
 static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 {
        DEFINE_IR_RAW_EVENT(rawir);
-       u32 carrier;
        u8 sample;
        int i;
 
@@ -629,9 +629,6 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
        if (debug)
                nvt_dump_rx_buf(nvt);
 
-       if (nvt->carrier_detect_enabled)
-               carrier = nvt_rx_carrier_detect(nvt);
-
        nvt_dbg_verbose("Processing buffer of len %d", nvt->pkts);
 
        init_ir_raw_event(&rawir);
@@ -1045,7 +1042,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
        /* Set up the rc device */
        rdev->priv = nvt;
        rdev->driver_type = RC_DRIVER_IR_RAW;
-       rdev->allowed_protos = RC_TYPE_ALL;
+       rdev->allowed_protos = RC_BIT_ALL;
        rdev->open = nvt_open;
        rdev->close = nvt_close;
        rdev->tx_ir = nvt_tx_ir;
@@ -1220,12 +1217,12 @@ static struct pnp_driver nvt_driver = {
        .shutdown       = nvt_shutdown,
 };
 
-int nvt_init(void)
+static int nvt_init(void)
 {
        return pnp_register_driver(&nvt_driver);
 }
 
-void nvt_exit(void)
+static void nvt_exit(void)
 {
        pnp_unregister_driver(&nvt_driver);
 }
index 0d5e0872a2ea2f43b2d9fd31f18ffeac78361118..7c3674ff5ea2a06073820bb1b19d2b7ec0097ef9 100644 (file)
@@ -103,7 +103,6 @@ struct nvt_dev {
 
        /* rx settings */
        bool learning_enabled;
-       bool carrier_detect_enabled;
 
        /* track cir wake state */
        u8 wake_state;
index f9be68132c67069e9f30eca7acade491d2770d41..53d02827a4724f8e5dfeb1eeea19895f42b7fbba 100644 (file)
@@ -195,7 +195,7 @@ static int __init loop_init(void)
        rc->map_name            = RC_MAP_EMPTY;
        rc->priv                = &loopdev;
        rc->driver_type         = RC_DRIVER_IR_RAW;
-       rc->allowed_protos      = RC_TYPE_ALL;
+       rc->allowed_protos      = RC_BIT_ALL;
        rc->timeout             = 100 * 1000 * 1000; /* 100 ms */
        rc->min_timeout         = 1;
        rc->max_timeout         = UINT_MAX;
index cabc19c105152937dab25fd0b04052f7d053a63f..601d1ac1c688b2608e8b96cbecae27f877c4b4b6 100644 (file)
@@ -725,25 +725,36 @@ static struct class ir_input_class = {
        .devnode        = ir_devnode,
 };
 
+/*
+ * These are the protocol textual descriptions that are
+ * used by the sysfs protocols file. Note that the order
+ * of the entries is relevant.
+ */
 static struct {
        u64     type;
        char    *name;
 } proto_names[] = {
-       { RC_TYPE_UNKNOWN,      "unknown"       },
-       { RC_TYPE_RC5,          "rc-5"          },
-       { RC_TYPE_NEC,          "nec"           },
-       { RC_TYPE_RC6,          "rc-6"          },
-       { RC_TYPE_JVC,          "jvc"           },
-       { RC_TYPE_SONY,         "sony"          },
-       { RC_TYPE_RC5_SZ,       "rc-5-sz"       },
-       { RC_TYPE_SANYO,        "sanyo"         },
-       { RC_TYPE_MCE_KBD,      "mce_kbd"       },
-       { RC_TYPE_LIRC,         "lirc"          },
-       { RC_TYPE_OTHER,        "other"         },
+       { RC_BIT_NONE,          "none"          },
+       { RC_BIT_OTHER,         "other"         },
+       { RC_BIT_UNKNOWN,       "unknown"       },
+       { RC_BIT_RC5 |
+         RC_BIT_RC5X,          "rc-5"          },
+       { RC_BIT_NEC,           "nec"           },
+       { RC_BIT_RC6_0 |
+         RC_BIT_RC6_6A_20 |
+         RC_BIT_RC6_6A_24 |
+         RC_BIT_RC6_6A_32 |
+         RC_BIT_RC6_MCE,       "rc-6"          },
+       { RC_BIT_JVC,           "jvc"           },
+       { RC_BIT_SONY12 |
+         RC_BIT_SONY15 |
+         RC_BIT_SONY20,        "sony"          },
+       { RC_BIT_RC5_SZ,        "rc-5-sz"       },
+       { RC_BIT_SANYO,         "sanyo"         },
+       { RC_BIT_MCE_KBD,       "mce_kbd"       },
+       { RC_BIT_LIRC,          "lirc"          },
 };
 
-#define PROTO_NONE     "none"
-
 /**
  * show_protocols() - shows the current IR protocol(s)
  * @device:    the device descriptor
@@ -790,6 +801,9 @@ static ssize_t show_protocols(struct device *device,
                        tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
                else if (allowed & proto_names[i].type)
                        tmp += sprintf(tmp, "%s ", proto_names[i].name);
+
+               if (allowed & proto_names[i].type)
+                       allowed &= ~proto_names[i].type;
        }
 
        if (tmp != buf)
@@ -867,26 +881,20 @@ static ssize_t store_protocols(struct device *device,
                        disable = false;
                }
 
-               if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
-                       tmp += sizeof(PROTO_NONE);
-                       mask = 0;
-                       count++;
-               } else {
-                       for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
-                               if (!strcasecmp(tmp, proto_names[i].name)) {
-                                       tmp += strlen(proto_names[i].name);
-                                       mask = proto_names[i].type;
-                                       break;
-                               }
-                       }
-                       if (i == ARRAY_SIZE(proto_names)) {
-                               IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
-                               ret = -EINVAL;
-                               goto out;
+               for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+                       if (!strcasecmp(tmp, proto_names[i].name)) {
+                               mask = proto_names[i].type;
+                               break;
                        }
-                       count++;
                }
 
+               if (i == ARRAY_SIZE(proto_names)) {
+                       IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
+                       return -EINVAL;
+               }
+
+               count++;
+
                if (enable)
                        type |= mask;
                else if (disable)
@@ -902,7 +910,7 @@ static ssize_t store_protocols(struct device *device,
        }
 
        if (dev->change_protocol) {
-               rc = dev->change_protocol(dev, type);
+               rc = dev->change_protocol(dev, &type);
                if (rc < 0) {
                        IR_dprintk(1, "Error setting protocols to 0x%llx\n",
                                   (long long)type);
@@ -1117,7 +1125,8 @@ int rc_register_device(struct rc_dev *dev)
        }
 
        if (dev->change_protocol) {
-               rc = dev->change_protocol(dev, rc_map->rc_type);
+               u64 rc_type = (1 << rc_map->rc_type);
+               rc = dev->change_protocol(dev, &rc_type);
                if (rc < 0)
                        goto out_raw;
        }
index 9f5a17bb5ef5df9d09e09519a2424dbac2e0e158..a8887aba9fafe9483267f9122d0b8e39929b5c8c 100644 (file)
@@ -1082,7 +1082,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
        rc->dev.parent = dev;
        rc->priv = rr3;
        rc->driver_type = RC_DRIVER_IR_RAW;
-       rc->allowed_protos = RC_TYPE_ALL;
+       rc->allowed_protos = RC_BIT_ALL;
        rc->timeout = US_TO_NS(2750);
        rc->tx_ir = redrat3_transmit_ir;
        rc->s_tx_carrier = redrat3_set_tx_carrier;
index d6f4bfe09391e92b68981499d99bb2e076060b98..c720f12f661e5121c7ad0e5d9ba77e13f43d5013 100644 (file)
@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
        rdev->dev.parent = dev;
        rdev->priv = sz;
        rdev->driver_type = RC_DRIVER_IR_RAW;
-       rdev->allowed_protos = RC_TYPE_ALL;
+       rdev->allowed_protos = RC_BIT_ALL;
        rdev->driver_name = DRIVER_NAME;
        rdev->map_name = RC_MAP_STREAMZAP;
 
index fef05235234a7b232197429e771522fa5adad882..f0921b5483ebdd34bd967d8f03434c2d843e86b8 100644 (file)
@@ -316,7 +316,7 @@ static int __devinit ttusbir_probe(struct usb_interface *intf,
        usb_to_input_id(tt->udev, &rc->input_id);
        rc->dev.parent = &intf->dev;
        rc->driver_type = RC_DRIVER_IR_RAW;
-       rc->allowed_protos = RC_TYPE_ALL;
+       rc->allowed_protos = RC_BIT_ALL;
        rc->priv = tt;
        rc->driver_name = DRIVER_NAME;
        rc->map_name = RC_MAP_TT_1500;
index 7c9b5f33113b225405a33a30edd2098c4f6ffa52..7f3c476dde05fb712cbb0fbbbc55c36e3150aba4 100644 (file)
@@ -7,6 +7,7 @@
  *  with minor modifications.
  *
  *  Original Author: David Härdeman <david@hardeman.nu>
+ *     Copyright (C) 2012 Sean Young <sean@mess.org>
  *     Copyright (C) 2009 - 2011 David Härdeman <david@hardeman.nu>
  *
  *  Dedicated to my daughter Matilda, without whose loving attention this
@@ -22,9 +23,7 @@
  *    o IR Receive
  *    o IR Transmit
  *    o Wake-On-CIR functionality
- *
- *  To do:
- *    o Learning
+ *    o Carrier detection
  *
  *  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
 #define WBCIR_REGSEL_MASK      0x20
 /* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */
 #define WBCIR_REG_ADDR0                0x00
+/* Enable carrier counter */
+#define WBCIR_CNTR_EN          0x01
+/* Reset carrier counter */
+#define WBCIR_CNTR_R           0x02
+/* Invert TX */
+#define WBCIR_IRTX_INV         0x04
 
 /* Valid banks for the SP3 UART */
 enum wbcir_bank {
@@ -184,7 +189,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       */
@@ -207,7 +212,8 @@ struct wbcir_data {
        /* RX state */
        enum wbcir_rxstate rxstate;
        struct led_trigger *rxtrigger;
-       struct ir_raw_event rxev;
+       int carrier_report_enabled;
+       u32 pulse_duration;
 
        /* TX state */
        enum wbcir_txstate txstate;
@@ -329,6 +335,30 @@ wbcir_to_rc6cells(u8 val)
  *
  *****************************************************************************/
 
+static void
+wbcir_carrier_report(struct wbcir_data *data)
+{
+       unsigned counter = inb(data->ebase + WBCIR_REG_ECEIR_CNT_LO) |
+                       inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8;
+
+       if (counter > 0 && counter < 0xffff) {
+               DEFINE_IR_RAW_EVENT(ev);
+
+               ev.carrier_report = 1;
+               ev.carrier = DIV_ROUND_CLOSEST(counter * 1000000u,
+                                               data->pulse_duration);
+
+               ir_raw_event_store(data->dev, &ev);
+       }
+
+       /* reset and restart the counter */
+       data->pulse_duration = 0;
+       wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
+                                               WBCIR_CNTR_EN | WBCIR_CNTR_R);
+       wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_EN,
+                                               WBCIR_CNTR_EN | WBCIR_CNTR_R);
+}
+
 static void
 wbcir_idle_rx(struct rc_dev *dev, bool idle)
 {
@@ -339,9 +369,16 @@ wbcir_idle_rx(struct rc_dev *dev, bool idle)
                led_trigger_event(data->rxtrigger, LED_FULL);
        }
 
-       if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE)
+       if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) {
+               data->rxstate = WBCIR_RXSTATE_INACTIVE;
+               led_trigger_event(data->rxtrigger, LED_OFF);
+
+               if (data->carrier_report_enabled)
+                       wbcir_carrier_report(data);
+
                /* Tell hardware to go idle by setting RXINACTIVE */
                outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR);
+       }
 }
 
 static void
@@ -349,21 +386,22 @@ wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device)
 {
        u8 irdata;
        DEFINE_IR_RAW_EVENT(rawir);
+       unsigned duration;
 
        /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
        while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) {
                irdata = inb(data->sbase + WBCIR_REG_SP3_RXDATA);
                if (data->rxstate == WBCIR_RXSTATE_ERROR)
                        continue;
+
+               duration = ((irdata & 0x7F) + 1) * 2;
                rawir.pulse = irdata & 0x80 ? false : true;
-               rawir.duration = US_TO_NS(((irdata & 0x7F) + 1) * 10);
-               ir_raw_event_store_with_filter(data->dev, &rawir);
-       }
+               rawir.duration = US_TO_NS(duration);
 
-       /* Check if we should go idle */
-       if (data->dev->idle) {
-               led_trigger_event(data->rxtrigger, LED_OFF);
-               data->rxstate = WBCIR_RXSTATE_INACTIVE;
+               if (rawir.pulse)
+                       data->pulse_duration += duration;
+
+               ir_raw_event_store_with_filter(data->dev, &rawir);
        }
 
        ir_raw_event_handle(data->dev);
@@ -491,6 +529,33 @@ wbcir_irq_handler(int irqno, void *cookie)
  *
  *****************************************************************************/
 
+static int
+wbcir_set_carrier_report(struct rc_dev *dev, int enable)
+{
+       struct wbcir_data *data = dev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&data->spinlock, flags);
+
+       if (data->carrier_report_enabled == enable) {
+               spin_unlock_irqrestore(&data->spinlock, flags);
+               return 0;
+       }
+
+       data->pulse_duration = 0;
+       wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
+                                               WBCIR_CNTR_EN | WBCIR_CNTR_R);
+
+       if (enable && data->dev->idle)
+               wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL,
+                               WBCIR_CNTR_EN, WBCIR_CNTR_EN | WBCIR_CNTR_R);
+
+       data->carrier_report_enabled = enable;
+       spin_unlock_irqrestore(&data->spinlock, flags);
+
+       return 0;
+}
+
 static int
 wbcir_txcarrier(struct rc_dev *dev, u32 carrier)
 {
@@ -837,7 +902,7 @@ wbcir_init_hw(struct wbcir_data *data)
 
        /* Set IRTX_INV */
        if (invert)
-               outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL);
+               outb(WBCIR_IRTX_INV, data->ebase + WBCIR_REG_ECEIR_CCTL);
        else
                outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL);
 
@@ -866,8 +931,8 @@ wbcir_init_hw(struct wbcir_data *data)
        /* prescaler 1.0, tx/rx fifo lvl 16 */
        outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
 
-       /* Set baud divisor to sample every 10 us */
-       outb(0x0F, data->sbase + WBCIR_REG_SP3_BGDL);
+       /* Set baud divisor to sample every 2 ns */
+       outb(0x03, data->sbase + WBCIR_REG_SP3_BGDL);
        outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
 
        /* Set CEIR mode */
@@ -876,9 +941,12 @@ wbcir_init_hw(struct wbcir_data *data)
        inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
        inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
 
-       /* Disable RX demod, enable run-length enc/dec, set freq span */
+       /*
+        * Disable RX demod, enable run-length enc/dec, set freq span and
+        * enable over-sampling
+        */
        wbcir_select_bank(data, WBCIR_BANK_7);
-       outb(0x90, data->sbase + WBCIR_REG_SP3_RCCFG);
+       outb(0xd0, data->sbase + WBCIR_REG_SP3_RCCFG);
 
        /* Disable timer */
        wbcir_select_bank(data, WBCIR_BANK_4);
@@ -915,9 +983,8 @@ wbcir_init_hw(struct wbcir_data *data)
 
        /* Clear RX state */
        data->rxstate = WBCIR_RXSTATE_INACTIVE;
-       data->rxev.duration = 0;
        ir_raw_event_reset(data->dev);
-       ir_raw_event_handle(data->dev);
+       ir_raw_event_set_idle(data->dev, true);
 
        /* Clear TX state */
        if (data->txstate == WBCIR_TXSTATE_ACTIVE) {
@@ -1007,7 +1074,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
        }
 
        data->dev->driver_type = RC_DRIVER_IR_RAW;
-       data->dev->driver_name = WBCIR_NAME;
+       data->dev->driver_name = DRVNAME;
        data->dev->input_name = WBCIR_NAME;
        data->dev->input_phys = "wbcir/cir0";
        data->dev->input_id.bustype = BUS_HOST;
@@ -1016,13 +1083,15 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
        data->dev->input_id.version = WBCIR_ID_CHIP;
        data->dev->map_name = RC_MAP_RC6_MCE;
        data->dev->s_idle = wbcir_idle_rx;
+       data->dev->s_carrier_report = wbcir_set_carrier_report;
        data->dev->s_tx_mask = wbcir_txmask;
        data->dev->s_tx_carrier = wbcir_txcarrier;
        data->dev->tx_ir = wbcir_tx;
        data->dev->priv = data;
        data->dev->dev.parent = &device->dev;
        data->dev->timeout = MS_TO_NS(100);
-       data->dev->allowed_protos = RC_TYPE_ALL;
+       data->dev->rx_resolution = US_TO_NS(2);
+       data->dev->allowed_protos = RC_BIT_ALL;
 
        if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
                dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
index aff39ae457a0d1c469ea8ff1e9a4e81136347a17..81f38aae9c66f6ba2893eb1ff5ea7f6c092be96d 100644 (file)
@@ -35,8 +35,6 @@
  * Currently it blind writes bunch of static registers from the
  * fc2580_freq_regs_lut[] when fc2580_set_params() is called. Add some
  * logic to reduce unneeded register writes.
- * There is also don't-care registers, initialized with value 0xff, and those
- * are also written to the chip currently (yes, not wise).
  */
 
 /* write multiple registers */
@@ -111,6 +109,17 @@ static int fc2580_rd_reg(struct fc2580_priv *priv, u8 reg, u8 *val)
        return fc2580_rd_regs(priv, reg, val, 1);
 }
 
+/* write single register conditionally only when value differs from 0xff
+ * XXX: This is special routine meant only for writing fc2580_freq_regs_lut[]
+ * values. Do not use for the other purposes. */
+static int fc2580_wr_reg_ff(struct fc2580_priv *priv, u8 reg, u8 val)
+{
+       if (val == 0xff)
+               return 0;
+       else
+               return fc2580_wr_regs(priv, reg, &val, 1);
+}
+
 static int fc2580_set_params(struct dvb_frontend *fe)
 {
        struct fc2580_priv *priv = fe->tuner_priv;
@@ -213,99 +222,99 @@ static int fc2580_set_params(struct dvb_frontend *fe)
        if (i == ARRAY_SIZE(fc2580_freq_regs_lut))
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
+       ret = fc2580_wr_reg_ff(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x27, fc2580_freq_regs_lut[i].r27_val);
+       ret = fc2580_wr_reg_ff(priv, 0x27, fc2580_freq_regs_lut[i].r27_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x28, fc2580_freq_regs_lut[i].r28_val);
+       ret = fc2580_wr_reg_ff(priv, 0x28, fc2580_freq_regs_lut[i].r28_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x29, fc2580_freq_regs_lut[i].r29_val);
+       ret = fc2580_wr_reg_ff(priv, 0x29, fc2580_freq_regs_lut[i].r29_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
+       ret = fc2580_wr_reg_ff(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
+       ret = fc2580_wr_reg_ff(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
+       ret = fc2580_wr_reg_ff(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x30, fc2580_freq_regs_lut[i].r30_val);
+       ret = fc2580_wr_reg_ff(priv, 0x30, fc2580_freq_regs_lut[i].r30_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x44, fc2580_freq_regs_lut[i].r44_val);
+       ret = fc2580_wr_reg_ff(priv, 0x44, fc2580_freq_regs_lut[i].r44_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x50, fc2580_freq_regs_lut[i].r50_val);
+       ret = fc2580_wr_reg_ff(priv, 0x50, fc2580_freq_regs_lut[i].r50_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x53, fc2580_freq_regs_lut[i].r53_val);
+       ret = fc2580_wr_reg_ff(priv, 0x53, fc2580_freq_regs_lut[i].r53_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
+       ret = fc2580_wr_reg_ff(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x61, fc2580_freq_regs_lut[i].r61_val);
+       ret = fc2580_wr_reg_ff(priv, 0x61, fc2580_freq_regs_lut[i].r61_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x62, fc2580_freq_regs_lut[i].r62_val);
+       ret = fc2580_wr_reg_ff(priv, 0x62, fc2580_freq_regs_lut[i].r62_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x63, fc2580_freq_regs_lut[i].r63_val);
+       ret = fc2580_wr_reg_ff(priv, 0x63, fc2580_freq_regs_lut[i].r63_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x67, fc2580_freq_regs_lut[i].r67_val);
+       ret = fc2580_wr_reg_ff(priv, 0x67, fc2580_freq_regs_lut[i].r67_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x68, fc2580_freq_regs_lut[i].r68_val);
+       ret = fc2580_wr_reg_ff(priv, 0x68, fc2580_freq_regs_lut[i].r68_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x69, fc2580_freq_regs_lut[i].r69_val);
+       ret = fc2580_wr_reg_ff(priv, 0x69, fc2580_freq_regs_lut[i].r69_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
+       ret = fc2580_wr_reg_ff(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
+       ret = fc2580_wr_reg_ff(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
+       ret = fc2580_wr_reg_ff(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
+       ret = fc2580_wr_reg_ff(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
+       ret = fc2580_wr_reg_ff(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
+       ret = fc2580_wr_reg_ff(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
        if (ret < 0)
                goto err;
 
index ba84936aafd6f8bda6e043d7328fa81fd39a6f52..95ed46f2cd2600b036f1ac2299757e0b616a3da1 100644 (file)
@@ -161,7 +161,7 @@ static int max2165_set_bandwidth(struct max2165_priv *priv, u32 bw)
        return 0;
 }
 
-int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction)
+static int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction)
 {
        u32 remainder;
        u32 q, f = 0;
index 389668474070cb045ceeabbf67c856a0d6980126..83a6240f64d3d17b1a486bb7dbddac50864ee490 100644 (file)
@@ -136,7 +136,7 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 {
        struct tua9001_priv *priv = fe->tuner_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret, i;
+       int ret = 0, i;
        u16 val;
        u32 frequency;
        struct reg_val data[2];
index 4937712278f67757ba114a0f5bfbc9227fc00ab6..5c0fd787cc8f3035e8ab60954ba5a9a5bc8585e2 100644 (file)
@@ -934,7 +934,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
        int                        rc = 0, is_retry = 0;
        u16                        hwmodel;
        v4l2_std_id                std0;
-       u8                         hw_major, hw_minor, fw_major, fw_minor;
+       u8                         hw_major = 0, hw_minor = 0, fw_major = 0, fw_minor = 0;
 
        dprintk(1, "%s called\n", __func__);
 
index 448361c6a13eea6e74adefab2ec9d50d448fe7a3..0cb7c28dcb1787e661fffe919ab6851e4a939c6a 100644 (file)
@@ -25,7 +25,7 @@
 #include "media/tuner.h"
 #include "media/v4l2-common.h"
 
-void hvr950q_cs5340_audio(void *priv, int enable)
+static void hvr950q_cs5340_audio(void *priv, int enable)
 {
        /* Because the HVR-950q shares an i2s bus between the cs5340 and the
           au8522, we need to hold cs5340 in reset when using the au8522 */
index b328f6550d0b28714ff7339e08844e5491c8b407..9a6f15613a3832d7c17754938098ed7f815458aa 100644 (file)
@@ -272,7 +272,6 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
        struct au0828_dev *dev = container_of(work, struct au0828_dev,
                                              restart_streaming);
        struct au0828_dvb *dvb = &dev->dvb;
-       int ret;
 
        if (dev->urb_streaming == 0)
                return;
@@ -282,7 +281,7 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
        mutex_lock(&dvb->lock);
 
        /* Stop transport */
-       ret = stop_urb_transfer(dev);
+       stop_urb_transfer(dev);
        au0828_write(dev, 0x608, 0x00);
        au0828_write(dev, 0x609, 0x00);
        au0828_write(dev, 0x60a, 0x00);
@@ -293,7 +292,7 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
        au0828_write(dev, 0x609, 0x72);
        au0828_write(dev, 0x60a, 0x71);
        au0828_write(dev, 0x60b, 0x01);
-       ret = start_urb_transfer(dev);
+       start_urb_transfer(dev);
 
        mutex_unlock(&dvb->lock);
 }
index 87058557057133f9d209e842c60f000e02f93fba..45387aab10c7ca5633c66c8616c4beb978039594 100644 (file)
@@ -158,7 +158,7 @@ static void au0828_irq_callback(struct urb *urb)
 /*
  * Stop and Deallocate URBs
  */
-void au0828_uninit_isoc(struct au0828_dev *dev)
+static void au0828_uninit_isoc(struct au0828_dev *dev)
 {
        struct urb *urb;
        int i;
@@ -197,9 +197,9 @@ void au0828_uninit_isoc(struct au0828_dev *dev)
 /*
  * Allocate URBs and start IRQ
  */
-int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
-                    int num_bufs, int max_pkt_size,
-                    int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
+static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
+                           int num_bufs, int max_pkt_size,
+                           int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
 {
        struct au0828_dmaqueue *dma_q = &dev->vidq;
        int i;
@@ -783,7 +783,7 @@ static int au0828_i2s_init(struct au0828_dev *dev)
  * Auvitek au0828 analog stream enable
  * Please set interface0 to AS5 before enable the stream
  */
-int au0828_analog_stream_enable(struct au0828_dev *d)
+static int au0828_analog_stream_enable(struct au0828_dev *d)
 {
        dprintk(1, "au0828_analog_stream_enable called\n");
        au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
@@ -810,7 +810,7 @@ int au0828_analog_stream_disable(struct au0828_dev *d)
        return 0;
 }
 
-void au0828_analog_stream_reset(struct au0828_dev *dev)
+static void au0828_analog_stream_reset(struct au0828_dev *dev)
 {
        dprintk(1, "au0828_analog_stream_reset called\n");
        au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
@@ -913,7 +913,7 @@ static int get_ressource(struct au0828_fh *fh)
 /* This function ensures that video frames continue to be delivered even if
    the ITU-656 input isn't receiving any data (thereby preventing applications
    such as tvtime from hanging) */
-void au0828_vid_buffer_timeout(unsigned long data)
+static void au0828_vid_buffer_timeout(unsigned long data)
 {
        struct au0828_dev *dev = (struct au0828_dev *) data;
        struct au0828_dmaqueue *dma_q = &dev->vidq;
@@ -937,7 +937,7 @@ void au0828_vid_buffer_timeout(unsigned long data)
        spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-void au0828_vbi_buffer_timeout(unsigned long data)
+static void au0828_vbi_buffer_timeout(unsigned long data)
 {
        struct au0828_dev *dev = (struct au0828_dev *) data;
        struct au0828_dmaqueue *dma_q = &dev->vbiq;
index 447148eff9588658f954ba5e3d90cdbe6c1fbc76..7222079137406313589bb4119ca5e01b6fe1946f 100644 (file)
@@ -1068,12 +1068,12 @@ int cx231xx_unmute_audio(struct cx231xx *dev)
 }
 EXPORT_SYMBOL_GPL(cx231xx_unmute_audio);
 
-int stopAudioFirmware(struct cx231xx *dev)
+static int stopAudioFirmware(struct cx231xx *dev)
 {
        return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x03);
 }
 
-int restartAudioFirmware(struct cx231xx *dev)
+static int restartAudioFirmware(struct cx231xx *dev)
 {
        return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x13);
 }
@@ -2631,11 +2631,6 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
                        rc = cx231xx_stop_stream(dev, ep_mask);
        }
 
-       if (dev->mode == CX231XX_ANALOG_MODE)
-               ;/* do any in Analog mode */
-       else
-               ;/* do any in digital mode */
-
        return rc;
 }
 EXPORT_SYMBOL_GPL(cx231xx_capture_start);
index b84ebc54d91bce2279e1f1f7b8a8b09d4d0ff12d..bbed1e40eeda6cab07fb712d20c4414094760238 100644 (file)
@@ -686,7 +686,7 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
 }
 EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
 
-void cx231xx_reset_out(struct cx231xx *dev)
+static void cx231xx_reset_out(struct cx231xx *dev)
 {
        cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
        msleep(200);
@@ -694,11 +694,13 @@ void cx231xx_reset_out(struct cx231xx *dev)
        msleep(200);
        cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
 }
-void cx231xx_enable_OSC(struct cx231xx *dev)
+
+static void cx231xx_enable_OSC(struct cx231xx *dev)
 {
        cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
 }
-void cx231xx_sleep_s5h1432(struct cx231xx *dev)
+
+static void cx231xx_sleep_s5h1432(struct cx231xx *dev)
 {
        cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
 }
index 781feed406f72747bb510cb8e4f2eed70afadd77..96a5a09653994657df3c9602559a3e3102aa9e3a 100644 (file)
@@ -72,8 +72,8 @@ static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
 /*
  * cx231xx_i2c_send_bytes()
  */
-int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
-                          const struct i2c_msg *msg)
+static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
+                                 const struct i2c_msg *msg)
 {
        struct cx231xx_i2c *bus = i2c_adap->algo_data;
        struct cx231xx *dev = bus->dev;
index 96176e9db5a28faa01086e1aca1c364b401efe15..0f7b42446826b5922a2deea2b9ebb6a5f1ffbd79 100644 (file)
@@ -99,7 +99,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
        /* The i2c micro-controller only outputs the cmd part of NEC protocol */
        dev->init_data.rc_dev->scanmask = 0xff;
        dev->init_data.rc_dev->driver_name = "cx231xx";
-       dev->init_data.type = RC_TYPE_NEC;
+       dev->init_data.type = RC_BIT_NEC;
        info.addr = 0x30;
 
        /* Load and bind ir-kbd-i2c */
index 3d7526e28d426f8ca119f4d3b1326abd469b7622..943d93423705a0e1c5d404db966219ff528ebb15 100644 (file)
@@ -1306,7 +1306,7 @@ static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
        if (!rc->map_name)
                rc->map_name = RC_MAP_EMPTY;
 
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        rc->query = af9015_rc_query;
        rc->interval = 500;
 
index ea27eaff4e34fdc77d9739d82b4620698a58fca7..61ae7f9d0b27329b5cd493f70be4bb6855fde0b8 100644 (file)
@@ -1023,10 +1023,10 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
                switch (tmp) {
                case 0: /* NEC */
                default:
-                       rc->allowed_protos = RC_TYPE_NEC;
+                       rc->allowed_protos = RC_BIT_NEC;
                        break;
                case 1: /* RC6 */
-                       rc->allowed_protos = RC_TYPE_RC6;
+                       rc->allowed_protos = RC_BIT_RC6_MCE;
                        break;
                }
 
index ec540140c81037ffb0317a3d726fbd30e58fa94e..d05c5b563dac69485af3ea1ca4b219c39c08e990 100644 (file)
@@ -1048,7 +1048,7 @@ static int anysee_rc_query(struct dvb_usb_device *d)
 
 static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        rc->query          = anysee_rc_query;
        rc->interval       = 250;  /* windows driver uses 500ms */
 
@@ -1170,7 +1170,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
        struct dvb_usb_device *d = ci->data;
        struct anysee_state *state = d_to_priv(d);
        int ret;
-       u8 tmp;
+       u8 tmp = 0;
 
        ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40);
        if (ret)
index 54f1221d930df3c5eb0d554c4d56da63cc06583d..d75dbf27e99e21b5ef4065c41f466b3b1645c57d 100644 (file)
@@ -826,7 +826,7 @@ static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
        pr_debug("Getting az6007 Remote Control properties\n");
 
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        rc->query          = az6007_rc_query;
        rc->interval       = 400;
 
index bae16a1189d66deed84242f0c7fd26be398f77b7..059291b892b81c2e250da9e7b2ea64266db95f0c 100644 (file)
@@ -137,7 +137,7 @@ struct dvb_usb_driver_info {
 struct dvb_usb_rc {
        const char *map_name;
        u64 allowed_protos;
-       int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+       int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
        int (*query) (struct dvb_usb_device *d);
        unsigned int interval;
        const enum rc_driver_type driver_type;
index ba51f65204de833cb9965f5f0764f85c8ce9166e..671b4fa232b4a9f9e74fdc1d59f55f99d16c518b 100644 (file)
@@ -224,7 +224,7 @@ static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf,
        dvb_dmx_swfilter_raw(&adap->demux, buf, len);
 }
 
-int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
 {
        dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
                        adap->id);
@@ -236,7 +236,7 @@ int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
        return usb_urb_initv2(&adap->stream, &adap->props->stream);
 }
 
-int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
 {
        dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
                        adap->id);
@@ -368,7 +368,7 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        return dvb_usb_ctrl_feed(dvbdmxfeed, -1);
 }
 
-int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
 {
        int ret;
        struct dvb_usb_device *d = adap_to_d(adap);
@@ -440,7 +440,7 @@ err_dvb_register_adapter:
        return ret;
 }
 
-int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
 {
        dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
                        adap->id);
@@ -456,7 +456,7 @@ int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
        return 0;
 }
 
-int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff)
+static int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        int ret;
 
@@ -553,7 +553,7 @@ err:
        return ret;
 }
 
-int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
 {
        int ret, i, count_registered = 0;
        struct dvb_usb_device *d = adap_to_d(adap);
@@ -622,7 +622,7 @@ err:
        return ret;
 }
 
-int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap)
 {
        int i;
        dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
index 695f9106bc54c1b8b55028d9b1d1c458386928f3..47204280b8b3d1f5b557417a27d32430bccb2c21 100644 (file)
@@ -659,13 +659,19 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
                it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
                it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x0f);
                it913x_wr_reg(d, DEV_0, EP0_TX_NAK, 0x1b);
-               it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f);
+               if (st->proprietary_ir == false) /* Enable endpoint 3 */
+                       it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x3f);
+               else
+                       it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f);
                it913x_wr_reg(d, DEV_0, EP4_TX_LEN_LSB,
                                        ep_size & 0xff);
                it913x_wr_reg(d, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
                ret = it913x_wr_reg(d, DEV_0, EP4_MAX_PKT, pkt_size);
        } else if (adap->id == 1 && adap->fe[0]) {
-               it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f);
+               if (st->proprietary_ir == false)
+                       it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x7f);
+               else
+                       it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f);
                it913x_wr_reg(d, DEV_0, EP5_TX_LEN_LSB,
                                        ep_size & 0xff);
                it913x_wr_reg(d, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
@@ -698,7 +704,7 @@ static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
                return 0;
        }
 
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        rc->query = it913x_rc_query;
        rc->interval = 250;
 
index c41d9d9ec7b54df963ede5ad9deb6d9534e50620..6427ac359f21abda6447a38471c1c560d511dec0 100644 (file)
@@ -799,7 +799,7 @@ static const char fw_c_rs2000[] = LME2510_C_RS2000;
 static const char fw_lg[] = LME2510_LG;
 static const char fw_s0194[] = LME2510_S0194;
 
-const char *lme_firmware_switch(struct dvb_usb_device *d, int cold)
+static const char *lme_firmware_switch(struct dvb_usb_device *d, int cold)
 {
        struct lme2510_state *st = d->priv;
        struct usb_device *udev = d->udev;
@@ -1253,7 +1253,7 @@ static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
 static int lme2510_get_rc_config(struct dvb_usb_device *d,
        struct dvb_usb_rc *rc)
 {
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        return 0;
 }
 
index 093f1acce403e7fa35ddea58914dd386ee32f426..a4c302d0aa37011472e3dbc047b2041d4ddf8eb3 100644 (file)
@@ -1197,7 +1197,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
                struct dvb_usb_rc *rc)
 {
        rc->map_name = RC_MAP_EMPTY;
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        rc->query = rtl2831u_rc_query;
        rc->interval = 400;
 
@@ -1269,7 +1269,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
                struct dvb_usb_rc *rc)
 {
        rc->map_name = RC_MAP_EMPTY;
-       rc->allowed_protos = RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_NEC;
        rc->query = rtl2832u_rc_query;
        rc->interval = 400;
 
@@ -1338,6 +1338,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
                &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) },
        { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK,
                &rtl2832u_props, "NOXON DAB/DAB+ USB dongle", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV2,
+               &rtl2832u_props, "NOXON DAB/DAB+ USB dongle (rev 2)", NULL) },
        { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0,
                &rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) },
        { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101,
index 5989b65903779b08bb70c54251bf186ed47846c4..7346f85f3f2f161cc101605bf88e02883b2c6df6 100644 (file)
@@ -112,7 +112,7 @@ int usb_urb_submitv2(struct usb_data_stream *stream,
        return 0;
 }
 
-int usb_urb_free_urbs(struct usb_data_stream *stream)
+static int usb_urb_free_urbs(struct usb_data_stream *stream)
 {
        int i;
 
@@ -205,7 +205,7 @@ static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream)
        return 0;
 }
 
-int usb_free_stream_buffers(struct usb_data_stream *stream)
+static int usb_free_stream_buffers(struct usb_data_stream *stream)
 {
        if (stream->state & USB_STATE_URB_BUF) {
                while (stream->buf_num) {
@@ -223,8 +223,8 @@ int usb_free_stream_buffers(struct usb_data_stream *stream)
        return 0;
 }
 
-int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
-               unsigned long size)
+static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
+                                   unsigned long size)
 {
        stream->buf_num = 0;
        stream->buf_size = size;
index 5e45ae6054275139da2299adf7925440ed14eb73..91e0119e8a8702908badd7aecb8c14738f0a4719 100644 (file)
@@ -298,7 +298,8 @@ struct stb6100_config az6027_stb6100_config = {
 
 
 /* check for mutex FIXME */
-int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int az6027_usb_in_op(struct dvb_usb_device *d, u8 req,
+                           u16 value, u16 index, u8 *b, int blen)
 {
        int ret = -1;
        if (mutex_lock_interruptible(&d->usb_mutex))
@@ -1051,10 +1052,10 @@ static struct i2c_algorithm az6027_i2c_algo = {
        .functionality = az6027_i2c_func,
 };
 
-int az6027_identify_state(struct usb_device *udev,
-                         struct dvb_usb_device_properties *props,
-                         struct dvb_usb_device_description **desc,
-                         int *cold)
+static int az6027_identify_state(struct usb_device *udev,
+                                struct dvb_usb_device_properties *props,
+                                struct dvb_usb_device_description **desc,
+                                int *cold)
 {
        u8 *b;
        s16 ret;
index 7de125c0b36f4576f951ea8e90a87d7c308f0857..637b6123f391e9bce0fce074314e270e4e9e9238 100644 (file)
@@ -64,7 +64,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
                        struct dvb_usb_device_description **desc, int *cold);
-extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
+extern int dib0700_change_protocol(struct rc_dev *dev, u64 *rc_type);
 extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz);
 
 extern int dib0700_device_count;
index ef87229de6af5d791060b00cd82188bcebbc8c20..19b5ed2825d719d656066b26af8aea2250151960 100644 (file)
@@ -605,7 +605,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return ret;
 }
 
-int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+int dib0700_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
        struct dvb_usb_device *d = rc->priv;
        struct dib0700_state *st = d->priv;
@@ -621,17 +621,19 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
        st->buf[2] = 0;
 
        /* Set the IR mode */
-       if (rc_type == RC_TYPE_RC5)
+       if (*rc_type & RC_BIT_RC5) {
                new_proto = 1;
-       else if (rc_type == RC_TYPE_NEC)
+               *rc_type = RC_BIT_RC5;
+       } else if (*rc_type & RC_BIT_NEC) {
                new_proto = 0;
-       else if (rc_type == RC_TYPE_RC6) {
+               *rc_type = RC_BIT_NEC;
+       } else if (*rc_type & RC_BIT_RC6_MCE) {
                if (st->fw_version < 0x10200) {
                        ret = -EINVAL;
                        goto out;
                }
-
                new_proto = 2;
+               *rc_type = RC_BIT_RC6_MCE;
        } else {
                ret = -EINVAL;
                goto out;
@@ -645,7 +647,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
                goto out;
        }
 
-       d->props.rc.core.protocol = rc_type;
+       d->props.rc.core.protocol = *rc_type;
 
 out:
        mutex_unlock(&d->usb_mutex);
@@ -707,7 +709,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
                 purb->actual_length);
 
        switch (d->props.rc.core.protocol) {
-       case RC_TYPE_NEC:
+       case RC_BIT_NEC:
                toggle = 0;
 
                /* NEC protocol sends repeat code as 0 0 0 FF */
index 510001da6e836a0c1e6ca0bdc492fa1532e63ccc..11798426fa88505d3202a59e6e0b74992afd3698 100644 (file)
@@ -518,7 +518,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 
        d->last_event = 0;
        switch (d->props.rc.core.protocol) {
-       case RC_TYPE_NEC:
+       case RC_BIT_NEC:
                /* NEC protocol sends repeat code as 0 0 0 FF */
                if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
                    (key[3] == 0xff))
@@ -3658,9 +3658,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_interval      = DEFAULT_RC_INTERVAL,
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3698,9 +3698,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_interval      = DEFAULT_RC_INTERVAL,
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3763,9 +3763,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_interval      = DEFAULT_RC_INTERVAL,
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3808,9 +3808,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3890,9 +3890,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3936,9 +3936,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3987,9 +3987,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4055,9 +4055,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4106,9 +4106,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4177,9 +4177,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4215,9 +4215,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4295,9 +4295,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4341,9 +4341,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4394,9 +4394,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4433,9 +4433,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4472,9 +4472,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4511,9 +4511,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4550,9 +4550,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4589,9 +4589,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4644,9 +4644,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4681,9 +4681,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4721,9 +4721,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4761,9 +4761,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4802,9 +4802,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
                        .module_name      = "dib0700",
                        .rc_query         = dib0700_rc_query_old_firmware,
-                       .allowed_protos   = RC_TYPE_RC5 |
-                                           RC_TYPE_RC6 |
-                                           RC_TYPE_NEC,
+                       .allowed_protos   = RC_BIT_RC5 |
+                                           RC_BIT_RC6_MCE |
+                                           RC_BIT_NEC,
                        .change_protocol  = dib0700_change_protocol,
                },
        },
index aab0f99bc892bc764530e9966b87561eede5974f..ce4c4e3b58bb7516f9bdff338d1b6b8ed2d0332e 100644 (file)
@@ -202,7 +202,7 @@ struct dvb_rc {
        u64 protocol;
        u64 allowed_protos;
        enum rc_driver_type driver_type;
-       int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+       int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
        char *module_name;
        int (*rc_query) (struct dvb_usb_device *d);
        int rc_interval;
index 02e878577c3dcb33f2cb18f0cfe9b6361a73b452..d1ddfa13de86d8a474796e0af2da49bdcb8eaa78 100644 (file)
@@ -927,7 +927,7 @@ static struct dvb_usb_device_properties pctv452e_properties = {
 
        .rc.core = {
                .rc_codes       = RC_MAP_DIB0700_RC5_TABLE,
-               .allowed_protos = RC_TYPE_UNKNOWN,
+               .allowed_protos = RC_BIT_UNKNOWN,
                .rc_query       = pctv452e_rc_query,
                .rc_interval    = 100,
        },
@@ -980,7 +980,7 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
 
        .rc.core = {
                .rc_codes       = RC_MAP_TT_1500,
-               .allowed_protos = RC_TYPE_UNKNOWN,
+               .allowed_protos = RC_BIT_UNKNOWN,
                .rc_query       = pctv452e_rc_query,
                .rc_interval    = 100,
        },
index 7a8c8c18590fdcb16c561cff57ea6d2abc6f875e..40832a1aef6c71c0df2eaf51ffdea327bafe18da 100644 (file)
@@ -732,7 +732,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
                .rc_codes    = RC_MAP_TECHNISAT_USB2,
                .module_name = "technisat-usb2",
                .rc_query    = technisat_usb2_rc_query,
-               .allowed_protos = RC_TYPE_ALL,
+               .allowed_protos = RC_BIT_ALL,
                .driver_type    = RC_DRIVER_IR_RAW,
        }
 };
index 6a50cdea3bcee539a79ccecd9a211c13309b803d..bcdac225ebe10a2cd3c67c8496fdddb92fe9d5f2 100644 (file)
@@ -741,7 +741,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
                .rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
                .rc_codes         = RC_MAP_TT_1500,
                .rc_query         = tt3650_rc_query,
-               .allowed_protos   = RC_TYPE_UNKNOWN,
+               .allowed_protos   = RC_BIT_UNKNOWN,
        },
 
        .num_adapters = 1,
index 07c673a6e7643068cb49c8ab3f01e9b299b2b060..22cf9f96cb9e68098476d06b0018d6f7baf868be 100644 (file)
@@ -56,7 +56,7 @@ static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
 }
 
 int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
-                           u16 index, u8 *b, int blen)
+                    u16 index, u8 *b, int blen)
 {
        int ret;
 
@@ -67,8 +67,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
        return ret;
 }
 
-int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
-                                     u16 index, u8 *b, int blen)
+static int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req,
+                                     u16 value, u16 index, u8 *b, int blen)
 {
        int ret;
        deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
@@ -86,7 +86,7 @@ int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
                return 0;
 }
 
-int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
                             u16 index, u8 *b, int blen)
 {
        int ret;
index 16a84f9f46d8421e9c902a2b9886a950f1e6bc4d..619bffbab3bc050f2cb2f1f1929bd5da1bdd91a8 100644 (file)
@@ -1979,6 +1979,15 @@ struct em28xx_board em28xx_boards[] = {
                                EM28XX_I2C_CLK_WAIT_ENABLE |
                                EM28XX_I2C_FREQ_400_KHZ,
        },
+       [EM2884_BOARD_TERRATEC_HTC_USB_XS] = {
+               .name         = "Terratec Cinergy HTC USB XS",
+               .has_dvb      = 1,
+               .ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+               .tuner_type   = TUNER_ABSENT,
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -2057,9 +2066,9 @@ struct usb_device_id em28xx_id_table[] = {
        { USB_DEVICE(0x0ccd, 0x0043),
                        .driver_info = EM2870_BOARD_TERRATEC_XS },
        { USB_DEVICE(0x0ccd, 0x008e),   /* Cinergy HTC USB XS Rev. 1 */
-                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+                       .driver_info = EM2884_BOARD_TERRATEC_HTC_USB_XS },
        { USB_DEVICE(0x0ccd, 0x00ac),   /* Cinergy HTC USB XS Rev. 2 */
-                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+                       .driver_info = EM2884_BOARD_TERRATEC_HTC_USB_XS },
        { USB_DEVICE(0x0ccd, 0x10a2),   /* H5 Rev. 1 */
                        .driver_info = EM2884_BOARD_TERRATEC_H5 },
        { USB_DEVICE(0x0ccd, 0x10ad),   /* H5 Rev. 2 */
@@ -3297,7 +3306,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 
        dev->num_alt = interface->num_altsetting;
 
-       if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
+       if ((unsigned)card[nr] < em28xx_bcount)
                dev->model = card[nr];
 
        /* save our data pointer in this interface device */
index 13ae821949e9f5f3007aaf77554e63e1551cc28e..63f2e7070c005d8ed05af171bd1d80c6006295f4 100644 (file)
@@ -331,7 +331,7 @@ static struct drxk_config hauppauge_930c_drxk = {
        .load_firmware_sync = true,
 };
 
-struct drxk_config terratec_htc_stick_drxk = {
+static struct drxk_config terratec_htc_stick_drxk = {
        .adr = 0x29,
        .single_master = 1,
        .no_i2c_bridge = 1,
@@ -520,7 +520,10 @@ static void terratec_htc_stick_init(struct em28xx *dev)
                { -1,                   -1,     -1,     -1},
        };
 
-       /* Init the analog decoder? */
+       /*
+        * Init the analog decoder (not yet supported), but
+        * it's probably still a good idea.
+        */
        struct {
                unsigned char r[4];
                int len;
@@ -547,6 +550,64 @@ static void terratec_htc_stick_init(struct em28xx *dev)
        em28xx_gpio_set(dev, terratec_htc_stick_end);
 };
 
+static void terratec_htc_usb_xs_init(struct em28xx *dev)
+{
+       int i;
+
+       struct em28xx_reg_seq terratec_htc_usb_xs_init[] = {
+               {EM28XX_R08_GPIO,       0xff,   0xff,   10},
+               {EM2874_R80_GPIO,       0xb2,   0xff,   100},
+               {EM2874_R80_GPIO,       0xb2,   0xff,   50},
+               {EM2874_R80_GPIO,       0xb6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct em28xx_reg_seq terratec_htc_usb_xs_end[] = {
+               {EM2874_R80_GPIO,       0xa6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xa6,   0xff,   50},
+               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+
+       /*
+        * Init the analog decoder (not yet supported), but
+        * it's probably still a good idea.
+        */
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+               {{ 0x04, 0x00 }, 2},
+               {{ 0x00, 0x04 }, 2},
+               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+               {{ 0x04, 0x14 }, 2},
+               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+       };
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+
+       em28xx_gpio_set(dev, terratec_htc_usb_xs_init);
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+       msleep(10);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+       msleep(10);
+
+       dev->i2c_client.addr = 0x82 >> 1;
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+
+       em28xx_gpio_set(dev, terratec_htc_usb_xs_end);
+};
+
 static void pctv_520e_init(struct em28xx *dev)
 {
        /*
@@ -1147,6 +1208,25 @@ static int em28xx_dvb_init(struct em28xx *dev)
                        goto out_free;
                }
 
+               /* Attach the demodulator. */
+               if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+                               &dev->i2c_adap,
+                               &em28xx_cxd2820r_tda18271_config)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2884_BOARD_TERRATEC_HTC_USB_XS:
+               terratec_htc_usb_xs_init(dev);
+
+               /* attach demodulator */
+               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
+                                       &dev->i2c_adap);
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
                /* Attach the demodulator. */
                if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
                                &dev->i2c_adap,
index 97d36b4f19db95094bda60d549888e6e564315cf..660bf803c9e4b8df04defd0c0a0758280e30a69b 100644 (file)
@@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc)
        cancel_delayed_work_sync(&ir->work);
 }
 
-static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
+static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
 {
        int rc = 0;
        struct em28xx_IR *ir = rc_dev->priv;
@@ -354,14 +354,16 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
 
        /* Adjust xclk based o IR table for RC5/NEC tables */
 
-       if (rc_type == RC_TYPE_RC5) {
+       if (*rc_type & RC_BIT_RC5) {
                dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
                ir->full_code = 1;
-       } else if (rc_type == RC_TYPE_NEC) {
+               *rc_type = RC_BIT_RC5;
+       } else if (*rc_type & RC_BIT_NEC) {
                dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
                ir_config = EM2874_IR_NEC;
                ir->full_code = 1;
-       } else if (rc_type != RC_TYPE_UNKNOWN)
+               *rc_type = RC_BIT_NEC;
+       } else if (*rc_type != RC_BIT_UNKNOWN)
                rc = -EINVAL;
 
        em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
@@ -524,6 +526,7 @@ static int em28xx_ir_init(struct em28xx *dev)
        struct em28xx_IR *ir;
        struct rc_dev *rc;
        int err = -ENOMEM;
+       u64 rc_type;
 
        if (dev->board.ir_codes == NULL) {
                /* No remote control support */
@@ -546,14 +549,15 @@ static int em28xx_ir_init(struct em28xx *dev)
         * em2874 supports more protocols. For now, let's just announce
         * the two protocols that were already tested
         */
-       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
        rc->priv = ir;
        rc->change_protocol = em28xx_ir_change_protocol;
        rc->open = em28xx_ir_start;
        rc->close = em28xx_ir_stop;
 
        /* By default, keep protocol field untouched */
-       err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+       rc_type = RC_BIT_UNKNOWN;
+       err = em28xx_ir_change_protocol(rc, &rc_type);
        if (err)
                goto err_out_free;
 
index 8757523e686363d79252878a6bb6d8d64d79cb39..86e90d86da6d51547ae73b5f5a4d3197e488ccbb 100644 (file)
 #define EM2874_BOARD_MAXMEDIA_UB425_TC            84
 #define EM2884_BOARD_PCTV_510E                    85
 #define EM2884_BOARD_PCTV_520E                    86
+#define EM2884_BOARD_TERRATEC_HTC_USB_XS         87
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
index a2b934146ebf9245da1a972b36addc89eb7b026c..e0a431bb0d4207aa5b7910b9b483af31d9d381e1 100644 (file)
@@ -1586,8 +1586,7 @@ static int vidioc_querybuf(struct file *file, void *priv,
        struct gspca_dev *gspca_dev = video_drvdata(file);
        struct gspca_frame *frame;
 
-       if (v4l2_buf->index < 0
-           || v4l2_buf->index >= gspca_dev->nframes)
+       if (v4l2_buf->index >= gspca_dev->nframes)
                return -EINVAL;
 
        frame = &gspca_dev->frame[v4l2_buf->index];
index e3eab82cd4e5d31097b064e654e18a9079d8ee43..352317d7acdbacb7bc423f954bc05738790fe9ec 100644 (file)
@@ -32,7 +32,7 @@ do {                                                          \
 #define D_USBO 0x00
 #define D_V4L2 0x0100
 #else
-#define PDEBUG(level, fmt, ...)
+#define PDEBUG(level, fmt, ...) do {} while(0)
 #endif
 
 #define GSPCA_MAX_FRAMES 16    /* maximum number of video frame buffers */
index b897aa86f315665645808efa95be5b11d3ac2171..1ba29fe7fada3603fa6b93ca80bd9fdf8738202e 100644 (file)
@@ -114,7 +114,7 @@ static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
 }
 
 /* Responses are one byte only */
-static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
+static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char *response)
 {
        int retval;
 
@@ -123,7 +123,7 @@ static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
        retval = usb_bulk_msg(gspca_dev->dev,
        usb_rcvbulkpipe(gspca_dev->dev, 0x84),
                                gspca_dev->usb_buf, 1, NULL, 500);
-       response = gspca_dev->usb_buf[0];
+       *response = gspca_dev->usb_buf[0];
        if (retval < 0) {
                pr_err("read command [%02x] error %d\n",
                       gspca_dev->usb_buf[0], retval);
@@ -260,7 +260,7 @@ static int jlj_start(struct gspca_dev *gspca_dev)
                if (start_commands[i].delay)
                        msleep(start_commands[i].delay);
                if (start_commands[i].ack_wanted)
-                       jlj_read1(gspca_dev, response);
+                       jlj_read1(gspca_dev, &response);
        }
        setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
        msleep(2);
index cc8ec3f7e8dc59df40952cc0dfdaf810c86e4ffd..c8e1572eb5024cba1f12af7ece1f4ca24bf8a8d5 100644 (file)
@@ -73,6 +73,12 @@ static
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
                }
+       }, {
+               .ident = "Fujitsu-Siemens Amilo Pi 2530",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 2530")
+               }
        }, {
                .ident = "MSI GX700",
                .matches = {
index 2d5c6d8343a01c475291b3435de77cec7112ff35..4f5869a98082201e2ef39d8bb3f009b0972826a4 100644 (file)
  * Register page 0:
  *
  * Address     Description
- * 0x02                Red balance control
- * 0x03                Green balance control
- * 0x04        Blue balance control
- *                  Valus are inverted (0=max, 255=min).
+ * 0x01                Red balance control
+ * 0x02                Green balance control
+ * 0x03                Blue balance control
  *                  The Windows driver uses a quadratic approach to map
  *                  the settable values (0-200) on register values:
- *                  min=0x80, default=0x40, max=0x20
- * 0x0f-0x20   Colors, saturation and exposure control
+ *                  min=0x20, default=0x40, max=0x80
+ * 0x0f-0x20   Color and saturation control
  * 0xa2-0xab   Brightness, contrast and gamma control
  * 0xb6                Sharpness control (bits 0-4)
  *
  *
  * Page | Register   | Function
  * -----+------------+---------------------------------------------------
+ *  0   | 0x01       | setredbalance()
+ *  0   | 0x03       | setbluebalance()
  *  0   | 0x0f..0x20 | setcolors()
  *  0   | 0xa2..0xab | setbrightcont()
  *  0   | 0xb6       | setsharpness()
- *  0   | 0xc5       | setredbalance()
  *  0   | 0xc6       | setwhitebalance()
- *  0   | 0xc7       | setbluebalance()
  *  0   | 0xdc       | setbrightcont(), setcolors()
  *  3   | 0x02       | setexposure()
  *  3   | 0x10, 0x12 | setgain()
 /* Include pac common sof detection functions */
 #include "pac_common.h"
 
-#define PAC7302_GAIN_DEFAULT      15
-#define PAC7302_GAIN_KNEE         42
-#define PAC7302_EXPOSURE_DEFAULT  66 /* 33 ms / 30 fps */
-#define PAC7302_EXPOSURE_KNEE    133 /* 66 ms / 15 fps */
+#define PAC7302_RGB_BALANCE_MIN                  0
+#define PAC7302_RGB_BALANCE_MAX                200
+#define PAC7302_RGB_BALANCE_DEFAULT    100
+#define PAC7302_GAIN_DEFAULT            15
+#define PAC7302_GAIN_KNEE               42
+#define PAC7302_EXPOSURE_DEFAULT        66 /* 33 ms / 30 fps */
+#define PAC7302_EXPOSURE_KNEE          133 /* 66 ms / 15 fps */
 
 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
                "Thomas Kaiser thomas@kaiser-linux.li");
@@ -439,12 +441,31 @@ static void setwhitebalance(struct gspca_dev *gspca_dev)
        reg_w(gspca_dev, 0xdc, 0x01);
 }
 
+static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val)
+{
+       const unsigned int k = 1000;    /* precision factor */
+       unsigned int norm;
+
+       /* Normed value [0...k] */
+       norm = k * (rgb_ctrl_val - PAC7302_RGB_BALANCE_MIN)
+                   / (PAC7302_RGB_BALANCE_MAX - PAC7302_RGB_BALANCE_MIN);
+       /* Qudratic apporach improves control at small (register) values: */
+       return 64 * norm * norm / (k*k)  +  32 * norm / k  +  32;
+       /* Y = 64*X*X + 32*X + 32
+        * => register values 0x20-0x80; Windows driver uses these limits */
+
+       /* NOTE: for full value range (0x00-0xff) use
+        *         Y = 254*X*X + X
+        *         => 254 * norm * norm / (k*k)  +  1 * norm / k        */
+}
+
 static void setredbalance(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
-       reg_w(gspca_dev, 0xc5, sd->red_balance->val);
+       reg_w(gspca_dev, 0xff, 0x00);                   /* page 0 */
+       reg_w(gspca_dev, 0x01,
+             rgbbalance_ctrl_to_reg_value(sd->red_balance->val));
 
        reg_w(gspca_dev, 0xdc, 0x01);
 }
@@ -454,7 +475,8 @@ static void setbluebalance(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        reg_w(gspca_dev, 0xff, 0x00);                   /* page 0 */
-       reg_w(gspca_dev, 0xc7, sd->blue_balance->val);
+       reg_w(gspca_dev, 0x03,
+             rgbbalance_ctrl_to_reg_value(sd->blue_balance->val));
 
        reg_w(gspca_dev, 0xdc, 0x01);
 }
@@ -643,9 +665,15 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
                                        V4L2_CID_WHITE_BALANCE_TEMPERATURE,
                                        0, 255, 1, 55);
        sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
+                                       V4L2_CID_RED_BALANCE,
+                                       PAC7302_RGB_BALANCE_MIN,
+                                       PAC7302_RGB_BALANCE_MAX,
+                                       1, PAC7302_RGB_BALANCE_DEFAULT);
        sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1);
+                                       V4L2_CID_BLUE_BALANCE,
+                                       PAC7302_RGB_BALANCE_MIN,
+                                       PAC7302_RGB_BALANCE_MAX,
+                                       1, PAC7302_RGB_BALANCE_DEFAULT);
 
        gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
                                        V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
index fd1f8d2d3b0b4f52b6640b4f540ac1cf3226898f..70511d5f953857492aca04655cdf079836a998dc 100644 (file)
@@ -1449,6 +1449,7 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
        {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
 #endif
+       {USB_DEVICE(0x0c45, 0x6027), SB(OV7630, 101)}, /* Genius Eye 310 */
        {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
        {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
        {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
index 304f43ef59eb16a8778d2adbc43baf4743187a9b..84dc26fe80eed741866e2aaece3aa77f60414986 100644 (file)
@@ -401,12 +401,14 @@ static int hdpvr_probe(struct usb_interface *interface,
        client = hdpvr_register_ir_rx_i2c(dev);
        if (!client) {
                v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n");
+               retval = -ENODEV;
                goto reg_fail;
        }
 
        client = hdpvr_register_ir_tx_i2c(dev);
        if (!client) {
                v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n");
+               retval = -ENODEV;
                goto reg_fail;
        }
 #endif
index 82e819fa91c0814047074b867ae2bca713570b75..031cf024304c356e8573f13119505de49b71e1a8 100644 (file)
@@ -55,7 +55,7 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
        /* Our default information for ir-kbd-i2c.c to use */
        init_data->ir_codes = RC_MAP_HAUPPAUGE;
        init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-       init_data->type = RC_TYPE_RC5;
+       init_data->type = RC_BIT_RC5;
        init_data->name = "HD-PVR";
        init_data->polling_interval = 405; /* ms, duplicated from Windows */
        hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
index fb828ba1dbbe8044e09cf33a5b3269ef09417254..299751a8b06bc323bb347217235bf6486b2e6488 100644 (file)
@@ -3563,9 +3563,9 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,
                                     enum pvr2_v4l_type index,int v)
 {
        switch (index) {
-       case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;
-       case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;
-       case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;
+       case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;break;
+       case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;break;
+       case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;break;
        default: break;
        }
 }
index 885ce11f222d779e5320e2dc43494bc6b7011cd0..9ab596c78a4e35a0f23af1a5f4422741bbcc71d7 100644 (file)
@@ -581,7 +581,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
        case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
                init_data->ir_codes              = RC_MAP_HAUPPAUGE;
                init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-               init_data->type                  = RC_TYPE_RC5;
+               init_data->type                  = RC_BIT_RC5;
                init_data->name                  = hdw->hdw_desc->description;
                init_data->polling_interval      = 100; /* ms From ir-kbd-i2c */
                /* IR Receiver */
@@ -596,7 +596,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
        case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
                init_data->ir_codes              = RC_MAP_HAUPPAUGE;
                init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-               init_data->type                  = RC_TYPE_RC5;
+               init_data->type                  = RC_BIT_RC5;
                init_data->name                  = hdw->hdw_desc->description;
                /* IR Receiver */
                info.addr          = 0x71;
index db249cad3cd975f1be344057d5d6cab7fda344f6..6930676051e74fb0efda27771520ca0dd913b7fc 100644 (file)
@@ -196,7 +196,7 @@ static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
        return ret;
 }
 
-int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
+static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
 {
        struct pvr2_v4l2_fh *fh = file->private_data;
        struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
@@ -365,7 +365,7 @@ static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
                        vt->audmode);
 }
 
-int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
+static int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
 {
        struct pvr2_v4l2_fh *fh = file->private_data;
        struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
index 1f506fde97d0a52433a7477f6ac843cc60af1f2f..3a1618580ed6c6a774713fb44e8c6fcab8d31c5c 100644 (file)
@@ -179,6 +179,8 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
                return -EINVAL;
        if (frames < 4)
                frames = 4;
+       else if (size > PSZ_QCIF && frames > 15)
+               frames = 15;
        else if (frames > 25)
                frames = 25;
        frames = frames2frames[frames];
index 42e36bac4d72a93add64b485652fc957bf0a30a3..5210239cbaeefcc9b92cd548bfbe1c010fd6b89d 100644 (file)
@@ -155,7 +155,7 @@ static struct video_device pwc_template = {
 /***************************************************************************/
 /* Private functions */
 
-struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
+static struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
 {
        unsigned long flags = 0;
        struct pwc_frame_buf *buf = NULL;
@@ -1000,7 +1000,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
        pdev->vb_queue.ops = &pwc_vb_queue_ops;
        pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
-       vb2_queue_init(&pdev->vb_queue);
+       rc = vb2_queue_init(&pdev->vb_queue);
+       if (rc < 0) {
+               PWC_ERROR("Oops, could not initialize vb2 queue.\n");
+               goto err_free_mem;
+       }
 
        /* Init video_device structure */
        memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
index 2191f6ddf9e7536883a6b7e7973ceeba30b0ef61..8ebec0d7bf59509bd19ea1756528e1e9407fbe45 100644 (file)
@@ -1651,7 +1651,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
        int is_ntsc = 0;
 #define NUM_FRAME_ENUMS 4
        int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5};
-       if (fe->index < 0 || fe->index >= NUM_FRAME_ENUMS)
+       if (fe->index >= NUM_FRAME_ENUMS)
                return -EINVAL;
        switch (fe->width) {
        case 640:
index 3c76e62d820da4ac3ccffe8f8f4cbe6b3229451d..5afbd9a4b55c985f2cbf3b118060767ebebb4f9c 100644 (file)
@@ -4,7 +4,8 @@
 
 config SMS_USB_DRV
        tristate "Siano SMS1xxx based MDTV receiver"
-       depends on DVB_CORE && RC_CORE && HAS_DMA
+       depends on DVB_CORE && HAS_DMA
+       select MEDIA_COMMON_OPTIONS
        ---help---
          Choose if you would like to have Siano's support for USB interface
 
index 5bfc8e2f018f20fb07389b7fadf8902c7073714e..73605864fffadb98ce9e780cf8499bee83a1704c 100644 (file)
@@ -2481,11 +2481,13 @@ sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
                if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
                    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
                        return -EINVAL;
+               break;
        case BRIDGE_SN9C105:
        case BRIDGE_SN9C120:
                if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
                    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
                        return -EINVAL;
+               break;
        }
 
        frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
index 176ac937306be7e63b6362ae55f071adde7f00c0..850cf285ada8d97e2f2348da39f139d041d6404b 100644 (file)
@@ -116,7 +116,7 @@ static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
        if (rc < 0)
                return rc;
 
-       stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
+       rc = stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
        if (rc < 0)
                return rc;
 
index 8bdfb0275313929d0698817eedb5143ecec72ec0..fa3671de02aa66081019f9d102339a0c6873f972 100644 (file)
@@ -475,7 +475,11 @@ int stk1160_alloc_isoc(struct stk1160 *dev)
                if (!dev->isoc_ctl.transfer_buffer[i]) {
                        stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n",
                                sb_size, i);
-                       goto free_i_bufs;
+
+                       /* Not enough transfer buffers, so just give up */
+                       if (i < STK1160_MIN_BUFS)
+                               goto free_i_bufs;
+                       goto nomore_tx_bufs;
                }
                memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
 
@@ -506,13 +510,28 @@ int stk1160_alloc_isoc(struct stk1160 *dev)
                }
        }
 
-       stk1160_dbg("urbs allocated\n");
+       stk1160_dbg("%d urbs allocated\n", num_bufs);
 
        /* At last we can say we have some buffers */
        dev->isoc_ctl.num_bufs = num_bufs;
 
        return 0;
 
+nomore_tx_bufs:
+       /*
+        * Failed to allocate desired buffer count. However, we may have
+        * enough to work fine, so we just free the extra urb,
+        * store the allocated count and keep going, fingers crossed!
+        */
+       usb_free_urb(dev->isoc_ctl.urb[i]);
+       dev->isoc_ctl.urb[i] = NULL;
+
+       stk1160_warn("%d urbs allocated. Trying to continue...\n", i - 1);
+
+       dev->isoc_ctl.num_bufs = i - 1;
+
+       return 0;
+
 free_i_bufs:
        /* Save the allocated buffers so far, so we can properly free them */
        dev->isoc_ctl.num_bufs = i+1;
index 68c8707d36abed789d196ccd3e8a5d528b0b78ac..05b05b160e1e9abdd886bf49702bc35c8b3a52dc 100644 (file)
 #define STK1160_VERSION                "0.9.5"
 #define STK1160_VERSION_NUM    0x000905
 
-/* TODO: Decide on number of packets for each buffer */
+/* Decide on number of packets for each buffer */
 #define STK1160_NUM_PACKETS 64
 
 /* Number of buffers for isoc transfers */
-#define STK1160_NUM_BUFS 16 /* TODO */
+#define STK1160_NUM_BUFS 16
+#define STK1160_MIN_BUFS 1
 
 /* TODO: This endpoint address should be retrieved */
 #define STK1160_EP_VIDEO 0x82
index 86a0fc56c330f93076dfbd6c0984dd4d6e3b1023..5d3c032d733cf6e92ca7b345de95862204cd3d91 100644 (file)
@@ -54,10 +54,6 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN");
 MODULE_DESCRIPTION("Syntek DC1125 webcam driver");
 
-
-/* bool for webcam LED management */
-int first_init = 1;
-
 /* Some cameras have audio interfaces, we aren't interested in those */
 static struct usb_device_id stkwebcam_table[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) },
@@ -554,6 +550,7 @@ static void stk_free_buffers(struct stk_camera *dev)
 
 static int v4l_stk_open(struct file *fp)
 {
+       static int first_init = 1; /* webcam LED management */
        struct stk_camera *dev;
        struct video_device *vdev;
 
index 30fcb117e89899a25208428061900d22eefb829c..ca4994a5190ce4fbb5f11a918869ca78963c7021 100644 (file)
@@ -1,6 +1,7 @@
 #include "pd-common.h"
 #include <linux/kernel.h>
 #include <linux/usb.h>
+#include <linux/time.h>
 #include <linux/dvb/dmx.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
index 1f448ac7a496c160d567b1b6c2eeb5b4eabff288..3082bfa9b2c5d60fdc38a383344f915564b86e2f 100644 (file)
@@ -888,7 +888,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
 {
        struct front_face *front = fh;
 
-       if (in->index < 0 || in->index >= POSEIDON_INPUTS)
+       if (in->index >= POSEIDON_INPUTS)
                return -EINVAL;
        strcpy(in->name, pd_inputs[in->index].name);
        in->type  = V4L2_INPUT_TYPE_TUNER;
@@ -923,7 +923,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
        struct poseidon *pd = front->pd;
        s32 ret, cmd_status;
 
-       if (i < 0 || i >= POSEIDON_INPUTS)
+       if (i >= POSEIDON_INPUTS)
                return -EINVAL;
        ret = send_set_req(pd, SGNL_SRC_SEL,
                        pd_inputs[i].tlg_src, &cmd_status);
index dffbd4bd47b15d92ffff672189aa2f18e90be4f0..8a6bbf1d80e1a484956bf655c9a1df75752a3b63 100644 (file)
@@ -109,12 +109,12 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
         */
 
        switch (ir->rc_type) {
-       case RC_TYPE_NEC:
+       case RC_BIT_NEC:
                leader = 900;   /* ms */
                pulse  = 700;   /* ms - the actual value would be 562 */
                break;
        default:
-       case RC_TYPE_RC5:
+       case RC_BIT_RC5:
                leader = 900;   /* ms - from the NEC decoding */
                pulse  = 1780;  /* ms - The actual value would be 1776 */
                break;
@@ -122,12 +122,12 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
 
        pulse = ir_clock_mhz * pulse;
        leader = ir_clock_mhz * leader;
-       if (ir->rc_type == RC_TYPE_NEC)
+       if (ir->rc_type == RC_BIT_NEC)
                leader = leader | 0x8000;
 
        dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
                __func__,
-               (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
+               (ir->rc_type == RC_BIT_NEC) ? "NEC" : "RC-5",
                ir_clock_mhz, leader, pulse);
 
        /* Remote WAKEUP = enable, normal mode, from IR decoder output */
@@ -297,7 +297,7 @@ static void tm6000_ir_stop(struct rc_dev *rc)
        cancel_delayed_work_sync(&ir->work);
 }
 
-static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
        struct tm6000_IR *ir = rc->priv;
 
@@ -306,10 +306,10 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 
        dprintk(2, "%s\n",__func__);
 
-       if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+       if ((rc->rc_map.scan) && (*rc_type == RC_BIT_NEC))
                ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
 
-       ir->rc_type = rc_type;
+       ir->rc_type = *rc_type;
 
        tm6000_ir_config(ir);
        /* TODO */
@@ -398,6 +398,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
        struct tm6000_IR *ir;
        struct rc_dev *rc;
        int err = -ENOMEM;
+       u64 rc_type;
 
        if (!enable_ir)
                return -ENODEV;
@@ -421,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
        ir->rc = rc;
 
        /* input setup */
-       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+       rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
        /* Neded, in order to support NEC remotes with 24 or 32 bits */
        rc->scanmask = 0xffff;
        rc->priv = ir;
@@ -444,7 +445,8 @@ int tm6000_ir_init(struct tm6000_core *dev)
        usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
        strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-       tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+       rc_type = RC_BIT_UNKNOWN;
+       tm6000_ir_change_protocol(rc, &rc_type);
 
        rc->input_name = ir->name;
        rc->input_phys = ir->phys;
index 4342cd4f5c8a7ad76cef1730348fb9ece2b1ada0..f656fd7a39a27de037923320ea605c0fe14c1e83 100644 (file)
@@ -1802,6 +1802,7 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
                if (!dev->radio_dev) {
                        printk(KERN_INFO "%s: can't register radio device\n",
                               dev->name);
+                       ret = -ENXIO;
                        return ret; /* FIXME release resource */
                }
 
index 43cf61fe4943a2b2f88fc0de7cd20f78ba5041bc..8a25876d72c601eaca1b820319129810daf9f313 100644 (file)
@@ -167,7 +167,7 @@ enum {
 
 /* This macro restricts an int variable to an inclusive range */
 #define RESTRICT_TO_RANGE(v, mi, ma) \
-       { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+       { if (((int)v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
 
 /*
  * We use macros to do YUV -> RGB conversion because this is
index f7061a5ef1d2a1c424c78f486d4348fc96b9b8ff..516a5b188ea5248a48f1cacb64cddb984096d9ea 100644 (file)
@@ -927,7 +927,7 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain,
        int ret;
 
        if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
-               return -EINVAL;
+               return -EACCES;
 
        if (!ctrl->loaded) {
                ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
@@ -1061,7 +1061,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
 
        ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
        if (ctrl == NULL) {
-               ret = -EINVAL;
+               ret = -ENOENT;
                goto done;
        }
 
@@ -1099,12 +1099,13 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
                return -ERESTARTSYS;
 
        ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
-               ret = -EINVAL;
+       if (ctrl == NULL) {
+               ret = -ENOENT;
                goto done;
        }
 
-       if (query_menu->index >= mapping->menu_count) {
+       if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU ||
+           query_menu->index >= mapping->menu_count) {
                ret = -EINVAL;
                goto done;
        }
@@ -1263,7 +1264,7 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
 
        ctrl = uvc_find_control(handle->chain, sev->id, &mapping);
        if (ctrl == NULL) {
-               ret = -EINVAL;
+               ret = -ENOENT;
                goto done;
        }
 
@@ -1414,7 +1415,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
 
        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
        if (ctrl == NULL)
-               return -EINVAL;
+               return -ENOENT;
 
        return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
 }
@@ -1431,8 +1432,10 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
        int ret;
 
        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
-       if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0)
-               return -EINVAL;
+       if (ctrl == NULL)
+               return -ENOENT;
+       if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
+               return -EACCES;
 
        /* Clamp out of range values. */
        switch (mapping->v4l2_type) {
@@ -1452,8 +1455,12 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
                if (step == 0)
                        step = 1;
 
-               xctrl->value = min + (xctrl->value - min + step/2) / step * step;
-               xctrl->value = clamp(xctrl->value, min, max);
+               xctrl->value = min + ((u32)(xctrl->value - min) + step / 2)
+                            / step * step;
+               if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
+                       xctrl->value = clamp(xctrl->value, min, max);
+               else
+                       xctrl->value = clamp_t(u32, xctrl->value, min, max);
                value = xctrl->value;
                break;
 
index 5967081747ceb974814a5818ad8cccb43aacf64a..5dbefa68b1d20f0e0ca14fd725b99aafb9410fcd 100644 (file)
@@ -1562,6 +1562,9 @@ static int uvc_scan_device(struct uvc_device *dev)
                INIT_LIST_HEAD(&chain->entities);
                mutex_init(&chain->ctrl_mutex);
                chain->dev = dev;
+               v4l2_prio_init(&chain->prio);
+
+               term->flags |= UVC_ENTITY_FLAG_DEFAULT;
 
                if (uvc_scan_chain(chain, term) < 0) {
                        kfree(chain);
@@ -1722,6 +1725,8 @@ static int uvc_register_video(struct uvc_device *dev,
        vdev->v4l2_dev = &dev->vdev;
        vdev->fops = &uvc_fops;
        vdev->release = uvc_release;
+       vdev->prio = &stream->chain->prio;
+       set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
        if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
                vdev->vfl_dir = VFL_DIR_TX;
        strlcpy(vdev->name, dev->name, sizeof vdev->name);
@@ -1741,6 +1746,11 @@ static int uvc_register_video(struct uvc_device *dev,
                return ret;
        }
 
+       if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               stream->chain->caps |= V4L2_CAP_VIDEO_CAPTURE;
+       else
+               stream->chain->caps |= V4L2_CAP_VIDEO_OUTPUT;
+
        atomic_inc(&dev->nstreams);
        return 0;
 }
index 29e239911d0e28a6d7a688ab5907781ffa1b41d0..dc56a59ecadc4b5dc2185a9717256eec96ba17c0 100644 (file)
@@ -93,6 +93,8 @@ static int uvc_mc_init_entity(struct uvc_entity *entity)
        } else if (entity->vdev != NULL) {
                ret = media_entity_init(&entity->vdev->entity,
                                        entity->num_pads, entity->pads, 0);
+               if (entity->flags & UVC_ENTITY_FLAG_DEFAULT)
+                       entity->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
        } else
                ret = 0;
 
index 18a91fae6bc1869e644ffa05e5e103e13b67a3dc..778addc5caffa3112f6509a57269f30431e1d58d 100644 (file)
@@ -128,7 +128,7 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
        int ret;
 
        queue->queue.type = type;
-       queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+       queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
        queue->queue.drv_priv = queue;
        queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
        queue->queue.ops = &uvc_queue_qops;
index f00db3060e0e36e005b306a53f393cc55071b101..8e056046bc203c4224dd08fa931f56219bdd6157 100644 (file)
@@ -165,17 +165,18 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
                        fcc[0], fcc[1], fcc[2], fcc[3],
                        fmt->fmt.pix.width, fmt->fmt.pix.height);
 
-       /* Check if the hardware supports the requested format. */
+       /* Check if the hardware supports the requested format, use the default
+        * format otherwise.
+        */
        for (i = 0; i < stream->nformats; ++i) {
                format = &stream->format[i];
                if (format->fcc == fmt->fmt.pix.pixelformat)
                        break;
        }
 
-       if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
-               uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n",
-                               fmt->fmt.pix.pixelformat);
-               return -EINVAL;
+       if (i == stream->nformats) {
+               format = stream->def_format;
+               fmt->fmt.pix.pixelformat = format->fcc;
        }
 
        /* Find the closest image size. The distance between image sizes is
@@ -564,15 +565,30 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                usb_make_path(stream->dev->udev,
                              cap->bus_info, sizeof(cap->bus_info));
                cap->version = LINUX_VERSION_CODE;
+               cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+                                 | chain->caps;
                if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
-                                         | V4L2_CAP_STREAMING;
+                       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+                                        | V4L2_CAP_STREAMING;
                else
-                       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
-                                         | V4L2_CAP_STREAMING;
+                       cap->device_caps = V4L2_CAP_VIDEO_OUTPUT
+                                        | V4L2_CAP_STREAMING;
                break;
        }
 
+       /* Priority */
+       case VIDIOC_G_PRIORITY:
+               *(u32 *)arg = v4l2_prio_max(vdev->prio);
+               break;
+
+       case VIDIOC_S_PRIORITY:
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
+               return v4l2_prio_change(vdev->prio, &handle->vfh.prio,
+                                       *(u32 *)arg);
+
        /* Get, Set & Query control */
        case VIDIOC_QUERYCTRL:
                return uvc_query_v4l2_ctrl(chain, arg);
@@ -591,8 +607,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
                ret = uvc_ctrl_get(chain, &xctrl);
                uvc_ctrl_rollback(handle);
-               if (ret >= 0)
-                       ctrl->value = xctrl.value;
+               if (ret < 0)
+                       return ret == -ENOENT ? -EINVAL : ret;
+
+               ctrl->value = xctrl.value;
                break;
        }
 
@@ -601,6 +619,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                struct v4l2_control *ctrl = arg;
                struct v4l2_ext_control xctrl;
 
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                memset(&xctrl, 0, sizeof xctrl);
                xctrl.id = ctrl->id;
                xctrl.value = ctrl->value;
@@ -612,7 +634,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                ret = uvc_ctrl_set(chain, &xctrl);
                if (ret < 0) {
                        uvc_ctrl_rollback(handle);
-                       return ret;
+                       return ret == -ENOENT ? -EINVAL : ret;
                }
                ret = uvc_ctrl_commit(handle, &xctrl, 1);
                if (ret == 0)
@@ -637,8 +659,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        ret = uvc_ctrl_get(chain, ctrl);
                        if (ret < 0) {
                                uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = i;
-                               return ret;
+                               ctrls->error_idx = ret == -ENOENT
+                                                ? ctrls->count : i;
+                               return ret == -ENOENT ? -EINVAL : ret;
                        }
                }
                ctrls->error_idx = 0;
@@ -647,6 +670,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_S_EXT_CTRLS:
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+               /* Fall through */
        case VIDIOC_TRY_EXT_CTRLS:
        {
                struct v4l2_ext_controls *ctrls = arg;
@@ -661,8 +688,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        ret = uvc_ctrl_set(chain, ctrl);
                        if (ret < 0) {
                                uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = i;
-                               return ret;
+                               ctrls->error_idx = (ret == -ENOENT &&
+                                                   cmd == VIDIOC_S_EXT_CTRLS)
+                                                ? ctrls->count : i;
+                               return ret == -ENOENT ? -EINVAL : ret;
                        }
                }
 
@@ -739,6 +768,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        {
                u32 input = *(u32 *)arg + 1;
 
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
@@ -792,6 +825,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_S_FMT:
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
@@ -894,6 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                return uvc_v4l2_get_streamparm(stream, arg);
 
        case VIDIOC_S_PARM:
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
@@ -924,10 +965,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
        case VIDIOC_G_CROP:
        case VIDIOC_S_CROP:
-               return -EINVAL;
+               return -ENOTTY;
 
        /* Buffers & streaming */
        case VIDIOC_REQBUFS:
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
@@ -973,6 +1018,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (*type != stream->type)
                        return -EINVAL;
 
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
@@ -991,6 +1040,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (*type != stream->type)
                        return -EINVAL;
 
+               ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+               if (ret < 0)
+                       return ret;
+
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
@@ -1030,7 +1083,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
        case VIDIOC_ENUMOUTPUT:
                uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
-               return -EINVAL;
+               return -ENOTTY;
 
        case UVCIOC_CTRL_MAP:
                return uvc_ioctl_ctrl_map(chain, arg);
index 57c3076a4625b09d4b75d05671c3bfbe38eb9109..3394c34320117542ccab9adc4607a1caedb18f53 100644 (file)
@@ -1812,6 +1812,7 @@ int uvc_video_init(struct uvc_streaming *stream)
        probe->bFormatIndex = format->index;
        probe->bFrameIndex = frame->bFrameIndex;
 
+       stream->def_format = format;
        stream->cur_format = format;
        stream->cur_frame = frame;
 
index af216ec45e390fa1bc8863372fd742b6b43b53da..af505fdd9b3f73d581665f660cf622921bea64c2 100644 (file)
@@ -225,10 +225,14 @@ struct uvc_format_desc {
  * always be accessed with the UVC_ENTITY_* macros and never directly.
  */
 
+#define UVC_ENTITY_FLAG_DEFAULT                (1 << 0)
+
 struct uvc_entity {
        struct list_head list;          /* Entity as part of a UVC device. */
        struct list_head chain;         /* Entity as part of a video device
                                         * chain. */
+       unsigned int flags;
+
        __u8 id;
        __u16 type;
        char name[64];
@@ -371,6 +375,9 @@ struct uvc_video_chain {
        struct uvc_entity *selector;            /* Selector unit */
 
        struct mutex ctrl_mutex;                /* Protects ctrl.info */
+
+       struct v4l2_prio_state prio;            /* V4L2 priority state */
+       u32 caps;                               /* V4L2 chain-wide caps */
 };
 
 struct uvc_stats_frame {
@@ -436,6 +443,7 @@ struct uvc_streaming {
        struct uvc_format *format;
 
        struct uvc_streaming_control ctrl;
+       struct uvc_format *def_format;
        struct uvc_format *cur_format;
        struct uvc_frame *cur_frame;
        /* Protect access to ctrl, cur_format, cur_frame and hardware video
index 9afab35878b417f0c0ef7a7b352b718655373d7b..39edd444293226406a4faed135930dcf09ff059c 100644 (file)
@@ -1007,8 +1007,7 @@ static void read_pipe_completion(struct urb *purb)
                return;
        }
 
-       if (purb->actual_length < 0 ||
-           purb->actual_length > pipe_info->transfer_size) {
+       if (purb->actual_length > pipe_info->transfer_size) {
                dev_err(&cam->udev->dev, "wrong number of bytes\n");
                return;
        }
index 0c54e19d9944271bca76d9658363aea34aaccd5a..65875c3aba1b5e59c2d5df049e0e9defd0543a45 100644 (file)
@@ -59,6 +59,7 @@ config VIDEOBUF_DVB
 
 # Used by drivers that need Videobuf2 modules
 config VIDEOBUF2_CORE
+       select DMA_SHARED_BUFFER
        tristate
 
 config VIDEOBUF2_MEMOPS
@@ -68,11 +69,13 @@ config VIDEOBUF2_DMA_CONTIG
        tristate
        select VIDEOBUF2_CORE
        select VIDEOBUF2_MEMOPS
+       select DMA_SHARED_BUFFER
 
 config VIDEOBUF2_VMALLOC
        tristate
        select VIDEOBUF2_CORE
        select VIDEOBUF2_MEMOPS
+       select DMA_SHARED_BUFFER
 
 config VIDEOBUF2_DMA_SG
        tristate
index f995dd31151d0cc36bce91110e8ca3c0443c0138..380ddd89fa4c6f8d6c1bb1b612eeb97fa8420a9f 100644 (file)
@@ -837,7 +837,7 @@ bool v4l2_detect_gtf(unsigned frame_height,
                struct v4l2_dv_timings *fmt)
 {
        int pix_clk;
-       int  v_fp, v_bp, h_fp, h_bp, hsync;
+       int  v_fp, v_bp, h_fp, hsync;
        int frame_width, image_height, image_width;
        bool default_gtf;
        int h_blank;
@@ -885,7 +885,6 @@ bool v4l2_detect_gtf(unsigned frame_height,
        hsync = hsync - hsync % GTF_CELL_GRAN;
 
        h_fp = h_blank / 2 - hsync;
-       h_bp = h_blank / 2;
 
        fmt->bt.polarities = polarities;
        fmt->bt.width = image_width;
index 83ffb6436baf67e22f7308acae67966dbfef6094..7157af301b14946b6b7c3ecbd0933fe80e472f35 100644 (file)
@@ -297,6 +297,7 @@ struct v4l2_plane32 {
        union {
                __u32           mem_offset;
                compat_long_t   userptr;
+               __s32           fd;
        } m;
        __u32                   data_offset;
        __u32                   reserved[11];
@@ -318,6 +319,7 @@ struct v4l2_buffer32 {
                __u32           offset;
                compat_long_t   userptr;
                compat_caddr_t  planes;
+               __s32           fd;
        } m;
        __u32                   length;
        __u32                   reserved2;
@@ -341,6 +343,9 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
                up_pln = compat_ptr(p);
                if (put_user((unsigned long)up_pln, &up->m.userptr))
                        return -EFAULT;
+       } else if (memory == V4L2_MEMORY_DMABUF) {
+               if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
+                       return -EFAULT;
        } else {
                if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
                                        sizeof(__u32)))
@@ -364,6 +369,11 @@ static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
                if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
                                        sizeof(__u32)))
                        return -EFAULT;
+       /* For DMABUF, driver might've set up the fd, so copy it back. */
+       if (memory == V4L2_MEMORY_DMABUF)
+               if (copy_in_user(&up32->m.fd, &up->m.fd,
+                                       sizeof(int)))
+                       return -EFAULT;
 
        return 0;
 }
@@ -446,6 +456,10 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
                        if (get_user(kp->m.offset, &up->m.offset))
                                return -EFAULT;
                        break;
+               case V4L2_MEMORY_DMABUF:
+                       if (get_user(kp->m.fd, &up->m.fd))
+                               return -EFAULT;
+                       break;
                }
        }
 
@@ -510,6 +524,10 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
                        if (put_user(kp->m.offset, &up->m.offset))
                                return -EFAULT;
                        break;
+               case V4L2_MEMORY_DMABUF:
+                       if (put_user(kp->m.fd, &up->m.fd))
+                               return -EFAULT;
+                       break;
                }
        }
 
@@ -1000,6 +1018,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_S_FBUF32:
        case VIDIOC_OVERLAY32:
        case VIDIOC_QBUF32:
+       case VIDIOC_EXPBUF:
        case VIDIOC_DQBUF32:
        case VIDIOC_STREAMON32:
        case VIDIOC_STREAMOFF32:
index a2df842e5100cfbffb16a0e88d4c2400d0666765..98dcad9c8a3bc804c941606dc82088b1d7dae414 100644 (file)
@@ -571,6 +571,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
        SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
        SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
        SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
+       SET_VALID_IOCTL(ops, VIDIOC_EXPBUF, vidioc_expbuf);
        SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
        SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
        SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
index 18a040b935a312d31abb944c50405e026a510f1b..c7200921815282a11e0afa1804840fa803e07917 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 9e3fc040ea20303056fcffcaa0b6f0f318deffb4..e57c002b415066a7cf616cc9ef719b12a855bd2b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 8f388ff31ebb8732fd1793778c578f9395df777a..aa6e7c788db2b00ed0493c9babae92924a65b6a5 100644 (file)
@@ -155,6 +155,7 @@ static const char *v4l2_memory_names[] = {
        [V4L2_MEMORY_MMAP]    = "mmap",
        [V4L2_MEMORY_USERPTR] = "userptr",
        [V4L2_MEMORY_OVERLAY] = "overlay",
+       [V4L2_MEMORY_DMABUF] = "dmabuf",
 };
 
 #define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
@@ -453,6 +454,15 @@ static void v4l_print_buffer(const void *arg, bool write_only)
                        tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
 }
 
+static void v4l_print_exportbuffer(const void *arg, bool write_only)
+{
+       const struct v4l2_exportbuffer *p = arg;
+
+       pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n",
+               p->fd, prt_names(p->type, v4l2_type_names),
+               p->index, p->plane, p->flags);
+}
+
 static void v4l_print_create_buffers(const void *arg, bool write_only)
 {
        const struct v4l2_create_buffers *p = arg;
@@ -1960,6 +1970,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
        IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
+       IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
        IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
        IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
        IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
index 3ac83583ad7ae5695e3087d2960bc88647c4e501..438ea45d10749750a2941474265b0e72ea75f239 100644 (file)
@@ -368,6 +368,19 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
 
+/**
+ * v4l2_m2m_expbuf() - export a source or destination buffer, depending on
+ * the type
+ */
+int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+                 struct v4l2_exportbuffer *eb)
+{
+       struct vb2_queue *vq;
+
+       vq = v4l2_m2m_get_vq(m2m_ctx, eb->type);
+       return vb2_expbuf(vq, eb);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_expbuf);
 /**
  * v4l2_m2m_streamon() - turn on streaming for a video queue
  */
@@ -510,12 +523,10 @@ struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops)
 {
        struct v4l2_m2m_dev *m2m_dev;
 
-       if (!m2m_ops)
+       if (!m2m_ops || WARN_ON(!m2m_ops->device_run) ||
+                       WARN_ON(!m2m_ops->job_abort))
                return ERR_PTR(-EINVAL);
 
-       BUG_ON(!m2m_ops->device_run);
-       BUG_ON(!m2m_ops->job_abort);
-
        m2m_dev = kzalloc(sizeof *m2m_dev, GFP_KERNEL);
        if (!m2m_dev)
                return ERR_PTR(-ENOMEM);
index dced41c1d993d78f72c20f0ac00592154393b206..996c248dea42bc501497b2b6328321c456373d3b 100644 (file)
@@ -412,20 +412,20 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
                                     struct v4l2_subdev_format *fmt)
 {
-       switch (media_entity_type(pad->entity)) {
-       case MEDIA_ENT_T_V4L2_SUBDEV:
+       if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+               struct v4l2_subdev *sd =
+                       media_entity_to_v4l2_subdev(pad->entity);
+
                fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
                fmt->pad = pad->index;
-               return v4l2_subdev_call(media_entity_to_v4l2_subdev(
-                                               pad->entity),
-                                       pad, get_fmt, NULL, fmt);
-       default:
-               WARN(1, "Driver bug! Wrong media entity type %d, entity %s\n",
-                    media_entity_type(pad->entity), pad->entity->name);
-               /* Fall through */
-       case MEDIA_ENT_T_DEVNODE_V4L:
-               return -EINVAL;
+               return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
        }
+
+       WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L,
+            "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
+            pad->entity->type, pad->entity->name);
+
+       return -EINVAL;
 }
 
 int v4l2_subdev_link_validate(struct media_link *link)
index bf7a326b1cdc06f8346981f246a74be572894fe4..5449e8aa984a7b9ba18d1f02679a68d976411f9c 100644 (file)
@@ -335,6 +335,9 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
        case V4L2_MEMORY_OVERLAY:
                b->m.offset  = vb->boff;
                break;
+       case V4L2_MEMORY_DMABUF:
+               /* DMABUF is not handled in videobuf framework */
+               break;
        }
 
        b->flags    = 0;
@@ -405,6 +408,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q,
                        break;
                case V4L2_MEMORY_USERPTR:
                case V4L2_MEMORY_OVERLAY:
+               case V4L2_MEMORY_DMABUF:
                        /* nothing */
                        break;
                }
index 432df119af278dd953a492fece76552a4c8d3e86..9f81be23a81f06a1d527ac792071e1b7a6154979 100644 (file)
@@ -108,6 +108,36 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
        }
 }
 
+/**
+ * __vb2_plane_dmabuf_put() - release memory associated with
+ * a DMABUF shared plane
+ */
+static void __vb2_plane_dmabuf_put(struct vb2_queue *q, struct vb2_plane *p)
+{
+       if (!p->mem_priv)
+               return;
+
+       if (p->dbuf_mapped)
+               call_memop(q, unmap_dmabuf, p->mem_priv);
+
+       call_memop(q, detach_dmabuf, p->mem_priv);
+       dma_buf_put(p->dbuf);
+       memset(p, 0, sizeof(*p));
+}
+
+/**
+ * __vb2_buf_dmabuf_put() - release memory associated with
+ * a DMABUF shared buffer
+ */
+static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       unsigned int plane;
+
+       for (plane = 0; plane < vb->num_planes; ++plane)
+               __vb2_plane_dmabuf_put(q, &vb->planes[plane]);
+}
+
 /**
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
@@ -230,6 +260,8 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
                /* Free MMAP buffers or release USERPTR buffers */
                if (q->memory == V4L2_MEMORY_MMAP)
                        __vb2_buf_mem_free(vb);
+               else if (q->memory == V4L2_MEMORY_DMABUF)
+                       __vb2_buf_dmabuf_put(vb);
                else
                        __vb2_buf_userptr_put(vb);
        }
@@ -362,6 +394,8 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
                        b->m.offset = vb->v4l2_planes[0].m.mem_offset;
                else if (q->memory == V4L2_MEMORY_USERPTR)
                        b->m.userptr = vb->v4l2_planes[0].m.userptr;
+               else if (q->memory == V4L2_MEMORY_DMABUF)
+                       b->m.fd = vb->v4l2_planes[0].m.fd;
        }
 
        /*
@@ -453,6 +487,20 @@ static int __verify_mmap_ops(struct vb2_queue *q)
        return 0;
 }
 
+/**
+ * __verify_dmabuf_ops() - verify that all memory operations required for
+ * DMABUF queue type have been provided
+ */
+static int __verify_dmabuf_ops(struct vb2_queue *q)
+{
+       if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
+           !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
+           !q->mem_ops->unmap_dmabuf)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * __verify_memory_type() - Check whether the memory type and buffer type
  * passed to a buffer operation are compatible with the queue.
@@ -460,7 +508,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
 static int __verify_memory_type(struct vb2_queue *q,
                enum v4l2_memory memory, enum v4l2_buf_type type)
 {
-       if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR) {
+       if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
+           memory != V4L2_MEMORY_DMABUF) {
                dprintk(1, "reqbufs: unsupported memory type\n");
                return -EINVAL;
        }
@@ -484,6 +533,11 @@ static int __verify_memory_type(struct vb2_queue *q,
                return -EINVAL;
        }
 
+       if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
+               dprintk(1, "reqbufs: DMABUF for current setup unsupported\n");
+               return -EINVAL;
+       }
+
        /*
         * Place the busy tests at the end: -EBUSY can be ignored when
         * create_bufs is called with count == 0, but count == 0 should still
@@ -790,6 +844,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 {
        struct vb2_queue *q = vb->vb2_queue;
        unsigned long flags;
+       unsigned int plane;
 
        if (vb->state != VB2_BUF_STATE_ACTIVE)
                return;
@@ -800,6 +855,10 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
        dprintk(4, "Done processing on buffer %d, state: %d\n",
                        vb->v4l2_buf.index, vb->state);
 
+       /* sync buffers */
+       for (plane = 0; plane < vb->num_planes; ++plane)
+               call_memop(q, finish, vb->planes[plane].mem_priv);
+
        /* Add the buffer to the done buffers list */
        spin_lock_irqsave(&q->done_lock, flags);
        vb->state = state;
@@ -845,6 +904,16 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                                        b->m.planes[plane].length;
                        }
                }
+               if (b->memory == V4L2_MEMORY_DMABUF) {
+                       for (plane = 0; plane < vb->num_planes; ++plane) {
+                               v4l2_planes[plane].m.fd =
+                                       b->m.planes[plane].m.fd;
+                               v4l2_planes[plane].length =
+                                       b->m.planes[plane].length;
+                               v4l2_planes[plane].data_offset =
+                                       b->m.planes[plane].data_offset;
+                       }
+               }
        } else {
                /*
                 * Single-planar buffers do not use planes array,
@@ -859,6 +928,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                        v4l2_planes[0].m.userptr = b->m.userptr;
                        v4l2_planes[0].length = b->length;
                }
+
+               if (b->memory == V4L2_MEMORY_DMABUF) {
+                       v4l2_planes[0].m.fd = b->m.fd;
+                       v4l2_planes[0].length = b->length;
+                       v4l2_planes[0].data_offset = 0;
+               }
+
        }
 
        vb->v4l2_buf.field = b->field;
@@ -958,15 +1034,122 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        return 0;
 }
 
+/**
+ * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
+ */
+static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+       struct v4l2_plane planes[VIDEO_MAX_PLANES];
+       struct vb2_queue *q = vb->vb2_queue;
+       void *mem_priv;
+       unsigned int plane;
+       int ret;
+       int write = !V4L2_TYPE_IS_OUTPUT(q->type);
+
+       /* Verify and copy relevant information provided by the userspace */
+       __fill_vb2_buffer(vb, b, planes);
+
+       for (plane = 0; plane < vb->num_planes; ++plane) {
+               struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
+
+               if (IS_ERR_OR_NULL(dbuf)) {
+                       dprintk(1, "qbuf: invalid dmabuf fd for plane %d\n",
+                               plane);
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               /* use DMABUF size if length is not provided */
+               if (planes[plane].length == 0)
+                       planes[plane].length = dbuf->size;
+
+               if (planes[plane].length < planes[plane].data_offset +
+                   q->plane_sizes[plane]) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               /* Skip the plane if already verified */
+               if (dbuf == vb->planes[plane].dbuf &&
+                   vb->v4l2_planes[plane].length == planes[plane].length) {
+                       dma_buf_put(dbuf);
+                       continue;
+               }
+
+               dprintk(1, "qbuf: buffer for plane %d changed\n", plane);
+
+               /* Release previously acquired memory if present */
+               __vb2_plane_dmabuf_put(q, &vb->planes[plane]);
+               memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
+
+               /* Acquire each plane's memory */
+               mem_priv = call_memop(q, attach_dmabuf, q->alloc_ctx[plane],
+                       dbuf, planes[plane].length, write);
+               if (IS_ERR(mem_priv)) {
+                       dprintk(1, "qbuf: failed to attach dmabuf\n");
+                       ret = PTR_ERR(mem_priv);
+                       dma_buf_put(dbuf);
+                       goto err;
+               }
+
+               vb->planes[plane].dbuf = dbuf;
+               vb->planes[plane].mem_priv = mem_priv;
+       }
+
+       /* TODO: This pins the buffer(s) with  dma_buf_map_attachment()).. but
+        * really we want to do this just before the DMA, not while queueing
+        * the buffer(s)..
+        */
+       for (plane = 0; plane < vb->num_planes; ++plane) {
+               ret = call_memop(q, map_dmabuf, vb->planes[plane].mem_priv);
+               if (ret) {
+                       dprintk(1, "qbuf: failed to map dmabuf for plane %d\n",
+                               plane);
+                       goto err;
+               }
+               vb->planes[plane].dbuf_mapped = 1;
+       }
+
+       /*
+        * Call driver-specific initialization on the newly acquired buffer,
+        * if provided.
+        */
+       ret = call_qop(q, buf_init, vb);
+       if (ret) {
+               dprintk(1, "qbuf: buffer initialization failed\n");
+               goto err;
+       }
+
+       /*
+        * Now that everything is in order, copy relevant information
+        * provided by userspace.
+        */
+       for (plane = 0; plane < vb->num_planes; ++plane)
+               vb->v4l2_planes[plane] = planes[plane];
+
+       return 0;
+err:
+       /* In case of errors, release planes that were already acquired */
+       __vb2_buf_dmabuf_put(vb);
+
+       return ret;
+}
+
 /**
  * __enqueue_in_driver() - enqueue a vb2_buffer in driver for processing
  */
 static void __enqueue_in_driver(struct vb2_buffer *vb)
 {
        struct vb2_queue *q = vb->vb2_queue;
+       unsigned int plane;
 
        vb->state = VB2_BUF_STATE_ACTIVE;
        atomic_inc(&q->queued_count);
+
+       /* sync buffers */
+       for (plane = 0; plane < vb->num_planes; ++plane)
+               call_memop(q, prepare, vb->planes[plane].mem_priv);
+
        q->ops->buf_queue(vb);
 }
 
@@ -982,6 +1165,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        case V4L2_MEMORY_USERPTR:
                ret = __qbuf_userptr(vb, b);
                break;
+       case V4L2_MEMORY_DMABUF:
+               ret = __qbuf_dmabuf(vb, b);
+               break;
        default:
                WARN(1, "Invalid queue type\n");
                ret = -EINVAL;
@@ -1302,6 +1488,30 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q)
 }
 EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
 
+/**
+ * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state
+ */
+static void __vb2_dqbuf(struct vb2_buffer *vb)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       unsigned int i;
+
+       /* nothing to do if the buffer is already dequeued */
+       if (vb->state == VB2_BUF_STATE_DEQUEUED)
+               return;
+
+       vb->state = VB2_BUF_STATE_DEQUEUED;
+
+       /* unmap DMABUF buffer */
+       if (q->memory == V4L2_MEMORY_DMABUF)
+               for (i = 0; i < vb->num_planes; ++i) {
+                       if (!vb->planes[i].dbuf_mapped)
+                               continue;
+                       call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv);
+                       vb->planes[i].dbuf_mapped = 0;
+               }
+}
+
 /**
  * vb2_dqbuf() - Dequeue a buffer to the userspace
  * @q:         videobuf2 queue
@@ -1363,11 +1573,12 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
        __fill_v4l2_buffer(vb, b);
        /* Remove from videobuf queue */
        list_del(&vb->queued_entry);
+       /* go back to dequeued state */
+       __vb2_dqbuf(vb);
 
        dprintk(1, "dqbuf of buffer %d, with state %d\n",
                        vb->v4l2_buf.index, vb->state);
 
-       vb->state = VB2_BUF_STATE_DEQUEUED;
        return 0;
 }
 EXPORT_SYMBOL_GPL(vb2_dqbuf);
@@ -1406,7 +1617,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
         * Reinitialize all buffers for next use.
         */
        for (i = 0; i < q->num_buffers; ++i)
-               q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
+               __vb2_dqbuf(q->bufs[i]);
 }
 
 /**
@@ -1539,6 +1750,79 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
        return -EINVAL;
 }
 
+/**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q:         videobuf2 queue
+ * @eb:                export buffer structure passed from userspace to vidioc_expbuf
+ *             handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+       struct vb2_buffer *vb = NULL;
+       struct vb2_plane *vb_plane;
+       int ret;
+       struct dma_buf *dbuf;
+
+       if (q->memory != V4L2_MEMORY_MMAP) {
+               dprintk(1, "Queue is not currently set up for mmap\n");
+               return -EINVAL;
+       }
+
+       if (!q->mem_ops->get_dmabuf) {
+               dprintk(1, "Queue does not support DMA buffer exporting\n");
+               return -EINVAL;
+       }
+
+       if (eb->flags & ~O_CLOEXEC) {
+               dprintk(1, "Queue does support only O_CLOEXEC flag\n");
+               return -EINVAL;
+       }
+
+       if (eb->type != q->type) {
+               dprintk(1, "qbuf: invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       if (eb->index >= q->num_buffers) {
+               dprintk(1, "buffer index out of range\n");
+               return -EINVAL;
+       }
+
+       vb = q->bufs[eb->index];
+
+       if (eb->plane >= vb->num_planes) {
+               dprintk(1, "buffer plane out of range\n");
+               return -EINVAL;
+       }
+
+       vb_plane = &vb->planes[eb->plane];
+
+       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+       if (IS_ERR_OR_NULL(dbuf)) {
+               dprintk(1, "Failed to export buffer %d, plane %d\n",
+                       eb->index, eb->plane);
+               return -EINVAL;
+       }
+
+       ret = dma_buf_fd(dbuf, eb->flags);
+       if (ret < 0) {
+               dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
+                       eb->index, eb->plane, ret);
+               dma_buf_put(dbuf);
+               return ret;
+       }
+
+       dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
+               eb->index, eb->plane, ret);
+       eb->fd = ret;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
 /**
  * vb2_mmap() - map video buffers into application address space
  * @q:         videobuf2 queue
@@ -2245,6 +2529,16 @@ int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 }
 EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
 
+int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_expbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
+
 /* v4l2_file_operations helpers */
 
 int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
index 4b7132660a938f52b105b6306b39d5d54a39777e..10beaee7f0ae592ae88803d7720d298a20beac0d 100644 (file)
  * the Free Software Foundation.
  */
 
+#include <linux/dma-buf.h>
 #include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
@@ -23,40 +26,158 @@ struct vb2_dc_conf {
 };
 
 struct vb2_dc_buf {
-       struct vb2_dc_conf              *conf;
+       struct device                   *dev;
        void                            *vaddr;
-       dma_addr_t                      dma_addr;
        unsigned long                   size;
-       struct vm_area_struct           *vma;
-       atomic_t                        refcount;
+       dma_addr_t                      dma_addr;
+       enum dma_data_direction         dma_dir;
+       struct sg_table                 *dma_sgt;
+
+       /* MMAP related */
        struct vb2_vmarea_handler       handler;
+       atomic_t                        refcount;
+       struct sg_table                 *sgt_base;
+
+       /* USERPTR related */
+       struct vm_area_struct           *vma;
+
+       /* DMABUF related */
+       struct dma_buf_attachment       *db_attach;
 };
 
-static void vb2_dma_contig_put(void *buf_priv);
+/*********************************************/
+/*        scatterlist table functions        */
+/*********************************************/
+
+
+static void vb2_dc_sgt_foreach_page(struct sg_table *sgt,
+       void (*cb)(struct page *pg))
+{
+       struct scatterlist *s;
+       unsigned int i;
+
+       for_each_sg(sgt->sgl, s, sgt->orig_nents, i) {
+               struct page *page = sg_page(s);
+               unsigned int n_pages = PAGE_ALIGN(s->offset + s->length)
+                       >> PAGE_SHIFT;
+               unsigned int j;
+
+               for (j = 0; j < n_pages; ++j, ++page)
+                       cb(page);
+       }
+}
+
+static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt)
+{
+       struct scatterlist *s;
+       dma_addr_t expected = sg_dma_address(sgt->sgl);
+       unsigned int i;
+       unsigned long size = 0;
+
+       for_each_sg(sgt->sgl, s, sgt->nents, i) {
+               if (sg_dma_address(s) != expected)
+                       break;
+               expected = sg_dma_address(s) + sg_dma_len(s);
+               size += sg_dma_len(s);
+       }
+       return size;
+}
+
+/*********************************************/
+/*         callbacks for all buffers         */
+/*********************************************/
+
+static void *vb2_dc_cookie(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+
+       return &buf->dma_addr;
+}
+
+static void *vb2_dc_vaddr(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+
+       return buf->vaddr;
+}
+
+static unsigned int vb2_dc_num_users(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+
+       return atomic_read(&buf->refcount);
+}
+
+static void vb2_dc_prepare(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+       struct sg_table *sgt = buf->dma_sgt;
+
+       /* DMABUF exporter will flush the cache for us */
+       if (!sgt || buf->db_attach)
+               return;
+
+       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dc_finish(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+       struct sg_table *sgt = buf->dma_sgt;
+
+       /* DMABUF exporter will flush the cache for us */
+       if (!sgt || buf->db_attach)
+               return;
+
+       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+/*********************************************/
+/*        callbacks for MMAP buffers         */
+/*********************************************/
+
+static void vb2_dc_put(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+
+       if (!atomic_dec_and_test(&buf->refcount))
+               return;
+
+       if (buf->sgt_base) {
+               sg_free_table(buf->sgt_base);
+               kfree(buf->sgt_base);
+       }
+       dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+       put_device(buf->dev);
+       kfree(buf);
+}
 
-static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 {
        struct vb2_dc_conf *conf = alloc_ctx;
+       struct device *dev = conf->dev;
        struct vb2_dc_buf *buf;
 
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)
                return ERR_PTR(-ENOMEM);
 
-       buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
-                                       GFP_KERNEL);
+       /* align image size to PAGE_SIZE */
+       size = PAGE_ALIGN(size);
+
+       buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
        if (!buf->vaddr) {
-               dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
-                       size);
+               dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
                kfree(buf);
                return ERR_PTR(-ENOMEM);
        }
 
-       buf->conf = conf;
+       /* Prevent the device from being released while the buffer is used */
+       buf->dev = get_device(dev);
        buf->size = size;
 
        buf->handler.refcount = &buf->refcount;
-       buf->handler.put = vb2_dma_contig_put;
+       buf->handler.put = vb2_dc_put;
        buf->handler.arg = buf;
 
        atomic_inc(&buf->refcount);
@@ -64,100 +185,569 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
        return buf;
 }
 
-static void vb2_dma_contig_put(void *buf_priv)
+static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
        struct vb2_dc_buf *buf = buf_priv;
+       int ret;
 
-       if (atomic_dec_and_test(&buf->refcount)) {
-               dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
-                                 buf->dma_addr);
-               kfree(buf);
+       if (!buf) {
+               printk(KERN_ERR "No buffer to map\n");
+               return -EINVAL;
+       }
+
+       /*
+        * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
+        * map whole buffer
+        */
+       vma->vm_pgoff = 0;
+
+       ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
+               buf->dma_addr, buf->size);
+
+       if (ret) {
+               pr_err("Remapping memory failed, error: %d\n", ret);
+               return ret;
        }
+
+       vma->vm_flags           |= VM_DONTEXPAND | VM_DONTDUMP;
+       vma->vm_private_data    = &buf->handler;
+       vma->vm_ops             = &vb2_common_vm_ops;
+
+       vma->vm_ops->open(vma);
+
+       pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
+               __func__, (unsigned long)buf->dma_addr, vma->vm_start,
+               buf->size);
+
+       return 0;
 }
 
-static void *vb2_dma_contig_cookie(void *buf_priv)
+/*********************************************/
+/*         DMABUF ops for exporters          */
+/*********************************************/
+
+struct vb2_dc_attachment {
+       struct sg_table sgt;
+       enum dma_data_direction dir;
+};
+
+static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+       struct dma_buf_attachment *dbuf_attach)
 {
-       struct vb2_dc_buf *buf = buf_priv;
+       struct vb2_dc_attachment *attach;
+       unsigned int i;
+       struct scatterlist *rd, *wr;
+       struct sg_table *sgt;
+       struct vb2_dc_buf *buf = dbuf->priv;
+       int ret;
 
-       return &buf->dma_addr;
+       attach = kzalloc(sizeof(*attach), GFP_KERNEL);
+       if (!attach)
+               return -ENOMEM;
+
+       sgt = &attach->sgt;
+       /* Copy the buf->base_sgt scatter list to the attachment, as we can't
+        * map the same scatter list to multiple attachments at the same time.
+        */
+       ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL);
+       if (ret) {
+               kfree(attach);
+               return -ENOMEM;
+       }
+
+       rd = buf->sgt_base->sgl;
+       wr = sgt->sgl;
+       for (i = 0; i < sgt->orig_nents; ++i) {
+               sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
+               rd = sg_next(rd);
+               wr = sg_next(wr);
+       }
+
+       attach->dir = DMA_NONE;
+       dbuf_attach->priv = attach;
+
+       return 0;
 }
 
-static void *vb2_dma_contig_vaddr(void *buf_priv)
+static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
+       struct dma_buf_attachment *db_attach)
 {
-       struct vb2_dc_buf *buf = buf_priv;
-       if (!buf)
-               return NULL;
+       struct vb2_dc_attachment *attach = db_attach->priv;
+       struct sg_table *sgt;
+
+       if (!attach)
+               return;
+
+       sgt = &attach->sgt;
+
+       /* release the scatterlist cache */
+       if (attach->dir != DMA_NONE)
+               dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+                       attach->dir);
+       sg_free_table(sgt);
+       kfree(attach);
+       db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_dc_dmabuf_ops_map(
+       struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
+{
+       struct vb2_dc_attachment *attach = db_attach->priv;
+       /* stealing dmabuf mutex to serialize map/unmap operations */
+       struct mutex *lock = &db_attach->dmabuf->lock;
+       struct sg_table *sgt;
+       int ret;
+
+       mutex_lock(lock);
+
+       sgt = &attach->sgt;
+       /* return previously mapped sg table */
+       if (attach->dir == dir) {
+               mutex_unlock(lock);
+               return sgt;
+       }
+
+       /* release any previous cache */
+       if (attach->dir != DMA_NONE) {
+               dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+                       attach->dir);
+               attach->dir = DMA_NONE;
+       }
+
+       /* mapping to the client with new direction */
+       ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+       if (ret <= 0) {
+               pr_err("failed to map scatterlist\n");
+               mutex_unlock(lock);
+               return ERR_PTR(-EIO);
+       }
+
+       attach->dir = dir;
+
+       mutex_unlock(lock);
+
+       return sgt;
+}
+
+static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+       struct sg_table *sgt, enum dma_data_direction dir)
+{
+       /* nothing to be done here */
+}
+
+static void vb2_dc_dmabuf_ops_release(struct dma_buf *dbuf)
+{
+       /* drop reference obtained in vb2_dc_get_dmabuf */
+       vb2_dc_put(dbuf->priv);
+}
+
+static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
+{
+       struct vb2_dc_buf *buf = dbuf->priv;
+
+       return buf->vaddr + pgnum * PAGE_SIZE;
+}
+
+static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
+{
+       struct vb2_dc_buf *buf = dbuf->priv;
 
        return buf->vaddr;
 }
 
-static unsigned int vb2_dma_contig_num_users(void *buf_priv)
+static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
+       struct vm_area_struct *vma)
 {
-       struct vb2_dc_buf *buf = buf_priv;
+       return vb2_dc_mmap(dbuf->priv, vma);
+}
 
-       return atomic_read(&buf->refcount);
+static struct dma_buf_ops vb2_dc_dmabuf_ops = {
+       .attach = vb2_dc_dmabuf_ops_attach,
+       .detach = vb2_dc_dmabuf_ops_detach,
+       .map_dma_buf = vb2_dc_dmabuf_ops_map,
+       .unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
+       .kmap = vb2_dc_dmabuf_ops_kmap,
+       .kmap_atomic = vb2_dc_dmabuf_ops_kmap,
+       .vmap = vb2_dc_dmabuf_ops_vmap,
+       .mmap = vb2_dc_dmabuf_ops_mmap,
+       .release = vb2_dc_dmabuf_ops_release,
+};
+
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+       int ret;
+       struct sg_table *sgt;
+
+       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+       if (!sgt) {
+               dev_err(buf->dev, "failed to alloc sg table\n");
+               return NULL;
+       }
+
+       ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
+               buf->size);
+       if (ret < 0) {
+               dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+               kfree(sgt);
+               return NULL;
+       }
+
+       return sgt;
 }
 
-static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
 {
        struct vb2_dc_buf *buf = buf_priv;
+       struct dma_buf *dbuf;
 
-       if (!buf) {
-               printk(KERN_ERR "No buffer to map\n");
-               return -EINVAL;
+       if (!buf->sgt_base)
+               buf->sgt_base = vb2_dc_get_base_sgt(buf);
+
+       if (WARN_ON(!buf->sgt_base))
+               return NULL;
+
+       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+       if (IS_ERR(dbuf))
+               return NULL;
+
+       /* dmabuf keeps reference to vb2 buffer */
+       atomic_inc(&buf->refcount);
+
+       return dbuf;
+}
+
+/*********************************************/
+/*       callbacks for USERPTR buffers       */
+/*********************************************/
+
+static inline int vma_is_io(struct vm_area_struct *vma)
+{
+       return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
+}
+
+static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
+       int n_pages, struct vm_area_struct *vma, int write)
+{
+       if (vma_is_io(vma)) {
+               unsigned int i;
+
+               for (i = 0; i < n_pages; ++i, start += PAGE_SIZE) {
+                       unsigned long pfn;
+                       int ret = follow_pfn(vma, start, &pfn);
+
+                       if (ret) {
+                               pr_err("no page for address %lu\n", start);
+                               return ret;
+                       }
+                       pages[i] = pfn_to_page(pfn);
+               }
+       } else {
+               int n;
+
+               n = get_user_pages(current, current->mm, start & PAGE_MASK,
+                       n_pages, write, 1, pages, NULL);
+               /* negative error means that no page was pinned */
+               n = max(n, 0);
+               if (n != n_pages) {
+                       pr_err("got only %d of %d user pages\n", n, n_pages);
+                       while (n)
+                               put_page(pages[--n]);
+                       return -EFAULT;
+               }
        }
 
-       return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
-                                 &vb2_common_vm_ops, &buf->handler);
+       return 0;
 }
 
-static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
-                                       unsigned long size, int write)
+static void vb2_dc_put_dirty_page(struct page *page)
 {
+       set_page_dirty_lock(page);
+       put_page(page);
+}
+
+static void vb2_dc_put_userptr(void *buf_priv)
+{
+       struct vb2_dc_buf *buf = buf_priv;
+       struct sg_table *sgt = buf->dma_sgt;
+
+       dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+       if (!vma_is_io(buf->vma))
+               vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
+
+       sg_free_table(sgt);
+       kfree(sgt);
+       vb2_put_vma(buf->vma);
+       kfree(buf);
+}
+
+static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+       unsigned long size, int write)
+{
+       struct vb2_dc_conf *conf = alloc_ctx;
        struct vb2_dc_buf *buf;
+       unsigned long start;
+       unsigned long end;
+       unsigned long offset;
+       struct page **pages;
+       int n_pages;
+       int ret = 0;
        struct vm_area_struct *vma;
-       dma_addr_t dma_addr = 0;
-       int ret;
+       struct sg_table *sgt;
+       unsigned long contig_size;
+       unsigned long dma_align = dma_get_cache_alignment();
+
+       /* Only cache aligned DMA transfers are reliable */
+       if (!IS_ALIGNED(vaddr | size, dma_align)) {
+               pr_debug("user data must be aligned to %lu bytes\n", dma_align);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!size) {
+               pr_debug("size is zero\n");
+               return ERR_PTR(-EINVAL);
+       }
 
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)
                return ERR_PTR(-ENOMEM);
 
-       ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
+       buf->dev = conf->dev;
+       buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+       start = vaddr & PAGE_MASK;
+       offset = vaddr & ~PAGE_MASK;
+       end = PAGE_ALIGN(vaddr + size);
+       n_pages = (end - start) >> PAGE_SHIFT;
+
+       pages = kmalloc(n_pages * sizeof(pages[0]), GFP_KERNEL);
+       if (!pages) {
+               ret = -ENOMEM;
+               pr_err("failed to allocate pages table\n");
+               goto fail_buf;
+       }
+
+       /* current->mm->mmap_sem is taken by videobuf2 core */
+       vma = find_vma(current->mm, vaddr);
+       if (!vma) {
+               pr_err("no vma for address %lu\n", vaddr);
+               ret = -EFAULT;
+               goto fail_pages;
+       }
+
+       if (vma->vm_end < vaddr + size) {
+               pr_err("vma at %lu is too small for %lu bytes\n", vaddr, size);
+               ret = -EFAULT;
+               goto fail_pages;
+       }
+
+       buf->vma = vb2_get_vma(vma);
+       if (!buf->vma) {
+               pr_err("failed to copy vma\n");
+               ret = -ENOMEM;
+               goto fail_pages;
+       }
+
+       /* extract page list from userspace mapping */
+       ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
        if (ret) {
-               printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
-                               vaddr);
-               kfree(buf);
-               return ERR_PTR(ret);
+               pr_err("failed to get user pages\n");
+               goto fail_vma;
+       }
+
+       sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+       if (!sgt) {
+               pr_err("failed to allocate sg table\n");
+               ret = -ENOMEM;
+               goto fail_get_user_pages;
+       }
+
+       ret = sg_alloc_table_from_pages(sgt, pages, n_pages,
+               offset, size, GFP_KERNEL);
+       if (ret) {
+               pr_err("failed to initialize sg table\n");
+               goto fail_sgt;
        }
 
+       /* pages are no longer needed */
+       kfree(pages);
+       pages = NULL;
+
+       sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+               buf->dma_dir);
+       if (sgt->nents <= 0) {
+               pr_err("failed to map scatterlist\n");
+               ret = -EIO;
+               goto fail_sgt_init;
+       }
+
+       contig_size = vb2_dc_get_contiguous_size(sgt);
+       if (contig_size < size) {
+               pr_err("contiguous mapping is too small %lu/%lu\n",
+                       contig_size, size);
+               ret = -EFAULT;
+               goto fail_map_sg;
+       }
+
+       buf->dma_addr = sg_dma_address(sgt->sgl);
        buf->size = size;
-       buf->dma_addr = dma_addr;
-       buf->vma = vma;
+       buf->dma_sgt = sgt;
 
        return buf;
+
+fail_map_sg:
+       dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+
+fail_sgt_init:
+       if (!vma_is_io(buf->vma))
+               vb2_dc_sgt_foreach_page(sgt, put_page);
+       sg_free_table(sgt);
+
+fail_sgt:
+       kfree(sgt);
+
+fail_get_user_pages:
+       if (pages && !vma_is_io(buf->vma))
+               while (n_pages)
+                       put_page(pages[--n_pages]);
+
+fail_vma:
+       vb2_put_vma(buf->vma);
+
+fail_pages:
+       kfree(pages); /* kfree is NULL-proof */
+
+fail_buf:
+       kfree(buf);
+
+       return ERR_PTR(ret);
 }
 
-static void vb2_dma_contig_put_userptr(void *mem_priv)
+/*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_dc_map_dmabuf(void *mem_priv)
 {
        struct vb2_dc_buf *buf = mem_priv;
+       struct sg_table *sgt;
+       unsigned long contig_size;
 
-       if (!buf)
+       if (WARN_ON(!buf->db_attach)) {
+               pr_err("trying to pin a non attached buffer\n");
+               return -EINVAL;
+       }
+
+       if (WARN_ON(buf->dma_sgt)) {
+               pr_err("dmabuf buffer is already pinned\n");
+               return 0;
+       }
+
+       /* get the associated scatterlist for this buffer */
+       sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
+       if (IS_ERR_OR_NULL(sgt)) {
+               pr_err("Error getting dmabuf scatterlist\n");
+               return -EINVAL;
+       }
+
+       /* checking if dmabuf is big enough to store contiguous chunk */
+       contig_size = vb2_dc_get_contiguous_size(sgt);
+       if (contig_size < buf->size) {
+               pr_err("contiguous chunk is too small %lu/%lu b\n",
+                       contig_size, buf->size);
+               dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+               return -EFAULT;
+       }
+
+       buf->dma_addr = sg_dma_address(sgt->sgl);
+       buf->dma_sgt = sgt;
+
+       return 0;
+}
+
+static void vb2_dc_unmap_dmabuf(void *mem_priv)
+{
+       struct vb2_dc_buf *buf = mem_priv;
+       struct sg_table *sgt = buf->dma_sgt;
+
+       if (WARN_ON(!buf->db_attach)) {
+               pr_err("trying to unpin a not attached buffer\n");
                return;
+       }
 
-       vb2_put_vma(buf->vma);
+       if (WARN_ON(!sgt)) {
+               pr_err("dmabuf buffer is already unpinned\n");
+               return;
+       }
+
+       dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+
+       buf->dma_addr = 0;
+       buf->dma_sgt = NULL;
+}
+
+static void vb2_dc_detach_dmabuf(void *mem_priv)
+{
+       struct vb2_dc_buf *buf = mem_priv;
+
+       /* if vb2 works correctly you should never detach mapped buffer */
+       if (WARN_ON(buf->dma_addr))
+               vb2_dc_unmap_dmabuf(buf);
+
+       /* detach this attachment */
+       dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
        kfree(buf);
 }
 
+static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+       unsigned long size, int write)
+{
+       struct vb2_dc_conf *conf = alloc_ctx;
+       struct vb2_dc_buf *buf;
+       struct dma_buf_attachment *dba;
+
+       if (dbuf->size < size)
+               return ERR_PTR(-EFAULT);
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       buf->dev = conf->dev;
+       /* create attachment for the dmabuf with the user device */
+       dba = dma_buf_attach(dbuf, buf->dev);
+       if (IS_ERR(dba)) {
+               pr_err("failed to attach dmabuf\n");
+               kfree(buf);
+               return dba;
+       }
+
+       buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       buf->size = size;
+       buf->db_attach = dba;
+
+       return buf;
+}
+
+/*********************************************/
+/*       DMA CONTIG exported functions       */
+/*********************************************/
+
 const struct vb2_mem_ops vb2_dma_contig_memops = {
-       .alloc          = vb2_dma_contig_alloc,
-       .put            = vb2_dma_contig_put,
-       .cookie         = vb2_dma_contig_cookie,
-       .vaddr          = vb2_dma_contig_vaddr,
-       .mmap           = vb2_dma_contig_mmap,
-       .get_userptr    = vb2_dma_contig_get_userptr,
-       .put_userptr    = vb2_dma_contig_put_userptr,
-       .num_users      = vb2_dma_contig_num_users,
+       .alloc          = vb2_dc_alloc,
+       .put            = vb2_dc_put,
+       .get_dmabuf     = vb2_dc_get_dmabuf,
+       .cookie         = vb2_dc_cookie,
+       .vaddr          = vb2_dc_vaddr,
+       .mmap           = vb2_dc_mmap,
+       .get_userptr    = vb2_dc_get_userptr,
+       .put_userptr    = vb2_dc_put_userptr,
+       .prepare        = vb2_dc_prepare,
+       .finish         = vb2_dc_finish,
+       .map_dmabuf     = vb2_dc_map_dmabuf,
+       .unmap_dmabuf   = vb2_dc_unmap_dmabuf,
+       .attach_dmabuf  = vb2_dc_attach_dmabuf,
+       .detach_dmabuf  = vb2_dc_detach_dmabuf,
+       .num_users      = vb2_dc_num_users,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
 
index 051ea3571b208968d6b55ed3f8568038898f1b84..81c1ad8b2cf1eb9582443273c427720be71b04d7 100644 (file)
@@ -136,46 +136,6 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
 }
 EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);
 
-/**
- * vb2_mmap_pfn_range() - map physical pages to userspace
- * @vma:       virtual memory region for the mapping
- * @paddr:     starting physical address of the memory to be mapped
- * @size:      size of the memory to be mapped
- * @vm_ops:    vm operations to be assigned to the created area
- * @priv:      private data to be associated with the area
- *
- * Returns 0 on success.
- */
-int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
-                               unsigned long size,
-                               const struct vm_operations_struct *vm_ops,
-                               void *priv)
-{
-       int ret;
-
-       size = min_t(unsigned long, vma->vm_end - vma->vm_start, size);
-
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       ret = remap_pfn_range(vma, vma->vm_start, paddr >> PAGE_SHIFT,
-                               size, vma->vm_page_prot);
-       if (ret) {
-               printk(KERN_ERR "Remapping memory failed, error: %d\n", ret);
-               return ret;
-       }
-
-       vma->vm_flags           |= VM_DONTEXPAND | VM_DONTDUMP;
-       vma->vm_private_data    = priv;
-       vma->vm_ops             = vm_ops;
-
-       vma->vm_ops->open(vma);
-
-       pr_debug("%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
-                       __func__, paddr, vma->vm_start, size);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(vb2_mmap_pfn_range);
-
 /**
  * vb2_common_vm_open() - increase refcount of the vma
  * @vma:       virtual memory region for the mapping
index 94efa04d8d55f3e4af400f0910cf791dbf9faf02..a47fd4f589a14bc9a466eee544a582659e25babd 100644 (file)
@@ -30,6 +30,7 @@ struct vb2_vmalloc_buf {
        unsigned int                    n_pages;
        atomic_t                        refcount;
        struct vb2_vmarea_handler       handler;
+       struct dma_buf                  *dbuf;
 };
 
 static void vb2_vmalloc_put(void *buf_priv);
@@ -207,11 +208,66 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
        return 0;
 }
 
+/*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_vmalloc_map_dmabuf(void *mem_priv)
+{
+       struct vb2_vmalloc_buf *buf = mem_priv;
+
+       buf->vaddr = dma_buf_vmap(buf->dbuf);
+
+       return buf->vaddr ? 0 : -EFAULT;
+}
+
+static void vb2_vmalloc_unmap_dmabuf(void *mem_priv)
+{
+       struct vb2_vmalloc_buf *buf = mem_priv;
+
+       dma_buf_vunmap(buf->dbuf, buf->vaddr);
+       buf->vaddr = NULL;
+}
+
+static void vb2_vmalloc_detach_dmabuf(void *mem_priv)
+{
+       struct vb2_vmalloc_buf *buf = mem_priv;
+
+       if (buf->vaddr)
+               dma_buf_vunmap(buf->dbuf, buf->vaddr);
+
+       kfree(buf);
+}
+
+static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+       unsigned long size, int write)
+{
+       struct vb2_vmalloc_buf *buf;
+
+       if (dbuf->size < size)
+               return ERR_PTR(-EFAULT);
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       buf->dbuf = dbuf;
+       buf->write = write;
+       buf->size = size;
+
+       return buf;
+}
+
+
 const struct vb2_mem_ops vb2_vmalloc_memops = {
        .alloc          = vb2_vmalloc_alloc,
        .put            = vb2_vmalloc_put,
        .get_userptr    = vb2_vmalloc_get_userptr,
        .put_userptr    = vb2_vmalloc_put_userptr,
+       .map_dmabuf     = vb2_vmalloc_map_dmabuf,
+       .unmap_dmabuf   = vb2_vmalloc_unmap_dmabuf,
+       .attach_dmabuf  = vb2_vmalloc_attach_dmabuf,
+       .detach_dmabuf  = vb2_vmalloc_detach_dmabuf,
        .vaddr          = vb2_vmalloc_vaddr,
        .mmap           = vb2_vmalloc_mmap,
        .num_users      = vb2_vmalloc_num_users,
index 5fb195af43e23696572e8debff626e5ac4a00d69..4a7d2ebdfc97e7ee7d1773f3d82672783f44dc87 100644 (file)
@@ -138,7 +138,7 @@ VI. Setting Parameters
 
    The return value is the size in bytes of the data written into
    ops->resbuf if no errors occur.  If an error occurs, -1 is returned 
-   and errno is set appropriatly:
+   and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -222,7 +222,7 @@ VIII. Downloading Software
    RETURNS
 
    This function returns 0 no errors occur. If an error occurs, -1 
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -264,7 +264,7 @@ IX. Uploading Software
    RETURNS
 
    This function returns 0 if no errors occur.  If an error occurs, -1
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -301,7 +301,7 @@ X. Removing Software
    RETURNS
 
    This function returns 0 if no errors occur.  If an error occurs, -1
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -325,7 +325,7 @@ X. Validating Configuration
    RETURNS
 
    This function returns 0 if no erro occur.  If an error occurs, -1 is
-   returned and errno is set appropriatly:
+   returned and errno is set appropriately:
 
       ETIMEDOUT   Timeout waiting for reply message
       ENXIO       Invalid IOP number
@@ -360,7 +360,7 @@ XI. Configuration Dialog
    RETURNS
 
    This function returns 0 if no error occur. If an error occurs, -1
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
index 4796bbf0ae4e5b4fdd1476ac8e6cd4e9e43ec6c5..49e86aed2bc4f13d05ffbf5a2d094b5a979372cc 100644 (file)
@@ -609,7 +609,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
        u8 operation;
 
        /*
-        * This is to deail with the case of an application
+        * This is to deal with the case of an application
         * opening a device and then the device disappears while
         * it's in use, and then the application tries to release
         * it.  ex: Unmounting a deleted RAID volume at reboot.
index 9a49c243a6ac59c78c98cd9de021429d44aa8908..5451beff183ffdf69e24d5d1ca016d11215882a2 100644 (file)
@@ -189,7 +189,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)
                return -ENXIO;
 
        /*
-        * Stop users being able to try and allocate arbitary amounts
+        * Stop users being able to try and allocate arbitrary amounts
         * of DMA space. 64K is way more than sufficient for this.
         */
        if (kcmd.oplen > 65536)
index 94bdf83b4bc8c911189c055b22cc9cc0d31defe0..b63987c6ed200ec3ed447df7be2a0cdd6895d51b 100644 (file)
@@ -211,7 +211,6 @@ config MFD_TPS6586X
        depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
        select REGMAP_I2C
-       depends on REGULATOR
        help
          If you say yes here you get support for the TPS6586X series of
          Power Management chips.
index 3e27c031aeaa26fad637fadb86641851470595e0..59da1650fb814ea5c688f2c83051734d6bc2e8a7 100644 (file)
@@ -1036,23 +1036,43 @@ static struct mfd_cell abx500_common_devs[] = {
 static struct mfd_cell ab8500_bm_devs[] = {
        {
                .name = "ab8500-charger",
+               .of_compatible = "stericsson,ab8500-charger",
                .num_resources = ARRAY_SIZE(ab8500_charger_resources),
                .resources = ab8500_charger_resources,
+#ifndef CONFIG_OF
+               .platform_data = &ab8500_bm_data,
+               .pdata_size = sizeof(ab8500_bm_data),
+#endif
        },
        {
                .name = "ab8500-btemp",
+               .of_compatible = "stericsson,ab8500-btemp",
                .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
                .resources = ab8500_btemp_resources,
+#ifndef CONFIG_OF
+               .platform_data = &ab8500_bm_data,
+               .pdata_size = sizeof(ab8500_bm_data),
+#endif
        },
        {
                .name = "ab8500-fg",
+               .of_compatible = "stericsson,ab8500-fg",
                .num_resources = ARRAY_SIZE(ab8500_fg_resources),
                .resources = ab8500_fg_resources,
+#ifndef CONFIG_OF
+               .platform_data = &ab8500_bm_data,
+               .pdata_size = sizeof(ab8500_bm_data),
+#endif
        },
        {
                .name = "ab8500-chargalg",
+               .of_compatible = "stericsson,ab8500-chargalg",
                .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
                .resources = ab8500_chargalg_resources,
+#ifndef CONFIG_OF
+               .platform_data = &ab8500_bm_data,
+               .pdata_size = sizeof(ab8500_bm_data),
+#endif
        },
 };
 
index 1a6f943f733728c1cb7ac5ed2a4d190be9c98855..c784f4602a746c8d4eec1d8c4383ed4cae0a8df6 100644 (file)
@@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = {
 static struct mfd_cell wm5102_devs[] = {
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
        { .name = "arizona-micsupp" },
        { .name = "arizona-pwm" },
        { .name = "wm5102-codec" },
@@ -280,6 +281,7 @@ static struct mfd_cell wm5102_devs[] = {
 static struct mfd_cell wm5110_devs[] = {
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
        { .name = "arizona-micsupp" },
        { .name = "arizona-pwm" },
        { .name = "wm5110-codec" },
index f123517065ec911ff6e4154aa25a3f8e1dd0bd98..abd5c80c7cf5f59c9a3adf78d188482148ecf512 100644 (file)
  * This driver is based on max8998.c
  */
 
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/of_irq.h>
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
@@ -47,6 +49,13 @@ static struct mfd_cell max8997_devs[] = {
        { .name = "max8997-led", .id = 2 },
 };
 
+#ifdef CONFIG_OF
+static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
+       { .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
+       {},
+};
+#endif
+
 int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
 {
        struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
@@ -123,6 +132,58 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
 }
 EXPORT_SYMBOL_GPL(max8997_update_reg);
 
+#ifdef CONFIG_OF
+/*
+ * Only the common platform data elements for max8997 are parsed here from the
+ * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
+ * to parse their own platform data elements from device tree.
+ *
+ * The max8997 platform data structure is instantiated here and the drivers for
+ * the sub-modules need not instantiate another instance while parsing their
+ * platform data.
+ */
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+                                       struct device *dev)
+{
+       struct max8997_platform_data *pd;
+
+       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd) {
+               dev_err(dev, "could not allocate memory for pdata\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       pd->ono = irq_of_parse_and_map(dev->of_node, 1);
+
+       /*
+        * ToDo: the 'wakeup' member in the platform data is more of a linux
+        * specfic information. Hence, there is no binding for that yet and
+        * not parsed here.
+        */
+
+       return pd;
+}
+#else
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+                                       struct device *dev)
+{
+       return 0;
+}
+#endif
+
+static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+                                               const struct i2c_device_id *id)
+{
+#ifdef CONFIG_OF
+       if (i2c->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
+               return (int)match->data;
+       }
+#endif
+       return (int)id->driver_data;
+}
+
 static int max8997_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -137,12 +198,21 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
        i2c_set_clientdata(i2c, max8997);
        max8997->dev = &i2c->dev;
        max8997->i2c = i2c;
-       max8997->type = id->driver_data;
+       max8997->type = max8997_i2c_get_driver_data(i2c, id);
        max8997->irq = i2c->irq;
 
+       if (max8997->dev->of_node) {
+               pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
+               if (IS_ERR(pdata)) {
+                       ret = PTR_ERR(pdata);
+                       goto err;
+               }
+       }
+
        if (!pdata)
                goto err;
 
+       max8997->pdata = pdata;
        max8997->ono = pdata->ono;
 
        mutex_init(&max8997->iolock);
@@ -434,6 +504,7 @@ static struct i2c_driver max8997_i2c_driver = {
                   .name = "max8997",
                   .owner = THIS_MODULE,
                   .pm = &max8997_pm,
+                  .of_match_table = of_match_ptr(max8997_pmic_dt_match),
        },
        .probe = max8997_i2c_probe,
        .remove = max8997_i2c_remove,
index 9f92c3b2209318c8476ff1de350b9939ff1a0015..87ba7ada3bbc8a72392745cdc3400fb541e8056c 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/regulator/machine.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
@@ -98,6 +96,9 @@ static struct mfd_cell tps6586x_cell[] = {
        {
                .name = "tps6586x-gpio",
        },
+       {
+               .name = "tps6586x-pmic",
+       },
        {
                .name = "tps6586x-rtc",
        },
@@ -350,80 +351,19 @@ failed:
 }
 
 #ifdef CONFIG_OF
-static struct of_regulator_match tps6586x_matches[] = {
-       { .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
-       { .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
-       { .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
-       { .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
-       { .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
-       { .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
-       { .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
-       { .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
-       { .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
-       { .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
-       { .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
-       { .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
-       { .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
-       { .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
-       { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
-};
-
 static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
 {
-       const unsigned int num = ARRAY_SIZE(tps6586x_matches);
        struct device_node *np = client->dev.of_node;
        struct tps6586x_platform_data *pdata;
-       struct tps6586x_subdev_info *devs;
-       struct device_node *regs;
-       const char *sys_rail_name = NULL;
-       unsigned int count;
-       unsigned int i, j;
-       int err;
-
-       regs = of_find_node_by_name(np, "regulators");
-       if (!regs)
-               return NULL;
-
-       err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
-       if (err < 0) {
-               of_node_put(regs);
-               return NULL;
-       }
-
-       of_node_put(regs);
-       count = err;
-
-       devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
-       if (!devs)
-               return NULL;
-
-       for (i = 0, j = 0; i < num && j < count; i++) {
-               struct regulator_init_data *reg_idata;
-
-               if (!tps6586x_matches[i].init_data)
-                       continue;
-
-               reg_idata  = tps6586x_matches[i].init_data;
-               devs[j].name = "tps6586x-regulator";
-               devs[j].platform_data = tps6586x_matches[i].init_data;
-               devs[j].id = (int)tps6586x_matches[i].driver_data;
-               if (devs[j].id == TPS6586X_ID_SYS)
-                       sys_rail_name = reg_idata->constraints.name;
-
-               if ((devs[j].id == TPS6586X_ID_LDO_5) ||
-                       (devs[j].id == TPS6586X_ID_LDO_RTC))
-                       reg_idata->supply_regulator = sys_rail_name;
-
-               devs[j].of_node = tps6586x_matches[i].of_node;
-               j++;
-       }
 
        pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
+       if (!pdata) {
+               dev_err(&client->dev, "Memory allocation failed\n");
                return NULL;
+       }
 
-       pdata->num_subdevs = count;
-       pdata->subdevs = devs;
+       pdata->num_subdevs = 0;
+       pdata->subdevs = NULL;
        pdata->gpio_base = -1;
        pdata->irq_base = -1;
        pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
index 14490cc785d29879f37a06ee52ffed57b8c32c9e..3141c4a173a7c8e9285931be1f330f420f0ce69e 100644 (file)
@@ -258,6 +258,7 @@ static const struct reg_default wm5102_reg_default[] = {
        { 0x00000154, 0x0000 },   /* R340   - Rate Estimator 3 */ 
        { 0x00000155, 0x0000 },   /* R341   - Rate Estimator 4 */ 
        { 0x00000156, 0x0000 },   /* R342   - Rate Estimator 5 */ 
+       { 0x00000161, 0x0000 },   /* R353   - Dynamic Frequency Scaling 1 */ 
        { 0x00000171, 0x0000 },   /* R369   - FLL1 Control 1 */ 
        { 0x00000172, 0x0008 },   /* R370   - FLL1 Control 2 */ 
        { 0x00000173, 0x0018 },   /* R371   - FLL1 Control 3 */ 
@@ -1047,6 +1048,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_RATE_ESTIMATOR_3:
        case ARIZONA_RATE_ESTIMATOR_4:
        case ARIZONA_RATE_ESTIMATOR_5:
+       case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
        case ARIZONA_FLL1_CONTROL_1:
        case ARIZONA_FLL1_CONTROL_2:
        case ARIZONA_FLL1_CONTROL_3:
@@ -1079,6 +1081,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_FLL2_GPIO_CLOCK:
        case ARIZONA_MIC_CHARGE_PUMP_1:
        case ARIZONA_LDO1_CONTROL_1:
+       case ARIZONA_LDO1_CONTROL_2:
        case ARIZONA_LDO2_CONTROL_1:
        case ARIZONA_MIC_BIAS_CTRL_1:
        case ARIZONA_MIC_BIAS_CTRL_2:
index c7f62ac544ad74e2282b29b62c1c9f25e16cc868..bcb226ff9d2b7415bc567d2e855bf18ebfcc487f 100644 (file)
@@ -401,13 +401,19 @@ static const struct reg_default wm1811_reva_patch[] = {
  */
 static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 {
-       struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+       struct wm8994_pdata *pdata;
        struct regmap_config *regmap_config;
        const struct reg_default *regmap_patch = NULL;
        const char *devname;
        int ret, i, patch_regs;
        int pulls = 0;
 
+       if (dev_get_platdata(wm8994->dev)) {
+               pdata = dev_get_platdata(wm8994->dev);
+               wm8994->pdata = *pdata;
+       }
+       pdata = &wm8994->pdata;
+
        dev_set_drvdata(wm8994->dev, wm8994);
 
        /* Add the on-chip regulators first for bootstrapping */
@@ -604,24 +610,21 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                }
        }
 
-       if (pdata) {
-               wm8994->irq_base = pdata->irq_base;
-               wm8994->gpio_base = pdata->gpio_base;
-
-               /* GPIO configuration is only applied if it's non-zero */
-               for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
-                       if (pdata->gpio_defaults[i]) {
-                               wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
-                                               0xffff,
-                                               pdata->gpio_defaults[i]);
-                       }
+       wm8994->irq_base = pdata->irq_base;
+       wm8994->gpio_base = pdata->gpio_base;
+
+       /* GPIO configuration is only applied if it's non-zero */
+       for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+               if (pdata->gpio_defaults[i]) {
+                       wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
+                                       0xffff, pdata->gpio_defaults[i]);
                }
+       }
 
-               wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
+       wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
 
-               if (pdata->spkmode_pu)
-                       pulls |= WM8994_SPKMODE_PU;
-       }
+       if (pdata->spkmode_pu)
+               pulls |= WM8994_SPKMODE_PU;
 
        /* Disable unneeded pulls */
        wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
index c58f9abcb35659f58ee9fbdbaad5c387d366ad06..158da5a81a661824a2dca0ee2a9fe93fb5cacfb6 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <linux/of.h>
+
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
 static LIST_HEAD(ssc_list);
@@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
 
        spin_lock(&user_lock);
        list_for_each_entry(ssc, &ssc_list, list) {
-               if (ssc->pdev->id == ssc_num) {
+               if (ssc->pdev->dev.of_node) {
+                       if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
+                               == ssc_num) {
+                               ssc_valid = 1;
+                               break;
+                       }
+               } else if (ssc->pdev->id == ssc_num) {
                        ssc_valid = 1;
                        break;
                }
@@ -68,39 +76,93 @@ void ssc_free(struct ssc_device *ssc)
 }
 EXPORT_SYMBOL(ssc_free);
 
-static int __init ssc_probe(struct platform_device *pdev)
+static struct atmel_ssc_platform_data at91rm9200_config = {
+       .use_dma = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9g45_config = {
+       .use_dma = 1,
+};
+
+static const struct platform_device_id atmel_ssc_devtypes[] = {
+       {
+               .name = "at91rm9200_ssc",
+               .driver_data = (unsigned long) &at91rm9200_config,
+       }, {
+               .name = "at91sam9g45_ssc",
+               .driver_data = (unsigned long) &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ssc_dt_ids[] = {
+       {
+               .compatible = "atmel,at91rm9200-ssc",
+               .data = &at91rm9200_config,
+       }, {
+               .compatible = "atmel,at91sam9g45-ssc",
+               .data = &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
+#endif
+
+static inline const struct atmel_ssc_platform_data * __init
+       atmel_ssc_get_driver_data(struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
+               if (match == NULL)
+                       return NULL;
+               return match->data;
+       }
+
+       return (struct atmel_ssc_platform_data *)
+               platform_get_device_id(pdev)->driver_data;
+}
+
+static int ssc_probe(struct platform_device *pdev)
 {
-       int retval = 0;
        struct resource *regs;
        struct ssc_device *ssc;
+       const struct atmel_ssc_platform_data *plat_dat;
 
-       ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+       ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
        if (!ssc) {
                dev_dbg(&pdev->dev, "out of memory\n");
-               retval = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
+       ssc->pdev = pdev;
+
+       plat_dat = atmel_ssc_get_driver_data(pdev);
+       if (!plat_dat)
+               return -ENODEV;
+       ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
+
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
                dev_dbg(&pdev->dev, "no mmio resource defined\n");
-               retval = -ENXIO;
-               goto out_free;
+               return -ENXIO;
        }
 
-       ssc->clk = clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(ssc->clk)) {
-               dev_dbg(&pdev->dev, "no pclk clock defined\n");
-               retval = -ENXIO;
-               goto out_free;
-       }
-
-       ssc->pdev = pdev;
-       ssc->regs = ioremap(regs->start, resource_size(regs));
+       ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
        if (!ssc->regs) {
                dev_dbg(&pdev->dev, "ioremap failed\n");
-               retval = -EINVAL;
-               goto out_clk;
+               return -EINVAL;
+       }
+
+       ssc->phybase = regs->start;
+
+       ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(ssc->clk)) {
+               dev_dbg(&pdev->dev, "no pclk clock defined\n");
+               return -ENXIO;
        }
 
        /* disable all interrupts */
@@ -112,8 +174,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        ssc->irq = platform_get_irq(pdev, 0);
        if (!ssc->irq) {
                dev_dbg(&pdev->dev, "could not get irq\n");
-               retval = -ENXIO;
-               goto out_unmap;
+               return -ENXIO;
        }
 
        spin_lock(&user_lock);
@@ -125,16 +186,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
                        ssc->regs, ssc->irq);
 
-       goto out;
-
-out_unmap:
-       iounmap(ssc->regs);
-out_clk:
-       clk_put(ssc->clk);
-out_free:
-       kfree(ssc);
-out:
-       return retval;
+       return 0;
 }
 
 static int ssc_remove(struct platform_device *pdev)
@@ -142,34 +194,23 @@ static int ssc_remove(struct platform_device *pdev)
        struct ssc_device *ssc = platform_get_drvdata(pdev);
 
        spin_lock(&user_lock);
-       iounmap(ssc->regs);
-       clk_put(ssc->clk);
        list_del(&ssc->list);
-       kfree(ssc);
        spin_unlock(&user_lock);
 
        return 0;
 }
 
 static struct platform_driver ssc_driver = {
-       .remove         = ssc_remove,
        .driver         = {
                .name           = "ssc",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(atmel_ssc_dt_ids),
        },
+       .id_table       = atmel_ssc_devtypes,
+       .probe          = ssc_probe,
+       .remove         = ssc_remove,
 };
-
-static int __init ssc_init(void)
-{
-       return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
-       platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
index 737e4edc241bcf3d17db3f2cb21866b76504f072..8d13c6594520094c82f054628b1086bfe5cc7bec 100644 (file)
@@ -533,7 +533,7 @@ config MMC_DW_PLTFM
          If unsure, say Y.
 
 config MMC_DW_EXYNOS
-       tristate "Exynos specific extentions for Synopsys DW Memory Card Interface"
+       tristate "Exynos specific extensions for Synopsys DW Memory Card Interface"
        depends on MMC_DW
        select MMC_DW_PLTFM
        help
index 891558de3ec19d1ef67ca69751be8f06e21e480f..2de66b062f0d733be6e97751312d9f576c198236 100644 (file)
@@ -219,7 +219,7 @@ static int platram_probe(struct platform_device *pdev)
 
        platram_setrw(info, PLATRAM_RW);
 
-       /* check to see if there are any available partitions, or wether
+       /* check to see if there are any available partitions, or whether
         * to add this device whole */
 
        err = mtd_device_parse_register(info->mtd, pdata->probes, NULL,
index 295e4bedad960a0efe653dc893fe0f1e0270f2f1..79ded48e7427f7b868a9b419385db2263f279474 100644 (file)
@@ -879,7 +879,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
        if (chip->ecc.mode != NAND_ECC_HW)
                return;
 
-               /* change the behaviour depending on wether we are using
+               /* change the behaviour depending on whether we are using
                 * the large or small page nand device */
 
        if (chip->page_shift > 10) {
index 6dded569b111d07fee6bb49088847f633f628852..21b68e5c14fd24c49d606289220f51a2a9902e65 100644 (file)
@@ -245,7 +245,7 @@ struct bonding {
        struct   delayed_work ad_work;
        struct   delayed_work mcast_work;
 #ifdef CONFIG_DEBUG_FS
-       /* debugging suport via debugfs */
+       /* debugging support via debugfs */
        struct   dentry *debug_dir;
 #endif /* CONFIG_DEBUG_FS */
 };
index 0338352bc0369cc4d7f1836ec2395b6bf2383e28..70dba5d01ad3cc8178318f9976a5922894a86859 100644 (file)
@@ -109,7 +109,7 @@ static inline struct ax_device *to_ax_dev(struct net_device *dev)
 /*
  * ax_initial_check
  *
- * do an initial probe for the card to check wether it exists
+ * do an initial probe for the card to check whether it exists
  * and is functional
  */
 static int ax_initial_check(struct net_device *dev)
index b8b4b749daab7d8f5a954c679422035182c0df30..09b625e0fdaa999260daaca271adac8b67112108 100644 (file)
@@ -4318,7 +4318,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
 
        if (o->next_tx_only >= o->max_cos)
                /* >= becuase tx only must always be smaller than cos since the
-                * primary connection suports COS 0
+                * primary connection supports COS 0
                 */
                BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
                           o->next_tx_only, o->max_cos);
index aef45d3113bac5e9200d4dae8efc9a754a38d18e..3dee68612c9e87868e3b5b61b475693273480319 100644 (file)
@@ -3307,7 +3307,7 @@ static void config_pcie(struct adapter *adap)
            G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
        log2_width = fls(adap->params.pci.width) - 1;
        acklat = ack_lat[log2_width][pldsize];
-       if (val & 1)            /* check LOsEnable */
+       if (val & PCI_EXP_LNKCTL_ASPM_L0S)      /* check LOsEnable */
                acklat += fst_trn_tx * 4;
        rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
 
index 130dd9d5b493d6600a0e68194a1a4919a414151b..a27b4ae20f43486f57fef3cf3f9d08e93bcf0c6e 100644 (file)
@@ -3203,7 +3203,7 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
        memset(c, 0, sizeof(*c));
        c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                               FW_CMD_REQUEST | FW_CMD_READ);
-       c->retval_len16 = htonl(FW_LEN16(*c));
+       c->cfvalid_to_len16 = htonl(FW_LEN16(*c));
        ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c);
        if (ret < 0)
                return ret;
@@ -3397,7 +3397,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                      FW_CMD_REQUEST |
                      FW_CMD_READ);
-       caps_cmd.retval_len16 =
+       caps_cmd.cfvalid_to_len16 =
                htonl(FW_CAPS_CONFIG_CMD_CFVALID |
                      FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
                      FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
@@ -3422,7 +3422,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                      FW_CMD_REQUEST |
                      FW_CMD_WRITE);
-       caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+       caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         NULL);
        if (ret < 0)
@@ -3497,7 +3497,7 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
        memset(&caps_cmd, 0, sizeof(caps_cmd));
        caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                                     FW_CMD_REQUEST | FW_CMD_READ);
-       caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+       caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
        if (ret < 0)
@@ -3929,7 +3929,7 @@ static int adap_init0(struct adapter *adap)
        memset(&caps_cmd, 0, sizeof(caps_cmd));
        caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                                     FW_CMD_REQUEST | FW_CMD_READ);
-       caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+       caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
        if (ret < 0)
index 3ecc087d732d12ea3e61214235f1a99254f87924..fe9a2ea3588ba64384c154e18fc75e4372229a50 100644 (file)
@@ -508,7 +508,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
 {
        if (q->pend_cred >= 8) {
                wmb();
-               t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO |
+               t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
                             QID(q->cntxt_id) | PIDX(q->pend_cred / 8));
                q->pend_cred &= 7;
        }
@@ -2082,10 +2082,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
                        goto fl_nomem;
 
                flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc);
-               c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN |
+               c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN(1) |
                                            FW_IQ_CMD_FL0FETCHRO(1) |
                                            FW_IQ_CMD_FL0DATARO(1) |
-                                           FW_IQ_CMD_FL0PADEN);
+                                           FW_IQ_CMD_FL0PADEN(1));
                c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) |
                                FW_IQ_CMD_FL0FBMAX(3));
                c.fl0size = htons(flsz);
index 45f2bea2e929b098ce2fa90be9987406c66c8d05..8d9c7547b07004778388171ef3b58bcd46b81d35 100644 (file)
@@ -648,12 +648,12 @@ static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
 
        if (!byte_cnt || byte_cnt > 4)
                return -EINVAL;
-       if (t4_read_reg(adapter, SF_OP) & BUSY)
+       if (t4_read_reg(adapter, SF_OP) & SF_BUSY)
                return -EBUSY;
        cont = cont ? SF_CONT : 0;
        lock = lock ? SF_LOCK : 0;
        t4_write_reg(adapter, SF_OP, lock | cont | BYTECNT(byte_cnt - 1));
-       ret = t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
+       ret = t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5);
        if (!ret)
                *valp = t4_read_reg(adapter, SF_DATA);
        return ret;
@@ -676,14 +676,14 @@ static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
 {
        if (!byte_cnt || byte_cnt > 4)
                return -EINVAL;
-       if (t4_read_reg(adapter, SF_OP) & BUSY)
+       if (t4_read_reg(adapter, SF_OP) & SF_BUSY)
                return -EBUSY;
        cont = cont ? SF_CONT : 0;
        lock = lock ? SF_LOCK : 0;
        t4_write_reg(adapter, SF_DATA, val);
        t4_write_reg(adapter, SF_OP, lock |
                     cont | BYTECNT(byte_cnt - 1) | OP_WR);
-       return t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
+       return t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5);
 }
 
 /**
@@ -2252,14 +2252,14 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
                t4_write_reg(adap, EPIO_REG(DATA0), mask0);
                t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i) | EPIOWR);
                t4_read_reg(adap, EPIO_REG(OP));                /* flush */
-               if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
+               if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY)
                        return -ETIMEDOUT;
 
                /* write CRC */
                t4_write_reg(adap, EPIO_REG(DATA0), crc);
                t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i + 32) | EPIOWR);
                t4_read_reg(adap, EPIO_REG(OP));                /* flush */
-               if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
+               if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY)
                        return -ETIMEDOUT;
        }
 #undef EPIO_REG
@@ -2405,7 +2405,7 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
 retry:
        memset(&c, 0, sizeof(c));
        INIT_CMD(c, HELLO, WRITE);
-       c.err_to_mbasyncnot = htonl(
+       c.err_to_clearinit = htonl(
                FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
                FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
                FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox :
@@ -2426,7 +2426,7 @@ retry:
                return ret;
        }
 
-       v = ntohl(c.err_to_mbasyncnot);
+       v = ntohl(c.err_to_clearinit);
        master_mbox = FW_HELLO_CMD_MBMASTER_GET(v);
        if (state) {
                if (v & FW_HELLO_CMD_ERR)
@@ -2774,7 +2774,7 @@ int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
                htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                      FW_CMD_REQUEST |
                      FW_CMD_READ);
-       caps_cmd.retval_len16 =
+       caps_cmd.cfvalid_to_len16 =
                htonl(FW_CAPS_CONFIG_CMD_CFVALID |
                      FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
                      FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
@@ -2797,7 +2797,7 @@ int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
                htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                      FW_CMD_REQUEST |
                      FW_CMD_WRITE);
-       caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+       caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        return t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), NULL);
 }
 
index eb71b8250b917ddd61740daf45f7b456f52aadae..b760808fd6d9831e1c56edf09fd5038dbf7f9f23 100644 (file)
@@ -658,6 +658,7 @@ struct ulptx_sgl {
        __be32 cmd_nsge;
 #define ULPTX_CMD(x) ((x) << 24)
 #define ULPTX_NSGE(x) ((x) << 0)
+#define ULPTX_MORE (1U << 23)
        __be32 len0;
        __be64 addr0;
        struct ulptx_sge_pair sge[0];
index a1a8b57200f607971f8f450495a8b7abe9478d5c..75393f5cff41877d18b3e04ed6294ae351107e94 100644 (file)
@@ -67,7 +67,7 @@
 #define  QID_MASK    0xffff8000U
 #define  QID_SHIFT   15
 #define  QID(x)      ((x) << QID_SHIFT)
-#define  DBPRIO      0x00004000U
+#define  DBPRIO(x)   ((x) << 14)
 #define  PIDX_MASK   0x00003fffU
 #define  PIDX_SHIFT  0
 #define  PIDX(x)     ((x) << PIDX_SHIFT)
 #define SGE_FL_BUFFER_SIZE1 0x1048
 #define SGE_FL_BUFFER_SIZE2 0x104c
 #define SGE_FL_BUFFER_SIZE3 0x1050
+#define SGE_FL_BUFFER_SIZE4 0x1054
+#define SGE_FL_BUFFER_SIZE5 0x1058
+#define SGE_FL_BUFFER_SIZE6 0x105c
+#define SGE_FL_BUFFER_SIZE7 0x1060
+#define SGE_FL_BUFFER_SIZE8 0x1064
+
 #define SGE_INGRESS_RX_THRESHOLD 0x10a0
 #define  THRESHOLD_0_MASK   0x3f000000U
 #define  THRESHOLD_0_SHIFT  24
 #define  EGRTHRESHOLD(x)     ((x) << EGRTHRESHOLDshift)
 #define  EGRTHRESHOLD_GET(x) (((x) & EGRTHRESHOLD_MASK) >> EGRTHRESHOLDshift)
 
+#define SGE_DBFIFO_STATUS 0x10a4
+#define  HP_INT_THRESH_SHIFT 28
+#define  HP_INT_THRESH_MASK  0xfU
+#define  HP_INT_THRESH(x)    ((x) << HP_INT_THRESH_SHIFT)
+#define  LP_INT_THRESH_SHIFT 12
+#define  LP_INT_THRESH_MASK  0xfU
+#define  LP_INT_THRESH(x)    ((x) << LP_INT_THRESH_SHIFT)
+
+#define SGE_DOORBELL_CONTROL 0x10a8
+#define  ENABLE_DROP        (1 << 13)
+
 #define SGE_TIMER_VALUE_0_AND_1 0x10b8
 #define  TIMERVALUE0_MASK   0xffff0000U
 #define  TIMERVALUE0_SHIFT  16
 #define A_SGE_CTXT_CMD 0x11fc
 #define A_SGE_DBQ_CTXT_BADDR 0x1084
 
+#define PCIE_PF_CFG 0x40
+#define  AIVEC(x)      ((x) << 4)
+#define  AIVEC_MASK    0x3ffU
+
 #define PCIE_PF_CLI 0x44
 #define PCIE_INT_CAUSE 0x3004
 #define  UNXSPLCPLERR  0x20000000U
 #define PCIE_MEM_ACCESS_OFFSET 0x306c
 
 #define PCIE_FW 0x30b8
+#define  PCIE_FW_ERR           0x80000000U
+#define  PCIE_FW_INIT          0x40000000U
+#define  PCIE_FW_HALT          0x20000000U
+#define  PCIE_FW_MASTER_VLD    0x00008000U
+#define  PCIE_FW_MASTER(x)     ((x) << 12)
+#define  PCIE_FW_MASTER_MASK   0x7
+#define  PCIE_FW_MASTER_GET(x) (((x) >> 12) & PCIE_FW_MASTER_MASK)
 
 #define PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS 0x5908
 #define  RNPP 0x80000000U
 #define  MBOWNER(x)     ((x) << MBOWNER_SHIFT)
 #define  MBOWNER_GET(x) (((x) & MBOWNER_MASK) >> MBOWNER_SHIFT)
 
+#define CIM_PF_HOST_INT_ENABLE 0x288
+#define  MBMSGRDYINTEN(x) ((x) << 19)
+
 #define CIM_PF_HOST_INT_CAUSE 0x28c
 #define  MBMSGRDYINT 0x00080000U
 
 
 #define SF_DATA 0x193f8
 #define SF_OP 0x193fc
-#define  BUSY          0x80000000U
+#define  SF_BUSY       0x80000000U
 #define  SF_LOCK       0x00000010U
 #define  SF_CONT       0x00000008U
 #define  BYTECNT_MASK  0x00000006U
 #define  I2CM       0x00000002U
 #define  CIM        0x00000001U
 
+#define PL_INT_ENABLE 0x19410
 #define PL_INT_MAP0 0x19414
 #define PL_RST 0x19428
 #define  PIORST     0x00000002U
index a6364632b490a7d1a7e57bbb086c74afcbe3181a..0abc864cdd3ae89a40fed822029a38e1e9b7f953 100644 (file)
@@ -68,6 +68,7 @@ struct fw_wr_hdr {
 };
 
 #define FW_WR_OP(x)     ((x) << 24)
+#define FW_WR_OP_GET(x)         (((x) >> 24) & 0xff)
 #define FW_WR_ATOMIC(x)         ((x) << 23)
 #define FW_WR_FLUSH(x)   ((x) << 22)
 #define FW_WR_COMPL(x)   ((x) << 21)
@@ -222,6 +223,7 @@ struct fw_cmd_hdr {
 #define FW_CMD_OP(x)           ((x) << 24)
 #define FW_CMD_OP_GET(x)        (((x) >> 24) & 0xff)
 #define FW_CMD_REQUEST          (1U << 23)
+#define FW_CMD_REQUEST_GET(x)   (((x) >> 23) & 0x1)
 #define FW_CMD_READ            (1U << 22)
 #define FW_CMD_WRITE           (1U << 21)
 #define FW_CMD_EXEC            (1U << 20)
@@ -229,6 +231,7 @@ struct fw_cmd_hdr {
 #define FW_CMD_RETVAL(x)       ((x) << 8)
 #define FW_CMD_RETVAL_GET(x)   (((x) >> 8) & 0xff)
 #define FW_CMD_LEN16(x)         ((x) << 0)
+#define FW_LEN16(fw_struct)    FW_CMD_LEN16(sizeof(fw_struct) / 16)
 
 enum fw_ldst_addrspc {
        FW_LDST_ADDRSPC_FIRMWARE  = 0x0001,
@@ -241,7 +244,8 @@ enum fw_ldst_addrspc {
        FW_LDST_ADDRSPC_TP_MIB    = 0x0012,
        FW_LDST_ADDRSPC_MDIO      = 0x0018,
        FW_LDST_ADDRSPC_MPS       = 0x0020,
-       FW_LDST_ADDRSPC_FUNC      = 0x0028
+       FW_LDST_ADDRSPC_FUNC      = 0x0028,
+       FW_LDST_ADDRSPC_FUNC_PCIE = 0x0029,
 };
 
 enum fw_ldst_mps_fid {
@@ -303,6 +307,16 @@ struct fw_ldst_cmd {
                        __be64 data0;
                        __be64 data1;
                } func;
+               struct fw_ldst_pcie {
+                       u8 ctrl_to_fn;
+                       u8 bnum;
+                       u8 r;
+                       u8 ext_r;
+                       u8 select_naccess;
+                       u8 pcie_fn;
+                       __be16 nset_pkd;
+                       __be32 data[12];
+               } pcie;
        } u;
 };
 
@@ -312,6 +326,9 @@ struct fw_ldst_cmd {
 #define FW_LDST_CMD_FID(x)     ((x) << 15)
 #define FW_LDST_CMD_CTL(x)     ((x) << 0)
 #define FW_LDST_CMD_RPLCPF(x)  ((x) << 0)
+#define FW_LDST_CMD_LC         (1U << 4)
+#define FW_LDST_CMD_NACCESS(x) ((x) << 0)
+#define FW_LDST_CMD_FN(x)      ((x) << 0)
 
 struct fw_reset_cmd {
        __be32 op_to_write;
@@ -333,7 +350,7 @@ enum fw_hellow_cmd {
 struct fw_hello_cmd {
        __be32 op_to_write;
        __be32 retval_len16;
-       __be32 err_to_mbasyncnot;
+       __be32 err_to_clearinit;
 #define FW_HELLO_CMD_ERR           (1U << 31)
 #define FW_HELLO_CMD_INIT          (1U << 30)
 #define FW_HELLO_CMD_MASTERDIS(x)   ((x) << 29)
@@ -343,6 +360,7 @@ struct fw_hello_cmd {
 #define FW_HELLO_CMD_MBMASTER(x)     ((x) << FW_HELLO_CMD_MBMASTER_SHIFT)
 #define FW_HELLO_CMD_MBMASTER_GET(x) \
        (((x) >> FW_HELLO_CMD_MBMASTER_SHIFT) & FW_HELLO_CMD_MBMASTER_MASK)
+#define FW_HELLO_CMD_MBASYNCNOTINT(x)  ((x) << 23)
 #define FW_HELLO_CMD_MBASYNCNOT(x)  ((x) << 20)
 #define FW_HELLO_CMD_STAGE(x)       ((x) << 17)
 #define FW_HELLO_CMD_CLEARINIT      (1U << 16)
@@ -428,6 +446,7 @@ enum fw_caps_config_iscsi {
 enum fw_caps_config_fcoe {
        FW_CAPS_CONFIG_FCOE_INITIATOR   = 0x00000001,
        FW_CAPS_CONFIG_FCOE_TARGET      = 0x00000002,
+       FW_CAPS_CONFIG_FCOE_CTRL_OFLD   = 0x00000004,
 };
 
 enum fw_memtype_cf {
@@ -440,7 +459,7 @@ enum fw_memtype_cf {
 
 struct fw_caps_config_cmd {
        __be32 op_to_write;
-       __be32 retval_len16;
+       __be32 cfvalid_to_len16;
        __be32 r2;
        __be32 hwmbitmap;
        __be16 nbmcaps;
@@ -701,8 +720,8 @@ struct fw_iq_cmd {
 #define FW_IQ_CMD_FL0FETCHRO(x) ((x) << 6)
 #define FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << 4)
 #define FW_IQ_CMD_FL0CPRIO(x) ((x) << 3)
-#define FW_IQ_CMD_FL0PADEN (1U << 2)
-#define FW_IQ_CMD_FL0PACKEN (1U << 1)
+#define FW_IQ_CMD_FL0PADEN(x) ((x) << 2)
+#define FW_IQ_CMD_FL0PACKEN(x) ((x) << 1)
 #define FW_IQ_CMD_FL0CONGEN (1U << 0)
 
 #define FW_IQ_CMD_FL0DCAEN(x) ((x) << 15)
@@ -1190,6 +1209,14 @@ enum fw_port_dcb_cfg_rc {
        FW_PORT_DCB_CFG_ERROR   = 0x1
 };
 
+enum fw_port_dcb_type {
+       FW_PORT_DCB_TYPE_PGID           = 0x00,
+       FW_PORT_DCB_TYPE_PGRATE         = 0x01,
+       FW_PORT_DCB_TYPE_PRIORATE       = 0x02,
+       FW_PORT_DCB_TYPE_PFC            = 0x03,
+       FW_PORT_DCB_TYPE_APP_ID         = 0x04,
+};
+
 struct fw_port_cmd {
        __be32 op_to_portid;
        __be32 action_to_len16;
@@ -1257,6 +1284,7 @@ struct fw_port_cmd {
 #define FW_PORT_CMD_TXIPG(x) ((x) << 19)
 
 #define FW_PORT_CMD_LSTATUS (1U << 31)
+#define FW_PORT_CMD_LSTATUS_GET(x) (((x) >> 31) & 0x1)
 #define FW_PORT_CMD_LSPEED(x) ((x) << 24)
 #define FW_PORT_CMD_LSPEED_GET(x) (((x) >> 24) & 0x3f)
 #define FW_PORT_CMD_TXPAUSE (1U << 23)
@@ -1305,6 +1333,9 @@ enum fw_port_module_type {
        FW_PORT_MOD_TYPE_TWINAX_PASSIVE,
        FW_PORT_MOD_TYPE_TWINAX_ACTIVE,
        FW_PORT_MOD_TYPE_LRM,
+       FW_PORT_MOD_TYPE_ERROR          = FW_PORT_CMD_MODTYPE_MASK - 3,
+       FW_PORT_MOD_TYPE_UNKNOWN        = FW_PORT_CMD_MODTYPE_MASK - 2,
+       FW_PORT_MOD_TYPE_NOTSUPPORTED   = FW_PORT_CMD_MODTYPE_MASK - 1,
 
        FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK
 };
index f16745f4b36bf2b2c30bbe8740029aa4327b5020..92170d50d9d8d0a1fa6b4ed1508de34d1855ae10 100644 (file)
@@ -536,7 +536,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
        if (fl->pend_cred >= FL_PER_EQ_UNIT) {
                wmb();
                t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
-                            DBPRIO |
+                            DBPRIO(1) |
                             QID(fl->cntxt_id) |
                             PIDX(fl->pend_cred / FL_PER_EQ_UNIT));
                fl->pend_cred %= FL_PER_EQ_UNIT;
@@ -952,7 +952,7 @@ static inline void ring_tx_db(struct adapter *adapter, struct sge_txq *tq,
         * Warn if we write doorbells with the wrong priority and write
         * descriptors before telling HW.
         */
-       WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO);
+       WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO(1));
        wmb();
        t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
                     QID(tq->cntxt_id) | PIDX(n));
@@ -2126,8 +2126,8 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
                cmd.iqns_to_fl0congen =
                        cpu_to_be32(
                                FW_IQ_CMD_FL0HOSTFCMODE(SGE_HOSTFCMODE_NONE) |
-                               FW_IQ_CMD_FL0PACKEN |
-                               FW_IQ_CMD_FL0PADEN);
+                               FW_IQ_CMD_FL0PACKEN(1) |
+                               FW_IQ_CMD_FL0PADEN(1));
                cmd.fl0dcaen_to_fl0cidxfthresh =
                        cpu_to_be16(
                                FW_IQ_CMD_FL0FBMIN(SGE_FETCHBURSTMIN_64B) |
index 9089d00f14216431b9bf33db13a51b35414184b9..14e30515f6aa86a9f45d88aded9a027c736872b4 100644 (file)
@@ -1671,7 +1671,7 @@ static void e1000_get_wol(struct net_device *netdev,
        /* apply any specific unsupported masks here */
        switch (hw->device_id) {
        case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-               /* KSP3 does not suppport UCAST wake-ups */
+               /* KSP3 does not support UCAST wake-ups */
                wol->supported &= ~WAKE_UCAST;
 
                if (adapter->wol & E1000_WUFC_EX)
index 0029934748bc26c9e820ca2bd707b56b5c82672a..edfba9370922f54632f96440d394772a9da9054b 100644 (file)
@@ -31,6 +31,30 @@ config MV643XX_ETH
          Some boards that use the Discovery chipset are the Momenco
          Ocelot C and Jaguar ATX and Pegasos II.
 
+config MVMDIO
+       tristate "Marvell MDIO interface support"
+       ---help---
+         This driver supports the MDIO interface found in the network
+         interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
+         Dove, Armada 370 and Armada XP).
+
+         For now, this driver is only needed for the MVNETA driver
+         (used on Armada 370 and XP), but it could be used in the
+         future by the MV643XX_ETH driver.
+
+config MVNETA
+       tristate "Marvell Armada 370/XP network interface support"
+       depends on MACH_ARMADA_370_XP
+       select PHYLIB
+       select MVMDIO
+       ---help---
+         This driver supports the network interface units in the
+         Marvell ARMADA XP and ARMADA 370 SoC family.
+
+         Note that this driver is distinct from the mv643xx_eth
+         driver, which should be used for the older Marvell SoCs
+         (Dove, Orion, Discovery, Kirkwood).
+
 config PXA168_ETH
        tristate "Marvell pxa168 ethernet support"
        depends on CPU_PXA168
index 57e3234a37ba3789251bc8182e9f591d7930bf09..7f63b4aac434c61c3a80d60e954b0c57fcb9c9e0 100644 (file)
@@ -3,6 +3,8 @@
 #
 
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_MVMDIO) += mvmdio.o
+obj-$(CONFIG_MVNETA) += mvneta.o
 obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
new file mode 100644 (file)
index 0000000..6d6002b
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Driver for the MDIO interface of Marvell network interfaces.
+ *
+ * Since the MDIO interface of Marvell network interfaces is shared
+ * between all network interfaces, having a single driver allows to
+ * handle concurrent accesses properly (you may have four Ethernet
+ * ports, but they in fact share the same SMI interface to access the
+ * MDIO bus). Moreover, this MDIO interface code is similar between
+ * the mv643xx_eth driver and the mvneta driver. For now, it is only
+ * used by the mvneta driver, but it could later be used by the
+ * mv643xx_eth driver as well.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy.h>
+#include <linux/of_address.h>
+#include <linux/of_mdio.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#define MVMDIO_SMI_DATA_SHIFT              0
+#define MVMDIO_SMI_PHY_ADDR_SHIFT          16
+#define MVMDIO_SMI_PHY_REG_SHIFT           21
+#define MVMDIO_SMI_READ_OPERATION          BIT(26)
+#define MVMDIO_SMI_WRITE_OPERATION         0
+#define MVMDIO_SMI_READ_VALID              BIT(27)
+#define MVMDIO_SMI_BUSY                    BIT(28)
+
+struct orion_mdio_dev {
+       struct mutex lock;
+       void __iomem *smireg;
+};
+
+/* Wait for the SMI unit to be ready for another operation
+ */
+static int orion_mdio_wait_ready(struct mii_bus *bus)
+{
+       struct orion_mdio_dev *dev = bus->priv;
+       int count;
+       u32 val;
+
+       count = 0;
+       while (1) {
+               val = readl(dev->smireg);
+               if (!(val & MVMDIO_SMI_BUSY))
+                       break;
+
+               if (count > 100) {
+                       dev_err(bus->parent, "Timeout: SMI busy for too long\n");
+                       return -ETIMEDOUT;
+               }
+
+               udelay(10);
+               count++;
+       }
+
+       return 0;
+}
+
+static int orion_mdio_read(struct mii_bus *bus, int mii_id,
+                          int regnum)
+{
+       struct orion_mdio_dev *dev = bus->priv;
+       int count;
+       u32 val;
+       int ret;
+
+       mutex_lock(&dev->lock);
+
+       ret = orion_mdio_wait_ready(bus);
+       if (ret < 0) {
+               mutex_unlock(&dev->lock);
+               return ret;
+       }
+
+       writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+               (regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
+               MVMDIO_SMI_READ_OPERATION),
+              dev->smireg);
+
+       /* Wait for the value to become available */
+       count = 0;
+       while (1) {
+               val = readl(dev->smireg);
+               if (val & MVMDIO_SMI_READ_VALID)
+                       break;
+
+               if (count > 100) {
+                       dev_err(bus->parent, "Timeout when reading PHY\n");
+                       mutex_unlock(&dev->lock);
+                       return -ETIMEDOUT;
+               }
+
+               udelay(10);
+               count++;
+       }
+
+       mutex_unlock(&dev->lock);
+
+       return val & 0xFFFF;
+}
+
+static int orion_mdio_write(struct mii_bus *bus, int mii_id,
+                           int regnum, u16 value)
+{
+       struct orion_mdio_dev *dev = bus->priv;
+       int ret;
+
+       mutex_lock(&dev->lock);
+
+       ret = orion_mdio_wait_ready(bus);
+       if (ret < 0) {
+               mutex_unlock(&dev->lock);
+               return ret;
+       }
+
+       writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+               (regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
+               MVMDIO_SMI_WRITE_OPERATION            |
+               (value << MVMDIO_SMI_DATA_SHIFT)),
+              dev->smireg);
+
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int orion_mdio_reset(struct mii_bus *bus)
+{
+       return 0;
+}
+
+static int __devinit orion_mdio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct mii_bus *bus;
+       struct orion_mdio_dev *dev;
+       int i, ret;
+
+       bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev));
+       if (!bus) {
+               dev_err(&pdev->dev, "Cannot allocate MDIO bus\n");
+               return -ENOMEM;
+       }
+
+       bus->name = "orion_mdio_bus";
+       bus->read = orion_mdio_read;
+       bus->write = orion_mdio_write;
+       bus->reset = orion_mdio_reset;
+       snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii",
+                dev_name(&pdev->dev));
+       bus->parent = &pdev->dev;
+
+       bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+       if (!bus->irq) {
+               dev_err(&pdev->dev, "Cannot allocate PHY IRQ array\n");
+               mdiobus_free(bus);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < PHY_MAX_ADDR; i++)
+               bus->irq[i] = PHY_POLL;
+
+       dev = bus->priv;
+       dev->smireg = of_iomap(pdev->dev.of_node, 0);
+       if (!dev->smireg) {
+               dev_err(&pdev->dev, "No SMI register address given in DT\n");
+               kfree(bus->irq);
+               mdiobus_free(bus);
+               return -ENODEV;
+       }
+
+       mutex_init(&dev->lock);
+
+       ret = of_mdiobus_register(bus, np);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
+               iounmap(dev->smireg);
+               kfree(bus->irq);
+               mdiobus_free(bus);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, bus);
+
+       return 0;
+}
+
+static int __devexit orion_mdio_remove(struct platform_device *pdev)
+{
+       struct mii_bus *bus = platform_get_drvdata(pdev);
+       mdiobus_unregister(bus);
+       kfree(bus->irq);
+       mdiobus_free(bus);
+       return 0;
+}
+
+static const struct of_device_id orion_mdio_match[] = {
+       { .compatible = "marvell,orion-mdio" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, orion_mdio_match);
+
+static struct platform_driver orion_mdio_driver = {
+       .probe = orion_mdio_probe,
+       .remove = __devexit_p(orion_mdio_remove),
+       .driver = {
+               .name = "orion-mdio",
+               .of_match_table = orion_mdio_match,
+       },
+};
+
+module_platform_driver(orion_mdio_driver);
+
+MODULE_DESCRIPTION("Marvell MDIO interface driver");
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
new file mode 100644 (file)
index 0000000..3f8086b
--- /dev/null
@@ -0,0 +1,2848 @@
+/*
+ * Driver for Marvell NETA network card for Armada XP and Armada 370 SoCs.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Rami Rosen <rosenr@marvell.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/inetdevice.h>
+#include <linux/mbus.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+
+/* Registers */
+#define MVNETA_RXQ_CONFIG_REG(q)                (0x1400 + ((q) << 2))
+#define      MVNETA_RXQ_HW_BUF_ALLOC            BIT(1)
+#define      MVNETA_RXQ_PKT_OFFSET_ALL_MASK     (0xf    << 8)
+#define      MVNETA_RXQ_PKT_OFFSET_MASK(offs)   ((offs) << 8)
+#define MVNETA_RXQ_THRESHOLD_REG(q)             (0x14c0 + ((q) << 2))
+#define      MVNETA_RXQ_NON_OCCUPIED(v)         ((v) << 16)
+#define MVNETA_RXQ_BASE_ADDR_REG(q)             (0x1480 + ((q) << 2))
+#define MVNETA_RXQ_SIZE_REG(q)                  (0x14a0 + ((q) << 2))
+#define      MVNETA_RXQ_BUF_SIZE_SHIFT          19
+#define      MVNETA_RXQ_BUF_SIZE_MASK           (0x1fff << 19)
+#define MVNETA_RXQ_STATUS_REG(q)                (0x14e0 + ((q) << 2))
+#define      MVNETA_RXQ_OCCUPIED_ALL_MASK       0x3fff
+#define MVNETA_RXQ_STATUS_UPDATE_REG(q)         (0x1500 + ((q) << 2))
+#define      MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT  16
+#define      MVNETA_RXQ_ADD_NON_OCCUPIED_MAX    255
+#define MVNETA_PORT_RX_RESET                    0x1cc0
+#define      MVNETA_PORT_RX_DMA_RESET           BIT(0)
+#define MVNETA_PHY_ADDR                         0x2000
+#define      MVNETA_PHY_ADDR_MASK               0x1f
+#define MVNETA_MBUS_RETRY                       0x2010
+#define MVNETA_UNIT_INTR_CAUSE                  0x2080
+#define MVNETA_UNIT_CONTROL                     0x20B0
+#define      MVNETA_PHY_POLLING_ENABLE          BIT(1)
+#define MVNETA_WIN_BASE(w)                      (0x2200 + ((w) << 3))
+#define MVNETA_WIN_SIZE(w)                      (0x2204 + ((w) << 3))
+#define MVNETA_WIN_REMAP(w)                     (0x2280 + ((w) << 2))
+#define MVNETA_BASE_ADDR_ENABLE                 0x2290
+#define MVNETA_PORT_CONFIG                      0x2400
+#define      MVNETA_UNI_PROMISC_MODE            BIT(0)
+#define      MVNETA_DEF_RXQ(q)                  ((q) << 1)
+#define      MVNETA_DEF_RXQ_ARP(q)              ((q) << 4)
+#define      MVNETA_TX_UNSET_ERR_SUM            BIT(12)
+#define      MVNETA_DEF_RXQ_TCP(q)              ((q) << 16)
+#define      MVNETA_DEF_RXQ_UDP(q)              ((q) << 19)
+#define      MVNETA_DEF_RXQ_BPDU(q)             ((q) << 22)
+#define      MVNETA_RX_CSUM_WITH_PSEUDO_HDR     BIT(25)
+#define      MVNETA_PORT_CONFIG_DEFL_VALUE(q)   (MVNETA_DEF_RXQ(q)       | \
+                                                MVNETA_DEF_RXQ_ARP(q)   | \
+                                                MVNETA_DEF_RXQ_TCP(q)   | \
+                                                MVNETA_DEF_RXQ_UDP(q)   | \
+                                                MVNETA_DEF_RXQ_BPDU(q)  | \
+                                                MVNETA_TX_UNSET_ERR_SUM | \
+                                                MVNETA_RX_CSUM_WITH_PSEUDO_HDR)
+#define MVNETA_PORT_CONFIG_EXTEND                0x2404
+#define MVNETA_MAC_ADDR_LOW                      0x2414
+#define MVNETA_MAC_ADDR_HIGH                     0x2418
+#define MVNETA_SDMA_CONFIG                       0x241c
+#define      MVNETA_SDMA_BRST_SIZE_16            4
+#define      MVNETA_NO_DESC_SWAP                 0x0
+#define      MVNETA_RX_BRST_SZ_MASK(burst)       ((burst) << 1)
+#define      MVNETA_RX_NO_DATA_SWAP              BIT(4)
+#define      MVNETA_TX_NO_DATA_SWAP              BIT(5)
+#define      MVNETA_TX_BRST_SZ_MASK(burst)       ((burst) << 22)
+#define MVNETA_PORT_STATUS                       0x2444
+#define      MVNETA_TX_IN_PRGRS                  BIT(1)
+#define      MVNETA_TX_FIFO_EMPTY                BIT(8)
+#define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
+#define MVNETA_TYPE_PRIO                         0x24bc
+#define      MVNETA_FORCE_UNI                    BIT(21)
+#define MVNETA_TXQ_CMD_1                         0x24e4
+#define MVNETA_TXQ_CMD                           0x2448
+#define      MVNETA_TXQ_DISABLE_SHIFT            8
+#define      MVNETA_TXQ_ENABLE_MASK              0x000000ff
+#define MVNETA_ACC_MODE                          0x2500
+#define MVNETA_CPU_MAP(cpu)                      (0x2540 + ((cpu) << 2))
+#define      MVNETA_CPU_RXQ_ACCESS_ALL_MASK      0x000000ff
+#define      MVNETA_CPU_TXQ_ACCESS_ALL_MASK      0x0000ff00
+#define MVNETA_RXQ_TIME_COAL_REG(q)              (0x2580 + ((q) << 2))
+#define MVNETA_INTR_NEW_CAUSE                    0x25a0
+#define      MVNETA_RX_INTR_MASK(nr_rxqs)        (((1 << nr_rxqs) - 1) << 8)
+#define MVNETA_INTR_NEW_MASK                     0x25a4
+#define MVNETA_INTR_OLD_CAUSE                    0x25a8
+#define MVNETA_INTR_OLD_MASK                     0x25ac
+#define MVNETA_INTR_MISC_CAUSE                   0x25b0
+#define MVNETA_INTR_MISC_MASK                    0x25b4
+#define MVNETA_INTR_ENABLE                       0x25b8
+#define      MVNETA_TXQ_INTR_ENABLE_ALL_MASK     0x0000ff00
+#define      MVNETA_RXQ_INTR_ENABLE_ALL_MASK     0xff000000
+#define MVNETA_RXQ_CMD                           0x2680
+#define      MVNETA_RXQ_DISABLE_SHIFT            8
+#define      MVNETA_RXQ_ENABLE_MASK              0x000000ff
+#define MVETH_TXQ_TOKEN_COUNT_REG(q)             (0x2700 + ((q) << 4))
+#define MVETH_TXQ_TOKEN_CFG_REG(q)               (0x2704 + ((q) << 4))
+#define MVNETA_GMAC_CTRL_0                       0x2c00
+#define      MVNETA_GMAC_MAX_RX_SIZE_SHIFT       2
+#define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc
+#define      MVNETA_GMAC0_PORT_ENABLE            BIT(0)
+#define MVNETA_GMAC_CTRL_2                       0x2c08
+#define      MVNETA_GMAC2_PSC_ENABLE             BIT(3)
+#define      MVNETA_GMAC2_PORT_RGMII             BIT(4)
+#define      MVNETA_GMAC2_PORT_RESET             BIT(6)
+#define MVNETA_GMAC_STATUS                       0x2c10
+#define      MVNETA_GMAC_LINK_UP                 BIT(0)
+#define      MVNETA_GMAC_SPEED_1000              BIT(1)
+#define      MVNETA_GMAC_SPEED_100               BIT(2)
+#define      MVNETA_GMAC_FULL_DUPLEX             BIT(3)
+#define      MVNETA_GMAC_RX_FLOW_CTRL_ENABLE     BIT(4)
+#define      MVNETA_GMAC_TX_FLOW_CTRL_ENABLE     BIT(5)
+#define      MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE     BIT(6)
+#define      MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE     BIT(7)
+#define MVNETA_GMAC_AUTONEG_CONFIG               0x2c0c
+#define      MVNETA_GMAC_FORCE_LINK_DOWN         BIT(0)
+#define      MVNETA_GMAC_FORCE_LINK_PASS         BIT(1)
+#define      MVNETA_GMAC_CONFIG_MII_SPEED        BIT(5)
+#define      MVNETA_GMAC_CONFIG_GMII_SPEED       BIT(6)
+#define      MVNETA_GMAC_CONFIG_FULL_DUPLEX      BIT(12)
+#define MVNETA_MIB_COUNTERS_BASE                 0x3080
+#define      MVNETA_MIB_LATE_COLLISION           0x7c
+#define MVNETA_DA_FILT_SPEC_MCAST                0x3400
+#define MVNETA_DA_FILT_OTH_MCAST                 0x3500
+#define MVNETA_DA_FILT_UCAST_BASE                0x3600
+#define MVNETA_TXQ_BASE_ADDR_REG(q)              (0x3c00 + ((q) << 2))
+#define MVNETA_TXQ_SIZE_REG(q)                   (0x3c20 + ((q) << 2))
+#define      MVNETA_TXQ_SENT_THRESH_ALL_MASK     0x3fff0000
+#define      MVNETA_TXQ_SENT_THRESH_MASK(coal)   ((coal) << 16)
+#define MVNETA_TXQ_UPDATE_REG(q)                 (0x3c60 + ((q) << 2))
+#define      MVNETA_TXQ_DEC_SENT_SHIFT           16
+#define MVNETA_TXQ_STATUS_REG(q)                 (0x3c40 + ((q) << 2))
+#define      MVNETA_TXQ_SENT_DESC_SHIFT          16
+#define      MVNETA_TXQ_SENT_DESC_MASK           0x3fff0000
+#define MVNETA_PORT_TX_RESET                     0x3cf0
+#define      MVNETA_PORT_TX_DMA_RESET            BIT(0)
+#define MVNETA_TX_MTU                            0x3e0c
+#define MVNETA_TX_TOKEN_SIZE                     0x3e14
+#define      MVNETA_TX_TOKEN_SIZE_MAX            0xffffffff
+#define MVNETA_TXQ_TOKEN_SIZE_REG(q)             (0x3e40 + ((q) << 2))
+#define      MVNETA_TXQ_TOKEN_SIZE_MAX           0x7fffffff
+
+#define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK     0xff
+
+/* Descriptor ring Macros */
+#define MVNETA_QUEUE_NEXT_DESC(q, index)       \
+       (((index) < (q)->last_desc) ? ((index) + 1) : 0)
+
+/* Various constants */
+
+/* Coalescing */
+#define MVNETA_TXDONE_COAL_PKTS                16
+#define MVNETA_RX_COAL_PKTS            32
+#define MVNETA_RX_COAL_USEC            100
+
+/* Timer */
+#define MVNETA_TX_DONE_TIMER_PERIOD    10
+
+/* Napi polling weight */
+#define MVNETA_RX_POLL_WEIGHT          64
+
+/* The two bytes Marvell header. Either contains a special value used
+ * by Marvell switches when a specific hardware mode is enabled (not
+ * supported by this driver) or is filled automatically by zeroes on
+ * the RX side. Those two bytes being at the front of the Ethernet
+ * header, they allow to have the IP header aligned on a 4 bytes
+ * boundary automatically: the hardware skips those two bytes on its
+ * own.
+ */
+#define MVNETA_MH_SIZE                 2
+
+#define MVNETA_VLAN_TAG_LEN             4
+
+#define MVNETA_CPU_D_CACHE_LINE_SIZE    32
+#define MVNETA_TX_CSUM_MAX_SIZE                9800
+#define MVNETA_ACC_MODE_EXT            1
+
+/* Timeout constants */
+#define MVNETA_TX_DISABLE_TIMEOUT_MSEC 1000
+#define MVNETA_RX_DISABLE_TIMEOUT_MSEC 1000
+#define MVNETA_TX_FIFO_EMPTY_TIMEOUT   10000
+
+#define MVNETA_TX_MTU_MAX              0x3ffff
+
+/* Max number of Rx descriptors */
+#define MVNETA_MAX_RXD 128
+
+/* Max number of Tx descriptors */
+#define MVNETA_MAX_TXD 532
+
+/* descriptor aligned size */
+#define MVNETA_DESC_ALIGNED_SIZE       32
+
+#define MVNETA_RX_PKT_SIZE(mtu) \
+       ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \
+             ETH_HLEN + ETH_FCS_LEN,                        \
+             MVNETA_CPU_D_CACHE_LINE_SIZE)
+
+#define MVNETA_RX_BUF_SIZE(pkt_size)   ((pkt_size) + NET_SKB_PAD)
+
+struct mvneta_stats {
+       struct  u64_stats_sync syncp;
+       u64     packets;
+       u64     bytes;
+};
+
+struct mvneta_port {
+       int pkt_size;
+       void __iomem *base;
+       struct mvneta_rx_queue *rxqs;
+       struct mvneta_tx_queue *txqs;
+       struct timer_list tx_done_timer;
+       struct net_device *dev;
+
+       u32 cause_rx_tx;
+       struct napi_struct napi;
+
+       /* Flags */
+       unsigned long flags;
+#define MVNETA_F_TX_DONE_TIMER_BIT  0
+
+       /* Napi weight */
+       int weight;
+
+       /* Core clock */
+       struct clk *clk;
+       u8 mcast_count[256];
+       u16 tx_ring_size;
+       u16 rx_ring_size;
+       struct mvneta_stats tx_stats;
+       struct mvneta_stats rx_stats;
+
+       struct mii_bus *mii_bus;
+       struct phy_device *phy_dev;
+       phy_interface_t phy_interface;
+       struct device_node *phy_node;
+       unsigned int link;
+       unsigned int duplex;
+       unsigned int speed;
+};
+
+/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
+ * layout of the transmit and reception DMA descriptors, and their
+ * layout is therefore defined by the hardware design
+ */
+struct mvneta_tx_desc {
+       u32  command;           /* Options used by HW for packet transmitting.*/
+#define MVNETA_TX_L3_OFF_SHIFT 0
+#define MVNETA_TX_IP_HLEN_SHIFT        8
+#define MVNETA_TX_L4_UDP       BIT(16)
+#define MVNETA_TX_L3_IP6       BIT(17)
+#define MVNETA_TXD_IP_CSUM     BIT(18)
+#define MVNETA_TXD_Z_PAD       BIT(19)
+#define MVNETA_TXD_L_DESC      BIT(20)
+#define MVNETA_TXD_F_DESC      BIT(21)
+#define MVNETA_TXD_FLZ_DESC    (MVNETA_TXD_Z_PAD  | \
+                                MVNETA_TXD_L_DESC | \
+                                MVNETA_TXD_F_DESC)
+#define MVNETA_TX_L4_CSUM_FULL BIT(30)
+#define MVNETA_TX_L4_CSUM_NOT  BIT(31)
+
+       u16  reserverd1;        /* csum_l4 (for future use)             */
+       u16  data_size;         /* Data size of transmitted packet in bytes */
+       u32  buf_phys_addr;     /* Physical addr of transmitted buffer  */
+       u32  reserved2;         /* hw_cmd - (for future use, PMT)       */
+       u32  reserved3[4];      /* Reserved - (for future use)          */
+};
+
+struct mvneta_rx_desc {
+       u32  status;            /* Info about received packet           */
+#define MVNETA_RXD_ERR_CRC             0x0
+#define MVNETA_RXD_ERR_SUMMARY         BIT(16)
+#define MVNETA_RXD_ERR_OVERRUN         BIT(17)
+#define MVNETA_RXD_ERR_LEN             BIT(18)
+#define MVNETA_RXD_ERR_RESOURCE                (BIT(17) | BIT(18))
+#define MVNETA_RXD_ERR_CODE_MASK       (BIT(17) | BIT(18))
+#define MVNETA_RXD_L3_IP4              BIT(25)
+#define MVNETA_RXD_FIRST_LAST_DESC     (BIT(26) | BIT(27))
+#define MVNETA_RXD_L4_CSUM_OK          BIT(30)
+
+       u16  reserved1;         /* pnc_info - (for future use, PnC)     */
+       u16  data_size;         /* Size of received packet in bytes     */
+       u32  buf_phys_addr;     /* Physical address of the buffer       */
+       u32  reserved2;         /* pnc_flow_id  (for future use, PnC)   */
+       u32  buf_cookie;        /* cookie for access to RX buffer in rx path */
+       u16  reserved3;         /* prefetch_cmd, for future use         */
+       u16  reserved4;         /* csum_l4 - (for future use, PnC)      */
+       u32  reserved5;         /* pnc_extra PnC (for future use, PnC)  */
+       u32  reserved6;         /* hw_cmd (for future use, PnC and HWF) */
+};
+
+struct mvneta_tx_queue {
+       /* Number of this TX queue, in the range 0-7 */
+       u8 id;
+
+       /* Number of TX DMA descriptors in the descriptor ring */
+       int size;
+
+       /* Number of currently used TX DMA descriptor in the
+        * descriptor ring
+        */
+       int count;
+
+       /* Array of transmitted skb */
+       struct sk_buff **tx_skb;
+
+       /* Index of last TX DMA descriptor that was inserted */
+       int txq_put_index;
+
+       /* Index of the TX DMA descriptor to be cleaned up */
+       int txq_get_index;
+
+       u32 done_pkts_coal;
+
+       /* Virtual address of the TX DMA descriptors array */
+       struct mvneta_tx_desc *descs;
+
+       /* DMA address of the TX DMA descriptors array */
+       dma_addr_t descs_phys;
+
+       /* Index of the last TX DMA descriptor */
+       int last_desc;
+
+       /* Index of the next TX DMA descriptor to process */
+       int next_desc_to_proc;
+};
+
+struct mvneta_rx_queue {
+       /* rx queue number, in the range 0-7 */
+       u8 id;
+
+       /* num of rx descriptors in the rx descriptor ring */
+       int size;
+
+       /* counter of times when mvneta_refill() failed */
+       int missed;
+
+       u32 pkts_coal;
+       u32 time_coal;
+
+       /* Virtual address of the RX DMA descriptors array */
+       struct mvneta_rx_desc *descs;
+
+       /* DMA address of the RX DMA descriptors array */
+       dma_addr_t descs_phys;
+
+       /* Index of the last RX DMA descriptor */
+       int last_desc;
+
+       /* Index of the next RX DMA descriptor to process */
+       int next_desc_to_proc;
+};
+
+static int rxq_number = 8;
+static int txq_number = 8;
+
+static int rxq_def;
+static int txq_def;
+
+#define MVNETA_DRIVER_NAME "mvneta"
+#define MVNETA_DRIVER_VERSION "1.0"
+
+/* Utility/helper methods */
+
+/* Write helper method */
+static void mvreg_write(struct mvneta_port *pp, u32 offset, u32 data)
+{
+       writel(data, pp->base + offset);
+}
+
+/* Read helper method */
+static u32 mvreg_read(struct mvneta_port *pp, u32 offset)
+{
+       return readl(pp->base + offset);
+}
+
+/* Increment txq get counter */
+static void mvneta_txq_inc_get(struct mvneta_tx_queue *txq)
+{
+       txq->txq_get_index++;
+       if (txq->txq_get_index == txq->size)
+               txq->txq_get_index = 0;
+}
+
+/* Increment txq put counter */
+static void mvneta_txq_inc_put(struct mvneta_tx_queue *txq)
+{
+       txq->txq_put_index++;
+       if (txq->txq_put_index == txq->size)
+               txq->txq_put_index = 0;
+}
+
+
+/* Clear all MIB counters */
+static void mvneta_mib_counters_clear(struct mvneta_port *pp)
+{
+       int i;
+       u32 dummy;
+
+       /* Perform dummy reads from MIB counters */
+       for (i = 0; i < MVNETA_MIB_LATE_COLLISION; i += 4)
+               dummy = mvreg_read(pp, (MVNETA_MIB_COUNTERS_BASE + i));
+}
+
+/* Get System Network Statistics */
+struct rtnl_link_stats64 *mvneta_get_stats64(struct net_device *dev,
+                                            struct rtnl_link_stats64 *stats)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       unsigned int start;
+
+       memset(stats, 0, sizeof(struct rtnl_link_stats64));
+
+       do {
+               start = u64_stats_fetch_begin_bh(&pp->rx_stats.syncp);
+               stats->rx_packets = pp->rx_stats.packets;
+               stats->rx_bytes = pp->rx_stats.bytes;
+       } while (u64_stats_fetch_retry_bh(&pp->rx_stats.syncp, start));
+
+
+       do {
+               start = u64_stats_fetch_begin_bh(&pp->tx_stats.syncp);
+               stats->tx_packets = pp->tx_stats.packets;
+               stats->tx_bytes = pp->tx_stats.bytes;
+       } while (u64_stats_fetch_retry_bh(&pp->tx_stats.syncp, start));
+
+       stats->rx_errors        = dev->stats.rx_errors;
+       stats->rx_dropped       = dev->stats.rx_dropped;
+
+       stats->tx_dropped       = dev->stats.tx_dropped;
+
+       return stats;
+}
+
+/* Rx descriptors helper methods */
+
+/* Checks whether the given RX descriptor is both the first and the
+ * last descriptor for the RX packet. Each RX packet is currently
+ * received through a single RX descriptor, so not having each RX
+ * descriptor with its first and last bits set is an error
+ */
+static int mvneta_rxq_desc_is_first_last(struct mvneta_rx_desc *desc)
+{
+       return (desc->status & MVNETA_RXD_FIRST_LAST_DESC) ==
+               MVNETA_RXD_FIRST_LAST_DESC;
+}
+
+/* Add number of descriptors ready to receive new packets */
+static void mvneta_rxq_non_occup_desc_add(struct mvneta_port *pp,
+                                         struct mvneta_rx_queue *rxq,
+                                         int ndescs)
+{
+       /* Only MVNETA_RXQ_ADD_NON_OCCUPIED_MAX (255) descriptors can
+        * be added at once
+        */
+       while (ndescs > MVNETA_RXQ_ADD_NON_OCCUPIED_MAX) {
+               mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id),
+                           (MVNETA_RXQ_ADD_NON_OCCUPIED_MAX <<
+                            MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT));
+               ndescs -= MVNETA_RXQ_ADD_NON_OCCUPIED_MAX;
+       }
+
+       mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id),
+                   (ndescs << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT));
+}
+
+/* Get number of RX descriptors occupied by received packets */
+static int mvneta_rxq_busy_desc_num_get(struct mvneta_port *pp,
+                                       struct mvneta_rx_queue *rxq)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_RXQ_STATUS_REG(rxq->id));
+       return val & MVNETA_RXQ_OCCUPIED_ALL_MASK;
+}
+
+/* Update num of rx desc called upon return from rx path or
+ * from mvneta_rxq_drop_pkts().
+ */
+static void mvneta_rxq_desc_num_update(struct mvneta_port *pp,
+                                      struct mvneta_rx_queue *rxq,
+                                      int rx_done, int rx_filled)
+{
+       u32 val;
+
+       if ((rx_done <= 0xff) && (rx_filled <= 0xff)) {
+               val = rx_done |
+                 (rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT);
+               mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val);
+               return;
+       }
+
+       /* Only 255 descriptors can be added at once */
+       while ((rx_done > 0) || (rx_filled > 0)) {
+               if (rx_done <= 0xff) {
+                       val = rx_done;
+                       rx_done = 0;
+               } else {
+                       val = 0xff;
+                       rx_done -= 0xff;
+               }
+               if (rx_filled <= 0xff) {
+                       val |= rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
+                       rx_filled = 0;
+               } else {
+                       val |= 0xff << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
+                       rx_filled -= 0xff;
+               }
+               mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val);
+       }
+}
+
+/* Get pointer to next RX descriptor to be processed by SW */
+static struct mvneta_rx_desc *
+mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq)
+{
+       int rx_desc = rxq->next_desc_to_proc;
+
+       rxq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc);
+       return rxq->descs + rx_desc;
+}
+
+/* Change maximum receive size of the port. */
+static void mvneta_max_rx_size_set(struct mvneta_port *pp, int max_rx_size)
+{
+       u32 val;
+
+       val =  mvreg_read(pp, MVNETA_GMAC_CTRL_0);
+       val &= ~MVNETA_GMAC_MAX_RX_SIZE_MASK;
+       val |= ((max_rx_size - MVNETA_MH_SIZE) / 2) <<
+               MVNETA_GMAC_MAX_RX_SIZE_SHIFT;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
+}
+
+
+/* Set rx queue offset */
+static void mvneta_rxq_offset_set(struct mvneta_port *pp,
+                                 struct mvneta_rx_queue *rxq,
+                                 int offset)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id));
+       val &= ~MVNETA_RXQ_PKT_OFFSET_ALL_MASK;
+
+       /* Offset is in */
+       val |= MVNETA_RXQ_PKT_OFFSET_MASK(offset >> 3);
+       mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
+}
+
+
+/* Tx descriptors helper methods */
+
+/* Update HW with number of TX descriptors to be sent */
+static void mvneta_txq_pend_desc_add(struct mvneta_port *pp,
+                                    struct mvneta_tx_queue *txq,
+                                    int pend_desc)
+{
+       u32 val;
+
+       /* Only 255 descriptors can be added at once ; Assume caller
+        * process TX desriptors in quanta less than 256
+        */
+       val = pend_desc;
+       mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+}
+
+/* Get pointer to next TX descriptor to be processed (send) by HW */
+static struct mvneta_tx_desc *
+mvneta_txq_next_desc_get(struct mvneta_tx_queue *txq)
+{
+       int tx_desc = txq->next_desc_to_proc;
+
+       txq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(txq, tx_desc);
+       return txq->descs + tx_desc;
+}
+
+/* Release the last allocated TX descriptor. Useful to handle DMA
+ * mapping failures in the TX path.
+ */
+static void mvneta_txq_desc_put(struct mvneta_tx_queue *txq)
+{
+       if (txq->next_desc_to_proc == 0)
+               txq->next_desc_to_proc = txq->last_desc - 1;
+       else
+               txq->next_desc_to_proc--;
+}
+
+/* Set rxq buf size */
+static void mvneta_rxq_buf_size_set(struct mvneta_port *pp,
+                                   struct mvneta_rx_queue *rxq,
+                                   int buf_size)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_RXQ_SIZE_REG(rxq->id));
+
+       val &= ~MVNETA_RXQ_BUF_SIZE_MASK;
+       val |= ((buf_size >> 3) << MVNETA_RXQ_BUF_SIZE_SHIFT);
+
+       mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), val);
+}
+
+/* Disable buffer management (BM) */
+static void mvneta_rxq_bm_disable(struct mvneta_port *pp,
+                                 struct mvneta_rx_queue *rxq)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id));
+       val &= ~MVNETA_RXQ_HW_BUF_ALLOC;
+       mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
+}
+
+
+
+/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */
+static void __devinit mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
+{
+       u32  val;
+
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+
+       if (enable)
+               val |= MVNETA_GMAC2_PORT_RGMII;
+       else
+               val &= ~MVNETA_GMAC2_PORT_RGMII;
+
+       mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+}
+
+/* Config SGMII port */
+static void __devinit mvneta_port_sgmii_config(struct mvneta_port *pp)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+       val |= MVNETA_GMAC2_PSC_ENABLE;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+}
+
+/* Start the Ethernet port RX and TX activity */
+static void mvneta_port_up(struct mvneta_port *pp)
+{
+       int queue;
+       u32 q_map;
+
+       /* Enable all initialized TXs. */
+       mvneta_mib_counters_clear(pp);
+       q_map = 0;
+       for (queue = 0; queue < txq_number; queue++) {
+               struct mvneta_tx_queue *txq = &pp->txqs[queue];
+               if (txq->descs != NULL)
+                       q_map |= (1 << queue);
+       }
+       mvreg_write(pp, MVNETA_TXQ_CMD, q_map);
+
+       /* Enable all initialized RXQs. */
+       q_map = 0;
+       for (queue = 0; queue < rxq_number; queue++) {
+               struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
+               if (rxq->descs != NULL)
+                       q_map |= (1 << queue);
+       }
+
+       mvreg_write(pp, MVNETA_RXQ_CMD, q_map);
+}
+
+/* Stop the Ethernet port activity */
+static void mvneta_port_down(struct mvneta_port *pp)
+{
+       u32 val;
+       int count;
+
+       /* Stop Rx port activity. Check port Rx activity. */
+       val = mvreg_read(pp, MVNETA_RXQ_CMD) & MVNETA_RXQ_ENABLE_MASK;
+
+       /* Issue stop command for active channels only */
+       if (val != 0)
+               mvreg_write(pp, MVNETA_RXQ_CMD,
+                           val << MVNETA_RXQ_DISABLE_SHIFT);
+
+       /* Wait for all Rx activity to terminate. */
+       count = 0;
+       do {
+               if (count++ >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) {
+                       netdev_warn(pp->dev,
+                                   "TIMEOUT for RX stopped ! rx_queue_cmd: 0x08%x\n",
+                                   val);
+                       break;
+               }
+               mdelay(1);
+
+               val = mvreg_read(pp, MVNETA_RXQ_CMD);
+       } while (val & 0xff);
+
+       /* Stop Tx port activity. Check port Tx activity. Issue stop
+        * command for active channels only
+        */
+       val = (mvreg_read(pp, MVNETA_TXQ_CMD)) & MVNETA_TXQ_ENABLE_MASK;
+
+       if (val != 0)
+               mvreg_write(pp, MVNETA_TXQ_CMD,
+                           (val << MVNETA_TXQ_DISABLE_SHIFT));
+
+       /* Wait for all Tx activity to terminate. */
+       count = 0;
+       do {
+               if (count++ >= MVNETA_TX_DISABLE_TIMEOUT_MSEC) {
+                       netdev_warn(pp->dev,
+                                   "TIMEOUT for TX stopped status=0x%08x\n",
+                                   val);
+                       break;
+               }
+               mdelay(1);
+
+               /* Check TX Command reg that all Txqs are stopped */
+               val = mvreg_read(pp, MVNETA_TXQ_CMD);
+
+       } while (val & 0xff);
+
+       /* Double check to verify that TX FIFO is empty */
+       count = 0;
+       do {
+               if (count++ >= MVNETA_TX_FIFO_EMPTY_TIMEOUT) {
+                       netdev_warn(pp->dev,
+                                   "TX FIFO empty timeout status=0x08%x\n",
+                                   val);
+                       break;
+               }
+               mdelay(1);
+
+               val = mvreg_read(pp, MVNETA_PORT_STATUS);
+       } while (!(val & MVNETA_TX_FIFO_EMPTY) &&
+                (val & MVNETA_TX_IN_PRGRS));
+
+       udelay(200);
+}
+
+/* Enable the port by setting the port enable bit of the MAC control register */
+static void mvneta_port_enable(struct mvneta_port *pp)
+{
+       u32 val;
+
+       /* Enable port */
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
+       val |= MVNETA_GMAC0_PORT_ENABLE;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
+}
+
+/* Disable the port and wait for about 200 usec before retuning */
+static void mvneta_port_disable(struct mvneta_port *pp)
+{
+       u32 val;
+
+       /* Reset the Enable bit in the Serial Control Register */
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
+       val &= ~MVNETA_GMAC0_PORT_ENABLE;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
+
+       udelay(200);
+}
+
+/* Multicast tables methods */
+
+/* Set all entries in Unicast MAC Table; queue==-1 means reject all */
+static void mvneta_set_ucast_table(struct mvneta_port *pp, int queue)
+{
+       int offset;
+       u32 val;
+
+       if (queue == -1) {
+               val = 0;
+       } else {
+               val = 0x1 | (queue << 1);
+               val |= (val << 24) | (val << 16) | (val << 8);
+       }
+
+       for (offset = 0; offset <= 0xc; offset += 4)
+               mvreg_write(pp, MVNETA_DA_FILT_UCAST_BASE + offset, val);
+}
+
+/* Set all entries in Special Multicast MAC Table; queue==-1 means reject all */
+static void mvneta_set_special_mcast_table(struct mvneta_port *pp, int queue)
+{
+       int offset;
+       u32 val;
+
+       if (queue == -1) {
+               val = 0;
+       } else {
+               val = 0x1 | (queue << 1);
+               val |= (val << 24) | (val << 16) | (val << 8);
+       }
+
+       for (offset = 0; offset <= 0xfc; offset += 4)
+               mvreg_write(pp, MVNETA_DA_FILT_SPEC_MCAST + offset, val);
+
+}
+
+/* Set all entries in Other Multicast MAC Table. queue==-1 means reject all */
+static void mvneta_set_other_mcast_table(struct mvneta_port *pp, int queue)
+{
+       int offset;
+       u32 val;
+
+       if (queue == -1) {
+               memset(pp->mcast_count, 0, sizeof(pp->mcast_count));
+               val = 0;
+       } else {
+               memset(pp->mcast_count, 1, sizeof(pp->mcast_count));
+               val = 0x1 | (queue << 1);
+               val |= (val << 24) | (val << 16) | (val << 8);
+       }
+
+       for (offset = 0; offset <= 0xfc; offset += 4)
+               mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val);
+}
+
+/* This method sets defaults to the NETA port:
+ *     Clears interrupt Cause and Mask registers.
+ *     Clears all MAC tables.
+ *     Sets defaults to all registers.
+ *     Resets RX and TX descriptor rings.
+ *     Resets PHY.
+ * This method can be called after mvneta_port_down() to return the port
+ *     settings to defaults.
+ */
+static void mvneta_defaults_set(struct mvneta_port *pp)
+{
+       int cpu;
+       int queue;
+       u32 val;
+
+       /* Clear all Cause registers */
+       mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+
+       /* Mask all interrupts */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_ENABLE, 0);
+
+       /* Enable MBUS Retry bit16 */
+       mvreg_write(pp, MVNETA_MBUS_RETRY, 0x20);
+
+       /* Set CPU queue access map - all CPUs have access to all RX
+        * queues and to all TX queues
+        */
+       for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++)
+               mvreg_write(pp, MVNETA_CPU_MAP(cpu),
+                           (MVNETA_CPU_RXQ_ACCESS_ALL_MASK |
+                            MVNETA_CPU_TXQ_ACCESS_ALL_MASK));
+
+       /* Reset RX and TX DMAs */
+       mvreg_write(pp, MVNETA_PORT_RX_RESET, MVNETA_PORT_RX_DMA_RESET);
+       mvreg_write(pp, MVNETA_PORT_TX_RESET, MVNETA_PORT_TX_DMA_RESET);
+
+       /* Disable Legacy WRR, Disable EJP, Release from reset */
+       mvreg_write(pp, MVNETA_TXQ_CMD_1, 0);
+       for (queue = 0; queue < txq_number; queue++) {
+               mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(queue), 0);
+               mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(queue), 0);
+       }
+
+       mvreg_write(pp, MVNETA_PORT_TX_RESET, 0);
+       mvreg_write(pp, MVNETA_PORT_RX_RESET, 0);
+
+       /* Set Port Acceleration Mode */
+       val = MVNETA_ACC_MODE_EXT;
+       mvreg_write(pp, MVNETA_ACC_MODE, val);
+
+       /* Update val of portCfg register accordingly with all RxQueue types */
+       val = MVNETA_PORT_CONFIG_DEFL_VALUE(rxq_def);
+       mvreg_write(pp, MVNETA_PORT_CONFIG, val);
+
+       val = 0;
+       mvreg_write(pp, MVNETA_PORT_CONFIG_EXTEND, val);
+       mvreg_write(pp, MVNETA_RX_MIN_FRAME_SIZE, 64);
+
+       /* Build PORT_SDMA_CONFIG_REG */
+       val = 0;
+
+       /* Default burst size */
+       val |= MVNETA_TX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16);
+       val |= MVNETA_RX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16);
+
+       val |= (MVNETA_RX_NO_DATA_SWAP | MVNETA_TX_NO_DATA_SWAP |
+               MVNETA_NO_DESC_SWAP);
+
+       /* Assign port SDMA configuration */
+       mvreg_write(pp, MVNETA_SDMA_CONFIG, val);
+
+       mvneta_set_ucast_table(pp, -1);
+       mvneta_set_special_mcast_table(pp, -1);
+       mvneta_set_other_mcast_table(pp, -1);
+
+       /* Set port interrupt enable register - default enable all */
+       mvreg_write(pp, MVNETA_INTR_ENABLE,
+                   (MVNETA_RXQ_INTR_ENABLE_ALL_MASK
+                    | MVNETA_TXQ_INTR_ENABLE_ALL_MASK));
+}
+
+/* Set max sizes for tx queues */
+static void mvneta_txq_max_tx_size_set(struct mvneta_port *pp, int max_tx_size)
+
+{
+       u32 val, size, mtu;
+       int queue;
+
+       mtu = max_tx_size * 8;
+       if (mtu > MVNETA_TX_MTU_MAX)
+               mtu = MVNETA_TX_MTU_MAX;
+
+       /* Set MTU */
+       val = mvreg_read(pp, MVNETA_TX_MTU);
+       val &= ~MVNETA_TX_MTU_MAX;
+       val |= mtu;
+       mvreg_write(pp, MVNETA_TX_MTU, val);
+
+       /* TX token size and all TXQs token size must be larger that MTU */
+       val = mvreg_read(pp, MVNETA_TX_TOKEN_SIZE);
+
+       size = val & MVNETA_TX_TOKEN_SIZE_MAX;
+       if (size < mtu) {
+               size = mtu;
+               val &= ~MVNETA_TX_TOKEN_SIZE_MAX;
+               val |= size;
+               mvreg_write(pp, MVNETA_TX_TOKEN_SIZE, val);
+       }
+       for (queue = 0; queue < txq_number; queue++) {
+               val = mvreg_read(pp, MVNETA_TXQ_TOKEN_SIZE_REG(queue));
+
+               size = val & MVNETA_TXQ_TOKEN_SIZE_MAX;
+               if (size < mtu) {
+                       size = mtu;
+                       val &= ~MVNETA_TXQ_TOKEN_SIZE_MAX;
+                       val |= size;
+                       mvreg_write(pp, MVNETA_TXQ_TOKEN_SIZE_REG(queue), val);
+               }
+       }
+}
+
+/* Set unicast address */
+static void mvneta_set_ucast_addr(struct mvneta_port *pp, u8 last_nibble,
+                                 int queue)
+{
+       unsigned int unicast_reg;
+       unsigned int tbl_offset;
+       unsigned int reg_offset;
+
+       /* Locate the Unicast table entry */
+       last_nibble = (0xf & last_nibble);
+
+       /* offset from unicast tbl base */
+       tbl_offset = (last_nibble / 4) * 4;
+
+       /* offset within the above reg  */
+       reg_offset = last_nibble % 4;
+
+       unicast_reg = mvreg_read(pp, (MVNETA_DA_FILT_UCAST_BASE + tbl_offset));
+
+       if (queue == -1) {
+               /* Clear accepts frame bit at specified unicast DA tbl entry */
+               unicast_reg &= ~(0xff << (8 * reg_offset));
+       } else {
+               unicast_reg &= ~(0xff << (8 * reg_offset));
+               unicast_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset));
+       }
+
+       mvreg_write(pp, (MVNETA_DA_FILT_UCAST_BASE + tbl_offset), unicast_reg);
+}
+
+/* Set mac address */
+static void mvneta_mac_addr_set(struct mvneta_port *pp, unsigned char *addr,
+                               int queue)
+{
+       unsigned int mac_h;
+       unsigned int mac_l;
+
+       if (queue != -1) {
+               mac_l = (addr[4] << 8) | (addr[5]);
+               mac_h = (addr[0] << 24) | (addr[1] << 16) |
+                       (addr[2] << 8) | (addr[3] << 0);
+
+               mvreg_write(pp, MVNETA_MAC_ADDR_LOW, mac_l);
+               mvreg_write(pp, MVNETA_MAC_ADDR_HIGH, mac_h);
+       }
+
+       /* Accept frames of this address */
+       mvneta_set_ucast_addr(pp, addr[5], queue);
+}
+
+/* Set the number of packets that will be received before RX interrupt
+ * will be generated by HW.
+ */
+static void mvneta_rx_pkts_coal_set(struct mvneta_port *pp,
+                                   struct mvneta_rx_queue *rxq, u32 value)
+{
+       mvreg_write(pp, MVNETA_RXQ_THRESHOLD_REG(rxq->id),
+                   value | MVNETA_RXQ_NON_OCCUPIED(0));
+       rxq->pkts_coal = value;
+}
+
+/* Set the time delay in usec before RX interrupt will be generated by
+ * HW.
+ */
+static void mvneta_rx_time_coal_set(struct mvneta_port *pp,
+                                   struct mvneta_rx_queue *rxq, u32 value)
+{
+       u32 val;
+       unsigned long clk_rate;
+
+       clk_rate = clk_get_rate(pp->clk);
+       val = (clk_rate / 1000000) * value;
+
+       mvreg_write(pp, MVNETA_RXQ_TIME_COAL_REG(rxq->id), val);
+       rxq->time_coal = value;
+}
+
+/* Set threshold for TX_DONE pkts coalescing */
+static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,
+                                        struct mvneta_tx_queue *txq, u32 value)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_TXQ_SIZE_REG(txq->id));
+
+       val &= ~MVNETA_TXQ_SENT_THRESH_ALL_MASK;
+       val |= MVNETA_TXQ_SENT_THRESH_MASK(value);
+
+       mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), val);
+
+       txq->done_pkts_coal = value;
+}
+
+/* Trigger tx done timer in MVNETA_TX_DONE_TIMER_PERIOD msecs */
+static void mvneta_add_tx_done_timer(struct mvneta_port *pp)
+{
+       if (test_and_set_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags) == 0) {
+               pp->tx_done_timer.expires = jiffies +
+                       msecs_to_jiffies(MVNETA_TX_DONE_TIMER_PERIOD);
+               add_timer(&pp->tx_done_timer);
+       }
+}
+
+
+/* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
+static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
+                               u32 phys_addr, u32 cookie)
+{
+       rx_desc->buf_cookie = cookie;
+       rx_desc->buf_phys_addr = phys_addr;
+}
+
+/* Decrement sent descriptors counter */
+static void mvneta_txq_sent_desc_dec(struct mvneta_port *pp,
+                                    struct mvneta_tx_queue *txq,
+                                    int sent_desc)
+{
+       u32 val;
+
+       /* Only 255 TX descriptors can be updated at once */
+       while (sent_desc > 0xff) {
+               val = 0xff << MVNETA_TXQ_DEC_SENT_SHIFT;
+               mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+               sent_desc = sent_desc - 0xff;
+       }
+
+       val = sent_desc << MVNETA_TXQ_DEC_SENT_SHIFT;
+       mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+}
+
+/* Get number of TX descriptors already sent by HW */
+static int mvneta_txq_sent_desc_num_get(struct mvneta_port *pp,
+                                       struct mvneta_tx_queue *txq)
+{
+       u32 val;
+       int sent_desc;
+
+       val = mvreg_read(pp, MVNETA_TXQ_STATUS_REG(txq->id));
+       sent_desc = (val & MVNETA_TXQ_SENT_DESC_MASK) >>
+               MVNETA_TXQ_SENT_DESC_SHIFT;
+
+       return sent_desc;
+}
+
+/* Get number of sent descriptors and decrement counter.
+ *  The number of sent descriptors is returned.
+ */
+static int mvneta_txq_sent_desc_proc(struct mvneta_port *pp,
+                                    struct mvneta_tx_queue *txq)
+{
+       int sent_desc;
+
+       /* Get number of sent descriptors */
+       sent_desc = mvneta_txq_sent_desc_num_get(pp, txq);
+
+       /* Decrement sent descriptors counter */
+       if (sent_desc)
+               mvneta_txq_sent_desc_dec(pp, txq, sent_desc);
+
+       return sent_desc;
+}
+
+/* Set TXQ descriptors fields relevant for CSUM calculation */
+static u32 mvneta_txq_desc_csum(int l3_offs, int l3_proto,
+                               int ip_hdr_len, int l4_proto)
+{
+       u32 command;
+
+       /* Fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk,
+        * G_L4_chk, L4_type; required only for checksum
+        * calculation
+        */
+       command =  l3_offs    << MVNETA_TX_L3_OFF_SHIFT;
+       command |= ip_hdr_len << MVNETA_TX_IP_HLEN_SHIFT;
+
+       if (l3_proto == swab16(ETH_P_IP))
+               command |= MVNETA_TXD_IP_CSUM;
+       else
+               command |= MVNETA_TX_L3_IP6;
+
+       if (l4_proto == IPPROTO_TCP)
+               command |=  MVNETA_TX_L4_CSUM_FULL;
+       else if (l4_proto == IPPROTO_UDP)
+               command |= MVNETA_TX_L4_UDP | MVNETA_TX_L4_CSUM_FULL;
+       else
+               command |= MVNETA_TX_L4_CSUM_NOT;
+
+       return command;
+}
+
+
+/* Display more error info */
+static void mvneta_rx_error(struct mvneta_port *pp,
+                           struct mvneta_rx_desc *rx_desc)
+{
+       u32 status = rx_desc->status;
+
+       if (!mvneta_rxq_desc_is_first_last(rx_desc)) {
+               netdev_err(pp->dev,
+                          "bad rx status %08x (buffer oversize), size=%d\n",
+                          rx_desc->status, rx_desc->data_size);
+               return;
+       }
+
+       switch (status & MVNETA_RXD_ERR_CODE_MASK) {
+       case MVNETA_RXD_ERR_CRC:
+               netdev_err(pp->dev, "bad rx status %08x (crc error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       case MVNETA_RXD_ERR_OVERRUN:
+               netdev_err(pp->dev, "bad rx status %08x (overrun error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       case MVNETA_RXD_ERR_LEN:
+               netdev_err(pp->dev, "bad rx status %08x (max frame length error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       case MVNETA_RXD_ERR_RESOURCE:
+               netdev_err(pp->dev, "bad rx status %08x (resource error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       }
+}
+
+/* Handle RX checksum offload */
+static void mvneta_rx_csum(struct mvneta_port *pp,
+                          struct mvneta_rx_desc *rx_desc,
+                          struct sk_buff *skb)
+{
+       if ((rx_desc->status & MVNETA_RXD_L3_IP4) &&
+           (rx_desc->status & MVNETA_RXD_L4_CSUM_OK)) {
+               skb->csum = 0;
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               return;
+       }
+
+       skb->ip_summed = CHECKSUM_NONE;
+}
+
+/* Return tx queue pointer (find last set bit) according to causeTxDone reg */
+static struct mvneta_tx_queue *mvneta_tx_done_policy(struct mvneta_port *pp,
+                                                    u32 cause)
+{
+       int queue = fls(cause) - 1;
+
+       return (queue < 0 || queue >= txq_number) ? NULL : &pp->txqs[queue];
+}
+
+/* Free tx queue skbuffs */
+static void mvneta_txq_bufs_free(struct mvneta_port *pp,
+                                struct mvneta_tx_queue *txq, int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++) {
+               struct mvneta_tx_desc *tx_desc = txq->descs +
+                       txq->txq_get_index;
+               struct sk_buff *skb = txq->tx_skb[txq->txq_get_index];
+
+               mvneta_txq_inc_get(txq);
+
+               if (!skb)
+                       continue;
+
+               dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr,
+                                tx_desc->data_size, DMA_TO_DEVICE);
+               dev_kfree_skb_any(skb);
+       }
+}
+
+/* Handle end of transmission */
+static int mvneta_txq_done(struct mvneta_port *pp,
+                          struct mvneta_tx_queue *txq)
+{
+       struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
+       int tx_done;
+
+       tx_done = mvneta_txq_sent_desc_proc(pp, txq);
+       if (tx_done == 0)
+               return tx_done;
+       mvneta_txq_bufs_free(pp, txq, tx_done);
+
+       txq->count -= tx_done;
+
+       if (netif_tx_queue_stopped(nq)) {
+               if (txq->size - txq->count >= MAX_SKB_FRAGS + 1)
+                       netif_tx_wake_queue(nq);
+       }
+
+       return tx_done;
+}
+
+/* Refill processing */
+static int mvneta_rx_refill(struct mvneta_port *pp,
+                           struct mvneta_rx_desc *rx_desc)
+
+{
+       dma_addr_t phys_addr;
+       struct sk_buff *skb;
+
+       skb = netdev_alloc_skb(pp->dev, pp->pkt_size);
+       if (!skb)
+               return -ENOMEM;
+
+       phys_addr = dma_map_single(pp->dev->dev.parent, skb->head,
+                                  MVNETA_RX_BUF_SIZE(pp->pkt_size),
+                                  DMA_FROM_DEVICE);
+       if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) {
+               dev_kfree_skb(skb);
+               return -ENOMEM;
+       }
+
+       mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb);
+
+       return 0;
+}
+
+/* Handle tx checksum */
+static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
+{
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               int ip_hdr_len = 0;
+               u8 l4_proto;
+
+               if (skb->protocol == htons(ETH_P_IP)) {
+                       struct iphdr *ip4h = ip_hdr(skb);
+
+                       /* Calculate IPv4 checksum and L4 checksum */
+                       ip_hdr_len = ip4h->ihl;
+                       l4_proto = ip4h->protocol;
+               } else if (skb->protocol == htons(ETH_P_IPV6)) {
+                       struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+                       /* Read l4_protocol from one of IPv6 extra headers */
+                       if (skb_network_header_len(skb) > 0)
+                               ip_hdr_len = (skb_network_header_len(skb) >> 2);
+                       l4_proto = ip6h->nexthdr;
+               } else
+                       return MVNETA_TX_L4_CSUM_NOT;
+
+               return mvneta_txq_desc_csum(skb_network_offset(skb),
+                               skb->protocol, ip_hdr_len, l4_proto);
+       }
+
+       return MVNETA_TX_L4_CSUM_NOT;
+}
+
+/* Returns rx queue pointer (find last set bit) according to causeRxTx
+ * value
+ */
+static struct mvneta_rx_queue *mvneta_rx_policy(struct mvneta_port *pp,
+                                               u32 cause)
+{
+       int queue = fls(cause >> 8) - 1;
+
+       return (queue < 0 || queue >= rxq_number) ? NULL : &pp->rxqs[queue];
+}
+
+/* Drop packets received by the RXQ and free buffers */
+static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
+                                struct mvneta_rx_queue *rxq)
+{
+       int rx_done, i;
+
+       rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
+       for (i = 0; i < rxq->size; i++) {
+               struct mvneta_rx_desc *rx_desc = rxq->descs + i;
+               struct sk_buff *skb = (struct sk_buff *)rx_desc->buf_cookie;
+
+               dev_kfree_skb_any(skb);
+               dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+                                rx_desc->data_size, DMA_FROM_DEVICE);
+       }
+
+       if (rx_done)
+               mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
+}
+
+/* Main rx processing */
+static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
+                    struct mvneta_rx_queue *rxq)
+{
+       struct net_device *dev = pp->dev;
+       int rx_done, rx_filled;
+
+       /* Get number of received packets */
+       rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
+
+       if (rx_todo > rx_done)
+               rx_todo = rx_done;
+
+       rx_done = 0;
+       rx_filled = 0;
+
+       /* Fairness NAPI loop */
+       while (rx_done < rx_todo) {
+               struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);
+               struct sk_buff *skb;
+               u32 rx_status;
+               int rx_bytes, err;
+
+               prefetch(rx_desc);
+               rx_done++;
+               rx_filled++;
+               rx_status = rx_desc->status;
+               skb = (struct sk_buff *)rx_desc->buf_cookie;
+
+               if (!mvneta_rxq_desc_is_first_last(rx_desc) ||
+                   (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
+                       dev->stats.rx_errors++;
+                       mvneta_rx_error(pp, rx_desc);
+                       mvneta_rx_desc_fill(rx_desc, rx_desc->buf_phys_addr,
+                                           (u32)skb);
+                       continue;
+               }
+
+               dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+                                rx_desc->data_size, DMA_FROM_DEVICE);
+
+               rx_bytes = rx_desc->data_size -
+                       (ETH_FCS_LEN + MVNETA_MH_SIZE);
+               u64_stats_update_begin(&pp->rx_stats.syncp);
+               pp->rx_stats.packets++;
+               pp->rx_stats.bytes += rx_bytes;
+               u64_stats_update_end(&pp->rx_stats.syncp);
+
+               /* Linux processing */
+               skb_reserve(skb, MVNETA_MH_SIZE);
+               skb_put(skb, rx_bytes);
+
+               skb->protocol = eth_type_trans(skb, dev);
+
+               mvneta_rx_csum(pp, rx_desc, skb);
+
+               napi_gro_receive(&pp->napi, skb);
+
+               /* Refill processing */
+               err = mvneta_rx_refill(pp, rx_desc);
+               if (err) {
+                       netdev_err(pp->dev, "Linux processing - Can't refill\n");
+                       rxq->missed++;
+                       rx_filled--;
+               }
+       }
+
+       /* Update rxq management counters */
+       mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled);
+
+       return rx_done;
+}
+
+/* Handle tx fragmentation processing */
+static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
+                                 struct mvneta_tx_queue *txq)
+{
+       struct mvneta_tx_desc *tx_desc;
+       int i;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+               void *addr = page_address(frag->page.p) + frag->page_offset;
+
+               tx_desc = mvneta_txq_next_desc_get(txq);
+               tx_desc->data_size = frag->size;
+
+               tx_desc->buf_phys_addr =
+                       dma_map_single(pp->dev->dev.parent, addr,
+                                      tx_desc->data_size, DMA_TO_DEVICE);
+
+               if (dma_mapping_error(pp->dev->dev.parent,
+                                     tx_desc->buf_phys_addr)) {
+                       mvneta_txq_desc_put(txq);
+                       goto error;
+               }
+
+               if (i == (skb_shinfo(skb)->nr_frags - 1)) {
+                       /* Last descriptor */
+                       tx_desc->command = MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD;
+
+                       txq->tx_skb[txq->txq_put_index] = skb;
+
+                       mvneta_txq_inc_put(txq);
+               } else {
+                       /* Descriptor in the middle: Not First, Not Last */
+                       tx_desc->command = 0;
+
+                       txq->tx_skb[txq->txq_put_index] = NULL;
+                       mvneta_txq_inc_put(txq);
+               }
+       }
+
+       return 0;
+
+error:
+       /* Release all descriptors that were used to map fragments of
+        * this packet, as well as the corresponding DMA mappings
+        */
+       for (i = i - 1; i >= 0; i--) {
+               tx_desc = txq->descs + i;
+               dma_unmap_single(pp->dev->dev.parent,
+                                tx_desc->buf_phys_addr,
+                                tx_desc->data_size,
+                                DMA_TO_DEVICE);
+               mvneta_txq_desc_put(txq);
+       }
+
+       return -ENOMEM;
+}
+
+/* Main tx processing */
+static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       struct mvneta_tx_queue *txq = &pp->txqs[txq_def];
+       struct mvneta_tx_desc *tx_desc;
+       struct netdev_queue *nq;
+       int frags = 0;
+       u32 tx_cmd;
+
+       if (!netif_running(dev))
+               goto out;
+
+       frags = skb_shinfo(skb)->nr_frags + 1;
+       nq    = netdev_get_tx_queue(dev, txq_def);
+
+       /* Get a descriptor for the first part of the packet */
+       tx_desc = mvneta_txq_next_desc_get(txq);
+
+       tx_cmd = mvneta_skb_tx_csum(pp, skb);
+
+       tx_desc->data_size = skb_headlen(skb);
+
+       tx_desc->buf_phys_addr = dma_map_single(dev->dev.parent, skb->data,
+                                               tx_desc->data_size,
+                                               DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(dev->dev.parent,
+                                      tx_desc->buf_phys_addr))) {
+               mvneta_txq_desc_put(txq);
+               frags = 0;
+               goto out;
+       }
+
+       if (frags == 1) {
+               /* First and Last descriptor */
+               tx_cmd |= MVNETA_TXD_FLZ_DESC;
+               tx_desc->command = tx_cmd;
+               txq->tx_skb[txq->txq_put_index] = skb;
+               mvneta_txq_inc_put(txq);
+       } else {
+               /* First but not Last */
+               tx_cmd |= MVNETA_TXD_F_DESC;
+               txq->tx_skb[txq->txq_put_index] = NULL;
+               mvneta_txq_inc_put(txq);
+               tx_desc->command = tx_cmd;
+               /* Continue with other skb fragments */
+               if (mvneta_tx_frag_process(pp, skb, txq)) {
+                       dma_unmap_single(dev->dev.parent,
+                                        tx_desc->buf_phys_addr,
+                                        tx_desc->data_size,
+                                        DMA_TO_DEVICE);
+                       mvneta_txq_desc_put(txq);
+                       frags = 0;
+                       goto out;
+               }
+       }
+
+       txq->count += frags;
+       mvneta_txq_pend_desc_add(pp, txq, frags);
+
+       if (txq->size - txq->count < MAX_SKB_FRAGS + 1)
+               netif_tx_stop_queue(nq);
+
+out:
+       if (frags > 0) {
+               u64_stats_update_begin(&pp->tx_stats.syncp);
+               pp->tx_stats.packets++;
+               pp->tx_stats.bytes += skb->len;
+               u64_stats_update_end(&pp->tx_stats.syncp);
+
+       } else {
+               dev->stats.tx_dropped++;
+               dev_kfree_skb_any(skb);
+       }
+
+       if (txq->count >= MVNETA_TXDONE_COAL_PKTS)
+               mvneta_txq_done(pp, txq);
+
+       /* If after calling mvneta_txq_done, count equals
+        * frags, we need to set the timer
+        */
+       if (txq->count == frags && frags > 0)
+               mvneta_add_tx_done_timer(pp);
+
+       return NETDEV_TX_OK;
+}
+
+
+/* Free tx resources, when resetting a port */
+static void mvneta_txq_done_force(struct mvneta_port *pp,
+                                 struct mvneta_tx_queue *txq)
+
+{
+       int tx_done = txq->count;
+
+       mvneta_txq_bufs_free(pp, txq, tx_done);
+
+       /* reset txq */
+       txq->count = 0;
+       txq->txq_put_index = 0;
+       txq->txq_get_index = 0;
+}
+
+/* handle tx done - called from tx done timer callback */
+static u32 mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done,
+                             int *tx_todo)
+{
+       struct mvneta_tx_queue *txq;
+       u32 tx_done = 0;
+       struct netdev_queue *nq;
+
+       *tx_todo = 0;
+       while (cause_tx_done != 0) {
+               txq = mvneta_tx_done_policy(pp, cause_tx_done);
+               if (!txq)
+                       break;
+
+               nq = netdev_get_tx_queue(pp->dev, txq->id);
+               __netif_tx_lock(nq, smp_processor_id());
+
+               if (txq->count) {
+                       tx_done += mvneta_txq_done(pp, txq);
+                       *tx_todo += txq->count;
+               }
+
+               __netif_tx_unlock(nq);
+               cause_tx_done &= ~((1 << txq->id));
+       }
+
+       return tx_done;
+}
+
+/* Compute crc8 of the specified address, using a unique algorithm ,
+ * according to hw spec, different than generic crc8 algorithm
+ */
+static int mvneta_addr_crc(unsigned char *addr)
+{
+       int crc = 0;
+       int i;
+
+       for (i = 0; i < ETH_ALEN; i++) {
+               int j;
+
+               crc = (crc ^ addr[i]) << 8;
+               for (j = 7; j >= 0; j--) {
+                       if (crc & (0x100 << j))
+                               crc ^= 0x107 << j;
+               }
+       }
+
+       return crc;
+}
+
+/* This method controls the net device special MAC multicast support.
+ * The Special Multicast Table for MAC addresses supports MAC of the form
+ * 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
+ * The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+ * Table entries in the DA-Filter table. This method set the Special
+ * Multicast Table appropriate entry.
+ */
+static void mvneta_set_special_mcast_addr(struct mvneta_port *pp,
+                                         unsigned char last_byte,
+                                         int queue)
+{
+       unsigned int smc_table_reg;
+       unsigned int tbl_offset;
+       unsigned int reg_offset;
+
+       /* Register offset from SMC table base    */
+       tbl_offset = (last_byte / 4);
+       /* Entry offset within the above reg */
+       reg_offset = last_byte % 4;
+
+       smc_table_reg = mvreg_read(pp, (MVNETA_DA_FILT_SPEC_MCAST
+                                       + tbl_offset * 4));
+
+       if (queue == -1)
+               smc_table_reg &= ~(0xff << (8 * reg_offset));
+       else {
+               smc_table_reg &= ~(0xff << (8 * reg_offset));
+               smc_table_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset));
+       }
+
+       mvreg_write(pp, MVNETA_DA_FILT_SPEC_MCAST + tbl_offset * 4,
+                   smc_table_reg);
+}
+
+/* This method controls the network device Other MAC multicast support.
+ * The Other Multicast Table is used for multicast of another type.
+ * A CRC-8 is used as an index to the Other Multicast Table entries
+ * in the DA-Filter table.
+ * The method gets the CRC-8 value from the calling routine and
+ * sets the Other Multicast Table appropriate entry according to the
+ * specified CRC-8 .
+ */
+static void mvneta_set_other_mcast_addr(struct mvneta_port *pp,
+                                       unsigned char crc8,
+                                       int queue)
+{
+       unsigned int omc_table_reg;
+       unsigned int tbl_offset;
+       unsigned int reg_offset;
+
+       tbl_offset = (crc8 / 4) * 4; /* Register offset from OMC table base */
+       reg_offset = crc8 % 4;       /* Entry offset within the above reg   */
+
+       omc_table_reg = mvreg_read(pp, MVNETA_DA_FILT_OTH_MCAST + tbl_offset);
+
+       if (queue == -1) {
+               /* Clear accepts frame bit at specified Other DA table entry */
+               omc_table_reg &= ~(0xff << (8 * reg_offset));
+       } else {
+               omc_table_reg &= ~(0xff << (8 * reg_offset));
+               omc_table_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset));
+       }
+
+       mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + tbl_offset, omc_table_reg);
+}
+
+/* The network device supports multicast using two tables:
+ *    1) Special Multicast Table for MAC addresses of the form
+ *       0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
+ *       The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+ *       Table entries in the DA-Filter table.
+ *    2) Other Multicast Table for multicast of another type. A CRC-8 value
+ *       is used as an index to the Other Multicast Table entries in the
+ *       DA-Filter table.
+ */
+static int mvneta_mcast_addr_set(struct mvneta_port *pp, unsigned char *p_addr,
+                                int queue)
+{
+       unsigned char crc_result = 0;
+
+       if (memcmp(p_addr, "\x01\x00\x5e\x00\x00", 5) == 0) {
+               mvneta_set_special_mcast_addr(pp, p_addr[5], queue);
+               return 0;
+       }
+
+       crc_result = mvneta_addr_crc(p_addr);
+       if (queue == -1) {
+               if (pp->mcast_count[crc_result] == 0) {
+                       netdev_info(pp->dev, "No valid Mcast for crc8=0x%02x\n",
+                                   crc_result);
+                       return -EINVAL;
+               }
+
+               pp->mcast_count[crc_result]--;
+               if (pp->mcast_count[crc_result] != 0) {
+                       netdev_info(pp->dev,
+                                   "After delete there are %d valid Mcast for crc8=0x%02x\n",
+                                   pp->mcast_count[crc_result], crc_result);
+                       return -EINVAL;
+               }
+       } else
+               pp->mcast_count[crc_result]++;
+
+       mvneta_set_other_mcast_addr(pp, crc_result, queue);
+
+       return 0;
+}
+
+/* Configure Fitering mode of Ethernet port */
+static void mvneta_rx_unicast_promisc_set(struct mvneta_port *pp,
+                                         int is_promisc)
+{
+       u32 port_cfg_reg, val;
+
+       port_cfg_reg = mvreg_read(pp, MVNETA_PORT_CONFIG);
+
+       val = mvreg_read(pp, MVNETA_TYPE_PRIO);
+
+       /* Set / Clear UPM bit in port configuration register */
+       if (is_promisc) {
+               /* Accept all Unicast addresses */
+               port_cfg_reg |= MVNETA_UNI_PROMISC_MODE;
+               val |= MVNETA_FORCE_UNI;
+               mvreg_write(pp, MVNETA_MAC_ADDR_LOW, 0xffff);
+               mvreg_write(pp, MVNETA_MAC_ADDR_HIGH, 0xffffffff);
+       } else {
+               /* Reject all Unicast addresses */
+               port_cfg_reg &= ~MVNETA_UNI_PROMISC_MODE;
+               val &= ~MVNETA_FORCE_UNI;
+       }
+
+       mvreg_write(pp, MVNETA_PORT_CONFIG, port_cfg_reg);
+       mvreg_write(pp, MVNETA_TYPE_PRIO, val);
+}
+
+/* register unicast and multicast addresses */
+static void mvneta_set_rx_mode(struct net_device *dev)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       struct netdev_hw_addr *ha;
+
+       if (dev->flags & IFF_PROMISC) {
+               /* Accept all: Multicast + Unicast */
+               mvneta_rx_unicast_promisc_set(pp, 1);
+               mvneta_set_ucast_table(pp, rxq_def);
+               mvneta_set_special_mcast_table(pp, rxq_def);
+               mvneta_set_other_mcast_table(pp, rxq_def);
+       } else {
+               /* Accept single Unicast */
+               mvneta_rx_unicast_promisc_set(pp, 0);
+               mvneta_set_ucast_table(pp, -1);
+               mvneta_mac_addr_set(pp, dev->dev_addr, rxq_def);
+
+               if (dev->flags & IFF_ALLMULTI) {
+                       /* Accept all multicast */
+                       mvneta_set_special_mcast_table(pp, rxq_def);
+                       mvneta_set_other_mcast_table(pp, rxq_def);
+               } else {
+                       /* Accept only initialized multicast */
+                       mvneta_set_special_mcast_table(pp, -1);
+                       mvneta_set_other_mcast_table(pp, -1);
+
+                       if (!netdev_mc_empty(dev)) {
+                               netdev_for_each_mc_addr(ha, dev) {
+                                       mvneta_mcast_addr_set(pp, ha->addr,
+                                                             rxq_def);
+                               }
+                       }
+               }
+       }
+}
+
+/* Interrupt handling - the callback for request_irq() */
+static irqreturn_t mvneta_isr(int irq, void *dev_id)
+{
+       struct mvneta_port *pp = (struct mvneta_port *)dev_id;
+
+       /* Mask all interrupts */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+
+       napi_schedule(&pp->napi);
+
+       return IRQ_HANDLED;
+}
+
+/* NAPI handler
+ * Bits 0 - 7 of the causeRxTx register indicate that are transmitted
+ * packets on the corresponding TXQ (Bit 0 is for TX queue 1).
+ * Bits 8 -15 of the cause Rx Tx register indicate that are received
+ * packets on the corresponding RXQ (Bit 8 is for RX queue 0).
+ * Each CPU has its own causeRxTx register
+ */
+static int mvneta_poll(struct napi_struct *napi, int budget)
+{
+       int rx_done = 0;
+       u32 cause_rx_tx;
+       unsigned long flags;
+       struct mvneta_port *pp = netdev_priv(napi->dev);
+
+       if (!netif_running(pp->dev)) {
+               napi_complete(napi);
+               return rx_done;
+       }
+
+       /* Read cause register */
+       cause_rx_tx = mvreg_read(pp, MVNETA_INTR_NEW_CAUSE) &
+               MVNETA_RX_INTR_MASK(rxq_number);
+
+       /* For the case where the last mvneta_poll did not process all
+        * RX packets
+        */
+       cause_rx_tx |= pp->cause_rx_tx;
+       if (rxq_number > 1) {
+               while ((cause_rx_tx != 0) && (budget > 0)) {
+                       int count;
+                       struct mvneta_rx_queue *rxq;
+                       /* get rx queue number from cause_rx_tx */
+                       rxq = mvneta_rx_policy(pp, cause_rx_tx);
+                       if (!rxq)
+                               break;
+
+                       /* process the packet in that rx queue */
+                       count = mvneta_rx(pp, budget, rxq);
+                       rx_done += count;
+                       budget -= count;
+                       if (budget > 0) {
+                               /* set off the rx bit of the
+                                * corresponding bit in the cause rx
+                                * tx register, so that next iteration
+                                * will find the next rx queue where
+                                * packets are received on
+                                */
+                               cause_rx_tx &= ~((1 << rxq->id) << 8);
+                       }
+               }
+       } else {
+               rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]);
+               budget -= rx_done;
+       }
+
+       if (budget > 0) {
+               cause_rx_tx = 0;
+               napi_complete(napi);
+               local_irq_save(flags);
+               mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+                           MVNETA_RX_INTR_MASK(rxq_number));
+               local_irq_restore(flags);
+       }
+
+       pp->cause_rx_tx = cause_rx_tx;
+       return rx_done;
+}
+
+/* tx done timer callback */
+static void mvneta_tx_done_timer_callback(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct mvneta_port *pp = netdev_priv(dev);
+       int tx_done = 0, tx_todo = 0;
+
+       if (!netif_running(dev))
+               return ;
+
+       clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags);
+
+       tx_done = mvneta_tx_done_gbe(pp,
+                                    (((1 << txq_number) - 1) &
+                                     MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK),
+                                    &tx_todo);
+       if (tx_todo > 0)
+               mvneta_add_tx_done_timer(pp);
+}
+
+/* Handle rxq fill: allocates rxq skbs; called when initializing a port */
+static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
+                          int num)
+{
+       struct net_device *dev = pp->dev;
+       int i;
+
+       for (i = 0; i < num; i++) {
+               struct sk_buff *skb;
+               struct mvneta_rx_desc *rx_desc;
+               unsigned long phys_addr;
+
+               skb = dev_alloc_skb(pp->pkt_size);
+               if (!skb) {
+                       netdev_err(dev, "%s:rxq %d, %d of %d buffs  filled\n",
+                               __func__, rxq->id, i, num);
+                       break;
+               }
+
+               rx_desc = rxq->descs + i;
+               memset(rx_desc, 0, sizeof(struct mvneta_rx_desc));
+               phys_addr = dma_map_single(dev->dev.parent, skb->head,
+                                          MVNETA_RX_BUF_SIZE(pp->pkt_size),
+                                          DMA_FROM_DEVICE);
+               if (unlikely(dma_mapping_error(dev->dev.parent, phys_addr))) {
+                       dev_kfree_skb(skb);
+                       break;
+               }
+
+               mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb);
+       }
+
+       /* Add this number of RX descriptors as non occupied (ready to
+        * get packets)
+        */
+       mvneta_rxq_non_occup_desc_add(pp, rxq, i);
+
+       return i;
+}
+
+/* Free all packets pending transmit from all TXQs and reset TX port */
+static void mvneta_tx_reset(struct mvneta_port *pp)
+{
+       int queue;
+
+       /* free the skb's in the hal tx ring */
+       for (queue = 0; queue < txq_number; queue++)
+               mvneta_txq_done_force(pp, &pp->txqs[queue]);
+
+       mvreg_write(pp, MVNETA_PORT_TX_RESET, MVNETA_PORT_TX_DMA_RESET);
+       mvreg_write(pp, MVNETA_PORT_TX_RESET, 0);
+}
+
+static void mvneta_rx_reset(struct mvneta_port *pp)
+{
+       mvreg_write(pp, MVNETA_PORT_RX_RESET, MVNETA_PORT_RX_DMA_RESET);
+       mvreg_write(pp, MVNETA_PORT_RX_RESET, 0);
+}
+
+/* Rx/Tx queue initialization/cleanup methods */
+
+/* Create a specified RX queue */
+static int mvneta_rxq_init(struct mvneta_port *pp,
+                          struct mvneta_rx_queue *rxq)
+
+{
+       rxq->size = pp->rx_ring_size;
+
+       /* Allocate memory for RX descriptors */
+       rxq->descs = dma_alloc_coherent(pp->dev->dev.parent,
+                                       rxq->size * MVNETA_DESC_ALIGNED_SIZE,
+                                       &rxq->descs_phys, GFP_KERNEL);
+       if (rxq->descs == NULL) {
+               netdev_err(pp->dev,
+                          "rxq=%d: Can't allocate %d bytes for %d RX descr\n",
+                          rxq->id, rxq->size * MVNETA_DESC_ALIGNED_SIZE,
+                          rxq->size);
+               return -ENOMEM;
+       }
+
+       BUG_ON(rxq->descs !=
+              PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE));
+
+       rxq->last_desc = rxq->size - 1;
+
+       /* Set Rx descriptors queue starting address */
+       mvreg_write(pp, MVNETA_RXQ_BASE_ADDR_REG(rxq->id), rxq->descs_phys);
+       mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size);
+
+       /* Set Offset */
+       mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD);
+
+       /* Set coalescing pkts and time */
+       mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
+       mvneta_rx_time_coal_set(pp, rxq, rxq->time_coal);
+
+       /* Fill RXQ with buffers from RX pool */
+       mvneta_rxq_buf_size_set(pp, rxq, MVNETA_RX_BUF_SIZE(pp->pkt_size));
+       mvneta_rxq_bm_disable(pp, rxq);
+       mvneta_rxq_fill(pp, rxq, rxq->size);
+
+       return 0;
+}
+
+/* Cleanup Rx queue */
+static void mvneta_rxq_deinit(struct mvneta_port *pp,
+                             struct mvneta_rx_queue *rxq)
+{
+       mvneta_rxq_drop_pkts(pp, rxq);
+
+       if (rxq->descs)
+               dma_free_coherent(pp->dev->dev.parent,
+                                 rxq->size * MVNETA_DESC_ALIGNED_SIZE,
+                                 rxq->descs,
+                                 rxq->descs_phys);
+
+       rxq->descs             = NULL;
+       rxq->last_desc         = 0;
+       rxq->next_desc_to_proc = 0;
+       rxq->descs_phys        = 0;
+}
+
+/* Create and initialize a tx queue */
+static int mvneta_txq_init(struct mvneta_port *pp,
+                          struct mvneta_tx_queue *txq)
+{
+       txq->size = pp->tx_ring_size;
+
+       /* Allocate memory for TX descriptors */
+       txq->descs = dma_alloc_coherent(pp->dev->dev.parent,
+                                       txq->size * MVNETA_DESC_ALIGNED_SIZE,
+                                       &txq->descs_phys, GFP_KERNEL);
+       if (txq->descs == NULL) {
+               netdev_err(pp->dev,
+                          "txQ=%d: Can't allocate %d bytes for %d TX descr\n",
+                          txq->id, txq->size * MVNETA_DESC_ALIGNED_SIZE,
+                          txq->size);
+               return -ENOMEM;
+       }
+
+       /* Make sure descriptor address is cache line size aligned  */
+       BUG_ON(txq->descs !=
+              PTR_ALIGN(txq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE));
+
+       txq->last_desc = txq->size - 1;
+
+       /* Set maximum bandwidth for enabled TXQs */
+       mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(txq->id), 0x03ffffff);
+       mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(txq->id), 0x3fffffff);
+
+       /* Set Tx descriptors queue starting address */
+       mvreg_write(pp, MVNETA_TXQ_BASE_ADDR_REG(txq->id), txq->descs_phys);
+       mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), txq->size);
+
+       txq->tx_skb = kmalloc(txq->size * sizeof(*txq->tx_skb), GFP_KERNEL);
+       if (txq->tx_skb == NULL) {
+               dma_free_coherent(pp->dev->dev.parent,
+                                 txq->size * MVNETA_DESC_ALIGNED_SIZE,
+                                 txq->descs, txq->descs_phys);
+               return -ENOMEM;
+       }
+       mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal);
+
+       return 0;
+}
+
+/* Free allocated resources when mvneta_txq_init() fails to allocate memory*/
+static void mvneta_txq_deinit(struct mvneta_port *pp,
+                             struct mvneta_tx_queue *txq)
+{
+       kfree(txq->tx_skb);
+
+       if (txq->descs)
+               dma_free_coherent(pp->dev->dev.parent,
+                                 txq->size * MVNETA_DESC_ALIGNED_SIZE,
+                                 txq->descs, txq->descs_phys);
+
+       txq->descs             = NULL;
+       txq->last_desc         = 0;
+       txq->next_desc_to_proc = 0;
+       txq->descs_phys        = 0;
+
+       /* Set minimum bandwidth for disabled TXQs */
+       mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(txq->id), 0);
+       mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(txq->id), 0);
+
+       /* Set Tx descriptors queue starting address and size */
+       mvreg_write(pp, MVNETA_TXQ_BASE_ADDR_REG(txq->id), 0);
+       mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), 0);
+}
+
+/* Cleanup all Tx queues */
+static void mvneta_cleanup_txqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < txq_number; queue++)
+               mvneta_txq_deinit(pp, &pp->txqs[queue]);
+}
+
+/* Cleanup all Rx queues */
+static void mvneta_cleanup_rxqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < rxq_number; queue++)
+               mvneta_rxq_deinit(pp, &pp->rxqs[queue]);
+}
+
+
+/* Init all Rx queues */
+static int mvneta_setup_rxqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < rxq_number; queue++) {
+               int err = mvneta_rxq_init(pp, &pp->rxqs[queue]);
+               if (err) {
+                       netdev_err(pp->dev, "%s: can't create rxq=%d\n",
+                                  __func__, queue);
+                       mvneta_cleanup_rxqs(pp);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+/* Init all tx queues */
+static int mvneta_setup_txqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < txq_number; queue++) {
+               int err = mvneta_txq_init(pp, &pp->txqs[queue]);
+               if (err) {
+                       netdev_err(pp->dev, "%s: can't create txq=%d\n",
+                                  __func__, queue);
+                       mvneta_cleanup_txqs(pp);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static void mvneta_start_dev(struct mvneta_port *pp)
+{
+       mvneta_max_rx_size_set(pp, pp->pkt_size);
+       mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
+
+       /* start the Rx/Tx activity */
+       mvneta_port_enable(pp);
+
+       /* Enable polling on the port */
+       napi_enable(&pp->napi);
+
+       /* Unmask interrupts */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+                   MVNETA_RX_INTR_MASK(rxq_number));
+
+       phy_start(pp->phy_dev);
+       netif_tx_start_all_queues(pp->dev);
+}
+
+static void mvneta_stop_dev(struct mvneta_port *pp)
+{
+       phy_stop(pp->phy_dev);
+
+       napi_disable(&pp->napi);
+
+       netif_carrier_off(pp->dev);
+
+       mvneta_port_down(pp);
+       netif_tx_stop_all_queues(pp->dev);
+
+       /* Stop the port activity */
+       mvneta_port_disable(pp);
+
+       /* Clear all ethernet port interrupts */
+       mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
+
+       /* Mask all ethernet port interrupts */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+
+       mvneta_tx_reset(pp);
+       mvneta_rx_reset(pp);
+}
+
+/* tx timeout callback - display a message and stop/start the network device */
+static void mvneta_tx_timeout(struct net_device *dev)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       netdev_info(dev, "tx timeout\n");
+       mvneta_stop_dev(pp);
+       mvneta_start_dev(pp);
+}
+
+/* Return positive if MTU is valid */
+static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)
+{
+       if (mtu < 68) {
+               netdev_err(dev, "cannot change mtu to less than 68\n");
+               return -EINVAL;
+       }
+
+       /* 9676 == 9700 - 20 and rounding to 8 */
+       if (mtu > 9676) {
+               netdev_info(dev, "Illegal MTU value %d, round to 9676\n", mtu);
+               mtu = 9676;
+       }
+
+       if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
+               netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
+                       mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
+               mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
+       }
+
+       return mtu;
+}
+
+/* Change the device mtu */
+static int mvneta_change_mtu(struct net_device *dev, int mtu)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       int ret;
+
+       mtu = mvneta_check_mtu_valid(dev, mtu);
+       if (mtu < 0)
+               return -EINVAL;
+
+       dev->mtu = mtu;
+
+       if (!netif_running(dev))
+               return 0;
+
+       /* The interface is running, so we have to force a
+        * reallocation of the RXQs
+        */
+       mvneta_stop_dev(pp);
+
+       mvneta_cleanup_txqs(pp);
+       mvneta_cleanup_rxqs(pp);
+
+       pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu);
+
+       ret = mvneta_setup_rxqs(pp);
+       if (ret) {
+               netdev_err(pp->dev, "unable to setup rxqs after MTU change\n");
+               return ret;
+       }
+
+       mvneta_setup_txqs(pp);
+
+       mvneta_start_dev(pp);
+       mvneta_port_up(pp);
+
+       return 0;
+}
+
+/* Handle setting mac address */
+static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       u8 *mac = addr + 2;
+       int i;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       /* Remove previous address table entry */
+       mvneta_mac_addr_set(pp, dev->dev_addr, -1);
+
+       /* Set new addr in hw */
+       mvneta_mac_addr_set(pp, mac, rxq_def);
+
+       /* Set addr in the device */
+       for (i = 0; i < ETH_ALEN; i++)
+               dev->dev_addr[i] = mac[i];
+
+       return 0;
+}
+
+static void mvneta_adjust_link(struct net_device *ndev)
+{
+       struct mvneta_port *pp = netdev_priv(ndev);
+       struct phy_device *phydev = pp->phy_dev;
+       int status_change = 0;
+
+       if (phydev->link) {
+               if ((pp->speed != phydev->speed) ||
+                   (pp->duplex != phydev->duplex)) {
+                       u32 val;
+
+                       val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+                       val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
+                                MVNETA_GMAC_CONFIG_GMII_SPEED |
+                                MVNETA_GMAC_CONFIG_FULL_DUPLEX);
+
+                       if (phydev->duplex)
+                               val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
+
+                       if (phydev->speed == SPEED_1000)
+                               val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
+                       else
+                               val |= MVNETA_GMAC_CONFIG_MII_SPEED;
+
+                       mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+
+                       pp->duplex = phydev->duplex;
+                       pp->speed  = phydev->speed;
+               }
+       }
+
+       if (phydev->link != pp->link) {
+               if (!phydev->link) {
+                       pp->duplex = -1;
+                       pp->speed = 0;
+               }
+
+               pp->link = phydev->link;
+               status_change = 1;
+       }
+
+       if (status_change) {
+               if (phydev->link) {
+                       u32 val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+                       val |= (MVNETA_GMAC_FORCE_LINK_PASS |
+                               MVNETA_GMAC_FORCE_LINK_DOWN);
+                       mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+                       mvneta_port_up(pp);
+                       netdev_info(pp->dev, "link up\n");
+               } else {
+                       mvneta_port_down(pp);
+                       netdev_info(pp->dev, "link down\n");
+               }
+       }
+}
+
+static int mvneta_mdio_probe(struct mvneta_port *pp)
+{
+       struct phy_device *phy_dev;
+
+       phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0,
+                                pp->phy_interface);
+       if (!phy_dev) {
+               netdev_err(pp->dev, "could not find the PHY\n");
+               return -ENODEV;
+       }
+
+       phy_dev->supported &= PHY_GBIT_FEATURES;
+       phy_dev->advertising = phy_dev->supported;
+
+       pp->phy_dev = phy_dev;
+       pp->link    = 0;
+       pp->duplex  = 0;
+       pp->speed   = 0;
+
+       return 0;
+}
+
+static void mvneta_mdio_remove(struct mvneta_port *pp)
+{
+       phy_disconnect(pp->phy_dev);
+       pp->phy_dev = NULL;
+}
+
+static int mvneta_open(struct net_device *dev)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       int ret;
+
+       mvneta_mac_addr_set(pp, dev->dev_addr, rxq_def);
+
+       pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu);
+
+       ret = mvneta_setup_rxqs(pp);
+       if (ret)
+               return ret;
+
+       ret = mvneta_setup_txqs(pp);
+       if (ret)
+               goto err_cleanup_rxqs;
+
+       /* Connect to port interrupt line */
+       ret = request_irq(pp->dev->irq, mvneta_isr, 0,
+                         MVNETA_DRIVER_NAME, pp);
+       if (ret) {
+               netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq);
+               goto err_cleanup_txqs;
+       }
+
+       /* In default link is down */
+       netif_carrier_off(pp->dev);
+
+       ret = mvneta_mdio_probe(pp);
+       if (ret < 0) {
+               netdev_err(dev, "cannot probe MDIO bus\n");
+               goto err_free_irq;
+       }
+
+       mvneta_start_dev(pp);
+
+       return 0;
+
+err_free_irq:
+       free_irq(pp->dev->irq, pp);
+err_cleanup_txqs:
+       mvneta_cleanup_txqs(pp);
+err_cleanup_rxqs:
+       mvneta_cleanup_rxqs(pp);
+       return ret;
+}
+
+/* Stop the port, free port interrupt line */
+static int mvneta_stop(struct net_device *dev)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       mvneta_stop_dev(pp);
+       mvneta_mdio_remove(pp);
+       free_irq(dev->irq, pp);
+       mvneta_cleanup_rxqs(pp);
+       mvneta_cleanup_txqs(pp);
+       del_timer(&pp->tx_done_timer);
+       clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags);
+
+       return 0;
+}
+
+/* Ethtool methods */
+
+/* Get settings (phy address, speed) for ethtools */
+int mvneta_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       if (!pp->phy_dev)
+               return -ENODEV;
+
+       return phy_ethtool_gset(pp->phy_dev, cmd);
+}
+
+/* Set settings (phy address, speed) for ethtools */
+int mvneta_ethtool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       if (!pp->phy_dev)
+               return -ENODEV;
+
+       return phy_ethtool_sset(pp->phy_dev, cmd);
+}
+
+/* Set interrupt coalescing for ethtools */
+static int mvneta_ethtool_set_coalesce(struct net_device *dev,
+                                      struct ethtool_coalesce *c)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+       int queue;
+
+       for (queue = 0; queue < rxq_number; queue++) {
+               struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
+               rxq->time_coal = c->rx_coalesce_usecs;
+               rxq->pkts_coal = c->rx_max_coalesced_frames;
+               mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
+               mvneta_rx_time_coal_set(pp, rxq, rxq->time_coal);
+       }
+
+       for (queue = 0; queue < txq_number; queue++) {
+               struct mvneta_tx_queue *txq = &pp->txqs[queue];
+               txq->done_pkts_coal = c->tx_max_coalesced_frames;
+               mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal);
+       }
+
+       return 0;
+}
+
+/* get coalescing for ethtools */
+static int mvneta_ethtool_get_coalesce(struct net_device *dev,
+                                      struct ethtool_coalesce *c)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       c->rx_coalesce_usecs        = pp->rxqs[0].time_coal;
+       c->rx_max_coalesced_frames  = pp->rxqs[0].pkts_coal;
+
+       c->tx_max_coalesced_frames =  pp->txqs[0].done_pkts_coal;
+       return 0;
+}
+
+
+static void mvneta_ethtool_get_drvinfo(struct net_device *dev,
+                                   struct ethtool_drvinfo *drvinfo)
+{
+       strlcpy(drvinfo->driver, MVNETA_DRIVER_NAME,
+               sizeof(drvinfo->driver));
+       strlcpy(drvinfo->version, MVNETA_DRIVER_VERSION,
+               sizeof(drvinfo->version));
+       strlcpy(drvinfo->bus_info, dev_name(&dev->dev),
+               sizeof(drvinfo->bus_info));
+}
+
+
+static void mvneta_ethtool_get_ringparam(struct net_device *netdev,
+                                        struct ethtool_ringparam *ring)
+{
+       struct mvneta_port *pp = netdev_priv(netdev);
+
+       ring->rx_max_pending = MVNETA_MAX_RXD;
+       ring->tx_max_pending = MVNETA_MAX_TXD;
+       ring->rx_pending = pp->rx_ring_size;
+       ring->tx_pending = pp->tx_ring_size;
+}
+
+static int mvneta_ethtool_set_ringparam(struct net_device *dev,
+                                       struct ethtool_ringparam *ring)
+{
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       if ((ring->rx_pending == 0) || (ring->tx_pending == 0))
+               return -EINVAL;
+       pp->rx_ring_size = ring->rx_pending < MVNETA_MAX_RXD ?
+               ring->rx_pending : MVNETA_MAX_RXD;
+       pp->tx_ring_size = ring->tx_pending < MVNETA_MAX_TXD ?
+               ring->tx_pending : MVNETA_MAX_TXD;
+
+       if (netif_running(dev)) {
+               mvneta_stop(dev);
+               if (mvneta_open(dev)) {
+                       netdev_err(dev,
+                                  "error on opening device after ring param change\n");
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+static const struct net_device_ops mvneta_netdev_ops = {
+       .ndo_open            = mvneta_open,
+       .ndo_stop            = mvneta_stop,
+       .ndo_start_xmit      = mvneta_tx,
+       .ndo_set_rx_mode     = mvneta_set_rx_mode,
+       .ndo_set_mac_address = mvneta_set_mac_addr,
+       .ndo_change_mtu      = mvneta_change_mtu,
+       .ndo_tx_timeout      = mvneta_tx_timeout,
+       .ndo_get_stats64     = mvneta_get_stats64,
+};
+
+const struct ethtool_ops mvneta_eth_tool_ops = {
+       .get_link       = ethtool_op_get_link,
+       .get_settings   = mvneta_ethtool_get_settings,
+       .set_settings   = mvneta_ethtool_set_settings,
+       .set_coalesce   = mvneta_ethtool_set_coalesce,
+       .get_coalesce   = mvneta_ethtool_get_coalesce,
+       .get_drvinfo    = mvneta_ethtool_get_drvinfo,
+       .get_ringparam  = mvneta_ethtool_get_ringparam,
+       .set_ringparam  = mvneta_ethtool_set_ringparam,
+};
+
+/* Initialize hw */
+static int __devinit mvneta_init(struct mvneta_port *pp, int phy_addr)
+{
+       int queue;
+
+       /* Disable port */
+       mvneta_port_disable(pp);
+
+       /* Set port default values */
+       mvneta_defaults_set(pp);
+
+       pp->txqs = kzalloc(txq_number * sizeof(struct mvneta_tx_queue),
+                          GFP_KERNEL);
+       if (!pp->txqs)
+               return -ENOMEM;
+
+       /* Initialize TX descriptor rings */
+       for (queue = 0; queue < txq_number; queue++) {
+               struct mvneta_tx_queue *txq = &pp->txqs[queue];
+               txq->id = queue;
+               txq->size = pp->tx_ring_size;
+               txq->done_pkts_coal = MVNETA_TXDONE_COAL_PKTS;
+       }
+
+       pp->rxqs = kzalloc(rxq_number * sizeof(struct mvneta_rx_queue),
+                          GFP_KERNEL);
+       if (!pp->rxqs) {
+               kfree(pp->txqs);
+               return -ENOMEM;
+       }
+
+       /* Create Rx descriptor rings */
+       for (queue = 0; queue < rxq_number; queue++) {
+               struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
+               rxq->id = queue;
+               rxq->size = pp->rx_ring_size;
+               rxq->pkts_coal = MVNETA_RX_COAL_PKTS;
+               rxq->time_coal = MVNETA_RX_COAL_USEC;
+       }
+
+       return 0;
+}
+
+static void mvneta_deinit(struct mvneta_port *pp)
+{
+       kfree(pp->txqs);
+       kfree(pp->rxqs);
+}
+
+/* platform glue : initialize decoding windows */
+static void __devinit
+mvneta_conf_mbus_windows(struct mvneta_port *pp,
+                        const struct mbus_dram_target_info *dram)
+{
+       u32 win_enable;
+       u32 win_protect;
+       int i;
+
+       for (i = 0; i < 6; i++) {
+               mvreg_write(pp, MVNETA_WIN_BASE(i), 0);
+               mvreg_write(pp, MVNETA_WIN_SIZE(i), 0);
+
+               if (i < 4)
+                       mvreg_write(pp, MVNETA_WIN_REMAP(i), 0);
+       }
+
+       win_enable = 0x3f;
+       win_protect = 0;
+
+       for (i = 0; i < dram->num_cs; i++) {
+               const struct mbus_dram_window *cs = dram->cs + i;
+               mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) |
+                           (cs->mbus_attr << 8) | dram->mbus_dram_target_id);
+
+               mvreg_write(pp, MVNETA_WIN_SIZE(i),
+                           (cs->size - 1) & 0xffff0000);
+
+               win_enable &= ~(1 << i);
+               win_protect |= 3 << (2 * i);
+       }
+
+       mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable);
+}
+
+/* Power up the port */
+static void __devinit mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
+{
+       u32 val;
+
+       /* MAC Cause register should be cleared */
+       mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
+
+       if (phy_mode == PHY_INTERFACE_MODE_SGMII)
+               mvneta_port_sgmii_config(pp);
+
+       mvneta_gmac_rgmii_set(pp, 1);
+
+       /* Cancel Port Reset */
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+       val &= ~MVNETA_GMAC2_PORT_RESET;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+
+       while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) &
+               MVNETA_GMAC2_PORT_RESET) != 0)
+               continue;
+}
+
+/* Device initialization routine */
+static int __devinit mvneta_probe(struct platform_device *pdev)
+{
+       const struct mbus_dram_target_info *dram_target_info;
+       struct device_node *dn = pdev->dev.of_node;
+       struct device_node *phy_node;
+       u32 phy_addr;
+       struct mvneta_port *pp;
+       struct net_device *dev;
+       const char *mac_addr;
+       int phy_mode;
+       int err;
+
+       /* Our multiqueue support is not complete, so for now, only
+        * allow the usage of the first RX queue
+        */
+       if (rxq_def != 0) {
+               dev_err(&pdev->dev, "Invalid rxq_def argument: %d\n", rxq_def);
+               return -EINVAL;
+       }
+
+       dev = alloc_etherdev_mq(sizeof(struct mvneta_port), 8);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->irq = irq_of_parse_and_map(dn, 0);
+       if (dev->irq == 0) {
+               err = -EINVAL;
+               goto err_free_netdev;
+       }
+
+       phy_node = of_parse_phandle(dn, "phy", 0);
+       if (!phy_node) {
+               dev_err(&pdev->dev, "no associated PHY\n");
+               err = -ENODEV;
+               goto err_free_irq;
+       }
+
+       phy_mode = of_get_phy_mode(dn);
+       if (phy_mode < 0) {
+               dev_err(&pdev->dev, "incorrect phy-mode\n");
+               err = -EINVAL;
+               goto err_free_irq;
+       }
+
+       mac_addr = of_get_mac_address(dn);
+
+       if (!mac_addr || !is_valid_ether_addr(mac_addr))
+               eth_hw_addr_random(dev);
+       else
+               memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+
+       dev->tx_queue_len = MVNETA_MAX_TXD;
+       dev->watchdog_timeo = 5 * HZ;
+       dev->netdev_ops = &mvneta_netdev_ops;
+
+       SET_ETHTOOL_OPS(dev, &mvneta_eth_tool_ops);
+
+       pp = netdev_priv(dev);
+
+       pp->tx_done_timer.function = mvneta_tx_done_timer_callback;
+       init_timer(&pp->tx_done_timer);
+       clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags);
+
+       pp->weight = MVNETA_RX_POLL_WEIGHT;
+       pp->phy_node = phy_node;
+       pp->phy_interface = phy_mode;
+
+       pp->base = of_iomap(dn, 0);
+       if (pp->base == NULL) {
+               err = -ENOMEM;
+               goto err_free_irq;
+       }
+
+       pp->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(pp->clk)) {
+               err = PTR_ERR(pp->clk);
+               goto err_unmap;
+       }
+
+       clk_prepare_enable(pp->clk);
+
+       pp->tx_done_timer.data = (unsigned long)dev;
+
+       pp->tx_ring_size = MVNETA_MAX_TXD;
+       pp->rx_ring_size = MVNETA_MAX_RXD;
+
+       pp->dev = dev;
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       err = mvneta_init(pp, phy_addr);
+       if (err < 0) {
+               dev_err(&pdev->dev, "can't init eth hal\n");
+               goto err_clk;
+       }
+       mvneta_port_power_up(pp, phy_mode);
+
+       dram_target_info = mv_mbus_dram_info();
+       if (dram_target_info)
+               mvneta_conf_mbus_windows(pp, dram_target_info);
+
+       netif_napi_add(dev, &pp->napi, mvneta_poll, pp->weight);
+
+       err = register_netdev(dev);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to register\n");
+               goto err_deinit;
+       }
+
+       dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
+       dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM;
+       dev->priv_flags |= IFF_UNICAST_FLT;
+
+       netdev_info(dev, "mac: %pM\n", dev->dev_addr);
+
+       platform_set_drvdata(pdev, pp->dev);
+
+       return 0;
+
+err_deinit:
+       mvneta_deinit(pp);
+err_clk:
+       clk_disable_unprepare(pp->clk);
+err_unmap:
+       iounmap(pp->base);
+err_free_irq:
+       irq_dispose_mapping(dev->irq);
+err_free_netdev:
+       free_netdev(dev);
+       return err;
+}
+
+/* Device removal routine */
+static int __devexit mvneta_remove(struct platform_device *pdev)
+{
+       struct net_device  *dev = platform_get_drvdata(pdev);
+       struct mvneta_port *pp = netdev_priv(dev);
+
+       unregister_netdev(dev);
+       mvneta_deinit(pp);
+       clk_disable_unprepare(pp->clk);
+       iounmap(pp->base);
+       irq_dispose_mapping(dev->irq);
+       free_netdev(dev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static const struct of_device_id mvneta_match[] = {
+       { .compatible = "marvell,armada-370-neta" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mvneta_match);
+
+static struct platform_driver mvneta_driver = {
+       .probe = mvneta_probe,
+       .remove = __devexit_p(mvneta_remove),
+       .driver = {
+               .name = MVNETA_DRIVER_NAME,
+               .of_match_table = mvneta_match,
+       },
+};
+
+module_platform_driver(mvneta_driver);
+
+MODULE_DESCRIPTION("Marvell NETA Ethernet Driver - www.marvell.com");
+MODULE_AUTHOR("Rami Rosen <rosenr@marvell.com>, Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_LICENSE("GPL");
+
+module_param(rxq_number, int, S_IRUGO);
+module_param(txq_number, int, S_IRUGO);
+
+module_param(rxq_def, int, S_IRUGO);
+module_param(txq_def, int, S_IRUGO);
index 3d1899ff1076e753cfa5a07f7f199a4f01904b2e..fdc5f23d8e9f26ae9a0fe30638a4359cb22eafa3 100644 (file)
@@ -1498,6 +1498,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
        u32 reply;
        u8 is_going_down = 0;
        int i;
+       unsigned long flags;
 
        slave_state[slave].comm_toggle ^= 1;
        reply = (u32) slave_state[slave].comm_toggle << 31;
@@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
                mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave);
                goto reset_slave;
        }
-       spin_lock(&priv->mfunc.master.slave_state_lock);
+       spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
        if (!slave_state[slave].is_slave_going_down)
                slave_state[slave].last_cmd = cmd;
        else
                is_going_down = 1;
-       spin_unlock(&priv->mfunc.master.slave_state_lock);
+       spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
        if (is_going_down) {
                mlx4_warn(dev, "Slave is going down aborting command(%d)"
                          " executing from slave:%d\n",
@@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
 reset_slave:
        /* cleanup any slave resources */
        mlx4_delete_all_resources_for_slave(dev, slave);
-       spin_lock(&priv->mfunc.master.slave_state_lock);
+       spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
        if (!slave_state[slave].is_slave_going_down)
                slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET;
-       spin_unlock(&priv->mfunc.master.slave_state_lock);
+       spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
        /*with slave in the middle of flr, no need to clean resources again.*/
 inform_slave_state:
        memset(&slave_state[slave].event_eq, 0,
@@ -1755,7 +1756,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                        spin_lock_init(&s_state->lock);
                }
 
-               memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
+               memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
                priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
                INIT_WORK(&priv->mfunc.master.comm_work,
                          mlx4_master_comm_channel);
index aa9c2f6cf3c0e6afd6243aa6d50b4f15de1af474..b8d0854a7ad1e1a3d77d39dc883cb806a3b071c9 100644 (file)
@@ -51,7 +51,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
        int err;
 
        cq->size = entries;
-       cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
+       cq->buf_size = cq->size * mdev->dev->caps.cqe_size;
 
        cq->ring = ring;
        cq->is_tx = mode;
index 7d1287f81a31037ef3bc1bd9802500ca3ffcc629..75a3f467bb5be601494653a8406eaf5780e52d5b 100644 (file)
@@ -1604,6 +1604,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                goto out;
        }
        priv->rx_ring_num = prof->rx_ring_num;
+       priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
        priv->mac_index = -1;
        priv->msg_enable = MLX4_EN_MSG_LEVEL;
        spin_lock_init(&priv->stats_lock);
index f76c9671f3628c22bbb1280316b8f4eb57c71c3e..fed26d867f4e3f6bc1452bfcd3ab1136a48c8628 100644 (file)
@@ -566,6 +566,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
        struct ethhdr *ethh;
        dma_addr_t dma;
        u64 s_mac;
+       int factor = priv->cqe_factor;
 
        if (!priv->port_up)
                return 0;
@@ -574,7 +575,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
         * descriptor offset can be deduced from the CQE index instead of
         * reading 'cqe->index' */
        index = cq->mcq.cons_index & ring->size_mask;
-       cqe = &cq->buf[index];
+       cqe = &cq->buf[(index << factor) + factor];
 
        /* Process all completed CQEs */
        while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
@@ -709,7 +710,7 @@ next:
 
                ++cq->mcq.cons_index;
                index = (cq->mcq.cons_index) & ring->size_mask;
-               cqe = &cq->buf[index];
+               cqe = &cq->buf[(index << factor) + factor];
                if (++polled == budget)
                        goto out;
        }
index 1f571d009155de6f96335179a744f5c695b8e20e..2b799f4f1c37100f06eab93aef628d4124182230 100644 (file)
@@ -315,12 +315,13 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
        struct mlx4_cqe *buf = cq->buf;
        u32 packets = 0;
        u32 bytes = 0;
+       int factor = priv->cqe_factor;
 
        if (!priv->port_up)
                return;
 
        index = cons_index & size_mask;
-       cqe = &buf[index];
+       cqe = &buf[(index << factor) + factor];
        ring_index = ring->cons & size_mask;
 
        /* Process all completed CQEs */
@@ -349,7 +350,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 
                ++cons_index;
                index = cons_index & size_mask;
-               cqe = &buf[index];
+               cqe = &buf[(index << factor) + factor];
        }
 
 
index b84a88bc44dc2a5e7391ca7bc7116344dd63a97f..251ae2f9311680cb69eaada07cf3ad8a3cf58354 100644 (file)
@@ -101,15 +101,21 @@ static void eq_set_ci(struct mlx4_eq *eq, int req_not)
        mb();
 }
 
-static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry)
+static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor)
 {
-       unsigned long off = (entry & (eq->nent - 1)) * MLX4_EQ_ENTRY_SIZE;
-       return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE;
+       /* (entry & (eq->nent - 1)) gives us a cyclic array */
+       unsigned long offset = (entry & (eq->nent - 1)) * (MLX4_EQ_ENTRY_SIZE << eqe_factor);
+       /* CX3 is capable of extending the EQE from 32 to 64 bytes.
+        * When this feature is enabled, the first (in the lower addresses)
+        * 32 bytes in the 64 byte EQE are reserved and the next 32 bytes
+        * contain the legacy EQE information.
+        */
+       return eq->page_list[offset / PAGE_SIZE].buf + (offset + (eqe_factor ? MLX4_EQ_ENTRY_SIZE : 0)) % PAGE_SIZE;
 }
 
-static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq)
+static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq, u8 eqe_factor)
 {
-       struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index);
+       struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index, eqe_factor);
        return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe;
 }
 
@@ -177,7 +183,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
                return;
        }
 
-       memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
+       memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
        s_eqe->slave_id = slave;
        /* ensure all information is written before setting the ownersip bit */
        wmb();
@@ -401,6 +407,7 @@ void mlx4_master_handle_slave_flr(struct work_struct *work)
        struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
        int i;
        int err;
+       unsigned long flags;
 
        mlx4_dbg(dev, "mlx4_handle_slave_flr\n");
 
@@ -412,10 +419,10 @@ void mlx4_master_handle_slave_flr(struct work_struct *work)
 
                        mlx4_delete_all_resources_for_slave(dev, i);
                        /*return the slave to running mode*/
-                       spin_lock(&priv->mfunc.master.slave_state_lock);
+                       spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
                        slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
                        slave_state[i].is_slave_going_down = 0;
-                       spin_unlock(&priv->mfunc.master.slave_state_lock);
+                       spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
                        /*notify the FW:*/
                        err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE,
                                       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
@@ -440,8 +447,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
        u8 update_slave_state;
        int i;
        enum slave_port_gen_event gen_event;
+       unsigned long flags;
 
-       while ((eqe = next_eqe_sw(eq))) {
+       while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) {
                /*
                 * Make sure we read EQ entry contents after we've
                 * checked the ownership bit.
@@ -647,13 +655,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
                        } else
                                update_slave_state = 1;
 
-                       spin_lock(&priv->mfunc.master.slave_state_lock);
+                       spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
                        if (update_slave_state) {
                                priv->mfunc.master.slave_state[flr_slave].active = false;
                                priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR;
                                priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1;
                        }
-                       spin_unlock(&priv->mfunc.master.slave_state_lock);
+                       spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
                        queue_work(priv->mfunc.master.comm_wq,
                                   &priv->mfunc.master.slave_flr_event_work);
                        break;
@@ -864,7 +872,8 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
 
        eq->dev   = dev;
        eq->nent  = roundup_pow_of_two(max(nent, 2));
-       npages = PAGE_ALIGN(eq->nent * MLX4_EQ_ENTRY_SIZE) / PAGE_SIZE;
+       /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */
+       npages = PAGE_ALIGN(eq->nent * (MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor)) / PAGE_SIZE;
 
        eq->page_list = kmalloc(npages * sizeof *eq->page_list,
                                GFP_KERNEL);
@@ -966,8 +975,9 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cmd_mailbox *mailbox;
        int err;
-       int npages = PAGE_ALIGN(MLX4_EQ_ENTRY_SIZE * eq->nent) / PAGE_SIZE;
        int i;
+       /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */
+       int npages = PAGE_ALIGN((MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor) * eq->nent) / PAGE_SIZE;
 
        mailbox = mlx4_alloc_cmd_mailbox(dev);
        if (IS_ERR(mailbox))
@@ -1267,7 +1277,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
                /* Temporary use polling for command completions */
                mlx4_cmd_use_polling(dev);
 
-               /* Map the new eq to handle all asyncronous events */
+               /* Map the new eq to handle all asynchronous events */
                err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
                                  priv->eq_table.eq[i].eqn);
                if (err) {
index 4f30b99324cf196a46e4c09aed191adfc6323a9e..9a9de51ecc91f72f1ea309385744ed21319fa6bf 100644 (file)
@@ -110,6 +110,8 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
                [42] = "Multicast VEP steering support",
                [48] = "Counters support",
                [59] = "Port management change event support",
+               [61] = "64 byte EQE support",
+               [62] = "64 byte CQE support",
        };
        int i;
 
@@ -235,7 +237,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
                field = dev->caps.num_ports;
                MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
 
-               size = 0; /* no PF behaviour is set for now */
+               size = dev->caps.function_caps; /* set PF behaviours */
                MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
 
                field = 0; /* protected FMR support not available as yet */
@@ -1237,6 +1239,24 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
        if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
                *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
 
+       /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
+       if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) {
+               *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29);
+               dev->caps.eqe_size   = 64;
+               dev->caps.eqe_factor = 1;
+       } else {
+               dev->caps.eqe_size   = 32;
+               dev->caps.eqe_factor = 0;
+       }
+
+       if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) {
+               *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30);
+               dev->caps.cqe_size   = 64;
+               dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE;
+       } else {
+               dev->caps.cqe_size   = 32;
+       }
+
        /* QPC/EEC/CQC/EQC/RDMARC attributes */
 
        MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
@@ -1319,6 +1339,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        struct mlx4_cmd_mailbox *mailbox;
        __be32 *outbox;
        int err;
+       u8 byte_field;
 
 #define QUERY_HCA_GLOBAL_CAPS_OFFSET   0x04
 
@@ -1370,6 +1391,13 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
                         INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
        }
 
+       /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
+       MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS);
+       if (byte_field & 0x20) /* 64-bytes eqe enabled */
+               param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED;
+       if (byte_field & 0x40) /* 64-bytes cqe enabled */
+               param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED;
+
        /* TPT attributes */
 
        MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
index 85abe9c11a2262e199682f33f6ec77ac92062624..2c2e7ade2a34c2912dab6ac92acc4ef90d3d675e 100644 (file)
@@ -172,6 +172,7 @@ struct mlx4_init_hca_param {
        u8  log_uar_sz;
        u8  uar_page_sz; /* log pg sz in 4k chunks */
        u8  fs_hash_enable_bits;
+       u64 dev_cap_enabled;
 };
 
 struct mlx4_init_ib_param {
index 200cc0ec805226506623a90e501f0db527a1dd41..b2acbe7706a34c667d20ca4a58e7057e4c0866b0 100644 (file)
@@ -95,8 +95,14 @@ MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
                                         " Not in use with device managed"
                                         " flow steering");
 
+static bool enable_64b_cqe_eqe;
+module_param(enable_64b_cqe_eqe, bool, 0444);
+MODULE_PARM_DESC(enable_64b_cqe_eqe,
+                "Enable 64 byte CQEs/EQEs when the the FW supports this");
+
 #define HCA_GLOBAL_CAP_MASK            0
-#define PF_CONTEXT_BEHAVIOUR_MASK      0
+
+#define PF_CONTEXT_BEHAVIOUR_MASK      MLX4_FUNC_CAP_64B_EQE_CQE
 
 static char mlx4_version[] =
        DRV_NAME ": Mellanox ConnectX core driver v"
@@ -386,6 +392,21 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH];
 
        dev->caps.sqp_demux = (mlx4_is_master(dev)) ? MLX4_MAX_NUM_SLAVES : 0;
+
+       if (!enable_64b_cqe_eqe) {
+               if (dev_cap->flags &
+                   (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) {
+                       mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n");
+                       dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE;
+                       dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE;
+               }
+       }
+
+       if ((dev_cap->flags &
+           (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&
+           mlx4_is_master(dev))
+               dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE;
+
        return 0;
 }
 /*The function checks if there are live vf, return the num of them*/
@@ -599,6 +620,21 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                goto err_mem;
        }
 
+       if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_EQE_ENABLED) {
+               dev->caps.eqe_size   = 64;
+               dev->caps.eqe_factor = 1;
+       } else {
+               dev->caps.eqe_size   = 32;
+               dev->caps.eqe_factor = 0;
+       }
+
+       if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) {
+               dev->caps.cqe_size   = 64;
+               dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE;
+       } else {
+               dev->caps.cqe_size   = 32;
+       }
+
        return 0;
 
 err_mem:
index 334ec483480ba657da74487a03c15c2f011f1257..8d54412ada63ca97093f14c97aff85fa47879254 100644 (file)
@@ -473,6 +473,7 @@ struct mlx4_en_priv {
        int mac_index;
        unsigned max_mtu;
        int base_qpn;
+       int cqe_factor;
 
        struct mlx4_en_rss_map rss_map;
        __be32 ctrl_flags;
index 093d594435e136db52fff20587d64f23e92df569..83f0ea929d3d90971aa9aea7ad5730778ab1276d 100644 (file)
@@ -6769,7 +6769,7 @@ static int stp;
 /*
  * This enables fast aging in the KSZ8842 switch.  Not sure what situation
  * needs that.  However, fast aging is used to flush the dynamic MAC table when
- * STP suport is enabled.
+ * STP support is enabled.
  */
 static int fast_aging;
 
index 7ec4b864a5508d64dc02613ece2f00384014b322..75ec5e7cf50d454f7868142d9f7c6233da0b8461 100644 (file)
@@ -27,7 +27,7 @@ struct mcp_gen_header {
         *
         * Fields below this comment are extensions added in later versions
         * of this struct, drivers should compare the header_length against
-        * offsetof(field) to check wether a given MCP implements them.
+        * offsetof(field) to check whether a given MCP implements them.
         *
         * Never remove any field.  Keep everything naturally align.
         */
index 58f13adaa5490793ebb01be90b38482ee92ec53b..ae7cd7f3656d04174b74ae534814029795217f18 100644 (file)
@@ -608,7 +608,7 @@ static int bcm5421_poll_link(struct mii_phy* phy)
        if ( mode == BCM54XX_COPPER)
                return genmii_poll_link(phy);
 
-       /* try to find out wether we have a link */
+       /* try to find out whether we have a link */
        phy_write(phy, MII_NCONFIG, 0x2000);
        phy_reg = phy_read(phy, MII_NCONFIG);
 
@@ -634,7 +634,7 @@ static int bcm5421_read_link(struct mii_phy* phy)
 
        phy->speed = SPEED_1000;
 
-       /* find out wether we are running half- or full duplex */
+       /* find out whether we are running half- or full duplex */
        phy_write(phy, MII_NCONFIG, 0x2000);
        phy_reg = phy_read(phy, MII_NCONFIG);
 
@@ -681,7 +681,7 @@ static int bcm5461_poll_link(struct mii_phy* phy)
        if ( mode == BCM54XX_COPPER)
                return genmii_poll_link(phy);
 
-       /* find out wether we have a link */
+       /* find out whether we have a link */
        phy_write(phy, MII_NCONFIG, 0x7000);
        phy_reg = phy_read(phy, MII_NCONFIG);
 
@@ -710,7 +710,7 @@ static int bcm5461_read_link(struct mii_phy* phy)
 
        phy->speed = SPEED_1000;
 
-       /* find out wether we are running half- or full duplex */
+       /* find out whether we are running half- or full duplex */
        phy_write(phy, MII_NCONFIG, 0x7000);
        phy_reg = phy_read(phy, MII_NCONFIG);
 
index 2ac2164a1e39bd70b0a046ee6dc7df05b76e1045..40b426edc9e6cbab7babc20ee4cb7a9dd2f0bbc6 100644 (file)
@@ -297,13 +297,12 @@ static void tun_flow_cleanup(unsigned long data)
        spin_unlock_bh(&tun->lock);
 }
 
-static void tun_flow_update(struct tun_struct *tun, struct sk_buff *skb,
+static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
                            u16 queue_index)
 {
        struct hlist_head *head;
        struct tun_flow_entry *e;
        unsigned long delay = tun->ageing_time;
-       u32 rxhash = skb_get_rxhash(skb);
 
        if (!rxhash)
                return;
@@ -1010,6 +1009,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        int copylen;
        bool zerocopy = false;
        int err;
+       u32 rxhash;
 
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) > total_len)
@@ -1162,12 +1162,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
        }
 
+       rxhash = skb_get_rxhash(skb);
        netif_rx_ni(skb);
 
        tun->dev->stats.rx_packets++;
        tun->dev->stats.rx_bytes += len;
 
-       tun_flow_update(tun, skb, tfile->queue_index);
+       tun_flow_update(tun, rxhash, tfile->queue_index);
        return total_len;
 }
 
index 4b66ab1d0e5cf8f9e0fb9511c145e0049585172f..6702da838b0ebc7b434267b18d595d696cc03799 100644 (file)
@@ -209,6 +209,7 @@ int debugfs_i2400m_reset_set(void *data, u64 val)
                result = i2400m_reset(i2400m, rt);
                if (result >= 0)
                        result = 0;
+               break;
        default:
                result = -EINVAL;
        }
index 8e9b826f878b423aa1ba0b587c926cf21da68b1e..7ae73fbd91361092f1a0590be0cbc2e2b0ecc9a4 100644 (file)
@@ -114,23 +114,23 @@ static void ath_pci_aspm_init(struct ath_common *common)
 
        if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
            (AR_SREV_9285(ah))) {
-               /* Bluetooth coexistance requires disabling ASPM. */
+               /* Bluetooth coexistence requires disabling ASPM. */
                pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
-                       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+                       PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
 
                /*
                 * Both upstream and downstream PCIe components should
                 * have the same ASPM settings.
                 */
                pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
-                       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+                       PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);
 
                ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
                return;
        }
 
        pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
-       if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+       if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
                ah->aspm_enabled = true;
                /* Initialize PCIe PM and SERDES registers. */
                ath9k_hw_configpcipowersave(ah, false);
index 4a4e98f7180777c97b9a9cc0ec10fcdc97a46c83..4374079dfc2a031d6faa0a2819c69e1b9c49885f 100644 (file)
@@ -2963,7 +2963,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
        ssid_el_p[1] = priv->SSID_size;
        memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
        ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
-       ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
+       ssid_el_p[3 + priv->SSID_size] = 4; /* len of supported rates */
        memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
 
        atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
index 9731252424900e0e5e080ced9c33d2a5ee9a82fe..5fe17cbab1f313c7095595fa0d8a0d31b1435e56 100644 (file)
@@ -1045,7 +1045,7 @@ typedef enum _ORDINAL_TABLE_1 {   // NS - means Not Supported by FW
        IPW_ORD_POWER_MGMT_MODE,        // Power mode - 0=CAM, 1=PSP
        IPW_ORD_POWER_MGMT_INDEX,       //NS //
        IPW_ORD_COUNTRY_CODE,   // IEEE country code as recv'd from beacon
-       IPW_ORD_COUNTRY_CHANNELS,       // channels suported by country
+       IPW_ORD_COUNTRY_CHANNELS,       // channels supported by country
 // IPW_ORD_COUNTRY_CHANNELS:
 // For 11b the lower 2-byte are used for channels from 1-14
 //   and the higher 2-byte are not used.
index 2d092f328547d8ca37dfef233a4619c23f7b5aa4..1b15b0b2292b4fe06c3fa1efcc95279c9901370e 100644 (file)
@@ -917,10 +917,6 @@ struct il4965_scd_bc_tbl {
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT  0x041
 
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
-
 #define IL4965_DEFAULT_TX_RETRY  15
 
 /* EEPROM */
index 318ed3c9fe7499899d08fc3de1de917438690109..7e16d10a7f140e4bc0a1414af1ec317f7284b9c6 100644 (file)
@@ -1183,9 +1183,10 @@ EXPORT_SYMBOL(il_power_update_mode);
 void
 il_power_initialize(struct il_priv *il)
 {
-       u16 lctl = il_pcie_link_ctl(il);
+       u16 lctl;
 
-       il->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+       pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
+       il->power_data.pci_pm = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
 
        il->power_data.debug_sleep_level_override = -1;
 
@@ -4233,9 +4234,8 @@ il_apm_init(struct il_priv *il)
         *    power savings, even without L1.
         */
        if (il->cfg->set_l0s) {
-               lctl = il_pcie_link_ctl(il);
-               if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                   PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+               pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
+               if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
                        /* L1-ASPM enabled; disable(!) L0S  */
                        il_set_bit(il, CSR_GIO_REG,
                                   CSR_GIO_REG_VAL_L0S_ENABLED);
index e254cba4557adbf12d6f3e7e0534b3c36c73c2d4..a9a569f432fb3517d5421ea1c4d43cdd96a4d816 100644 (file)
@@ -1829,14 +1829,6 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd);
  * PCI                                              *
  *****************************************************/
 
-static inline u16
-il_pcie_link_ctl(struct il_priv *il)
-{
-       u16 pci_lnk_ctl;
-       pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &pci_lnk_ctl);
-       return pci_lnk_ctl;
-}
-
 void il_bg_watchdog(unsigned long data);
 u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval);
 __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
@@ -2434,10 +2426,6 @@ struct il_tfd {
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT  0x041
 
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
-
 struct il_rate_info {
        u8 plcp;                /* uCode API:  RATE_6M_PLCP, etc. */
        u8 plcp_siso;           /* uCode API:  RATE_SISO_6M_PLCP, etc. */
index d66cad4a7d6abcfd4d3bd7677f5ceb09a7a0c7f3..35708b959ad6e563a38d29f1bd75c51e87c9c2c8 100644 (file)
@@ -94,8 +94,6 @@ static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans)
 
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT  0x041
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
 
 static void iwl_pcie_apm_config(struct iwl_trans *trans)
 {
@@ -111,9 +109,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
         *    power savings, even without L1.
         */
        pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
-
-       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+       if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
                /* L1-ASPM enabled; disable(!) L0S */
                iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
                dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
@@ -122,7 +118,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
                iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
                dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
        }
-       trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+       trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
 }
 
 /*
index ff306d763e37a893976e67b9a5502760b208ff4a..71ab320fae821a34b5afc4917f6915248c10fdd6 100644 (file)
@@ -1155,7 +1155,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
        if (r)
                goto out;
        /* Currently we support IEEE 802.11g for full and high speed USB.
-        * It might be discussed, whether we should suppport pure b mode for
+        * It might be discussed, whether we should support pure b mode for
         * full speed USB.
         */
        r = set_mandatory_rates(chip, 1);
index dfba3e64d59530bd67be7fea1519769364e02235..d37bfcf5a3a26560a9632930e996e11effabbbe5 100644 (file)
@@ -53,7 +53,7 @@ config OF_DEVICE
 
 config OF_I2C
        def_tristate I2C
-       depends on I2C && !SPARC
+       depends on I2C
        help
          OpenFirmware I2C accessors
 
index 538e3cfad23e20c1dfca368a1e85adc53920c574..be846408dbc14e86dd5df8b2d511eac36be4c711 100644 (file)
@@ -1025,7 +1025,7 @@ EXPORT_SYMBOL(of_parse_phandle);
  * To get a device_node of the `node2' node you may call this:
  * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
  */
-int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
+int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
                                const char *cells_name, int index,
                                struct of_phandle_args *out_args)
 {
index a543746fb354d99913cac3323b99b6f5aa71dbc9..ad6a8b63569201050dd3a7b487c5396b6b8ed28f 100644 (file)
@@ -170,6 +170,11 @@ int pci_bus_add_device(struct pci_dev *dev)
        int retval;
 
        pci_fixup_device(pci_fixup_final, dev);
+
+       retval = pcibios_add_device(dev);
+       if (retval)
+               return retval;
+
        retval = device_add(&dev->dev);
        if (retval)
                return retval;
index b0e46dede1a9e699bd7a1cfb03f853b6b63a4139..13e9e63a72665ab22ee431fdcd22392a2fb68c77 100644 (file)
@@ -151,4 +151,15 @@ config HOTPLUG_PCI_SGI
 
          When in doubt, say N.
 
+config HOTPLUG_PCI_S390
+       tristate "System z PCI Hotplug Support"
+       depends on S390 && 64BIT
+       help
+         Say Y here if you want to use the System z PCI Hotplug
+         driver for PCI devices. Without this driver it is not
+         possible to access stand-by PCI functions nor to deconfigure
+         PCI functions.
+
+         When in doubt, say Y.
+
 endif # HOTPLUG_PCI
index c459cd4e39c2848dbed90f1713e1ad0c4abcd103..47ec8c80e16d0fabe925ecc0e78790fad1a68743 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA)         += rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)    += rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)          += sgi_hotplug.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)         += acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_S390)         += s390_pci_hpc.o
 
 # acpiphp_ibm extends acpiphp, so should be linked afterwards.
 
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
new file mode 100644 (file)
index 0000000..dee68e0
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * PCI Hot Plug Controller Driver for System z
+ *
+ * Copyright 2012 IBM Corp.
+ *
+ * Author(s):
+ *   Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#define COMPONENT "zPCI hpc"
+#define pr_fmt(fmt) COMPONENT ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
+#include <linux/init.h>
+#include <asm/sclp.h>
+
+#define SLOT_NAME_SIZE 10
+static LIST_HEAD(s390_hotplug_slot_list);
+
+MODULE_AUTHOR("Jan Glauber <jang@linux.vnet.ibm.com");
+MODULE_DESCRIPTION("Hot Plug PCI Controller for System z");
+MODULE_LICENSE("GPL");
+
+static int zpci_fn_configured(enum zpci_state state)
+{
+       return state == ZPCI_FN_STATE_CONFIGURED ||
+              state == ZPCI_FN_STATE_ONLINE;
+}
+
+/*
+ * struct slot - slot information for each *physical* slot
+ */
+struct slot {
+       struct list_head slot_list;
+       struct hotplug_slot *hotplug_slot;
+       struct zpci_dev *zdev;
+};
+
+static int enable_slot(struct hotplug_slot *hotplug_slot)
+{
+       struct slot *slot = hotplug_slot->private;
+       int rc;
+
+       if (slot->zdev->state != ZPCI_FN_STATE_STANDBY)
+               return -EIO;
+
+       rc = sclp_pci_configure(slot->zdev->fid);
+       if (!rc) {
+               slot->zdev->state = ZPCI_FN_STATE_CONFIGURED;
+               /* automatically scan the device after is was configured */
+               zpci_enable_device(slot->zdev);
+               zpci_scan_device(slot->zdev);
+       }
+       return rc;
+}
+
+static int disable_slot(struct hotplug_slot *hotplug_slot)
+{
+       struct slot *slot = hotplug_slot->private;
+       int rc;
+
+       if (!zpci_fn_configured(slot->zdev->state))
+               return -EIO;
+
+       /* TODO: we rely on the user to unbind/remove the device, is that plausible
+        *       or do we need to trigger that here?
+        */
+       rc = sclp_pci_deconfigure(slot->zdev->fid);
+       if (!rc) {
+               /* Fixme: better call List-PCI to find the disabled FH
+                  for the FID since the FH should be opaque... */
+               slot->zdev->fh &= 0x7fffffff;
+               slot->zdev->state = ZPCI_FN_STATE_STANDBY;
+       }
+       return rc;
+}
+
+static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+{
+       struct slot *slot = hotplug_slot->private;
+
+       switch (slot->zdev->state) {
+       case ZPCI_FN_STATE_STANDBY:
+               *value = 0;
+               break;
+       default:
+               *value = 1;
+               break;
+       }
+       return 0;
+}
+
+static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+{
+       /* if the slot exits it always contains a function */
+       *value = 1;
+       return 0;
+}
+
+static void release_slot(struct hotplug_slot *hotplug_slot)
+{
+       struct slot *slot = hotplug_slot->private;
+
+       pr_debug("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
+       kfree(slot->hotplug_slot->info);
+       kfree(slot->hotplug_slot);
+       kfree(slot);
+}
+
+static struct hotplug_slot_ops s390_hotplug_slot_ops = {
+       .enable_slot =          enable_slot,
+       .disable_slot =         disable_slot,
+       .get_power_status =     get_power_status,
+       .get_adapter_status =   get_adapter_status,
+};
+
+static int init_pci_slot(struct zpci_dev *zdev)
+{
+       struct hotplug_slot *hotplug_slot;
+       struct hotplug_slot_info *info;
+       char name[SLOT_NAME_SIZE];
+       struct slot *slot;
+       int rc;
+
+       if (!zdev)
+               return 0;
+
+       slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+       if (!slot)
+               goto error;
+
+       hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
+       if (!hotplug_slot)
+               goto error_hp;
+       hotplug_slot->private = slot;
+
+       slot->hotplug_slot = hotplug_slot;
+       slot->zdev = zdev;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               goto error_info;
+       hotplug_slot->info = info;
+
+       hotplug_slot->ops = &s390_hotplug_slot_ops;
+       hotplug_slot->release = &release_slot;
+
+       get_power_status(hotplug_slot, &info->power_status);
+       get_adapter_status(hotplug_slot, &info->adapter_status);
+
+       snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid);
+       rc = pci_hp_register(slot->hotplug_slot, zdev->bus,
+                            ZPCI_DEVFN, name);
+       if (rc) {
+               pr_err("pci_hp_register failed with error %d\n", rc);
+               goto error_reg;
+       }
+       list_add(&slot->slot_list, &s390_hotplug_slot_list);
+       return 0;
+
+error_reg:
+       kfree(info);
+error_info:
+       kfree(hotplug_slot);
+error_hp:
+       kfree(slot);
+error:
+       return -ENOMEM;
+}
+
+static int __init init_pci_slots(void)
+{
+       struct zpci_dev *zdev;
+       int device = 0;
+
+       /*
+        * Create a structure for each slot, and register that slot
+        * with the pci_hotplug subsystem.
+        */
+       mutex_lock(&zpci_list_lock);
+       list_for_each_entry(zdev, &zpci_list, entry) {
+               init_pci_slot(zdev);
+               device++;
+       }
+
+       mutex_unlock(&zpci_list_lock);
+       return (device) ? 0 : -ENODEV;
+}
+
+static void exit_pci_slot(struct zpci_dev *zdev)
+{
+       struct list_head *tmp, *n;
+       struct slot *slot;
+
+       list_for_each_safe(tmp, n, &s390_hotplug_slot_list) {
+               slot = list_entry(tmp, struct slot, slot_list);
+               if (slot->zdev != zdev)
+                       continue;
+               list_del(&slot->slot_list);
+               pci_hp_deregister(slot->hotplug_slot);
+       }
+}
+
+static void __exit exit_pci_slots(void)
+{
+       struct list_head *tmp, *n;
+       struct slot *slot;
+
+       /*
+        * Unregister all of our slots with the pci_hotplug subsystem.
+        * Memory will be freed in release_slot() callback after slot's
+        * lifespan is finished.
+        */
+       list_for_each_safe(tmp, n, &s390_hotplug_slot_list) {
+               slot = list_entry(tmp, struct slot, slot_list);
+               list_del(&slot->slot_list);
+               pci_hp_deregister(slot->hotplug_slot);
+       }
+}
+
+static int __init pci_hotplug_s390_init(void)
+{
+       /*
+        * Do specific initialization stuff for your driver here
+        * like initializing your controller hardware (if any) and
+        * determining the number of slots you have in the system
+        * right now.
+        */
+
+       if (!pci_probe)
+               return -EOPNOTSUPP;
+
+       /* register callbacks for slot handling from arch code */
+       mutex_lock(&zpci_list_lock);
+       hotplug_ops.create_slot = init_pci_slot;
+       hotplug_ops.remove_slot = exit_pci_slot;
+       mutex_unlock(&zpci_list_lock);
+       pr_info("registered hotplug slot callbacks\n");
+       return init_pci_slots();
+}
+
+static void __exit pci_hotplug_s390_exit(void)
+{
+       exit_pci_slots();
+}
+
+module_init(pci_hotplug_s390_init);
+module_exit(pci_hotplug_s390_exit);
index 2eca902a428390394af90b7d6387981fc04ea8db..3c6bbdd059a459614ab2710f377d3f9796ccd3aa 100644 (file)
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
 
 module_init(ioapic_init);
 module_exit(ioapic_exit);
+
+MODULE_LICENSE("GPL");
index aeccc911abb829182cbee0b82ecb4c0b49640aa2..bafd2bbcaf6541d1983fababa4563ae174837e15 100644 (file)
@@ -106,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
                virtfn->resource[i].name = pci_name(virtfn);
                virtfn->resource[i].flags = res->flags;
                size = resource_size(res);
-               do_div(size, iov->total);
+               do_div(size, iov->total_VFs);
                virtfn->resource[i].start = res->start + size * id;
                virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
                rc = request_resource(res, &virtfn->resource[i]);
@@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev)
        u16 status;
        struct pci_sriov *iov = dev->sriov;
 
-       if (!iov->nr_virtfn)
+       if (!iov->num_VFs)
                return 0;
 
        if (!(iov->cap & PCI_SRIOV_CAP_VFM))
@@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work)
        u16 status;
        struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
 
-       for (i = iov->initial; i < iov->nr_virtfn; i++) {
+       for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
                state = readb(iov->mstate + i);
                if (state == PCI_SRIOV_VFM_MI) {
                        writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
@@ -244,7 +244,7 @@ static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
        resource_size_t pa;
        struct pci_sriov *iov = dev->sriov;
 
-       if (nr_virtfn <= iov->initial)
+       if (nr_virtfn <= iov->initial_VFs)
                return 0;
 
        pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
@@ -294,15 +294,15 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
        if (!nr_virtfn)
                return 0;
 
-       if (iov->nr_virtfn)
+       if (iov->num_VFs)
                return -EINVAL;
 
        pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
-       if (initial > iov->total ||
-           (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total)))
+       if (initial > iov->total_VFs ||
+           (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
                return -EIO;
 
-       if (nr_virtfn < 0 || nr_virtfn > iov->total ||
+       if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
            (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
                return -EINVAL;
 
@@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
        msleep(100);
        pci_cfg_access_unlock(dev);
 
-       iov->initial = initial;
+       iov->initial_VFs = initial;
        if (nr_virtfn < initial)
                initial = nr_virtfn;
 
@@ -376,7 +376,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
        }
 
        kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
-       iov->nr_virtfn = nr_virtfn;
+       iov->num_VFs = nr_virtfn;
 
        return 0;
 
@@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev)
        int i;
        struct pci_sriov *iov = dev->sriov;
 
-       if (!iov->nr_virtfn)
+       if (!iov->num_VFs)
                return;
 
        if (iov->cap & PCI_SRIOV_CAP_VFM)
                sriov_disable_migration(dev);
 
-       for (i = 0; i < iov->nr_virtfn; i++)
+       for (i = 0; i < iov->num_VFs; i++)
                virtfn_remove(dev, i, 0);
 
        iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
@@ -419,7 +419,7 @@ static void sriov_disable(struct pci_dev *dev)
        if (iov->link != dev->devfn)
                sysfs_remove_link(&dev->dev.kobj, "dep_link");
 
-       iov->nr_virtfn = 0;
+       iov->num_VFs = 0;
 }
 
 static int sriov_init(struct pci_dev *dev, int pos)
@@ -496,7 +496,7 @@ found:
        iov->pos = pos;
        iov->nres = nres;
        iov->ctrl = ctrl;
-       iov->total = total;
+       iov->total_VFs = total;
        iov->offset = offset;
        iov->stride = stride;
        iov->pgsz = pgsz;
@@ -529,7 +529,7 @@ failed:
 
 static void sriov_release(struct pci_dev *dev)
 {
-       BUG_ON(dev->sriov->nr_virtfn);
+       BUG_ON(dev->sriov->num_VFs);
 
        if (dev != dev->sriov->dev)
                pci_dev_put(dev->sriov->dev);
@@ -554,7 +554,7 @@ static void sriov_restore_state(struct pci_dev *dev)
                pci_update_resource(dev, i);
 
        pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
-       pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn);
+       pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
        pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
        if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
                msleep(100);
@@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
        list_for_each_entry(dev, &bus->devices, bus_list) {
                if (!dev->is_physfn)
                        continue;
-               busnr = virtfn_bus(dev, dev->sriov->total - 1);
+               busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
                if (busnr > max)
                        max = busnr;
        }
@@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
  */
 int pci_num_vf(struct pci_dev *dev)
 {
-       if (!dev || !dev->is_physfn)
+       if (!dev->is_physfn)
                return 0;
-       else
-               return dev->sriov->nr_virtfn;
+
+       return dev->sriov->num_VFs;
 }
 EXPORT_SYMBOL_GPL(pci_num_vf);
+
+/**
+ * pci_sriov_set_totalvfs -- reduce the TotalVFs available
+ * @dev: the PCI PF device
+ * numvfs: number that should be used for TotalVFs supported
+ *
+ * Should be called from PF driver's probe routine with
+ * device's mutex held.
+ *
+ * Returns 0 if PF is an SRIOV-capable device and
+ * value of numvfs valid. If not a PF with VFS, return -EINVAL;
+ * if VFs already enabled, return -EBUSY.
+ */
+int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
+{
+       if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs))
+               return -EINVAL;
+
+       /* Shouldn't change if VFs already enabled */
+       if (dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE)
+               return -EBUSY;
+       else
+               dev->sriov->driver_max_VFs = numvfs;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
+
+/**
+ * pci_sriov_get_totalvfs -- get total VFs supported on this devic3
+ * @dev: the PCI PF device
+ *
+ * For a PCIe device with SRIOV support, return the PCIe
+ * SRIOV capability value of TotalVFs or the value of driver_max_VFs
+ * if the driver reduced it.  Otherwise, -EINVAL.
+ */
+int pci_sriov_get_totalvfs(struct pci_dev *dev)
+{
+       if (!dev->is_physfn)
+               return -EINVAL;
+
+       if (dev->sriov->driver_max_VFs)
+               return dev->sriov->driver_max_VFs;
+
+       return dev->sriov->total_VFs;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
index e5f69a43b1b18e0961ff05ddc29ae3872be962fc..b008cf86b9c3f8d4fab1493a41895f196519e94d 100644 (file)
@@ -14,11 +14,11 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
 {
        struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
 
-       dev_printk(KERN_ERR, &pdev->dev,
-                  "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
-                  dev_name(&parent->dev), parent->vendor, parent->device);
-       dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
-       dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
+       dev_err(&pdev->dev,
+               "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
+               dev_name(&parent->dev), parent->vendor, parent->device);
+       dev_err(&pdev->dev, "%s\n", reason);
+       dev_err(&pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
        WARN_ON(1);
 }
 
index a825d78fd0aa7e50bfb50520d6af16604436890e..5099636a6e5f65782ea87fbb9c25a0aeeeed282e 100644 (file)
@@ -207,6 +207,8 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
        desc->masked = __msix_mask_irq(desc, flag);
 }
 
+#ifdef CONFIG_GENERIC_HARDIRQS
+
 static void msi_set_mask_bit(struct irq_data *data, u32 flag)
 {
        struct msi_desc *desc = irq_data_get_msi(data);
@@ -230,6 +232,8 @@ void unmask_msi_irq(struct irq_data *data)
        msi_set_mask_bit(data, 0);
 }
 
+#endif /* CONFIG_GENERIC_HARDIRQS */
+
 void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
        BUG_ON(entry->dev->current_state != PCI_D0);
@@ -337,8 +341,10 @@ static void free_msi_irqs(struct pci_dev *dev)
                if (!entry->irq)
                        continue;
                nvec = 1 << entry->msi_attrib.multiple;
+#ifdef CONFIG_GENERIC_HARDIRQS
                for (i = 0; i < nvec; i++)
                        BUG_ON(irq_has_action(entry->irq + i));
+#endif
        }
 
        arch_teardown_msi_irqs(dev);
index 1dc78c5cabf8f52175159ef6191a479828497e08..f79cbcd3944bf5e61e76a96022331a665e63f93e 100644 (file)
@@ -248,31 +248,26 @@ struct drv_dev_and_id {
 static long local_pci_probe(void *_ddi)
 {
        struct drv_dev_and_id *ddi = _ddi;
-       struct device *dev = &ddi->dev->dev;
-       struct device *parent = dev->parent;
+       struct pci_dev *pci_dev = ddi->dev;
+       struct pci_driver *pci_drv = ddi->drv;
+       struct device *dev = &pci_dev->dev;
        int rc;
 
-       /* The parent bridge must be in active state when probing */
-       if (parent)
-               pm_runtime_get_sync(parent);
-       /* Unbound PCI devices are always set to disabled and suspended.
-        * During probe, the device is set to enabled and active and the
-        * usage count is incremented.  If the driver supports runtime PM,
-        * it should call pm_runtime_put_noidle() in its probe routine and
-        * pm_runtime_get_noresume() in its remove routine.
+       /*
+        * Unbound PCI devices are always put in D0, regardless of
+        * runtime PM status.  During probe, the device is set to
+        * active and the usage count is incremented.  If the driver
+        * supports runtime PM, it should call pm_runtime_put_noidle()
+        * in its probe routine and pm_runtime_get_noresume() in its
+        * remove routine.
         */
-       pm_runtime_get_noresume(dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
-
-       rc = ddi->drv->probe(ddi->dev, ddi->id);
+       pm_runtime_get_sync(dev);
+       pci_dev->driver = pci_drv;
+       rc = pci_drv->probe(pci_dev, ddi->id);
        if (rc) {
-               pm_runtime_disable(dev);
-               pm_runtime_set_suspended(dev);
-               pm_runtime_put_noidle(dev);
+               pci_dev->driver = NULL;
+               pm_runtime_put_sync(dev);
        }
-       if (parent)
-               pm_runtime_put(parent);
        return rc;
 }
 
@@ -322,10 +317,8 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
                id = pci_match_device(drv, pci_dev);
                if (id)
                        error = pci_call_probe(drv, pci_dev, id);
-               if (error >= 0) {
-                       pci_dev->driver = drv;
+               if (error >= 0)
                        error = 0;
-               }
        }
        return error;
 }
@@ -361,9 +354,7 @@ static int pci_device_remove(struct device * dev)
        }
 
        /* Undo the runtime PM settings in local_pci_probe() */
-       pm_runtime_disable(dev);
-       pm_runtime_set_suspended(dev);
-       pm_runtime_put_noidle(dev);
+       pm_runtime_put_sync(dev);
 
        /*
         * If the device is still on, set the power state as "unknown",
@@ -986,6 +977,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
        pci_power_t prev = pci_dev->current_state;
        int error;
 
+       /*
+        * If pci_dev->driver is not set (unbound), the device should
+        * always remain in D0 regardless of the runtime PM status
+        */
+       if (!pci_dev->driver)
+               return 0;
+
        if (!pm || !pm->runtime_suspend)
                return -ENOSYS;
 
@@ -1007,10 +1005,10 @@ static int pci_pm_runtime_suspend(struct device *dev)
                return 0;
        }
 
-       if (!pci_dev->state_saved)
+       if (!pci_dev->state_saved) {
                pci_save_state(pci_dev);
-
-       pci_finish_runtime_suspend(pci_dev);
+               pci_finish_runtime_suspend(pci_dev);
+       }
 
        return 0;
 }
@@ -1021,6 +1019,13 @@ static int pci_pm_runtime_resume(struct device *dev)
        struct pci_dev *pci_dev = to_pci_dev(dev);
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
+       /*
+        * If pci_dev->driver is not set (unbound), the device should
+        * always remain in D0 regardless of the runtime PM status
+        */
+       if (!pci_dev->driver)
+               return 0;
+
        if (!pm || !pm->runtime_resume)
                return -ENOSYS;
 
@@ -1038,8 +1043,16 @@ static int pci_pm_runtime_resume(struct device *dev)
 
 static int pci_pm_runtime_idle(struct device *dev)
 {
+       struct pci_dev *pci_dev = to_pci_dev(dev);
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
+       /*
+        * If pci_dev->driver is not set (unbound), the device should
+        * always remain in D0 regardless of the runtime PM status
+        */
+       if (!pci_dev->driver)
+               goto out;
+
        if (!pm)
                return -ENOSYS;
 
@@ -1049,8 +1062,8 @@ static int pci_pm_runtime_idle(struct device *dev)
                        return ret;
        }
 
+out:
        pm_runtime_suspend(dev);
-
        return 0;
 }
 
index 775e933c222547d14c30840daebd16b5a438be72..6e47c519c51070788ea7fa4e0a3f56896b962ab9 100644 (file)
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is "
 
 static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       dev_printk(KERN_INFO, &dev->dev, "claimed by stub\n");
+       dev_info(&dev->dev, "claimed by stub\n");
        return 0;
 }
 
index 68d56f02e721f8de0f3f7f7b5869168bc32e1350..05b78b16d20bdca1acb822e7654360102fb09072 100644 (file)
@@ -401,6 +401,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
 }
 #endif
 
+#ifdef CONFIG_PCI_IOV
+static ssize_t sriov_totalvfs_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
+}
+
+
+static ssize_t sriov_numvfs_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
+}
+
+/*
+ * num_vfs > 0; number of vfs to enable
+ * num_vfs = 0; disable all vfs
+ *
+ * Note: SRIOV spec doesn't allow partial VF
+ *       disable, so its all or none.
+ */
+static ssize_t sriov_numvfs_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       int num_vfs_enabled = 0;
+       int num_vfs;
+       int ret = 0;
+       u16 total;
+
+       if (kstrtoint(buf, 0, &num_vfs) < 0)
+               return -EINVAL;
+
+       /* is PF driver loaded w/callback */
+       if (!pdev->driver || !pdev->driver->sriov_configure) {
+               dev_info(&pdev->dev,
+                        "Driver doesn't support SRIOV configuration via sysfs\n");
+               return -ENOSYS;
+       }
+
+       /* if enabling vf's ... */
+       total = pci_sriov_get_totalvfs(pdev);
+       /* Requested VFs to enable < totalvfs and none enabled already */
+       if ((num_vfs > 0) && (num_vfs <= total)) {
+               if (pdev->sriov->num_VFs == 0) {
+                       num_vfs_enabled =
+                               pdev->driver->sriov_configure(pdev, num_vfs);
+                       if ((num_vfs_enabled >= 0) &&
+                           (num_vfs_enabled != num_vfs)) {
+                               dev_warn(&pdev->dev,
+                                        "Only %d VFs enabled\n",
+                                        num_vfs_enabled);
+                               return count;
+                       } else if (num_vfs_enabled < 0)
+                               /* error code from driver callback */
+                               return num_vfs_enabled;
+               } else if (num_vfs == pdev->sriov->num_VFs) {
+                       dev_warn(&pdev->dev,
+                                "%d VFs already enabled; no enable action taken\n",
+                                num_vfs);
+                       return count;
+               } else {
+                       dev_warn(&pdev->dev,
+                                "%d VFs already enabled. Disable before enabling %d VFs\n",
+                                pdev->sriov->num_VFs, num_vfs);
+                       return -EINVAL;
+               }
+       }
+
+       /* disable vfs */
+       if (num_vfs == 0) {
+               if (pdev->sriov->num_VFs != 0) {
+                       ret = pdev->driver->sriov_configure(pdev, 0);
+                       return ret ? ret : count;
+               } else {
+                       dev_warn(&pdev->dev,
+                                "All VFs disabled; no disable action taken\n");
+                       return count;
+               }
+       }
+
+       dev_err(&pdev->dev,
+               "Invalid value for number of VFs to enable: %d\n", num_vfs);
+
+       return -EINVAL;
+}
+
+static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
+static struct device_attribute sriov_numvfs_attr =
+               __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
+                      sriov_numvfs_show, sriov_numvfs_store);
+#endif /* CONFIG_PCI_IOV */
+
 struct device_attribute pci_dev_attrs[] = {
        __ATTR_RO(resource),
        __ATTR_RO(vendor),
@@ -1262,29 +1362,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
                pdev->rom_attr = attr;
        }
 
-       if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
-               retval = device_create_file(&pdev->dev, &vga_attr);
-               if (retval)
-                       goto err_rom_file;
-       }
-
        /* add platform-specific attributes */
        retval = pcibios_add_platform_entries(pdev);
        if (retval)
-               goto err_vga_file;
+               goto err_rom_file;
 
        /* add sysfs entries for various capabilities */
        retval = pci_create_capabilities_sysfs(pdev);
        if (retval)
-               goto err_vga_file;
+               goto err_rom_file;
 
        pci_create_firmware_label_files(pdev);
 
        return 0;
 
-err_vga_file:
-       if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-               device_remove_file(&pdev->dev, &vga_attr);
 err_rom_file:
        if (rom_size) {
                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
@@ -1370,3 +1461,62 @@ static int __init pci_sysfs_init(void)
 }
 
 late_initcall(pci_sysfs_init);
+
+static struct attribute *pci_dev_dev_attrs[] = {
+       &vga_attr.attr,
+       NULL,
+};
+
+static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
+                                               struct attribute *a, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       if (a == &vga_attr.attr)
+               if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+                       return 0;
+
+       return a->mode;
+}
+
+#ifdef CONFIG_PCI_IOV
+static struct attribute *sriov_dev_attrs[] = {
+       &sriov_totalvfs_attr.attr,
+       &sriov_numvfs_attr.attr,
+       NULL,
+};
+
+static umode_t sriov_attrs_are_visible(struct kobject *kobj,
+                                        struct attribute *a, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+
+       if (!dev_is_pf(dev))
+               return 0;
+
+       return a->mode;
+}
+
+static struct attribute_group sriov_dev_attr_group = {
+       .attrs = sriov_dev_attrs,
+       .is_visible = sriov_attrs_are_visible,
+};
+#endif /* CONFIG_PCI_IOV */
+
+static struct attribute_group pci_dev_attr_group = {
+       .attrs = pci_dev_dev_attrs,
+       .is_visible = pci_dev_attrs_are_visible,
+};
+
+static const struct attribute_group *pci_dev_attr_groups[] = {
+       &pci_dev_attr_group,
+#ifdef CONFIG_PCI_IOV
+       &sriov_dev_attr_group,
+#endif
+       NULL,
+};
+
+struct device_type pci_dev_type = {
+       .groups = pci_dev_attr_groups,
+};
index bdf66b500f22bae2ba17dc7ed325eae5015b40ac..5cb5820fae40147a29c79913cd1ebadcbfba1348 100644 (file)
@@ -1333,6 +1333,19 @@ void pcim_pin_device(struct pci_dev *pdev)
                dr->pinned = 1;
 }
 
+/*
+ * pcibios_add_device - provide arch specific hooks when adding device dev
+ * @dev: the PCI device being added
+ *
+ * Permits the platform to provide architecture specific functionality when
+ * devices are added. This is the default implementation. Architecture
+ * implementations can override this.
+ */
+int __weak pcibios_add_device (struct pci_dev *dev)
+{
+       return 0;
+}
+
 /**
  * pcibios_disable_device - disable arch specific PCI resources for device dev
  * @dev: the PCI device to disable
@@ -1578,15 +1591,25 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
 
-       /* PCI (as opposed to PCIe) PME requires that the device have
-          its PME# line hooked up correctly. Not all hardware vendors
-          do this, so the PME never gets delivered and the device
-          remains asleep. The easiest way around this is to
-          periodically walk the list of suspended devices and check
-          whether any have their PME flag set. The assumption is that
-          we'll wake up often enough anyway that this won't be a huge
-          hit, and the power savings from the devices will still be a
-          win. */
+       /*
+        * PCI (as opposed to PCIe) PME requires that the device have
+        * its PME# line hooked up correctly. Not all hardware vendors
+        * do this, so the PME never gets delivered and the device
+        * remains asleep. The easiest way around this is to
+        * periodically walk the list of suspended devices and check
+        * whether any have their PME flag set. The assumption is that
+        * we'll wake up often enough anyway that this won't be a huge
+        * hit, and the power savings from the devices will still be a
+        * win.
+        *
+        * Although PCIe uses in-band PME message instead of PME# line
+        * to report PME, PME does not work for some PCIe devices in
+        * reality.  For example, there are devices that set their PME
+        * status bits, but don't really bother to send a PME message;
+        * there are PCI Express Root Ports that don't bother to
+        * trigger interrupts when they receive PME messages from the
+        * devices below.  So PME poll is used for PCIe devices too.
+        */
 
        if (dev->pme_poll) {
                struct pci_pme_device *pme_dev;
@@ -1900,6 +1923,8 @@ void pci_pm_init(struct pci_dev *dev)
        u16 pmc;
 
        pm_runtime_forbid(&dev->dev);
+       pm_runtime_set_active(&dev->dev);
+       pm_runtime_enable(&dev->dev);
        device_enable_async_suspend(&dev->dev);
        dev->wakeup_prepared = false;
 
@@ -3865,14 +3890,13 @@ static void pci_no_domains(void)
 }
 
 /**
- * pci_ext_cfg_enabled - can we access extended PCI config space?
- * @dev: The PCI device of the root bridge.
+ * pci_ext_cfg_avail - can we access extended PCI config space?
  *
  * Returns 1 if we can access PCI extended config space (offsets
  * greater than 0xff). This is the default implementation. Architecture
  * implementations can override this.
  */
-int __weak pci_ext_cfg_avail(struct pci_dev *dev)
+int __weak pci_ext_cfg_avail(void)
 {
        return 1;
 }
index e253881c42759eaeb2b76070f830de192663e347..e8518292826f0182bc23206f0b7e25fe88de858f 100644 (file)
@@ -158,6 +158,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
 }
 extern struct device_attribute pci_dev_attrs[];
 extern struct device_attribute pcibus_dev_attrs[];
+extern struct device_type pci_dev_type;
 extern struct bus_attribute pci_bus_attrs[];
 
 
@@ -229,13 +230,14 @@ struct pci_sriov {
        int nres;               /* number of resources */
        u32 cap;                /* SR-IOV Capabilities */
        u16 ctrl;               /* SR-IOV Control */
-       u16 total;              /* total VFs associated with the PF */
-       u16 initial;            /* initial VFs associated with the PF */
-       u16 nr_virtfn;          /* number of VFs available */
+       u16 total_VFs;          /* total VFs associated with the PF */
+       u16 initial_VFs;        /* initial VFs associated with the PF */
+       u16 num_VFs;            /* number of VFs available */
        u16 offset;             /* first VF Routing ID offset */
        u16 stride;             /* following VF stride */
        u32 pgsz;               /* page size for BAR alignment */
        u8 link;                /* Function Dependency Link */
+       u16 driver_max_VFs;     /* max num VFs driver supports */
        struct pci_dev *dev;    /* lowest numbered PF */
        struct pci_dev *self;   /* this PF */
        struct mutex lock;      /* lock for VF bus */
index 94a7598eb262fec103cb9611ba8612e452d1de7b..22f840f4dda1065eb97b54da307b5f6d2dda0c5a 100644 (file)
@@ -87,6 +87,9 @@ struct aer_broadcast_data {
 static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
                enum pci_ers_result new)
 {
+       if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
+               return PCI_ERS_RESULT_NO_AER_DRIVER;
+
        if (new == PCI_ERS_RESULT_NONE)
                return orig;
 
@@ -97,7 +100,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
                break;
        case PCI_ERS_RESULT_DISCONNECT:
                if (new == PCI_ERS_RESULT_NEED_RESET)
-                       orig = new;
+                       orig = PCI_ERS_RESULT_NEED_RESET;
                break;
        default:
                break;
index af4e31cd3a3b6b1f895a36afaf4bb874b3e1fb66..421bbc5fee324b485f409e7a025338bc524eecf5 100644 (file)
@@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                                   dev->driver ?
                                   "no AER-aware driver" : "no driver");
                }
-               goto out;
+
+               /*
+                * If there's any device in the subtree that does not
+                * have an error_detected callback, returning
+                * PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of
+                * the subsequent mmio_enabled/slot_reset/resume
+                * callbacks of "any" device in the subtree. All the
+                * devices in the subtree are left in the error state
+                * without recovery.
+                */
+
+               if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+                       vote = PCI_ERS_RESULT_NO_AER_DRIVER;
+               else
+                       vote = PCI_ERS_RESULT_NONE;
+       } else {
+               err_handler = dev->driver->err_handler;
+               vote = err_handler->error_detected(dev, result_data->state);
        }
 
-       err_handler = dev->driver->err_handler;
-       vote = err_handler->error_detected(dev, result_data->state);
        result_data->result = merge_result(result_data->result, vote);
-out:
        device_unlock(&dev->dev);
        return 0;
 }
index 213753b283a6838174dd1fd409add971c7a363ae..b52630b8eada26ad35f8304e436c63f3e064edd3 100644 (file)
@@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
                return;
 
        /* Training failed. Restore common clock configurations */
-       dev_printk(KERN_ERR, &parent->dev,
-                  "ASPM: Could not configure common clock\n");
+       dev_err(&parent->dev, "ASPM: Could not configure common clock\n");
        list_for_each_entry(child, &linkbus->devices, bus_list)
                pcie_capability_write_word(child, PCI_EXP_LNKCTL,
                                           child_reg[PCI_FUNC(child->devfn)]);
@@ -427,7 +426,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 
 static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
 {
-       pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val);
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
+                                          PCI_EXP_LNKCTL_ASPMC, val);
 }
 
 static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
@@ -442,12 +442,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
                return;
        /* Convert ASPM state to upstream/downstream ASPM register state */
        if (state & ASPM_STATE_L0S_UP)
-               dwstream |= PCIE_LINK_STATE_L0S;
+               dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
        if (state & ASPM_STATE_L0S_DW)
-               upstream |= PCIE_LINK_STATE_L0S;
+               upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
        if (state & ASPM_STATE_L1) {
-               upstream |= PCIE_LINK_STATE_L1;
-               dwstream |= PCIE_LINK_STATE_L1;
+               upstream |= PCI_EXP_LNKCTL_ASPM_L1;
+               dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
        }
        /*
         * Spec 2.0 suggests all functions should be configured the
@@ -507,9 +507,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
                 */
                pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
                if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
-                       dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
-                               " on pre-1.1 PCIe device.  You can enable it"
-                               " with 'pcie_aspm=force'\n");
+                       dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device.  You can enable it with 'pcie_aspm=force'\n");
                        return -EINVAL;
                }
        }
index ed129b4146246144de63db421ff04d28d5d7de27..b42133afca985659f6e9dde41a99ce2a05808a7b 100644 (file)
@@ -120,8 +120,7 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
                 * the value in this field indicates which MSI-X Table entry is
                 * used to generate the interrupt message."
                 */
-               pos = pci_pcie_cap(dev);
-               pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
+               pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
                entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
                if (entry >= nr_entries)
                        goto Error;
index 3683f6094e3f19a3575fc29b2f55dd47250a397f..6186f03d84f37c8aa696d3df504e722a5cd36b38 100644 (file)
@@ -521,7 +521,7 @@ static unsigned char pcie_link_speed[] = {
 
 void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
 {
-       bus->cur_bus_speed = pcie_link_speed[linksta & 0xf];
+       bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
 }
 EXPORT_SYMBOL_GPL(pcie_update_link_speed);
 
@@ -579,14 +579,16 @@ static void pci_set_bus_speed(struct pci_bus *bus)
        if (pos) {
                u16 status;
                enum pci_bus_speed max;
-               pci_read_config_word(bridge, pos + 2, &status);
 
-               if (status & 0x8000) {
+               pci_read_config_word(bridge, pos + PCI_X_BRIDGE_SSTATUS,
+                                    &status);
+
+               if (status & PCI_X_SSTATUS_533MHZ) {
                        max = PCI_SPEED_133MHz_PCIX_533;
-               } else if (status & 0x4000) {
+               } else if (status & PCI_X_SSTATUS_266MHZ) {
                        max = PCI_SPEED_133MHz_PCIX_266;
-               } else if (status & 0x0002) {
-                       if (((status >> 12) & 0x3) == 2) {
+               } else if (status & PCI_X_SSTATUS_133MHZ) {
+                       if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) {
                                max = PCI_SPEED_133MHz_PCIX_ECC;
                        } else {
                                max = PCI_SPEED_133MHz_PCIX;
@@ -596,7 +598,8 @@ static void pci_set_bus_speed(struct pci_bus *bus)
                }
 
                bus->max_bus_speed = max;
-               bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf];
+               bus->cur_bus_speed = pcix_bus_speed[
+                       (status & PCI_X_SSTATUS_FREQ) >> 6];
 
                return;
        }
@@ -607,7 +610,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
                u16 linksta;
 
                pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
-               bus->max_bus_speed = pcie_link_speed[linkcap & 0xf];
+               bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
 
                pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
                pcie_update_link_speed(bus, linksta);
@@ -975,6 +978,7 @@ int pci_setup_device(struct pci_dev *dev)
        dev->sysdata = dev->bus->sysdata;
        dev->dev.parent = dev->bus->bridge;
        dev->dev.bus = &pci_bus_type;
+       dev->dev.type = &pci_dev_type;
        dev->hdr_type = hdr_type & 0x7f;
        dev->multifunction = !!(hdr_type & 0x80);
        dev->error_state = pci_channel_io_normal;
@@ -1889,6 +1893,28 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
        return max;
 }
 
+/**
+ * pci_rescan_bus - scan a PCI bus for devices.
+ * @bus: PCI bus to scan
+ *
+ * Scan a PCI bus and child buses for new devices, adds them,
+ * and enables them.
+ *
+ * Returns the max number of subordinate bus discovered.
+ */
+unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+{
+       unsigned int max;
+
+       max = pci_scan_child_bus(bus);
+       pci_assign_unassigned_bus_resources(bus);
+       pci_enable_bridges(bus);
+       pci_bus_add_devices(bus);
+
+       return max;
+}
+EXPORT_SYMBOL_GPL(pci_rescan_bus);
+
 EXPORT_SYMBOL(pci_add_new_bus);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_bridge);
index 22ad3ee0cf0b66c90e8663ff4e74ca3119d11730..8f7a6344e79e4ca31f7db08ac63a2d4f168649e1 100644 (file)
@@ -1790,6 +1790,45 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
                         PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
                         quirk_tc86c001_ide);
 
+/*
+ * PLX PCI 9050 PCI Target bridge controller has an errata that prevents the
+ * local configuration registers accessible via BAR0 (memory) or BAR1 (i/o)
+ * being read correctly if bit 7 of the base address is set.
+ * The BAR0 or BAR1 region may be disabled (size 0) or enabled (size 128).
+ * Re-allocate the regions to a 256-byte boundary if necessary.
+ */
+static void quirk_plx_pci9050(struct pci_dev *dev)
+{
+       unsigned int bar;
+
+       /* Fixed in revision 2 (PCI 9052). */
+       if (dev->revision >= 2)
+               return;
+       for (bar = 0; bar <= 1; bar++)
+               if (pci_resource_len(dev, bar) == 0x80 &&
+                   (pci_resource_start(dev, bar) & 0x80)) {
+                       struct resource *r = &dev->resource[bar];
+                       dev_info(&dev->dev,
+                                "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
+                                bar);
+                       r->start = 0;
+                       r->end = 0xff;
+               }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+                        quirk_plx_pci9050);
+/*
+ * The following Meilhaus (vendor ID 0x1402) device IDs (amongst others)
+ * may be using the PLX PCI 9050: 0x0630, 0x0940, 0x0950, 0x0960, 0x100b,
+ * 0x1400, 0x140a, 0x140b, 0x14e0, 0x14ea, 0x14eb, 0x1604, 0x1608, 0x160c,
+ * 0x168f, 0x2000, 0x2600, 0x3000, 0x810a, 0x810b.
+ *
+ * Currently, device IDs 0x2000 and 0x2600 are used by the Comedi "me_daq"
+ * driver.
+ */
+DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2000, quirk_plx_pci9050);
+DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2600, quirk_plx_pci9050);
+
 static void quirk_netmos(struct pci_dev *dev)
 {
        unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
index 513972f3ed13631f152b4d9b3bef9d8f489db857..7c0fd9252e6f03c1b1f17f53282be0c5a1fdb57d 100644 (file)
@@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
        pci_remove_bus_device(dev);
 }
 EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
+
+void pci_stop_root_bus(struct pci_bus *bus)
+{
+       struct pci_dev *child, *tmp;
+       struct pci_host_bridge *host_bridge;
+
+       if (!pci_is_root_bus(bus))
+               return;
+
+       host_bridge = to_pci_host_bridge(bus->bridge);
+       list_for_each_entry_safe_reverse(child, tmp,
+                                        &bus->devices, bus_list)
+               pci_stop_bus_device(child);
+
+       /* stop the host bridge */
+       device_del(&host_bridge->dev);
+}
+
+void pci_remove_root_bus(struct pci_bus *bus)
+{
+       struct pci_dev *child, *tmp;
+       struct pci_host_bridge *host_bridge;
+
+       if (!pci_is_root_bus(bus))
+               return;
+
+       host_bridge = to_pci_host_bridge(bus->bridge);
+       list_for_each_entry_safe(child, tmp,
+                                &bus->devices, bus_list)
+               pci_remove_bus_device(child);
+       pci_remove_bus(bus);
+       host_bridge->bus = NULL;
+
+       /* remove the host bridge */
+       put_device(&host_bridge->dev);
+}
index 0b3037ab8b9326bd5cbbad3517ff6c1bd348542a..ab886b7ee327af413f98976382869242fcba679b 100644 (file)
@@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        loff_t start;
        void __iomem *rom;
 
+       /*
+        * Some devices may provide ROMs via a source other than the BAR
+        */
+       if (pdev->rom && pdev->romlen) {
+               *size = pdev->romlen;
+               return phys_to_virt(pdev->rom);
        /*
         * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
         * memory map if the VGA enable bit of the Bridge Control register is
         * set for embedded VGA.
         */
-       if (res->flags & IORESOURCE_ROM_SHADOW) {
+       } else if (res->flags & IORESOURCE_ROM_SHADOW) {
                /* primary video rom always starts here */
                start = (loff_t)0xC0000;
                *size = 0x20000; /* cover C000:0 through E000:0 */
@@ -181,7 +187,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
        if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
                return;
 
-       iounmap(rom);
+       if (!pdev->rom || !pdev->romlen)
+               iounmap(rom);
 
        /* Disable again before continuing, leave enabled if pci=rom */
        if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
index 1e808ca338f804208099472392e8a2117ebb4163..6d3591d57ea00734148e48e8fb2774bc34bb81b6 100644 (file)
@@ -1550,25 +1550,12 @@ enable_all:
 }
 EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
 
-#ifdef CONFIG_HOTPLUG
-/**
- * pci_rescan_bus - scan a PCI bus for devices.
- * @bus: PCI bus to scan
- *
- * Scan a PCI bus and child buses for new devices, adds them,
- * and enables them.
- *
- * Returns the max number of subordinate bus discovered.
- */
-unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 {
-       unsigned int max;
        struct pci_dev *dev;
        LIST_HEAD(add_list); /* list of resources that
                                        want additional resources */
 
-       max = pci_scan_child_bus(bus);
-
        down_read(&pci_bus_sem);
        list_for_each_entry(dev, &bus->devices, bus_list)
                if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
        up_read(&pci_bus_sem);
        __pci_bus_assign_resources(bus, &add_list, NULL);
        BUG_ON(!list_empty(&add_list));
-
-       pci_enable_bridges(bus);
-       pci_bus_add_devices(bus);
-
-       return max;
 }
-EXPORT_SYMBOL_GPL(pci_rescan_bus);
-#endif
index db542f4196a4a77f2b9e6df7f8474a7d4f2b4531..966abc6054d7b625c18a5eeb854dc065b40d43c1 100644 (file)
@@ -1068,13 +1068,16 @@ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
        case XenbusStateInitialising:
        case XenbusStateInitWait:
        case XenbusStateInitialised:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateConnected:
                pcifront_try_connect(pdev);
                break;
 
+       case XenbusStateClosed:
+               if (xdev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                dev_warn(&xdev->dev, "backend going away!\n");
                pcifront_try_disconnect(pdev);
index b1d956d81f0c341fc8f24a8c013e3ddc1d016079..9f45e2f77d531748016db6799a39fcd7465b6ab9 100644 (file)
@@ -245,6 +245,13 @@ config BATTERY_INTEL_MID
          Say Y here to enable the battery driver on Intel MID
          platforms.
 
+config BATTERY_RX51
+       tristate "Nokia RX-51 (N900) battery driver"
+       depends on TWL4030_MADC
+       help
+         Say Y here to enable support for battery information on Nokia
+         RX-51, also known as N900 tablet.
+
 config CHARGER_ISP1704
        tristate "ISP1704 USB Charger Detection"
        depends on USB_OTG_UTILS
@@ -315,6 +322,16 @@ config CHARGER_MAX8998
          Say Y to enable support for the battery charger control sysfs and
          platform data of MAX8998/LP3974 PMICs.
 
+config CHARGER_BQ2415X
+       tristate "TI BQ2415x battery charger driver"
+       depends on I2C
+       help
+         Say Y to enable support for the TI BQ2415x battery charger
+         PMICs.
+
+         You'll need this driver to charge batteries on e.g. Nokia
+         RX-51/N900.
+
 config CHARGER_SMB347
        tristate "Summit Microelectronics SMB347 Battery Charger"
        depends on I2C
@@ -329,13 +346,6 @@ config AB8500_BM
        help
          Say Y to include support for AB8500 battery management.
 
-config AB8500_BATTERY_THERM_ON_BATCTRL
-       bool "Thermistor connected on BATCTRL ADC"
-       depends on AB8500_BM
-       help
-         Say Y to enable battery temperature measurements using
-         thermistor connected on BATCTRL ADC.
-
 source "drivers/power/reset/Kconfig"
 
 endif # POWER_SUPPLY
index f1d99f4a0bc35b8b64c8e494a03c2f4049688985..22c8913382c0839bda10690268fb740e5ea42999 100644 (file)
@@ -37,7 +37,8 @@ obj-$(CONFIG_CHARGER_88PM860X)        += 88pm860x_charger.o
 obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)   += jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)        += intel_mid_battery.o
-obj-$(CONFIG_AB8500_BM)                += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
+obj-$(CONFIG_BATTERY_RX51)     += rx51_battery.o
+obj-$(CONFIG_AB8500_BM)                += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
 obj-$(CONFIG_CHARGER_ISP1704)  += isp1704_charger.o
 obj-$(CONFIG_CHARGER_MAX8903)  += max8903_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)  += twl4030_charger.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_CHARGER_GPIO)    += gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)  += charger-manager.o
 obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
+obj-$(CONFIG_CHARGER_BQ2415X)  += bq2415x_charger.o
 obj-$(CONFIG_POWER_AVS)                += avs/
 obj-$(CONFIG_CHARGER_SMB347)   += smb347-charger.o
 obj-$(CONFIG_POWER_RESET)      += reset/
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
new file mode 100644 (file)
index 0000000..03cc528
--- /dev/null
@@ -0,0 +1,521 @@
+#include <linux/export.h>
+#include <linux/power_supply.h>
+#include <linux/of.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+
+/*
+ * These are the defined batteries that uses a NTC and ID resistor placed
+ * inside of the battery pack.
+ * Note that the res_to_temp table must be strictly sorted by falling resistance
+ * values to work.
+ */
+static struct abx500_res_to_temp temp_tbl_A_thermistor[] = {
+       {-5, 53407},
+       { 0, 48594},
+       { 5, 43804},
+       {10, 39188},
+       {15, 34870},
+       {20, 30933},
+       {25, 27422},
+       {30, 24347},
+       {35, 21694},
+       {40, 19431},
+       {45, 17517},
+       {50, 15908},
+       {55, 14561},
+       {60, 13437},
+       {65, 12500},
+};
+
+static struct abx500_res_to_temp temp_tbl_B_thermistor[] = {
+       {-5, 200000},
+       { 0, 159024},
+       { 5, 151921},
+       {10, 144300},
+       {15, 136424},
+       {20, 128565},
+       {25, 120978},
+       {30, 113875},
+       {35, 107397},
+       {40, 101629},
+       {45,  96592},
+       {50,  92253},
+       {55,  88569},
+       {60,  85461},
+       {65,  82869},
+};
+
+static struct abx500_v_to_cap cap_tbl_A_thermistor[] = {
+       {4171,  100},
+       {4114,   95},
+       {4009,   83},
+       {3947,   74},
+       {3907,   67},
+       {3863,   59},
+       {3830,   56},
+       {3813,   53},
+       {3791,   46},
+       {3771,   33},
+       {3754,   25},
+       {3735,   20},
+       {3717,   17},
+       {3681,   13},
+       {3664,    8},
+       {3651,    6},
+       {3635,    5},
+       {3560,    3},
+       {3408,    1},
+       {3247,    0},
+};
+
+static struct abx500_v_to_cap cap_tbl_B_thermistor[] = {
+       {4161,  100},
+       {4124,   98},
+       {4044,   90},
+       {4003,   85},
+       {3966,   80},
+       {3933,   75},
+       {3888,   67},
+       {3849,   60},
+       {3813,   55},
+       {3787,   47},
+       {3772,   30},
+       {3751,   25},
+       {3718,   20},
+       {3681,   16},
+       {3660,   14},
+       {3589,   10},
+       {3546,    7},
+       {3495,    4},
+       {3404,    2},
+       {3250,    0},
+};
+
+static struct abx500_v_to_cap cap_tbl[] = {
+       {4186,  100},
+       {4163,   99},
+       {4114,   95},
+       {4068,   90},
+       {3990,   80},
+       {3926,   70},
+       {3898,   65},
+       {3866,   60},
+       {3833,   55},
+       {3812,   50},
+       {3787,   40},
+       {3768,   30},
+       {3747,   25},
+       {3730,   20},
+       {3705,   15},
+       {3699,   14},
+       {3684,   12},
+       {3672,    9},
+       {3657,    7},
+       {3638,    6},
+       {3556,    4},
+       {3424,    2},
+       {3317,    1},
+       {3094,    0},
+};
+
+/*
+ * Note that the res_to_temp table must be strictly sorted by falling
+ * resistance values to work.
+ */
+static struct abx500_res_to_temp temp_tbl[] = {
+       {-5, 214834},
+       { 0, 162943},
+       { 5, 124820},
+       {10,  96520},
+       {15,  75306},
+       {20,  59254},
+       {25,  47000},
+       {30,  37566},
+       {35,  30245},
+       {40,  24520},
+       {45,  20010},
+       {50,  16432},
+       {55,  13576},
+       {60,  11280},
+       {65,   9425},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+static struct batres_vs_temp temp_to_batres_tbl_thermistor[] = {
+       { 40, 120},
+       { 30, 135},
+       { 20, 165},
+       { 10, 230},
+       { 00, 325},
+       {-10, 445},
+       {-20, 595},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+static struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = {
+       { 60, 300},
+       { 30, 300},
+       { 20, 300},
+       { 10, 300},
+       { 00, 300},
+       {-10, 300},
+       {-20, 300},
+};
+
+/* battery resistance table for LI ION 9100 battery */
+static struct batres_vs_temp temp_to_batres_tbl_9100[] = {
+       { 60, 180},
+       { 30, 180},
+       { 20, 180},
+       { 10, 180},
+       { 00, 180},
+       {-10, 180},
+       {-20, 180},
+};
+
+static struct abx500_battery_type bat_type_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+       /* First element always represent the UNKNOWN battery */
+       .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+       .resis_high = 0,
+       .resis_low = 0,
+       .battery_resistance = 300,
+       .charge_full_design = 612,
+       .nominal_voltage = 3700,
+       .termination_vol = 4050,
+       .termination_curr = 200,
+       .recharge_vol = 3990,
+       .normal_cur_lvl = 400,
+       .normal_vol_lvl = 4100,
+       .maint_a_cur_lvl = 400,
+       .maint_a_vol_lvl = 4050,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 400,
+       .maint_b_vol_lvl = 4000,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+       .resis_high = 53407,
+       .resis_low = 12500,
+       .battery_resistance = 300,
+       .charge_full_design = 900,
+       .nominal_voltage = 3600,
+       .termination_vol = 4150,
+       .termination_curr = 80,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor),
+       .r_to_t_tbl = temp_tbl_A_thermistor,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor),
+       .v_to_cap_tbl = cap_tbl_A_thermistor,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+       .resis_high = 200000,
+       .resis_low = 82869,
+       .battery_resistance = 300,
+       .charge_full_design = 900,
+       .nominal_voltage = 3600,
+       .termination_vol = 4150,
+       .termination_curr = 80,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor),
+       .r_to_t_tbl = temp_tbl_B_thermistor,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor),
+       .v_to_cap_tbl = cap_tbl_B_thermistor,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+
+static struct abx500_battery_type bat_type_ext_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+       /* First element always represent the UNKNOWN battery */
+       .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+       .resis_high = 0,
+       .resis_low = 0,
+       .battery_resistance = 300,
+       .charge_full_design = 612,
+       .nominal_voltage = 3700,
+       .termination_vol = 4050,
+       .termination_curr = 200,
+       .recharge_vol = 3990,
+       .normal_cur_lvl = 400,
+       .normal_vol_lvl = 4100,
+       .maint_a_cur_lvl = 400,
+       .maint_a_vol_lvl = 4050,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 400,
+       .maint_b_vol_lvl = 4000,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+/*
+ * These are the batteries that doesn't have an internal NTC resistor to measure
+ * its temperature. The temperature in this case is measure with a NTC placed
+ * near the battery but on the PCB.
+ */
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+       .resis_high = 76000,
+       .resis_low = 53000,
+       .battery_resistance = 300,
+       .charge_full_design = 900,
+       .nominal_voltage = 3700,
+       .termination_vol = 4150,
+       .termination_curr = 100,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LION,
+       .resis_high = 30000,
+       .resis_low = 10000,
+       .battery_resistance = 300,
+       .charge_full_design = 950,
+       .nominal_voltage = 3700,
+       .termination_vol = 4150,
+       .termination_curr = 100,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LION,
+       .resis_high = 95000,
+       .resis_low = 76001,
+       .battery_resistance = 300,
+       .charge_full_design = 950,
+       .nominal_voltage = 3700,
+       .termination_vol = 4150,
+       .termination_curr = 100,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+
+static const struct abx500_bm_capacity_levels cap_levels = {
+       .critical       = 2,
+       .low            = 10,
+       .normal         = 70,
+       .high           = 95,
+       .full           = 100,
+};
+
+static const struct abx500_fg_parameters fg = {
+       .recovery_sleep_timer = 10,
+       .recovery_total_time = 100,
+       .init_timer = 1,
+       .init_discard_time = 5,
+       .init_total_time = 40,
+       .high_curr_time = 60,
+       .accu_charging = 30,
+       .accu_high_curr = 30,
+       .high_curr_threshold = 50,
+       .lowbat_threshold = 3100,
+       .battok_falling_th_sel0 = 2860,
+       .battok_raising_th_sel1 = 2860,
+       .user_cap_limit = 15,
+       .maint_thres = 97,
+};
+
+static const struct abx500_maxim_parameters maxi_params = {
+       .ena_maxi = true,
+       .chg_curr = 910,
+       .wait_cycles = 10,
+       .charger_curr_step = 100,
+};
+
+static const struct abx500_bm_charger_parameters chg = {
+       .usb_volt_max           = 5500,
+       .usb_curr_max           = 1500,
+       .ac_volt_max            = 7500,
+       .ac_curr_max            = 1500,
+};
+
+struct abx500_bm_data ab8500_bm_data = {
+       .temp_under             = 3,
+       .temp_low               = 8,
+       .temp_high              = 43,
+       .temp_over              = 48,
+       .main_safety_tmr_h      = 4,
+       .temp_interval_chg      = 20,
+       .temp_interval_nochg    = 120,
+       .usb_safety_tmr_h       = 4,
+       .bkup_bat_v             = BUP_VCH_SEL_2P6V,
+       .bkup_bat_i             = BUP_ICH_SEL_150UA,
+       .no_maintenance         = false,
+       .adc_therm              = ABx500_ADC_THERM_BATCTRL,
+       .chg_unknown_bat        = false,
+       .enable_overshoot       = false,
+       .fg_res                 = 100,
+       .cap_levels             = &cap_levels,
+       .bat_type               = bat_type_thermistor,
+       .n_btypes               = 3,
+       .batt_id                = 0,
+       .interval_charging      = 5,
+       .interval_not_charging  = 120,
+       .temp_hysteresis        = 3,
+       .gnd_lift_resistance    = 34,
+       .maxi                   = &maxi_params,
+       .chg_params             = &chg,
+       .fg_params              = &fg,
+};
+
+int __devinit
+bmdevs_of_probe(struct device *dev,
+               struct device_node *np,
+               struct abx500_bm_data **battery)
+{
+       struct  abx500_battery_type *btype;
+       struct  device_node *np_bat_supply;
+       struct  abx500_bm_data *bat;
+       const char *btech;
+       char bat_tech[8];
+       int i, thermistor;
+
+       *battery = &ab8500_bm_data;
+
+       /* get phandle to 'battery-info' node */
+       np_bat_supply = of_parse_phandle(np, "battery", 0);
+       if (!np_bat_supply) {
+               dev_err(dev, "missing property battery\n");
+               return -EINVAL;
+       }
+       if (of_property_read_bool(np_bat_supply,
+                       "thermistor-on-batctrl"))
+               thermistor = NTC_INTERNAL;
+       else
+               thermistor = NTC_EXTERNAL;
+
+       bat = *battery;
+       if (thermistor == NTC_EXTERNAL) {
+               bat->n_btypes  = 4;
+               bat->bat_type  = bat_type_ext_thermistor;
+               bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
+       }
+       btech = of_get_property(np_bat_supply,
+               "stericsson,battery-type", NULL);
+       if (!btech) {
+               dev_warn(dev, "missing property battery-name/type\n");
+               strcpy(bat_tech, "UNKNOWN");
+       } else {
+               strcpy(bat_tech, btech);
+       }
+
+       if (strncmp(bat_tech, "LION", 4) == 0) {
+               bat->no_maintenance  = true;
+               bat->chg_unknown_bat = true;
+               bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
+               bat->bat_type[BATTERY_UNKNOWN].termination_vol    = 4150;
+               bat->bat_type[BATTERY_UNKNOWN].recharge_vol       = 4130;
+               bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl     = 520;
+               bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl     = 4200;
+       }
+       /* select the battery resolution table */
+       for (i = 0; i < bat->n_btypes; ++i) {
+               btype = (bat->bat_type + i);
+               if (thermistor == NTC_EXTERNAL) {
+                       btype->batres_tbl =
+                               temp_to_batres_tbl_ext_thermistor;
+               } else if (strncmp(bat_tech, "LION", 4) == 0) {
+                       btype->batres_tbl =
+                               temp_to_batres_tbl_9100;
+               } else {
+                       btype->batres_tbl =
+                               temp_to_batres_tbl_thermistor;
+               }
+       }
+       of_node_put(np_bat_supply);
+       return 0;
+}
index 989b09950affb71fefb663b5aafa5e7564f9ee2d..20e2a7d3ef43c0f6877aae8e5b3cb9c08fc6a9ae 100644 (file)
 #include <linux/power_supply.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
-#include <linux/mfd/abx500/ab8500.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
 #include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/jiffies.h>
 
 #define VTVOUT_V                       1800
 
@@ -76,7 +78,6 @@ struct ab8500_btemp_ranges {
  * @parent:            Pointer to the struct ab8500
  * @gpadc:             Pointer to the struct gpadc
  * @fg:                        Pointer to the struct fg
- * @pdata:             Pointer to the abx500_btemp platform data
  * @bat:               Pointer to the abx500_bm platform data
  * @btemp_psy:         Structure for BTEMP specific battery properties
  * @events:            Structure for information about events triggered
@@ -93,7 +94,6 @@ struct ab8500_btemp {
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
        struct ab8500_fg *fg;
-       struct abx500_btemp_platform_data *pdata;
        struct abx500_bm_data *bat;
        struct power_supply btemp_psy;
        struct ab8500_btemp_events events;
@@ -955,56 +955,57 @@ static int ab8500_btemp_remove(struct platform_device *pdev)
        flush_scheduled_work();
        power_supply_unregister(&di->btemp_psy);
        platform_set_drvdata(pdev, NULL);
-       kfree(di);
 
        return 0;
 }
 
+static char *supply_interface[] = {
+       "ab8500_chargalg",
+       "ab8500_fg",
+};
+
 static int ab8500_btemp_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
+       struct ab8500_btemp *di;
        int irq, i, ret = 0;
        u8 val;
-       struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
-       struct ab8500_btemp *di;
-
-       if (!plat_data) {
-               dev_err(&pdev->dev, "No platform data\n");
-               return -EINVAL;
-       }
 
-       di = kzalloc(sizeof(*di), GFP_KERNEL);
-       if (!di)
+       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+       if (!di) {
+               dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
                return -ENOMEM;
+       }
+       di->bat = pdev->mfd_cell->platform_data;
+       if (!di->bat) {
+               if (np) {
+                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "failed to get battery information\n");
+                               return ret;
+                       }
+               } else {
+                       dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
+                       return -EINVAL;
+               }
+       } else {
+               dev_info(&pdev->dev, "falling back to legacy platform data\n");
+       }
 
        /* get parent data */
        di->dev = &pdev->dev;
        di->parent = dev_get_drvdata(pdev->dev.parent);
        di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
-       /* get btemp specific platform data */
-       di->pdata = plat_data->btemp;
-       if (!di->pdata) {
-               dev_err(di->dev, "no btemp platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
-       }
-
-       /* get battery specific platform data */
-       di->bat = plat_data->battery;
-       if (!di->bat) {
-               dev_err(di->dev, "no battery platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
-       }
-
        /* BTEMP supply */
        di->btemp_psy.name = "ab8500_btemp";
        di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
        di->btemp_psy.properties = ab8500_btemp_props;
        di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
        di->btemp_psy.get_property = ab8500_btemp_get_property;
-       di->btemp_psy.supplied_to = di->pdata->supplied_to;
-       di->btemp_psy.num_supplicants = di->pdata->num_supplicants;
+       di->btemp_psy.supplied_to = supply_interface;
+       di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
        di->btemp_psy.external_power_changed =
                ab8500_btemp_external_power_changed;
 
@@ -1014,8 +1015,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
                create_singlethread_workqueue("ab8500_btemp_wq");
        if (di->btemp_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
-               ret = -ENOMEM;
-               goto free_device_info;
+               return -ENOMEM;
        }
 
        /* Init work for measuring temperature periodically */
@@ -1093,12 +1093,14 @@ free_irq:
        }
 free_btemp_wq:
        destroy_workqueue(di->btemp_wq);
-free_device_info:
-       kfree(di);
-
        return ret;
 }
 
+static const struct of_device_id ab8500_btemp_match[] = {
+       { .compatible = "stericsson,ab8500-btemp", },
+       { },
+};
+
 static struct platform_driver ab8500_btemp_driver = {
        .probe = ab8500_btemp_probe,
        .remove = ab8500_btemp_remove,
@@ -1107,6 +1109,7 @@ static struct platform_driver ab8500_btemp_driver = {
        .driver = {
                .name = "ab8500-btemp",
                .owner = THIS_MODULE,
+               .of_match_table = ab8500_btemp_match,
        },
 };
 
index 7ecb8abe20b54a69189772c5ed913ede3475cf29..3be9c0ee3fc58a2c016cb9509ceb316c54312b5f 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/err.h>
 #include <linux/workqueue.h>
 #include <linux/kobject.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
@@ -181,9 +183,9 @@ struct ab8500_charger_usb_state {
  * @vbat               Battery voltage
  * @old_vbat           Previously measured battery voltage
  * @autopower          Indicate if we should have automatic pwron after pwrloss
+ * @autopower_cfg      platform specific power config support for "pwron after pwrloss"
  * @parent:            Pointer to the struct ab8500
  * @gpadc:             Pointer to the struct gpadc
- * @pdata:             Pointer to the abx500_charger platform data
  * @bat:               Pointer to the abx500_bm platform data
  * @flags:             Structure for information about events triggered
  * @usb_state:         Structure for usb stack information
@@ -218,9 +220,9 @@ struct ab8500_charger {
        int vbat;
        int old_vbat;
        bool autopower;
+       bool autopower_cfg;
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
-       struct abx500_charger_platform_data *pdata;
        struct abx500_bm_data *bat;
        struct ab8500_charger_event_flags flags;
        struct ab8500_charger_usb_state usb_state;
@@ -322,7 +324,7 @@ static void ab8500_power_loss_handling(struct ab8500_charger *di)
 static void ab8500_power_supply_changed(struct ab8500_charger *di,
                                        struct power_supply *psy)
 {
-       if (di->pdata->autopower_cfg) {
+       if (di->autopower_cfg) {
                if (!di->usb.charger_connected &&
                    !di->ac.charger_connected &&
                    di->autopower) {
@@ -2526,25 +2528,45 @@ static int ab8500_charger_remove(struct platform_device *pdev)
        power_supply_unregister(&di->usb_chg.psy);
        power_supply_unregister(&di->ac_chg.psy);
        platform_set_drvdata(pdev, NULL);
-       kfree(di);
 
        return 0;
 }
 
+static char *supply_interface[] = {
+       "ab8500_chargalg",
+       "ab8500_fg",
+       "ab8500_btemp",
+};
+
 static int ab8500_charger_probe(struct platform_device *pdev)
 {
-       int irq, i, charger_status, ret = 0;
-       struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
        struct ab8500_charger *di;
+       int irq, i, charger_status, ret = 0;
 
-       if (!plat_data) {
-               dev_err(&pdev->dev, "No platform data\n");
-               return -EINVAL;
-       }
-
-       di = kzalloc(sizeof(*di), GFP_KERNEL);
-       if (!di)
+       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+       if (!di) {
+               dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__);
                return -ENOMEM;
+       }
+       di->bat = pdev->mfd_cell->platform_data;
+       if (!di->bat) {
+               if (np) {
+                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "failed to get battery information\n");
+                               return ret;
+                       }
+                       di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
+               } else {
+                       dev_err(&pdev->dev, "missing dt node for ab8500_charger\n");
+                       return -EINVAL;
+               }
+       } else {
+               dev_info(&pdev->dev, "falling back to legacy platform data\n");
+               di->autopower_cfg = false;
+       }
 
        /* get parent data */
        di->dev = &pdev->dev;
@@ -2554,22 +2576,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
        /* initialize lock */
        spin_lock_init(&di->usb_state.usb_lock);
 
-       /* get charger specific platform data */
-       di->pdata = plat_data->charger;
-       if (!di->pdata) {
-               dev_err(di->dev, "no charger platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
-       }
-
-       /* get battery specific platform data */
-       di->bat = plat_data->battery;
-       if (!di->bat) {
-               dev_err(di->dev, "no battery platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
-       }
-
        di->autopower = false;
 
        /* AC supply */
@@ -2579,8 +2585,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
        di->ac_chg.psy.properties = ab8500_charger_ac_props;
        di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props);
        di->ac_chg.psy.get_property = ab8500_charger_ac_get_property;
-       di->ac_chg.psy.supplied_to = di->pdata->supplied_to;
-       di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants;
+       di->ac_chg.psy.supplied_to = supply_interface;
+       di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
        /* ux500_charger sub-class */
        di->ac_chg.ops.enable = &ab8500_charger_ac_en;
        di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
@@ -2597,8 +2603,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
        di->usb_chg.psy.properties = ab8500_charger_usb_props;
        di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props);
        di->usb_chg.psy.get_property = ab8500_charger_usb_get_property;
-       di->usb_chg.psy.supplied_to = di->pdata->supplied_to;
-       di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants;
+       di->usb_chg.psy.supplied_to = supply_interface;
+       di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
        /* ux500_charger sub-class */
        di->usb_chg.ops.enable = &ab8500_charger_usb_en;
        di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
@@ -2614,8 +2620,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
                create_singlethread_workqueue("ab8500_charger_wq");
        if (di->charger_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
-               ret = -ENOMEM;
-               goto free_device_info;
+               return -ENOMEM;
        }
 
        /* Init work for HW failure check */
@@ -2757,12 +2762,14 @@ free_regulator:
        regulator_put(di->regu);
 free_charger_wq:
        destroy_workqueue(di->charger_wq);
-free_device_info:
-       kfree(di);
-
        return ret;
 }
 
+static const struct of_device_id ab8500_charger_match[] = {
+       { .compatible = "stericsson,ab8500-charger", },
+       { },
+};
+
 static struct platform_driver ab8500_charger_driver = {
        .probe = ab8500_charger_probe,
        .remove = ab8500_charger_remove,
@@ -2771,6 +2778,7 @@ static struct platform_driver ab8500_charger_driver = {
        .driver = {
                .name = "ab8500-charger",
                .owner = THIS_MODULE,
+               .of_match_table = ab8500_charger_match,
        },
 };
 
index 331dc43ded4e6fe319d336a5725431317e94b701..b3bf178c346270fdb22800c53ed21b574a25b956 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/kobject.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500.h>
 #include <linux/slab.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
 #include <linux/delay.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/mfd/abx500.h>
 #include <linux/time.h>
+#include <linux/of.h>
 #include <linux/completion.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+#include <linux/mfd/abx500/ab8500-gpadc.h>
 
 #define MILLI_TO_MICRO                 1000
 #define FG_LSB_IN_MA                   1627
@@ -172,7 +173,6 @@ struct inst_curr_result_list {
  * @avg_cap:           Average capacity filter
  * @parent:            Pointer to the struct ab8500
  * @gpadc:             Pointer to the struct gpadc
- * @pdata:             Pointer to the abx500_fg platform data
  * @bat:               Pointer to the abx500_bm platform data
  * @fg_psy:            Structure that holds the FG specific battery properties
  * @fg_wq:             Work queue for running the FG algorithm
@@ -212,7 +212,6 @@ struct ab8500_fg {
        struct ab8500_fg_avg_cap avg_cap;
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
-       struct abx500_fg_platform_data *pdata;
        struct abx500_bm_data *bat;
        struct power_supply fg_psy;
        struct workqueue_struct *fg_wq;
@@ -2429,7 +2428,6 @@ static int ab8500_fg_remove(struct platform_device *pdev)
        flush_scheduled_work();
        power_supply_unregister(&di->fg_psy);
        platform_set_drvdata(pdev, NULL);
-       kfree(di);
        return ret;
 }
 
@@ -2442,21 +2440,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
        {"CCEOC", ab8500_fg_cc_data_end_handler},
 };
 
+static char *supply_interface[] = {
+       "ab8500_chargalg",
+       "ab8500_usb",
+};
+
 static int ab8500_fg_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
+       struct ab8500_fg *di;
        int i, irq;
        int ret = 0;
-       struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
-       struct ab8500_fg *di;
-
-       if (!plat_data) {
-               dev_err(&pdev->dev, "No platform data\n");
-               return -EINVAL;
-       }
 
-       di = kzalloc(sizeof(*di), GFP_KERNEL);
-       if (!di)
+       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+       if (!di) {
+               dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
                return -ENOMEM;
+       }
+       di->bat = pdev->mfd_cell->platform_data;
+       if (!di->bat) {
+               if (np) {
+                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "failed to get battery information\n");
+                               return ret;
+                       }
+               } else {
+                       dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
+                       return -EINVAL;
+               }
+       } else {
+               dev_info(&pdev->dev, "falling back to legacy platform data\n");
+       }
 
        mutex_init(&di->cc_lock);
 
@@ -2465,29 +2481,13 @@ static int ab8500_fg_probe(struct platform_device *pdev)
        di->parent = dev_get_drvdata(pdev->dev.parent);
        di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
-       /* get fg specific platform data */
-       di->pdata = plat_data->fg;
-       if (!di->pdata) {
-               dev_err(di->dev, "no fg platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
-       }
-
-       /* get battery specific platform data */
-       di->bat = plat_data->battery;
-       if (!di->bat) {
-               dev_err(di->dev, "no battery platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
-       }
-
        di->fg_psy.name = "ab8500_fg";
        di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
        di->fg_psy.properties = ab8500_fg_props;
        di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
        di->fg_psy.get_property = ab8500_fg_get_property;
-       di->fg_psy.supplied_to = di->pdata->supplied_to;
-       di->fg_psy.num_supplicants = di->pdata->num_supplicants;
+       di->fg_psy.supplied_to = supply_interface;
+       di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
        di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
 
        di->bat_cap.max_mah_design = MILLI_TO_MICRO *
@@ -2506,8 +2506,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
        di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
        if (di->fg_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
-               ret = -ENOMEM;
-               goto free_device_info;
+               return -ENOMEM;
        }
 
        /* Init work for running the fg algorithm instantly */
@@ -2606,12 +2605,14 @@ free_irq:
        }
 free_inst_curr_wq:
        destroy_workqueue(di->fg_wq);
-free_device_info:
-       kfree(di);
-
        return ret;
 }
 
+static const struct of_device_id ab8500_fg_match[] = {
+       { .compatible = "stericsson,ab8500-fg", },
+       { },
+};
+
 static struct platform_driver ab8500_fg_driver = {
        .probe = ab8500_fg_probe,
        .remove = ab8500_fg_remove,
@@ -2620,6 +2621,7 @@ static struct platform_driver ab8500_fg_driver = {
        .driver = {
                .name = "ab8500-fg",
                .owner = THIS_MODULE,
+               .of_match_table = ab8500_fg_match,
        },
 };
 
index 19f25419079056b5a27260e53ce70639b0eeabdd..2970891460641177f53449dc1ff32b33ed26a375 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/kobject.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ux500_chargalg.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
@@ -205,7 +207,6 @@ enum maxim_ret {
  * @chg_info:          information about connected charger types
  * @batt_data:         data of the battery
  * @susp_status:       current charger suspension status
- * @pdata:             pointer to the abx500_chargalg platform data
  * @bat:               pointer to the abx500_bm platform data
  * @chargalg_psy:      structure that holds the battery properties exposed by
  *                     the charging algorithm
@@ -231,7 +232,6 @@ struct abx500_chargalg {
        struct abx500_chargalg_charger_info chg_info;
        struct abx500_chargalg_battery_data batt_data;
        struct abx500_chargalg_suspension_status susp_status;
-       struct abx500_chargalg_platform_data *pdata;
        struct abx500_bm_data *bat;
        struct power_supply chargalg_psy;
        struct ux500_charger *ac_chg;
@@ -1795,36 +1795,53 @@ static int abx500_chargalg_remove(struct platform_device *pdev)
        flush_scheduled_work();
        power_supply_unregister(&di->chargalg_psy);
        platform_set_drvdata(pdev, NULL);
-       kfree(di);
 
        return 0;
 }
 
+static char *supply_interface[] = {
+       "ab8500_fg",
+};
+
 static int abx500_chargalg_probe(struct platform_device *pdev)
 {
-       struct abx500_bm_plat_data *plat_data;
+       struct device_node *np = pdev->dev.of_node;
+       struct abx500_chargalg *di;
        int ret = 0;
 
-       struct abx500_chargalg *di =
-               kzalloc(sizeof(struct abx500_chargalg), GFP_KERNEL);
-       if (!di)
+       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+       if (!di) {
+               dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
                return -ENOMEM;
+       }
+       di->bat = pdev->mfd_cell->platform_data;
+       if (!di->bat) {
+               if (np) {
+                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "failed to get battery information\n");
+                               return ret;
+                       }
+               } else {
+                       dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n");
+                       return -EINVAL;
+               }
+       } else {
+               dev_info(&pdev->dev, "falling back to legacy platform data\n");
+       }
 
        /* get device struct */
        di->dev = &pdev->dev;
 
-       plat_data = pdev->dev.platform_data;
-       di->pdata = plat_data->chargalg;
-       di->bat = plat_data->battery;
-
        /* chargalg supply */
        di->chargalg_psy.name = "abx500_chargalg";
        di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
        di->chargalg_psy.properties = abx500_chargalg_props;
        di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props);
        di->chargalg_psy.get_property = abx500_chargalg_get_property;
-       di->chargalg_psy.supplied_to = di->pdata->supplied_to;
-       di->chargalg_psy.num_supplicants = di->pdata->num_supplicants;
+       di->chargalg_psy.supplied_to = supply_interface;
+       di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
        di->chargalg_psy.external_power_changed =
                abx500_chargalg_external_power_changed;
 
@@ -1844,7 +1861,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
                create_singlethread_workqueue("abx500_chargalg_wq");
        if (di->chargalg_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
-               goto free_device_info;
+               return -ENOMEM;
        }
 
        /* Init work for chargalg */
@@ -1885,20 +1902,23 @@ free_psy:
        power_supply_unregister(&di->chargalg_psy);
 free_chargalg_wq:
        destroy_workqueue(di->chargalg_wq);
-free_device_info:
-       kfree(di);
-
        return ret;
 }
 
+static const struct of_device_id ab8500_chargalg_match[] = {
+       { .compatible = "stericsson,ab8500-chargalg", },
+       { },
+};
+
 static struct platform_driver abx500_chargalg_driver = {
        .probe = abx500_chargalg_probe,
        .remove = abx500_chargalg_remove,
        .suspend = abx500_chargalg_suspend,
        .resume = abx500_chargalg_resume,
        .driver = {
-               .name = "abx500-chargalg",
+               .name = "ab8500-chargalg",
                .owner = THIS_MODULE,
+               .of_match_table = ab8500_chargalg_match,
        },
 };
 
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
new file mode 100644 (file)
index 0000000..ee842b3
--- /dev/null
@@ -0,0 +1,1670 @@
+/*
+ * bq2415x charger driver
+ *
+ * Copyright (C) 2011-2012  Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Datasheets:
+ * http://www.ti.com/product/bq24150
+ * http://www.ti.com/product/bq24150a
+ * http://www.ti.com/product/bq24152
+ * http://www.ti.com/product/bq24153
+ * http://www.ti.com/product/bq24153a
+ * http://www.ti.com/product/bq24155
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/idr.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include <linux/power/bq2415x_charger.h>
+
+/* timeout for resetting chip timer */
+#define BQ2415X_TIMER_TIMEOUT          10
+
+#define BQ2415X_REG_STATUS             0x00
+#define BQ2415X_REG_CONTROL            0x01
+#define BQ2415X_REG_VOLTAGE            0x02
+#define BQ2415X_REG_VENDER             0x03
+#define BQ2415X_REG_CURRENT            0x04
+
+/* reset state for all registers */
+#define BQ2415X_RESET_STATUS           BIT(6)
+#define BQ2415X_RESET_CONTROL          (BIT(4)|BIT(5))
+#define BQ2415X_RESET_VOLTAGE          (BIT(1)|BIT(3))
+#define BQ2415X_RESET_CURRENT          (BIT(0)|BIT(3)|BIT(7))
+
+/* status register */
+#define BQ2415X_BIT_TMR_RST            7
+#define BQ2415X_BIT_OTG                        7
+#define BQ2415X_BIT_EN_STAT            6
+#define BQ2415X_MASK_STAT              (BIT(4)|BIT(5))
+#define BQ2415X_SHIFT_STAT             4
+#define BQ2415X_BIT_BOOST              3
+#define BQ2415X_MASK_FAULT             (BIT(0)|BIT(1)|BIT(2))
+#define BQ2415X_SHIFT_FAULT            0
+
+/* control register */
+#define BQ2415X_MASK_LIMIT             (BIT(6)|BIT(7))
+#define BQ2415X_SHIFT_LIMIT            6
+#define BQ2415X_MASK_VLOWV             (BIT(4)|BIT(5))
+#define BQ2415X_SHIFT_VLOWV            4
+#define BQ2415X_BIT_TE                 3
+#define BQ2415X_BIT_CE                 2
+#define BQ2415X_BIT_HZ_MODE            1
+#define BQ2415X_BIT_OPA_MODE           0
+
+/* voltage register */
+#define BQ2415X_MASK_VO                (BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7))
+#define BQ2415X_SHIFT_VO               2
+#define BQ2415X_BIT_OTG_PL             1
+#define BQ2415X_BIT_OTG_EN             0
+
+/* vender register */
+#define BQ2415X_MASK_VENDER            (BIT(5)|BIT(6)|BIT(7))
+#define BQ2415X_SHIFT_VENDER           5
+#define BQ2415X_MASK_PN                        (BIT(3)|BIT(4))
+#define BQ2415X_SHIFT_PN               3
+#define BQ2415X_MASK_REVISION          (BIT(0)|BIT(1)|BIT(2))
+#define BQ2415X_SHIFT_REVISION         0
+
+/* current register */
+#define BQ2415X_MASK_RESET             BIT(7)
+#define BQ2415X_MASK_VI_CHRG           (BIT(4)|BIT(5)|BIT(6))
+#define BQ2415X_SHIFT_VI_CHRG          4
+/* N/A                                 BIT(3) */
+#define BQ2415X_MASK_VI_TERM           (BIT(0)|BIT(1)|BIT(2))
+#define BQ2415X_SHIFT_VI_TERM          0
+
+
+enum bq2415x_command {
+       BQ2415X_TIMER_RESET,
+       BQ2415X_OTG_STATUS,
+       BQ2415X_STAT_PIN_STATUS,
+       BQ2415X_STAT_PIN_ENABLE,
+       BQ2415X_STAT_PIN_DISABLE,
+       BQ2415X_CHARGE_STATUS,
+       BQ2415X_BOOST_STATUS,
+       BQ2415X_FAULT_STATUS,
+
+       BQ2415X_CHARGE_TERMINATION_STATUS,
+       BQ2415X_CHARGE_TERMINATION_ENABLE,
+       BQ2415X_CHARGE_TERMINATION_DISABLE,
+       BQ2415X_CHARGER_STATUS,
+       BQ2415X_CHARGER_ENABLE,
+       BQ2415X_CHARGER_DISABLE,
+       BQ2415X_HIGH_IMPEDANCE_STATUS,
+       BQ2415X_HIGH_IMPEDANCE_ENABLE,
+       BQ2415X_HIGH_IMPEDANCE_DISABLE,
+       BQ2415X_BOOST_MODE_STATUS,
+       BQ2415X_BOOST_MODE_ENABLE,
+       BQ2415X_BOOST_MODE_DISABLE,
+
+       BQ2415X_OTG_LEVEL,
+       BQ2415X_OTG_ACTIVATE_HIGH,
+       BQ2415X_OTG_ACTIVATE_LOW,
+       BQ2415X_OTG_PIN_STATUS,
+       BQ2415X_OTG_PIN_ENABLE,
+       BQ2415X_OTG_PIN_DISABLE,
+
+       BQ2415X_VENDER_CODE,
+       BQ2415X_PART_NUMBER,
+       BQ2415X_REVISION,
+};
+
+enum bq2415x_chip {
+       BQUNKNOWN,
+       BQ24150,
+       BQ24150A,
+       BQ24151,
+       BQ24151A,
+       BQ24152,
+       BQ24153,
+       BQ24153A,
+       BQ24155,
+       BQ24156,
+       BQ24156A,
+       BQ24158,
+};
+
+static char *bq2415x_chip_name[] = {
+       "unknown",
+       "bq24150",
+       "bq24150a",
+       "bq24151",
+       "bq24151a",
+       "bq24152",
+       "bq24153",
+       "bq24153a",
+       "bq24155",
+       "bq24156",
+       "bq24156a",
+       "bq24158",
+};
+
+struct bq2415x_device {
+       struct device *dev;
+       struct bq2415x_platform_data init_data;
+       struct power_supply charger;
+       struct delayed_work work;
+       enum bq2415x_mode reported_mode;/* mode reported by hook function */
+       enum bq2415x_mode mode;         /* current configured mode */
+       enum bq2415x_chip chip;
+       const char *timer_error;
+       char *model;
+       char *name;
+       int autotimer;  /* 1 - if driver automatically reset timer, 0 - not */
+       int automode;   /* 1 - enabled, 0 - disabled; -1 - not supported */
+       int id;
+};
+
+/* each registered chip must have unique id */
+static DEFINE_IDR(bq2415x_id);
+
+static DEFINE_MUTEX(bq2415x_id_mutex);
+static DEFINE_MUTEX(bq2415x_timer_mutex);
+static DEFINE_MUTEX(bq2415x_i2c_mutex);
+
+/**** i2c read functions ****/
+
+/* read value from register */
+static int bq2415x_i2c_read(struct bq2415x_device *bq, u8 reg)
+{
+       struct i2c_client *client = to_i2c_client(bq->dev);
+       struct i2c_msg msg[2];
+       u8 val;
+       int ret;
+
+       if (!client->adapter)
+               return -ENODEV;
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].buf = &reg;
+       msg[0].len = sizeof(reg);
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].buf = &val;
+       msg[1].len = sizeof(val);
+
+       mutex_lock(&bq2415x_i2c_mutex);
+       ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+       mutex_unlock(&bq2415x_i2c_mutex);
+
+       if (ret < 0)
+               return ret;
+
+       return val;
+}
+
+/* read value from register, apply mask and right shift it */
+static int bq2415x_i2c_read_mask(struct bq2415x_device *bq, u8 reg,
+                                u8 mask, u8 shift)
+{
+       int ret;
+
+       if (shift > 8)
+               return -EINVAL;
+
+       ret = bq2415x_i2c_read(bq, reg);
+       if (ret < 0)
+               return ret;
+       return (ret & mask) >> shift;
+}
+
+/* read value from register and return one specified bit */
+static int bq2415x_i2c_read_bit(struct bq2415x_device *bq, u8 reg, u8 bit)
+{
+       if (bit > 8)
+               return -EINVAL;
+       return bq2415x_i2c_read_mask(bq, reg, BIT(bit), bit);
+}
+
+/**** i2c write functions ****/
+
+/* write value to register */
+static int bq2415x_i2c_write(struct bq2415x_device *bq, u8 reg, u8 val)
+{
+       struct i2c_client *client = to_i2c_client(bq->dev);
+       struct i2c_msg msg[1];
+       u8 data[2];
+       int ret;
+
+       data[0] = reg;
+       data[1] = val;
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].buf = data;
+       msg[0].len = ARRAY_SIZE(data);
+
+       mutex_lock(&bq2415x_i2c_mutex);
+       ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+       mutex_unlock(&bq2415x_i2c_mutex);
+
+       /* i2c_transfer returns number of messages transferred */
+       if (ret < 0)
+               return ret;
+       else if (ret != 1)
+               return -EIO;
+
+       return 0;
+}
+
+/* read value from register, change it with mask left shifted and write back */
+static int bq2415x_i2c_write_mask(struct bq2415x_device *bq, u8 reg, u8 val,
+                                 u8 mask, u8 shift)
+{
+       int ret;
+
+       if (shift > 8)
+               return -EINVAL;
+
+       ret = bq2415x_i2c_read(bq, reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= ~mask;
+       ret |= val << shift;
+
+       return bq2415x_i2c_write(bq, reg, ret);
+}
+
+/* change only one bit in register */
+static int bq2415x_i2c_write_bit(struct bq2415x_device *bq, u8 reg,
+                                bool val, u8 bit)
+{
+       if (bit > 8)
+               return -EINVAL;
+       return bq2415x_i2c_write_mask(bq, reg, val, BIT(bit), bit);
+}
+
+/**** global functions ****/
+
+/* exec command function */
+static int bq2415x_exec_command(struct bq2415x_device *bq,
+                               enum bq2415x_command command)
+{
+       int ret;
+
+       switch (command) {
+       case BQ2415X_TIMER_RESET:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS,
+                               1, BQ2415X_BIT_TMR_RST);
+       case BQ2415X_OTG_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
+                               BQ2415X_BIT_OTG);
+       case BQ2415X_STAT_PIN_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
+                               BQ2415X_BIT_EN_STAT);
+       case BQ2415X_STAT_PIN_ENABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 1,
+                               BQ2415X_BIT_EN_STAT);
+       case BQ2415X_STAT_PIN_DISABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 0,
+                               BQ2415X_BIT_EN_STAT);
+       case BQ2415X_CHARGE_STATUS:
+               return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS,
+                               BQ2415X_MASK_STAT, BQ2415X_SHIFT_STAT);
+       case BQ2415X_BOOST_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
+                               BQ2415X_BIT_BOOST);
+       case BQ2415X_FAULT_STATUS:
+               return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS,
+                       BQ2415X_MASK_FAULT, BQ2415X_SHIFT_FAULT);
+
+       case BQ2415X_CHARGE_TERMINATION_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+                               BQ2415X_BIT_TE);
+       case BQ2415X_CHARGE_TERMINATION_ENABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               1, BQ2415X_BIT_TE);
+       case BQ2415X_CHARGE_TERMINATION_DISABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               0, BQ2415X_BIT_TE);
+       case BQ2415X_CHARGER_STATUS:
+               ret = bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+                       BQ2415X_BIT_CE);
+               if (ret < 0)
+                       return ret;
+               else
+                       return ret > 0 ? 0 : 1;
+       case BQ2415X_CHARGER_ENABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               0, BQ2415X_BIT_CE);
+       case BQ2415X_CHARGER_DISABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               1, BQ2415X_BIT_CE);
+       case BQ2415X_HIGH_IMPEDANCE_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+                               BQ2415X_BIT_HZ_MODE);
+       case BQ2415X_HIGH_IMPEDANCE_ENABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               1, BQ2415X_BIT_HZ_MODE);
+       case BQ2415X_HIGH_IMPEDANCE_DISABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               0, BQ2415X_BIT_HZ_MODE);
+       case BQ2415X_BOOST_MODE_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+                               BQ2415X_BIT_OPA_MODE);
+       case BQ2415X_BOOST_MODE_ENABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               1, BQ2415X_BIT_OPA_MODE);
+       case BQ2415X_BOOST_MODE_DISABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+                               0, BQ2415X_BIT_OPA_MODE);
+
+       case BQ2415X_OTG_LEVEL:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE,
+                               BQ2415X_BIT_OTG_PL);
+       case BQ2415X_OTG_ACTIVATE_HIGH:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+                               1, BQ2415X_BIT_OTG_PL);
+       case BQ2415X_OTG_ACTIVATE_LOW:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+                               0, BQ2415X_BIT_OTG_PL);
+       case BQ2415X_OTG_PIN_STATUS:
+               return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE,
+                               BQ2415X_BIT_OTG_EN);
+       case BQ2415X_OTG_PIN_ENABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+                               1, BQ2415X_BIT_OTG_EN);
+       case BQ2415X_OTG_PIN_DISABLE:
+               return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+                               0, BQ2415X_BIT_OTG_EN);
+
+       case BQ2415X_VENDER_CODE:
+               return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
+                       BQ2415X_MASK_VENDER, BQ2415X_SHIFT_VENDER);
+       case BQ2415X_PART_NUMBER:
+               return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
+                               BQ2415X_MASK_PN, BQ2415X_SHIFT_PN);
+       case BQ2415X_REVISION:
+               return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
+                       BQ2415X_MASK_REVISION, BQ2415X_SHIFT_REVISION);
+       }
+       return -EINVAL;
+}
+
+/* detect chip type */
+static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq)
+{
+       struct i2c_client *client = to_i2c_client(bq->dev);
+       int ret = bq2415x_exec_command(bq, BQ2415X_PART_NUMBER);
+
+       if (ret < 0)
+               return ret;
+
+       switch (client->addr) {
+       case 0x6b:
+               switch (ret) {
+               case 0:
+                       if (bq->chip == BQ24151A)
+                               return bq->chip;
+                       else
+                               return BQ24151;
+               case 1:
+                       if (bq->chip == BQ24150A ||
+                               bq->chip == BQ24152 ||
+                               bq->chip == BQ24155)
+                               return bq->chip;
+                       else
+                               return BQ24150;
+               case 2:
+                       if (bq->chip == BQ24153A)
+                               return bq->chip;
+                       else
+                               return BQ24153;
+               default:
+                       return BQUNKNOWN;
+               }
+               break;
+
+       case 0x6a:
+               switch (ret) {
+               case 0:
+                       if (bq->chip == BQ24156A)
+                               return bq->chip;
+                       else
+                               return BQ24156;
+               case 2:
+                       return BQ24158;
+               default:
+                       return BQUNKNOWN;
+               }
+               break;
+       }
+
+       return BQUNKNOWN;
+}
+
+/* detect chip revision */
+static int bq2415x_detect_revision(struct bq2415x_device *bq)
+{
+       int ret = bq2415x_exec_command(bq, BQ2415X_REVISION);
+       int chip = bq2415x_detect_chip(bq);
+
+       if (ret < 0 || chip < 0)
+               return -1;
+
+       switch (chip) {
+       case BQ24150:
+       case BQ24150A:
+       case BQ24151:
+       case BQ24151A:
+       case BQ24152:
+               if (ret >= 0 && ret <= 3)
+                       return ret;
+               else
+                       return -1;
+       case BQ24153:
+       case BQ24153A:
+       case BQ24156:
+       case BQ24156A:
+       case BQ24158:
+               if (ret == 3)
+                       return 0;
+               else if (ret == 1)
+                       return 1;
+               else
+                       return -1;
+       case BQ24155:
+               if (ret == 3)
+                       return 3;
+               else
+                       return -1;
+       case BQUNKNOWN:
+               return -1;
+       }
+
+       return -1;
+}
+
+/* return chip vender code */
+static int bq2415x_get_vender_code(struct bq2415x_device *bq)
+{
+       int ret;
+
+       ret = bq2415x_exec_command(bq, BQ2415X_VENDER_CODE);
+       if (ret < 0)
+               return 0;
+
+       /* convert to binary */
+       return (ret & 0x1) +
+              ((ret >> 1) & 0x1) * 10 +
+              ((ret >> 2) & 0x1) * 100;
+}
+
+/* reset all chip registers to default state */
+static void bq2415x_reset_chip(struct bq2415x_device *bq)
+{
+       bq2415x_i2c_write(bq, BQ2415X_REG_CURRENT, BQ2415X_RESET_CURRENT);
+       bq2415x_i2c_write(bq, BQ2415X_REG_VOLTAGE, BQ2415X_RESET_VOLTAGE);
+       bq2415x_i2c_write(bq, BQ2415X_REG_CONTROL, BQ2415X_RESET_CONTROL);
+       bq2415x_i2c_write(bq, BQ2415X_REG_STATUS, BQ2415X_RESET_STATUS);
+       bq->timer_error = NULL;
+}
+
+/**** properties functions ****/
+
+/* set current limit in mA */
+static int bq2415x_set_current_limit(struct bq2415x_device *bq, int mA)
+{
+       int val;
+
+       if (mA <= 100)
+               val = 0;
+       else if (mA <= 500)
+               val = 1;
+       else if (mA <= 800)
+               val = 2;
+       else
+               val = 3;
+
+       return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val,
+                       BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT);
+}
+
+/* get current limit in mA */
+static int bq2415x_get_current_limit(struct bq2415x_device *bq)
+{
+       int ret;
+
+       ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL,
+                       BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT);
+       if (ret < 0)
+               return ret;
+       else if (ret == 0)
+               return 100;
+       else if (ret == 1)
+               return 500;
+       else if (ret == 2)
+               return 800;
+       else if (ret == 3)
+               return 1800;
+       return -EINVAL;
+}
+
+/* set weak battery voltage in mV */
+static int bq2415x_set_weak_battery_voltage(struct bq2415x_device *bq, int mV)
+{
+       int val;
+
+       /* round to 100mV */
+       if (mV <= 3400 + 50)
+               val = 0;
+       else if (mV <= 3500 + 50)
+               val = 1;
+       else if (mV <= 3600 + 50)
+               val = 2;
+       else
+               val = 3;
+
+       return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val,
+                       BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV);
+}
+
+/* get weak battery voltage in mV */
+static int bq2415x_get_weak_battery_voltage(struct bq2415x_device *bq)
+{
+       int ret;
+
+       ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL,
+                       BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV);
+       if (ret < 0)
+               return ret;
+       return 100 * (34 + ret);
+}
+
+/* set battery regulation voltage in mV */
+static int bq2415x_set_battery_regulation_voltage(struct bq2415x_device *bq,
+                                                 int mV)
+{
+       int val = (mV/10 - 350) / 2;
+
+       if (val < 0)
+               val = 0;
+       else if (val > 94) /* FIXME: Max is 94 or 122 ? Set max value ? */
+               return -EINVAL;
+
+       return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val,
+                       BQ2415X_MASK_VO, BQ2415X_SHIFT_VO);
+}
+
+/* get battery regulation voltage in mV */
+static int bq2415x_get_battery_regulation_voltage(struct bq2415x_device *bq)
+{
+       int ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_VOLTAGE,
+                       BQ2415X_MASK_VO, BQ2415X_SHIFT_VO);
+
+       if (ret < 0)
+               return ret;
+       return 10 * (350 + 2*ret);
+}
+
+/* set charge current in mA (platform data must provide resistor sense) */
+static int bq2415x_set_charge_current(struct bq2415x_device *bq, int mA)
+{
+       int val;
+
+       if (bq->init_data.resistor_sense <= 0)
+               return -ENOSYS;
+
+       val = (mA * bq->init_data.resistor_sense - 37400) / 6800;
+       if (val < 0)
+               val = 0;
+       else if (val > 7)
+               val = 7;
+
+       return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val,
+                       BQ2415X_MASK_VI_CHRG | BQ2415X_MASK_RESET,
+                       BQ2415X_SHIFT_VI_CHRG);
+}
+
+/* get charge current in mA (platform data must provide resistor sense) */
+static int bq2415x_get_charge_current(struct bq2415x_device *bq)
+{
+       int ret;
+
+       if (bq->init_data.resistor_sense <= 0)
+               return -ENOSYS;
+
+       ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT,
+                       BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG);
+       if (ret < 0)
+               return ret;
+       return (37400 + 6800*ret) / bq->init_data.resistor_sense;
+}
+
+/* set termination current in mA (platform data must provide resistor sense) */
+static int bq2415x_set_termination_current(struct bq2415x_device *bq, int mA)
+{
+       int val;
+
+       if (bq->init_data.resistor_sense <= 0)
+               return -ENOSYS;
+
+       val = (mA * bq->init_data.resistor_sense - 3400) / 3400;
+       if (val < 0)
+               val = 0;
+       else if (val > 7)
+               val = 7;
+
+       return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val,
+                       BQ2415X_MASK_VI_TERM | BQ2415X_MASK_RESET,
+                       BQ2415X_SHIFT_VI_TERM);
+}
+
+/* get termination current in mA (platform data must provide resistor sense) */
+static int bq2415x_get_termination_current(struct bq2415x_device *bq)
+{
+       int ret;
+
+       if (bq->init_data.resistor_sense <= 0)
+               return -ENOSYS;
+
+       ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT,
+                       BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM);
+       if (ret < 0)
+               return ret;
+       return (3400 + 3400*ret) / bq->init_data.resistor_sense;
+}
+
+/* set default value of property */
+#define bq2415x_set_default_value(bq, prop) \
+       do { \
+               int ret = 0; \
+               if (bq->init_data.prop != -1) \
+                       ret = bq2415x_set_##prop(bq, bq->init_data.prop); \
+               if (ret < 0) \
+                       return ret; \
+       } while (0)
+
+/* set default values of all properties */
+static int bq2415x_set_defaults(struct bq2415x_device *bq)
+{
+       bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE);
+       bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE);
+       bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_DISABLE);
+
+       bq2415x_set_default_value(bq, current_limit);
+       bq2415x_set_default_value(bq, weak_battery_voltage);
+       bq2415x_set_default_value(bq, battery_regulation_voltage);
+
+       if (bq->init_data.resistor_sense > 0) {
+               bq2415x_set_default_value(bq, charge_current);
+               bq2415x_set_default_value(bq, termination_current);
+               bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_ENABLE);
+       }
+
+       bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE);
+       return 0;
+}
+
+/**** charger mode functions ****/
+
+/* set charger mode */
+static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
+{
+       int ret = 0;
+       int charger = 0;
+       int boost = 0;
+
+       if (mode == BQ2415X_MODE_HOST_CHARGER ||
+               mode == BQ2415X_MODE_DEDICATED_CHARGER)
+                       charger = 1;
+
+       if (mode == BQ2415X_MODE_BOOST)
+               boost = 1;
+
+       if (!charger)
+               ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE);
+
+       if (!boost)
+               ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE);
+
+       if (ret < 0)
+               return ret;
+
+       switch (mode) {
+       case BQ2415X_MODE_NONE:
+               dev_dbg(bq->dev, "changing mode to: N/A\n");
+               ret = bq2415x_set_current_limit(bq, 100);
+               break;
+       case BQ2415X_MODE_HOST_CHARGER:
+               dev_dbg(bq->dev, "changing mode to: Host/HUB charger\n");
+               ret = bq2415x_set_current_limit(bq, 500);
+               break;
+       case BQ2415X_MODE_DEDICATED_CHARGER:
+               dev_dbg(bq->dev, "changing mode to: Dedicated charger\n");
+               ret = bq2415x_set_current_limit(bq, 1800);
+               break;
+       case BQ2415X_MODE_BOOST: /* Boost mode */
+               dev_dbg(bq->dev, "changing mode to: Boost\n");
+               ret = bq2415x_set_current_limit(bq, 100);
+               break;
+       }
+
+       if (ret < 0)
+               return ret;
+
+       if (charger)
+               ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE);
+       else if (boost)
+               ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_ENABLE);
+
+       if (ret < 0)
+               return ret;
+
+       bq2415x_set_default_value(bq, weak_battery_voltage);
+       bq2415x_set_default_value(bq, battery_regulation_voltage);
+
+       bq->mode = mode;
+       sysfs_notify(&bq->charger.dev->kobj, NULL, "mode");
+
+       return 0;
+
+}
+
+/* hook function called by other driver which set reported mode */
+static void bq2415x_hook_function(enum bq2415x_mode mode, void *data)
+{
+       struct bq2415x_device *bq = data;
+
+       if (!bq)
+               return;
+
+       dev_dbg(bq->dev, "hook function was called\n");
+       bq->reported_mode = mode;
+
+       /* if automode is not enabled do not tell about reported_mode */
+       if (bq->automode < 1)
+               return;
+
+       sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
+       bq2415x_set_mode(bq, bq->reported_mode);
+
+}
+
+/**** timer functions ****/
+
+/* enable/disable auto resetting chip timer */
+static void bq2415x_set_autotimer(struct bq2415x_device *bq, int state)
+{
+       mutex_lock(&bq2415x_timer_mutex);
+
+       if (bq->autotimer == state) {
+               mutex_unlock(&bq2415x_timer_mutex);
+               return;
+       }
+
+       bq->autotimer = state;
+
+       if (state) {
+               schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ);
+               bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
+               bq->timer_error = NULL;
+       } else {
+               cancel_delayed_work_sync(&bq->work);
+       }
+
+       mutex_unlock(&bq2415x_timer_mutex);
+}
+
+/* called by bq2415x_timer_work on timer error */
+static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg)
+{
+       bq->timer_error = msg;
+       sysfs_notify(&bq->charger.dev->kobj, NULL, "timer");
+       dev_err(bq->dev, "%s\n", msg);
+       if (bq->automode > 0)
+               bq->automode = 0;
+       bq2415x_set_mode(bq, BQ2415X_MODE_NONE);
+       bq2415x_set_autotimer(bq, 0);
+}
+
+/* delayed work function for auto resetting chip timer */
+static void bq2415x_timer_work(struct work_struct *work)
+{
+       struct bq2415x_device *bq = container_of(work, struct bq2415x_device,
+                                                work.work);
+       int ret;
+       int error;
+       int boost;
+
+       if (!bq->autotimer)
+               return;
+
+       ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
+       if (ret < 0) {
+               bq2415x_timer_error(bq, "Resetting timer failed");
+               return;
+       }
+
+       boost = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_STATUS);
+       if (boost < 0) {
+               bq2415x_timer_error(bq, "Unknown error");
+               return;
+       }
+
+       error = bq2415x_exec_command(bq, BQ2415X_FAULT_STATUS);
+       if (error < 0) {
+               bq2415x_timer_error(bq, "Unknown error");
+               return;
+       }
+
+       if (boost) {
+               switch (error) {
+               /* Non fatal errors, chip is OK */
+               case 0: /* No error */
+                       break;
+               case 6: /* Timer expired */
+                       dev_err(bq->dev, "Timer expired\n");
+                       break;
+               case 3: /* Battery voltage too low */
+                       dev_err(bq->dev, "Battery voltage to low\n");
+                       break;
+
+               /* Fatal errors, disable and reset chip */
+               case 1: /* Overvoltage protection (chip fried) */
+                       bq2415x_timer_error(bq,
+                               "Overvoltage protection (chip fried)");
+                       return;
+               case 2: /* Overload */
+                       bq2415x_timer_error(bq, "Overload");
+                       return;
+               case 4: /* Battery overvoltage protection */
+                       bq2415x_timer_error(bq,
+                               "Battery overvoltage protection");
+                       return;
+               case 5: /* Thermal shutdown (too hot) */
+                       bq2415x_timer_error(bq,
+                                       "Thermal shutdown (too hot)");
+                       return;
+               case 7: /* N/A */
+                       bq2415x_timer_error(bq, "Unknown error");
+                       return;
+               }
+       } else {
+               switch (error) {
+               /* Non fatal errors, chip is OK */
+               case 0: /* No error */
+                       break;
+               case 2: /* Sleep mode */
+                       dev_err(bq->dev, "Sleep mode\n");
+                       break;
+               case 3: /* Poor input source */
+                       dev_err(bq->dev, "Poor input source\n");
+                       break;
+               case 6: /* Timer expired */
+                       dev_err(bq->dev, "Timer expired\n");
+                       break;
+               case 7: /* No battery */
+                       dev_err(bq->dev, "No battery\n");
+                       break;
+
+               /* Fatal errors, disable and reset chip */
+               case 1: /* Overvoltage protection (chip fried) */
+                       bq2415x_timer_error(bq,
+                               "Overvoltage protection (chip fried)");
+                       return;
+               case 4: /* Battery overvoltage protection */
+                       bq2415x_timer_error(bq,
+                               "Battery overvoltage protection");
+                       return;
+               case 5: /* Thermal shutdown (too hot) */
+                       bq2415x_timer_error(bq,
+                               "Thermal shutdown (too hot)");
+                       return;
+               }
+       }
+
+       schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ);
+}
+
+/**** power supply interface code ****/
+
+static enum power_supply_property bq2415x_power_supply_props[] = {
+       /* TODO: maybe add more power supply properties */
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_MODEL_NAME,
+};
+
+static int bq2415x_power_supply_get_property(struct power_supply *psy,
+                                            enum power_supply_property psp,
+                                            union power_supply_propval *val)
+{
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS);
+               if (ret < 0)
+                       return ret;
+               else if (ret == 0) /* Ready */
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               else if (ret == 1) /* Charge in progress */
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               else if (ret == 2) /* Charge done */
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+               else
+                       val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+               break;
+       case POWER_SUPPLY_PROP_MODEL_NAME:
+               val->strval = bq->model;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int bq2415x_power_supply_init(struct bq2415x_device *bq)
+{
+       int ret;
+       int chip;
+       char revstr[8];
+
+       bq->charger.name = bq->name;
+       bq->charger.type = POWER_SUPPLY_TYPE_USB;
+       bq->charger.properties = bq2415x_power_supply_props;
+       bq->charger.num_properties = ARRAY_SIZE(bq2415x_power_supply_props);
+       bq->charger.get_property = bq2415x_power_supply_get_property;
+
+       ret = bq2415x_detect_chip(bq);
+       if (ret < 0)
+               chip = BQUNKNOWN;
+       else
+               chip = ret;
+
+       ret = bq2415x_detect_revision(bq);
+       if (ret < 0)
+               strcpy(revstr, "unknown");
+       else
+               sprintf(revstr, "1.%d", ret);
+
+       bq->model = kasprintf(GFP_KERNEL,
+                               "chip %s, revision %s, vender code %.3d",
+                               bq2415x_chip_name[chip], revstr,
+                               bq2415x_get_vender_code(bq));
+       if (!bq->model) {
+               dev_err(bq->dev, "failed to allocate model name\n");
+               return -ENOMEM;
+       }
+
+       ret = power_supply_register(bq->dev, &bq->charger);
+       if (ret) {
+               kfree(bq->model);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void bq2415x_power_supply_exit(struct bq2415x_device *bq)
+{
+       bq->autotimer = 0;
+       if (bq->automode > 0)
+               bq->automode = 0;
+       cancel_delayed_work_sync(&bq->work);
+       power_supply_unregister(&bq->charger);
+       kfree(bq->model);
+}
+
+/**** additional sysfs entries for power supply interface ****/
+
+/* show *_status entries */
+static ssize_t bq2415x_sysfs_show_status(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                               charger);
+       enum bq2415x_command command;
+       int ret;
+
+       if (strcmp(attr->attr.name, "otg_status") == 0)
+               command = BQ2415X_OTG_STATUS;
+       else if (strcmp(attr->attr.name, "charge_status") == 0)
+               command = BQ2415X_CHARGE_STATUS;
+       else if (strcmp(attr->attr.name, "boost_status") == 0)
+               command = BQ2415X_BOOST_STATUS;
+       else if (strcmp(attr->attr.name, "fault_status") == 0)
+               command = BQ2415X_FAULT_STATUS;
+       else
+               return -EINVAL;
+
+       ret = bq2415x_exec_command(bq, command);
+       if (ret < 0)
+               return ret;
+       return sprintf(buf, "%d\n", ret);
+}
+
+/*
+ * set timer entry:
+ *    auto - enable auto mode
+ *    off - disable auto mode
+ *    (other values) - reset chip timer
+ */
+static ssize_t bq2415x_sysfs_set_timer(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf,
+                                      size_t count)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                               charger);
+       int ret = 0;
+
+       if (strncmp(buf, "auto", 4) == 0)
+               bq2415x_set_autotimer(bq, 1);
+       else if (strncmp(buf, "off", 3) == 0)
+               bq2415x_set_autotimer(bq, 0);
+       else
+               ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
+
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+/* show timer entry (auto or off) */
+static ssize_t bq2415x_sysfs_show_timer(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+
+       if (bq->timer_error)
+               return sprintf(buf, "%s\n", bq->timer_error);
+
+       if (bq->autotimer)
+               return sprintf(buf, "auto\n");
+       return sprintf(buf, "off\n");
+}
+
+/*
+ * set mode entry:
+ *    auto - if automode is supported, enable it and set mode to reported
+ *    none - disable charger and boost mode
+ *    host - charging mode for host/hub chargers (current limit 500mA)
+ *    dedicated - charging mode for dedicated chargers (unlimited current limit)
+ *    boost - disable charger and enable boost mode
+ */
+static ssize_t bq2415x_sysfs_set_mode(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf,
+                                     size_t count)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       enum bq2415x_mode mode;
+       int ret = 0;
+
+       if (strncmp(buf, "auto", 4) == 0) {
+               if (bq->automode < 0)
+                       return -ENOSYS;
+               bq->automode = 1;
+               mode = bq->reported_mode;
+       } else if (strncmp(buf, "none", 4) == 0) {
+               if (bq->automode > 0)
+                       bq->automode = 0;
+               mode = BQ2415X_MODE_NONE;
+       } else if (strncmp(buf, "host", 4) == 0) {
+               if (bq->automode > 0)
+                       bq->automode = 0;
+               mode = BQ2415X_MODE_HOST_CHARGER;
+       } else if (strncmp(buf, "dedicated", 9) == 0) {
+               if (bq->automode > 0)
+                       bq->automode = 0;
+               mode = BQ2415X_MODE_DEDICATED_CHARGER;
+       } else if (strncmp(buf, "boost", 5) == 0) {
+               if (bq->automode > 0)
+                       bq->automode = 0;
+               mode = BQ2415X_MODE_BOOST;
+       } else if (strncmp(buf, "reset", 5) == 0) {
+               bq2415x_reset_chip(bq);
+               bq2415x_set_defaults(bq);
+               if (bq->automode <= 0)
+                       return count;
+               bq->automode = 1;
+               mode = bq->reported_mode;
+       } else {
+               return -EINVAL;
+       }
+
+       ret = bq2415x_set_mode(bq, mode);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+/* show mode entry (auto, none, host, dedicated or boost) */
+static ssize_t bq2415x_sysfs_show_mode(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                               charger);
+       ssize_t ret = 0;
+
+       if (bq->automode > 0)
+               ret += sprintf(buf+ret, "auto (");
+
+       switch (bq->mode) {
+       case BQ2415X_MODE_NONE:
+               ret += sprintf(buf+ret, "none");
+               break;
+       case BQ2415X_MODE_HOST_CHARGER:
+               ret += sprintf(buf+ret, "host");
+               break;
+       case BQ2415X_MODE_DEDICATED_CHARGER:
+               ret += sprintf(buf+ret, "dedicated");
+               break;
+       case BQ2415X_MODE_BOOST:
+               ret += sprintf(buf+ret, "boost");
+               break;
+       }
+
+       if (bq->automode > 0)
+               ret += sprintf(buf+ret, ")");
+
+       ret += sprintf(buf+ret, "\n");
+       return ret;
+}
+
+/* show reported_mode entry (none, host, dedicated or boost) */
+static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev,
+                                               struct device_attribute *attr,
+                                               char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+
+       if (bq->automode < 0)
+               return -EINVAL;
+
+       switch (bq->reported_mode) {
+       case BQ2415X_MODE_NONE:
+               return sprintf(buf, "none\n");
+       case BQ2415X_MODE_HOST_CHARGER:
+               return sprintf(buf, "host\n");
+       case BQ2415X_MODE_DEDICATED_CHARGER:
+               return sprintf(buf, "dedicated\n");
+       case BQ2415X_MODE_BOOST:
+               return sprintf(buf, "boost\n");
+       }
+
+       return -EINVAL;
+}
+
+/* directly set raw value to chip register, format: 'register value' */
+static ssize_t bq2415x_sysfs_set_registers(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf,
+                                          size_t count)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       ssize_t ret = 0;
+       unsigned int reg;
+       unsigned int val;
+
+       if (sscanf(buf, "%x %x", &reg, &val) != 2)
+               return -EINVAL;
+
+       if (reg > 4 || val > 255)
+               return -EINVAL;
+
+       ret = bq2415x_i2c_write(bq, reg, val);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+/* print value of chip register, format: 'register=value' */
+static ssize_t bq2415x_sysfs_print_reg(struct bq2415x_device *bq,
+                                      u8 reg,
+                                      char *buf)
+{
+       int ret = bq2415x_i2c_read(bq, reg);
+
+       if (ret < 0)
+               return sprintf(buf, "%#.2x=error %d\n", reg, ret);
+       return sprintf(buf, "%#.2x=%#.2x\n", reg, ret);
+}
+
+/* show all raw values of chip register, format per line: 'register=value' */
+static ssize_t bq2415x_sysfs_show_registers(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       ssize_t ret = 0;
+
+       ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_STATUS, buf+ret);
+       ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CONTROL, buf+ret);
+       ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VOLTAGE, buf+ret);
+       ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VENDER, buf+ret);
+       ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CURRENT, buf+ret);
+       return ret;
+}
+
+/* set current and voltage limit entries (in mA or mV) */
+static ssize_t bq2415x_sysfs_set_limit(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf,
+                                      size_t count)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       long val;
+       int ret;
+
+       if (kstrtol(buf, 10, &val) < 0)
+               return -EINVAL;
+
+       if (strcmp(attr->attr.name, "current_limit") == 0)
+               ret = bq2415x_set_current_limit(bq, val);
+       else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0)
+               ret = bq2415x_set_weak_battery_voltage(bq, val);
+       else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0)
+               ret = bq2415x_set_battery_regulation_voltage(bq, val);
+       else if (strcmp(attr->attr.name, "charge_current") == 0)
+               ret = bq2415x_set_charge_current(bq, val);
+       else if (strcmp(attr->attr.name, "termination_current") == 0)
+               ret = bq2415x_set_termination_current(bq, val);
+       else
+               return -EINVAL;
+
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+/* show current and voltage limit entries (in mA or mV) */
+static ssize_t bq2415x_sysfs_show_limit(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       int ret;
+
+       if (strcmp(attr->attr.name, "current_limit") == 0)
+               ret = bq2415x_get_current_limit(bq);
+       else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0)
+               ret = bq2415x_get_weak_battery_voltage(bq);
+       else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0)
+               ret = bq2415x_get_battery_regulation_voltage(bq);
+       else if (strcmp(attr->attr.name, "charge_current") == 0)
+               ret = bq2415x_get_charge_current(bq);
+       else if (strcmp(attr->attr.name, "termination_current") == 0)
+               ret = bq2415x_get_termination_current(bq);
+       else
+               return -EINVAL;
+
+       if (ret < 0)
+               return ret;
+       return sprintf(buf, "%d\n", ret);
+}
+
+/* set *_enable entries */
+static ssize_t bq2415x_sysfs_set_enable(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf,
+                                       size_t count)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       enum bq2415x_command command;
+       long val;
+       int ret;
+
+       if (kstrtol(buf, 10, &val) < 0)
+               return -EINVAL;
+
+       if (strcmp(attr->attr.name, "charge_termination_enable") == 0)
+               command = val ? BQ2415X_CHARGE_TERMINATION_ENABLE :
+                       BQ2415X_CHARGE_TERMINATION_DISABLE;
+       else if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
+               command = val ? BQ2415X_HIGH_IMPEDANCE_ENABLE :
+                       BQ2415X_HIGH_IMPEDANCE_DISABLE;
+       else if (strcmp(attr->attr.name, "otg_pin_enable") == 0)
+               command = val ? BQ2415X_OTG_PIN_ENABLE :
+                       BQ2415X_OTG_PIN_DISABLE;
+       else if (strcmp(attr->attr.name, "stat_pin_enable") == 0)
+               command = val ? BQ2415X_STAT_PIN_ENABLE :
+                       BQ2415X_STAT_PIN_DISABLE;
+       else
+               return -EINVAL;
+
+       ret = bq2415x_exec_command(bq, command);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+/* show *_enable entries */
+static ssize_t bq2415x_sysfs_show_enable(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct power_supply *psy = dev_get_drvdata(dev);
+       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+                                                charger);
+       enum bq2415x_command command;
+       int ret;
+
+       if (strcmp(attr->attr.name, "charge_termination_enable") == 0)
+               command = BQ2415X_CHARGE_TERMINATION_STATUS;
+       else if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
+               command = BQ2415X_HIGH_IMPEDANCE_STATUS;
+       else if (strcmp(attr->attr.name, "otg_pin_enable") == 0)
+               command = BQ2415X_OTG_PIN_STATUS;
+       else if (strcmp(attr->attr.name, "stat_pin_enable") == 0)
+               command = BQ2415X_STAT_PIN_STATUS;
+       else
+               return -EINVAL;
+
+       ret = bq2415x_exec_command(bq, command);
+       if (ret < 0)
+               return ret;
+       return sprintf(buf, "%d\n", ret);
+}
+
+static DEVICE_ATTR(current_limit, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(weak_battery_voltage, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(battery_regulation_voltage, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(charge_current, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(termination_current, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+
+static DEVICE_ATTR(charge_termination_enable, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+static DEVICE_ATTR(otg_pin_enable, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+static DEVICE_ATTR(stat_pin_enable, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+
+static DEVICE_ATTR(reported_mode, S_IRUGO,
+               bq2415x_sysfs_show_reported_mode, NULL);
+static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_mode, bq2415x_sysfs_set_mode);
+static DEVICE_ATTR(timer, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_timer, bq2415x_sysfs_set_timer);
+
+static DEVICE_ATTR(registers, S_IWUSR | S_IRUGO,
+               bq2415x_sysfs_show_registers, bq2415x_sysfs_set_registers);
+
+static DEVICE_ATTR(otg_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+static DEVICE_ATTR(charge_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+static DEVICE_ATTR(boost_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+static DEVICE_ATTR(fault_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+
+static struct attribute *bq2415x_sysfs_attributes[] = {
+       /*
+        * TODO: some (appropriate) of these attrs should be switched to
+        * use power supply class props.
+        */
+       &dev_attr_current_limit.attr,
+       &dev_attr_weak_battery_voltage.attr,
+       &dev_attr_battery_regulation_voltage.attr,
+       &dev_attr_charge_current.attr,
+       &dev_attr_termination_current.attr,
+
+       &dev_attr_charge_termination_enable.attr,
+       &dev_attr_high_impedance_enable.attr,
+       &dev_attr_otg_pin_enable.attr,
+       &dev_attr_stat_pin_enable.attr,
+
+       &dev_attr_reported_mode.attr,
+       &dev_attr_mode.attr,
+       &dev_attr_timer.attr,
+
+       &dev_attr_registers.attr,
+
+       &dev_attr_otg_status.attr,
+       &dev_attr_charge_status.attr,
+       &dev_attr_boost_status.attr,
+       &dev_attr_fault_status.attr,
+       NULL,
+};
+
+static const struct attribute_group bq2415x_sysfs_attr_group = {
+       .attrs = bq2415x_sysfs_attributes,
+};
+
+static int bq2415x_sysfs_init(struct bq2415x_device *bq)
+{
+       return sysfs_create_group(&bq->charger.dev->kobj,
+                       &bq2415x_sysfs_attr_group);
+}
+
+static void bq2415x_sysfs_exit(struct bq2415x_device *bq)
+{
+       sysfs_remove_group(&bq->charger.dev->kobj, &bq2415x_sysfs_attr_group);
+}
+
+/* main bq2415x probe function */
+static int bq2415x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       int ret;
+       int num;
+       char *name;
+       struct bq2415x_device *bq;
+
+       if (!client->dev.platform_data) {
+               dev_err(&client->dev, "platform data not set\n");
+               return -ENODEV;
+       }
+
+       /* Get new ID for the new device */
+       ret = idr_pre_get(&bq2415x_id, GFP_KERNEL);
+       if (ret == 0)
+               return -ENOMEM;
+
+       mutex_lock(&bq2415x_id_mutex);
+       ret = idr_get_new(&bq2415x_id, client, &num);
+       mutex_unlock(&bq2415x_id_mutex);
+
+       if (ret < 0)
+               return ret;
+
+       name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
+       if (!name) {
+               dev_err(&client->dev, "failed to allocate device name\n");
+               ret = -ENOMEM;
+               goto error_1;
+       }
+
+       bq = kzalloc(sizeof(*bq), GFP_KERNEL);
+       if (!bq) {
+               dev_err(&client->dev, "failed to allocate device data\n");
+               ret = -ENOMEM;
+               goto error_2;
+       }
+
+       i2c_set_clientdata(client, bq);
+
+       bq->id = num;
+       bq->dev = &client->dev;
+       bq->chip = id->driver_data;
+       bq->name = name;
+       bq->mode = BQ2415X_MODE_NONE;
+       bq->reported_mode = BQ2415X_MODE_NONE;
+       bq->autotimer = 0;
+       bq->automode = 0;
+
+       memcpy(&bq->init_data, client->dev.platform_data,
+                       sizeof(bq->init_data));
+
+       bq2415x_reset_chip(bq);
+
+       ret = bq2415x_power_supply_init(bq);
+       if (ret) {
+               dev_err(bq->dev, "failed to register power supply: %d\n", ret);
+               goto error_3;
+       }
+
+       ret = bq2415x_sysfs_init(bq);
+       if (ret) {
+               dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
+               goto error_4;
+       }
+
+       ret = bq2415x_set_defaults(bq);
+       if (ret) {
+               dev_err(bq->dev, "failed to set default values: %d\n", ret);
+               goto error_5;
+       }
+
+       if (bq->init_data.set_mode_hook) {
+               if (bq->init_data.set_mode_hook(
+                               bq2415x_hook_function, bq)) {
+                       bq->automode = 1;
+                       bq2415x_set_mode(bq, bq->reported_mode);
+                       dev_info(bq->dev, "automode enabled\n");
+               } else {
+                       bq->automode = -1;
+                       dev_info(bq->dev, "automode failed\n");
+               }
+       } else {
+               bq->automode = -1;
+               dev_info(bq->dev, "automode not supported\n");
+       }
+
+       INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work);
+       bq2415x_set_autotimer(bq, 1);
+
+       dev_info(bq->dev, "driver registered\n");
+       return 0;
+
+error_5:
+       bq2415x_sysfs_exit(bq);
+error_4:
+       bq2415x_power_supply_exit(bq);
+error_3:
+       kfree(bq);
+error_2:
+       kfree(name);
+error_1:
+       mutex_lock(&bq2415x_id_mutex);
+       idr_remove(&bq2415x_id, num);
+       mutex_unlock(&bq2415x_id_mutex);
+
+       return ret;
+}
+
+/* main bq2415x remove function */
+
+static int bq2415x_remove(struct i2c_client *client)
+{
+       struct bq2415x_device *bq = i2c_get_clientdata(client);
+
+       if (bq->init_data.set_mode_hook)
+               bq->init_data.set_mode_hook(NULL, NULL);
+
+       bq2415x_sysfs_exit(bq);
+       bq2415x_power_supply_exit(bq);
+
+       bq2415x_reset_chip(bq);
+
+       mutex_lock(&bq2415x_id_mutex);
+       idr_remove(&bq2415x_id, bq->id);
+       mutex_unlock(&bq2415x_id_mutex);
+
+       dev_info(bq->dev, "driver unregistered\n");
+
+       kfree(bq->name);
+       kfree(bq);
+
+       return 0;
+}
+
+static const struct i2c_device_id bq2415x_i2c_id_table[] = {
+       { "bq2415x", BQUNKNOWN },
+       { "bq24150", BQ24150 },
+       { "bq24150a", BQ24150A },
+       { "bq24151", BQ24151 },
+       { "bq24151a", BQ24151A },
+       { "bq24152", BQ24152 },
+       { "bq24153", BQ24153 },
+       { "bq24153a", BQ24153A },
+       { "bq24155", BQ24155 },
+       { "bq24156", BQ24156 },
+       { "bq24156a", BQ24156A },
+       { "bq24158", BQ24158 },
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table);
+
+static struct i2c_driver bq2415x_driver = {
+       .driver = {
+               .name = "bq2415x-charger",
+       },
+       .probe = bq2415x_probe,
+       .remove = bq2415x_remove,
+       .id_table = bq2415x_i2c_id_table,
+};
+
+static int __init bq2415x_init(void)
+{
+       return i2c_add_driver(&bq2415x_driver);
+}
+module_init(bq2415x_init);
+
+static void __exit bq2415x_exit(void)
+{
+       i2c_del_driver(&bq2415x_driver);
+}
+module_exit(bq2415x_exit);
+
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
+MODULE_DESCRIPTION("bq2415x charger driver");
+MODULE_LICENSE("GPL");
index e0edaf7de54bcb8b8823f899a74b23dccfd038f6..36b34efdafc9fda1d8cc96773031f5b106f005f9 100644 (file)
@@ -230,6 +230,14 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
  */
 static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
 {
+       int flags;
+       bool is_bq27500 = di->chip == BQ27500;
+       bool is_higher = bq27xxx_is_chip_version_higher(di);
+
+       flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
+       if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
+               return -ENODATA;
+
        return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
 }
 
index 6bb6e2f5ea814e408c52f23ca78d35f8a22e7444..2fa9b6bf1f3f9e08d9d5512e875ec377902898f9 100644 (file)
@@ -80,13 +80,13 @@ static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb,
 {
        int ret;
 
-       ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb));
+       ret = i2c_smbus_read_word_data(info->client, reg_msb);
        if (ret < 0) {
                dev_err(&info->client->dev, "register read failed\n");
                return ret;
        }
 
-       *val = ret;
+       *val = swab16(ret);
        return 0;
 }
 
index e902b088d52cf334429b287ad1b26640ffbd051a..32ce17e235c08ef3644c81573a22ad37417e50b2 100644 (file)
@@ -279,7 +279,8 @@ static int gab_probe(struct platform_device *pdev)
        }
 
        memcpy(psy->properties, gab_props, sizeof(gab_props));
-       properties = psy->properties + sizeof(gab_props);
+       properties = (enum power_supply_property *)
+                               ((char *)psy->properties + sizeof(gab_props));
 
        /*
         * getting channel from iio and copying the battery properties
@@ -327,7 +328,7 @@ static int gab_probe(struct platform_device *pdev)
                ret = request_any_context_irq(irq, gab_charged,
                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                                "battery charged", adc_bat);
-               if (ret)
+               if (ret < 0)
                        goto err_gpio;
        }
 
index 74ac69e0687fdc262791cc006e27b4d4895c3b0d..bf914893c6fd40e2a54423fd3352d6522f039288 100644 (file)
@@ -33,7 +33,6 @@ struct jz_battery {
        struct jz_battery_platform_data *pdata;
        struct platform_device *pdev;
 
-       struct resource *mem;
        void __iomem *base;
 
        int irq;
@@ -244,13 +243,14 @@ static int jz_battery_probe(struct platform_device *pdev)
        struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data;
        struct jz_battery *jz_battery;
        struct power_supply *battery;
+       struct resource *mem;
 
        if (!pdata) {
                dev_err(&pdev->dev, "No platform_data supplied\n");
                return -ENXIO;
        }
 
-       jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL);
+       jz_battery = devm_kzalloc(&pdev->dev, sizeof(*jz_battery), GFP_KERNEL);
        if (!jz_battery) {
                dev_err(&pdev->dev, "Failed to allocate driver structure\n");
                return -ENOMEM;
@@ -260,33 +260,15 @@ static int jz_battery_probe(struct platform_device *pdev)
 
        jz_battery->irq = platform_get_irq(pdev, 0);
        if (jz_battery->irq < 0) {
-               ret = jz_battery->irq;
                dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
-               goto err_free;
+               return jz_battery->irq;
        }
 
-       jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!jz_battery->mem) {
-               ret = -ENOENT;
-               dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
-               goto err_free;
-       }
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       jz_battery->mem = request_mem_region(jz_battery->mem->start,
-                               resource_size(jz_battery->mem), pdev->name);
-       if (!jz_battery->mem) {
-               ret = -EBUSY;
-               dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-               goto err_free;
-       }
-
-       jz_battery->base = ioremap_nocache(jz_battery->mem->start,
-                               resource_size(jz_battery->mem));
-       if (!jz_battery->base) {
-               ret = -EBUSY;
-               dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
-               goto err_release_mem_region;
-       }
+       jz_battery->base = devm_request_and_ioremap(&pdev->dev, mem);
+       if (!jz_battery->base)
+               return -EBUSY;
 
        battery = &jz_battery->battery;
        battery->name = pdata->info.name;
@@ -309,7 +291,7 @@ static int jz_battery_probe(struct platform_device *pdev)
                        jz_battery);
        if (ret) {
                dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
-               goto err_iounmap;
+               goto err;
        }
        disable_irq(jz_battery->irq);
 
@@ -366,13 +348,8 @@ err_free_gpio:
                gpio_free(jz_battery->pdata->gpio_charge);
 err_free_irq:
        free_irq(jz_battery->irq, jz_battery);
-err_iounmap:
+err:
        platform_set_drvdata(pdev, NULL);
-       iounmap(jz_battery->base);
-err_release_mem_region:
-       release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
-err_free:
-       kfree(jz_battery);
        return ret;
 }
 
@@ -392,10 +369,6 @@ static int jz_battery_remove(struct platform_device *pdev)
 
        free_irq(jz_battery->irq, jz_battery);
 
-       iounmap(jz_battery->base);
-       release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
-       kfree(jz_battery);
-
        return 0;
 }
 
index a1c51ac117fd2a7cf319449296ff7d6eb9b1428c..22b6407c9ca9949d65b0c719e895549e8bb3e902 100644 (file)
@@ -235,25 +235,14 @@ static int lp8788_get_battery_present(struct lp8788_charger *pchg,
        return 0;
 }
 
-static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg,
-                               unsigned int *result)
+static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result)
 {
        struct iio_channel *channel = pchg->chan[LP8788_VBATT];
-       int scaleint;
-       int scalepart;
-       int ret;
 
        if (!channel)
                return -EINVAL;
 
-       ret = iio_read_channel_scale(channel, &scaleint, &scalepart);
-       if (ret != IIO_VAL_INT_PLUS_MICRO)
-               return -EINVAL;
-
-       /* unit: mV */
-       *result = (scaleint + scalepart * 1000000) / 1000;
-
-       return 0;
+       return iio_read_channel_processed(channel, result);
 }
 
 static int lp8788_get_battery_voltage(struct lp8788_charger *pchg,
@@ -268,7 +257,7 @@ static int lp8788_get_battery_capacity(struct lp8788_charger *pchg,
        struct lp8788 *lp = pchg->lp;
        struct lp8788_charger_platform_data *pdata = pchg->pdata;
        unsigned int max_vbatt;
-       unsigned int vbatt;
+       int vbatt;
        enum lp8788_charging_state state;
        u8 data;
        int ret;
@@ -304,19 +293,18 @@ static int lp8788_get_battery_temperature(struct lp8788_charger *pchg,
                                union power_supply_propval *val)
 {
        struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP];
-       int scaleint;
-       int scalepart;
+       int result;
        int ret;
 
        if (!channel)
                return -EINVAL;
 
-       ret = iio_read_channel_scale(channel, &scaleint, &scalepart);
-       if (ret != IIO_VAL_INT_PLUS_MICRO)
+       ret = iio_read_channel_processed(channel, &result);
+       if (ret < 0)
                return -EINVAL;
 
        /* unit: 0.1 'C */
-       val->intval = (scaleint + scalepart * 1000000) / 100;
+       val->intval = result * 10;
 
        return 0;
 }
@@ -592,53 +580,22 @@ static void lp8788_irq_unregister(struct platform_device *pdev,
        }
 }
 
-static void lp8788_setup_adc_channel(struct lp8788_charger *pchg)
+static void lp8788_setup_adc_channel(const char *consumer_name,
+                               struct lp8788_charger *pchg)
 {
        struct lp8788_charger_platform_data *pdata = pchg->pdata;
-       struct device *dev = pchg->lp->dev;
        struct iio_channel *chan;
-       enum lp8788_adc_id id;
-       const char *chan_name[LPADC_MAX] = {
-               [LPADC_VBATT_5P5] = "vbatt-5p5",
-               [LPADC_VBATT_6P0] = "vbatt-6p0",
-               [LPADC_VBATT_5P0] = "vbatt-5p0",
-               [LPADC_ADC1]      = "adc1",
-               [LPADC_ADC2]      = "adc2",
-               [LPADC_ADC3]      = "adc3",
-               [LPADC_ADC4]      = "adc4",
-       };
 
        if (!pdata)
                return;
 
-       id = pdata->vbatt_adc;
-       switch (id) {
-       case LPADC_VBATT_5P5:
-       case LPADC_VBATT_6P0:
-       case LPADC_VBATT_5P0:
-               chan = iio_channel_get(NULL, chan_name[id]);
-               pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
-               break;
-       default:
-               dev_err(dev, "invalid ADC id for VBATT: %d\n", id);
-               pchg->chan[LP8788_VBATT] = NULL;
-               break;
-       }
+       /* ADC channel for battery voltage */
+       chan = iio_channel_get(consumer_name, pdata->adc_vbatt);
+       pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
 
-       id = pdata->batt_temp_adc;
-       switch (id) {
-       case LPADC_ADC1:
-       case LPADC_ADC2:
-       case LPADC_ADC3:
-       case LPADC_ADC4:
-               chan = iio_channel_get(NULL, chan_name[id]);
-               pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
-               break;
-       default:
-               dev_err(dev, "invalid ADC id for BATT_TEMP : %d\n", id);
-               pchg->chan[LP8788_BATT_TEMP] = NULL;
-               break;
-       }
+       /* ADC channel for battery temperature */
+       chan = iio_channel_get(consumer_name, pdata->adc_batt_temp);
+       pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
 }
 
 static void lp8788_release_adc_channel(struct lp8788_charger *pchg)
@@ -747,7 +704,7 @@ static int lp8788_charger_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       lp8788_setup_adc_channel(pchg);
+       lp8788_setup_adc_channel(pdev->name, pchg);
 
        ret = lp8788_psy_register(pdev, pchg);
        if (ret)
index 5ffe46916f0be4a445f63a257dc0b86383177c32..d664ef58afa7d0ffd34d03e89444cd015f31ab7d 100644 (file)
@@ -572,7 +572,8 @@ static int max17042_init_chip(struct max17042_chip *chip)
                        __func__);
                return -EIO;
        }
-       max17042_verify_model_lock(chip);
+
+       ret = max17042_verify_model_lock(chip);
        if (ret) {
                dev_err(&chip->client->dev, "%s lock verify failed\n",
                        __func__);
index 1a075f1f1b676c9cd7c2f16666852a46cf4629f1..665cdc76c26502e7a207ac8cbfc1dbfb90be5864 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -426,6 +427,54 @@ static int max8925_deinit_charger(struct max8925_power_info *info)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static struct max8925_power_pdata *
+max8925_power_dt_init(struct platform_device *pdev)
+{
+       struct device_node *nproot = pdev->dev.parent->of_node;
+       struct device_node *np;
+       int batt_detect;
+       int topoff_threshold;
+       int fast_charge;
+       int no_temp_support;
+       int no_insert_detect;
+       struct max8925_power_pdata *pdata;
+
+       if (!nproot)
+               return pdev->dev.platform_data;
+
+       np = of_find_node_by_name(nproot, "charger");
+       if (!np) {
+               dev_err(&pdev->dev, "failed to find charger node\n");
+               return NULL;
+       }
+
+       pdata = devm_kzalloc(&pdev->dev,
+                       sizeof(struct max8925_power_pdata),
+                       GFP_KERNEL);
+
+       of_property_read_u32(np, "topoff-threshold", &topoff_threshold);
+       of_property_read_u32(np, "batt-detect", &batt_detect);
+       of_property_read_u32(np, "fast-charge", &fast_charge);
+       of_property_read_u32(np, "no-insert-detect", &no_insert_detect);
+       of_property_read_u32(np, "no-temp-support", &no_temp_support);
+
+       pdata->batt_detect = batt_detect;
+       pdata->fast_charge = fast_charge;
+       pdata->topoff_threshold = topoff_threshold;
+       pdata->no_insert_detect = no_insert_detect;
+       pdata->no_temp_support = no_temp_support;
+
+       return pdata;
+}
+#else
+static struct max8925_power_pdata *
+max8925_power_dt_init(struct platform_device *pdev)
+{
+       return pdev->dev.platform_data;
+}
+#endif
+
 static int max8925_power_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -433,7 +482,7 @@ static int max8925_power_probe(struct platform_device *pdev)
        struct max8925_power_info *info;
        int ret;
 
-       pdata = pdev->dev.platform_data;
+       pdata = max8925_power_dt_init(pdev);
        if (!pdata) {
                dev_err(&pdev->dev, "platform data isn't assigned to "
                        "power supply\n");
index f77a41272e5d6f3e5f9fecf1b40b7a4a5e1bb459..8a7cfb3cc16694e7fdd4881d9bede20b7aaf4099 100644 (file)
@@ -216,6 +216,86 @@ static void psy_unregister_thermal(struct power_supply *psy)
                return;
        thermal_zone_device_unregister(psy->tzd);
 }
+
+/* thermal cooling device callbacks */
+static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd,
+                                       unsigned long *state)
+{
+       struct power_supply *psy;
+       union power_supply_propval val;
+       int ret;
+
+       psy = tcd->devdata;
+       ret = psy->get_property(psy,
+               POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
+       if (!ret)
+               *state = val.intval;
+
+       return ret;
+}
+
+static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd,
+                                       unsigned long *state)
+{
+       struct power_supply *psy;
+       union power_supply_propval val;
+       int ret;
+
+       psy = tcd->devdata;
+       ret = psy->get_property(psy,
+               POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
+       if (!ret)
+               *state = val.intval;
+
+       return ret;
+}
+
+static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
+                                       unsigned long state)
+{
+       struct power_supply *psy;
+       union power_supply_propval val;
+       int ret;
+
+       psy = tcd->devdata;
+       val.intval = state;
+       ret = psy->set_property(psy,
+               POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
+
+       return ret;
+}
+
+static struct thermal_cooling_device_ops psy_tcd_ops = {
+       .get_max_state = ps_get_max_charge_cntl_limit,
+       .get_cur_state = ps_get_cur_chrage_cntl_limit,
+       .set_cur_state = ps_set_cur_charge_cntl_limit,
+};
+
+static int psy_register_cooler(struct power_supply *psy)
+{
+       int i;
+
+       /* Register for cooling device if psy can control charging */
+       for (i = 0; i < psy->num_properties; i++) {
+               if (psy->properties[i] ==
+                               POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) {
+                       psy->tcd = thermal_cooling_device_register(
+                                                       (char *)psy->name,
+                                                       psy, &psy_tcd_ops);
+                       if (IS_ERR(psy->tcd))
+                               return PTR_ERR(psy->tcd);
+                       break;
+               }
+       }
+       return 0;
+}
+
+static void psy_unregister_cooler(struct power_supply *psy)
+{
+       if (IS_ERR_OR_NULL(psy->tcd))
+               return;
+       thermal_cooling_device_unregister(psy->tcd);
+}
 #else
 static int psy_register_thermal(struct power_supply *psy)
 {
@@ -225,6 +305,15 @@ static int psy_register_thermal(struct power_supply *psy)
 static void psy_unregister_thermal(struct power_supply *psy)
 {
 }
+
+static int psy_register_cooler(struct power_supply *psy)
+{
+       return 0;
+}
+
+static void psy_unregister_cooler(struct power_supply *psy)
+{
+}
 #endif
 
 int power_supply_register(struct device *parent, struct power_supply *psy)
@@ -259,6 +348,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto register_thermal_failed;
 
+       rc = psy_register_cooler(psy);
+       if (rc)
+               goto register_cooler_failed;
+
        rc = power_supply_create_triggers(psy);
        if (rc)
                goto create_triggers_failed;
@@ -268,6 +361,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        goto success;
 
 create_triggers_failed:
+       psy_unregister_cooler(psy);
+register_cooler_failed:
        psy_unregister_thermal(psy);
 register_thermal_failed:
        device_del(dev);
@@ -284,6 +379,7 @@ void power_supply_unregister(struct power_supply *psy)
        cancel_work_sync(&psy->changed_work);
        sysfs_remove_link(&psy->dev->kobj, "powers");
        power_supply_remove_triggers(psy);
+       psy_unregister_cooler(psy);
        psy_unregister_thermal(psy);
        device_unregister(psy->dev);
 }
index 395c2cfa16c0bbd3bb200b31f5d2de343e2cd7e3..40fa3b7cae548033d0d69e358574326e11a8f22c 100644 (file)
@@ -164,6 +164,8 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(constant_charge_current_max),
        POWER_SUPPLY_ATTR(constant_charge_voltage),
        POWER_SUPPLY_ATTR(constant_charge_voltage_max),
+       POWER_SUPPLY_ATTR(charge_control_limit),
+       POWER_SUPPLY_ATTR(charge_control_limit_max),
        POWER_SUPPLY_ATTR(energy_full_design),
        POWER_SUPPLY_ATTR(energy_empty_design),
        POWER_SUPPLY_ATTR(energy_full),
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c
new file mode 100644 (file)
index 0000000..ca49d6c
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Nokia RX-51 battery driver
+ *
+ * Copyright (C) 2012  Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/i2c/twl4030-madc.h>
+
+struct rx51_device_info {
+       struct device *dev;
+       struct power_supply bat;
+};
+
+/*
+ * Read ADCIN channel value, code copied from maemo kernel
+ */
+static int rx51_battery_read_adc(int channel)
+{
+       struct twl4030_madc_request req;
+
+       req.channels = 1 << channel;
+       req.do_avg = 1;
+       req.method = TWL4030_MADC_SW1;
+       req.func_cb = NULL;
+       req.type = TWL4030_MADC_WAIT;
+
+       if (twl4030_madc_conversion(&req) <= 0)
+               return -ENODATA;
+
+       return req.rbuf[channel];
+}
+
+/*
+ * Read ADCIN channel 12 (voltage) and convert RAW value to micro voltage
+ * This conversion formula was extracted from maemo program bsi-read
+ */
+static int rx51_battery_read_voltage(struct rx51_device_info *di)
+{
+       int voltage = rx51_battery_read_adc(12);
+
+       if (voltage < 0)
+               return voltage;
+
+       return 1000 * (10000 * voltage / 1705);
+}
+
+/*
+ * Temperature look-up tables
+ * TEMP = (1/(t1 + 1/298) - 273.15)
+ * Where t1 = (1/B) * ln((RAW_ADC_U * 2.5)/(R * I * 255))
+ * Formula is based on experimental data, RX-51 CAL data, maemo program bme
+ * and formula from da9052 driver with values R = 100, B = 3380, I = 0.00671
+ */
+
+/*
+ * Table1 (temperature for first 25 RAW values)
+ * Usage: TEMP = rx51_temp_table1[RAW]
+ *   RAW is between 1 and 24
+ *   TEMP is between 201 C and 55 C
+ */
+static u8 rx51_temp_table1[] = {
+       255, 201, 159, 138, 124, 114, 106,  99,  94,  89,  85,  82,  78,  75,
+        73,  70,  68,  66,  64,  62,  61,  59,  57,  56,  55
+};
+
+/*
+ * Table2 (lowest RAW value for temperature)
+ * Usage: RAW = rx51_temp_table2[TEMP-rx51_temp_table2_first]
+ *   TEMP is between 53 C and -32 C
+ *   RAW is between 25 and 993
+ */
+#define rx51_temp_table2_first 53
+static u16 rx51_temp_table2[] = {
+        25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  39,
+        40,  41,  43,  44,  46,  48,  49,  51,  53,  55,  57,  59,  61,  64,
+        66,  69,  71,  74,  77,  80,  83,  86,  90,  94,  97, 101, 106, 110,
+       115, 119, 125, 130, 136, 141, 148, 154, 161, 168, 176, 184, 202, 211,
+       221, 231, 242, 254, 266, 279, 293, 308, 323, 340, 357, 375, 395, 415,
+       437, 460, 485, 511, 539, 568, 600, 633, 669, 706, 747, 790, 836, 885,
+       937, 993, 1024
+};
+
+/*
+ * Read ADCIN channel 0 (battery temp) and convert value to tenths of Celsius
+ * Use Temperature look-up tables for conversation
+ */
+static int rx51_battery_read_temperature(struct rx51_device_info *di)
+{
+       int min = 0;
+       int max = ARRAY_SIZE(rx51_temp_table2) - 1;
+       int raw = rx51_battery_read_adc(0);
+
+       /* Zero and negative values are undefined */
+       if (raw <= 0)
+               return INT_MAX;
+
+       /* ADC channels are 10 bit, higher value are undefined */
+       if (raw >= (1 << 10))
+               return INT_MIN;
+
+       /* First check for temperature in first direct table */
+       if (raw < ARRAY_SIZE(rx51_temp_table1))
+               return rx51_temp_table1[raw] * 100;
+
+       /* Binary search RAW value in second inverse table */
+       while (max - min > 1) {
+               int mid = (max + min) / 2;
+               if (rx51_temp_table2[mid] <= raw)
+                       min = mid;
+               else if (rx51_temp_table2[mid] > raw)
+                       max = mid;
+               if (rx51_temp_table2[mid] == raw)
+                       break;
+       }
+
+       return (rx51_temp_table2_first - min) * 100;
+}
+
+/*
+ * Read ADCIN channel 4 (BSI) and convert RAW value to micro Ah
+ * This conversion formula was extracted from maemo program bsi-read
+ */
+static int rx51_battery_read_capacity(struct rx51_device_info *di)
+{
+       int capacity = rx51_battery_read_adc(4);
+
+       if (capacity < 0)
+               return capacity;
+
+       return 1280 * (1200 * capacity)/(1024 - capacity);
+}
+
+/*
+ * Return power_supply property
+ */
+static int rx51_battery_get_property(struct power_supply *psy,
+                                       enum power_supply_property psp,
+                                       union power_supply_propval *val)
+{
+       struct rx51_device_info *di = container_of((psy),
+                               struct rx51_device_info, bat);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               val->intval = 4200000;
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = rx51_battery_read_voltage(di) ? 1 : 0;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               val->intval = rx51_battery_read_voltage(di);
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = rx51_battery_read_temperature(di);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+               val->intval = rx51_battery_read_capacity(di);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (val->intval == INT_MAX || val->intval == INT_MIN)
+               return -EINVAL;
+
+       return 0;
+}
+
+static enum power_supply_property rx51_battery_props[] = {
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+};
+
+static int __devinit rx51_battery_probe(struct platform_device *pdev)
+{
+       struct rx51_device_info *di;
+       int ret;
+
+       di = kzalloc(sizeof(*di), GFP_KERNEL);
+       if (!di)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, di);
+
+       di->bat.name = dev_name(&pdev->dev);
+       di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+       di->bat.properties = rx51_battery_props;
+       di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
+       di->bat.get_property = rx51_battery_get_property;
+
+       ret = power_supply_register(di->dev, &di->bat);
+       if (ret) {
+               platform_set_drvdata(pdev, NULL);
+               kfree(di);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit rx51_battery_remove(struct platform_device *pdev)
+{
+       struct rx51_device_info *di = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&di->bat);
+       platform_set_drvdata(pdev, NULL);
+       kfree(di);
+
+       return 0;
+}
+
+static struct platform_driver rx51_battery_driver = {
+       .probe = rx51_battery_probe,
+       .remove = __devexit_p(rx51_battery_remove),
+       .driver = {
+               .name = "rx51-battery",
+               .owner = THIS_MODULE,
+       },
+};
+module_platform_driver(rx51_battery_driver);
+
+MODULE_ALIAS("platform:rx51-battery");
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
+MODULE_DESCRIPTION("Nokia RX-51 battery driver");
+MODULE_LICENSE("GPL");
index f9e70cf08199121b0a9e8b5d4297cf1951106b93..a69d0d11b54006b35d3ad3c04a9c53f3456d842f 100644 (file)
@@ -114,12 +114,12 @@ static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg)
 
 static int twl4030_bci_read(u8 reg, u8 *val)
 {
-       return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg);
+       return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
 }
 
 static int twl4030_clear_set_boot_bci(u8 clear, u8 set)
 {
-       return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear,
+       return twl4030_clear_set(TWL_MODULE_PM_MASTER, clear,
                        TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set,
                        TWL4030_PM_MASTER_BOOT_BCI);
 }
@@ -152,7 +152,7 @@ static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
        int ret;
        u8 hwsts;
 
-       ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
+       ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &hwsts,
                              TWL4030_PM_MASTER_STS_HW_CONDITIONS);
        if (ret < 0)
                return 0;
@@ -199,7 +199,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
                        return ret;
 
                /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
-               ret = twl4030_clear_set(TWL4030_MODULE_MAIN_CHARGE, 0,
+               ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
                        TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
        } else {
                ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
@@ -238,7 +238,7 @@ static int twl4030_charger_enable_backup(int uvolt, int uamp)
        if (uvolt < 2500000 ||
            uamp < 25) {
                /* disable charging of backup battery */
-               ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER,
+               ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER,
                                        TWL4030_BBCHEN, 0, TWL4030_BB_CFG);
                return ret;
        }
@@ -262,7 +262,7 @@ static int twl4030_charger_enable_backup(int uvolt, int uamp)
        else
                flags |= TWL4030_BBISEL_25uA;
 
-       ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER,
+       ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER,
                                TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK,
                                flags,
                                TWL4030_BB_CFG);
index 1c5ab0172ea282c73b0835d07be67e4172a8a6af..2b557119adad4b11d63ec345c96b425183e691f3 100644 (file)
@@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
 #define pm8607_regulator_dt_init(x, y, z)      (-1)
 #endif
 
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+static int pm8607_regulator_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm8607_regulator_info *info = NULL;
@@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+static int pm8607_regulator_remove(struct platform_device *pdev)
 {
        struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
 
@@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pm8607_regulator_probe,
-       .remove         = __devexit_p(pm8607_regulator_remove),
+       .remove         = pm8607_regulator_remove,
        .id_table       = pm8607_regulator_driver_ids,
 };
 
index 67d47b59a66d878c9188afaaa62b92f255d657bb..551a22b075387a0641d37ff9dc1a34e25b65ee9d 100644 (file)
@@ -109,6 +109,16 @@ config REGULATOR_DA9052
          This driver supports the voltage regulators of DA9052-BC and
          DA9053-AA/Bx PMIC.
 
+config REGULATOR_DA9055
+       tristate "Dialog Semiconductor DA9055 regulators"
+       depends on MFD_DA9055
+       help
+         Say y here to support the BUCKs and LDOs regulators found on
+         Dialog Semiconductor DA9055 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called da9055-regulator.
+
 config REGULATOR_FAN53555
        tristate "Fairchild FAN53555 Regulator"
        depends on I2C
@@ -204,6 +214,16 @@ config REGULATOR_MAX8952
          via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS
          modes ranging from 0.77V to 1.40V by 0.01V steps.
 
+config REGULATOR_MAX8973
+       tristate "Maxim MAX8973 voltage regulator "
+       depends on I2C
+       select REGMAP_I2C
+       help
+         The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
+         switching regulator delievers up to 9A of output current. Each
+         phase operates at a 2MHz fixed frequency with a 120 deg shift
+         from the adjacent phase, allowing the use of small magnetic component.
+
 config REGULATOR_MAX8997
        tristate "Maxim 8997/8966 regulator"
        depends on MFD_MAX8997
@@ -335,6 +355,17 @@ config REGULATOR_PALMAS
          on the muxing. This is handled automatically in the driver by
          reading the mux info from OTP.
 
+config REGULATOR_TPS51632
+       tristate "TI TPS51632 Power Regulator"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         This driver supports TPS51632 voltage regulator chip.
+         The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+         with Serial VID control and DVFS.
+         The voltage output can be configure through I2C interface or PWM
+         interface.
+
 config REGULATOR_TPS6105X
        tristate "TI TPS6105X Power regulators"
        depends on TPS6105X
@@ -415,6 +446,15 @@ config REGULATOR_TPS65912
        help
            This driver supports TPS65912 voltage regulator chip.
 
+config REGULATOR_TPS80031
+       tristate "TI TPS80031/TPS80032 power regualtor driver"
+       depends on MFD_TPS80031
+       help
+         TPS80031/ TPS80032 Fully Integrated Power Management with Power
+         Path and Battery Charger. It has 5 configurable step-down
+         converters, 11 general purpose LDOs, VBUS generator and digital
+         output to control regulators.
+
 config REGULATOR_TWL4030
        bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
        depends on TWL4030_CORE
@@ -422,6 +462,13 @@ config REGULATOR_TWL4030
          This driver supports the voltage regulators provided by
          this family of companion chips.
 
+config REGULATOR_VEXPRESS
+       tristate "Versatile Express regulators"
+       depends on VEXPRESS_CONFIG
+       help
+         This driver provides support for voltage regulators available
+         on the ARM Ltd's Versatile Express platform.
+
 config REGULATOR_WM831X
        tristate "Wolfson Microelectronics WM831x PMIC regulators"
        depends on MFD_WM831X
@@ -450,5 +497,12 @@ config REGULATOR_WM8994
          This driver provides support for the voltage regulators on the
          WM8994 CODEC.
 
+config REGULATOR_AS3711
+       tristate "AS3711 PMIC"
+       depends on MFD_AS3711
+       help
+         This driver provides support for the voltage regulators on the
+         AS3711 PMIC
+
 endif
 
index e431eed8a8782f2f49fc1869365b76929dc52001..b802b0c7fb02d7d7bb3bf3c1fa72b95aed899ce4 100644 (file)
@@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500)       += ab8500.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
+obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
+obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
+obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
 obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
@@ -41,6 +44,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
@@ -56,7 +60,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
index 167c93f21981a0178a9bd9d47ba879604ed7fb4a..8b5876356db97da46cd5ac0dd59dccb4b2521361 100644 (file)
@@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+static int aat2870_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = aat2870_regulator_probe,
-       .remove = __devexit_p(aat2870_regulator_remove),
+       .remove = aat2870_regulator_remove,
 };
 
 static int __init aat2870_regulator_init(void)
index df4ad8927f0ce88257cb70db8fdfed535f8d17f2..111ec69a3e9454a40fa96091e4a7bc679cfa5dd1 100644 (file)
@@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
  * for all the different regulators.
  */
 
-static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
+static int ab3100_regulators_probe(struct platform_device *pdev)
 {
        struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
        struct regulator_config config = { };
@@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
+static int ab3100_regulators_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ab3100_regulators_probe,
-       .remove = __devexit_p(ab3100_regulators_remove),
+       .remove = ab3100_regulators_remove,
 };
 
 static __init int ab3100_regulators_init(void)
index e3d1d063025a45b12179e0712ea0d2599bfcb21c..09014f38a9481f8afb630ce8a5c5fdb513100380 100644 (file)
@@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
        REG_INIT(AB8500_REGUCTRLDISCH2,         0x04, 0x44, 0x16),
 };
 
-static __devinit int
+static int
 ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
 {
        int err;
@@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
        return 0;
 }
 
-static __devinit int ab8500_regulator_register(struct platform_device *pdev,
+static int ab8500_regulator_register(struct platform_device *pdev,
                                        struct regulator_init_data *init_data,
                                        int id,
                                        struct device_node *np)
@@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
        { .name = "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
 };
 
-static __devinit int
+static int
 ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 {
        int err, i;
@@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
        return 0;
 }
 
-static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
+static int ab8500_regulator_probe(struct platform_device *pdev)
 {
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
        struct ab8500_platform_data *pdata;
@@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
+static int ab8500_regulator_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver ab8500_regulator_driver = {
        .probe = ab8500_regulator_probe,
-       .remove = __devexit_p(ab8500_regulator_remove),
+       .remove = ab8500_regulator_remove,
        .driver         = {
                .name   = "ab8500-regulator",
                .owner  = THIS_MODULE,
index f123f7e3b7525acd164ed639e022f25dc46711cf..6b981b5faa7015c53f10a463d7a53097edeab075 100644 (file)
@@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ad5398_id);
 
-static int __devinit ad5398_probe(struct i2c_client *client,
+static int ad5398_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct regulator_init_data *init_data = client->dev.platform_data;
@@ -256,7 +256,7 @@ err:
        return ret;
 }
 
-static int __devexit ad5398_remove(struct i2c_client *client)
+static int ad5398_remove(struct i2c_client *client)
 {
        struct ad5398_chip_info *chip = i2c_get_clientdata(client);
 
@@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
 
 static struct i2c_driver ad5398_driver = {
        .probe = ad5398_probe,
-       .remove = __devexit_p(ad5398_remove),
+       .remove = ad5398_remove,
        .driver         = {
                .name   = "ad5398",
        },
index 1af97686f4448864d92b7dbfdf58e79c883edbb8..0199eeea63b13f6d770b49897d14bb3da1173290 100644 (file)
@@ -48,36 +48,21 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
                                        unsigned selector)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       u32 val, mask;
 
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       val = anatop_reg->min_bit_val + selector;
-       dev_dbg(&reg->dev, "%s: calculated val %d\n", __func__, val);
-       mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
-               anatop_reg->vol_bit_shift;
-       val <<= anatop_reg->vol_bit_shift;
-       regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg,
-                               mask, val);
-
-       return 0;
+       return regulator_set_voltage_sel_regmap(reg, selector);
 }
 
 static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       u32 val, mask;
 
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
-       mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
-               anatop_reg->vol_bit_shift;
-       val = (val & mask) >> anatop_reg->vol_bit_shift;
-
-       return val - anatop_reg->min_bit_val;
+       return regulator_get_voltage_sel_regmap(reg);
 }
 
 static struct regulator_ops anatop_rops = {
@@ -87,7 +72,7 @@ static struct regulator_ops anatop_rops = {
        .map_voltage = regulator_map_voltage_linear,
 };
 
-static int __devinit anatop_regulator_probe(struct platform_device *pdev)
+static int anatop_regulator_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
@@ -158,15 +143,20 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
                goto anatop_probe_end;
        }
 
-       rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
-               / 25000 + 1;
+       rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1
+                           + sreg->min_bit_val;
        rdesc->min_uV = sreg->min_voltage;
        rdesc->uV_step = 25000;
+       rdesc->linear_min_sel = sreg->min_bit_val;
+       rdesc->vsel_reg = sreg->control_reg;
+       rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
+                          sreg->vol_bit_shift;
 
        config.dev = &pdev->dev;
        config.init_data = initdata;
        config.driver_data = sreg;
        config.of_node = pdev->dev.of_node;
+       config.regmap = sreg->anatop;
 
        /* register regulator */
        rdev = regulator_register(rdesc, &config);
@@ -186,7 +176,7 @@ anatop_probe_end:
        return ret;
 }
 
-static int __devexit anatop_regulator_remove(struct platform_device *pdev)
+static int anatop_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
@@ -210,7 +200,7 @@ static struct platform_driver anatop_regulator_driver = {
                .of_match_table = of_anatop_regulator_match_tbl,
        },
        .probe  = anatop_regulator_probe,
-       .remove = __devexit_p(anatop_regulator_remove),
+       .remove = anatop_regulator_remove,
 };
 
 static int __init anatop_regulator_init(void)
index d184aa35abcb45a91795aeed9de35ad8f7d1a75a..ed7beec53af85505b49815d97d94947d0d311efb 100644 (file)
@@ -34,6 +34,108 @@ struct arizona_ldo1 {
        struct regulator_init_data init_data;
 };
 
+static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
+                                       unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector == rdev->desc->n_voltages - 1)
+               return 1800000;
+       else
+               return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+
+static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV)
+{
+       int sel;
+
+       sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+       if (sel >= rdev->desc->n_voltages)
+               sel = rdev->desc->n_voltages - 1;
+
+       return sel;
+}
+
+static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
+                                          unsigned sel)
+{
+       struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+       struct regmap *regmap = ldo->arizona->regmap;
+       unsigned int val;
+       int ret;
+
+       if (sel == rdev->desc->n_voltages - 1)
+               val = ARIZONA_LDO1_HI_PWR;
+       else
+               val = 0;
+
+       ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2,
+                                ARIZONA_LDO1_HI_PWR, val);
+       if (ret != 0)
+               return ret;
+
+       ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
+                                ARIZONA_SUBSYS_MAX_FREQ, val);
+       if (ret != 0)
+               return ret;
+
+       if (val)
+               return 0;
+
+       val = sel << ARIZONA_LDO1_VSEL_SHIFT;
+
+       return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
+                                 ARIZONA_LDO1_VSEL_MASK, val);
+}
+
+static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+       struct regmap *regmap = ldo->arizona->regmap;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val);
+       if (ret != 0)
+               return ret;
+
+       if (val & ARIZONA_LDO1_HI_PWR)
+               return rdev->desc->n_voltages - 1;
+
+       ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
+       if (ret != 0)
+               return ret;
+
+       return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+}
+
+static struct regulator_ops arizona_ldo1_hc_ops = {
+       .list_voltage = arizona_ldo1_hc_list_voltage,
+       .map_voltage = arizona_ldo1_hc_map_voltage,
+       .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
+       .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
+       .get_bypass = regulator_get_bypass_regmap,
+       .set_bypass = regulator_set_bypass_regmap,
+};
+
+static const struct regulator_desc arizona_ldo1_hc = {
+       .name = "LDO1",
+       .supply_name = "LDOVDD",
+       .type = REGULATOR_VOLTAGE,
+       .ops = &arizona_ldo1_hc_ops,
+
+       .bypass_reg = ARIZONA_LDO1_CONTROL_1,
+       .bypass_mask = ARIZONA_LDO1_BYPASS,
+       .min_uV = 900000,
+       .uV_step = 50000,
+       .n_voltages = 8,
+       .enable_time = 500,
+
+       .owner = THIS_MODULE,
+};
+
 static struct regulator_ops arizona_ldo1_ops = {
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
@@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = {
        .bypass_mask = ARIZONA_LDO1_BYPASS,
        .min_uV = 900000,
        .uV_step = 50000,
-       .n_voltages = 6,
+       .n_voltages = 7,
+       .enable_time = 500,
 
        .owner = THIS_MODULE,
 };
 
+static const struct regulator_init_data arizona_ldo1_dvfs = {
+       .constraints = {
+               .min_uV = 1200000,
+               .max_uV = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                                 REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies = 1,
+};
+
 static const struct regulator_init_data arizona_ldo1_default = {
        .constraints = {
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = {
        .num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+static int arizona_ldo1_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       const struct regulator_desc *desc;
        struct regulator_config config = { };
        struct arizona_ldo1 *ldo1;
        int ret;
@@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
         * default init_data for it.  This will be overridden with
         * platform data if provided.
         */
-       ldo1->init_data = arizona_ldo1_default;
+       switch (arizona->type) {
+       case WM5102:
+               desc = &arizona_ldo1_hc;
+               ldo1->init_data = arizona_ldo1_dvfs;
+               break;
+       default:
+               desc = &arizona_ldo1;
+               ldo1->init_data = arizona_ldo1_default;
+               break;
+       }
+
        ldo1->init_data.consumer_supplies = &ldo1->supply;
        ldo1->supply.supply = "DCVDD";
        ldo1->supply.dev_name = dev_name(arizona->dev);
@@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
        else
                config.init_data = &ldo1->init_data;
 
-       ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+       ldo1->regulator = regulator_register(desc, &config);
        if (IS_ERR(ldo1->regulator)) {
                ret = PTR_ERR(ldo1->regulator);
                dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+static int arizona_ldo1_remove(struct platform_device *pdev)
 {
        struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
 
@@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_ldo1_driver = {
        .probe = arizona_ldo1_probe,
-       .remove = __devexit_p(arizona_ldo1_remove),
+       .remove = arizona_ldo1_remove,
        .driver         = {
                .name   = "arizona-ldo1",
                .owner  = THIS_MODULE,
index d9b1f82cc5bd80939206025432f2602072dfe244..a6d040cbf8ac1dade86099eb0a71df4c2f94c4c8 100644 (file)
@@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = {
        .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
        .bypass_mask = ARIZONA_CPMIC_BYPASS,
 
+       .enable_time = 3000,
+
        .owner = THIS_MODULE,
 };
 
@@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
        .num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+static int arizona_micsupp_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+static int arizona_micsupp_remove(struct platform_device *pdev)
 {
        struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
 
@@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_micsupp_driver = {
        .probe = arizona_micsupp_probe,
-       .remove = __devexit_p(arizona_micsupp_remove),
+       .remove = arizona_micsupp_remove,
        .driver         = {
                .name   = "arizona-micsupp",
                .owner  = THIS_MODULE,
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
new file mode 100644 (file)
index 0000000..2f1341d
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/as3711.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+
+struct as3711_regulator_info {
+       struct regulator_desc   desc;
+       unsigned int            max_uV;
+};
+
+struct as3711_regulator {
+       struct as3711_regulator_info *reg_info;
+       struct regulator_dev *rdev;
+};
+
+static int as3711_list_voltage_sd(struct regulator_dev *rdev,
+                                 unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (!selector)
+               return 0;
+       if (selector < 0x41)
+               return 600000 + selector * 12500;
+       if (selector < 0x71)
+               return 1400000 + (selector - 0x40) * 25000;
+       return 2600000 + (selector - 0x70) * 50000;
+}
+
+static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
+                                   unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector < 0x10)
+               return 1200000 + selector * 50000;
+       return 1800000 + (selector - 0x10) * 100000;
+}
+
+static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
+                                   unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages ||
+           (selector > 0x10 && selector < 0x20))
+               return -EINVAL;
+
+       if (selector < 0x11)
+               return 900000 + selector * 50000;
+       return 1750000 + (selector - 0x20) * 50000;
+}
+
+static int as3711_bound_check(struct regulator_dev *rdev,
+                             int *min_uV, int *max_uV)
+{
+       struct as3711_regulator *reg = rdev_get_drvdata(rdev);
+       struct as3711_regulator_info *info = reg->reg_info;
+
+       dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
+               *min_uV, rdev->desc->min_uV, info->max_uV);
+
+       if (*max_uV < *min_uV ||
+           *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
+               return -EINVAL;
+
+       if (rdev->desc->n_voltages == 1)
+               return 0;
+
+       if (*max_uV > info->max_uV)
+               *max_uV = info->max_uV;
+
+       if (*min_uV < rdev->desc->min_uV)
+               *min_uV = rdev->desc->min_uV;
+
+       return *min_uV;
+}
+
+static int as3711_sel_check(int min, int max, int bottom, int step)
+{
+       int sel, voltage;
+
+       /* Round up min, when dividing: keeps us within the range */
+       sel = DIV_ROUND_UP(min - bottom, step);
+       voltage = sel * step + bottom;
+       pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
+              min, max, bottom, step, sel);
+       if (voltage > max)
+               return -EINVAL;
+
+       return sel;
+}
+
+static int as3711_map_voltage_sd(struct regulator_dev *rdev,
+                                int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1400000)
+               return as3711_sel_check(min_uV, max_uV, 600000, 12500);
+
+       if (min_uV <= 2600000)
+               return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
+
+       return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
+}
+
+/*
+ * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
+ * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
+ * FAST:       sdX_fast=1
+ * NORMAL:     low_noise=1
+ * IDLE:       low_noise=0
+ */
+
+static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
+{
+       unsigned int fast_bit = rdev->desc->enable_mask,
+               low_noise_bit = fast_bit << 4;
+       u8 val;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = fast_bit | low_noise_bit;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = low_noise_bit;
+               break;
+       case REGULATOR_MODE_IDLE:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
+                                 low_noise_bit | fast_bit, val);
+}
+
+static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
+{
+       unsigned int fast_bit = rdev->desc->enable_mask,
+               low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
+       unsigned int val;
+       int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
+
+       if (ret < 0)
+               return ret;
+
+       if ((val & mask) == mask)
+               return REGULATOR_MODE_FAST;
+
+       if ((val & mask) == low_noise_bit)
+               return REGULATOR_MODE_NORMAL;
+
+       if (!(val & mask))
+               return REGULATOR_MODE_IDLE;
+
+       return -EINVAL;
+}
+
+static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1800000)
+               return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
+
+       return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
+}
+
+static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1700000)
+               return as3711_sel_check(min_uV, max_uV, 900000, 50000);
+
+       return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
+}
+
+static struct regulator_ops as3711_sd_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_sd,
+       .map_voltage            = as3711_map_voltage_sd,
+       .get_mode               = as3711_get_mode_sd,
+       .set_mode               = as3711_set_mode_sd,
+};
+
+static struct regulator_ops as3711_aldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_aldo,
+       .map_voltage            = as3711_map_voltage_aldo,
+};
+
+static struct regulator_ops as3711_dldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_dldo,
+       .map_voltage            = as3711_map_voltage_dldo,
+};
+
+#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)     \
+       [AS3711_REGULATOR_ ## _id] = {                                                  \
+       .desc = {                                                                       \
+               .name = "as3711-regulator-" # _id,                                      \
+               .id = AS3711_REGULATOR_ ## _id,                                         \
+               .n_voltages = (_vmask + 1),                                             \
+               .ops = &as3711_ ## _sfx ## _ops,                                        \
+               .type = REGULATOR_VOLTAGE,                                              \
+               .owner = THIS_MODULE,                                                   \
+               .vsel_reg = AS3711_ ## _id ## _VOLTAGE,                                 \
+               .vsel_mask = _vmask << _vshift,                                         \
+               .enable_reg = AS3711_ ## _en_reg,                                       \
+               .enable_mask = BIT(_en_bit),                                            \
+               .min_uV = _min_uV,                                                      \
+       },                                                                              \
+       .max_uV = _max_uV,                                                              \
+}
+
+static struct as3711_regulator_info as3711_reg_info[] = {
+       AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+       AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+       AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       /* StepUp output voltage depends on supplying regulator */
+};
+
+#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
+
+static int as3711_regulator_probe(struct platform_device *pdev)
+{
+       struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
+       struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_init_data *reg_data;
+       struct regulator_config config = {.dev = &pdev->dev,};
+       struct as3711_regulator *reg = NULL;
+       struct as3711_regulator *regs;
+       struct regulator_dev *rdev;
+       struct as3711_regulator_info *ri;
+       int ret;
+       int id;
+
+       if (!pdata)
+               dev_dbg(&pdev->dev, "No platform data...\n");
+
+       regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
+                       sizeof(struct as3711_regulator), GFP_KERNEL);
+       if (!regs) {
+               dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+               return -ENOMEM;
+       }
+
+       for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
+               reg_data = pdata ? pdata->init_data[id] : NULL;
+
+               /* No need to register if there is no regulator data */
+               if (!ri->desc.name)
+                       continue;
+
+               reg = &regs[id];
+               reg->reg_info = ri;
+
+               config.init_data = reg_data;
+               config.driver_data = reg;
+               config.regmap = as3711->regmap;
+
+               rdev = regulator_register(&ri->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "Failed to register regulator %s\n",
+                               ri->desc.name);
+                       ret = PTR_ERR(rdev);
+                       goto eregreg;
+               }
+               reg->rdev = rdev;
+       }
+       platform_set_drvdata(pdev, regs);
+       return 0;
+
+eregreg:
+       while (--id >= 0)
+               regulator_unregister(regs[id].rdev);
+
+       return ret;
+}
+
+static int as3711_regulator_remove(struct platform_device *pdev)
+{
+       struct as3711_regulator *regs = platform_get_drvdata(pdev);
+       int id;
+
+       for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
+               regulator_unregister(regs[id].rdev);
+       return 0;
+}
+
+static struct platform_driver as3711_regulator_driver = {
+       .driver = {
+               .name   = "as3711-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = as3711_regulator_probe,
+       .remove         = as3711_regulator_remove,
+};
+
+static int __init as3711_regulator_init(void)
+{
+       return platform_driver_register(&as3711_regulator_driver);
+}
+subsys_initcall(as3711_regulator_init);
+
+static void __exit as3711_regulator_exit(void)
+{
+       platform_driver_unregister(&as3711_regulator_driver);
+}
+module_exit(as3711_regulator_exit);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("AS3711 regulator driver");
+MODULE_ALIAS("platform:as3711-regulator");
+MODULE_LICENSE("GPL v2");
index e872c8be080ed427a2e546efffee50c12acdd9fe..0f65b246cc0c8d24c559cdeafd340232d1c55e0c 100644 (file)
@@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
                        *min_uV = regulator->min_uV;
        }
 
-       if (*min_uV > *max_uV)
+       if (*min_uV > *max_uV) {
+               dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
+                       regulator->min_uV, regulator->max_uV);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
 
                /* final: [min_uV..max_uV] valid iff constraints valid */
                if (max_uV < min_uV) {
-                       rdev_err(rdev, "unsupportable voltage constraints\n");
+                       rdev_err(rdev,
+                                "unsupportable voltage constraints %u-%uuV\n",
+                                min_uV, max_uV);
                        return -EINVAL;
                }
 
@@ -1866,6 +1871,28 @@ int regulator_is_enabled(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_is_enabled);
 
+/**
+ * regulator_can_change_voltage - check if regulator can change voltage
+ * @regulator: regulator source
+ *
+ * Returns positive if the regulator driver backing the source/client
+ * can change its voltage, false otherwise. Usefull for detecting fixed
+ * or dummy regulators and disabling voltage change logic in the client
+ * driver.
+ */
+int regulator_can_change_voltage(struct regulator *regulator)
+{
+       struct regulator_dev    *rdev = regulator->rdev;
+
+       if (rdev->constraints &&
+           rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
+           (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1)
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_can_change_voltage);
+
 /**
  * regulator_count_voltages - count regulator_list_voltage() selectors
  * @regulator: regulator source
@@ -1897,6 +1924,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
 {
        if (selector >= rdev->desc->n_voltages)
                return -EINVAL;
+       if (selector < rdev->desc->linear_min_sel)
+               return 0;
+
+       selector -= rdev->desc->linear_min_sel;
 
        return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
 }
@@ -1985,6 +2016,11 @@ int regulator_is_supported_voltage(struct regulator *regulator,
                        return ret;
        }
 
+       /* Any voltage within constrains range is fine? */
+       if (rdev->desc->continuous_voltage_range)
+               return min_uV >= rdev->constraints->min_uV &&
+                               max_uV <= rdev->constraints->max_uV;
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
@@ -2120,6 +2156,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
        if (ret < 0)
                return ret;
 
+       ret += rdev->desc->linear_min_sel;
+
        /* Map back into a voltage to verify we're still in bounds */
        voltage = rdev->desc->ops->list_voltage(rdev, ret);
        if (voltage < min_uV || voltage > max_uV)
index 36c5b92fe0af26487cb093234800d534061c41f6..2afa5730f324ba1ef1bb068b5f63c79e41c11a8f 100644 (file)
@@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
        return NULL;
 }
 
-static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+static int da903x_regulator_probe(struct platform_device *pdev)
 {
        struct da903x_regulator_info *ri = NULL;
        struct regulator_dev *rdev;
@@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+static int da903x_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = da903x_regulator_probe,
-       .remove         = __devexit_p(da903x_regulator_remove),
+       .remove         = da903x_regulator_remove,
 };
 
 static int __init da903x_regulator_init(void)
index 27355b1199e571ed090f24c5799dce5511d2cc94..d0963090442d220f69ebecb8c6dbbf22866b62f8 100644 (file)
@@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
        else if (offset == 0)
                row = 1;
 
-       if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
-           max_uA < da9052_current_limits[row][DA9052_MIN_UA])
-               return -EINVAL;
-
        for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
-               if (da9052_current_limits[row][i] <= max_uA) {
+               if ((min_uA <= da9052_current_limits[row][i]) &&
+                   (da9052_current_limits[row][i] <= max_uA)) {
                        reg_val = i;
                        break;
                }
        }
 
+       if (i < 0)
+               return -EINVAL;
+
        /* Determine the even or odd position of the buck current limit
         * register field
        */
@@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
        return NULL;
 }
 
-static int __devinit da9052_regulator_probe(struct platform_device *pdev)
+static int da9052_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        struct da9052_regulator *regulator;
@@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+static int da9052_regulator_remove(struct platform_device *pdev)
 {
        struct da9052_regulator *regulator = platform_get_drvdata(pdev);
 
@@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_regulator_driver = {
        .probe = da9052_regulator_probe,
-       .remove = __devexit_p(da9052_regulator_remove),
+       .remove = da9052_regulator_remove,
        .driver = {
                .name = "da9052-regulator",
                .owner = THIS_MODULE,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
new file mode 100644 (file)
index 0000000..a4b9cb8
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+* Regulator driver for DA9055 PMIC
+*
+* Copyright(c) 2012 Dialog Semiconductor Ltd.
+*
+* Author: David Dajun Chen <dchen@diasemi.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_MIN_UA          0
+#define DA9055_MAX_UA          3
+
+#define DA9055_LDO_MODE_SYNC   0
+#define DA9055_LDO_MODE_SLEEP  1
+
+#define DA9055_BUCK_MODE_SLEEP 1
+#define DA9055_BUCK_MODE_SYNC  2
+#define DA9055_BUCK_MODE_AUTO  3
+
+/* DA9055 REGULATOR IDs */
+#define DA9055_ID_BUCK1        0
+#define DA9055_ID_BUCK2        1
+#define DA9055_ID_LDO1         2
+#define DA9055_ID_LDO2         3
+#define DA9055_ID_LDO3         4
+#define DA9055_ID_LDO4         5
+#define DA9055_ID_LDO5         6
+#define DA9055_ID_LDO6         7
+
+/* DA9055 BUCK current limit */
+static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+
+struct da9055_conf_reg {
+       int reg;
+       int sel_mask;
+       int en_mask;
+};
+
+struct da9055_volt_reg {
+       int reg_a;
+       int reg_b;
+       int sl_shift;
+       int v_mask;
+       int v_shift;
+};
+
+struct da9055_mode_reg {
+       int reg;
+       int mask;
+       int shift;
+};
+
+struct da9055_regulator_info {
+       struct regulator_desc reg_desc;
+       struct da9055_conf_reg conf;
+       struct da9055_volt_reg volt;
+       struct da9055_mode_reg mode;
+};
+
+struct da9055_regulator {
+       struct da9055 *da9055;
+       struct da9055_regulator_info *info;
+       struct regulator_dev *rdev;
+       enum gpio_select reg_rselect;
+};
+
+static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret, mode = 0;
+
+       ret = da9055_reg_read(regulator->da9055, info->mode.reg);
+       if (ret < 0)
+               return ret;
+
+       switch ((ret & info->mode.mask) >> info->mode.shift) {
+       case DA9055_BUCK_MODE_SYNC:
+               mode = REGULATOR_MODE_FAST;
+               break;
+       case DA9055_BUCK_MODE_AUTO:
+               mode = REGULATOR_MODE_NORMAL;
+               break;
+       case DA9055_BUCK_MODE_SLEEP:
+               mode = REGULATOR_MODE_STANDBY;
+               break;
+       }
+
+       return mode;
+}
+
+static int da9055_buck_set_mode(struct regulator_dev *rdev,
+                                       unsigned int mode)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int val = 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = DA9055_BUCK_MODE_SYNC << info->mode.shift;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = DA9055_BUCK_MODE_AUTO << info->mode.shift;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;
+               break;
+       }
+
+       return da9055_reg_update(regulator->da9055, info->mode.reg,
+                                info->mode.mask, val);
+}
+
+static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);
+       if (ret < 0)
+               return ret;
+
+       if (ret >> info->volt.sl_shift)
+               return REGULATOR_MODE_STANDBY;
+       else
+               return REGULATOR_MODE_NORMAL;
+}
+
+static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       struct da9055_volt_reg volt = info->volt;
+       int val = 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_NORMAL:
+       case REGULATOR_MODE_FAST:
+               val = DA9055_LDO_MODE_SYNC;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val = DA9055_LDO_MODE_SLEEP;
+               break;
+       }
+
+       return da9055_reg_update(regulator->da9055, volt.reg_b,
+                                1 << volt.sl_shift,
+                                val << volt.sl_shift);
+}
+
+static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->mode.mask;
+       return da9055_current_limits[ret >> info->mode.shift];
+}
+
+static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
+                                        int max_uA)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int i;
+
+       for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
+               if ((min_uA <= da9055_current_limits[i]) &&
+                   (da9055_current_limits[i] <= max_uA))
+                       return da9055_reg_update(regulator->da9055,
+                                                DA9055_REG_BUCK_LIM,
+                                                info->mode.mask,
+                                                i << info->mode.shift);
+       }
+
+       return -EINVAL;
+}
+
+static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       struct da9055_volt_reg volt = info->volt;
+       int ret, sel;
+
+       /*
+        * There are two voltage register set A & B for voltage ramping but
+        * either one of then can be active therefore we first determine
+        * the active register set.
+        */
+       ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->conf.sel_mask;
+
+       /* Get the voltage for the active register set A/B */
+       if (ret == DA9055_REGUALTOR_SET_A)
+               ret = da9055_reg_read(regulator->da9055, volt.reg_a);
+       else
+               ret = da9055_reg_read(regulator->da9055, volt.reg_b);
+
+       if (ret < 0)
+               return ret;
+
+       sel = (ret & volt.v_mask);
+       return sel;
+}
+
+static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
+                                           unsigned int selector)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       /*
+        * Regulator register set A/B is not selected through GPIO therefore
+        * we use default register set A for voltage ramping.
+        */
+       if (regulator->reg_rselect == NO_GPIO) {
+               /* Select register set A */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_A);
+               if (ret < 0)
+                       return ret;
+
+               /* Set the voltage */
+               return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+                                        info->volt.v_mask, selector);
+       }
+
+       /*
+        * Here regulator register set A/B is selected through GPIO.
+        * Therefore we first determine the selected register set A/B and
+        * then set the desired voltage for that register set A/B.
+        */
+       ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->conf.sel_mask;
+
+       /* Set the voltage */
+       if (ret == DA9055_REGUALTOR_SET_A)
+               return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+                                        info->volt.v_mask, selector);
+       else
+               return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+                                        info->volt.v_mask, selector);
+}
+
+static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,
+                                               int uV)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       /* Select register set B for suspend voltage ramping. */
+       if (regulator->reg_rselect == NO_GPIO) {
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_B);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ret = regulator_map_voltage_linear(rdev, uV, uV);
+       if (ret < 0)
+               return ret;
+
+       return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+                                info->volt.v_mask, ret);
+}
+
+static int da9055_suspend_enable(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       /* Select register set B for voltage ramping. */
+       if (regulator->reg_rselect == NO_GPIO)
+               return da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_B);
+       else
+               return 0;
+}
+
+static int da9055_suspend_disable(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       /* Diselect register set B. */
+       if (regulator->reg_rselect == NO_GPIO)
+               return da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_A);
+       else
+               return 0;
+}
+
+static struct regulator_ops da9055_buck_ops = {
+       .get_mode = da9055_buck_get_mode,
+       .set_mode = da9055_buck_set_mode,
+
+       .get_current_limit = da9055_buck_get_current_limit,
+       .set_current_limit = da9055_buck_set_current_limit,
+
+       .get_voltage_sel = da9055_regulator_get_voltage_sel,
+       .set_voltage_sel = da9055_regulator_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+
+       .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+       .set_suspend_enable = da9055_suspend_enable,
+       .set_suspend_disable = da9055_suspend_disable,
+       .set_suspend_mode = da9055_buck_set_mode,
+};
+
+static struct regulator_ops da9055_ldo_ops = {
+       .get_mode = da9055_ldo_get_mode,
+       .set_mode = da9055_ldo_set_mode,
+
+       .get_voltage_sel = da9055_regulator_get_voltage_sel,
+       .set_voltage_sel = da9055_regulator_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+
+       .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+       .set_suspend_enable = da9055_suspend_enable,
+       .set_suspend_disable = da9055_suspend_disable,
+       .set_suspend_mode = da9055_ldo_set_mode,
+
+};
+
+#define DA9055_LDO(_id, step, min, max, vbits, voffset) \
+{\
+       .reg_desc = {\
+               .name = #_id,\
+               .ops = &da9055_ldo_ops,\
+               .type = REGULATOR_VOLTAGE,\
+               .id = DA9055_ID_##_id,\
+               .n_voltages = (max - min) / step + 1 + (voffset), \
+               .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .enable_mask = 1, \
+               .min_uV = (min) * 1000,\
+               .uV_step = (step) * 1000,\
+               .linear_min_sel = (voffset),\
+               .owner = THIS_MODULE,\
+       },\
+       .conf = {\
+               .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .sel_mask = (1 << 4),\
+               .en_mask = 1,\
+       },\
+       .volt = {\
+               .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+               .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+               .sl_shift = 7,\
+               .v_mask = (1 << (vbits)) - 1,\
+               .v_shift = (vbits),\
+       },\
+}
+
+#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \
+{\
+       .reg_desc = {\
+               .name = #_id,\
+               .ops = &da9055_buck_ops,\
+               .type = REGULATOR_VOLTAGE,\
+               .id = DA9055_ID_##_id,\
+               .n_voltages = (max - min) / step + 1 + (voffset), \
+               .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .enable_mask = 1,\
+               .min_uV = (min) * 1000,\
+               .uV_step = (step) * 1000,\
+               .linear_min_sel = (voffset),\
+               .owner = THIS_MODULE,\
+       },\
+       .conf = {\
+               .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .sel_mask = (1 << 4),\
+               .en_mask = 1,\
+       },\
+       .volt = {\
+               .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+               .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+               .sl_shift = 7,\
+               .v_mask = (1 << (vbits)) - 1,\
+               .v_shift = (vbits),\
+       },\
+       .mode = {\
+               .reg = DA9055_REG_BCORE_MODE,\
+               .mask = (mbits),\
+               .shift = (sbits),\
+       },\
+}
+
+static struct da9055_regulator_info da9055_regulator_info[] = {
+       DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),
+       DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),
+       DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),
+       DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),
+       DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),
+};
+
+/*
+ * Configures regulator to be controlled either through GPIO 1 or 2.
+ * GPIO can control regulator state and/or select the regulator register
+ * set A/B for voltage ramping.
+ */
+static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
+                                     struct regulator_config *config,
+                                     struct da9055_pdata *pdata, int id)
+{
+       struct da9055_regulator_info *info = regulator->info;
+       int ret = 0;
+
+       if (pdata->gpio_ren && pdata->gpio_ren[id]) {
+               char name[18];
+               int gpio_mux = pdata->gpio_ren[id];
+
+               config->ena_gpio = pdata->ena_gpio[id];
+               config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+               config->ena_gpio_invert = 1;
+
+               /*
+                * GPI pin is muxed with regulator to control the
+                * regulator state.
+                */
+               sprintf(name, "DA9055 GPI %d", gpio_mux);
+               ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+                                           name);
+               if (ret < 0)
+                       goto err;
+
+               /*
+                * Let the regulator know that its state is controlled
+                * through GPI.
+                */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       DA9055_E_GPI_MASK,
+                                       pdata->reg_ren[id]
+                                       << DA9055_E_GPI_SHIFT);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (pdata->gpio_rsel && pdata->gpio_rsel[id]) {
+               char name[18];
+               int gpio_mux = pdata->gpio_rsel[id];
+
+               regulator->reg_rselect = pdata->reg_rsel[id];
+
+               /*
+                * GPI pin is muxed with regulator to select the
+                * regulator register set A/B for voltage ramping.
+                */
+               sprintf(name, "DA9055 GPI %d", gpio_mux);
+               ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+                                           name);
+               if (ret < 0)
+                       goto err;
+
+               /*
+                * Let the regulator know that its register set A/B
+                * will be selected through GPI for voltage ramping.
+                */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       DA9055_V_GPI_MASK,
+                                       pdata->reg_rsel[id]
+                                       << DA9055_V_GPI_SHIFT);
+       }
+
+err:
+       return ret;
+}
+
+static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)
+{
+       struct da9055_regulator *regulator = data;
+
+       regulator_notifier_call_chain(regulator->rdev,
+                                     REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+       return IRQ_HANDLED;
+}
+
+static inline struct da9055_regulator_info *find_regulator_info(int id)
+{
+       struct da9055_regulator_info *info;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {
+               info = &da9055_regulator_info[i];
+               if (info->reg_desc.id == id)
+                       return info;
+       }
+
+       return NULL;
+}
+
+static int __devinit da9055_regulator_probe(struct platform_device *pdev)
+{
+       struct regulator_config config = { };
+       struct da9055_regulator *regulator;
+       struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+       struct da9055_pdata *pdata = da9055->dev->platform_data;
+       int ret, irq;
+
+       if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
+               return -ENODEV;
+
+       regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
+                                GFP_KERNEL);
+       if (!regulator)
+               return -ENOMEM;
+
+       regulator->info = find_regulator_info(pdev->id);
+       if (regulator->info == NULL) {
+               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+               return -EINVAL;
+       }
+
+       regulator->da9055 = da9055;
+       config.dev = &pdev->dev;
+       config.driver_data = regulator;
+       config.regmap = da9055->regmap;
+
+       if (pdata && pdata->regulators)
+               config.init_data = pdata->regulators[pdev->id];
+
+       ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
+       if (ret < 0)
+               return ret;
+
+       regulator->rdev = regulator_register(&regulator->info->reg_desc,
+                                            &config);
+       if (IS_ERR(regulator->rdev)) {
+               dev_err(&pdev->dev, "Failed to register regulator %s\n",
+                       regulator->info->reg_desc.name);
+               ret = PTR_ERR(regulator->rdev);
+               return ret;
+       }
+
+       /* Only LDO 5 and 6 has got the over current interrupt */
+       if (pdev->id == DA9055_ID_LDO5 || pdev->id ==  DA9055_ID_LDO6) {
+               irq = platform_get_irq_byname(pdev, "REGULATOR");
+               irq = regmap_irq_get_virq(da9055->irq_data, irq);
+               ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                               da9055_ldo5_6_oc_irq,
+                                               IRQF_TRIGGER_HIGH |
+                                               IRQF_ONESHOT |
+                                               IRQF_PROBE_SHARED,
+                                               pdev->name, regulator);
+               if (ret != 0) {
+                       if (ret != -EBUSY) {
+                               dev_err(&pdev->dev,
+                               "Failed to request Regulator IRQ %d: %d\n",
+                               irq, ret);
+                               goto err_regulator;
+                       }
+               }
+       }
+
+       platform_set_drvdata(pdev, regulator);
+
+       return 0;
+
+err_regulator:
+       regulator_unregister(regulator->rdev);
+       return ret;
+}
+
+static int __devexit da9055_regulator_remove(struct platform_device *pdev)
+{
+       struct da9055_regulator *regulator = platform_get_drvdata(pdev);
+
+       regulator_unregister(regulator->rdev);
+
+       return 0;
+}
+
+static struct platform_driver da9055_regulator_driver = {
+       .probe = da9055_regulator_probe,
+       .remove = __devexit_p(da9055_regulator_remove),
+       .driver = {
+               .name = "da9055-regulator",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init da9055_regulator_init(void)
+{
+       return platform_driver_register(&da9055_regulator_driver);
+}
+subsys_initcall(da9055_regulator_init);
+
+static void __exit da9055_regulator_exit(void)
+{
+       platform_driver_unregister(&da9055_regulator_driver);
+}
+module_exit(da9055_regulator_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-regulator");
index 359f8d18fc3f35f03f0314661aba33def33846f7..219d162b651e3c75f2077517e5b3e0b69c28100f 100644 (file)
@@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
        },
 };
 
-static __devinit int db8500_regulator_register(struct platform_device *pdev,
+static int db8500_regulator_register(struct platform_device *pdev,
                                        struct regulator_init_data *init_data,
                                        int id,
                                        struct device_node *np)
@@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
        { .name = "db8500_esram34_ret",   .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
 };
 
-static __devinit int
+static int
 db8500_regulator_of_probe(struct platform_device *pdev,
                        struct device_node *np)
 {
@@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit db8500_regulator_probe(struct platform_device *pdev)
+static int db8500_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_init_data *db8500_init_data =
                                        dev_get_platdata(&pdev->dev);
index f2e5ecdc586424ba1f92947ee5c31f1ce3268cad..261f3d2299bc0a5d2d074824211172be7a6b8448 100644 (file)
@@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
        return 0;
 }
 
-int __devinit
+int
 ux500_regulator_debug_init(struct platform_device *pdev,
        struct dbx500_regulator_info *regulator_info,
        int num_regulators)
@@ -230,7 +230,7 @@ exit_no_debugfs:
        return -ENOMEM;
 }
 
-int __devexit ux500_regulator_debug_exit(void)
+int ux500_regulator_debug_exit(void)
 {
        debugfs_remove_recursive(rdebug.dir);
        kfree(rdebug.state_after_suspend);
index 03a1d7c11ef2b5c9ce0d07c91517673cf83d30bb..df9f42524abb3fd1164f61e7bee4065985d59d24 100644 (file)
@@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
        .ops = &dummy_ops,
 };
 
-static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+static int dummy_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        int ret;
index 339f4d732e973e5c4ca543d869da368af80a90c3..9165b0c40ed32a6b4e8a851e5c81f9b1f68f8be0 100644 (file)
@@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit fan53555_regulator_probe(struct i2c_client *client,
+static int fan53555_regulator_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct fan53555_device_info *di;
@@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client,
 
 }
 
-static int __devexit fan53555_regulator_remove(struct i2c_client *client)
+static int fan53555_regulator_remove(struct i2c_client *client)
 {
        struct fan53555_device_info *di = i2c_get_clientdata(client);
 
@@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
                .name = "fan53555-regulator",
        },
        .probe = fan53555_regulator_probe,
-       .remove = __devexit_p(fan53555_regulator_remove),
+       .remove = fan53555_regulator_remove,
        .id_table = fan53555_id,
 };
 
index 185468c4d38fcbe691c7842ca9a0f50068ca5e25..48d5b7608b00bd519cbb4c2434721335c91fa4d4 100644 (file)
@@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
        .list_voltage = fixed_voltage_list_voltage,
 };
 
-static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
+static int reg_fixed_voltage_probe(struct platform_device *pdev)
 {
        struct fixed_voltage_config *config;
        struct fixed_voltage_data *drvdata;
@@ -234,7 +234,7 @@ err:
        return ret;
 }
 
-static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
+static int reg_fixed_voltage_remove(struct platform_device *pdev)
 {
        struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
@@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
 
 static struct platform_driver regulator_fixed_voltage_driver = {
        .probe          = reg_fixed_voltage_probe,
-       .remove         = __devexit_p(reg_fixed_voltage_remove),
+       .remove         = reg_fixed_voltage_remove,
        .driver         = {
                .name           = "reg-fixed-voltage",
                .owner          = THIS_MODULE,
index 8b5944f2d7d1ddd36e82e92d786770e469743dfe..8ae288fc150b8682c9cb597b0b4c07cd8cdfda8f 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 struct gpio_regulator_data {
        struct regulator_desc desc;
@@ -79,7 +82,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev,
 
        for (ptr = 0; ptr < data->nr_gpios; ptr++) {
                state = (target & (1 << ptr)) >> ptr;
-               gpio_set_value(data->gpios[ptr].gpio, state);
+               gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
        }
        data->state = target;
 
@@ -116,7 +119,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
 
        for (ptr = 0; ptr < data->nr_gpios; ptr++) {
                state = (target & (1 << ptr)) >> ptr;
-               gpio_set_value(data->gpios[ptr].gpio, state);
+               gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
        }
        data->state = target;
 
@@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
        .list_voltage = gpio_regulator_list_voltage,
 };
 
+struct gpio_regulator_config *
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+{
+       struct gpio_regulator_config *config;
+       struct property *prop;
+       const char *regtype;
+       int proplen, gpio, i;
+
+       config = devm_kzalloc(dev,
+                       sizeof(struct gpio_regulator_config),
+                       GFP_KERNEL);
+       if (!config)
+               return ERR_PTR(-ENOMEM);
+
+       config->init_data = of_get_regulator_init_data(dev, np);
+       if (!config->init_data)
+               return ERR_PTR(-EINVAL);
+
+       config->supply_name = config->init_data->constraints.name;
+
+       if (of_property_read_bool(np, "enable-active-high"))
+               config->enable_high = true;
+
+       if (of_property_read_bool(np, "enable-at-boot"))
+               config->enabled_at_boot = true;
+
+       of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+
+       config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+       /* Fetch GPIOs. */
+       for (i = 0; ; i++)
+               if (of_get_named_gpio(np, "gpios", i) < 0)
+                       break;
+       config->nr_gpios = i;
+
+       config->gpios = devm_kzalloc(dev,
+                               sizeof(struct gpio) * config->nr_gpios,
+                               GFP_KERNEL);
+       if (!config->gpios)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < config->nr_gpios; i++) {
+               gpio = of_get_named_gpio(np, "gpios", i);
+               if (gpio < 0)
+                       break;
+               config->gpios[i].gpio = gpio;
+       }
+
+       /* Fetch states. */
+       prop = of_find_property(np, "states", NULL);
+       if (!prop) {
+               dev_err(dev, "No 'states' property found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       proplen = prop->length / sizeof(int);
+
+       config->states = devm_kzalloc(dev,
+                               sizeof(struct gpio_regulator_state)
+                               * (proplen / 2),
+                               GFP_KERNEL);
+       if (!config->states)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < proplen / 2; i++) {
+               config->states[i].value =
+                       be32_to_cpup((int *)prop->value + (i * 2));
+               config->states[i].gpios =
+                       be32_to_cpup((int *)prop->value + (i * 2 + 1));
+       }
+       config->nr_states = i;
+
+       of_property_read_string(np, "regulator-type", &regtype);
+
+       if (!strncmp("voltage", regtype, 7))
+               config->type = REGULATOR_VOLTAGE;
+       else if (!strncmp("current", regtype, 7))
+               config->type = REGULATOR_CURRENT;
+
+       return config;
+}
+
 static struct regulator_ops gpio_regulator_current_ops = {
        .get_current_limit = gpio_regulator_get_value,
        .set_current_limit = gpio_regulator_set_current_limit,
 };
 
-static int __devinit gpio_regulator_probe(struct platform_device *pdev)
+static int gpio_regulator_probe(struct platform_device *pdev)
 {
        struct gpio_regulator_config *config = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
        struct gpio_regulator_data *drvdata;
        struct regulator_config cfg = { };
        int ptr, ret, state;
 
+       if (np) {
+               config = of_get_gpio_regulator_config(&pdev->dev, np);
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       }
+
        drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
                               GFP_KERNEL);
        if (drvdata == NULL) {
@@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        cfg.dev = &pdev->dev;
        cfg.init_data = config->init_data;
        cfg.driver_data = drvdata;
+       cfg.of_node = np;
 
        if (config->enable_gpio >= 0)
                cfg.ena_gpio = config->enable_gpio;
@@ -254,7 +348,7 @@ err:
        return ret;
 }
 
-static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+static int gpio_regulator_remove(struct platform_device *pdev)
 {
        struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
 
@@ -270,12 +364,20 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+       { .compatible = "regulator-gpio", },
+       {},
+};
+#endif
+
 static struct platform_driver gpio_regulator_driver = {
        .probe          = gpio_regulator_probe,
-       .remove         = __devexit_p(gpio_regulator_remove),
+       .remove         = gpio_regulator_remove,
        .driver         = {
                .name           = "gpio-regulator",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(regulator_gpio_of_match),
        },
 };
 
index d8ecf49a5777e383876aae1f5894adc43d0bf741..d1e5bee2a26b210685290f7bb98d0a5138315a87 100644 (file)
@@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
        },
 };
 
-static int __devinit isl6271a_probe(struct i2c_client *i2c,
+static int isl6271a_probe(struct i2c_client *i2c,
                                     const struct i2c_device_id *id)
 {
        struct regulator_config config = { };
@@ -151,7 +151,7 @@ error:
        return err;
 }
 
-static int __devexit isl6271a_remove(struct i2c_client *i2c)
+static int isl6271a_remove(struct i2c_client *i2c)
 {
        struct isl_pmic *pmic = i2c_get_clientdata(i2c);
        int i;
@@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = isl6271a_probe,
-       .remove = __devexit_p(isl6271a_remove),
+       .remove = isl6271a_remove,
        .id_table = isl6271a_id,
 };
 
index 7c6e3b8ff484ad03ab60fd25d07f74d80395a65f..5f68ff11a2985bb6519d0b5d4f2a8c1e89ce9e05 100644 (file)
@@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
        return ret;
 }
 
-static int __devinit setup_regulators(struct lp3971 *lp3971,
+static int setup_regulators(struct lp3971 *lp3971,
                                      struct lp3971_platform_data *pdata)
 {
        int i, err;
@@ -429,7 +429,7 @@ err_nomem:
        return err;
 }
 
-static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
+static int lp3971_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct lp3971 *lp3971;
@@ -472,7 +472,7 @@ err_detect:
        return ret;
 }
 
-static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
+static int lp3971_i2c_remove(struct i2c_client *i2c)
 {
        struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
        int i;
@@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3971_i2c_probe,
-       .remove   = __devexit_p(lp3971_i2c_remove),
+       .remove   = lp3971_i2c_remove,
        .id_table = lp3971_i2c_id,
 };
 
index 3cdc755d9b225774aabf25a1101f4aeeae591cec..69c42c318b87c5506a4f1c9548bf1a303ddc3ae3 100644 (file)
@@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
        },
 };
 
-static int __devinit setup_regulators(struct lp3972 *lp3972,
+static int setup_regulators(struct lp3972 *lp3972,
        struct lp3972_platform_data *pdata)
 {
        int i, err;
@@ -523,7 +523,7 @@ err_nomem:
        return err;
 }
 
-static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
+static int lp3972_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct lp3972 *lp3972;
@@ -569,7 +569,7 @@ err_detect:
        return ret;
 }
 
-static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
+static int lp3972_i2c_remove(struct i2c_client *i2c)
 {
        struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
        int i;
@@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3972_i2c_probe,
-       .remove   = __devexit_p(lp3972_i2c_remove),
+       .remove   = lp3972_i2c_remove,
        .id_table = lp3972_i2c_id,
 };
 
index 708f4b6a17dcb02ee45b26223db11fc78b3319e3..9289ead715cab59d749c56222f605195051395db 100644 (file)
@@ -893,7 +893,7 @@ err_dev:
        return ret;
 }
 
-static int __devexit lp872x_remove(struct i2c_client *cl)
+static int lp872x_remove(struct i2c_client *cl)
 {
        struct lp872x *lp = i2c_get_clientdata(cl);
 
@@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
                .owner = THIS_MODULE,
        },
        .probe = lp872x_probe,
-       .remove = __devexit_p(lp872x_remove),
+       .remove = lp872x_remove,
        .id_table = lp872x_ids,
 };
 
index ba3e0aa402de84a67cfcb3ac15ee8c0555f2eb1b..aef3f2b0c5ea433e45647f1c10a7a429d416a234 100644 (file)
@@ -429,18 +429,6 @@ static struct regulator_desc lp8788_buck_desc[] = {
        },
 };
 
-static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
-{
-       struct device *dev = buck->lp->dev;
-
-       if (!gpio_is_valid(gpio)) {
-               dev_err(dev, "invalid gpio: %d\n", gpio);
-               return -EINVAL;
-       }
-
-       return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
-}
-
 static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
                                enum lp8788_buck_id id)
 {
@@ -452,7 +440,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
        switch (id) {
        case BUCK1:
                gpio = pdata->buck1_dvs->gpio;
-               ret = _gpio_request(buck, gpio, b1_name);
+               ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW,
+                                           b1_name);
                if (ret)
                        return ret;
 
@@ -461,7 +450,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
        case BUCK2:
                for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
                        gpio = pdata->buck2_dvs->gpio[i];
-                       ret = _gpio_request(buck, gpio, b2_name[i]);
+                       ret = devm_gpio_request_one(buck->lp->dev, gpio,
+                                                   DVS_LOW, b2_name[i]);
                        if (ret)
                                return ret;
                }
@@ -504,7 +494,7 @@ set_default_dvs_mode:
                                  default_dvs_mode[id]);
 }
 
-static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+static int lp8788_buck_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -542,7 +532,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+static int lp8788_buck_remove(struct platform_device *pdev)
 {
        struct lp8788_buck *buck = platform_get_drvdata(pdev);
 
@@ -554,7 +544,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_buck_driver = {
        .probe = lp8788_buck_probe,
-       .remove = __devexit_p(lp8788_buck_remove),
+       .remove = lp8788_buck_remove,
        .driver = {
                .name = LP8788_DEV_BUCK,
                .owner = THIS_MODULE,
index 6796eeb47dc6f65b1997f75cacc1f04cb8e7d6cf..3792741708ce65b4b0bbb3449643baef4a21b22c 100644 (file)
@@ -126,7 +126,7 @@ struct lp8788_ldo {
 };
 
 /* DLDO 1, 2, 3, 9 voltage table */
-const int lp8788_dldo1239_vtbl[] = {
+static const int lp8788_dldo1239_vtbl[] = {
        1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
        2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
        2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
@@ -662,14 +662,6 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
                [EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
                [EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
        };
-       u8 val[] = {
-               [EN_ALDO1]   = 0 << 5,
-               [EN_ALDO234] = 0 << 4,
-               [EN_ALDO5]   = 0 << 3,
-               [EN_ALDO7]   = 0 << 2,
-               [EN_DLDO7]   = 0 << 1,
-               [EN_DLDO911] = 0 << 0,
-       };
 
        switch (id) {
        case DLDO7:
@@ -708,11 +700,10 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
        return ret;
 
 set_default_ldo_enable_mode:
-       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
-                               val[enable_id]);
+       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
 }
 
-static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+static int lp8788_dldo_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -749,7 +740,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+static int lp8788_dldo_remove(struct platform_device *pdev)
 {
        struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -761,14 +752,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_dldo_driver = {
        .probe = lp8788_dldo_probe,
-       .remove = __devexit_p(lp8788_dldo_remove),
+       .remove = lp8788_dldo_remove,
        .driver = {
                .name = LP8788_DEV_DLDO,
                .owner = THIS_MODULE,
        },
 };
 
-static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+static int lp8788_aldo_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -805,7 +796,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+static int lp8788_aldo_remove(struct platform_device *pdev)
 {
        struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -817,7 +808,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_aldo_driver = {
        .probe = lp8788_aldo_probe,
-       .remove = __devexit_p(lp8788_aldo_remove),
+       .remove = lp8788_aldo_remove,
        .driver = {
                .name = LP8788_DEV_ALDO,
                .owner = THIS_MODULE,
index f67af3c1b9638636f5bdde781d15b79d516b89e8..8c5a54f541b50964567ba739a128b0ae59ec286a 100644 (file)
@@ -44,6 +44,9 @@ struct max1586_data {
        unsigned int min_uV;
        unsigned int max_uV;
 
+       unsigned int v3_curr_sel;
+       unsigned int v6_curr_sel;
+
        struct regulator_dev *rdev[0];
 };
 
@@ -63,31 +66,60 @@ static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
  * R24 and R25=100kOhm as described in the data sheet.
  * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
  */
+static int max1586_v3_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+
+       return max1586->v3_curr_sel;
+}
+
 static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
                                      unsigned selector)
 {
        struct max1586_data *max1586 = rdev_get_drvdata(rdev);
        struct i2c_client *client = max1586->client;
+       int ret;
        u8 v3_prog;
 
        dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
                regulator_list_voltage_linear(rdev, selector) / 1000);
 
        v3_prog = I2C_V3_SELECT | (u8) selector;
-       return i2c_smbus_write_byte(client, v3_prog);
+       ret = i2c_smbus_write_byte(client, v3_prog);
+       if (ret)
+               return ret;
+
+       max1586->v3_curr_sel = selector;
+
+       return 0;
+}
+
+static int max1586_v6_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+
+       return max1586->v6_curr_sel;
 }
 
 static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
                                      unsigned int selector)
 {
-       struct i2c_client *client = rdev_get_drvdata(rdev);
+       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+       struct i2c_client *client = max1586->client;
        u8 v6_prog;
+       int ret;
 
        dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
                rdev->desc->volt_table[selector] / 1000);
 
        v6_prog = I2C_V6_SELECT | (u8) selector;
-       return i2c_smbus_write_byte(client, v6_prog);
+       ret = i2c_smbus_write_byte(client, v6_prog);
+       if (ret)
+               return ret;
+
+       max1586->v6_curr_sel = selector;
+
+       return 0;
 }
 
 /*
@@ -95,12 +127,14 @@ static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
  * the set up value.
  */
 static struct regulator_ops max1586_v3_ops = {
+       .get_voltage_sel = max1586_v3_get_voltage_sel,
        .set_voltage_sel = max1586_v3_set_voltage_sel,
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
 };
 
 static struct regulator_ops max1586_v6_ops = {
+       .get_voltage_sel = max1586_v6_get_voltage_sel,
        .set_voltage_sel = max1586_v6_set_voltage_sel,
        .list_voltage = regulator_list_voltage_table,
 };
@@ -125,7 +159,7 @@ static struct regulator_desc max1586_reg[] = {
        },
 };
 
-static int __devinit max1586_pmic_probe(struct i2c_client *client,
+static int max1586_pmic_probe(struct i2c_client *client,
                                        const struct i2c_device_id *i2c_id)
 {
        struct regulator_dev **rdev;
@@ -148,6 +182,10 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
        max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000;
        max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000;
 
+       /* Set curr_sel to default voltage on power-up */
+       max1586->v3_curr_sel = 24; /* 1.3V */
+       max1586->v6_curr_sel = 0;
+
        rdev = max1586->rdev;
        for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) {
                id = pdata->subdevs[i].id;
@@ -188,7 +226,7 @@ err:
        return ret;
 }
 
-static int __devexit max1586_pmic_remove(struct i2c_client *client)
+static int max1586_pmic_remove(struct i2c_client *client)
 {
        struct max1586_data *max1586 = i2c_get_clientdata(client);
        int i;
@@ -207,7 +245,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
 
 static struct i2c_driver max1586_pmic_driver = {
        .probe = max1586_pmic_probe,
-       .remove = __devexit_p(max1586_pmic_remove),
+       .remove = max1586_pmic_remove,
        .driver         = {
                .name   = "max1586",
                .owner  = THIS_MODULE,
index 2a67d08658add7dfcabbc1c00d4a0a02b9b70a0d..b85040caaea318b13154927bc1beb0e13aef6ad4 100644 (file)
@@ -67,8 +67,94 @@ enum max77686_ramp_rate {
 
 struct max77686_data {
        struct regulator_dev *rdev[MAX77686_REGULATORS];
+       unsigned int opmode[MAX77686_REGULATORS];
 };
 
+/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
+static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       if (rdev->desc->id == MAX77686_BUCK1)
+               val = 0x1;
+       else
+               val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
+static int max77686_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       unsigned int val;
+
+       /* BUCK[5-9] doesn't support this feature */
+       if (rdev->desc->id >= MAX77686_BUCK5)
+               return 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
+static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       switch (mode) {
+       case REGULATOR_MODE_STANDBY:                    /* switch off */
+               val = 0x1 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+static int max77686_enable(struct regulator_dev *rdev)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 max77686->opmode[rdev->desc->id]);
+}
+
 static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
        unsigned int ramp_value = RAMP_RATE_NO_CTRL;
@@ -98,23 +184,49 @@ static struct regulator_ops max77686_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_ldo_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_buck1_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_disable    = max77686_buck_set_suspend_disable,
 };
 
 static struct regulator_ops max77686_buck_dvs_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = max77686_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_ramp_delay         = max77686_set_ramp_delay,
+       .set_suspend_disable    = max77686_buck_set_suspend_disable,
 };
 
 #define regulator_desc_ldo(num)                {                               \
@@ -133,7 +245,39 @@ static struct regulator_ops max77686_buck_dvs_ops = {
        .enable_mask    = MAX77686_OPMODE_MASK                          \
                        << MAX77686_OPMODE_SHIFT,                       \
 }
+#define regulator_desc_lpm_ldo(num)    {                               \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
 #define regulator_desc_ldo_low(num)            {                       \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo1_low(num)           {                       \
        .name           = "LDO"#num,                                    \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ops,                                \
@@ -167,7 +311,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 #define regulator_desc_buck1(num)              {                       \
        .name           = "BUCK"#num,                                   \
        .id             = MAX77686_BUCK##num,                           \
-       .ops            = &max77686_ops,                                \
+       .ops            = &max77686_buck1_ops,                          \
        .type           = REGULATOR_VOLTAGE,                            \
        .owner          = THIS_MODULE,                                  \
        .min_uV         = MAX77686_BUCK_MINUV,                          \
@@ -197,7 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 
 static struct regulator_desc regulators[] = {
-       regulator_desc_ldo_low(1),
+       regulator_desc_ldo1_low(1),
        regulator_desc_ldo_low(2),
        regulator_desc_ldo(3),
        regulator_desc_ldo(4),
@@ -206,13 +350,13 @@ static struct regulator_desc regulators[] = {
        regulator_desc_ldo_low(7),
        regulator_desc_ldo_low(8),
        regulator_desc_ldo(9),
-       regulator_desc_ldo(10),
-       regulator_desc_ldo(11),
-       regulator_desc_ldo(12),
+       regulator_desc_lpm_ldo(10),
+       regulator_desc_lpm_ldo(11),
+       regulator_desc_lpm_ldo(12),
        regulator_desc_ldo(13),
-       regulator_desc_ldo(14),
+       regulator_desc_lpm_ldo(14),
        regulator_desc_ldo_low(15),
-       regulator_desc_ldo(16),
+       regulator_desc_lpm_ldo(16),
        regulator_desc_ldo(17),
        regulator_desc_ldo(18),
        regulator_desc_ldo(19),
@@ -280,7 +424,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
 }
 #endif /* CONFIG_OF */
 
-static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+static int max77686_pmic_probe(struct platform_device *pdev)
 {
        struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -314,12 +458,14 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
 
        config.dev = &pdev->dev;
        config.regmap = iodev->regmap;
+       config.driver_data = max77686;
        platform_set_drvdata(pdev, max77686);
 
        for (i = 0; i < MAX77686_REGULATORS; i++) {
                config.init_data = pdata->regulators[i].initdata;
                config.of_node = pdata->regulators[i].of_node;
 
+               max77686->opmode[i] = regulators[i].enable_mask;
                max77686->rdev[i] = regulator_register(&regulators[i], &config);
                if (IS_ERR(max77686->rdev[i])) {
                        ret = PTR_ERR(max77686->rdev[i]);
@@ -337,7 +483,7 @@ err:
        return ret;
 }
 
-static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+static int max77686_pmic_remove(struct platform_device *pdev)
 {
        struct max77686_data *max77686 = platform_get_drvdata(pdev);
        int i;
@@ -360,7 +506,7 @@ static struct platform_driver max77686_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max77686_pmic_probe,
-       .remove = __devexit_p(max77686_pmic_remove),
+       .remove = max77686_pmic_remove,
        .id_table = max77686_pmic_id,
 };
 
index 9d540cd02dab5f4de264dc35599322b773d6c484..3ca14380f22db06aba4338544cf62967d48fa900 100644 (file)
@@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit max8649_regulator_probe(struct i2c_client *client,
+static int max8649_regulator_probe(struct i2c_client *client,
                                             const struct i2c_device_id *id)
 {
        struct max8649_platform_data *pdata = client->dev.platform_data;
@@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8649_regulator_remove(struct i2c_client *client)
+static int max8649_regulator_remove(struct i2c_client *client)
 {
        struct max8649_regulator_info *info = i2c_get_clientdata(client);
 
@@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
 
 static struct i2c_driver max8649_driver = {
        .probe          = max8649_regulator_probe,
-       .remove         = __devexit_p(max8649_regulator_remove),
+       .remove         = max8649_regulator_remove,
        .driver         = {
                .name   = "max8649",
        },
index 8d531742f593616d1145fef2aa00fd22e13f4b32..4d7c635c36c2d6cc92b1ecd8fafb9d533213ae21 100644 (file)
@@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
        },
 };
 
-static int __devinit max8660_probe(struct i2c_client *client,
+static int max8660_probe(struct i2c_client *client,
                                   const struct i2c_device_id *i2c_id)
 {
        struct regulator_dev **rdev;
@@ -420,7 +420,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8660_remove(struct i2c_client *client)
+static int max8660_remove(struct i2c_client *client)
 {
        struct max8660 *max8660 = i2c_get_clientdata(client);
        int i;
@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
 
 static struct i2c_driver max8660_driver = {
        .probe = max8660_probe,
-       .remove = __devexit_p(max8660_remove),
+       .remove = max8660_remove,
        .driver         = {
                .name   = "max8660",
                .owner  = THIS_MODULE,
index af7607515ab951e2b688b31e0a1cffef8b8bc396..d1a77512d83e69501c2a4a3a3e8c3f09b75f7ba6 100644 (file)
@@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
 }
 #endif
 
-static __devinit int max8907_regulator_probe(struct platform_device *pdev)
+static int max8907_regulator_probe(struct platform_device *pdev)
 {
        struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
        struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
@@ -368,7 +368,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static __devexit int max8907_regulator_remove(struct platform_device *pdev)
+static int max8907_regulator_remove(struct platform_device *pdev)
 {
        struct max8907_regulator *pmic = platform_get_drvdata(pdev);
        int i;
@@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = max8907_regulator_probe,
-       .remove = __devexit_p(max8907_regulator_remove),
+       .remove = max8907_regulator_remove,
 };
 
 static int __init max8907_regulator_init(void)
index 9bb0be37495f417d65728720f2d13217d51962d5..446a854455535b4603fa2584f09498b0e557cc0e 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8925.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 
 #define SD1_DVM_VMIN           850000
 #define SD1_DVM_VMAX           1000000
@@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
        .enable_reg     = MAX8925_LDOCTL##_id,                  \
 }
 
+#ifdef CONFIG_OF
+static struct of_regulator_match max8925_regulator_matches[] = {
+       { .name = "SDV1",},
+       { .name = "SDV2",},
+       { .name = "SDV3",},
+       { .name = "LDO1",},
+       { .name = "LDO2",},
+       { .name = "LDO3",},
+       { .name = "LDO4",},
+       { .name = "LDO5",},
+       { .name = "LDO6",},
+       { .name = "LDO7",},
+       { .name = "LDO8",},
+       { .name = "LDO9",},
+       { .name = "LDO10",},
+       { .name = "LDO11",},
+       { .name = "LDO12",},
+       { .name = "LDO13",},
+       { .name = "LDO14",},
+       { .name = "LDO15",},
+       { .name = "LDO16",},
+       { .name = "LDO17",},
+       { .name = "LDO18",},
+       { .name = "LDO19",},
+       { .name = "LDO20",},
+};
+#endif
+
 static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_SDV(1, 637.5, 1425, 12.5),
        MAX8925_SDV(2,   650, 2225,   25),
@@ -214,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8925_regulator_dt_init(struct platform_device *pdev,
+                                   struct max8925_regulator_info *info,
+                                   struct regulator_config *config,
+                                   int ridx)
+{
+       struct device_node *nproot, *np;
+       int rcount;
+       nproot = pdev->dev.parent->of_node;
+       if (!nproot)
+               return -ENODEV;
+       np = of_find_node_by_name(nproot, "regulators");
+       if (!np) {
+               dev_err(&pdev->dev, "failed to find regulators node\n");
+               return -ENODEV;
+       }
+
+       rcount = of_regulator_match(&pdev->dev, np,
+                               &max8925_regulator_matches[ridx], 1);
+       if (rcount < 0)
+               return -ENODEV;
+       config->init_data =     max8925_regulator_matches[ridx].init_data;
+       config->of_node = max8925_regulator_matches[ridx].of_node;
+
+       return 0;
+}
+#else
+#define max8925_regulator_dt_init(w, x, y, z)  (-1)
+#endif
+
+static int max8925_regulator_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct regulator_init_data *pdata = pdev->dev.platform_data;
@@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        struct max8925_regulator_info *ri;
        struct resource *res;
        struct regulator_dev *rdev;
-       int i;
+       int i, regulator_idx;
 
        res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (!res) {
@@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        }
        for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
                ri = &max8925_regulator_info[i];
-               if (ri->vol_reg == res->start)
+               if (ri->vol_reg == res->start) {
+                       regulator_idx = i;
                        break;
+               }
        }
+
        if (i == ARRAY_SIZE(max8925_regulator_info)) {
                dev_err(&pdev->dev, "Failed to find regulator %llu\n",
                        (unsigned long long)res->start);
@@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        ri->chip = chip;
 
        config.dev = &pdev->dev;
-       config.init_data = pdata;
        config.driver_data = ri;
 
+       if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
+               if (pdata)
+                       config.init_data = pdata;
+
        rdev = regulator_register(&ri->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+static int max8925_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = max8925_regulator_probe,
-       .remove         = __devexit_p(max8925_regulator_remove),
+       .remove         = max8925_regulator_remove,
 };
 
 static int __init max8925_regulator_init(void)
index 355ca7bad9d59a9583cdda44ee986ced030ab5fa..fc7935a19e3a143f996aeeb4879d4d8ba75f0e9b 100644 (file)
@@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
        .owner          = THIS_MODULE,
 };
 
-static int __devinit max8952_pmic_probe(struct i2c_client *client,
+static int max8952_pmic_probe(struct i2c_client *client,
                const struct i2c_device_id *i2c_id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8952_pmic_remove(struct i2c_client *client)
+static int max8952_pmic_remove(struct i2c_client *client)
 {
        struct max8952_data *max8952 = i2c_get_clientdata(client);
        struct max8952_platform_data *pdata = max8952->pdata;
@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
 
 static struct i2c_driver max8952_pmic_driver = {
        .probe          = max8952_pmic_probe,
-       .remove         = __devexit_p(max8952_pmic_remove),
+       .remove         = max8952_pmic_remove,
        .driver         = {
                .name   = "max8952",
        },
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
new file mode 100644 (file)
index 0000000..3ee2638
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * max8973-regulator.c -- Maxim max8973
+ *
+ * Regulator driver for MAXIM 8973 DC-DC step-down switching regulator.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max8973-regulator.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+/* Register definitions */
+#define MAX8973_VOUT                                   0x0
+#define MAX8973_VOUT_DVS                               0x1
+#define MAX8973_CONTROL1                               0x2
+#define MAX8973_CONTROL2                               0x3
+#define MAX8973_CHIPID1                                        0x4
+#define MAX8973_CHIPID2                                        0x5
+
+#define MAX8973_MAX_VOUT_REG                           2
+
+/* MAX8973_VOUT */
+#define MAX8973_VOUT_ENABLE                            BIT(7)
+#define MAX8973_VOUT_MASK                              0x7F
+
+/* MAX8973_VOUT_DVS */
+#define MAX8973_DVS_VOUT_MASK                          0x7F
+
+/* MAX8973_CONTROL1 */
+#define MAX8973_SNS_ENABLE                             BIT(7)
+#define MAX8973_FPWM_EN_M                              BIT(6)
+#define MAX8973_NFSR_ENABLE                            BIT(5)
+#define MAX8973_AD_ENABLE                              BIT(4)
+#define MAX8973_BIAS_ENABLE                            BIT(3)
+#define MAX8973_FREQSHIFT_9PER                         BIT(2)
+
+#define MAX8973_RAMP_12mV_PER_US                       0x0
+#define MAX8973_RAMP_25mV_PER_US                       0x1
+#define MAX8973_RAMP_50mV_PER_US                       0x2
+#define MAX8973_RAMP_200mV_PER_US                      0x3
+
+/* MAX8973_CONTROL2 */
+#define MAX8973_WDTMR_ENABLE                           BIT(6)
+#define MAX8973_DISCH_ENBABLE                          BIT(5)
+#define MAX8973_FT_ENABLE                              BIT(4)
+
+#define MAX8973_CKKADV_TRIP_DISABLE                    0xC
+#define MAX8973_CKKADV_TRIP_75mV_PER_US                        0x0
+#define MAX8973_CKKADV_TRIP_150mV_PER_US               0x4
+#define MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS       0x8
+#define MAX8973_CONTROL_CLKADV_TRIP_MASK               0x00030000
+
+#define MAX8973_INDUCTOR_MIN_30_PER                    0x0
+#define MAX8973_INDUCTOR_NOMINAL                       0x1
+#define MAX8973_INDUCTOR_PLUS_30_PER                   0x2
+#define MAX8973_INDUCTOR_PLUS_60_PER                   0x3
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MASK            0x00300000
+
+#define MAX8973_MIN_VOLATGE                            606250
+#define MAX8973_MAX_VOLATGE                            1400000
+#define MAX8973_VOLATGE_STEP                           6250
+#define MAX8973_BUCK_N_VOLTAGE                         0x80
+
+/* Maxim 8973 chip information */
+struct max8973_chip {
+       struct device *dev;
+       struct regulator_desc desc;
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       bool enable_external_control;
+       int dvs_gpio;
+       int lru_index[MAX8973_MAX_VOUT_REG];
+       int curr_vout_val[MAX8973_MAX_VOUT_REG];
+       int curr_vout_reg;
+       int curr_gpio_val;
+       bool valid_dvs_gpio;
+};
+
+/*
+ * find_voltage_set_register: Find new voltage configuration register (VOUT).
+ * The finding of the new VOUT register will be based on the LRU mechanism.
+ * Each VOUT register will have different voltage configured . This
+ * Function will look if any of the VOUT register have requested voltage set
+ * or not.
+ *     - If it is already there then it will make that register as most
+ *       recently used and return as found so that caller need not to set
+ *       the VOUT register but need to set the proper gpios to select this
+ *       VOUT register.
+ *     - If requested voltage is not found then it will use the least
+ *       recently mechanism to get new VOUT register for new configuration
+ *       and will return not_found so that caller need to set new VOUT
+ *       register and then gpios (both).
+ */
+static bool find_voltage_set_register(struct max8973_chip *tps,
+               int req_vsel, int *vout_reg, int *gpio_val)
+{
+       int i;
+       bool found = false;
+       int new_vout_reg = tps->lru_index[MAX8973_MAX_VOUT_REG - 1];
+       int found_index = MAX8973_MAX_VOUT_REG - 1;
+
+       for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) {
+               if (tps->curr_vout_val[tps->lru_index[i]] == req_vsel) {
+                       new_vout_reg = tps->lru_index[i];
+                       found_index = i;
+                       found = true;
+                       goto update_lru_index;
+               }
+       }
+
+update_lru_index:
+       for (i = found_index; i > 0; i--)
+               tps->lru_index[i] = tps->lru_index[i - 1];
+
+       tps->lru_index[0] = new_vout_reg;
+       *gpio_val = new_vout_reg;
+       *vout_reg = MAX8973_VOUT + new_vout_reg;
+       return found;
+}
+
+static int max8973_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+
+       ret = regmap_read(max->regmap, max->curr_vout_reg, &data);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d read failed, err = %d\n",
+                       max->curr_vout_reg, ret);
+               return ret;
+       }
+       return data & MAX8973_VOUT_MASK;
+}
+
+static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+            unsigned vsel)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       int ret;
+       bool found = false;
+       int vout_reg = max->curr_vout_reg;
+       int gpio_val = max->curr_gpio_val;
+
+       /*
+        * If gpios are available to select the VOUT register then least
+        * recently used register for new configuration.
+        */
+       if (max->valid_dvs_gpio)
+               found = find_voltage_set_register(max, vsel,
+                                       &vout_reg, &gpio_val);
+
+       if (!found) {
+               ret = regmap_update_bits(max->regmap, vout_reg,
+                                       MAX8973_VOUT_MASK, vsel);
+               if (ret < 0) {
+                       dev_err(max->dev, "register %d update failed, err %d\n",
+                                vout_reg, ret);
+                       return ret;
+               }
+               max->curr_vout_reg = vout_reg;
+               max->curr_vout_val[gpio_val] = vsel;
+       }
+
+       /* Select proper VOUT register vio gpios */
+       if (max->valid_dvs_gpio) {
+               gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1);
+               max->curr_gpio_val = gpio_val;
+       }
+       return 0;
+}
+
+static int max8973_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       int ret;
+       int pwm;
+
+       /* Enable force PWM mode in FAST mode only. */
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               pwm = MAX8973_FPWM_EN_M;
+               break;
+
+       case REGULATOR_MODE_NORMAL:
+               pwm = 0;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
+                               MAX8973_FPWM_EN_M, pwm);
+       if (ret < 0)
+               dev_err(max->dev, "register %d update failed, err %d\n",
+                               MAX8973_CONTROL1, ret);
+       return ret;
+}
+
+static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+
+       ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d read failed, err %d\n",
+                               MAX8973_CONTROL1, ret);
+               return ret;
+       }
+       return (data & MAX8973_FPWM_EN_M) ?
+               REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops max8973_dcdc_ops = {
+       .get_voltage_sel        = max8973_dcdc_get_voltage_sel,
+       .set_voltage_sel        = max8973_dcdc_set_voltage_sel,
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_mode               = max8973_dcdc_set_mode,
+       .get_mode               = max8973_dcdc_get_mode,
+};
+
+static int __devinit max8973_init_dcdc(struct max8973_chip *max,
+               struct max8973_regulator_platform_data *pdata)
+{
+       int ret;
+       uint8_t control1 = 0;
+       uint8_t control2 = 0;
+
+       if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
+               control1 |= MAX8973_SNS_ENABLE;
+
+       if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE))
+               control1 |= MAX8973_NFSR_ENABLE;
+
+       if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
+               control1 |= MAX8973_AD_ENABLE;
+
+       if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
+               control1 |= MAX8973_BIAS_ENABLE;
+
+       if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
+               control1 |= MAX8973_FREQSHIFT_9PER;
+
+       /* Set ramp delay */
+       if (pdata->reg_init_data &&
+                       pdata->reg_init_data->constraints.ramp_delay) {
+               if (pdata->reg_init_data->constraints.ramp_delay < 25000)
+                       control1 = MAX8973_RAMP_12mV_PER_US;
+               else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
+                       control1 = MAX8973_RAMP_25mV_PER_US;
+               else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
+                       control1 = MAX8973_RAMP_50mV_PER_US;
+               else
+                       control1 = MAX8973_RAMP_200mV_PER_US;
+       } else {
+               control1 = MAX8973_RAMP_12mV_PER_US;
+               max->desc.ramp_delay = 12500;
+       }
+
+       if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
+               control2 |= MAX8973_DISCH_ENBABLE;
+
+       /*  Clock advance trip configuration */
+       switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) {
+       case MAX8973_CONTROL_CLKADV_TRIP_DISABLED:
+               control2 |= MAX8973_CKKADV_TRIP_DISABLE;
+               break;
+
+       case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US:
+               control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US;
+               break;
+
+       case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US:
+               control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US;
+               break;
+
+       case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS:
+               control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS;
+               break;
+       }
+
+       /* Configure inductor value */
+       switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) {
+       case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL:
+               control2 |= MAX8973_INDUCTOR_NOMINAL;
+               break;
+
+       case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER:
+               control2 |= MAX8973_INDUCTOR_MIN_30_PER;
+               break;
+
+       case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER:
+               control2 |= MAX8973_INDUCTOR_PLUS_30_PER;
+               break;
+
+       case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER:
+               control2 |= MAX8973_INDUCTOR_PLUS_60_PER;
+               break;
+       }
+
+       ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d write failed, err = %d",
+                               MAX8973_CONTROL1, ret);
+               return ret;
+       }
+
+       ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d write failed, err = %d",
+                               MAX8973_CONTROL2, ret);
+               return ret;
+       }
+
+       /* If external control is enabled then disable EN bit */
+       if (max->enable_external_control) {
+               ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
+                                               MAX8973_VOUT_ENABLE, 0);
+               if (ret < 0)
+                       dev_err(max->dev, "register %d update failed, err = %d",
+                               MAX8973_VOUT, ret);
+       }
+       return ret;
+}
+
+static const struct regmap_config max8973_regmap_config = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = MAX8973_CHIPID2,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int __devinit max8973_probe(struct i2c_client *client,
+                                    const struct i2c_device_id *id)
+{
+       struct max8973_regulator_platform_data *pdata;
+       struct regulator_config config = { };
+       struct regulator_dev *rdev;
+       struct max8973_chip *max;
+       int ret;
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->dev, "No Platform data");
+               return -EIO;
+       }
+
+       max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
+       if (!max) {
+               dev_err(&client->dev, "Memory allocation for max failed\n");
+               return -ENOMEM;
+       }
+
+       max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
+       if (IS_ERR(max->regmap)) {
+               ret = PTR_ERR(max->regmap);
+               dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+               return ret;
+       }
+
+       i2c_set_clientdata(client, max);
+       max->dev = &client->dev;
+       max->desc.name = id->name;
+       max->desc.id = 0;
+       max->desc.ops = &max8973_dcdc_ops;
+       max->desc.type = REGULATOR_VOLTAGE;
+       max->desc.owner = THIS_MODULE;
+       max->desc.min_uV = MAX8973_MIN_VOLATGE;
+       max->desc.uV_step = MAX8973_VOLATGE_STEP;
+       max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;
+
+       if (!pdata->enable_ext_control) {
+               max->desc.enable_reg = MAX8973_VOUT;
+               max->desc.enable_mask = MAX8973_VOUT_ENABLE;
+               max8973_dcdc_ops.enable = regulator_enable_regmap;
+               max8973_dcdc_ops.disable = regulator_disable_regmap;
+               max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap;
+       }
+
+       max->enable_external_control = pdata->enable_ext_control;
+       max->dvs_gpio = pdata->dvs_gpio;
+       max->curr_gpio_val = pdata->dvs_def_state;
+       max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
+       max->lru_index[0] = max->curr_vout_reg;
+       max->valid_dvs_gpio = false;
+
+       if (gpio_is_valid(max->dvs_gpio)) {
+               int gpio_flags;
+               int i;
+
+               gpio_flags = (pdata->dvs_def_state) ?
+                               GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+               ret = devm_gpio_request_one(&client->dev, max->dvs_gpio,
+                               gpio_flags, "max8973-dvs");
+               if (ret) {
+                       dev_err(&client->dev,
+                               "gpio_request for gpio %d failed, err = %d\n",
+                               max->dvs_gpio, ret);
+                       return ret;
+               }
+               max->valid_dvs_gpio = true;
+
+               /*
+                * Initialize the lru index with vout_reg id
+                * The index 0 will be most recently used and
+                * set with the max->curr_vout_reg */
+               for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i)
+                       max->lru_index[i] = i;
+               max->lru_index[0] = max->curr_vout_reg;
+               max->lru_index[max->curr_vout_reg] = 0;
+       }
+
+       ret = max8973_init_dcdc(max, pdata);
+       if (ret < 0) {
+               dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
+               return ret;
+       }
+
+       config.dev = &client->dev;
+       config.init_data = pdata->reg_init_data;
+       config.driver_data = max;
+       config.of_node = client->dev.of_node;
+       config.regmap = max->regmap;
+
+       /* Register the regulators */
+       rdev = regulator_register(&max->desc, &config);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(max->dev, "regulator register failed, err %d\n", ret);
+               return ret;
+       }
+
+       max->rdev = rdev;
+       return 0;
+}
+
+static int __devexit max8973_remove(struct i2c_client *client)
+{
+       struct max8973_chip *max = i2c_get_clientdata(client);
+
+       regulator_unregister(max->rdev);
+       return 0;
+}
+
+static const struct i2c_device_id max8973_id[] = {
+       {.name = "max8973",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, max8973_id);
+
+static struct i2c_driver max8973_i2c_driver = {
+       .driver = {
+               .name = "max8973",
+               .owner = THIS_MODULE,
+       },
+       .probe = max8973_probe,
+       .remove = __devexit_p(max8973_remove),
+       .id_table = max8973_id,
+};
+
+static int __init max8973_init(void)
+{
+       return i2c_add_driver(&max8973_i2c_driver);
+}
+subsys_initcall(max8973_init);
+
+static void __exit max8973_cleanup(void)
+{
+       i2c_del_driver(&max8973_i2c_driver);
+}
+module_exit(max8973_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("MAX8973 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
index e39a0c7260dca5b7fe13098dbfd06d98c4b0b3e5..df0eafb0dc7e63a1f4a9e8bfb989d91caa1d9f63 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -31,6 +32,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
+#include <linux/regulator/of_regulator.h>
 
 struct max8997_data {
        struct device *dev;
@@ -933,22 +935,163 @@ static struct regulator_desc regulators[] = {
                                  max8997_charger_fixedstate_ops),
 };
 
-static __devinit int max8997_pmic_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+                       struct max8997_platform_data *pdata,
+                       struct device_node *pmic_np)
+{
+       int i, gpio;
+
+       for (i = 0; i < 3; i++) {
+               gpio = of_get_named_gpio(pmic_np,
+                                       "max8997,pmic-buck125-dvs-gpios", i);
+               if (!gpio_is_valid(gpio)) {
+                       dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+                       return -EINVAL;
+               }
+               pdata->buck125_gpios[i] = gpio;
+       }
+       return 0;
+}
+
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+                                       struct max8997_platform_data *pdata)
+{
+       struct device_node *pmic_np, *regulators_np, *reg_np;
+       struct max8997_regulator_data *rdata;
+       unsigned int i, dvs_voltage_nr = 1, ret;
+
+       pmic_np = iodev->dev->of_node;
+       if (!pmic_np) {
+               dev_err(iodev->dev, "could not find pmic sub-node\n");
+               return -ENODEV;
+       }
+
+       regulators_np = of_find_node_by_name(pmic_np, "regulators");
+       if (!regulators_np) {
+               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               return -EINVAL;
+       }
+
+       /* count the number of regulators to be supported in pmic */
+       pdata->num_regulators = 0;
+       for_each_child_of_node(regulators_np, reg_np)
+               pdata->num_regulators++;
+
+       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+                               pdata->num_regulators, GFP_KERNEL);
+       if (!rdata) {
+               dev_err(iodev->dev, "could not allocate memory for "
+                                               "regulator data\n");
+               return -ENOMEM;
+       }
+
+       pdata->regulators = rdata;
+       for_each_child_of_node(regulators_np, reg_np) {
+               for (i = 0; i < ARRAY_SIZE(regulators); i++)
+                       if (!of_node_cmp(reg_np->name, regulators[i].name))
+                               break;
+
+               if (i == ARRAY_SIZE(regulators)) {
+                       dev_warn(iodev->dev, "don't know how to configure "
+                               "regulator %s\n", reg_np->name);
+                       continue;
+               }
+
+               rdata->id = i;
+               rdata->initdata = of_get_regulator_init_data(
+                                               iodev->dev, reg_np);
+               rdata->reg_node = reg_np;
+               rdata++;
+       }
+
+       if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL))
+               pdata->buck1_gpiodvs = true;
+
+       if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL))
+               pdata->buck2_gpiodvs = true;
+
+       if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL))
+               pdata->buck5_gpiodvs = true;
+
+       if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+                                               pdata->buck5_gpiodvs) {
+               ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+               if (ret)
+                       return -EINVAL;
+
+               if (of_property_read_u32(pmic_np,
+                               "max8997,pmic-buck125-default-dvs-idx",
+                               &pdata->buck125_default_idx)) {
+                       pdata->buck125_default_idx = 0;
+               } else {
+                       if (pdata->buck125_default_idx >= 8) {
+                               pdata->buck125_default_idx = 0;
+                               dev_info(iodev->dev, "invalid value for "
+                               "default dvs index, using 0 instead\n");
+                       }
+               }
+
+               if (of_get_property(pmic_np,
+                       "max8997,pmic-ignore-gpiodvs-side-effect", NULL))
+                       pdata->ignore_gpiodvs_side_effect = true;
+
+               dvs_voltage_nr = 8;
+       }
+
+       if (of_property_read_u32_array(pmic_np,
+                               "max8997,pmic-buck1-dvs-voltage",
+                               pdata->buck1_voltage, dvs_voltage_nr)) {
+               dev_err(iodev->dev, "buck1 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32_array(pmic_np,
+                               "max8997,pmic-buck2-dvs-voltage",
+                               pdata->buck2_voltage, dvs_voltage_nr)) {
+               dev_err(iodev->dev, "buck2 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32_array(pmic_np,
+                               "max8997,pmic-buck5-dvs-voltage",
+                               pdata->buck5_voltage, dvs_voltage_nr)) {
+               dev_err(iodev->dev, "buck5 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+#else
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+                                       struct max8997_platform_data *pdata)
+{
+       return 0;
+}
+#endif /* CONFIG_OF */
+
+static int max8997_pmic_probe(struct platform_device *pdev)
 {
        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct max8997_platform_data *pdata = iodev->pdata;
        struct regulator_config config = { };
        struct regulator_dev **rdev;
        struct max8997_data *max8997;
        struct i2c_client *i2c;
-       int i, ret, size;
+       int i, ret, size, nr_dvs;
        u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
 
-       if (!pdata) {
+       if (IS_ERR_OR_NULL(pdata)) {
                dev_err(pdev->dev.parent, "No platform init data supplied.\n");
                return -ENODEV;
        }
 
+       if (iodev->dev->of_node) {
+               ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+               if (ret)
+                       return ret;
+       }
+
        max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
                               GFP_KERNEL);
        if (!max8997)
@@ -973,7 +1116,10 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
        memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3);
        max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect;
 
-       for (i = 0; i < 8; i++) {
+       nr_dvs = (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+                       pdata->buck5_gpiodvs) ? 8 : 1;
+
+       for (i = 0; i < nr_dvs; i++) {
                max8997->buck1_vol[i] = ret =
                        max8997_get_voltage_proper_val(
                                        &buck1245_voltage_map_desc,
@@ -1019,6 +1165,19 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                                max_buck5, 0x3f);
        }
 
+       /* Initialize all the DVS related BUCK registers */
+       for (i = 0; i < nr_dvs; i++) {
+               max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
+                               max8997->buck1_vol[i],
+                               0x3f);
+               max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
+                               max8997->buck2_vol[i],
+                               0x3f);
+               max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
+                               max8997->buck5_vol[i],
+                               0x3f);
+       }
+
        /*
         * If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them.
         * If at least one of them cares, set gpios.
@@ -1068,19 +1227,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
        max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
                        (1 << 1) : (0 << 1), 1 << 1);
 
-       /* Initialize all the DVS related BUCK registers */
-       for (i = 0; i < 8; i++) {
-               max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
-                               max8997->buck1_vol[i],
-                               0x3f);
-               max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
-                               max8997->buck2_vol[i],
-                               0x3f);
-               max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
-                               max8997->buck5_vol[i],
-                               0x3f);
-       }
-
        /* Misc Settings */
        max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
        max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
@@ -1101,6 +1247,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                config.dev = max8997->dev;
                config.init_data = pdata->regulators[i].initdata;
                config.driver_data = max8997;
+               config.of_node = pdata->regulators[i].reg_node;
 
                rdev[i] = regulator_register(&regulators[id], &config);
                if (IS_ERR(rdev[i])) {
@@ -1120,7 +1267,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8997_pmic_remove(struct platform_device *pdev)
+static int max8997_pmic_remove(struct platform_device *pdev)
 {
        struct max8997_data *max8997 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = max8997->rdev;
@@ -1143,7 +1290,7 @@ static struct platform_driver max8997_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8997_pmic_probe,
-       .remove = __devexit_p(max8997_pmic_remove),
+       .remove = max8997_pmic_remove,
        .id_table = max8997_pmic_id,
 };
 
index 5dfa920ff0c8873c91e8c02176af4d722f3c3659..b821d08eb64ae84b643f2cfe93cd0764738d21c9 100644 (file)
@@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
        }
 };
 
-static __devinit int max8998_pmic_probe(struct platform_device *pdev)
+static int max8998_pmic_probe(struct platform_device *pdev)
 {
        struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -818,7 +818,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8998_pmic_remove(struct platform_device *pdev)
+static int max8998_pmic_remove(struct platform_device *pdev)
 {
        struct max8998_data *max8998 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = max8998->rdev;
@@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8998_pmic_probe,
-       .remove = __devexit_p(max8998_pmic_remove),
+       .remove = max8998_pmic_remove,
        .id_table = max8998_pmic_id,
 };
 
index 0801a6d0c122e7e7b94e75b797497728ef2a7d36..c46c6705cd74538af5b30c2c112cde1cedad4df2 100644 (file)
@@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
 };
 
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+static int mc13783_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
@@ -445,7 +445,7 @@ err:
        return ret;
 }
 
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+static int mc13783_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
        struct mc13xxx_regulator_platform_data *pdata =
@@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
                .name   = "mc13783-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove         = __devexit_p(mc13783_regulator_remove),
+       .remove         = mc13783_regulator_remove,
        .probe          = mc13783_regulator_probe,
 };
 
index 1fa63812f7ace6070dcfda38a14cd5aab0466b69..0d84b1f33199ca5251c425ba898ffad4296da88f 100644 (file)
@@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
 }
 
 
-static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
+static int mc13892_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
@@ -588,7 +588,7 @@ err_unlock:
        return ret;
 }
 
-static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
+static int mc13892_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
        int i;
@@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
                .name   = "mc13892-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove = __devexit_p(mc13892_regulator_remove),
+       .remove = mc13892_regulator_remove,
        .probe  = mc13892_regulator_probe,
 };
 
index 88cbb832d555207b4e7fc124aa05b4afcbcbb3f1..4ed89c6541100e838e8d6c3afb5aea3e0ad5bebf 100644 (file)
@@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
 #ifdef CONFIG_OF
-int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 {
        struct device_node *parent, *child;
        int num = 0;
@@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
 
-struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
+struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
        struct platform_device *pdev, struct mc13xxx_regulator *regulators,
        int num_regulators)
 {
index 07aee694ba92abc4c8eab282b519a89dbff69ff1..e915629a25cf64ed660e9ac9f2b2112b1ea228e9 100644 (file)
@@ -309,68 +309,22 @@ static int palmas_list_voltage_smps(struct regulator_dev *dev,
        int id = rdev_get_id(dev);
        int mult = 1;
 
-       if (!selector)
-               return 0;
-
        /* Read the multiplier set in VSEL register to return
         * the correct voltage.
         */
        if (pmic->range[id])
                mult = 2;
 
-       /* Voltage is (0.49V + (selector * 0.01V)) * RANGE
-        * as defined in data sheet. RANGE is either x1 or x2
-        */
-       return  (490000 + (selector * 10000)) * mult;
-}
-
-static int palmas_get_voltage_smps_sel(struct regulator_dev *dev)
-{
-       struct palmas_pmic *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       int selector;
-       unsigned int reg;
-       unsigned int addr;
-
-       addr = palmas_regs_info[id].vsel_addr;
-
-       palmas_smps_read(pmic->palmas, addr, &reg);
-
-       selector = reg & PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
-
-       /* Adjust selector to match list_voltage ranges */
-       if ((selector > 0) && (selector < 6))
-               selector = 6;
-       if (!selector)
-               selector = 5;
-       if (selector > 121)
-               selector = 121;
-       selector -= 5;
-
-       return selector;
-}
-
-static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
-               unsigned selector)
-{
-       struct palmas_pmic *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       unsigned int reg = 0;
-       unsigned int addr;
-
-       addr = palmas_regs_info[id].vsel_addr;
-
-       /* Make sure we don't change the value of RANGE */
-       if (pmic->range[id])
-               reg |= PALMAS_SMPS12_VOLTAGE_RANGE;
-
-       /* Adjust the linux selector into range used in VSEL register */
-       if (selector)
-               reg |= selector + 5;
-
-       palmas_smps_write(pmic->palmas, addr, reg);
-
-       return 0;
+       if (selector == 0)
+               return 0;
+       else if (selector < 6)
+               return 500000 * mult;
+       else
+               /* Voltage is linear mapping starting from selector 6,
+                * volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE
+                * RANGE is either x1 or x2
+                */
+               return (490000 + ((selector - 5) * 10000)) * mult;
 }
 
 static int palmas_map_voltage_smps(struct regulator_dev *rdev,
@@ -386,11 +340,11 @@ static int palmas_map_voltage_smps(struct regulator_dev *rdev,
        if (pmic->range[id]) { /* RANGE is x2 */
                if (min_uV < 1000000)
                        min_uV = 1000000;
-               ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
+               ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6;
        } else {                /* RANGE is x1 */
                if (min_uV < 500000)
                        min_uV = 500000;
-               ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
+               ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6;
        }
 
        /* Map back into a voltage to verify we're still in bounds */
@@ -407,8 +361,8 @@ static struct regulator_ops palmas_ops_smps = {
        .disable                = palmas_disable_smps,
        .set_mode               = palmas_set_mode_smps,
        .get_mode               = palmas_get_mode_smps,
-       .get_voltage_sel        = palmas_get_voltage_smps_sel,
-       .set_voltage_sel        = palmas_set_voltage_smps_sel,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .list_voltage           = palmas_list_voltage_smps,
        .map_voltage            = palmas_map_voltage_smps,
 };
@@ -436,44 +390,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev)
        return !!(reg);
 }
 
-static int palmas_list_voltage_ldo(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       if (!selector)
-               return 0;
-
-       /* voltage is 0.85V + (selector * 0.05v) */
-       return  850000 + (selector * 50000);
-}
-
-static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
-               int min_uV, int max_uV)
-{
-       int ret, voltage;
-
-       if (min_uV == 0)
-               return 0;
-
-       if (min_uV < 900000)
-               min_uV = 900000;
-       ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1;
-
-       /* Map back into a voltage to verify we're still in bounds */
-       voltage = palmas_list_voltage_ldo(rdev, ret);
-       if (voltage < min_uV || voltage > max_uV)
-               return -EINVAL;
-
-       return ret;
-}
-
 static struct regulator_ops palmas_ops_ldo = {
        .is_enabled             = palmas_is_enabled_ldo,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .list_voltage           = palmas_list_voltage_ldo,
-       .map_voltage            = palmas_map_voltage_ldo,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
 };
 
 /*
@@ -595,7 +519,7 @@ static struct of_regulator_match palmas_matches[] = {
        { .name = "ldousb", },
 };
 
-static void __devinit palmas_dt_to_pdata(struct device *dev,
+static void palmas_dt_to_pdata(struct device *dev,
                struct device_node *node,
                struct palmas_pmic_platform_data *pdata)
 {
@@ -663,7 +587,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
 }
 
 
-static __devinit int palmas_probe(struct platform_device *pdev)
+static int palmas_probe(struct platform_device *pdev)
 {
        struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
        struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
@@ -733,6 +657,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                continue;
                }
 
+               /* Initialise sleep/init values from platform data */
+               if (pdata && pdata->reg_init[id]) {
+                       reg_init = pdata->reg_init[id];
+                       ret = palmas_smps_init(palmas, id, reg_init);
+                       if (ret)
+                               goto err_unregister_regulator;
+               }
+
                /* Register the regulators */
                pmic->desc[id].name = palmas_regs_info[id].name;
                pmic->desc[id].id = id;
@@ -753,29 +685,11 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                        pmic->desc[id].uV_step = 1250000;
                        break;
                default:
-                       pmic->desc[id].ops = &palmas_ops_smps;
-                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
-               }
-
-               pmic->desc[id].type = REGULATOR_VOLTAGE;
-               pmic->desc[id].owner = THIS_MODULE;
-
-               /* Initialise sleep/init values from platform data */
-               if (pdata) {
-                       reg_init = pdata->reg_init[id];
-                       if (reg_init) {
-                               ret = palmas_smps_init(palmas, id, reg_init);
-                               if (ret)
-                                       goto err_unregister_regulator;
-                       }
-               }
-
-               /*
-                * read and store the RANGE bit for later use
-                * This must be done before regulator is probed otherwise
-                * we error in probe with unsuportable ranges.
-                */
-               if (id != PALMAS_REG_SMPS10) {
+                       /*
+                        * Read and store the RANGE bit for later use
+                        * This must be done before regulator is probed,
+                        * otherwise we error in probe with unsupportable ranges.
+                        */
                        addr = palmas_regs_info[id].vsel_addr;
 
                        ret = palmas_smps_read(pmic->palmas, addr, &reg);
@@ -783,8 +697,19 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                goto err_unregister_regulator;
                        if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
                                pmic->range[id] = 1;
+
+                       pmic->desc[id].ops = &palmas_ops_smps;
+                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+                       pmic->desc[id].vsel_reg =
+                                       PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+                                               palmas_regs_info[id].vsel_addr);
+                       pmic->desc[id].vsel_mask =
+                                       PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
                }
 
+               pmic->desc[id].type = REGULATOR_VOLTAGE;
+               pmic->desc[id].owner = THIS_MODULE;
+
                if (pdata)
                        config.init_data = pdata->reg_data[id];
                else
@@ -821,6 +746,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 
                pmic->desc[id].type = REGULATOR_VOLTAGE;
                pmic->desc[id].owner = THIS_MODULE;
+               pmic->desc[id].min_uV = 900000;
+               pmic->desc[id].uV_step = 50000;
+               pmic->desc[id].linear_min_sel = 1;
                pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
                                                palmas_regs_info[id].vsel_addr);
                pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
@@ -868,7 +796,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static int __devexit palmas_remove(struct platform_device *pdev)
+static int palmas_remove(struct platform_device *pdev)
 {
        struct palmas_pmic *pmic = platform_get_drvdata(pdev);
        int id;
@@ -890,7 +818,7 @@ static struct platform_driver palmas_driver = {
                .owner = THIS_MODULE,
        },
        .probe = palmas_probe,
-       .remove = __devexit_p(palmas_remove),
+       .remove = palmas_remove,
 };
 
 static int __init palmas_init(void)
index 68777acc099fb6da2d0d4f1428b11ef1d704f9a3..4899342f1fc12cba02790a094c4be82f5ec30b15 100644 (file)
@@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
        VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
 };
 
-static int __devinit pcap_regulator_probe(struct platform_device *pdev)
+static int pcap_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_dev *rdev;
        void *pcap = dev_get_drvdata(pdev->dev.parent);
@@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcap_regulator_remove(struct platform_device *pdev)
+static int pcap_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = pcap_regulator_probe,
-       .remove = __devexit_p(pcap_regulator_remove),
+       .remove = pcap_regulator_remove,
 };
 
 static int __init pcap_regulator_init(void)
index 092e5cb848a1e3b0e30736bf6fe08823220f77aa..534075e13d6dba59e5f21b4db91fb3b0d9acdb25 100644 (file)
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/pmic.h>
 
-#define PCF50633_REGULATOR(_name, _id, _n)                     \
+#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
        {                                                       \
                .name = _name,                                  \
                .id = PCF50633_REGULATOR_##_id,                 \
                .ops = &pcf50633_regulator_ops,                 \
                .n_voltages = _n,                               \
+               .min_uV = _min_uV,                              \
+               .uV_step = _uV_step,                            \
+               .linear_min_sel = _min_sel,                     \
                .type = REGULATOR_VOLTAGE,                      \
                .owner = THIS_MODULE,                           \
                .vsel_reg = PCF50633_REG_##_id##OUT,            \
                .enable_mask = PCF50633_REGULATOR_ON,           \
        }
 
-/* Bits from voltage value */
-static u8 auto_voltage_bits(unsigned int millivolts)
-{
-       if (millivolts < 1800)
-               return 0x2f;
-       if (millivolts > 3800)
-               return 0xff;
-
-       millivolts -= 625;
-
-       return millivolts / 25;
-}
-
-static u8 down_voltage_bits(unsigned int millivolts)
-{
-       if (millivolts < 625)
-               return 0;
-       else if (millivolts > 3000)
-               return 0xff;
-
-       millivolts -= 625;
-
-       return millivolts / 25;
-}
-
-static u8 ldo_voltage_bits(unsigned int millivolts)
-{
-       if (millivolts < 900)
-               return 0;
-       else if (millivolts > 3600)
-               return 0x1f;
-
-       millivolts -= 900;
-       return millivolts / 100;
-}
-
-/* Obtain voltage value from bits */
-static unsigned int auto_voltage_value(u8 bits)
-{
-       /* AUTOOUT: 00000000 to 00101110 are reserved.
-        * Return 0 for bits in reserved range, which means this selector code
-        * can't be used on this system */
-       if (bits < 0x2f)
-               return 0;
-
-       return 625 + (bits * 25);
-}
-
-
-static unsigned int down_voltage_value(u8 bits)
-{
-       return 625 + (bits * 25);
-}
-
-
-static unsigned int ldo_voltage_value(u8 bits)
-{
-       bits &= 0x1f;
-
-       return 900 + (bits * 100);
-}
-
-static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
-                                         int min_uV, int max_uV)
-{
-       struct pcf50633 *pcf;
-       int regulator_id, millivolts;
-       u8 volt_bits;
-
-       pcf = rdev_get_drvdata(rdev);
-
-       regulator_id = rdev_get_id(rdev);
-       if (regulator_id >= PCF50633_NUM_REGULATORS)
-               return -EINVAL;
-
-       millivolts = min_uV / 1000;
-
-       switch (regulator_id) {
-       case PCF50633_REGULATOR_AUTO:
-               volt_bits = auto_voltage_bits(millivolts);
-               break;
-       case PCF50633_REGULATOR_DOWN1:
-       case PCF50633_REGULATOR_DOWN2:
-               volt_bits = down_voltage_bits(millivolts);
-               break;
-       case PCF50633_REGULATOR_LDO1:
-       case PCF50633_REGULATOR_LDO2:
-       case PCF50633_REGULATOR_LDO3:
-       case PCF50633_REGULATOR_LDO4:
-       case PCF50633_REGULATOR_LDO5:
-       case PCF50633_REGULATOR_LDO6:
-       case PCF50633_REGULATOR_HCLDO:
-       case PCF50633_REGULATOR_MEMLDO:
-               volt_bits = ldo_voltage_bits(millivolts);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return volt_bits;
-}
-
-static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
-                                               unsigned int index)
-{
-       int regulator_id = rdev_get_id(rdev);
-
-       int millivolts;
-
-       switch (regulator_id) {
-       case PCF50633_REGULATOR_AUTO:
-               millivolts = auto_voltage_value(index);
-               break;
-       case PCF50633_REGULATOR_DOWN1:
-       case PCF50633_REGULATOR_DOWN2:
-               millivolts = down_voltage_value(index);
-               break;
-       case PCF50633_REGULATOR_LDO1:
-       case PCF50633_REGULATOR_LDO2:
-       case PCF50633_REGULATOR_LDO3:
-       case PCF50633_REGULATOR_LDO4:
-       case PCF50633_REGULATOR_LDO5:
-       case PCF50633_REGULATOR_LDO6:
-       case PCF50633_REGULATOR_HCLDO:
-       case PCF50633_REGULATOR_MEMLDO:
-               millivolts = ldo_voltage_value(index);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return millivolts * 1000;
-}
-
 static struct regulator_ops pcf50633_regulator_ops = {
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .list_voltage = pcf50633_regulator_list_voltage,
-       .map_voltage = pcf50633_regulator_map_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
        .is_enabled = regulator_is_enabled_regmap,
 };
 
 static const struct regulator_desc regulators[] = {
-       [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128),
-       [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96),
-       [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96),
-       [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28),
-       [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28),
-       [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28),
-       [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28),
-       [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28),
-       [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28),
-       [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28),
-       [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
+       [PCF50633_REGULATOR_AUTO] =
+               PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
+       [PCF50633_REGULATOR_DOWN1] =
+               PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
+       [PCF50633_REGULATOR_DOWN2] =
+               PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
+       [PCF50633_REGULATOR_LDO1] =
+               PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO2] =
+               PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO3] =
+               PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO4] =
+               PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO5] =
+               PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO6] =
+               PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_HCLDO] =
+               PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_MEMLDO] =
+               PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
 };
 
-static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+static int pcf50633_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_dev *rdev;
        struct pcf50633 *pcf;
@@ -222,7 +102,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+static int pcf50633_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -237,7 +117,7 @@ static struct platform_driver pcf50633_regulator_driver = {
                .name = "pcf50633-regltr",
        },
        .probe = pcf50633_regulator_probe,
-       .remove = __devexit_p(pcf50633_regulator_remove),
+       .remove = pcf50633_regulator_remove,
 };
 
 static int __init pcf50633_regulator_init(void)
index 8bf4e8c9de9a2a811622ff0e8986a8fea9de2735..9e6f78694bf16d66d13e9ea95e160ed631603742 100644 (file)
@@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
        RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
 };
 
-static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+static int rc5t583_regulator_probe(struct platform_device *pdev)
 {
        struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
        struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -198,7 +198,7 @@ clean_exit:
        return ret;
 }
 
-static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+static int rc5t583_regulator_remove(struct platform_device *pdev)
 {
        struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
        int id;
@@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = rc5t583_regulator_probe,
-       .remove         = __devexit_p(rc5t583_regulator_remove),
+       .remove         = rc5t583_regulator_remove,
 };
 
 static int __init rc5t583_regulator_init(void)
index 926f9c8f2facde5b415b0e4bdc71b5fd2dc53fe6..bd062a2ffbe235cb9e4c4636b59b8676738676e8 100644 (file)
@@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
        regulator_desc_buck10,
 };
 
-static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
+static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
 
        if (ramp_enable) {
                if (s2mps11->buck2_ramp)
-                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
                if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
-                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
                sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
        }
 
        ramp_reg &= 0x00;
-       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
-       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
-       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
        ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
        sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
 
@@ -307,7 +307,7 @@ err:
        return ret;
 }
 
-static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+static int s2mps11_pmic_remove(struct platform_device *pdev)
 {
        struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
        int i;
@@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s2mps11_pmic_probe,
-       .remove = __devexit_p(s2mps11_pmic_remove),
+       .remove = s2mps11_pmic_remove,
        .id_table = s2mps11_pmic_id,
 };
 
index abe64a32aedf3a4b38ee05ea7c59849b4959642c..9f991f2c525af531ec0b5450523bb2e0e75a5b54 100644 (file)
@@ -168,7 +168,7 @@ static unsigned int s5m8767_opmode_reg[][4] = {
 static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
                                int *enable_ctrl)
 {
-       int reg_id = rdev_get_id(rdev);
+       int i, reg_id = rdev_get_id(rdev);
        unsigned int mode;
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
 
@@ -195,8 +195,17 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
                return -EINVAL;
        }
 
-       mode = s5m8767->opmode[reg_id].mode;
-       *enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
+       for (i = 0; i < s5m8767->num_regulators; i++) {
+               if (s5m8767->opmode[i].id == reg_id) {
+                       mode = s5m8767->opmode[i].mode;
+                       break;
+               }
+       }
+
+       if (i < s5m8767->num_regulators)
+               *enable_ctrl =
+               s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
+
        return 0;
 }
 
@@ -263,17 +272,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
                reg = S5M8767_REG_BUCK1CTRL2;
                break;
        case S5M8767_BUCK2:
-               reg = S5M8767_REG_BUCK2DVS2;
+               reg = S5M8767_REG_BUCK2DVS1;
                if (s5m8767->buck2_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK3:
-               reg = S5M8767_REG_BUCK3DVS2;
+               reg = S5M8767_REG_BUCK3DVS1;
                if (s5m8767->buck3_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK4:
-               reg = S5M8767_REG_BUCK4DVS2;
+               reg = S5M8767_REG_BUCK4DVS1;
                if (s5m8767->buck4_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
@@ -499,7 +508,7 @@ static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(BUCK9),
 };
 
-static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
+static int s5m8767_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -547,7 +556,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        rdev = s5m8767->rdev;
        s5m8767->dev = &pdev->dev;
        s5m8767->iodev = iodev;
-       s5m8767->num_regulators = S5M8767_REG_MAX - 2;
+       s5m8767->num_regulators = pdata->num_regulators;
        platform_set_drvdata(pdev, s5m8767);
 
        s5m8767->buck_gpioindex = pdata->buck_default_idx;
@@ -617,9 +626,16 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                }
        }
 
-       if (gpio_is_valid(pdata->buck_gpios[0]) &&
-               gpio_is_valid(pdata->buck_gpios[1]) &&
-               gpio_is_valid(pdata->buck_gpios[2])) {
+       if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
+                                               pdata->buck4_gpiodvs) {
+
+               if (!gpio_is_valid(pdata->buck_gpios[0]) ||
+                       !gpio_is_valid(pdata->buck_gpios[1]) ||
+                       !gpio_is_valid(pdata->buck_gpios[2])) {
+                       dev_err(&pdev->dev, "GPIO NOT VALID\n");
+                       return -EINVAL;
+               }
+
                ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
                                        "S5M8767 SET1");
                if (ret)
@@ -644,10 +660,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                /* SET3 GPIO */
                gpio_direction_output(pdata->buck_gpios[2],
                                (s5m8767->buck_gpioindex >> 0) & 0x1);
-       } else {
-               dev_err(&pdev->dev, "GPIO NOT VALID\n");
-               ret = -EINVAL;
-               return ret;
        }
 
        ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
@@ -773,7 +785,7 @@ err:
        return ret;
 }
 
-static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
+static int s5m8767_pmic_remove(struct platform_device *pdev)
 {
        struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = s5m8767->rdev;
@@ -798,7 +810,7 @@ static struct platform_driver s5m8767_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s5m8767_pmic_probe,
-       .remove = __devexit_p(s5m8767_pmic_remove),
+       .remove = s5m8767_pmic_remove,
        .id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644 (file)
index 0000000..ab21133
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * tps51632-regulator.c -- TI TPS51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG            0x0
+#define TPS51632_VOLTAGE_BASE_REG              0x1
+#define TPS51632_OFFSET_REG                    0x2
+#define TPS51632_IMON_REG                      0x3
+#define TPS51632_VMAX_REG                      0x4
+#define TPS51632_DVFS_CONTROL_REG              0x5
+#define TPS51632_POWER_STATE_REG               0x6
+#define TPS51632_SLEW_REGS                     0x7
+#define TPS51632_FAULT_REG                     0x14
+
+#define TPS51632_MAX_REG                       0x15
+
+#define TPS51632_VOUT_MASK                     0x7F
+#define TPS51632_VOUT_OFFSET_MASK              0x1F
+#define TPS51632_VMAX_MASK                     0x7F
+#define TPS51632_VMAX_LOCK                     0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN                    0x1
+#define TPS51632_DVFS_STEP_20                  0x2
+#define TPS51632_DVFS_VMAX_PG                  0x4
+#define TPS51632_DVFS_PWMRST                   0x8
+#define TPS51632_DVFS_OCA_EN                   0x10
+#define TPS51632_DVFS_FCCM                     0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK              0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM   0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM  0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM  0x2
+
+#define TPS51632_MIN_VOLATGE                   500000
+#define TPS51632_MAX_VOLATGE                   1520000
+#define TPS51632_VOLATGE_STEP_10mV             10000
+#define TPS51632_VOLATGE_STEP_20mV             20000
+#define TPS51632_MAX_VSEL                      0x7F
+#define TPS51632_MIN_VSEL                      0x19
+#define TPS51632_DEFAULT_RAMP_DELAY            6000
+#define TPS51632_VOLT_VSEL(uV)                                 \
+               (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE,        \
+                       TPS51632_VOLATGE_STEP_10mV) +           \
+                       TPS51632_MIN_VSEL)
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+       struct device *dev;
+       struct regulator_desc desc;
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       bool enable_pwm_dvfs;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+       int vsel;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       ret = regmap_read(tps->regmap, reg, &data);
+       if (ret < 0) {
+               dev_err(tps->dev, "reg read failed, err %d\n", ret);
+               return ret;
+       }
+
+       vsel = data & TPS51632_VOUT_MASK;
+       return vsel;
+}
+
+static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned selector)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       if (selector > TPS51632_MAX_VSEL)
+               return -EINVAL;
+
+       ret = regmap_write(tps->regmap, reg, selector);
+       if (ret < 0)
+               dev_err(tps->dev, "reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
+               int ramp_delay)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int bit = ramp_delay/6000;
+       int ret;
+
+       if (bit)
+               bit--;
+       ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
+       if (ret < 0)
+               dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+       .get_voltage_sel        = tps51632_dcdc_get_voltage_sel,
+       .set_voltage_sel        = tps51632_dcdc_set_voltage_sel,
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = tps51632_dcdc_set_ramp_delay,
+};
+
+static int tps51632_init_dcdc(struct tps51632_chip *tps,
+               struct tps51632_regulator_platform_data *pdata)
+{
+       int ret;
+       uint8_t control = 0;
+       int vsel;
+
+       if (!pdata->enable_pwm_dvfs)
+               goto skip_pwm_config;
+
+       control |= TPS51632_DVFS_PWMEN;
+       tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
+       vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
+       ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
+       if (ret < 0) {
+               dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
+               return ret;
+       }
+
+       if (pdata->dvfs_step_20mV)
+               control |= TPS51632_DVFS_STEP_20;
+
+       if (pdata->max_voltage_uV) {
+               unsigned int vmax;
+               /**
+                * TPS51632 hw behavior: VMAX register can be write only
+                * once as it get locked after first write. The lock get
+                * reset only when device is power-reset.
+                * Write register only when lock bit is not enabled.
+                */
+               ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
+               if (ret < 0) {
+                       dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
+                       return ret;
+               }
+               if (!(vmax & TPS51632_VMAX_LOCK)) {
+                       vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
+                       ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
+                                       vsel);
+                       if (ret < 0) {
+                               dev_err(tps->dev,
+                                       "VMAX write failed, err %d\n", ret);
+                               return ret;
+                       }
+               }
+       }
+
+skip_pwm_config:
+       ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+       if (ret < 0)
+               dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static bool rd_wr_reg(struct device *dev, unsigned int reg)
+{
+       if ((reg >= 0x8) && (reg <= 0x10))
+               return false;
+       return true;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .writeable_reg          = rd_wr_reg,
+       .readable_reg           = rd_wr_reg,
+       .max_register           = TPS51632_MAX_REG - 1,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int tps51632_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct tps51632_regulator_platform_data *pdata;
+       struct regulator_dev *rdev;
+       struct tps51632_chip *tps;
+       int ret;
+       struct regulator_config config = { };
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->dev, "No Platform data\n");
+               return -EINVAL;
+       }
+
+       if (pdata->enable_pwm_dvfs) {
+               if ((pdata->base_voltage_uV < TPS51632_MIN_VOLATGE) ||
+                   (pdata->base_voltage_uV > TPS51632_MAX_VOLATGE)) {
+                       dev_err(&client->dev, "Invalid base_voltage_uV setting\n");
+                       return -EINVAL;
+               }
+
+               if ((pdata->max_voltage_uV) &&
+                   ((pdata->max_voltage_uV < TPS51632_MIN_VOLATGE) ||
+                    (pdata->max_voltage_uV > TPS51632_MAX_VOLATGE))) {
+                       dev_err(&client->dev, "Invalid max_voltage_uV setting\n");
+                       return -EINVAL;
+               }
+       }
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps) {
+               dev_err(&client->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       tps->dev = &client->dev;
+       tps->desc.name = id->name;
+       tps->desc.id = 0;
+       tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+       tps->desc.min_uV = TPS51632_MIN_VOLATGE;
+       tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
+       tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
+       tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
+       tps->desc.ops = &tps51632_dcdc_ops;
+       tps->desc.type = REGULATOR_VOLTAGE;
+       tps->desc.owner = THIS_MODULE;
+
+       tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+               return ret;
+       }
+       i2c_set_clientdata(client, tps);
+
+       ret = tps51632_init_dcdc(tps, pdata);
+       if (ret < 0) {
+               dev_err(tps->dev, "Init failed, err = %d\n", ret);
+               return ret;
+       }
+
+       /* Register the regulators */
+       config.dev = &client->dev;
+       config.init_data = pdata->reg_init_data;
+       config.driver_data = tps;
+       config.regmap = tps->regmap;
+       config.of_node = client->dev.of_node;
+
+       rdev = regulator_register(&tps->desc, &config);
+       if (IS_ERR(rdev)) {
+               dev_err(tps->dev, "regulator register failed\n");
+               return PTR_ERR(rdev);
+       }
+
+       tps->rdev = rdev;
+       return 0;
+}
+
+static int tps51632_remove(struct i2c_client *client)
+{
+       struct tps51632_chip *tps = i2c_get_clientdata(client);
+
+       regulator_unregister(tps->rdev);
+       return 0;
+}
+
+static const struct i2c_device_id tps51632_id[] = {
+       {.name = "tps51632",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+       .driver = {
+               .name = "tps51632",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps51632_probe,
+       .remove = tps51632_remove,
+       .id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+       return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+       i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
index 1378409efaec70170b8a3c70eeb09e1402abec33..ec9453ffb77fd561ec1c2d6c3591b7302bc16b5f 100644 (file)
@@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
 /*
  * Registers the chip as a voltage regulator
  */
-static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
+static int tps6105x_regulator_probe(struct platform_device *pdev)
 {
        struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
        struct tps6105x_platform_data *pdata = tps6105x->pdata;
@@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
+static int tps6105x_regulator_remove(struct platform_device *pdev)
 {
        struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
        regulator_unregister(tps6105x->regulator);
@@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6105x_regulator_probe,
-       .remove = __devexit_p(tps6105x_regulator_remove),
+       .remove = tps6105x_regulator_remove,
 };
 
 static __init int tps6105x_regulator_init(void)
index 68729a7c8709fbcbc8e88e8cf99924afc2e69f18..acbd63fde4153fb7ffe9cf3a8b22dd25aad43383 100644 (file)
@@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
        .get_mode               = tps62360_get_mode,
 };
 
-static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
+static int tps62360_init_dcdc(struct tps62360_chip *tps,
                struct tps62360_regulator_platform_data *pdata)
 {
        int ret;
@@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
 MODULE_DEVICE_TABLE(of, tps62360_of_match);
 #endif
 
-static int __devinit tps62360_probe(struct i2c_client *client,
+static int tps62360_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        struct regulator_config config = { };
@@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
  *
  * Unregister TPS driver as an i2c client device driver
  */
-static int __devexit tps62360_remove(struct i2c_client *client)
+static int tps62360_remove(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
 
@@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
                .of_match_table = of_match_ptr(tps62360_of_match),
        },
        .probe = tps62360_probe,
-       .remove = __devexit_p(tps62360_remove),
+       .remove = tps62360_remove,
        .shutdown = tps62360_shutdown,
        .id_table = tps62360_id,
 };
index 6998d579d07b424891a79d09e62406a6b7e38d74..9b9af6d889c83214b06e9aa6b54767ede61289b1 100644 (file)
@@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit tps_65023_probe(struct i2c_client *client,
+static int tps_65023_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        const struct tps_driver_data *drv_data = (void *)id->driver_data;
@@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
        return error;
 }
 
-static int __devexit tps_65023_remove(struct i2c_client *client)
+static int tps_65023_remove(struct i2c_client *client)
 {
        struct tps_pmic *tps = i2c_get_clientdata(client);
        int i;
@@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps_65023_probe,
-       .remove = __devexit_p(tps_65023_remove),
+       .remove = tps_65023_remove,
        .id_table = tps_65023_id,
 };
 
index 07d01ccdf308fdf2a6871ce60f6d60f380d4060c..0233cfb5656058a57ccd0dce40591701c16ce8b6 100644 (file)
@@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
        .list_voltage = regulator_list_voltage_table,
 };
 
-static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
+static int tps6507x_pmic_probe(struct platform_device *pdev)
 {
        struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
        struct tps_info *info = &tps6507x_pmic_regs[0];
@@ -439,7 +439,7 @@ fail:
        return error;
 }
 
-static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
+static int tps6507x_pmic_remove(struct platform_device *pdev)
 {
        struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
        struct tps6507x_pmic *tps = tps6507x_dev->pmic;
@@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6507x_pmic_probe,
-       .remove = __devexit_p(tps6507x_pmic_remove),
+       .remove = tps6507x_pmic_remove,
 };
 
 static int __init tps6507x_pmic_init(void)
index 001ad554ac62634c6a77897ffc9a92cf641c2abf..41c391789c9790a59678dc1232bf0938e978a47e 100644 (file)
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65090.h>
-#include <linux/regulator/tps65090-regulator.h>
 
 struct tps65090_regulator {
-       int             id;
-       /* used by regulator core */
-       struct regulator_desc   desc;
-
-       /* Device */
        struct device           *dev;
+       struct regulator_desc   *desc;
+       struct regulator_dev    *rdev;
+};
+
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+       .enable         = regulator_enable_regmap,
+       .disable        = regulator_disable_regmap,
+       .is_enabled     = regulator_is_enabled_regmap,
 };
 
-static struct regulator_ops tps65090_ops = {
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ldo_ops = {
 };
 
-#define tps65090_REG(_id)                              \
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops)  \
 {                                                      \
-       .id             = TPS65090_ID_##_id,            \
-       .desc = {                                       \
-               .name = tps65090_rails(_id),            \
-               .id = TPS65090_ID_##_id,                \
-               .ops = &tps65090_ops,                   \
-               .type = REGULATOR_VOLTAGE,              \
-               .owner = THIS_MODULE,                   \
-               .enable_reg = (TPS65090_ID_##_id) + 12, \
-               .enable_mask = BIT(0),                  \
-       },                                              \
+       .name = "TPS65090_RAILS"#_id,                   \
+       .supply_name = _sname,                          \
+       .id = TPS65090_REGULATOR_##_id,                 \
+       .ops = &_ops,                                   \
+       .enable_reg = _en_reg,                          \
+       .enable_mask = BIT(0),                          \
+       .type = REGULATOR_VOLTAGE,                      \
+       .owner = THIS_MODULE,                           \
 }
 
-static struct tps65090_regulator TPS65090_regulator[] = {
-       tps65090_REG(DCDC1),
-       tps65090_REG(DCDC2),
-       tps65090_REG(DCDC3),
-       tps65090_REG(FET1),
-       tps65090_REG(FET2),
-       tps65090_REG(FET3),
-       tps65090_REG(FET4),
-       tps65090_REG(FET5),
-       tps65090_REG(FET6),
-       tps65090_REG(FET7),
+static struct regulator_desc tps65090_regulator_desc[] = {
+       tps65090_REG_DESC(DCDC1, "vsys1",   0x0C, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC2, "vsys2",   0x0D, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC3, "vsys3",   0x0E, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET1,  "infet1",  0x0F, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET2,  "infet2",  0x10, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET3,  "infet3",  0x11, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET4,  "infet4",  0x12, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET5,  "infet5",  0x13, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET6,  "infet6",  0x14, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET7,  "infet7",  0x15, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(LDO1,  "vsys_l1", 0,    tps65090_ldo_ops),
+       tps65090_REG_DESC(LDO2,  "vsys_l2", 0,    tps65090_ldo_ops),
 };
 
-static inline struct tps65090_regulator *find_regulator_info(int id)
+static inline bool is_dcdc(int id)
 {
-       struct tps65090_regulator *ri;
-       int i;
+       switch (id) {
+       case TPS65090_REGULATOR_DCDC1:
+       case TPS65090_REGULATOR_DCDC2:
+       case TPS65090_REGULATOR_DCDC3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int tps65090_config_ext_control(
+       struct tps65090_regulator *ri, bool enable)
+{
+       int ret;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       if (enable)
+               ret = tps65090_set_bits(parent, reg_en_reg, 1);
+       else
+               ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
+       return ret;
+}
+
+static int tps65090_regulator_disable_ext_control(
+               struct tps65090_regulator *ri,
+               struct tps65090_regulator_plat_data *tps_pdata)
+{
+       int ret = 0;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       /*
+        * First enable output for internal control if require.
+        * And then disable external control.
+        */
+       if (tps_pdata->reg_init_data->constraints.always_on ||
+                       tps_pdata->reg_init_data->constraints.boot_on) {
+               ret =  tps65090_set_bits(parent, reg_en_reg, 0);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
+                       return ret;
+               }
+       }
+       return tps65090_config_ext_control(ri, false);
+}
+
+static void tps65090_configure_regulator_config(
+               struct tps65090_regulator_plat_data *tps_pdata,
+               struct regulator_config *config)
+{
+       if (gpio_is_valid(tps_pdata->gpio)) {
+               int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+               if (tps_pdata->reg_init_data->constraints.always_on ||
+                               tps_pdata->reg_init_data->constraints.boot_on)
+                       gpio_flag = GPIOF_OUT_INIT_HIGH;
 
-       for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
-               ri = &TPS65090_regulator[i];
-               if (ri->desc.id == id)
-                       return ri;
+               config->ena_gpio = tps_pdata->gpio;
+               config->ena_gpio_flags = gpio_flag;
        }
-       return NULL;
 }
 
-static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
+static int tps65090_regulator_probe(struct platform_device *pdev)
 {
        struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
        struct tps65090_regulator *ri = NULL;
        struct regulator_config config = { };
        struct regulator_dev *rdev;
-       struct tps65090_regulator_platform_data *tps_pdata;
-       int id = pdev->id;
+       struct tps65090_regulator_plat_data *tps_pdata;
+       struct tps65090_regulator *pmic;
+       struct tps65090_platform_data *tps65090_pdata;
+       int num;
+       int ret;
 
-       dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+       dev_dbg(&pdev->dev, "Probing regulator\n");
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+       if (!tps65090_pdata) {
+               dev_err(&pdev->dev, "Platform data missing\n");
                return -EINVAL;
        }
-       tps_pdata = pdev->dev.platform_data;
-       ri->dev = &pdev->dev;
-
-       config.dev = &pdev->dev;
-       config.init_data = &tps_pdata->regulator;
-       config.driver_data = ri;
-       config.regmap = tps65090_mfd->rmap;
-
-       rdev = regulator_register(&ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+
+       pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
+                       GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
+               tps_pdata = tps65090_pdata->reg_pdata[num];
+
+               ri = &pmic[num];
+               ri->dev = &pdev->dev;
+               ri->desc = &tps65090_regulator_desc[num];
+
+               /*
+                * TPS5090 DCDC support the control from external digital input.
+                * Configure it as per platform data.
+                */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
+                       if (tps_pdata->enable_ext_control) {
+                               tps65090_configure_regulator_config(
+                                               tps_pdata, &config);
+                               ri->desc->ops = &tps65090_ext_control_ops;
+                       } else {
+                               ret = tps65090_regulator_disable_ext_control(
+                                               ri, tps_pdata);
+                               if (ret < 0) {
+                                       dev_err(&pdev->dev,
+                                               "failed disable ext control\n");
+                                       goto scrub;
+                               }
+                       }
+               }
+
+               config.dev = &pdev->dev;
+               config.driver_data = ri;
+               config.regmap = tps65090_mfd->rmap;
+               if (tps_pdata)
+                       config.init_data = tps_pdata->reg_init_data;
+               else
+                       config.init_data = NULL;
+
+               rdev = regulator_register(ri->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               ri->desc->name);
+                       ret = PTR_ERR(rdev);
+                       goto scrub;
+               }
+               ri->rdev = rdev;
+
+               /* Enable external control if it is require */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
+                               tps_pdata->enable_ext_control) {
+                       ret = tps65090_config_ext_control(ri, true);
+                       if (ret < 0) {
+                               /* Increment num to get unregister rdev */
+                               num++;
+                               goto scrub;
+                       }
+               }
        }
 
-       platform_set_drvdata(pdev, rdev);
+       platform_set_drvdata(pdev, pmic);
        return 0;
+
+scrub:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
 }
 
-static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
+static int tps65090_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps65090_regulator *ri;
+       int num;
 
-       regulator_unregister(rdev);
+       for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
        return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
        .driver = {
-               .name   = "tps65090-regulator",
+               .name   = "tps65090-pmic",
                .owner  = THIS_MODULE,
        },
        .probe          = tps65090_regulator_probe,
-       .remove         = __devexit_p(tps65090_regulator_remove),
+       .remove         = tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
@@ -148,3 +269,4 @@ module_exit(tps65090_regulator_exit);
 MODULE_DESCRIPTION("tps65090 regulator driver");
 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65090-pmic");
index ab00cab905b730459c6e752907f1139aaec9ee57..73dce76641265590179cb2440e75ad71ffd722d0 100644 (file)
@@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
 }
 #endif
 
-static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
+static int tps65217_regulator_probe(struct platform_device *pdev)
 {
        struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
        struct tps65217_board *pdata = dev_get_platdata(tps->dev);
@@ -397,7 +397,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
+static int tps65217_regulator_remove(struct platform_device *pdev)
 {
        struct tps65217 *tps = platform_get_drvdata(pdev);
        unsigned int i;
@@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
                .name = "tps65217-pmic",
        },
        .probe = tps65217_regulator_probe,
-       .remove = __devexit_p(tps65217_regulator_remove),
+       .remove = tps65217_regulator_remove,
 };
 
 static int __init tps65217_regulator_init(void)
index 058d2f2675e902c8d2856b83b3ee5a6b4c7c5503..843ee0a9bb92ce2a23e7a2209590b99cfa13e76c 100644 (file)
@@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
        return 0;
 }
 
-static int __devinit pmic_probe(struct spi_device *spi)
+static int pmic_probe(struct spi_device *spi)
 {
        struct tps6524x *hw;
        struct device *dev = &spi->dev;
@@ -649,7 +649,7 @@ fail:
 
 static struct spi_driver pmic_driver = {
        .probe          = pmic_probe,
-       .remove         = __devexit_p(pmic_remove),
+       .remove         = pmic_remove,
        .driver         = {
                .name   = "tps6524x",
                .owner  = THIS_MODULE,
index ce1e7cb8d513f13a8463a84b2de39d1a61cb180c..f86da672c758b4ab1070facacdf291cabc482c66 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/mfd/tps6586x.h>
 
 /* supply control and voltage setting  */
@@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
                                 1 << ri->enable_bit[1]);
 }
 
-static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
+static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
+                       int id, struct regulator_init_data *p)
 {
        struct device *parent = pdev->dev.parent;
-       struct regulator_init_data *p = pdev->dev.platform_data;
        struct tps6586x_settings *setting = p->driver_data;
        uint8_t reg;
 
@@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
                return 0;
 
        /* only SM0 and SM1 can have the slew rate settings */
-       switch (pdev->id) {
+       switch (id) {
        case TPS6586X_ID_SM_0:
                reg = TPS6586X_SM0SL;
                break;
@@ -298,58 +300,185 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
        return NULL;
 }
 
-static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct of_regulator_match tps6586x_matches[] = {
+       { .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
+       { .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
+       { .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
+       { .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
+       { .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
+       { .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
+       { .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
+       { .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
+       { .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
+       { .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
+       { .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
+       { .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
+       { .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
+       { .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
+       { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
+};
+
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+               struct platform_device *pdev,
+               struct of_regulator_match **tps6586x_reg_matches)
+{
+       const unsigned int num = ARRAY_SIZE(tps6586x_matches);
+       struct device_node *np = pdev->dev.parent->of_node;
+       struct device_node *regs;
+       const char *sys_rail = NULL;
+       unsigned int i;
+       struct tps6586x_platform_data *pdata;
+       int err;
+
+       regs = of_find_node_by_name(np, "regulators");
+       if (!regs) {
+               dev_err(&pdev->dev, "regulator node not found\n");
+               return NULL;
+       }
+
+       err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
+       if (err < 0) {
+               dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
+               of_node_put(regs);
+               return NULL;
+       }
+
+       of_node_put(regs);
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "Memory alloction failed\n");
+               return NULL;
+       }
+
+       for (i = 0; i < num; i++) {
+               int id;
+               if (!tps6586x_matches[i].init_data)
+                       continue;
+
+               pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
+               id = (int)tps6586x_matches[i].driver_data;
+               if (id == TPS6586X_ID_SYS)
+                       sys_rail = pdata->reg_init_data[i]->constraints.name;
+
+               if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
+                       pdata->reg_init_data[i]->supply_regulator = sys_rail;
+       }
+       *tps6586x_reg_matches = tps6586x_matches;
+       return pdata;
+}
+#else
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+               struct platform_device *pdev,
+               struct of_regulator_match **tps6586x_reg_matches)
+{
+       *tps6586x_reg_matches = NULL;
+       return NULL;
+}
+#endif
+
+static int tps6586x_regulator_probe(struct platform_device *pdev)
 {
        struct tps6586x_regulator *ri = NULL;
        struct regulator_config config = { };
-       struct regulator_dev *rdev;
-       int id = pdev->id;
+       struct regulator_dev **rdev;
+       struct regulator_init_data *reg_data;
+       struct tps6586x_platform_data *pdata;
+       struct of_regulator_match *tps6586x_reg_matches = NULL;
+       int id;
        int err;
 
-       dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+       dev_dbg(&pdev->dev, "Probing regulator\n");
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
-               return -EINVAL;
-       }
+       pdata = dev_get_platdata(pdev->dev.parent);
+       if ((!pdata) && (pdev->dev.parent->of_node))
+               pdata = tps6586x_parse_regulator_dt(pdev,
+                                       &tps6586x_reg_matches);
 
-       err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
-       if (err)
-               return err;
+       if (!pdata) {
+               dev_err(&pdev->dev, "Platform data not available, exiting\n");
+               return -ENODEV;
+       }
 
-       config.dev = pdev->dev.parent;
-       config.of_node = pdev->dev.of_node;
-       config.init_data = pdev->dev.platform_data;
-       config.driver_data = ri;
+       rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
+                               sizeof(*rdev), GFP_KERNEL);
+       if (!rdev) {
+               dev_err(&pdev->dev, "Mmemory alloc failed\n");
+               return -ENOMEM;
+       }
 
-       rdev = regulator_register(&ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+       for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
+               reg_data = pdata->reg_init_data[id];
+
+               ri = find_regulator_info(id);
+               if (!ri) {
+                       dev_err(&pdev->dev, "invalid regulator ID specified\n");
+                       err = -EINVAL;
+                       goto fail;
+               }
+
+               err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "regulator %d preinit failed, e %d\n", id, err);
+                       goto fail;
+               }
+
+               config.dev = pdev->dev.parent;
+               config.init_data = reg_data;
+               config.driver_data = ri;
+
+               if (tps6586x_reg_matches)
+                       config.of_node = tps6586x_reg_matches[id].of_node;
+
+               rdev[id] = regulator_register(&ri->desc, &config);
+               if (IS_ERR(rdev[id])) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
+                                       ri->desc.name);
+                       err = PTR_ERR(rdev[id]);
+                       goto fail;
+               }
+
+               if (reg_data) {
+                       err = tps6586x_regulator_set_slew_rate(pdev, id,
+                                       reg_data);
+                       if (err < 0) {
+                               dev_err(&pdev->dev,
+                                       "Slew rate config failed, e %d\n", err);
+                               regulator_unregister(rdev[id]);
+                               goto fail;
+                       }
+               }
        }
 
        platform_set_drvdata(pdev, rdev);
+       return 0;
 
-       return tps6586x_regulator_set_slew_rate(pdev);
+fail:
+       while (--id >= 0)
+               regulator_unregister(rdev[id]);
+       return err;
 }
 
-static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
+static int tps6586x_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct regulator_dev **rdev = platform_get_drvdata(pdev);
+       int id = TPS6586X_ID_MAX_REGULATOR;
+
+       while (--id >= 0)
+               regulator_unregister(rdev[id]);
 
-       regulator_unregister(rdev);
        return 0;
 }
 
 static struct platform_driver tps6586x_regulator_driver = {
        .driver = {
-               .name   = "tps6586x-regulator",
+               .name   = "tps6586x-pmic",
                .owner  = THIS_MODULE,
        },
        .probe          = tps6586x_regulator_probe,
-       .remove         = __devexit_p(tps6586x_regulator_remove),
+       .remove         = tps6586x_regulator_remove,
 };
 
 static int __init tps6586x_regulator_init(void)
index 793adda560c3c3364c2053cdb152974fc2a2f02b..59c3770fa77dbe5b77ae1b3c96c1e105cae8f58e 100644 (file)
@@ -38,6 +38,11 @@ static const unsigned int VIO_VSEL_table[] = {
 
 /* VSEL tables for TPS65910 specific LDOs and dcdc's */
 
+/* supported VRTC voltages in microvolts */
+static const unsigned int VRTC_VSEL_table[] = {
+       1800000,
+};
+
 /* supported VDD3 voltages in microvolts */
 static const unsigned int VDD3_VSEL_table[] = {
        5000000,
@@ -95,6 +100,8 @@ static struct tps_info tps65910_regs[] = {
        {
                .name = "vrtc",
                .vin_name = "vcc7",
+               .n_voltages = ARRAY_SIZE(VRTC_VSEL_table),
+               .voltage_table = VRTC_VSEL_table,
                .enable_time_us = 2200,
        },
        {
@@ -1026,7 +1033,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
 }
 #endif
 
-static __devinit int tps65910_probe(struct platform_device *pdev)
+static int tps65910_probe(struct platform_device *pdev)
 {
        struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -1184,7 +1191,7 @@ err_unregister_regulator:
        return err;
 }
 
-static int __devexit tps65910_remove(struct platform_device *pdev)
+static int tps65910_remove(struct platform_device *pdev)
 {
        struct tps65910_reg *pmic = platform_get_drvdata(pdev);
        int i;
@@ -1231,7 +1238,7 @@ static struct platform_driver tps65910_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65910_probe,
-       .remove = __devexit_p(tps65910_remove),
+       .remove = tps65910_remove,
        .shutdown = tps65910_shutdown,
 };
 
index 18b2a1dcb4b5d6ba189fa74dfe4c8f2d23fbe1d8..17e994e47dc139c3117a8affe76eef64b5e092e1 100644 (file)
@@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
        .list_voltage = tps65912_list_voltage,
 };
 
-static __devinit int tps65912_probe(struct platform_device *pdev)
+static int tps65912_probe(struct platform_device *pdev)
 {
        struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -525,7 +525,7 @@ err:
        return err;
 }
 
-static int __devexit tps65912_remove(struct platform_device *pdev)
+static int tps65912_remove(struct platform_device *pdev)
 {
        struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
        int i;
@@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65912_probe,
-       .remove = __devexit_p(tps65912_remove),
+       .remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
new file mode 100644 (file)
index 0000000..b15d711
--- /dev/null
@@ -0,0 +1,788 @@
+/*
+ * tps80031-regulator.c -- TI TPS80031 regulator driver.
+ *
+ * Regulator driver for TI TPS80031/TPS80032 Fully Integrated Power
+ * Management with Power Path and Battery Charger.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps80031.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+
+/* Flags for DCDC Voltage reading */
+#define DCDC_OFFSET_EN         BIT(0)
+#define DCDC_EXTENDED_EN       BIT(1)
+#define TRACK_MODE_ENABLE      BIT(2)
+
+#define SMPS_MULTOFFSET_VIO    BIT(1)
+#define SMPS_MULTOFFSET_SMPS1  BIT(3)
+#define SMPS_MULTOFFSET_SMPS2  BIT(4)
+#define SMPS_MULTOFFSET_SMPS3  BIT(6)
+#define SMPS_MULTOFFSET_SMPS4  BIT(0)
+
+#define SMPS_CMD_MASK          0xC0
+#define SMPS_VSEL_MASK         0x3F
+#define LDO_VSEL_MASK          0x1F
+#define LDO_TRACK_VSEL_MASK    0x3F
+
+#define MISC2_LDOUSB_IN_VSYS   BIT(4)
+#define MISC2_LDOUSB_IN_PMID   BIT(3)
+#define MISC2_LDOUSB_IN_MASK   0x18
+
+#define MISC2_LDO3_SEL_VIB_VAL BIT(0)
+#define MISC2_LDO3_SEL_VIB_MASK        0x1
+
+#define BOOST_HW_PWR_EN                BIT(5)
+#define BOOST_HW_PWR_EN_MASK   BIT(5)
+
+#define OPA_MODE_EN            BIT(6)
+#define OPA_MODE_EN_MASK       BIT(6)
+
+#define USB_VBUS_CTRL_SET      0x04
+#define USB_VBUS_CTRL_CLR      0x05
+#define VBUS_DISCHRG           0x20
+
+struct tps80031_regulator_info {
+       /* Regulator register address.*/
+       u8              trans_reg;
+       u8              state_reg;
+       u8              force_reg;
+       u8              volt_reg;
+       u8              volt_id;
+
+       /*Power request bits */
+       int             preq_bit;
+
+       /* used by regulator core */
+       struct regulator_desc   desc;
+
+};
+
+struct tps80031_regulator {
+       struct device                   *dev;
+       struct regulator_dev            *rdev;
+       struct tps80031_regulator_info  *rinfo;
+
+       u8                              device_flags;
+       unsigned int                    config_flags;
+       unsigned int                    ext_ctrl_flag;
+};
+
+static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
+{
+       return rdev_get_dev(rdev)->parent->parent;
+}
+
+static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       u8 reg_val;
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return true;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                               &reg_val);
+       if (ret < 0) {
+               dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+               return ret;
+       }
+       return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON);
+}
+
+static int tps80031_reg_enable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return 0;
+
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                       TPS80031_STATE_ON, TPS80031_STATE_MASK);
+       if (ret < 0) {
+               dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int tps80031_reg_disable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return 0;
+
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                       TPS80031_STATE_OFF, TPS80031_STATE_MASK);
+       if (ret < 0)
+               dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+       return ret;
+}
+
+/* DCDC voltages for the selector of 58 to 63 */
+static int tps80031_dcdc_voltages[4][5] = {
+       { 1350, 1500, 1800, 1900, 2100},
+       { 1350, 1500, 1800, 1900, 2100},
+       { 2084, 2315, 2778, 2932, 3241},
+       { 4167, 2315, 2778, 2932, 3241},
+};
+
+static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       int volt_index = ri->device_flags & 0x3;
+
+       if (sel == 0)
+               return 0;
+       else if (sel < 58)
+               return regulator_list_voltage_linear(rdev, sel - 1);
+       else
+               return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000;
+}
+
+static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned vsel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+       u8 reg_val;
+
+       if (ri->rinfo->force_reg) {
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, &reg_val);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                               ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+               if (!(reg_val & SMPS_CMD_MASK)) {
+                       ret = tps80031_update(parent, ri->rinfo->volt_id,
+                               ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK);
+                       if (ret < 0)
+                               dev_err(ri->dev,
+                                       "reg 0x%02x update failed, e = %d\n",
+                                       ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+       }
+       ret = tps80031_update(parent, ri->rinfo->volt_id,
+                       ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK);
+       if (ret < 0)
+               dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+       return ret;
+}
+
+static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       uint8_t vsel = 0;
+       int ret;
+
+       if (ri->rinfo->force_reg) {
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, &vsel);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                                       ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+
+               if (!(vsel & SMPS_CMD_MASK))
+                       return vsel & SMPS_VSEL_MASK;
+       }
+       ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &vsel);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+               return ret;
+       }
+       return vsel & SMPS_VSEL_MASK;
+}
+
+static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned sel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
+       if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+                       (ri->device_flags & TRACK_MODE_ENABLE)) {
+               unsigned nvsel = (sel) & 0x1F;
+               if (((tps80031_get_chip_info(parent) == TPS80031) ||
+                       ((tps80031_get_chip_info(parent) == TPS80032) &&
+                       (tps80031_get_pmu_version(parent) == 0x0))) &&
+                       ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) {
+                               dev_err(ri->dev,
+                                       "Invalid sel %d in track mode LDO2\n",
+                                       nvsel);
+                               return -EINVAL;
+               }
+       }
+
+       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                       ri->rinfo->volt_reg, sel);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+       return ret;
+}
+
+static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       uint8_t vsel;
+       int ret;
+
+       ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &vsel);
+       if (ret < 0) {
+               dev_err(ri->dev, "Error in writing the Voltage register\n");
+               return ret;
+       }
+       return vsel & rdev->desc->vsel_mask;
+}
+
+static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret = -EIO;
+       uint8_t ctrl1 = 0;
+       uint8_t ctrl3 = 0;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+                       TPS80031_CHARGERUSB_CTRL1, &ctrl1);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, &ctrl3);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+       if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN))
+               return 1;
+       return ret;
+}
+
+static int tps80031_vbus_enable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+
+       ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int tps80031_vbus_disable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret = 0;
+
+       if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+               ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+                       USB_VBUS_CTRL_SET, VBUS_DISCHRG);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+                               USB_VBUS_CTRL_SET, ret);
+                       return ret;
+               }
+       }
+
+       ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+                       TPS80031_CHARGERUSB_CTRL1,  OPA_MODE_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+                               TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+
+       ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+                               TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+
+       mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000));
+       if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+               ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+                       USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+                                       USB_VBUS_CTRL_CLR, ret);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+static struct regulator_ops tps80031_dcdc_ops = {
+       .list_voltage           = tps80031_dcdc_list_voltage,
+       .set_voltage_sel        = tps80031_dcdc_set_voltage_sel,
+       .get_voltage_sel        = tps80031_dcdc_get_voltage_sel,
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_voltage_sel        = tps80031_ldo_set_voltage_sel,
+       .get_voltage_sel        = tps80031_ldo_get_voltage_sel,
+       .enable                 = tps80031_reg_enable,
+       .disable                = tps80031_reg_disable,
+       .is_enabled             = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_sw_ops = {
+       .list_voltage   = regulator_list_voltage_linear,
+       .enable         = tps80031_vbus_enable,
+       .disable        = tps80031_vbus_disable,
+       .is_enabled     = tps80031_vbus_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_hw_ops = {
+       .list_voltage   = regulator_list_voltage_linear,
+};
+
+static struct regulator_ops tps80031_ext_reg_ops = {
+       .list_voltage   = regulator_list_voltage_linear,
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+};
+
+/* Non-exiting default definition for some register */
+#define TPS80031_SMPS3_CFG_FORCE       0
+#define TPS80031_SMPS4_CFG_FORCE       0
+
+#define TPS80031_VBUS_CFG_TRANS                0
+#define TPS80031_VBUS_CFG_STATE                0
+
+#define TPS80031_REG_SMPS(_id, _volt_id, _pbit)        \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .force_reg = TPS80031_##_id##_CFG_FORCE,                \
+       .volt_reg = TPS80031_##_id##_CFG_VOLTAGE,               \
+       .volt_id = TPS80031_SLAVE_##_volt_id,                   \
+       .preq_bit = _pbit,                                      \
+       .desc = {                                               \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .n_voltages = 63,                               \
+               .ops = &tps80031_dcdc_ops,                      \
+               .type = REGULATOR_VOLTAGE,                      \
+               .owner = THIS_MODULE,                           \
+               .enable_time = 500,                             \
+       },                                                      \
+}
+
+#define TPS80031_REG_LDO(_id, _preq_bit)                       \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .volt_reg = TPS80031_##_id##_CFG_VOLTAGE,               \
+       .volt_id = TPS80031_SLAVE_ID1,                          \
+       .preq_bit = _preq_bit,                                  \
+       .desc = {                                               \
+               .owner = THIS_MODULE,                           \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .ops = &tps80031_ldo_ops,                       \
+               .type = REGULATOR_VOLTAGE,                      \
+               .min_uV = 1000000,                              \
+               .uV_step = 100000,                              \
+               .linear_min_sel = 1,                            \
+               .n_voltages = 25,                               \
+               .vsel_mask = LDO_VSEL_MASK,                     \
+               .enable_time = 500,                             \
+       },                                                      \
+}
+
+#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit)   \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .volt_id = TPS80031_SLAVE_ID1,                          \
+       .preq_bit = _pbit,                                      \
+       .desc = {                                               \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .min_uV = max_mV * 1000,                        \
+               .n_voltages = 1,                                \
+               .ops = &_ops,                                   \
+               .type = REGULATOR_VOLTAGE,                      \
+               .owner = THIS_MODULE,                           \
+               .enable_time = _delay,                          \
+       },                                                      \
+}
+
+static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = {
+       TPS80031_REG_SMPS(VIO,   ID0, 4),
+       TPS80031_REG_SMPS(SMPS1, ID0, 0),
+       TPS80031_REG_SMPS(SMPS2, ID0, 1),
+       TPS80031_REG_SMPS(SMPS3, ID1, 2),
+       TPS80031_REG_SMPS(SMPS4, ID1, 3),
+       TPS80031_REG_LDO(VANA,   -1),
+       TPS80031_REG_LDO(LDO1,   8),
+       TPS80031_REG_LDO(LDO2,   9),
+       TPS80031_REG_LDO(LDO3,   10),
+       TPS80031_REG_LDO(LDO4,   11),
+       TPS80031_REG_LDO(LDO5,   12),
+       TPS80031_REG_LDO(LDO6,   13),
+       TPS80031_REG_LDO(LDO7,   14),
+       TPS80031_REG_LDO(LDOLN,  15),
+       TPS80031_REG_LDO(LDOUSB, 5),
+       TPS80031_REG_FIXED(VBUS,   5000, tps80031_vbus_hw_ops, 100000, -1),
+       TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16),
+       TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17),
+       TPS80031_REG_FIXED(SYSEN,  3300, tps80031_ext_reg_ops, 0, 18),
+};
+
+static int tps80031_power_req_config(struct device *parent,
+               struct tps80031_regulator *ri,
+               struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+       int ret = 0;
+
+       if (ri->rinfo->preq_bit < 0)
+               goto skip_pwr_req_config;
+
+       ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
+                       ri->rinfo->preq_bit, ri->rinfo->state_reg,
+                       ri->rinfo->trans_reg);
+       if (ret < 0) {
+               dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret);
+               return ret;
+       }
+
+skip_pwr_req_config:
+       if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) {
+               ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON,
+                               TPS80031_TRANS_SLEEP_MASK);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n",
+                                       ri->rinfo->trans_reg, ret);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+static int tps80031_regulator_config(struct device *parent,
+               struct tps80031_regulator *ri,
+               struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+       int ret = 0;
+
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_LDOUSB:
+               if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
+                       TPS80031_USBLDO_INPUT_PMID)) {
+                       unsigned val = 0;
+                       if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
+                               val = MISC2_LDOUSB_IN_VSYS;
+                       else
+                               val = MISC2_LDOUSB_IN_PMID;
+
+                       ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               TPS80031_MISC2, val,
+                               MISC2_LDOUSB_IN_MASK);
+                       if (ret < 0) {
+                               dev_err(ri->dev,
+                                       "LDOUSB config failed, e= %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case TPS80031_REGULATOR_LDO3:
+               if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) {
+                       ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL,
+                               MISC2_LDO3_SEL_VIB_MASK);
+                       if (ret < 0) {
+                               dev_err(ri->dev,
+                                       "LDO3 config failed, e = %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case TPS80031_REGULATOR_VBUS:
+               /* Provide SW control Ops if VBUS is SW control */
+               if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY))
+                       ri->rinfo->desc.ops = &tps80031_vbus_sw_ops;
+               break;
+       default:
+               break;
+       }
+
+       /* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg,
+               TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF |
+               TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK |
+               TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK);
+       if (ret < 0) {
+               dev_err(ri->dev, "trans reg update failed, e %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int check_smps_mode_mult(struct device *parent,
+       struct tps80031_regulator *ri)
+{
+       int mult_offset;
+       int ret;
+       u8 smps_offset;
+       u8 smps_mult;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+                       TPS80031_SMPS_OFFSET, &smps_offset);
+       if (ret < 0) {
+               dev_err(parent, "Error in reading smps offset register\n");
+               return ret;
+       }
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+                       TPS80031_SMPS_MULT, &smps_mult);
+       if (ret < 0) {
+               dev_err(parent, "Error in reading smps mult register\n");
+               return ret;
+       }
+
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_VIO:
+               mult_offset = SMPS_MULTOFFSET_VIO;
+               break;
+       case TPS80031_REGULATOR_SMPS1:
+               mult_offset = SMPS_MULTOFFSET_SMPS1;
+               break;
+       case TPS80031_REGULATOR_SMPS2:
+               mult_offset = SMPS_MULTOFFSET_SMPS2;
+               break;
+       case TPS80031_REGULATOR_SMPS3:
+               mult_offset = SMPS_MULTOFFSET_SMPS3;
+               break;
+       case TPS80031_REGULATOR_SMPS4:
+               mult_offset = SMPS_MULTOFFSET_SMPS4;
+               break;
+       case TPS80031_REGULATOR_LDO2:
+               ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0;
+               /* TRACK mode the ldo2 varies from 600mV to 1300mV */
+               if (ri->device_flags & TRACK_MODE_ENABLE) {
+                       ri->rinfo->desc.min_uV = 600000;
+                       ri->rinfo->desc.uV_step = 12500;
+                       ri->rinfo->desc.n_voltages = 57;
+                       ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK;
+               }
+               return 0;
+       default:
+               return 0;
+       }
+
+       ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0;
+       ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0;
+       switch (ri->device_flags) {
+       case 0:
+               ri->rinfo->desc.min_uV = 607700;
+               ri->rinfo->desc.uV_step = 12660;
+               break;
+       case DCDC_OFFSET_EN:
+               ri->rinfo->desc.min_uV = 700000;
+               ri->rinfo->desc.uV_step = 12500;
+               break;
+       case DCDC_EXTENDED_EN:
+               ri->rinfo->desc.min_uV = 1852000;
+               ri->rinfo->desc.uV_step = 38600;
+               break;
+       case DCDC_OFFSET_EN | DCDC_EXTENDED_EN:
+               ri->rinfo->desc.min_uV = 2161000;
+               ri->rinfo->desc.uV_step = 38600;
+               break;
+       }
+       return 0;
+}
+
+static int tps80031_regulator_probe(struct platform_device *pdev)
+{
+       struct tps80031_platform_data *pdata;
+       struct tps80031_regulator_platform_data *tps_pdata;
+       struct tps80031_regulator *ri;
+       struct tps80031_regulator *pmic;
+       struct regulator_dev *rdev;
+       struct regulator_config config = { };
+       int ret;
+       int num;
+
+       pdata = dev_get_platdata(pdev->dev.parent);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data\n");
+               return -EINVAL;
+       }
+
+       pmic = devm_kzalloc(&pdev->dev,
+                       TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+               tps_pdata = pdata->regulator_pdata[num];
+               ri = &pmic[num];
+               ri->rinfo = &tps80031_rinfo[num];
+               ri->dev = &pdev->dev;
+
+               check_smps_mode_mult(pdev->dev.parent, ri);
+               config.dev = &pdev->dev;
+               config.init_data = NULL;
+               config.driver_data = ri;
+               if (tps_pdata) {
+                       config.init_data = tps_pdata->reg_init_data;
+                       ri->config_flags = tps_pdata->config_flags;
+                       ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
+                       ret = tps80031_regulator_config(pdev->dev.parent,
+                                       ri, tps_pdata);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "regulator config failed, e %d\n", ret);
+                               goto fail;
+                       }
+
+                       ret = tps80031_power_req_config(pdev->dev.parent,
+                                       ri, tps_pdata);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "pwr_req config failed, err %d\n", ret);
+                               goto fail;
+                       }
+               }
+               rdev = regulator_register(&ri->rinfo->desc, &config);
+               if (IS_ERR_OR_NULL(rdev)) {
+                       dev_err(&pdev->dev,
+                               "register regulator failed %s\n",
+                                       ri->rinfo->desc.name);
+                       ret = PTR_ERR(rdev);
+                       goto fail;
+               }
+               ri->rdev = rdev;
+       }
+
+       platform_set_drvdata(pdev, pmic);
+       return 0;
+fail:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
+}
+
+static int tps80031_regulator_remove(struct platform_device *pdev)
+{
+       struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps80031_regulator *ri = NULL;
+       int num;
+
+       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return 0;
+}
+
+static struct platform_driver tps80031_regulator_driver = {
+       .driver = {
+               .name   = "tps80031-pmic",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tps80031_regulator_probe,
+       .remove         = tps80031_regulator_remove,
+};
+
+static int __init tps80031_regulator_init(void)
+{
+       return platform_driver_register(&tps80031_regulator_driver);
+}
+subsys_initcall(tps80031_regulator_init);
+
+static void __exit tps80031_regulator_exit(void)
+{
+       platform_driver_unregister(&tps80031_regulator_driver);
+}
+module_exit(tps80031_regulator_exit);
+
+MODULE_ALIAS("platform:tps80031-regulator");
+MODULE_DESCRIPTION("Regulator Driver for TI TPS80031/TPS80032 PMIC");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
index 7eb986a4074678cb58118577544a10838b8a185a..493c8c6a241f41b1820786b993b342816002bc1c 100644 (file)
@@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, twl_of_match);
 
-static int __devinit twlreg_probe(struct platform_device *pdev)
+static int twlreg_probe(struct platform_device *pdev)
 {
        int                             i, id;
        struct twlreg_info              *info;
@@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit twlreg_remove(struct platform_device *pdev)
+static int twlreg_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct twlreg_info *info = rdev->reg_data;
@@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
 
 static struct platform_driver twlreg_driver = {
        .probe          = twlreg_probe,
-       .remove         = __devexit_p(twlreg_remove),
+       .remove         = twlreg_remove,
        /* NOTE: short name, to work around driver model truncation of
         * "twl_regulator.12" (and friends) to "twl_regulator.1".
         */
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
new file mode 100644 (file)
index 0000000..4668c7f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+       struct regulator_desc desc;
+       struct regulator_dev *regdev;
+       struct vexpress_config_func *func;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+       u32 uV;
+       int err = vexpress_config_read(reg->func, 0, &uV);
+
+       return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+               int min_uV, int max_uV, unsigned *selector)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+       return vexpress_config_write(reg->func, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+       .get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+       .get_voltage = vexpress_regulator_get_voltage,
+       .set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+       int err;
+       struct vexpress_regulator *reg;
+       struct regulator_init_data *init_data;
+       struct regulator_config config = { };
+
+       reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+       if (!reg) {
+               err = -ENOMEM;
+               goto error_kzalloc;
+       }
+
+       reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
+       if (!reg->func) {
+               err = -ENXIO;
+               goto error_get_func;
+       }
+
+       reg->desc.name = dev_name(&pdev->dev);
+       reg->desc.type = REGULATOR_VOLTAGE;
+       reg->desc.owner = THIS_MODULE;
+       reg->desc.continuous_voltage_range = true;
+
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+       if (!init_data) {
+               err = -EINVAL;
+               goto error_get_regulator_init_data;
+       }
+
+       init_data->constraints.apply_uV = 0;
+       if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+               reg->desc.ops = &vexpress_regulator_ops;
+       else
+               reg->desc.ops = &vexpress_regulator_ops_ro;
+
+       config.dev = &pdev->dev;
+       config.init_data = init_data;
+       config.driver_data = reg;
+       config.of_node = pdev->dev.of_node;
+
+       reg->regdev = regulator_register(&reg->desc, &config);
+       if (IS_ERR(reg->regdev)) {
+               err = PTR_ERR(reg->regdev);
+               goto error_regulator_register;
+       }
+
+       platform_set_drvdata(pdev, reg);
+
+       return 0;
+
+error_regulator_register:
+error_get_regulator_init_data:
+       vexpress_config_func_put(reg->func);
+error_get_func:
+error_kzalloc:
+       return err;
+}
+
+static int vexpress_regulator_remove(struct platform_device *pdev)
+{
+       struct vexpress_regulator *reg = platform_get_drvdata(pdev);
+
+       vexpress_config_func_put(reg->func);
+       regulator_unregister(reg->regdev);
+
+       return 0;
+}
+
+static struct of_device_id vexpress_regulator_of_match[] = {
+       { .compatible = "arm,vexpress-volt", },
+       { }
+};
+
+static struct platform_driver vexpress_regulator_driver = {
+       .probe = vexpress_regulator_probe,
+       .remove = vexpress_regulator_remove,
+       .driver = {
+               .name = DRVNAME,
+               .owner = THIS_MODULE,
+               .of_match_table = vexpress_regulator_of_match,
+       },
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
index c038e74225381ea760f9e3984d62eb802af86814..01c66e9712a4aa236ba36ed409abbbce51cd66f2 100644 (file)
@@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
        .attrs  = regulator_virtual_attributes,
 };
 
-static int __devinit regulator_virtual_probe(struct platform_device *pdev)
+static int regulator_virtual_probe(struct platform_device *pdev)
 {
        char *reg_id = pdev->dev.platform_data;
        struct virtual_consumer_data *drvdata;
@@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit regulator_virtual_remove(struct platform_device *pdev)
+static int regulator_virtual_remove(struct platform_device *pdev)
 {
        struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
 
@@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
 
 static struct platform_driver regulator_virtual_consumer_driver = {
        .probe          = regulator_virtual_probe,
-       .remove         = __devexit_p(regulator_virtual_remove),
+       .remove         = regulator_virtual_remove,
        .driver         = {
                .name           = "reg-virt-consumer",
                .owner          = THIS_MODULE,
index 782c228a19bd503ccda868ac67f46cce7fbba2e7..0af6898bcd79b4e2739ffaa4282f8b1aea6fee70 100644 (file)
@@ -223,7 +223,7 @@ static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
        if (min_uV < 600000)
                vsel = 0;
        else if (min_uV <= 1800000)
-               vsel = ((min_uV - 600000) / 12500) + 8;
+               vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8;
        else
                return -EINVAL;
 
@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
        if (vsel > dcdc->dvs_vsel) {
                ret = wm831x_set_bits(wm831x, dvs_reg,
                                      WM831X_DC1_DVS_VSEL_MASK,
-                                     dcdc->dvs_vsel);
+                                     vsel);
                if (ret == 0)
                        dcdc->dvs_vsel = vsel;
                else
@@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = {
  * Set up DVS control.  We just log errors since we can still run
  * (with reduced performance) if we fail.
  */
-static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
                                            struct wm831x_buckv_pdata *pdata)
 {
        struct wm831x *wm831x = dcdc->wm831x;
@@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        }
 }
 
-static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
+static int wm831x_buckv_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -562,7 +562,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
+static int wm831x_buckv_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
        struct wm831x *wm831x = dcdc->wm831x;
@@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckv_driver = {
        .probe = wm831x_buckv_probe,
-       .remove = __devexit_p(wm831x_buckv_remove),
+       .remove = wm831x_buckv_remove,
        .driver         = {
                .name   = "wm831x-buckv",
                .owner  = THIS_MODULE,
@@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
        .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
 };
 
-static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
+static int wm831x_buckp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -710,7 +710,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
+static int wm831x_buckp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckp_driver = {
        .probe = wm831x_buckp_probe,
-       .remove = __devexit_p(wm831x_buckp_remove),
+       .remove = wm831x_buckp_remove,
        .driver         = {
                .name   = "wm831x-buckp",
                .owner  = THIS_MODULE,
@@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
+static int wm831x_boostp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -845,7 +845,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
+static int wm831x_boostp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_boostp_driver = {
        .probe = wm831x_boostp_probe,
-       .remove = __devexit_p(wm831x_boostp_remove),
+       .remove = wm831x_boostp_remove,
        .driver         = {
                .name   = "wm831x-boostp",
                .owner  = THIS_MODULE,
@@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
        .get_status = wm831x_dcdc_get_status,
 };
 
-static __devinit int wm831x_epe_probe(struct platform_device *pdev)
+static int wm831x_epe_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -936,7 +936,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_epe_remove(struct platform_device *pdev)
+static int wm831x_epe_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_epe_driver = {
        .probe = wm831x_epe_probe,
-       .remove = __devexit_p(wm831x_epe_remove),
+       .remove = wm831x_epe_remove,
        .driver         = {
                .name   = "wm831x-epe",
                .owner  = THIS_MODULE,
@@ -993,4 +993,5 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:wm831x-buckv");
 MODULE_ALIAS("platform:wm831x-buckp");
+MODULE_ALIAS("platform:wm831x-boostp");
 MODULE_ALIAS("platform:wm831x-epe");
index 2646a1902b33fe6287ee4bfea055c5c0d952fba5..68586ee3e1cb18197f64ea68d7cbee9e963408fc 100644 (file)
@@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
 }
 
 
-static __devinit int wm831x_isink_probe(struct platform_device *pdev)
+static int wm831x_isink_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -221,7 +221,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_isink_remove(struct platform_device *pdev)
+static int wm831x_isink_remove(struct platform_device *pdev)
 {
        struct wm831x_isink *isink = platform_get_drvdata(pdev);
 
@@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_isink_driver = {
        .probe = wm831x_isink_probe,
-       .remove = __devexit_p(wm831x_isink_remove),
+       .remove = wm831x_isink_remove,
        .driver         = {
                .name   = "wm831x-isink",
                .owner  = THIS_MODULE,
index c2dc03993dc7011d5ce9c87726cea6f25579d8c3..1ec379a9a95c88807c9987b23568e892b14bdc1a 100644 (file)
@@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
+static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -334,7 +334,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
+static int wm831x_gp_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_gp_ldo_driver = {
        .probe = wm831x_gp_ldo_probe,
-       .remove = __devexit_p(wm831x_gp_ldo_remove),
+       .remove = wm831x_gp_ldo_remove,
        .driver         = {
                .name   = "wm831x-ldo",
                .owner  = THIS_MODULE,
@@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
+static int wm831x_aldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -590,7 +590,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
+static int wm831x_aldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_aldo_driver = {
        .probe = wm831x_aldo_probe,
-       .remove = __devexit_p(wm831x_aldo_remove),
+       .remove = wm831x_aldo_remove,
        .driver         = {
                .name   = "wm831x-aldo",
                .owner  = THIS_MODULE,
@@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
+static int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -737,7 +737,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
+static int wm831x_alive_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_alive_ldo_driver = {
        .probe = wm831x_alive_ldo_probe,
-       .remove = __devexit_p(wm831x_alive_ldo_remove),
+       .remove = wm831x_alive_ldo_remove,
        .driver         = {
                .name   = "wm831x-alive-ldo",
                .owner  = THIS_MODULE,
index 27c746ef06364d2f02e95b8928ed748a31de6b1d..c6a32ea80b9d2aa063408f6ac38d11622253f477 100644 (file)
@@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
        },
 };
 
-static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
+static int wm8400_regulator_probe(struct platform_device *pdev)
 {
        struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
        struct regulator_config config = { };
@@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+static int wm8400_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
                .name = "wm8400-regulator",
        },
        .probe = wm8400_regulator_probe,
-       .remove = __devexit_p(wm8400_regulator_remove),
+       .remove = wm8400_regulator_remove,
 };
 
 /**
index 86bb48db149ed3d2bb1285f9dd4a24fb28a531f2..6ff872342648cc2cacbf23565826715b0d3bbff7 100644 (file)
@@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
        },
 };
 
-static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
+static int wm8994_ldo_probe(struct platform_device *pdev)
 {
        struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
        struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -142,7 +142,7 @@ err:
        return ret;
 }
 
-static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+static int wm8994_ldo_remove(struct platform_device *pdev)
 {
        struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8994_ldo_driver = {
        .probe = wm8994_ldo_probe,
-       .remove = __devexit_p(wm8994_ldo_remove),
+       .remove = wm8994_ldo_remove,
        .driver         = {
                .name   = "wm8994-ldo",
                .owner  = THIS_MODULE,
index e1f89d649733e22e75f1e00709b3675e9cced0a7..0d36f94ab51defdd1adea3c1d42b58366ac02f21 100644 (file)
@@ -66,13 +66,13 @@ rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
                return -EINVAL;
        }
 
-       /* We assume the firmware has the same endianess as the host */
+       /* We assume the firmware has the same endianness as the host */
 # ifdef __LITTLE_ENDIAN
        if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
 # else /* BIG ENDIAN */
        if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
 # endif
-               dev_err(dev, "Unsupported firmware endianess\n");
+               dev_err(dev, "Unsupported firmware endianness\n");
                return -EINVAL;
        }
 
index 26c81f233606ebe043360cf349196f5ed7557670..afb7cfa85ccc04ac637268ee0bba4240f05c12d3 100644 (file)
@@ -118,7 +118,7 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
        return ret;
 }
 
-/* simple check to see wether we have a isl1208 */
+/* simple check to see whether we have a isl1208 */
 static int
 isl1208_i2c_validate_client(struct i2c_client *client)
 {
index 77823d21d31488065b6ca8a12de02d1b5e9f013f..a7a2a998fa91fd2b626b2a241dbeef7ff212341e 100644 (file)
@@ -186,7 +186,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
        rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
        rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);
 
-       /* the only way to work out wether the system was mid-update
+       /* the only way to work out whether the system was mid-update
         * when we read it is to check the second counter, and if it
         * is zero, then we re-try the entire read
         */
index 0595c763dafd687ac3938f803618eed679549d76..29225e1c159ce244bfd09a5b202f810b1863b819 100644 (file)
@@ -349,6 +349,16 @@ static int dasd_state_basic_to_ready(struct dasd_device *device)
        return rc;
 }
 
+static inline
+int _wait_for_empty_queues(struct dasd_device *device)
+{
+       if (device->block)
+               return list_empty(&device->ccw_queue) &&
+                       list_empty(&device->block->ccw_queue);
+       else
+               return list_empty(&device->ccw_queue);
+}
+
 /*
  * Remove device from block device layer. Destroy dirty buffers.
  * Forget format information. Check if the target level is basic
@@ -1841,6 +1851,13 @@ static void __dasd_device_check_expire(struct dasd_device *device)
        cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
        if ((cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) &&
            (time_after_eq(jiffies, cqr->expires + cqr->starttime))) {
+               if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+                       /*
+                        * IO in safe offline processing should not
+                        * run out of retries
+                        */
+                       cqr->retries++;
+               }
                if (device->discipline->term_IO(cqr) != 0) {
                        /* Hmpf, try again in 5 sec */
                        dev_err(&device->cdev->dev,
@@ -3024,11 +3041,11 @@ void dasd_generic_remove(struct ccw_device *cdev)
 
        cdev->handler = NULL;
 
-       dasd_remove_sysfs_files(cdev);
        device = dasd_device_from_cdev(cdev);
        if (IS_ERR(device))
                return;
-       if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+       if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags) &&
+           !test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
                /* Already doing offline processing */
                dasd_put_device(device);
                return;
@@ -3048,6 +3065,8 @@ void dasd_generic_remove(struct ccw_device *cdev)
         */
        if (block)
                dasd_free_block(block);
+
+       dasd_remove_sysfs_files(cdev);
 }
 
 /*
@@ -3126,16 +3145,13 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
 {
        struct dasd_device *device;
        struct dasd_block *block;
-       int max_count, open_count;
+       int max_count, open_count, rc;
 
+       rc = 0;
        device = dasd_device_from_cdev(cdev);
        if (IS_ERR(device))
                return PTR_ERR(device);
-       if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags)) {
-               /* Already doing offline processing */
-               dasd_put_device(device);
-               return 0;
-       }
+
        /*
         * We must make sure that this device is currently not in use.
         * The open_count is increased for every opener, that includes
@@ -3159,6 +3175,54 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
                        return -EBUSY;
                }
        }
+
+       if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+               /*
+                * safe offline allready running
+                * could only be called by normal offline so safe_offline flag
+                * needs to be removed to run normal offline and kill all I/O
+                */
+               if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+                       /* Already doing normal offline processing */
+                       dasd_put_device(device);
+                       return -EBUSY;
+               } else
+                       clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
+
+       } else
+               if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+                       /* Already doing offline processing */
+                       dasd_put_device(device);
+                       return -EBUSY;
+               }
+
+       /*
+        * if safe_offline called set safe_offline_running flag and
+        * clear safe_offline so that a call to normal offline
+        * can overrun safe_offline processing
+        */
+       if (test_and_clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags) &&
+           !test_and_set_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+               /*
+                * If we want to set the device safe offline all IO operations
+                * should be finished before continuing the offline process
+                * so sync bdev first and then wait for our queues to become
+                * empty
+                */
+               /* sync blockdev and partitions */
+               rc = fsync_bdev(device->block->bdev);
+               if (rc != 0)
+                       goto interrupted;
+
+               /* schedule device tasklet and wait for completion */
+               dasd_schedule_device_bh(device);
+               rc = wait_event_interruptible(shutdown_waitq,
+                                             _wait_for_empty_queues(device));
+               if (rc != 0)
+                       goto interrupted;
+       }
+
+       set_bit(DASD_FLAG_OFFLINE, &device->flags);
        dasd_set_target_state(device, DASD_STATE_NEW);
        /* dasd_delete_device destroys the device reference. */
        block = device->block;
@@ -3170,6 +3234,14 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
        if (block)
                dasd_free_block(block);
        return 0;
+
+interrupted:
+       /* interrupted by signal */
+       clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
+       clear_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags);
+       clear_bit(DASD_FLAG_OFFLINE, &device->flags);
+       dasd_put_device(device);
+       return rc;
 }
 
 int dasd_generic_last_path_gone(struct dasd_device *device)
@@ -3489,15 +3561,6 @@ char *dasd_get_sense(struct irb *irb)
 }
 EXPORT_SYMBOL_GPL(dasd_get_sense);
 
-static inline int _wait_for_empty_queues(struct dasd_device *device)
-{
-       if (device->block)
-               return list_empty(&device->ccw_queue) &&
-                       list_empty(&device->block->ccw_queue);
-       else
-               return list_empty(&device->ccw_queue);
-}
-
 void dasd_generic_shutdown(struct ccw_device *cdev)
 {
        struct dasd_device *device;
index b2b8c18eecedc98f32b708aa000649f35102fa93..c196827c228fb9f3ce79412e7422051f2307d14d 100644 (file)
@@ -951,6 +951,39 @@ dasd_use_raw_store(struct device *dev, struct device_attribute *attr,
 static DEVICE_ATTR(raw_track_access, 0644, dasd_use_raw_show,
                   dasd_use_raw_store);
 
+static ssize_t
+dasd_safe_offline_store(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct ccw_device *cdev = to_ccwdev(dev);
+       struct dasd_device *device;
+       int rc;
+
+       device = dasd_device_from_cdev(cdev);
+       if (IS_ERR(device)) {
+               rc = PTR_ERR(device);
+               goto out;
+       }
+
+       if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
+           test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+               /* Already doing offline processing */
+               dasd_put_device(device);
+               rc = -EBUSY;
+               goto out;
+       }
+
+       set_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
+       dasd_put_device(device);
+
+       rc = ccw_device_set_offline(cdev);
+
+out:
+       return rc ? rc : count;
+}
+
+static DEVICE_ATTR(safe_offline, 0200, NULL, dasd_safe_offline_store);
+
 static ssize_t
 dasd_discipline_show(struct device *dev, struct device_attribute *attr,
                     char *buf)
@@ -1320,6 +1353,7 @@ static struct attribute * dasd_attrs[] = {
        &dev_attr_expires.attr,
        &dev_attr_reservation_policy.attr,
        &dev_attr_last_known_reservation_state.attr,
+       &dev_attr_safe_offline.attr,
        NULL,
 };
 
@@ -1344,7 +1378,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
 
 /*
  * Set / reset given feature.
- * Flag indicates wether to set (!=0) or the reset (=0) the feature.
+ * Flag indicates whether to set (!=0) or the reset (=0) the feature.
  */
 int
 dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
index 108332b44d986ee1da7fed8309e7c81a87516628..806fe912d6e779ad7456b35f175269352f56e8d6 100644 (file)
@@ -1026,7 +1026,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
 {
        void *conf_data;
        int conf_len, conf_data_saved;
-       int rc;
+       int rc, path_err;
        __u8 lpm, opm;
        struct dasd_eckd_private *private, path_private;
        struct dasd_path *path_data;
@@ -1037,6 +1037,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
        path_data = &device->path_data;
        opm = ccw_device_get_path_mask(device->cdev);
        conf_data_saved = 0;
+       path_err = 0;
        /* get configuration data per operational path */
        for (lpm = 0x80; lpm; lpm>>= 1) {
                if (!(lpm & opm))
@@ -1122,7 +1123,8 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
                                        "the same device, path %02X leads to "
                                        "device %s instead of %s\n", lpm,
                                        print_path_uid, print_device_uid);
-                               return -EINVAL;
+                               path_err = -EINVAL;
+                               continue;
                        }
 
                        path_private.conf_data = NULL;
@@ -1142,7 +1144,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
                        kfree(conf_data);
        }
 
-       return 0;
+       return path_err;
 }
 
 static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
@@ -3847,7 +3849,7 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
 
        len = 0;
        while (from <= to) {
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " CCW %p: %08X %08X DAT:",
                               from, ((int *) from)[0], ((int *) from)[1]);
 
@@ -3908,23 +3910,23 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                return;
        }
        /* dump the sense data */
-       len = sprintf(page,  KERN_ERR PRINTK_HEADER
+       len = sprintf(page, PRINTK_HEADER
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
-       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+       len += sprintf(page + len, PRINTK_HEADER
                       " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X "
                       "CS:%02X RC:%d\n",
                       req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
                       scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw),
                       scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
                       req ? req->intrc : 0);
-       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+       len += sprintf(page + len, PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       dev_name(&device->cdev->dev),
                       (void *) (addr_t) irb->scsw.cmd.cpa);
        if (irb->esw.esw0.erw.cons) {
                for (sl = 0; sl < 4; sl++) {
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                                       " Sense(hex) %2d-%2d:",
                                       (8 * sl), ((8 * sl) + 7));
 
@@ -3937,23 +3939,23 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
 
                if (irb->ecw[27] & DASD_SENSE_BIT_0) {
                        /* 24 Byte Sense Data */
-                       sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       sprintf(page + len, PRINTK_HEADER
                                " 24 Byte: %x MSG %x, "
                                "%s MSGb to SYSOP\n",
                                irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
                                irb->ecw[1] & 0x10 ? "" : "no");
                } else {
                        /* 32 Byte Sense Data */
-                       sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       sprintf(page + len, PRINTK_HEADER
                                " 32 Byte: Format: %x "
                                "Exception class %x\n",
                                irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
                }
        } else {
-               sprintf(page + len, KERN_ERR PRINTK_HEADER
+               sprintf(page + len, PRINTK_HEADER
                        " SORRY - NO VALID SENSE AVAILABLE\n");
        }
-       printk("%s", page);
+       printk(KERN_ERR "%s", page);
 
        if (req) {
                /* req == NULL for unsolicited interrupts */
@@ -3962,10 +3964,10 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                first = req->cpaddr;
                for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
                to = min(first + 6, last);
-               len = sprintf(page,  KERN_ERR PRINTK_HEADER
+               len = sprintf(page, PRINTK_HEADER
                              " Related CP in req: %p\n", req);
                dasd_eckd_dump_ccw_range(first, to, page + len);
-               printk("%s", page);
+               printk(KERN_ERR "%s", page);
 
                /* print failing CCW area (maximum 4) */
                /* scsw->cda is either valid or zero  */
@@ -3975,7 +3977,7 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                                irb->scsw.cmd.cpa; /* failing CCW */
                if (from <  fail - 2) {
                        from = fail - 2;     /* there is a gap - print header */
-                       len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n");
+                       len += sprintf(page, PRINTK_HEADER "......\n");
                }
                to = min(fail + 1, last);
                len += dasd_eckd_dump_ccw_range(from, to, page + len);
@@ -3984,11 +3986,11 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                from = max(from, ++to);
                if (from < last - 1) {
                        from = last - 1;     /* there is a gap - print header */
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
+                       len += sprintf(page + len, PRINTK_HEADER "......\n");
                }
                len += dasd_eckd_dump_ccw_range(from, last, page + len);
                if (len > 0)
-                       printk("%s", page);
+                       printk(KERN_ERR "%s", page);
        }
        free_page((unsigned long) page);
 }
@@ -4012,10 +4014,10 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
                return;
        }
        /* dump the sense data */
-       len = sprintf(page,  KERN_ERR PRINTK_HEADER
+       len = sprintf(page, PRINTK_HEADER
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
-       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+       len += sprintf(page + len, PRINTK_HEADER
                       " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X "
                       "CS:%02X fcxs:%02X schxs:%02X RC:%d\n",
                       req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
@@ -4023,7 +4025,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
                       scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
                       irb->scsw.tm.fcxs, irb->scsw.tm.schxs,
                       req ? req->intrc : 0);
-       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+       len += sprintf(page + len, PRINTK_HEADER
                       " device %s: Failing TCW: %p\n",
                       dev_name(&device->cdev->dev),
                       (void *) (addr_t) irb->scsw.tm.tcw);
@@ -4035,43 +4037,42 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
                        (struct tcw *)(unsigned long)irb->scsw.tm.tcw);
 
        if (tsb) {
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " tsb->length %d\n", tsb->length);
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " tsb->flags %x\n", tsb->flags);
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " tsb->dcw_offset %d\n", tsb->dcw_offset);
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " tsb->count %d\n", tsb->count);
                residual = tsb->count - 28;
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " residual %d\n", residual);
 
                switch (tsb->flags & 0x07) {
                case 1: /* tsa_iostat */
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                               " tsb->tsa.iostat.dev_time %d\n",
                                       tsb->tsa.iostat.dev_time);
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                               " tsb->tsa.iostat.def_time %d\n",
                                       tsb->tsa.iostat.def_time);
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                               " tsb->tsa.iostat.queue_time %d\n",
                                       tsb->tsa.iostat.queue_time);
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                               " tsb->tsa.iostat.dev_busy_time %d\n",
                                       tsb->tsa.iostat.dev_busy_time);
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                               " tsb->tsa.iostat.dev_act_time %d\n",
                                       tsb->tsa.iostat.dev_act_time);
                        sense = tsb->tsa.iostat.sense;
                        break;
                case 2: /* ts_ddpc */
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                               " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc);
                        for (sl = 0; sl < 2; sl++) {
-                               len += sprintf(page + len,
-                                              KERN_ERR PRINTK_HEADER
+                               len += sprintf(page + len, PRINTK_HEADER
                                               " tsb->tsa.ddpc.rcq %2d-%2d: ",
                                               (8 * sl), ((8 * sl) + 7));
                                rcq = tsb->tsa.ddpc.rcq;
@@ -4084,15 +4085,14 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
                        sense = tsb->tsa.ddpc.sense;
                        break;
                case 3: /* tsa_intrg */
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-                                     " tsb->tsa.intrg.: not supportet yet \n");
+                       len += sprintf(page + len, PRINTK_HEADER
+                                     " tsb->tsa.intrg.: not supportet yet\n");
                        break;
                }
 
                if (sense) {
                        for (sl = 0; sl < 4; sl++) {
-                               len += sprintf(page + len,
-                                              KERN_ERR PRINTK_HEADER
+                               len += sprintf(page + len, PRINTK_HEADER
                                               " Sense(hex) %2d-%2d:",
                                               (8 * sl), ((8 * sl) + 7));
                                for (sct = 0; sct < 8; sct++) {
@@ -4104,27 +4104,27 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 
                        if (sense[27] & DASD_SENSE_BIT_0) {
                                /* 24 Byte Sense Data */
-                               sprintf(page + len, KERN_ERR PRINTK_HEADER
+                               sprintf(page + len, PRINTK_HEADER
                                        " 24 Byte: %x MSG %x, "
                                        "%s MSGb to SYSOP\n",
                                        sense[7] >> 4, sense[7] & 0x0f,
                                        sense[1] & 0x10 ? "" : "no");
                        } else {
                                /* 32 Byte Sense Data */
-                               sprintf(page + len, KERN_ERR PRINTK_HEADER
+                               sprintf(page + len, PRINTK_HEADER
                                        " 32 Byte: Format: %x "
                                        "Exception class %x\n",
                                        sense[6] & 0x0f, sense[22] >> 4);
                        }
                } else {
-                       sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       sprintf(page + len, PRINTK_HEADER
                                " SORRY - NO VALID SENSE AVAILABLE\n");
                }
        } else {
-               sprintf(page + len, KERN_ERR PRINTK_HEADER
+               sprintf(page + len, PRINTK_HEADER
                        " SORRY - NO TSB DATA AVAILABLE\n");
        }
-       printk("%s", page);
+       printk(KERN_ERR "%s", page);
        free_page((unsigned long) page);
 }
 
@@ -4161,9 +4161,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        private = (struct dasd_eckd_private *) device->private;
 
        /* Read Configuration Data */
-       rc = dasd_eckd_read_conf(device);
-       if (rc)
-               goto out_err;
+       dasd_eckd_read_conf(device);
 
        dasd_eckd_get_uid(device, &temp_uid);
        /* Generate device unique id */
@@ -4183,9 +4181,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST);
 
        /* RE-Read Configuration Data */
-       rc = dasd_eckd_read_conf(device);
-       if (rc)
-               goto out_err;
+       dasd_eckd_read_conf(device);
 
        /* Read Feature Codes */
        dasd_eckd_read_features(device);
index fb7f3bdc66049210753b254c4dc972442c9d224a..eb748507c7fac2b81f7d3d2028a2f11c47aaa854 100644 (file)
@@ -479,19 +479,19 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                            "No memory to dump sense data");
                return;
        }
-       len = sprintf(page, KERN_ERR PRINTK_HEADER
+       len = sprintf(page, PRINTK_HEADER
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
-       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+       len += sprintf(page + len, PRINTK_HEADER
                       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
                       irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
-       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+       len += sprintf(page + len, PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       dev_name(&device->cdev->dev),
                       (void *) (addr_t) irb->scsw.cmd.cpa);
        if (irb->esw.esw0.erw.cons) {
                for (sl = 0; sl < 4; sl++) {
-                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       len += sprintf(page + len, PRINTK_HEADER
                                       " Sense(hex) %2d-%2d:",
                                       (8 * sl), ((8 * sl) + 7));
 
@@ -502,7 +502,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                        len += sprintf(page + len, "\n");
                }
        } else {
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " SORRY - NO VALID SENSE AVAILABLE\n");
        }
        printk(KERN_ERR "%s", page);
@@ -512,10 +512,9 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
        act = req->cpaddr;
         for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
        end = min(act + 8, last);
-       len = sprintf(page, KERN_ERR PRINTK_HEADER
-                     " Related CP in req: %p\n", req);
+       len = sprintf(page, PRINTK_HEADER " Related CP in req: %p\n", req);
        while (act <= end) {
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " CCW %p: %08X %08X DAT:",
                               act, ((int *) act)[0], ((int *) act)[1]);
                for (count = 0; count < 32 && count < act->count;
@@ -533,11 +532,11 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
        len = 0;
        if (act <  ((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa) - 2) {
                act = ((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa) - 2;
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
+               len += sprintf(page + len, PRINTK_HEADER "......\n");
        }
        end = min((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa + 2, last);
        while (act <= end) {
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " CCW %p: %08X %08X DAT:",
                               act, ((int *) act)[0], ((int *) act)[1]);
                for (count = 0; count < 32 && count < act->count;
@@ -552,10 +551,10 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
        /* print last CCWs */
        if (act <  last - 2) {
                act = last - 2;
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
+               len += sprintf(page + len, PRINTK_HEADER "......\n");
        }
        while (act <= last) {
-               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+               len += sprintf(page + len, PRINTK_HEADER
                               " CCW %p: %08X %08X DAT:",
                               act, ((int *) act)[0], ((int *) act)[1]);
                for (count = 0; count < 32 && count < act->count;
index 7ff93eea673d009a1636e8de79c9336e52e9647a..899e3f5a56e50db3f28d3649b56e6022ed566364 100644 (file)
@@ -516,6 +516,8 @@ struct dasd_block {
 #define DASD_FLAG_IS_RESERVED  7       /* The device is reserved */
 #define DASD_FLAG_LOCK_STOLEN  8       /* The device lock was stolen */
 #define DASD_FLAG_SUSPENDED    9       /* The device was suspended */
+#define DASD_FLAG_SAFE_OFFLINE 10      /* safe offline processing requested*/
+#define DASD_FLAG_SAFE_OFFLINE_RUNNING 11      /* safe offline running */
 
 
 void dasd_put_device_wake(struct dasd_device *);
index 8252f37d04ed317b3f39764089187e0c91779c29..03c0e044455335df0c6d3a0cc5defbf5c15dd0a6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <asm/compat.h>
 #include <asm/ccwdev.h>
+#include <asm/schid.h>
 #include <asm/cmb.h>
 #include <asm/uaccess.h>
 
@@ -308,11 +309,12 @@ static int dasd_ioctl_information(struct dasd_block *block,
                                  unsigned int cmd, void __user *argp)
 {
        struct dasd_information2_t *dasd_info;
-       unsigned long flags;
-       int rc;
+       struct subchannel_id sch_id;
+       struct ccw_dev_id dev_id;
        struct dasd_device *base;
        struct ccw_device *cdev;
-       struct ccw_dev_id dev_id;
+       unsigned long flags;
+       int rc;
 
        base = block->base;
        if (!base->discipline || !base->discipline->fill_info)
@@ -330,9 +332,10 @@ static int dasd_ioctl_information(struct dasd_block *block,
 
        cdev = base->cdev;
        ccw_device_get_id(cdev, &dev_id);
+       ccw_device_get_schid(cdev, &sch_id);
 
        dasd_info->devno = dev_id.devno;
-       dasd_info->schid = _ccw_device_get_subchannel_number(base->cdev);
+       dasd_info->schid = sch_id.sch_no;
        dasd_info->cu_type = cdev->id.cu_type;
        dasd_info->cu_model = cdev->id.cu_model;
        dasd_info->dev_type = cdev->id.dev_type;
index d7e97ae9ef6dee8c1238c3544b20290d14fbce5f..25bcd4c0ed82d35f522f4d0efdd7477ec6076a01 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 1999, 2009
+ * Copyright IBM Corp. 1999,2012
  *
  * Author(s): Martin Peschke <mpeschke@de.ibm.com>
  *           Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -103,6 +103,7 @@ extern u64 sclp_facilities;
 #define SCLP_HAS_CHP_RECONFIG  (sclp_facilities & 0x2000000000000000ULL)
 #define SCLP_HAS_CPU_INFO      (sclp_facilities & 0x0800000000000000ULL)
 #define SCLP_HAS_CPU_RECONFIG  (sclp_facilities & 0x0400000000000000ULL)
+#define SCLP_HAS_PCI_RECONFIG  (sclp_facilities & 0x0000000040000000ULL)
 
 
 struct gds_subvector {
index 71ea923c322d4330f2272dac818e0db327457199..c44d13f607bc586781221e144341c921aaf42010 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2007, 2009
+ * Copyright IBM Corp. 2007,2012
  *
  * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  *           Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/memory.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <asm/ctl_reg.h>
 #include <asm/chpid.h>
-#include <asm/sclp.h>
 #include <asm/setup.h>
-#include <asm/ctl_reg.h>
+#include <asm/page.h>
+#include <asm/sclp.h>
 
 #include "sclp.h"
 
@@ -400,17 +402,15 @@ out:
 
 static int sclp_assign_storage(u16 rn)
 {
-       unsigned long long start, address;
+       unsigned long long start;
        int rc;
 
        rc = do_assign_storage(0x000d0001, rn);
        if (rc)
-               goto out;
-       start = address = rn2addr(rn);
-       for (; address < start + rzm; address += PAGE_SIZE)
-               page_set_storage_key(address, PAGE_DEFAULT_KEY, 0);
-out:
-       return rc;
+               return rc;
+       start = rn2addr(rn);
+       storage_key_init_range(start, start + rzm);
+       return 0;
 }
 
 static int sclp_unassign_storage(u16 rn)
@@ -701,6 +701,67 @@ __initcall(sclp_detect_standby_memory);
 
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
+/*
+ * PCI I/O adapter configuration related functions.
+ */
+#define SCLP_CMDW_CONFIGURE_PCI                        0x001a0001
+#define SCLP_CMDW_DECONFIGURE_PCI              0x001b0001
+
+#define SCLP_RECONFIG_PCI_ATPYE                        2
+
+struct pci_cfg_sccb {
+       struct sccb_header header;
+       u8 atype;               /* adapter type */
+       u8 reserved1;
+       u16 reserved2;
+       u32 aid;                /* adapter identifier */
+} __packed;
+
+static int do_pci_configure(sclp_cmdw_t cmd, u32 fid)
+{
+       struct pci_cfg_sccb *sccb;
+       int rc;
+
+       if (!SCLP_HAS_PCI_RECONFIG)
+               return -EOPNOTSUPP;
+
+       sccb = (struct pci_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sccb)
+               return -ENOMEM;
+
+       sccb->header.length = PAGE_SIZE;
+       sccb->atype = SCLP_RECONFIG_PCI_ATPYE;
+       sccb->aid = fid;
+       rc = do_sync_request(cmd, sccb);
+       if (rc)
+               goto out;
+       switch (sccb->header.response_code) {
+       case 0x0020:
+       case 0x0120:
+               break;
+       default:
+               pr_warn("configure PCI I/O adapter failed: cmd=0x%08x  response=0x%04x\n",
+                       cmd, sccb->header.response_code);
+               rc = -EIO;
+               break;
+       }
+out:
+       free_page((unsigned long) sccb);
+       return rc;
+}
+
+int sclp_pci_configure(u32 fid)
+{
+       return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid);
+}
+EXPORT_SYMBOL(sclp_pci_configure);
+
+int sclp_pci_deconfigure(u32 fid)
+{
+       return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid);
+}
+EXPORT_SYMBOL(sclp_pci_deconfigure);
+
 /*
  * Channel path configuration related functions.
  */
index 731470e68493b14e8d09830b4400e1da01dde5a2..84846c2b96d34bdf3f0f1461038d76c9627e2704 100644 (file)
@@ -65,10 +65,18 @@ static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
        }
 }
 
-static int ccwgroup_set_online(struct ccwgroup_device *gdev)
+/**
+ * ccwgroup_set_online() - enable a ccwgroup device
+ * @gdev: target ccwgroup device
+ *
+ * This function attempts to put the ccwgroup device into the online state.
+ * Returns:
+ *  %0 on success and a negative error value on failure.
+ */
+int ccwgroup_set_online(struct ccwgroup_device *gdev)
 {
        struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
                return -EAGAIN;
@@ -84,11 +92,20 @@ out:
        atomic_set(&gdev->onoff, 0);
        return ret;
 }
+EXPORT_SYMBOL(ccwgroup_set_online);
 
-static int ccwgroup_set_offline(struct ccwgroup_device *gdev)
+/**
+ * ccwgroup_set_offline() - disable a ccwgroup device
+ * @gdev: target ccwgroup device
+ *
+ * This function attempts to put the ccwgroup device into the offline state.
+ * Returns:
+ *  %0 on success and a negative error value on failure.
+ */
+int ccwgroup_set_offline(struct ccwgroup_device *gdev)
 {
        struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
                return -EAGAIN;
@@ -104,6 +121,7 @@ out:
        atomic_set(&gdev->onoff, 0);
        return ret;
 }
+EXPORT_SYMBOL(ccwgroup_set_offline);
 
 static ssize_t ccwgroup_online_store(struct device *dev,
                                     struct device_attribute *attr,
index 4d51a7c4eb8b8af56b8a8cf2089a494079bea5bc..68e80e2734a4be89763ca466a48621911570bce4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   S/390 common I/O routines -- channel subsystem call
  *
- *    Copyright IBM Corp. 1999, 2010
+ *    Copyright IBM Corp. 1999,2012
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/pci.h>
 
 #include <asm/cio.h>
 #include <asm/chpid.h>
@@ -260,26 +261,45 @@ __get_chpid_from_lir(void *data)
        return (u16) (lir->indesc[0]&0x000000ff);
 }
 
-struct chsc_sei_area {
-       struct chsc_header request;
+struct chsc_sei_nt0_area {
+       u8  flags;
+       u8  vf;                         /* validity flags */
+       u8  rs;                         /* reporting source */
+       u8  cc;                         /* content code */
+       u16 fla;                        /* full link address */
+       u16 rsid;                       /* reporting source id */
        u32 reserved1;
        u32 reserved2;
-       u32 reserved3;
-       struct chsc_header response;
-       u32 reserved4;
-       u8  flags;
-       u8  vf;         /* validity flags */
-       u8  rs;         /* reporting source */
-       u8  cc;         /* content code */
-       u16 fla;        /* full link address */
-       u16 rsid;       /* reporting source id */
-       u32 reserved5;
-       u32 reserved6;
-       u8 ccdf[4096 - 16 - 24];        /* content-code dependent field */
        /* ccdf has to be big enough for a link-incident record */
-} __attribute__ ((packed));
-
-static void chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
+       u8  ccdf[PAGE_SIZE - 24 - 16];  /* content-code dependent field */
+} __packed;
+
+struct chsc_sei_nt2_area {
+       u8  flags;                      /* p and v bit */
+       u8  reserved1;
+       u8  reserved2;
+       u8  cc;                         /* content code */
+       u32 reserved3[13];
+       u8  ccdf[PAGE_SIZE - 24 - 56];  /* content-code dependent field */
+} __packed;
+
+#define CHSC_SEI_NT0   0ULL
+#define CHSC_SEI_NT2   (1ULL << 61)
+
+struct chsc_sei {
+       struct chsc_header request;
+       u32 reserved1;
+       u64 ntsm;                       /* notification type mask */
+       struct chsc_header response;
+       u32 reserved2;
+       union {
+               struct chsc_sei_nt0_area nt0_area;
+               struct chsc_sei_nt2_area nt2_area;
+               u8 nt_area[PAGE_SIZE - 24];
+       } u;
+} __packed;
+
+static void chsc_process_sei_link_incident(struct chsc_sei_nt0_area *sei_area)
 {
        struct chp_id chpid;
        int id;
@@ -298,7 +318,7 @@ static void chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
        }
 }
 
-static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
+static void chsc_process_sei_res_acc(struct chsc_sei_nt0_area *sei_area)
 {
        struct chp_link link;
        struct chp_id chpid;
@@ -330,7 +350,7 @@ static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
        s390_process_res_acc(&link);
 }
 
-static void chsc_process_sei_chp_avail(struct chsc_sei_area *sei_area)
+static void chsc_process_sei_chp_avail(struct chsc_sei_nt0_area *sei_area)
 {
        struct channel_path *chp;
        struct chp_id chpid;
@@ -366,7 +386,7 @@ struct chp_config_data {
        u8 pc;
 };
 
-static void chsc_process_sei_chp_config(struct chsc_sei_area *sei_area)
+static void chsc_process_sei_chp_config(struct chsc_sei_nt0_area *sei_area)
 {
        struct chp_config_data *data;
        struct chp_id chpid;
@@ -398,7 +418,7 @@ static void chsc_process_sei_chp_config(struct chsc_sei_area *sei_area)
        }
 }
 
-static void chsc_process_sei_scm_change(struct chsc_sei_area *sei_area)
+static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area)
 {
        int ret;
 
@@ -412,13 +432,26 @@ static void chsc_process_sei_scm_change(struct chsc_sei_area *sei_area)
                              " failed (rc=%d).\n", ret);
 }
 
-static void chsc_process_sei(struct chsc_sei_area *sei_area)
+static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
 {
-       /* Check if we might have lost some information. */
-       if (sei_area->flags & 0x40) {
-               CIO_CRW_EVENT(2, "chsc: event overflow\n");
-               css_schedule_eval_all();
+#ifdef CONFIG_PCI
+       switch (sei_area->cc) {
+       case 1:
+               zpci_event_error(sei_area->ccdf);
+               break;
+       case 2:
+               zpci_event_availability(sei_area->ccdf);
+               break;
+       default:
+               CIO_CRW_EVENT(2, "chsc: unhandled sei content code %d\n",
+                             sei_area->cc);
+               break;
        }
+#endif
+}
+
+static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
+{
        /* which kind of information was stored? */
        switch (sei_area->cc) {
        case 1: /* link incident*/
@@ -443,9 +476,51 @@ static void chsc_process_sei(struct chsc_sei_area *sei_area)
        }
 }
 
+static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm)
+{
+       do {
+               memset(sei, 0, sizeof(*sei));
+               sei->request.length = 0x0010;
+               sei->request.code = 0x000e;
+               sei->ntsm = ntsm;
+
+               if (chsc(sei))
+                       break;
+
+               if (sei->response.code == 0x0001) {
+                       CIO_CRW_EVENT(2, "chsc: sei successful\n");
+
+                       /* Check if we might have lost some information. */
+                       if (sei->u.nt0_area.flags & 0x40) {
+                               CIO_CRW_EVENT(2, "chsc: event overflow\n");
+                               css_schedule_eval_all();
+                       }
+
+                       switch (sei->ntsm) {
+                       case CHSC_SEI_NT0:
+                               chsc_process_sei_nt0(&sei->u.nt0_area);
+                               return 1;
+                       case CHSC_SEI_NT2:
+                               chsc_process_sei_nt2(&sei->u.nt2_area);
+                               return 1;
+                       default:
+                               CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n",
+                                             sei->ntsm);
+                               return 0;
+                       }
+               } else {
+                       CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
+                                     sei->response.code);
+                       break;
+               }
+       } while (sei->u.nt0_area.flags & 0x80);
+
+       return 0;
+}
+
 static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 {
-       struct chsc_sei_area *sei_area;
+       struct chsc_sei *sei;
 
        if (overflow) {
                css_schedule_eval_all();
@@ -459,25 +534,18 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
                return;
        /* Access to sei_page is serialized through machine check handler
         * thread, so no need for locking. */
-       sei_area = sei_page;
+       sei = sei_page;
 
        CIO_TRACE_EVENT(2, "prcss");
-       do {
-               memset(sei_area, 0, sizeof(*sei_area));
-               sei_area->request.length = 0x0010;
-               sei_area->request.code = 0x000e;
-               if (chsc(sei_area))
-                       break;
 
-               if (sei_area->response.code == 0x0001) {
-                       CIO_CRW_EVENT(4, "chsc: sei successful\n");
-                       chsc_process_sei(sei_area);
-               } else {
-                       CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
-                                     sei_area->response.code);
-                       break;
-               }
-       } while (sei_area->flags & 0x80);
+       /*
+        * The ntsm does not allow to select NT0 and NT2 together. We need to
+        * first check for NT2, than additionally for NT0...
+        */
+#ifdef CONFIG_PCI
+       if (!__chsc_process_crw(sei, CHSC_SEI_NT2))
+#endif
+               __chsc_process_crw(sei, CHSC_SEI_NT0);
 }
 
 void chsc_chp_online(struct chp_id chpid)
index fd3143c291c6a630933d608c6c6e455b2be04a0d..6995cff44636a23dfe857098c2faca86670311fe 100644 (file)
@@ -2036,16 +2036,6 @@ void ccw_driver_unregister(struct ccw_driver *cdriver)
        driver_unregister(&cdriver->driver);
 }
 
-/* Helper func for qdio. */
-struct subchannel_id
-ccw_device_get_subchannel_id(struct ccw_device *cdev)
-{
-       struct subchannel *sch;
-
-       sch = to_subchannel(cdev->dev.parent);
-       return sch->schid;
-}
-
 static void ccw_device_todo(struct work_struct *work)
 {
        struct ccw_device_private *priv;
@@ -2138,4 +2128,3 @@ EXPORT_SYMBOL(ccw_device_set_offline);
 EXPORT_SYMBOL(ccw_driver_register);
 EXPORT_SYMBOL(ccw_driver_unregister);
 EXPORT_SYMBOL(get_ccwdev_by_busid);
-EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);
index 6bace694239614dfb2d948ba6741c25de052ff73..2e575cff984549bbc90478663d6fcf3a23b10410 100644 (file)
@@ -142,9 +142,7 @@ int ccw_device_notify(struct ccw_device *, int);
 void ccw_device_set_disconnected(struct ccw_device *cdev);
 void ccw_device_set_notoper(struct ccw_device *cdev);
 
-/* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
-extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
 
 /* Channel measurement facility related */
 void retry_set_schib(struct ccw_device *cdev);
index ec7fb6d3b479a25a32bfad67ecc36a3539782b39..c77b6e06bf646a90ad01d6e33a61bc5411ecf884 100644 (file)
@@ -755,14 +755,18 @@ int ccw_device_tm_intrg(struct ccw_device *cdev)
 }
 EXPORT_SYMBOL(ccw_device_tm_intrg);
 
-// FIXME: these have to go:
-
-int
-_ccw_device_get_subchannel_number(struct ccw_device *cdev)
+/**
+ * ccw_device_get_schid - obtain a subchannel id
+ * @cdev: device to obtain the id for
+ * @schid: where to fill in the values
+ */
+void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)
 {
-       return cdev->private->schid.sch_no;
-}
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
 
+       *schid = sch->schid;
+}
+EXPORT_SYMBOL_GPL(ccw_device_get_schid);
 
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(ccw_device_set_options_mask);
@@ -777,5 +781,4 @@ EXPORT_SYMBOL(ccw_device_start_timeout_key);
 EXPORT_SYMBOL(ccw_device_start_key);
 EXPORT_SYMBOL(ccw_device_get_ciw);
 EXPORT_SYMBOL(ccw_device_get_path_mask);
-EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
 EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
index 368368fe04b27fa29a4506ae87177afa9e8e05a9..908d287f66c13c1b1f41daf6bdb7b15bdd6d845f 100644 (file)
@@ -234,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, struct pgid *p2)
  * Determine pathgroup state from PGID data.
  */
 static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
-                        int *mismatch, int *reserved, u8 *reset)
+                        int *mismatch, u8 *reserved, u8 *reset)
 {
        struct pgid *pgid = &cdev->private->pgid[0];
        struct pgid *first = NULL;
@@ -248,7 +248,7 @@ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
                if ((cdev->private->pgid_valid_mask & lpm) == 0)
                        continue;
                if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE)
-                       *reserved = 1;
+                       *reserved |= lpm;
                if (pgid_is_reset(pgid)) {
                        *reset |= lpm;
                        continue;
@@ -316,14 +316,14 @@ static void snid_done(struct ccw_device *cdev, int rc)
        struct subchannel *sch = to_subchannel(cdev->dev.parent);
        struct pgid *pgid;
        int mismatch = 0;
-       int reserved = 0;
+       u8 reserved = 0;
        u8 reset = 0;
        u8 donepm;
 
        if (rc)
                goto out;
        pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset);
-       if (reserved)
+       if (reserved == cdev->private->pgid_valid_mask)
                rc = -EUSERS;
        else if (mismatch)
                rc = -EOPNOTSUPP;
@@ -336,7 +336,7 @@ static void snid_done(struct ccw_device *cdev, int rc)
        }
 out:
        CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x "
-                     "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid,
+                     "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid,
                      id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm,
                      cdev->private->pgid_todo_mask, mismatch, reserved, reset);
        switch (rc) {
index e06fa03ea1e456bac69ba5f84e634ebbd9f645ce..1671d3461f298175dc9b5e9029114df0046d8d0b 100644 (file)
@@ -129,7 +129,6 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
        int rc, tmp_count = count, tmp_start = start, nr = q->nr, retried = 0;
        unsigned int ccq = 0;
 
-       BUG_ON(!q->irq_ptr->sch_token);
        qperf_inc(q, eqbs);
 
        if (!q->is_input_q)
@@ -147,7 +146,6 @@ again:
        }
 
        if (rc == 2) {
-               BUG_ON(tmp_count == count);
                qperf_inc(q, eqbs_partial);
                DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x",
                        tmp_count);
@@ -189,8 +187,6 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
 
        if (!count)
                return 0;
-
-       BUG_ON(!q->irq_ptr->sch_token);
        qperf_inc(q, sqbs);
 
        if (!q->is_input_q)
@@ -199,7 +195,7 @@ again:
        ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count);
        rc = qdio_check_ccq(q, ccq);
        if (!rc) {
-               WARN_ON(tmp_count);
+               WARN_ON_ONCE(tmp_count);
                return count - tmp_count;
        }
 
@@ -224,9 +220,6 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
        unsigned char __state = 0;
        int i;
 
-       BUG_ON(bufnr > QDIO_MAX_BUFFERS_MASK);
-       BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q);
-
        if (is_qebsm(q))
                return qdio_do_eqbs(q, state, bufnr, count, auto_ack);
 
@@ -258,9 +251,6 @@ static inline int set_buf_states(struct qdio_q *q, int bufnr,
 {
        int i;
 
-       BUG_ON(bufnr > QDIO_MAX_BUFFERS_MASK);
-       BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q);
-
        if (is_qebsm(q))
                return qdio_do_sqbs(q, state, bufnr, count);
 
@@ -345,7 +335,6 @@ again:
 
        /* hipersocket busy condition */
        if (unlikely(*busy_bit)) {
-               WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2);
                retries++;
 
                if (!start_time) {
@@ -559,7 +548,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop");
                break;
        default:
-               BUG();
+               WARN_ON_ONCE(1);
        }
 out:
        return q->first_to_check;
@@ -678,12 +667,10 @@ static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count)
                        if (aob == NULL)
                                continue;
 
-                       BUG_ON(q->u.out.sbal_state == NULL);
                        q->u.out.sbal_state[b].flags |=
                                QDIO_OUTBUF_STATE_FLAG_PENDING;
                        q->u.out.aobs[b] = NULL;
                } else if (state == SLSB_P_OUTPUT_EMPTY) {
-                       BUG_ON(q->u.out.sbal_state == NULL);
                        q->u.out.sbal_state[b].aob = NULL;
                }
                b = next_buf(b);
@@ -703,12 +690,11 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
                q->aobs[bufnr] = aob;
        }
        if (q->aobs[bufnr]) {
-               BUG_ON(q->sbal_state == NULL);
                q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE;
                q->sbal_state[bufnr].aob = q->aobs[bufnr];
                q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user;
                phys_aob = virt_to_phys(q->aobs[bufnr]);
-               BUG_ON(phys_aob & 0xFF);
+               WARN_ON_ONCE(phys_aob & 0xFF);
        }
 
 out:
@@ -809,8 +795,6 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
                goto out;
 
        switch (state) {
-       case SLSB_P_OUTPUT_PENDING:
-               BUG();
        case SLSB_P_OUTPUT_EMPTY:
                /* the adapter got it */
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
@@ -840,7 +824,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
        case SLSB_P_OUTPUT_HALTED:
                break;
        default:
-               BUG();
+               WARN_ON_ONCE(1);
        }
 
 out:
@@ -912,7 +896,7 @@ retry:
 static void __qdio_outbound_processing(struct qdio_q *q)
 {
        qperf_inc(q, tasklet_outbound);
-       BUG_ON(atomic_read(&q->nr_buf_used) < 0);
+       WARN_ON_ONCE(atomic_read(&q->nr_buf_used) < 0);
 
        if (qdio_outbound_q_moved(q))
                qdio_kick_handler(q);
@@ -1138,16 +1122,10 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
                irq_ptr->perf_stat.qdio_int++;
 
        if (IS_ERR(irb)) {
-               switch (PTR_ERR(irb)) {
-               case -EIO:
-                       DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no);
-                       qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
-                       wake_up(&cdev->private->wait_q);
-                       return;
-               default:
-                       WARN_ON(1);
-                       return;
-               }
+               DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no);
+               qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+               wake_up(&cdev->private->wait_q);
+               return;
        }
        qdio_irq_check_sense(irq_ptr, irb);
        cstat = irb->scsw.cmd.cstat;
@@ -1173,7 +1151,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
        case QDIO_IRQ_STATE_STOPPED:
                break;
        default:
-               WARN_ON(1);
+               WARN_ON_ONCE(1);
        }
        wake_up(&cdev->private->wait_q);
 }
@@ -1227,7 +1205,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
        if (!irq_ptr)
                return -ENODEV;
 
-       BUG_ON(irqs_disabled());
+       WARN_ON_ONCE(irqs_disabled());
        DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no);
 
        mutex_lock(&irq_ptr->setup_mutex);
@@ -1358,7 +1336,6 @@ int qdio_allocate(struct qdio_initialize *init_data)
        irq_ptr->qdr = (struct qdr *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!irq_ptr->qdr)
                goto out_rel;
-       WARN_ON((unsigned long)irq_ptr->qdr & 0xfff);
 
        if (qdio_allocate_qs(irq_ptr, init_data->no_input_qs,
                             init_data->no_output_qs))
@@ -1597,9 +1574,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
 
 set:
        count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
-
        used = atomic_add_return(count, &q->nr_buf_used) - count;
-       BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q);
 
        if (need_siga_in(q))
                return qdio_siga_input(q);
@@ -1624,7 +1599,6 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
 
        count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count);
        used = atomic_add_return(count, &q->nr_buf_used);
-       BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
 
        if (used == QDIO_MAX_BUFFERS_PER_Q)
                qperf_inc(q, outbound_queue_full);
@@ -1678,7 +1652,6 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
 {
        struct qdio_irq *irq_ptr;
 
-
        if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
                return -EINVAL;
 
@@ -1721,8 +1694,6 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
                return -ENODEV;
        q = irq_ptr->input_qs[nr];
 
-       WARN_ON(queue_irqs_enabled(q));
-
        clear_nonshared_ind(irq_ptr);
        qdio_stop_polling(q);
        clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
@@ -1769,7 +1740,6 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
        if (!irq_ptr)
                return -ENODEV;
        q = irq_ptr->input_qs[nr];
-       WARN_ON(queue_irqs_enabled(q));
 
        /*
         * Cannot rely on automatic sync after interrupt since queues may
index 6c973db149832f13ce9edd9dc38152991054c889..16ecd35b8e5137dbd675f2e51527224ea0370557 100644 (file)
@@ -140,10 +140,8 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
        q->sl = (struct sl *)((char *)q->slib + PAGE_SIZE / 2);
 
        /* fill in sbal */
-       for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) {
+       for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
                q->sbal[j] = *sbals_array++;
-               BUG_ON((unsigned long)q->sbal[j] & 0xff);
-       }
 
        /* fill in slib */
        if (i > 0) {
@@ -434,9 +432,8 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
        irq_ptr->int_parm = init_data->int_parm;
        irq_ptr->nr_input_qs = init_data->no_input_qs;
        irq_ptr->nr_output_qs = init_data->no_output_qs;
-
-       irq_ptr->schid = ccw_device_get_subchannel_id(init_data->cdev);
        irq_ptr->cdev = init_data->cdev;
+       ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid);
        setup_queues(irq_ptr, init_data);
 
        setup_qib(irq_ptr, init_data);
@@ -483,7 +480,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
        char s[80];
 
        snprintf(s, 80, "qdio: %s %s on SC %x using "
-                "AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s\n",
+                "AI:%d QEBSM:%d PRI:%d TDD:%d SIGA:%s%s%s%s%s\n",
                 dev_name(&cdev->dev),
                 (irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" :
                        ((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"),
index 2e060088fa87872cb9a9c45edd847e999c54bf6e..bdb394b066fcff56aac5588119c5ecc64efddf1f 100644 (file)
@@ -73,7 +73,6 @@ static void put_indicator(u32 *addr)
 void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
 {
        mutex_lock(&tiq_list_lock);
-       BUG_ON(irq_ptr->nr_input_qs < 1);
        list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
        mutex_unlock(&tiq_list_lock);
        xchg(irq_ptr->dsci, 1 << 7);
@@ -83,7 +82,6 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
 {
        struct qdio_q *q;
 
-       BUG_ON(irq_ptr->nr_input_qs < 1);
        q = irq_ptr->input_qs[0];
        /* if establish triggered an error */
        if (!q || !q->entry.prev || !q->entry.next)
index 035b6dc31b71f42bbb4529700aca331c805321c9..7c522f338bda16a50f11cf04aa845a8f6f937637 100644 (file)
@@ -241,84 +241,70 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev,
                                       struct ap_message *ap_msg,
                                       struct ica_rsa_modexpo_crt *crt)
 {
-       int mod_len, short_len, long_len, long_offset, limit;
+       int mod_len, short_len;
        unsigned char *p, *q, *dp, *dq, *u, *inp;
 
        mod_len = crt->inputdatalength;
        short_len = mod_len / 2;
-       long_len = mod_len / 2 + 8;
 
        /*
-        * CEX2A cannot handle p, dp, or U > 128 bytes.
-        * If we have one of these, we need to do extra checking.
-        * For CEX3A the limit is 256 bytes.
+        * CEX2A and CEX3A w/o FW update can handle requests up to
+        * 256 byte modulus (2k keys).
+        * CEX3A with FW update and CEX4A cards are able to handle
+        * 512 byte modulus (4k keys).
         */
-       if (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE)
-               limit = 256;
-       else
-               limit = 128;
-
-       if (long_len > limit) {
-               /*
-                * zcrypt_rsa_crt already checked for the leading
-                * zeroes of np_prime, bp_key and u_mult_inc.
-                */
-               long_offset = long_len - limit;
-               long_len = limit;
-       } else
-               long_offset = 0;
-
-       /*
-        * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use
-        * the larger message structure.
-        */
-       if (long_len <= 64) {
+       if (mod_len <= 128) {           /* up to 1024 bit key size */
                struct type50_crb1_msg *crb1 = ap_msg->message;
                memset(crb1, 0, sizeof(*crb1));
                ap_msg->length = sizeof(*crb1);
                crb1->header.msg_type_code = TYPE50_TYPE_CODE;
                crb1->header.msg_len = sizeof(*crb1);
                crb1->keyblock_type = TYPE50_CRB1_FMT;
-               p = crb1->p + sizeof(crb1->p) - long_len;
+               p = crb1->p + sizeof(crb1->p) - short_len;
                q = crb1->q + sizeof(crb1->q) - short_len;
-               dp = crb1->dp + sizeof(crb1->dp) - long_len;
+               dp = crb1->dp + sizeof(crb1->dp) - short_len;
                dq = crb1->dq + sizeof(crb1->dq) - short_len;
-               u = crb1->u + sizeof(crb1->u) - long_len;
+               u = crb1->u + sizeof(crb1->u) - short_len;
                inp = crb1->message + sizeof(crb1->message) - mod_len;
-       } else if (long_len <= 128) {
+       } else if (mod_len <= 256) {    /* up to 2048 bit key size */
                struct type50_crb2_msg *crb2 = ap_msg->message;
                memset(crb2, 0, sizeof(*crb2));
                ap_msg->length = sizeof(*crb2);
                crb2->header.msg_type_code = TYPE50_TYPE_CODE;
                crb2->header.msg_len = sizeof(*crb2);
                crb2->keyblock_type = TYPE50_CRB2_FMT;
-               p = crb2->p + sizeof(crb2->p) - long_len;
+               p = crb2->p + sizeof(crb2->p) - short_len;
                q = crb2->q + sizeof(crb2->q) - short_len;
-               dp = crb2->dp + sizeof(crb2->dp) - long_len;
+               dp = crb2->dp + sizeof(crb2->dp) - short_len;
                dq = crb2->dq + sizeof(crb2->dq) - short_len;
-               u = crb2->u + sizeof(crb2->u) - long_len;
+               u = crb2->u + sizeof(crb2->u) - short_len;
                inp = crb2->message + sizeof(crb2->message) - mod_len;
-       } else {
-               /* long_len >= 256 */
+       } else if ((mod_len <= 512) &&  /* up to 4096 bit key size */
+                  (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE)) { /* >= CEX3A */
                struct type50_crb3_msg *crb3 = ap_msg->message;
                memset(crb3, 0, sizeof(*crb3));
                ap_msg->length = sizeof(*crb3);
                crb3->header.msg_type_code = TYPE50_TYPE_CODE;
                crb3->header.msg_len = sizeof(*crb3);
                crb3->keyblock_type = TYPE50_CRB3_FMT;
-               p = crb3->p + sizeof(crb3->p) - long_len;
+               p = crb3->p + sizeof(crb3->p) - short_len;
                q = crb3->q + sizeof(crb3->q) - short_len;
-               dp = crb3->dp + sizeof(crb3->dp) - long_len;
+               dp = crb3->dp + sizeof(crb3->dp) - short_len;
                dq = crb3->dq + sizeof(crb3->dq) - short_len;
-               u = crb3->u + sizeof(crb3->u) - long_len;
+               u = crb3->u + sizeof(crb3->u) - short_len;
                inp = crb3->message + sizeof(crb3->message) - mod_len;
-       }
+       } else
+               return -EINVAL;
 
-       if (copy_from_user(p, crt->np_prime + long_offset, long_len) ||
+       /*
+        * correct the offset of p, bp and mult_inv according zcrypt.h
+        * block size right aligned (skip the first byte)
+        */
+       if (copy_from_user(p, crt->np_prime + MSGTYPE_ADJUSTMENT, short_len) ||
            copy_from_user(q, crt->nq_prime, short_len) ||
-           copy_from_user(dp, crt->bp_key + long_offset, long_len) ||
+           copy_from_user(dp, crt->bp_key + MSGTYPE_ADJUSTMENT, short_len) ||
            copy_from_user(dq, crt->bq_key, short_len) ||
-           copy_from_user(u, crt->u_mult_inv + long_offset, long_len) ||
+           copy_from_user(u, crt->u_mult_inv + MSGTYPE_ADJUSTMENT, short_len) ||
            copy_from_user(inp, crt->inputdata, mod_len))
                return -EFAULT;
 
index e56dc72c7733406280d778515073094c0fa485c7..0a66e4aeeb5047fb1c4cb3bfad63e665da8736f1 100644 (file)
@@ -33,6 +33,8 @@
 #define MSGTYPE50_CRB2_MAX_MSG_SIZE    0x390 /*sizeof(struct type50_crb2_msg)*/
 #define MSGTYPE50_CRB3_MAX_MSG_SIZE    0x710 /*sizeof(struct type50_crb3_msg)*/
 
+#define MSGTYPE_ADJUSTMENT             0x08  /*type04 extension (not needed in type50)*/
+
 int zcrypt_msgtype50_init(void);
 void zcrypt_msgtype50_exit(void);
 
index 74bf1aa7af464811b1ed74480b104d193ca0c5dc..142f632e2a2e45c7377709989d5495382e74f5c9 100644 (file)
@@ -603,6 +603,7 @@ config SCSI_ARCMSR
 
 source "drivers/scsi/megaraid/Kconfig.megaraid"
 source "drivers/scsi/mpt2sas/Kconfig"
+source "drivers/scsi/mpt3sas/Kconfig"
 source "drivers/scsi/ufs/Kconfig"
 
 config SCSI_HPTIOP
@@ -1812,6 +1813,7 @@ config SCSI_VIRTIO
           This is the virtual HBA driver for virtio.  If the kernel will
           be used in a virtual machine, say Y or M.
 
+source "drivers/scsi/csiostor/Kconfig"
 
 endif # SCSI_LOWLEVEL
 
index 888f73a4aae14ee62a3dcc089a6bcabdbeb8bd40..b607ba4f56304b1e9952e11c40f9285668d9f61e 100644 (file)
@@ -90,6 +90,7 @@ obj-$(CONFIG_SCSI_QLA_FC)     += qla2xxx/
 obj-$(CONFIG_SCSI_QLA_ISCSI)   += libiscsi.o qla4xxx/
 obj-$(CONFIG_SCSI_LPFC)                += lpfc/
 obj-$(CONFIG_SCSI_BFA_FC)      += bfa/
+obj-$(CONFIG_SCSI_CHELSIO_FCOE)        += csiostor/
 obj-$(CONFIG_SCSI_PAS16)       += pas16.o
 obj-$(CONFIG_SCSI_T128)                += t128.o
 obj-$(CONFIG_SCSI_DMX3191D)    += dmx3191d.o
@@ -106,6 +107,7 @@ obj-$(CONFIG_MEGARAID_LEGACY)       += megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)  += megaraid/
 obj-$(CONFIG_MEGARAID_SAS)     += megaraid/
 obj-$(CONFIG_SCSI_MPT2SAS)     += mpt2sas/
+obj-$(CONFIG_SCSI_MPT3SAS)     += mpt3sas/
 obj-$(CONFIG_SCSI_UFSHCD)      += ufs/
 obj-$(CONFIG_SCSI_ACARD)       += atp870u.o
 obj-$(CONFIG_SCSI_SUNESP)      += esp_scsi.o   sun_esp.o
index d79457ac8beff1628787ce8b9b4c632ed0b5e77d..681434e2dfe9b77a4da7487cdc9e9f8e2a293715 100644 (file)
@@ -132,11 +132,13 @@ struct inquiry_data {
  *              M O D U L E   G L O B A L S
  */
 
-static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
-static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
-static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
-static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max);
-static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new);
+static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *sgmap);
+static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg);
+static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg);
+static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
+                               struct aac_raw_io2 *rio2, int sg_max);
+static int aac_convert_sgraw2(struct aac_raw_io2 *rio2,
+                               int pages, int nseg, int nseg_new);
 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
 #ifdef AAC_DETAILED_STATUS_INFO
 static char *aac_get_status_string(u32 status);
@@ -971,6 +973,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 {
        struct aac_dev *dev = fib->dev;
        u16 fibsize, command;
+       long ret;
 
        aac_fib_init(fib);
        if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) {
@@ -982,7 +985,10 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
                readcmd2->byteCount = cpu_to_le32(count<<9);
                readcmd2->cid = cpu_to_le16(scmd_id(cmd));
                readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ);
-               aac_build_sgraw2(cmd, readcmd2, dev->scsi_host_ptr->sg_tablesize);
+               ret = aac_build_sgraw2(cmd, readcmd2,
+                               dev->scsi_host_ptr->sg_tablesize);
+               if (ret < 0)
+                       return ret;
                command = ContainerRawIo2;
                fibsize = sizeof(struct aac_raw_io2) +
                        ((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
@@ -996,7 +1002,9 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
                readcmd->flags = cpu_to_le16(RIO_TYPE_READ);
                readcmd->bpTotal = 0;
                readcmd->bpComplete = 0;
-               aac_build_sgraw(cmd, &readcmd->sg);
+               ret = aac_build_sgraw(cmd, &readcmd->sg);
+               if (ret < 0)
+                       return ret;
                command = ContainerRawIo;
                fibsize = sizeof(struct aac_raw_io) +
                        ((le32_to_cpu(readcmd->sg.count)-1) * sizeof(struct sgentryraw));
@@ -1019,6 +1027,8 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 {
        u16 fibsize;
        struct aac_read64 *readcmd;
+       long ret;
+
        aac_fib_init(fib);
        readcmd = (struct aac_read64 *) fib_data(fib);
        readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -1028,7 +1038,9 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
        readcmd->pad   = 0;
        readcmd->flags = 0;
 
-       aac_build_sg64(cmd, &readcmd->sg);
+       ret = aac_build_sg64(cmd, &readcmd->sg);
+       if (ret < 0)
+               return ret;
        fibsize = sizeof(struct aac_read64) +
                ((le32_to_cpu(readcmd->sg.count) - 1) *
                 sizeof (struct sgentry64));
@@ -1050,6 +1062,8 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
 {
        u16 fibsize;
        struct aac_read *readcmd;
+       long ret;
+
        aac_fib_init(fib);
        readcmd = (struct aac_read *) fib_data(fib);
        readcmd->command = cpu_to_le32(VM_CtBlockRead);
@@ -1057,7 +1071,9 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
        readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
        readcmd->count = cpu_to_le32(count * 512);
 
-       aac_build_sg(cmd, &readcmd->sg);
+       ret = aac_build_sg(cmd, &readcmd->sg);
+       if (ret < 0)
+               return ret;
        fibsize = sizeof(struct aac_read) +
                        ((le32_to_cpu(readcmd->sg.count) - 1) *
                         sizeof (struct sgentry));
@@ -1079,6 +1095,7 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 {
        struct aac_dev *dev = fib->dev;
        u16 fibsize, command;
+       long ret;
 
        aac_fib_init(fib);
        if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) {
@@ -1093,7 +1110,10 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
                                                   (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
                        cpu_to_le16(RIO2_IO_TYPE_WRITE|RIO2_IO_SUREWRITE) :
                        cpu_to_le16(RIO2_IO_TYPE_WRITE);
-               aac_build_sgraw2(cmd, writecmd2, dev->scsi_host_ptr->sg_tablesize);
+               ret = aac_build_sgraw2(cmd, writecmd2,
+                               dev->scsi_host_ptr->sg_tablesize);
+               if (ret < 0)
+                       return ret;
                command = ContainerRawIo2;
                fibsize = sizeof(struct aac_raw_io2) +
                        ((le32_to_cpu(writecmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
@@ -1110,7 +1130,9 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
                        cpu_to_le16(RIO_TYPE_WRITE);
                writecmd->bpTotal = 0;
                writecmd->bpComplete = 0;
-               aac_build_sgraw(cmd, &writecmd->sg);
+               ret = aac_build_sgraw(cmd, &writecmd->sg);
+               if (ret < 0)
+                       return ret;
                command = ContainerRawIo;
                fibsize = sizeof(struct aac_raw_io) +
                        ((le32_to_cpu(writecmd->sg.count)-1) * sizeof (struct sgentryraw));
@@ -1133,6 +1155,8 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba,
 {
        u16 fibsize;
        struct aac_write64 *writecmd;
+       long ret;
+
        aac_fib_init(fib);
        writecmd = (struct aac_write64 *) fib_data(fib);
        writecmd->command = cpu_to_le32(VM_CtHostWrite64);
@@ -1142,7 +1166,9 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba,
        writecmd->pad   = 0;
        writecmd->flags = 0;
 
-       aac_build_sg64(cmd, &writecmd->sg);
+       ret = aac_build_sg64(cmd, &writecmd->sg);
+       if (ret < 0)
+               return ret;
        fibsize = sizeof(struct aac_write64) +
                ((le32_to_cpu(writecmd->sg.count) - 1) *
                 sizeof (struct sgentry64));
@@ -1164,6 +1190,8 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 {
        u16 fibsize;
        struct aac_write *writecmd;
+       long ret;
+
        aac_fib_init(fib);
        writecmd = (struct aac_write *) fib_data(fib);
        writecmd->command = cpu_to_le32(VM_CtBlockWrite);
@@ -1173,7 +1201,9 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
        writecmd->sg.count = cpu_to_le32(1);
        /* ->stable is not used - it did mean which type of write */
 
-       aac_build_sg(cmd, &writecmd->sg);
+       ret = aac_build_sg(cmd, &writecmd->sg);
+       if (ret < 0)
+               return ret;
        fibsize = sizeof(struct aac_write) +
                ((le32_to_cpu(writecmd->sg.count) - 1) *
                 sizeof (struct sgentry));
@@ -1235,8 +1265,11 @@ static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
 {
        u16 fibsize;
        struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+       long ret;
 
-       aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
+       ret = aac_build_sg64(cmd, (struct sgmap64 *) &srbcmd->sg);
+       if (ret < 0)
+               return ret;
        srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
 
        memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
@@ -1263,8 +1296,11 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
 {
        u16 fibsize;
        struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+       long ret;
 
-       aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
+       ret = aac_build_sg(cmd, (struct sgmap *)&srbcmd->sg);
+       if (ret < 0)
+               return ret;
        srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
 
        memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
@@ -2870,7 +2906,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
        return -1;
 }
 
-static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
+static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg)
 {
        struct aac_dev *dev;
        unsigned long byte_count = 0;
@@ -2883,7 +2919,8 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
        psg->sg[0].count = 0;
 
        nseg = scsi_dma_map(scsicmd);
-       BUG_ON(nseg < 0);
+       if (nseg < 0)
+               return nseg;
        if (nseg) {
                struct scatterlist *sg;
                int i;
@@ -2912,7 +2949,7 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
 }
 
 
-static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg)
+static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg)
 {
        struct aac_dev *dev;
        unsigned long byte_count = 0;
@@ -2927,7 +2964,8 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
        psg->sg[0].count = 0;
 
        nseg = scsi_dma_map(scsicmd);
-       BUG_ON(nseg < 0);
+       if (nseg < 0)
+               return nseg;
        if (nseg) {
                struct scatterlist *sg;
                int i;
@@ -2957,7 +2995,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
        return byte_count;
 }
 
-static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg)
 {
        unsigned long byte_count = 0;
        int nseg;
@@ -2972,7 +3010,8 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw*
        psg->sg[0].flags = 0;
 
        nseg = scsi_dma_map(scsicmd);
-       BUG_ON(nseg < 0);
+       if (nseg < 0)
+               return nseg;
        if (nseg) {
                struct scatterlist *sg;
                int i;
@@ -3005,13 +3044,15 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw*
        return byte_count;
 }
 
-static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max)
+static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
+                               struct aac_raw_io2 *rio2, int sg_max)
 {
        unsigned long byte_count = 0;
        int nseg;
 
        nseg = scsi_dma_map(scsicmd);
-       BUG_ON(nseg < 0);
+       if (nseg < 0)
+               return nseg;
        if (nseg) {
                struct scatterlist *sg;
                int i, conformable = 0;
index 9e933a88a8bc5aaa95b8fc929ec51395a53495e1..742f5d7eb0f5988c8b07592eef1448685f5ab7a1 100644 (file)
@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 29800
+# define AAC_DRIVER_BUILD 29801
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
index a50b6a9030e88acaabc85aae89d2fd1df1e4c146..f1733dfa3ae24489b44b3f6bee92568589c7ade1 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 /* BladeEngine Generation numbers */
 #define BE_GEN2 2
 #define BE_GEN3 3
-
+#define BE_GEN4        4
 struct be_dma_mem {
        void *va;
        dma_addr_t dma;
@@ -84,9 +84,12 @@ static inline void queue_tail_inc(struct be_queue_info *q)
 /*ISCSI */
 
 struct be_eq_obj {
+       bool todo_mcc_cq;
+       bool todo_cq;
        struct be_queue_info q;
        struct beiscsi_hba *phba;
        struct be_queue_info *cq;
+       struct work_struct work_cqs; /* Work Item */
        struct blk_iopoll       iopoll;
 };
 
index 07d2cb126d934eca69956a6269ab3543a3333dac..5c87768c109c0fa9a8fc0dda6f8bcb6c357ca083 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -56,7 +56,7 @@ int beiscsi_pci_soft_reset(struct beiscsi_hba *phba)
        writel(pconline0, (void *)pci_online0_offset);
        writel(pconline1, (void *)pci_online1_offset);
 
-       sreset = BE2_SET_RESET;
+       sreset |= BE2_SET_RESET;
        writel(sreset, (void *)pci_reset_offset);
 
        i = 0;
@@ -133,6 +133,87 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba)
        return tag;
 }
 
+/*
+ * beiscsi_mccq_compl()- Wait for completion of MBX
+ * @phba: Driver private structure
+ * @tag: Tag for the MBX Command
+ * @wrb: the WRB used for the MBX Command
+ * @cmd_hdr: IOCTL Hdr for the MBX Cmd
+ *
+ * Waits for MBX completion with the passed TAG.
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
+int beiscsi_mccq_compl(struct beiscsi_hba *phba,
+               uint32_t tag, struct be_mcc_wrb **wrb,
+               void *cmd_hdr)
+{
+       int rc = 0;
+       uint32_t mcc_tag_response;
+       uint16_t status = 0, addl_status = 0, wrb_num = 0;
+       struct be_mcc_wrb *temp_wrb;
+       struct be_cmd_req_hdr *ioctl_hdr;
+       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+
+       if (beiscsi_error(phba))
+               return -EIO;
+
+       /* wait for the mccq completion */
+       rc = wait_event_interruptible_timeout(
+                               phba->ctrl.mcc_wait[tag],
+                               phba->ctrl.mcc_numtag[tag],
+                               msecs_to_jiffies(
+                               BEISCSI_HOST_MBX_TIMEOUT));
+
+       if (rc <= 0) {
+               beiscsi_log(phba, KERN_ERR,
+                           BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
+                           BEISCSI_LOG_CONFIG,
+                           "BC_%d : MBX Cmd Completion timed out\n");
+               rc = -EAGAIN;
+               goto release_mcc_tag;
+       } else
+               rc = 0;
+
+       mcc_tag_response = phba->ctrl.mcc_numtag[tag];
+       status = (mcc_tag_response & CQE_STATUS_MASK);
+       addl_status = ((mcc_tag_response & CQE_STATUS_ADDL_MASK) >>
+                       CQE_STATUS_ADDL_SHIFT);
+
+       if (cmd_hdr) {
+               ioctl_hdr = (struct be_cmd_req_hdr *)cmd_hdr;
+       } else {
+               wrb_num = (mcc_tag_response & CQE_STATUS_WRB_MASK) >>
+                          CQE_STATUS_WRB_SHIFT;
+               temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num);
+               ioctl_hdr = embedded_payload(temp_wrb);
+
+               if (wrb)
+                       *wrb = temp_wrb;
+       }
+
+       if (status || addl_status) {
+               beiscsi_log(phba, KERN_ERR,
+                           BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
+                           BEISCSI_LOG_CONFIG,
+                           "BC_%d : MBX Cmd Failed for "
+                           "Subsys : %d Opcode : %d with "
+                           "Status : %d and Extd_Status : %d\n",
+                           ioctl_hdr->subsystem,
+                           ioctl_hdr->opcode,
+                           status, addl_status);
+               rc = -EAGAIN;
+       }
+
+release_mcc_tag:
+       /* Release the MCC entry */
+       free_mcc_tag(&phba->ctrl, tag);
+
+       return rc;
+}
+
 void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag)
 {
        spin_lock(&ctrl->mbox_lock);
@@ -168,11 +249,24 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
        compl->flags = 0;
 }
 
+/*
+ * be_mcc_compl_process()- Check the MBX comapletion status
+ * @ctrl: Function specific MBX data structure
+ * @compl: Completion status of MBX Command
+ *
+ * Check for the MBX completion status when BMBX method used
+ *
+ * return
+ * Success: Zero
+ * Failure: Non-Zero
+ **/
 static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
                                struct be_mcc_compl *compl)
 {
        u16 compl_status, extd_status;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
        struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+       struct be_cmd_req_hdr *hdr = embedded_payload(wrb);
 
        be_dws_le_to_cpu(compl, 4);
 
@@ -184,7 +278,10 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
 
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BC_%d : error in cmd completion: status(compl/extd)=%d/%d\n",
+                           "BC_%d : error in cmd completion: "
+                           "Subsystem : %d Opcode : %d "
+                           "status(compl/extd)=%d/%d\n",
+                           hdr->subsystem, hdr->opcode,
                            compl_status, extd_status);
 
                return -EBUSY;
@@ -314,11 +411,24 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
        return status;
 }
 
-/* Wait till no more pending mcc requests are present */
+/*
+ * be_mcc_wait_compl()- Wait for MBX completion
+ * @phba: driver private structure
+ *
+ * Wait till no more pending mcc requests are present
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ *
+ **/
 static int be_mcc_wait_compl(struct beiscsi_hba *phba)
 {
        int i, status;
        for (i = 0; i < mcc_timeout; i++) {
+               if (beiscsi_error(phba))
+                       return -EIO;
+
                status = beiscsi_process_mcc(phba);
                if (status)
                        return status;
@@ -330,51 +440,83 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba)
        if (i == mcc_timeout) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BC_%d : mccq poll timed out\n");
-
+                           "BC_%d : FW Timed Out\n");
+               phba->fw_timeout = true;
+               beiscsi_ue_detect(phba);
                return -EBUSY;
        }
        return 0;
 }
 
-/* Notify MCC requests and wait for completion */
+/*
+ * be_mcc_notify_wait()- Notify and wait for Compl
+ * @phba: driver private structure
+ *
+ * Notify MCC requests and wait for completion
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
 int be_mcc_notify_wait(struct beiscsi_hba *phba)
 {
        be_mcc_notify(phba);
        return be_mcc_wait_compl(phba);
 }
 
+/*
+ * be_mbox_db_ready_wait()- Check ready status
+ * @ctrl: Function specific MBX data structure
+ *
+ * Check for the ready status of FW to send BMBX
+ * commands to adapter.
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
 static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
 {
-#define long_delay 2000
        void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
-       int cnt = 0, wait = 5;  /* in usecs */
+       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+       int wait = 0;
        u32 ready;
 
        do {
+
+               if (beiscsi_error(phba))
+                       return -EIO;
+
                ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
                if (ready)
                        break;
 
-               if (cnt > 12000000) {
-                       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+               if (wait > BEISCSI_HOST_MBX_TIMEOUT) {
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                                   "BC_%d : mbox_db poll timed out\n");
-
+                                   "BC_%d : FW Timed Out\n");
+                       phba->fw_timeout = true;
+                       beiscsi_ue_detect(phba);
                        return -EBUSY;
                }
 
-               if (cnt > 50) {
-                       wait = long_delay;
-                       mdelay(long_delay / 1000);
-               } else
-                       udelay(wait);
-               cnt += wait;
+               mdelay(1);
+               wait++;
        } while (true);
        return 0;
 }
 
+/*
+ * be_mbox_notify: Notify adapter of new BMBX command
+ * @ctrl: Function specific MBX data structure
+ *
+ * Ring doorbell to inform adapter of a BMBX command
+ * to process
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
 int be_mbox_notify(struct be_ctrl_info *ctrl)
 {
        int status;
@@ -391,13 +533,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
        iowrite32(val, db);
 
        status = be_mbox_db_ready_wait(ctrl);
-       if (status != 0) {
-               beiscsi_log(phba, KERN_ERR,
-                           BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BC_%d : be_mbox_db_ready_wait failed\n");
-
+       if (status)
                return status;
-       }
+
        val = 0;
        val &= ~MPU_MAILBOX_DB_RDY_MASK;
        val &= ~MPU_MAILBOX_DB_HI_MASK;
@@ -405,13 +543,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
        iowrite32(val, db);
 
        status = be_mbox_db_ready_wait(ctrl);
-       if (status != 0) {
-               beiscsi_log(phba, KERN_ERR,
-                           BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BC_%d : be_mbox_db_ready_wait failed\n");
-
+       if (status)
                return status;
-       }
+
        if (be_mcc_compl_is_new(compl)) {
                status = be_mcc_compl_process(ctrl, &mbox->compl);
                be_mcc_compl_use(compl);
@@ -499,7 +633,7 @@ void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
        req_hdr->opcode = opcode;
        req_hdr->subsystem = subsystem;
        req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
-       req_hdr->timeout = 120;
+       req_hdr->timeout = BEISCSI_FW_MBX_TIMEOUT;
 }
 
 static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
@@ -649,18 +783,34 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
                        OPCODE_COMMON_CQ_CREATE, sizeof(*req));
 
        req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+       if (chip_skh_r(ctrl->pdev)) {
+               req->hdr.version = MBX_CMD_VER2;
+               req->page_size = 1;
+               AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+                             ctxt, coalesce_wm);
+               AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
+                             ctxt, no_delay);
+               AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
+                             __ilog2_u32(cq->len / 256));
+               AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
+               AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
+       } else {
+               AMAP_SET_BITS(struct amap_cq_context, coalescwm,
+                             ctxt, coalesce_wm);
+               AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
+               AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
+                             __ilog2_u32(cq->len / 256));
+               AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
+               AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
+               AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
+                             PCI_FUNC(ctrl->pdev->devfn));
+       }
 
-       AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm);
-       AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
-       AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
-                     __ilog2_u32(cq->len / 256));
-       AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
-       AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
-       AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
-       AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
-       AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
-       AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
-                     PCI_FUNC(ctrl->pdev->devfn));
        be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
        be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
index 2c8f98df12875c478c3e5e0872623b6476f0106b..23397d51ac54f5f9550f15b3b4571ed8342ee762 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -57,6 +57,16 @@ struct be_mcc_wrb {
 #define CQE_STATUS_COMPL_SHIFT 0       /* bits 0 - 15 */
 #define CQE_STATUS_EXTD_MASK 0xFFFF
 #define CQE_STATUS_EXTD_SHIFT 16               /* bits 0 - 15 */
+#define CQE_STATUS_ADDL_MASK   0xFF00
+#define CQE_STATUS_MASK        0xFF
+#define CQE_STATUS_ADDL_SHIFT  0x08
+#define CQE_STATUS_WRB_MASK    0xFF0000
+#define CQE_STATUS_WRB_SHIFT   16
+#define BEISCSI_HOST_MBX_TIMEOUT (110 * 1000)
+#define BEISCSI_FW_MBX_TIMEOUT 100
+
+/* MBOX Command VER */
+#define MBX_CMD_VER2   0x02
 
 struct be_mcc_compl {
        u32 status;             /* dword 0 */
@@ -183,7 +193,8 @@ struct be_cmd_req_hdr {
        u8 domain;              /* dword 0 */
        u32 timeout;            /* dword 1 */
        u32 request_length;     /* dword 2 */
-       u32 rsvd0;              /* dword 3 */
+       u8 version;             /* dword 3 */
+       u8 rsvd0[3];            /* dword 3 */
 };
 
 struct be_cmd_resp_hdr {
@@ -483,10 +494,28 @@ struct amap_cq_context {
        u8 rsvd5[32];           /* dword 3 */
 } __packed;
 
+struct amap_cq_context_v2 {
+       u8 rsvd0[12];   /* dword 0 */
+       u8 coalescwm[2];    /* dword 0 */
+       u8 nodelay;     /* dword 0 */
+       u8 rsvd1[12];   /* dword 0 */
+       u8 count[2];    /* dword 0 */
+       u8 valid;       /* dword 0 */
+       u8 rsvd2;       /* dword 0 */
+       u8 eventable;   /* dword 0 */
+       u8 eqid[16];    /* dword 1 */
+       u8 rsvd3[15];   /* dword 1 */
+       u8 armed;       /* dword 1 */
+       u8 cqecount[16];/* dword 2 */
+       u8 rsvd4[16];   /* dword 2 */
+       u8 rsvd5[32];   /* dword 3 */
+};
+
 struct be_cmd_req_cq_create {
        struct be_cmd_req_hdr hdr;
        u16 num_pages;
-       u16 rsvd0;
+       u8 page_size;
+       u8 rsvd0;
        u8 context[sizeof(struct amap_cq_context) / 8];
        struct phys_addr pages[4];
 } __packed;
@@ -663,6 +692,9 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
 unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
 
 void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
+
+int beiscsi_mccq_compl(struct beiscsi_hba *phba,
+                       uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va);
 /*ISCSI Functuions */
 int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
 
@@ -804,6 +836,59 @@ struct amap_sol_cqe_ring {
        u8 valid;               /* dword 3 */
 } __packed;
 
+struct amap_sol_cqe_v2 {
+       u8 hw_sts[8];   /* dword 0 */
+       u8 i_sts[8];    /* dword 0 */
+       u8 wrb_index[16];   /* dword 0 */
+       u8 i_exp_cmd_sn[32];    /* dword 1 */
+       u8 code[6]; /* dword 2 */
+       u8 cmd_cmpl;    /* dword 2 */
+       u8 rsvd0;   /* dword 2 */
+       u8 i_cmd_wnd[8];    /* dword 2 */
+       u8 cid[13]; /* dword 2 */
+       u8 u;   /* dword 2 */
+       u8 o;   /* dword 2 */
+       u8 s;   /* dword 2 */
+       u8 i_res_cnt[31];   /* dword 3 */
+       u8 valid;   /* dword 3 */
+} __packed;
+
+struct common_sol_cqe {
+       u32 exp_cmdsn;
+       u32 res_cnt;
+       u16 wrb_index;
+       u16 cid;
+       u8 hw_sts;
+       u8 cmd_wnd;
+       u8 res_flag; /* the s feild of structure */
+       u8 i_resp; /* for skh if cmd_complete is set then i_sts is response */
+       u8 i_flags; /* for skh or the u and o feilds */
+       u8 i_sts; /* for skh if cmd_complete is not-set then i_sts is status */
+};
+
+/*** iSCSI ack/driver message completions ***/
+struct amap_it_dmsg_cqe {
+       u8 ack_num[32]; /* DWORD 0 */
+       u8 pdu_bytes_rcvd[32];  /* DWORD 1 */
+       u8 code[6]; /* DWORD 2 */
+       u8 cid[10]; /* DWORD 2 */
+       u8 wrb_idx[8];  /* DWORD 2 */
+       u8 rsvd0[8];    /* DWORD 2*/
+       u8 rsvd1[31];   /* DWORD 3*/
+       u8 valid;   /* DWORD 3 */
+} __packed;
+
+struct amap_it_dmsg_cqe_v2 {
+       u8 ack_num[32]; /* DWORD 0 */
+       u8 pdu_bytes_rcvd[32];  /* DWORD 1 */
+       u8 code[6]; /* DWORD 2 */
+       u8 rsvd0[10];   /* DWORD 2 */
+       u8 wrb_idx[16]; /* DWORD 2 */
+       u8 rsvd1[16];   /* DWORD 3 */
+       u8 cid[13]; /* DWORD 3 */
+       u8 rsvd2[2];    /* DWORD 3 */
+       u8 valid;   /* DWORD 3 */
+} __packed;
 
 
 /**
@@ -992,8 +1077,6 @@ struct be_cmd_get_all_if_id_req {
 #define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4     /* Abortive upload with reset,
                                                 * sequence number by driver  */
 
-/* Returns byte size of given field with a structure. */
-
 /* Returns the number of items in the field array. */
 #define BE_NUMBER_OF_FIELD(_type_, _field_)    \
        (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
index aedb0d9a9dae652d753455df07c2aee1a4d9e867..214d691adb53ab21d39ae7425df6f9150c1eb0d5 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -531,9 +531,9 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
                break;
        case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
                if (!if_info.dhcp_state)
-                       len = sprintf(buf, "static");
+                       len = sprintf(buf, "static\n");
                else
-                       len = sprintf(buf, "dhcp");
+                       len = sprintf(buf, "dhcp\n");
                break;
        case ISCSI_NET_PARAM_IPV4_SUBNET:
                len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask);
@@ -541,7 +541,7 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
        case ISCSI_NET_PARAM_VLAN_ENABLED:
                len = sprintf(buf, "%s\n",
                             (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
-                            ? "Disabled" : "Enabled");
+                            ? "Disabled\n" : "Enabled\n");
                break;
        case ISCSI_NET_PARAM_VLAN_ID:
                if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
@@ -586,7 +586,7 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface,
                len = be2iscsi_get_if_param(phba, iface, param, buf);
                break;
        case ISCSI_NET_PARAM_IFACE_ENABLE:
-               len = sprintf(buf, "enabled");
+               len = sprintf(buf, "enabled\n");
                break;
        case ISCSI_NET_PARAM_IPV4_GW:
                memset(&gateway, 0, sizeof(gateway));
@@ -690,11 +690,9 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
 static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
 {
        int rc;
-       unsigned int tag, wrb_num;
-       unsigned short status, extd_status;
+       unsigned int tag;
        struct be_mcc_wrb *wrb;
        struct be_cmd_hba_name *resp;
-       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 
        tag = be_cmd_get_initname(phba);
        if (!tag) {
@@ -702,26 +700,16 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
                            "BS_%d : Getting Initiator Name Failed\n");
 
                return -EBUSY;
-       } else
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                               phba->ctrl.mcc_numtag[tag]);
-
-       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+       }
 
-       if (status || extd_status) {
+       rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+       if (rc) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BS_%d : MailBox Command Failed with "
-                           "status = %d extd_status = %d\n",
-                           status, extd_status);
-
-               free_mcc_tag(&phba->ctrl, tag);
-               return -EAGAIN;
+                           "BS_%d : Initiator Name MBX Failed\n");
+               return rc;
        }
-       wrb = queue_get_wrb(mccq, wrb_num);
-       free_mcc_tag(&phba->ctrl, tag);
+
        resp = embedded_payload(wrb);
        rc = sprintf(buf, "%s\n", resp->initiator_name);
        return rc;
@@ -731,7 +719,6 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
  * beiscsi_get_port_state - Get the Port State
  * @shost : pointer to scsi_host structure
  *
- * returns number of bytes
  */
 static void beiscsi_get_port_state(struct Scsi_Host *shost)
 {
@@ -750,13 +737,12 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost)
  */
 static int beiscsi_get_port_speed(struct Scsi_Host *shost)
 {
-       unsigned int tag, wrb_num;
-       unsigned short status, extd_status;
+       int rc;
+       unsigned int tag;
        struct be_mcc_wrb *wrb;
        struct be_cmd_ntwk_link_status_resp *resp;
        struct beiscsi_hba *phba = iscsi_host_priv(shost);
        struct iscsi_cls_host *ihost = shost->shost_data;
-       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 
        tag = be_cmd_get_port_speed(phba);
        if (!tag) {
@@ -764,26 +750,14 @@ static int beiscsi_get_port_speed(struct Scsi_Host *shost)
                            "BS_%d : Getting Port Speed Failed\n");
 
                 return -EBUSY;
-        } else
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                               phba->ctrl.mcc_numtag[tag]);
-
-       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-
-       if (status || extd_status) {
+       }
+       rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+       if (rc) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BS_%d : MailBox Command Failed with "
-                           "status = %d extd_status = %d\n",
-                           status, extd_status);
-
-               free_mcc_tag(&phba->ctrl, tag);
-               return -EAGAIN;
+                           "BS_%d : Port Speed MBX Failed\n");
+               return rc;
        }
-       wrb = queue_get_wrb(mccq, wrb_num);
-       free_mcc_tag(&phba->ctrl, tag);
        resp = embedded_payload(wrb);
 
        switch (resp->mac_speed) {
@@ -937,6 +911,14 @@ static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
                      session->initial_r2t_en);
        AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
                      session->imm_data_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params,
+                     data_seq_inorder, params,
+                     session->dataseq_inorder_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params,
+                     pdu_seq_inorder, params,
+                     session->pdu_inorder_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params,
+                     session->max_r2t);
        AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
                      (conn->exp_statsn - 1));
 }
@@ -1027,12 +1009,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
 {
        struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
        struct beiscsi_hba *phba = beiscsi_ep->phba;
-       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
        struct be_mcc_wrb *wrb;
        struct tcp_connect_and_offload_out *ptcpcnct_out;
-       unsigned short status, extd_status;
        struct be_dma_mem nonemb_cmd;
-       unsigned int tag, wrb_num;
+       unsigned int tag;
        int ret = -ENOMEM;
 
        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
@@ -1084,35 +1064,26 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
                pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                                    nonemb_cmd.va, nonemb_cmd.dma);
                return -EAGAIN;
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
        }
-       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-       if (status || extd_status) {
+
+       ret = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+       if (ret) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BS_%d : mgmt_open_connection Failed"
-                           " status = %d extd_status = %d\n",
-                           status, extd_status);
+                           "BS_%d : mgmt_open_connection Failed");
 
-               free_mcc_tag(&phba->ctrl, tag);
                pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
                goto free_ep;
-       } else {
-               wrb = queue_get_wrb(mccq, wrb_num);
-               free_mcc_tag(&phba->ctrl, tag);
-
-               ptcpcnct_out = embedded_payload(wrb);
-               beiscsi_ep = ep->dd_data;
-               beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
-               beiscsi_ep->cid_vld = 1;
-               beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
-                           "BS_%d : mgmt_open_connection Success\n");
        }
+
+       ptcpcnct_out = embedded_payload(wrb);
+       beiscsi_ep = ep->dd_data;
+       beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
+       beiscsi_ep->cid_vld = 1;
+       beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
+                   "BS_%d : mgmt_open_connection Success\n");
+
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
        return 0;
@@ -1150,8 +1121,8 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
 
        if (phba->state != BE_ADAPTER_UP) {
                ret = -EBUSY;
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-                           "BS_%d : The Adapter state is Not UP\n");
+               beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+                           "BS_%d : The Adapter Port state is Down!!!\n");
                return ERR_PTR(ret);
        }
 
@@ -1216,11 +1187,9 @@ static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
                            beiscsi_ep->ep_cid);
 
                ret = -EAGAIN;
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-               free_mcc_tag(&phba->ctrl, tag);
        }
+
+       ret = beiscsi_mccq_compl(phba, tag, NULL, NULL);
        return ret;
 }
 
@@ -1281,12 +1250,9 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
                            "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
                            beiscsi_ep->ep_cid);
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-               free_mcc_tag(&phba->ctrl, tag);
        }
 
+       beiscsi_mccq_compl(phba, tag, NULL, NULL);
        beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
        beiscsi_free_ep(beiscsi_ep);
        beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
index 8b826fc06bccd1355c81a6dc633d806e8a5d9601..38eab7232159dd7ec412e798a3a521cc8bab862f 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
index ff73f9500b01c43c3bdbbd210052fd651a8f3487..48d37dded8f16fbd64290aa599b187d54b9baef3 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -47,8 +47,6 @@
 static unsigned int be_iopoll_budget = 10;
 static unsigned int be_max_phys_size = 64;
 static unsigned int enable_msix = 1;
-static unsigned int gcrashmode = 0;
-static unsigned int num_hba = 0;
 
 MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
 MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
@@ -153,11 +151,54 @@ BEISCSI_RW_ATTR(log_enable, 0x00,
                "\t\t\t\tIO Path Events         : 0x10\n"
                "\t\t\t\tConfiguration Path     : 0x20\n");
 
+DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL);
+DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL);
 struct device_attribute *beiscsi_attrs[] = {
        &dev_attr_beiscsi_log_enable,
+       &dev_attr_beiscsi_drvr_ver,
+       &dev_attr_beiscsi_adapter_family,
        NULL,
 };
 
+static char const *cqe_desc[] = {
+       "RESERVED_DESC",
+       "SOL_CMD_COMPLETE",
+       "SOL_CMD_KILLED_DATA_DIGEST_ERR",
+       "CXN_KILLED_PDU_SIZE_EXCEEDS_DSL",
+       "CXN_KILLED_BURST_LEN_MISMATCH",
+       "CXN_KILLED_AHS_RCVD",
+       "CXN_KILLED_HDR_DIGEST_ERR",
+       "CXN_KILLED_UNKNOWN_HDR",
+       "CXN_KILLED_STALE_ITT_TTT_RCVD",
+       "CXN_KILLED_INVALID_ITT_TTT_RCVD",
+       "CXN_KILLED_RST_RCVD",
+       "CXN_KILLED_TIMED_OUT",
+       "CXN_KILLED_RST_SENT",
+       "CXN_KILLED_FIN_RCVD",
+       "CXN_KILLED_BAD_UNSOL_PDU_RCVD",
+       "CXN_KILLED_BAD_WRB_INDEX_ERROR",
+       "CXN_KILLED_OVER_RUN_RESIDUAL",
+       "CXN_KILLED_UNDER_RUN_RESIDUAL",
+       "CMD_KILLED_INVALID_STATSN_RCVD",
+       "CMD_KILLED_INVALID_R2T_RCVD",
+       "CMD_CXN_KILLED_LUN_INVALID",
+       "CMD_CXN_KILLED_ICD_INVALID",
+       "CMD_CXN_KILLED_ITT_INVALID",
+       "CMD_CXN_KILLED_SEQ_OUTOFORDER",
+       "CMD_CXN_KILLED_INVALID_DATASN_RCVD",
+       "CXN_INVALIDATE_NOTIFY",
+       "CXN_INVALIDATE_INDEX_NOTIFY",
+       "CMD_INVALIDATED_NOTIFY",
+       "UNSOL_HDR_NOTIFY",
+       "UNSOL_DATA_NOTIFY",
+       "UNSOL_DATA_DIGEST_ERROR_NOTIFY",
+       "DRIVERMSG_NOTIFY",
+       "CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN",
+       "SOL_CMD_KILLED_DIF_ERR",
+       "CXN_KILLED_SYN_RCVD",
+       "CXN_KILLED_IMM_DATA_RCVD"
+};
+
 static int beiscsi_slave_configure(struct scsi_device *sdev)
 {
        blk_queue_max_segment_size(sdev->request_queue, 65536);
@@ -226,11 +267,9 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
                                    nonemb_cmd.va, nonemb_cmd.dma);
 
                return FAILED;
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-               free_mcc_tag(&phba->ctrl, tag);
        }
+
+       beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
        return iscsi_eh_abort(sc);
@@ -301,11 +340,9 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
                pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                                    nonemb_cmd.va, nonemb_cmd.dma);
                return FAILED;
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-               free_mcc_tag(&phba->ctrl, tag);
        }
+
+       beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
        return iscsi_eh_device_reset(sc);
@@ -482,6 +519,7 @@ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
        { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
        { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
        { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
+       { PCI_DEVICE(ELX_VENDOR_ID, OC_SKH_ID1) },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
@@ -730,7 +768,7 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
                     resource_id) / 32] &
                     EQE_RESID_MASK) >> 16) == mcc->id) {
                        spin_lock_irqsave(&phba->isr_lock, flags);
-                       phba->todo_mcc_cq = 1;
+                       pbe_eq->todo_mcc_cq = true;
                        spin_unlock_irqrestore(&phba->isr_lock, flags);
                }
                AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
@@ -738,8 +776,8 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
                eqe = queue_tail_node(eq);
                num_eq_processed++;
        }
-       if (phba->todo_mcc_cq)
-               queue_work(phba->wq, &phba->work_cqs);
+       if (pbe_eq->todo_mcc_cq)
+               queue_work(phba->wq, &pbe_eq->work_cqs);
        if (num_eq_processed)
                hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
 
@@ -779,29 +817,26 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id)
                        eqe = queue_tail_node(eq);
                        num_eq_processed++;
                }
-               if (num_eq_processed)
-                       hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
-
-               return IRQ_HANDLED;
        } else {
                while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
                                                & EQE_VALID_MASK) {
                        spin_lock_irqsave(&phba->isr_lock, flags);
-                       phba->todo_cq = 1;
+                       pbe_eq->todo_cq = true;
                        spin_unlock_irqrestore(&phba->isr_lock, flags);
                        AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
                        queue_tail_inc(eq);
                        eqe = queue_tail_node(eq);
                        num_eq_processed++;
                }
-               if (phba->todo_cq)
-                       queue_work(phba->wq, &phba->work_cqs);
 
-               if (num_eq_processed)
-                       hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
-
-               return IRQ_HANDLED;
+               if (pbe_eq->todo_cq)
+                       queue_work(phba->wq, &pbe_eq->work_cqs);
        }
+
+       if (num_eq_processed)
+               hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
+
+       return IRQ_HANDLED;
 }
 
 /**
@@ -849,7 +884,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
                             resource_id) / 32] &
                             EQE_RESID_MASK) >> 16) == mcc->id) {
                                spin_lock_irqsave(&phba->isr_lock, flags);
-                               phba->todo_mcc_cq = 1;
+                               pbe_eq->todo_mcc_cq = true;
                                spin_unlock_irqrestore(&phba->isr_lock, flags);
                                num_mcceq_processed++;
                        } else {
@@ -862,8 +897,8 @@ static irqreturn_t be_isr(int irq, void *dev_id)
                        eqe = queue_tail_node(eq);
                }
                if (num_ioeq_processed || num_mcceq_processed) {
-                       if (phba->todo_mcc_cq)
-                               queue_work(phba->wq, &phba->work_cqs);
+                       if (pbe_eq->todo_mcc_cq)
+                               queue_work(phba->wq, &pbe_eq->work_cqs);
 
                        if ((num_mcceq_processed) && (!num_ioeq_processed))
                                hwi_ring_eq_db(phba, eq->id, 0,
@@ -886,11 +921,11 @@ static irqreturn_t be_isr(int irq, void *dev_id)
                             resource_id) / 32] &
                             EQE_RESID_MASK) >> 16) != cq->id) {
                                spin_lock_irqsave(&phba->isr_lock, flags);
-                               phba->todo_mcc_cq = 1;
+                               pbe_eq->todo_mcc_cq = true;
                                spin_unlock_irqrestore(&phba->isr_lock, flags);
                        } else {
                                spin_lock_irqsave(&phba->isr_lock, flags);
-                               phba->todo_cq = 1;
+                               pbe_eq->todo_cq = true;
                                spin_unlock_irqrestore(&phba->isr_lock, flags);
                        }
                        AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
@@ -898,8 +933,8 @@ static irqreturn_t be_isr(int irq, void *dev_id)
                        eqe = queue_tail_node(eq);
                        num_ioeq_processed++;
                }
-               if (phba->todo_cq || phba->todo_mcc_cq)
-                       queue_work(phba->wq, &phba->work_cqs);
+               if (pbe_eq->todo_cq || pbe_eq->todo_mcc_cq)
+                       queue_work(phba->wq, &pbe_eq->work_cqs);
 
                if (num_ioeq_processed) {
                        hwi_ring_eq_db(phba, eq->id, 0,
@@ -1211,7 +1246,8 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 
 static void
 be_complete_io(struct beiscsi_conn *beiscsi_conn,
-              struct iscsi_task *task, struct sol_cqe *psol)
+               struct iscsi_task *task,
+               struct common_sol_cqe *csol_cqe)
 {
        struct beiscsi_io_task *io_task = task->dd_data;
        struct be_status_bhs *sts_bhs =
@@ -1221,20 +1257,14 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
        u32 resid = 0, exp_cmdsn, max_cmdsn;
        u8 rsp, status, flags;
 
-       exp_cmdsn = (psol->
-                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                       & SOL_EXP_CMD_SN_MASK);
-       max_cmdsn = ((psol->
-                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                       & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                               / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
-       rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32]
-                                               & SOL_RESP_MASK) >> 16);
-       status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32]
-                                               & SOL_STS_MASK) >> 8);
-       flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
+       exp_cmdsn = csol_cqe->exp_cmdsn;
+       max_cmdsn = (csol_cqe->exp_cmdsn +
+                    csol_cqe->cmd_wnd - 1);
+       rsp = csol_cqe->i_resp;
+       status = csol_cqe->i_sts;
+       flags = csol_cqe->i_flags;
+       resid = csol_cqe->res_cnt;
+
        if (!task->sc) {
                if (io_task->scsi_cmnd)
                        scsi_dma_unmap(io_task->scsi_cmnd);
@@ -1249,9 +1279,6 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
 
        /* bidi not initially supported */
        if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) {
-               resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) /
-                               32] & SOL_RES_CNT_MASK);
-
                if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))
                        task->sc->result = DID_ERROR << 16;
 
@@ -1273,13 +1300,8 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
                       min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
        }
 
-       if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
-               if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
-                                                       & SOL_RES_CNT_MASK)
-                        conn->rxdata_octets += (psol->
-                            dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
-                            & SOL_RES_CNT_MASK);
-       }
+       if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ)
+               conn->rxdata_octets += resid;
 unmap:
        scsi_dma_unmap(io_task->scsi_cmnd);
        iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
@@ -1287,7 +1309,8 @@ unmap:
 
 static void
 be_complete_logout(struct beiscsi_conn *beiscsi_conn,
-                  struct iscsi_task *task, struct sol_cqe *psol)
+                   struct iscsi_task *task,
+                   struct common_sol_cqe *csol_cqe)
 {
        struct iscsi_logout_rsp *hdr;
        struct beiscsi_io_task *io_task = task->dd_data;
@@ -1297,18 +1320,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
        hdr->opcode = ISCSI_OP_LOGOUT_RSP;
        hdr->t2wait = 5;
        hdr->t2retain = 0;
-       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
-       hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
-                                       32] & SOL_RESP_MASK);
-       hdr->exp_cmdsn = cpu_to_be32(psol->
-                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                                       & SOL_EXP_CMD_SN_MASK);
-       hdr->max_cmdsn = be32_to_cpu((psol->
-                        dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                                       & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->flags = csol_cqe->i_flags;
+       hdr->response = csol_cqe->i_resp;
+       hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
+       hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1);
+
        hdr->dlength[0] = 0;
        hdr->dlength[1] = 0;
        hdr->dlength[2] = 0;
@@ -1319,7 +1335,8 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
 
 static void
 be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
-               struct iscsi_task *task, struct sol_cqe *psol)
+                struct iscsi_task *task,
+                struct common_sol_cqe *csol_cqe)
 {
        struct iscsi_tm_rsp *hdr;
        struct iscsi_conn *conn = beiscsi_conn->conn;
@@ -1327,16 +1344,12 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
 
        hdr = (struct iscsi_tm_rsp *)task->hdr;
        hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
-       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
-       hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
-                                       32] & SOL_RESP_MASK);
-       hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
-                                   i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
-       hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
-                       i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->flags = csol_cqe->i_flags;
+       hdr->response = csol_cqe->i_resp;
+       hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
+       hdr->max_cmdsn = (csol_cqe->exp_cmdsn +
+                         csol_cqe->cmd_wnd - 1);
+
        hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
@@ -1352,15 +1365,24 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
        struct beiscsi_io_task *io_task;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
+       uint16_t wrb_index, cid;
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[((psol->
-                               dw[offsetof(struct amap_sol_cqe, cid) / 32] &
-                               SOL_CID_MASK) >> 6) -
-                               phba->fw_config.iscsi_cid_start];
-       pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
-                               dw[offsetof(struct amap_sol_cqe, wrb_index) /
-                               32] & SOL_WRB_INDEX_MASK) >> 16)];
+       if (chip_skh_r(phba->pcidev)) {
+               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+                                         wrb_idx, psol);
+               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+                                   cid, psol);
+       } else {
+               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+                                         wrb_idx, psol);
+               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+                                   cid, psol);
+       }
+
+       pwrb_context = &phwi_ctrlr->wrb_context[
+                       cid - phba->fw_config.iscsi_cid_start];
+       pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];
        task = pwrb_handle->pio_handle;
 
        io_task = task->dd_data;
@@ -1374,26 +1396,78 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
 
 static void
 be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
-                      struct iscsi_task *task, struct sol_cqe *psol)
+                       struct iscsi_task *task,
+                       struct common_sol_cqe *csol_cqe)
 {
        struct iscsi_nopin *hdr;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct beiscsi_io_task *io_task = task->dd_data;
 
        hdr = (struct iscsi_nopin *)task->hdr;
-       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-                       & SOL_FLAGS_MASK) >> 24) | 0x80;
-       hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
-                                    i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
-       hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
-                       i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->flags = csol_cqe->i_flags;
+       hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+       hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn +
+                        csol_cqe->cmd_wnd - 1);
+
        hdr->opcode = ISCSI_OP_NOOP_IN;
        hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
 
+static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
+               struct sol_cqe *psol,
+               struct common_sol_cqe *csol_cqe)
+{
+       if (chip_skh_r(phba->pcidev)) {
+               csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                   i_exp_cmd_sn, psol);
+               csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                 i_res_cnt, psol);
+               csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                   wrb_index, psol);
+               csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                             cid, psol);
+               csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                hw_sts, psol);
+               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_cmd_wnd, psol);
+               if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                 cmd_cmpl, psol))
+                       csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                       i_sts, psol);
+               else
+                       csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                        i_sts, psol);
+               if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                 u, psol))
+                       csol_cqe->i_flags = ISCSI_FLAG_CMD_UNDERFLOW;
+
+               if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                 o, psol))
+                       csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW;
+       } else {
+               csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                   i_exp_cmd_sn, psol);
+               csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_res_cnt, psol);
+               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_cmd_wnd, psol);
+               csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                   wrb_index, psol);
+               csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
+                                             cid, psol);
+               csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                hw_sts, psol);
+               csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                i_resp, psol);
+               csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+                                               i_sts, psol);
+               csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_flags, psol);
+       }
+}
+
+
 static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                             struct beiscsi_hba *phba, struct sol_cqe *psol)
 {
@@ -1405,19 +1479,22 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
        unsigned int type;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
+       struct common_sol_cqe csol_cqe = {0};
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof
-                               (struct amap_sol_cqe, cid) / 32]
-                               & SOL_CID_MASK) >> 6) -
-                               phba->fw_config.iscsi_cid_start];
-       pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
-                               dw[offsetof(struct amap_sol_cqe, wrb_index) /
-                               32] & SOL_WRB_INDEX_MASK) >> 16)];
+
+       /* Copy the elements to a common structure */
+       adapter_get_sol_cqe(phba, psol, &csol_cqe);
+
+       pwrb_context = &phwi_ctrlr->wrb_context[
+                       csol_cqe.cid - phba->fw_config.iscsi_cid_start];
+
+       pwrb_handle = pwrb_context->pwrb_handle_basestd[
+                     csol_cqe.wrb_index];
+
        task = pwrb_handle->pio_handle;
        pwrb = pwrb_handle->pwrb;
-       type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
-                                WRB_TYPE_MASK) >> 28;
+       type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type;
 
        spin_lock_bh(&session->lock);
        switch (type) {
@@ -1425,17 +1502,16 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
        case HWH_TYPE_IO_RD:
                if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
                     ISCSI_OP_NOOP_OUT)
-                       be_complete_nopin_resp(beiscsi_conn, task, psol);
+                       be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);
                else
-                       be_complete_io(beiscsi_conn, task, psol);
+                       be_complete_io(beiscsi_conn, task, &csol_cqe);
                break;
 
        case HWH_TYPE_LOGOUT:
                if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
-                       be_complete_logout(beiscsi_conn, task, psol);
+                       be_complete_logout(beiscsi_conn, task, &csol_cqe);
                else
-                       be_complete_tmf(beiscsi_conn, task, psol);
-
+                       be_complete_tmf(beiscsi_conn, task, &csol_cqe);
                break;
 
        case HWH_TYPE_LOGIN:
@@ -1446,7 +1522,7 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                break;
 
        case HWH_TYPE_NOP:
-               be_complete_nopin_resp(beiscsi_conn, task, psol);
+               be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);
                break;
 
        default:
@@ -1454,10 +1530,8 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
                            "BM_%d : In hwi_complete_cmd, unknown type = %d"
                            "wrb_index 0x%x CID 0x%x\n", type,
-                           ((psol->dw[offsetof(struct amap_iscsi_wrb,
-                           type) / 32] & SOL_WRB_INDEX_MASK) >> 16),
-                           ((psol->dw[offsetof(struct amap_sol_cqe,
-                           cid) / 32] & SOL_CID_MASK) >> 6));
+                           csol_cqe.wrb_index,
+                           csol_cqe.cid);
                break;
        }
 
@@ -1485,13 +1559,26 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        struct list_head *pbusy_list;
        struct async_pdu_handle *pasync_handle = NULL;
        unsigned char is_header = 0;
+       unsigned int index, dpl;
+
+       if (chip_skh_r(phba->pcidev)) {
+               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+                                   dpl, pdpdu_cqe);
+               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+                                     index, pdpdu_cqe);
+       } else {
+               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+                                   dpl, pdpdu_cqe);
+               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+                                     index, pdpdu_cqe);
+       }
 
        phys_addr.u.a32.address_lo =
-           pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] -
-           ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
-                                               & PDUCQE_DPL_MASK) >> 16);
+               (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                                       db_addr_lo) / 32] - dpl);
        phys_addr.u.a32.address_hi =
-           pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32];
+               pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                                      db_addr_hi) / 32];
 
        phys_addr.u.a64.address =
                        *((unsigned long long *)(&phys_addr.u.a64.address));
@@ -1501,14 +1588,12 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        case UNSOL_HDR_NOTIFY:
                is_header = 1;
 
-               pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
-                       (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
-                       index) / 32] & PDUCQE_INDEX_MASK));
+                pbusy_list = hwi_get_async_busy_list(pasync_ctx,
+                                                     is_header, index);
                break;
        case UNSOL_DATA_NOTIFY:
-               pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
-                                       dw[offsetof(struct amap_i_t_dpdu_cqe,
-                                       index) / 32] & PDUCQE_INDEX_MASK));
+                pbusy_list = hwi_get_async_busy_list(pasync_ctx,
+                                                     is_header, index);
                break;
        default:
                pbusy_list = NULL;
@@ -1531,12 +1616,9 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid -
                                             phba->fw_config.iscsi_cid_start;
        pasync_handle->is_header = is_header;
-       pasync_handle->buffer_len = ((pdpdu_cqe->
-                       dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
-                       & PDUCQE_DPL_MASK) >> 16);
+       pasync_handle->buffer_len = dpl;
+       *pcq_index = index;
 
-       *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
-                       index) / 32] & PDUCQE_INDEX_MASK);
        return pasync_handle;
 }
 
@@ -1914,6 +1996,13 @@ static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
 
 }
 
+/**
+ * beiscsi_process_cq()- Process the Completion Queue
+ * @pbe_eq: Event Q on which the Completion has come
+ *
+ * return
+ *     Number of Completion Entries processed.
+ **/
 static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 {
        struct be_queue_info *cq;
@@ -1935,12 +2024,24 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
               CQE_VALID_MASK) {
                be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
 
-               cid = ((sol->dw[offsetof(struct amap_sol_cqe, cid)/32] &
-                     CQE_CID_MASK) >> 6);
-               code = (sol->dw[offsetof(struct amap_sol_cqe, code)/32] &
-                      CQE_CODE_MASK);
-               ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
+                code = (sol->dw[offsetof(struct amap_sol_cqe, code) /
+                        32] & CQE_CODE_MASK);
+
+                /* Get the CID */
+               if (chip_skh_r(phba->pcidev)) {
+                       if ((code == DRIVERMSG_NOTIFY) ||
+                           (code == UNSOL_HDR_NOTIFY) ||
+                           (code == UNSOL_DATA_NOTIFY))
+                               cid = AMAP_GET_BITS(
+                                                   struct amap_i_t_dpdu_cqe_v2,
+                                                   cid, sol);
+                        else
+                                cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                    cid, sol);
+                  } else
+                        cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
 
+               ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
                beiscsi_ep = ep->dd_data;
                beiscsi_conn = beiscsi_ep->conn;
 
@@ -1958,7 +2059,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case DRIVERMSG_NOTIFY:
                        beiscsi_log(phba, KERN_INFO,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : Received DRIVERMSG_NOTIFY\n");
+                                   "BM_%d : Received %s[%d] on CID : %d\n",
+                                   cqe_desc[code], code, cid);
 
                        dmsg = (struct dmsg_cqe *)sol;
                        hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);
@@ -1966,7 +2068,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case UNSOL_HDR_NOTIFY:
                        beiscsi_log(phba, KERN_INFO,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : Received UNSOL_HDR_ NOTIFY\n");
+                                   "BM_%d : Received %s[%d] on CID : %d\n",
+                                   cqe_desc[code], code, cid);
 
                        hwi_process_default_pdu_ring(beiscsi_conn, phba,
                                             (struct i_t_dpdu_cqe *)sol);
@@ -1974,7 +2077,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case UNSOL_DATA_NOTIFY:
                        beiscsi_log(phba, KERN_INFO,
                                    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
-                                   "BM_%d : Received UNSOL_DATA_NOTIFY\n");
+                                   "BM_%d : Received %s[%d] on CID : %d\n",
+                                   cqe_desc[code], code, cid);
 
                        hwi_process_default_pdu_ring(beiscsi_conn, phba,
                                             (struct i_t_dpdu_cqe *)sol);
@@ -1984,8 +2088,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case CXN_INVALIDATE_NOTIFY:
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : Ignoring CQ Error notification for"
-                                   " cmd/cxn invalidate\n");
+                                   "BM_%d : Ignoring %s[%d] on CID : %d\n",
+                                   cqe_desc[code], code, cid);
                        break;
                case SOL_CMD_KILLED_DATA_DIGEST_ERR:
                case CMD_KILLED_INVALID_STATSN_RCVD:
@@ -1997,14 +2101,14 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case CMD_CXN_KILLED_INVALID_DATASN_RCVD:
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
-                                   "BM_%d : CQ Error notification for cmd.. "
-                                   "code %d cid 0x%x\n", code, cid);
+                                   "BM_%d : Cmd Notification %s[%d] on CID : %d\n",
+                                   cqe_desc[code], code,  cid);
                        break;
                case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : Digest error on def pdu ring,"
-                                   " dropping..\n");
+                                   "BM_%d :  Dropping %s[%d] on DPDU ring on CID : %d\n",
+                                   cqe_desc[code], code, cid);
                        hwi_flush_default_pdu_buffer(phba, beiscsi_conn,
                                             (struct i_t_dpdu_cqe *) sol);
                        break;
@@ -2017,6 +2121,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case CXN_KILLED_INVALID_ITT_TTT_RCVD:
                case CXN_KILLED_TIMED_OUT:
                case CXN_KILLED_FIN_RCVD:
+               case CXN_KILLED_RST_SENT:
+               case CXN_KILLED_RST_RCVD:
                case CXN_KILLED_BAD_UNSOL_PDU_RCVD:
                case CXN_KILLED_BAD_WRB_INDEX_ERROR:
                case CXN_KILLED_OVER_RUN_RESIDUAL:
@@ -2024,19 +2130,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN:
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : CQ Error %d, reset CID 0x%x...\n",
-                                   code, cid);
-                       if (beiscsi_conn)
-                               iscsi_conn_failure(beiscsi_conn->conn,
-                                                  ISCSI_ERR_CONN_FAILED);
-                       break;
-               case CXN_KILLED_RST_SENT:
-               case CXN_KILLED_RST_RCVD:
-                       beiscsi_log(phba, KERN_ERR,
-                                   BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : CQ Error %d, reset"
-                                   "received/sent on CID 0x%x...\n",
-                                   code, cid);
+                                   "BM_%d : Event %s[%d] received on CID : %d\n",
+                                   cqe_desc[code], code, cid);
                        if (beiscsi_conn)
                                iscsi_conn_failure(beiscsi_conn->conn,
                                                   ISCSI_ERR_CONN_FAILED);
@@ -2044,8 +2139,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                default:
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                                   "BM_%d : CQ Error Invalid code= %d "
-                                   "received on CID 0x%x...\n",
+                                   "BM_%d : Invalid CQE Event Received Code : %d"
+                                   "CID 0x%x...\n",
                                    code, cid);
                        break;
                }
@@ -2068,30 +2163,30 @@ void beiscsi_process_all_cqs(struct work_struct *work)
        unsigned long flags;
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
-       struct be_eq_obj *pbe_eq;
-       struct beiscsi_hba *phba =
-           container_of(work, struct beiscsi_hba, work_cqs);
+       struct beiscsi_hba *phba;
+       struct be_eq_obj *pbe_eq =
+           container_of(work, struct be_eq_obj, work_cqs);
 
+       phba = pbe_eq->phba;
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
-       if (phba->msix_enabled)
-               pbe_eq = &phwi_context->be_eq[phba->num_cpus];
-       else
-               pbe_eq = &phwi_context->be_eq[0];
 
-       if (phba->todo_mcc_cq) {
+       if (pbe_eq->todo_mcc_cq) {
                spin_lock_irqsave(&phba->isr_lock, flags);
-               phba->todo_mcc_cq = 0;
+               pbe_eq->todo_mcc_cq = false;
                spin_unlock_irqrestore(&phba->isr_lock, flags);
                beiscsi_process_mcc_isr(phba);
        }
 
-       if (phba->todo_cq) {
+       if (pbe_eq->todo_cq) {
                spin_lock_irqsave(&phba->isr_lock, flags);
-               phba->todo_cq = 0;
+               pbe_eq->todo_cq = false;
                spin_unlock_irqrestore(&phba->isr_lock, flags);
                beiscsi_process_cq(pbe_eq);
        }
+
+       /* rearm EQ for further interrupts */
+       hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
 }
 
 static int be_iopoll(struct blk_iopoll *iop, int budget)
@@ -2114,6 +2209,101 @@ static int be_iopoll(struct blk_iopoll *iop, int budget)
        return ret;
 }
 
+static void
+hwi_write_sgl_v2(struct iscsi_wrb *pwrb, struct scatterlist *sg,
+                 unsigned int num_sg, struct beiscsi_io_task *io_task)
+{
+       struct iscsi_sge *psgl;
+       unsigned int sg_len, index;
+       unsigned int sge_len = 0;
+       unsigned long long addr;
+       struct scatterlist *l_sg;
+       unsigned int offset;
+
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_lo, pwrb,
+                     io_task->bhs_pa.u.a32.address_lo);
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_hi, pwrb,
+                     io_task->bhs_pa.u.a32.address_hi);
+
+       l_sg = sg;
+       for (index = 0; (index < num_sg) && (index < 2); index++,
+                       sg = sg_next(sg)) {
+               if (index == 0) {
+                       sg_len = sg_dma_len(sg);
+                       addr = (u64) sg_dma_address(sg);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                     sge0_addr_lo, pwrb,
+                                     lower_32_bits(addr));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                     sge0_addr_hi, pwrb,
+                                     upper_32_bits(addr));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                     sge0_len, pwrb,
+                                     sg_len);
+                       sge_len = sg_len;
+               } else {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_r2t_offset,
+                                     pwrb, sge_len);
+                       sg_len = sg_dma_len(sg);
+                       addr = (u64) sg_dma_address(sg);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                     sge1_addr_lo, pwrb,
+                                     lower_32_bits(addr));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                     sge1_addr_hi, pwrb,
+                                     upper_32_bits(addr));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                     sge1_len, pwrb,
+                                     sg_len);
+               }
+       }
+       psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
+       memset(psgl, 0, sizeof(*psgl) * BE2_SGE);
+
+       AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2);
+
+       AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+                     io_task->bhs_pa.u.a32.address_hi);
+       AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+                     io_task->bhs_pa.u.a32.address_lo);
+
+       if (num_sg == 1) {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb,
+                             1);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb,
+                             0);
+       } else if (num_sg == 2) {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb,
+                             0);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb,
+                             1);
+       } else {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb,
+                             0);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb,
+                             0);
+       }
+
+       sg = l_sg;
+       psgl++;
+       psgl++;
+       offset = 0;
+       for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) {
+               sg_len = sg_dma_len(sg);
+               addr = (u64) sg_dma_address(sg);
+               AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+                             lower_32_bits(addr));
+               AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+                             upper_32_bits(addr));
+               AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len);
+               AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset);
+               AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
+               offset += sg_len;
+       }
+       psgl--;
+       AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
+}
+
 static void
 hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
              unsigned int num_sg, struct beiscsi_io_task *io_task)
@@ -2202,13 +2392,18 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
        AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
 }
 
+/**
+ * hwi_write_buffer()- Populate the WRB with task info
+ * @pwrb: ptr to the WRB entry
+ * @task: iscsi task which is to be executed
+ **/
 static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
 {
        struct iscsi_sge *psgl;
-       unsigned long long addr;
        struct beiscsi_io_task *io_task = task->dd_data;
        struct beiscsi_conn *beiscsi_conn = io_task->conn;
        struct beiscsi_hba *phba = beiscsi_conn->phba;
+       uint8_t dsp_value = 0;
 
        io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2;
        AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
@@ -2217,26 +2412,38 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
                                io_task->bhs_pa.u.a32.address_hi);
 
        if (task->data) {
-               if (task->data_count) {
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
-                       addr = (u64) pci_map_single(phba->pcidev,
-                                                   task->data,
-                                                   task->data_count, 1);
-               } else {
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
-                       addr = 0;
-               }
+
+               /* Check for the data_count */
+               dsp_value = (task->data_count) ? 1 : 0;
+
+               if (chip_skh_r(phba->pcidev))
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp,
+                                     pwrb, dsp_value);
+               else
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp,
+                                     pwrb, dsp_value);
+
+               /* Map addr only if there is data_count */
+               if (dsp_value) {
+                       io_task->mtask_addr = pci_map_single(phba->pcidev,
+                                                            task->data,
+                                                            task->data_count,
+                                                            PCI_DMA_TODEVICE);
+                       io_task->mtask_data_count = task->data_count;
+               } else
+                       io_task->mtask_addr = 0;
+
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
-                                               ((u32)(addr & 0xFFFFFFFF)));
+                             lower_32_bits(io_task->mtask_addr));
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
-                                               ((u32)(addr >> 32)));
+                             upper_32_bits(io_task->mtask_addr));
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
                                                task->data_count);
 
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1);
        } else {
                AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
-               addr = 0;
+               io_task->mtask_addr = 0;
        }
 
        psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
@@ -2259,9 +2466,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
                psgl++;
                if (task->data) {
                        AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
-                                               ((u32)(addr & 0xFFFFFFFF)));
+                                     lower_32_bits(io_task->mtask_addr));
                        AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
-                                               ((u32)(addr >> 32)));
+                                     upper_32_bits(io_task->mtask_addr));
                }
                AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
        }
@@ -2843,7 +3050,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
        }
        return 0;
 create_eq_error:
-       for (i = 0; i < (phba->num_cpus + 1); i++) {
+       for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {
                eq = &phwi_context->be_eq[i].q;
                mem = &eq->dma_mem;
                if (mem->va)
@@ -3268,15 +3475,31 @@ err:
        return -ENOMEM;
 }
 
-static int find_num_cpus(void)
+/**
+ * find_num_cpus()- Get the CPU online count
+ * @phba: ptr to priv structure
+ *
+ * CPU count is used for creating EQ.
+ **/
+static void find_num_cpus(struct beiscsi_hba *phba)
 {
        int  num_cpus = 0;
 
        num_cpus = num_online_cpus();
-       if (num_cpus >= MAX_CPUS)
-               num_cpus = MAX_CPUS - 1;
 
-       return num_cpus;
+       switch (phba->generation) {
+       case BE_GEN2:
+       case BE_GEN3:
+               phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ?
+                                 BEISCSI_MAX_NUM_CPUS : num_cpus;
+               break;
+       case BE_GEN4:
+               phba->num_cpus = (num_cpus > OC_SKH_MAX_NUM_CPUS) ?
+                                 OC_SKH_MAX_NUM_CPUS : num_cpus;
+               break;
+       default:
+               phba->num_cpus = 1;
+       }
 }
 
 static int hwi_init_port(struct beiscsi_hba *phba)
@@ -3644,12 +3867,9 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
 static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 {
        struct be_cmd_get_session_resp *session_resp;
-       struct be_mcc_wrb *wrb;
        struct be_dma_mem nonemb_cmd;
-       unsigned int tag, wrb_num;
-       unsigned short status, extd_status;
+       unsigned int tag;
        unsigned int s_handle;
-       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
        int ret = -ENOMEM;
 
        /* Get the session handle of the boot target */
@@ -3682,25 +3902,16 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
                            " Failed\n");
 
                goto boot_freemem;
-       } else
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
+       }
 
-       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-       if (status || extd_status) {
+       ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
+       if (ret) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-                           "BM_%d : beiscsi_get_session_info Failed"
-                           " status = %d extd_status = %d\n",
-                           status, extd_status);
-
-               free_mcc_tag(&phba->ctrl, tag);
+                           "BM_%d : beiscsi_get_session_info Failed");
                goto boot_freemem;
        }
-       wrb = queue_get_wrb(mccq, wrb_num);
-       free_mcc_tag(&phba->ctrl, tag);
+
        session_resp = nonemb_cmd.va ;
 
        memcpy(&phba->boot_sess, &session_resp->session_info,
@@ -3853,6 +4064,11 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
        kfree(phba->ep_array);
 }
 
+/**
+ * beiscsi_cleanup_task()- Free driver resources of the task
+ * @task: ptr to the iscsi task
+ *
+ **/
 static void beiscsi_cleanup_task(struct iscsi_task *task)
 {
        struct beiscsi_io_task *io_task = task->dd_data;
@@ -3900,6 +4116,13 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
                                spin_unlock(&phba->mgmt_sgl_lock);
                                io_task->psgl_handle = NULL;
                        }
+                       if (io_task->mtask_addr) {
+                               pci_unmap_single(phba->pcidev,
+                                                io_task->mtask_addr,
+                                                io_task->mtask_data_count,
+                                                PCI_DMA_TODEVICE);
+                               io_task->mtask_addr = 0;
+                       }
                }
        }
 }
@@ -3909,8 +4132,6 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
                           struct beiscsi_offload_params *params)
 {
        struct wrb_handle *pwrb_handle;
-       struct iscsi_target_context_update_wrb *pwrb = NULL;
-       struct be_mem_descriptor *mem_descr;
        struct beiscsi_hba *phba = beiscsi_conn->phba;
        struct iscsi_task *task = beiscsi_conn->task;
        struct iscsi_session *session = task->conn->session;
@@ -3927,67 +4148,16 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
 
        pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
                                       phba->fw_config.iscsi_cid_start));
-       pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
-       memset(pwrb, 0, sizeof(*pwrb));
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-                     max_burst_length, pwrb, params->dw[offsetof
-                     (struct amap_beiscsi_offload_params,
-                     max_burst_length) / 32]);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-                     max_send_data_segment_length, pwrb,
-                     params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     max_send_data_segment_length) / 32]);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-                     first_burst_length,
-                     pwrb,
-                     params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     first_burst_length) / 32]);
-
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
-                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     erl) / 32] & OFFLD_PARAMS_ERL));
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
-                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
-                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
-                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
-                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
-                      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
-                     pwrb,
-                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
-                     exp_statsn) / 32] + 1));
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
-                     0x7);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
-                     pwrb, pwrb_handle->wrb_index);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
-                     pwrb, pwrb_handle->nxt_wrb_index);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-                       session_state, pwrb, 0);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
-                     pwrb, 1);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
-                     pwrb, 0);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
-                     0);
 
-       mem_descr = phba->init_mem;
-       mem_descr += ISCSI_MEM_GLOBAL_HEADER;
-
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-                       pad_buffer_addr_hi, pwrb,
-                     mem_descr->mem_array[0].bus_address.u.a32.address_hi);
-       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-                       pad_buffer_addr_lo, pwrb,
-                     mem_descr->mem_array[0].bus_address.u.a32.address_lo);
+       /* Check for the adapter family */
+       if (chip_skh_r(phba->pcidev))
+               beiscsi_offload_cxn_v2(params, pwrb_handle);
+       else
+               beiscsi_offload_cxn_v0(params, pwrb_handle,
+                                      phba->init_mem);
 
-       be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb));
+       be_dws_le_to_cpu(pwrb_handle->pwrb,
+                        sizeof(struct iscsi_target_context_update_wrb));
 
        doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
        doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK)
@@ -4044,13 +4214,25 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                spin_lock(&phba->io_sgl_lock);
                io_task->psgl_handle = alloc_io_sgl_handle(phba);
                spin_unlock(&phba->io_sgl_lock);
-               if (!io_task->psgl_handle)
+               if (!io_task->psgl_handle) {
+                       beiscsi_log(phba, KERN_ERR,
+                                   BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
+                                   "BM_%d : Alloc of IO_SGL_ICD Failed"
+                                   "for the CID : %d\n",
+                                   beiscsi_conn->beiscsi_conn_cid);
                        goto free_hndls;
+               }
                io_task->pwrb_handle = alloc_wrb_handle(phba,
                                        beiscsi_conn->beiscsi_conn_cid -
                                        phba->fw_config.iscsi_cid_start);
-               if (!io_task->pwrb_handle)
+               if (!io_task->pwrb_handle) {
+                       beiscsi_log(phba, KERN_ERR,
+                                   BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
+                                   "BM_%d : Alloc of WRB_HANDLE Failed"
+                                   "for the CID : %d\n",
+                                   beiscsi_conn->beiscsi_conn_cid);
                        goto free_io_hndls;
+               }
        } else {
                io_task->scsi_cmnd = NULL;
                if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
@@ -4059,8 +4241,16 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                io_task->psgl_handle = (struct sgl_handle *)
                                                alloc_mgmt_sgl_handle(phba);
                                spin_unlock(&phba->mgmt_sgl_lock);
-                               if (!io_task->psgl_handle)
+                               if (!io_task->psgl_handle) {
+                                       beiscsi_log(phba, KERN_ERR,
+                                                   BEISCSI_LOG_IO |
+                                                   BEISCSI_LOG_CONFIG,
+                                                   "BM_%d : Alloc of MGMT_SGL_ICD Failed"
+                                                   "for the CID : %d\n",
+                                                   beiscsi_conn->
+                                                   beiscsi_conn_cid);
                                        goto free_hndls;
+                               }
 
                                beiscsi_conn->login_in_progress = 1;
                                beiscsi_conn->plogin_sgl_handle =
@@ -4069,8 +4259,16 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                        alloc_wrb_handle(phba,
                                        beiscsi_conn->beiscsi_conn_cid -
                                        phba->fw_config.iscsi_cid_start);
-                               if (!io_task->pwrb_handle)
-                                       goto free_io_hndls;
+                               if (!io_task->pwrb_handle) {
+                                       beiscsi_log(phba, KERN_ERR,
+                                                   BEISCSI_LOG_IO |
+                                                   BEISCSI_LOG_CONFIG,
+                                                   "BM_%d : Alloc of WRB_HANDLE Failed"
+                                                   "for the CID : %d\n",
+                                                   beiscsi_conn->
+                                                   beiscsi_conn_cid);
+                                       goto free_mgmt_hndls;
+                               }
                                beiscsi_conn->plogin_wrb_handle =
                                                        io_task->pwrb_handle;
 
@@ -4085,14 +4283,28 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        spin_lock(&phba->mgmt_sgl_lock);
                        io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
                        spin_unlock(&phba->mgmt_sgl_lock);
-                       if (!io_task->psgl_handle)
+                       if (!io_task->psgl_handle) {
+                               beiscsi_log(phba, KERN_ERR,
+                                           BEISCSI_LOG_IO |
+                                           BEISCSI_LOG_CONFIG,
+                                           "BM_%d : Alloc of MGMT_SGL_ICD Failed"
+                                           "for the CID : %d\n",
+                                           beiscsi_conn->
+                                           beiscsi_conn_cid);
                                goto free_hndls;
+                       }
                        io_task->pwrb_handle =
                                        alloc_wrb_handle(phba,
                                        beiscsi_conn->beiscsi_conn_cid -
                                        phba->fw_config.iscsi_cid_start);
-                       if (!io_task->pwrb_handle)
+                       if (!io_task->pwrb_handle) {
+                               beiscsi_log(phba, KERN_ERR,
+                                           BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
+                                           "BM_%d : Alloc of WRB_HANDLE Failed"
+                                           "for the CID : %d\n",
+                                           beiscsi_conn->beiscsi_conn_cid);
                                goto free_mgmt_hndls;
+                       }
 
                }
        }
@@ -4124,11 +4336,64 @@ free_hndls:
        pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
                      io_task->bhs_pa.u.a64.address);
        io_task->cmd_bhs = NULL;
-       beiscsi_log(phba, KERN_ERR,
-                   BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-                   "BM_%d : Alloc of SGL_ICD Failed\n");
        return -ENOMEM;
 }
+int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
+                      unsigned int num_sg, unsigned int xferlen,
+                      unsigned int writedir)
+{
+
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct iscsi_conn *conn = task->conn;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       struct iscsi_wrb *pwrb = NULL;
+       unsigned int doorbell = 0;
+
+       pwrb = io_task->pwrb_handle->pwrb;
+       memset(pwrb, 0, sizeof(*pwrb));
+
+       io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
+       io_task->bhs_len = sizeof(struct be_cmd_bhs);
+
+       if (writedir) {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb,
+                             INI_WR_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 1);
+       } else {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb,
+                             INI_RD_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 0);
+       }
+
+       io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb_v2,
+                                         type, pwrb);
+
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, lun, pwrb,
+                     cpu_to_be16(*(unsigned short *)
+                     &io_task->cmd_bhs->iscsi_hdr.lun));
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, xferlen);
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
+                     io_task->pwrb_handle->wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
+                     be32_to_cpu(task->cmdsn));
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
+                     io_task->psgl_handle->sgl_index);
+
+       hwi_write_sgl_v2(pwrb, sg, num_sg, io_task);
+       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
+                     io_task->pwrb_handle->nxt_wrb_index);
+
+       be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
+
+       doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
+       doorbell |= (io_task->pwrb_handle->wrb_index &
+                    DB_DEF_PDU_WRB_INDEX_MASK) <<
+                    DB_DEF_PDU_WRB_INDEX_SHIFT;
+       doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
+       iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
+       return 0;
+}
 
 static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
                          unsigned int num_sg, unsigned int xferlen,
@@ -4156,6 +4421,9 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
                AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
        }
 
+       io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb,
+                                         type, pwrb);
+
        AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
                      cpu_to_be16(*(unsigned short *)
                                  &io_task->cmd_bhs->iscsi_hdr.lun));
@@ -4191,55 +4459,75 @@ static int beiscsi_mtask(struct iscsi_task *task)
        struct iscsi_wrb *pwrb = NULL;
        unsigned int doorbell = 0;
        unsigned int cid;
+       unsigned int pwrb_typeoffset = 0;
 
        cid = beiscsi_conn->beiscsi_conn_cid;
        pwrb = io_task->pwrb_handle->pwrb;
        memset(pwrb, 0, sizeof(*pwrb));
-       AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
-                     be32_to_cpu(task->cmdsn));
-       AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
-                     io_task->pwrb_handle->wrb_index);
-       AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
-                     io_task->psgl_handle->sgl_index);
+
+       if (chip_skh_r(phba->pcidev)) {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
+                             be32_to_cpu(task->cmdsn));
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
+                             io_task->pwrb_handle->wrb_index);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
+                             io_task->psgl_handle->sgl_index);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
+                             task->data_count);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
+                             io_task->pwrb_handle->nxt_wrb_index);
+               pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
+       } else {
+               AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
+                             be32_to_cpu(task->cmdsn));
+               AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
+                             io_task->pwrb_handle->wrb_index);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
+                             io_task->psgl_handle->sgl_index);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
+                             task->data_count);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
+                             io_task->pwrb_handle->nxt_wrb_index);
+               pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
+       }
+
 
        switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
        case ISCSI_OP_LOGIN:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                             TGT_DM_CMD);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
                AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
+               ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_NOOP_OUT:
                if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                                     TGT_DM_CMD);
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
-                                     pwrb, 0);
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
+                       ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
+                       if (chip_skh_r(phba->pcidev))
+                               AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                             dmsg, pwrb, 1);
+                       else
+                               AMAP_SET_BITS(struct amap_iscsi_wrb,
+                                             dmsg, pwrb, 1);
                } else {
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                                     INI_RD_CMD);
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+                       ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset);
+                       if (chip_skh_r(phba->pcidev))
+                               AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                                             dmsg, pwrb, 0);
+                       else
+                               AMAP_SET_BITS(struct amap_iscsi_wrb,
+                                             dmsg, pwrb, 0);
                }
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_TEXT:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                             TGT_DM_CMD);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_SCSI_TMFUNC:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                             INI_TMF_CMD);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               ADAPTER_SET_WRB_TYPE(pwrb, INI_TMF_CMD, pwrb_typeoffset);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_LOGOUT:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                             HWH_TYPE_LOGOUT);
+               ADAPTER_SET_WRB_TYPE(pwrb, HWH_TYPE_LOGOUT, pwrb_typeoffset);
                hwi_write_buffer(pwrb, task);
                break;
 
@@ -4251,11 +4539,10 @@ static int beiscsi_mtask(struct iscsi_task *task)
                return -EINVAL;
        }
 
-       AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
-                     task->data_count);
-       AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
-                     io_task->pwrb_handle->nxt_wrb_index);
-       be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
+       /* Set the task type */
+       io_task->wrb_type = (chip_skh_r(phba->pcidev)) ?
+               AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb) :
+               AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb);
 
        doorbell |= cid & DB_WRB_POST_CID_MASK;
        doorbell |= (io_task->pwrb_handle->wrb_index &
@@ -4269,10 +4556,13 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
 {
        struct beiscsi_io_task *io_task = task->dd_data;
        struct scsi_cmnd *sc = task->sc;
+       struct beiscsi_hba *phba = NULL;
        struct scatterlist *sg;
        int num_sg;
        unsigned int  writedir = 0, xferlen = 0;
 
+       phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba;
+
        if (!sc)
                return beiscsi_mtask(task);
 
@@ -4295,7 +4585,7 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
         else
                writedir = 0;
 
-       return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
+        return phba->iotask_fn(task, sg, num_sg, xferlen, writedir);
 }
 
 /**
@@ -4326,20 +4616,24 @@ static int beiscsi_bsg_request(struct bsg_job *job)
                        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
                                    "BM_%d : Failed to allocate memory for "
                                    "beiscsi_bsg_request\n");
-                       return -EIO;
+                       return -ENOMEM;
                }
                tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job,
                                                  &nonemb_cmd);
                if (!tag) {
                        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-                                   "BM_%d : be_cmd_get_mac_addr Failed\n");
+                                   "BM_%d : MBX Tag Allocation Failed\n");
 
                        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                                            nonemb_cmd.va, nonemb_cmd.dma);
                        return -EAGAIN;
-               } else
-                       wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                                phba->ctrl.mcc_numtag[tag]);
+               }
+
+               rc = wait_event_interruptible_timeout(
+                                       phba->ctrl.mcc_wait[tag],
+                                       phba->ctrl.mcc_numtag[tag],
+                                       msecs_to_jiffies(
+                                       BEISCSI_HOST_MBX_TIMEOUT));
                extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
                status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
                free_mcc_tag(&phba->ctrl, tag);
@@ -4356,11 +4650,13 @@ static int beiscsi_bsg_request(struct bsg_job *job)
                                    nonemb_cmd.va, nonemb_cmd.dma);
                if (status || extd_status) {
                        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-                                   "BM_%d : be_cmd_get_mac_addr Failed"
+                                   "BM_%d : MBX Cmd Failed"
                                    " status = %d extd_status = %d\n",
                                    status, extd_status);
 
                        return -EIO;
+               } else {
+                       rc = 0;
                }
                break;
 
@@ -4380,14 +4676,18 @@ void beiscsi_hba_attrs_init(struct beiscsi_hba *phba)
        beiscsi_log_enable_init(phba, beiscsi_log_enable);
 }
 
+/*
+ * beiscsi_quiesce()- Cleanup Driver resources
+ * @phba: Instance Priv structure
+ *
+ * Free the OS and HW resources held by the driver
+ **/
 static void beiscsi_quiesce(struct beiscsi_hba *phba)
 {
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
        struct be_eq_obj *pbe_eq;
        unsigned int i, msix_vec;
-       u8 *real_offset = 0;
-       u32 value = 0;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -4411,19 +4711,14 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba)
 
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
-       real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
 
-       value = readl((void *)real_offset);
-
-       if (value & 0x00010000) {
-               value &= 0xfffeffff;
-               writel(value, (void *)real_offset);
-       }
        beiscsi_unmap_pci_function(phba);
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
                            phba->ctrl.mbox_mem_alloced.dma);
+
+       cancel_delayed_work_sync(&phba->beiscsi_hw_check_task);
 }
 
 static void beiscsi_remove(struct pci_dev *pcidev)
@@ -4476,6 +4771,25 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba)
        return;
 }
 
+/*
+ * beiscsi_hw_health_check()- Check adapter health
+ * @work: work item to check HW health
+ *
+ * Check if adapter in an unrecoverable state or not.
+ **/
+static void
+beiscsi_hw_health_check(struct work_struct *work)
+{
+       struct beiscsi_hba *phba =
+               container_of(work, struct beiscsi_hba,
+                            beiscsi_hw_check_task.work);
+
+       beiscsi_ue_detect(phba);
+
+       schedule_delayed_work(&phba->beiscsi_hw_check_task,
+                             msecs_to_jiffies(1000));
+}
+
 static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                                const struct pci_device_id *id)
 {
@@ -4483,9 +4797,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
        struct be_eq_obj *pbe_eq;
-       int ret, num_cpus, i;
-       u8 *real_offset = 0;
-       u32 value = 0;
+       int ret, i;
 
        ret = beiscsi_enable_pci(pcidev);
        if (ret < 0) {
@@ -4504,25 +4816,33 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
        /* Initialize Driver configuration Paramters */
        beiscsi_hba_attrs_init(phba);
 
+       phba->fw_timeout = false;
+
+
        switch (pcidev->device) {
        case BE_DEVICE_ID1:
        case OC_DEVICE_ID1:
        case OC_DEVICE_ID2:
                phba->generation = BE_GEN2;
+               phba->iotask_fn = beiscsi_iotask;
                break;
        case BE_DEVICE_ID2:
        case OC_DEVICE_ID3:
                phba->generation = BE_GEN3;
+               phba->iotask_fn = beiscsi_iotask;
                break;
+       case OC_SKH_ID1:
+               phba->generation = BE_GEN4;
+               phba->iotask_fn = beiscsi_iotask_v2;
        default:
                phba->generation = 0;
        }
 
        if (enable_msix)
-               num_cpus = find_num_cpus();
+               find_num_cpus(phba);
        else
-               num_cpus = 1;
-       phba->num_cpus = num_cpus;
+               phba->num_cpus = 1;
+
        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
                    "BM_%d : num_cpus = %d\n",
                    phba->num_cpus);
@@ -4540,31 +4860,18 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto hba_free;
        }
 
-       if (!num_hba) {
-               real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
-               value = readl((void *)real_offset);
-               if (value & 0x00010000) {
-                       gcrashmode++;
-                       beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                                   "BM_%d : Loading Driver in crashdump mode\n");
-                       ret = beiscsi_cmd_reset_function(phba);
-                       if (ret) {
-                               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                                           "BM_%d : Reset Failed. Aborting Crashdump\n");
-                               goto hba_free;
-                       }
-                       ret = be_chk_reset_complete(phba);
-                       if (ret) {
-                               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                                           "BM_%d : Failed to get out of reset."
-                                           "Aborting Crashdump\n");
-                               goto hba_free;
-                       }
-               } else {
-                       value |= 0x00010000;
-                       writel(value, (void *)real_offset);
-                       num_hba++;
-               }
+       ret = beiscsi_cmd_reset_function(phba);
+       if (ret) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BM_%d : Reset Failed. Aborting Crashdump\n");
+               goto hba_free;
+       }
+       ret = be_chk_reset_complete(phba);
+       if (ret) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BM_%d : Failed to get out of reset."
+                           "Aborting Crashdump\n");
+               goto hba_free;
        }
 
        spin_lock_init(&phba->io_sgl_lock);
@@ -4596,7 +4903,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 
        phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
 
-       snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
+       snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq",
                 phba->shost->host_no);
        phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
        if (!phba->wq) {
@@ -4606,10 +4913,12 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto free_twq;
        }
 
-       INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
+       INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task,
+                         beiscsi_hw_health_check);
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
+
        if (blk_iopoll_enabled) {
                for (i = 0; i < phba->num_cpus; i++) {
                        pbe_eq = &phwi_context->be_eq[i];
@@ -4617,7 +4926,25 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                                        be_iopoll);
                        blk_iopoll_enable(&pbe_eq->iopoll);
                }
+
+               i = (phba->msix_enabled) ? i : 0;
+               /* Work item for MCC handling */
+               pbe_eq = &phwi_context->be_eq[i];
+               INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs);
+       } else {
+               if (phba->msix_enabled) {
+                       for (i = 0; i <= phba->num_cpus; i++) {
+                               pbe_eq = &phwi_context->be_eq[i];
+                               INIT_WORK(&pbe_eq->work_cqs,
+                                         beiscsi_process_all_cqs);
+                       }
+               } else {
+                               pbe_eq = &phwi_context->be_eq[0];
+                               INIT_WORK(&pbe_eq->work_cqs,
+                                         beiscsi_process_all_cqs);
+                       }
        }
+
        ret = beiscsi_init_irqs(phba);
        if (ret < 0) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@@ -4637,6 +4964,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                            "iSCSI boot info.\n");
 
        beiscsi_create_def_ifaces(phba);
+       schedule_delayed_work(&phba->beiscsi_hw_check_task,
+                             msecs_to_jiffies(1000));
+
        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
                    "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
        return 0;
@@ -4652,15 +4982,6 @@ free_twq:
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
 free_port:
-       real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
-
-       value = readl((void *)real_offset);
-
-       if (value & 0x00010000) {
-               value &= 0xfffeffff;
-               writel(value, (void *)real_offset);
-       }
-
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
index b8912263ef4e739de691727269a5c58761dfba3a..5946577d79d6579f6f4fa4ff8c8eaf156caf9ac5 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
 
 #include "be.h"
 #define DRV_NAME               "be2iscsi"
-#define BUILD_STR              "4.4.58.0"
+#define BUILD_STR              "10.0.272.0"
 #define BE_NAME                        "Emulex OneConnect" \
                                "Open-iSCSI Driver version" BUILD_STR
 #define DRV_DESC               BE_NAME " " "Driver"
 
 #define BE_VENDOR_ID           0x19A2
+#define ELX_VENDOR_ID          0x10DF
 /* DEVICE ID's for BE2 */
 #define BE_DEVICE_ID1          0x212
 #define OC_DEVICE_ID1          0x702
@@ -51,6 +52,9 @@
 #define BE_DEVICE_ID2          0x222
 #define OC_DEVICE_ID3          0x712
 
+/* DEVICE ID for SKH */
+#define OC_SKH_ID1             0x722
+
 #define BE2_IO_DEPTH           1024
 #define BE2_MAX_SESSIONS       256
 #define BE2_CMDS_PER_CXN       128
 #define BE2_DEFPDU_HDR_SZ      64
 #define BE2_DEFPDU_DATA_SZ     8192
 
-#define MAX_CPUS               31
+#define MAX_CPUS               64
+#define BEISCSI_MAX_NUM_CPUS   7
+#define OC_SKH_MAX_NUM_CPUS    63
+
+
 #define BEISCSI_SGLIST_ELEMENTS        30
 
 #define BEISCSI_CMD_PER_LUN    128     /* scsi_host->cmd_per_lun */
@@ -257,6 +265,7 @@ struct invalidate_command_table {
        unsigned short cid;
 } __packed;
 
+#define chip_skh_r(pdev)       (pdev->device == OC_SKH_ID1)
 struct beiscsi_hba {
        struct hba_parameters params;
        struct hwi_controller *phwi_ctrlr;
@@ -270,12 +279,11 @@ struct beiscsi_hba {
        struct be_bus_address pci_pa;   /* CSR */
        /* PCI representation of our HBA */
        struct pci_dev *pcidev;
-       unsigned int state;
        unsigned short asic_revision;
        unsigned int num_cpus;
        unsigned int nxt_cqid;
-       struct msix_entry msix_entries[MAX_CPUS + 1];
-       char *msi_name[MAX_CPUS + 1];
+       struct msix_entry msix_entries[MAX_CPUS];
+       char *msi_name[MAX_CPUS];
        bool msix_enabled;
        struct be_mem_descriptor *init_mem;
 
@@ -325,12 +333,14 @@ struct beiscsi_hba {
                spinlock_t cid_lock;
        } fw_config;
 
+       unsigned int state;
+       bool fw_timeout;
+       bool ue_detected;
+       struct delayed_work beiscsi_hw_check_task;
+
        u8 mac_address[ETH_ALEN];
-       unsigned short todo_cq;
-       unsigned short todo_mcc_cq;
        char wq_name[20];
        struct workqueue_struct *wq;    /* The actuak work queue */
-       struct work_struct work_cqs;    /* The work being queued */
        struct be_ctrl_info ctrl;
        unsigned int generation;
        unsigned int interface_handle;
@@ -338,7 +348,10 @@ struct beiscsi_hba {
        struct invalidate_command_table inv_tbl[128];
 
        unsigned int attr_log_enable;
-
+       int (*iotask_fn)(struct iscsi_task *,
+                       struct scatterlist *sg,
+                       uint32_t num_sg, uint32_t xferlen,
+                       uint32_t writedir);
 };
 
 struct beiscsi_session {
@@ -410,6 +423,9 @@ struct beiscsi_io_task {
        struct be_cmd_bhs *cmd_bhs;
        struct be_bus_address bhs_pa;
        unsigned short bhs_len;
+       dma_addr_t mtask_addr;
+       uint32_t mtask_data_count;
+       uint8_t wrb_type;
 };
 
 struct be_nonio_bhs {
@@ -457,6 +473,9 @@ struct beiscsi_offload_params {
 #define OFFLD_PARAMS_HDE       0x00000008
 #define OFFLD_PARAMS_IR2T      0x00000010
 #define OFFLD_PARAMS_IMD       0x00000020
+#define OFFLD_PARAMS_DATA_SEQ_INORDER   0x00000040
+#define OFFLD_PARAMS_PDU_SEQ_INORDER    0x00000080
+#define OFFLD_PARAMS_MAX_R2T 0x00FFFF00
 
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
@@ -471,7 +490,10 @@ struct amap_beiscsi_offload_params {
        u8 hde[1];
        u8 ir2t[1];
        u8 imd[1];
-       u8 pad[26];
+       u8 data_seq_inorder[1];
+       u8 pdu_seq_inorder[1];
+       u8 max_r2t[16];
+       u8 pad[8];
        u8 exp_statsn[32];
 };
 
@@ -569,6 +591,20 @@ struct amap_i_t_dpdu_cqe {
        u8 valid;
 } __packed;
 
+struct amap_i_t_dpdu_cqe_v2 {
+       u8 db_addr_hi[32];  /* DWORD 0 */
+       u8 db_addr_lo[32];  /* DWORD 1 */
+       u8 code[6]; /* DWORD 2 */
+       u8 num_cons; /* DWORD 2*/
+       u8 rsvd0[8]; /* DWORD 2 */
+       u8 dpl[17]; /* DWORD 2 */
+       u8 index[16]; /* DWORD 3 */
+       u8 cid[13]; /* DWORD 3 */
+       u8 rsvd1; /* DWORD 3 */
+       u8 final; /* DWORD 3 */
+       u8 valid; /* DWORD 3 */
+} __packed;
+
 #define CQE_VALID_MASK 0x80000000
 #define CQE_CODE_MASK  0x0000003F
 #define CQE_CID_MASK   0x0000FFC0
@@ -617,6 +653,11 @@ struct iscsi_wrb {
 } __packed;
 
 #define WRB_TYPE_MASK 0xF0000000
+#define SKH_WRB_TYPE_OFFSET 27
+#define BE_WRB_TYPE_OFFSET  28
+
+#define ADAPTER_SET_WRB_TYPE(pwrb, wrb_type, type_offset) \
+               (pwrb->dw[0] |= (wrb_type << type_offset))
 
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
@@ -663,12 +704,57 @@ struct amap_iscsi_wrb {
 
 } __packed;
 
+struct amap_iscsi_wrb_v2 {
+       u8 r2t_exp_dtl[25]; /* DWORD 0 */
+       u8 rsvd0[2];    /* DWORD 0*/
+       u8 type[5];     /* DWORD 0 */
+       u8 ptr2nextwrb[8];  /* DWORD 1 */
+       u8 wrb_idx[8];      /* DWORD 1 */
+       u8 lun[16];     /* DWORD 1 */
+       u8 sgl_idx[16]; /* DWORD 2 */
+       u8 ref_sgl_icd_idx[16]; /* DWORD 2 */
+       u8 exp_data_sn[32]; /* DWORD 3 */
+       u8 iscsi_bhs_addr_hi[32];   /* DWORD 4 */
+       u8 iscsi_bhs_addr_lo[32];   /* DWORD 5 */
+       u8 cq_id[16];   /* DWORD 6 */
+       u8 rsvd1[16];   /* DWORD 6 */
+       u8 cmdsn_itt[32];   /* DWORD 7 */
+       u8 sge0_addr_hi[32];    /* DWORD 8 */
+       u8 sge0_addr_lo[32];    /* DWORD 9 */
+       u8 sge0_offset[24]; /* DWORD 10 */
+       u8 rsvd2[7];    /* DWORD 10 */
+       u8 sge0_last;   /* DWORD 10 */
+       u8 sge0_len[17];    /* DWORD 11 */
+       u8 rsvd3[7];    /* DWORD 11 */
+       u8 diff_enbl;   /* DWORD 11 */
+       u8 u_run;       /* DWORD 11 */
+       u8 o_run;       /* DWORD 11 */
+       u8 invalid;     /* DWORD 11 */
+       u8 dsp;         /* DWORD 11 */
+       u8 dmsg;        /* DWORD 11 */
+       u8 rsvd4;       /* DWORD 11 */
+       u8 lt;          /* DWORD 11 */
+       u8 sge1_addr_hi[32];    /* DWORD 12 */
+       u8 sge1_addr_lo[32];    /* DWORD 13 */
+       u8 sge1_r2t_offset[24]; /* DWORD 14 */
+       u8 rsvd5[7];    /* DWORD 14 */
+       u8 sge1_last;   /* DWORD 14 */
+       u8 sge1_len[17];    /* DWORD 15 */
+       u8 rsvd6[15];   /* DWORD 15 */
+} __packed;
+
+
 struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid);
 void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
 
 void beiscsi_process_all_cqs(struct work_struct *work);
 
+static inline bool beiscsi_error(struct beiscsi_hba *phba)
+{
+       return phba->ue_detected || phba->fw_timeout;
+}
+
 struct pdu_nop_out {
        u32 dw[12];
 };
@@ -728,6 +814,7 @@ struct iscsi_target_context_update_wrb {
  * Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field
  */
+#define BE_TGT_CTX_UPDT_CMD 0x07
 struct amap_iscsi_target_context_update_wrb {
        u8 lun[14];             /* DWORD 0 */
        u8 lt;                  /* DWORD 0 */
@@ -773,6 +860,47 @@ struct amap_iscsi_target_context_update_wrb {
 
 } __packed;
 
+#define BEISCSI_MAX_RECV_DATASEG_LEN    (64 * 1024)
+#define BEISCSI_MAX_CXNS    1
+struct amap_iscsi_target_context_update_wrb_v2 {
+       u8 max_burst_length[24];    /* DWORD 0 */
+       u8 rsvd0[3];    /* DWORD 0 */
+       u8 type[5];     /* DWORD 0 */
+       u8 ptr2nextwrb[8];  /* DWORD 1 */
+       u8 wrb_idx[8];      /* DWORD 1 */
+       u8 rsvd1[16];       /* DWORD 1 */
+       u8 max_send_data_segment_length[24];    /* DWORD 2 */
+       u8 rsvd2[8];    /* DWORD 2 */
+       u8 first_burst_length[24]; /* DWORD 3 */
+       u8 rsvd3[8]; /* DOWRD 3 */
+       u8 max_r2t[16]; /* DWORD 4 */
+       u8 rsvd4[10];   /* DWORD 4 */
+       u8 hde;         /* DWORD 4 */
+       u8 dde;         /* DWORD 4 */
+       u8 erl[2];      /* DWORD 4 */
+       u8 imd;         /* DWORD 4 */
+       u8 ir2t;        /* DWORD 4 */
+       u8 stat_sn[32];     /* DWORD 5 */
+       u8 rsvd5[32];   /* DWORD 6 */
+       u8 rsvd6[32];   /* DWORD 7 */
+       u8 max_recv_dataseg_len[24];    /* DWORD 8 */
+       u8 rsvd7[8]; /* DWORD 8 */
+       u8 rsvd8[32];   /* DWORD 9 */
+       u8 rsvd9[32];   /* DWORD 10 */
+       u8 max_cxns[16]; /* DWORD 11 */
+       u8 rsvd10[11]; /* DWORD  11*/
+       u8 invld; /* DWORD 11 */
+       u8 rsvd11;/* DWORD 11*/
+       u8 dmsg; /* DWORD 11 */
+       u8 data_seq_inorder; /* DWORD 11 */
+       u8 pdu_seq_inorder; /* DWORD 11 */
+       u8 rsvd12[32]; /*DWORD 12 */
+       u8 rsvd13[32]; /* DWORD 13 */
+       u8 rsvd14[32]; /* DWORD 14 */
+       u8 rsvd15[32]; /* DWORD 15 */
+} __packed;
+
+
 struct be_ring {
        u32 pages;              /* queue size in pages */
        u32 id;                 /* queue id assigned by beklib */
@@ -837,7 +965,7 @@ struct hwi_context_memory {
        u16 max_eqd;            /* in usecs */
        u16 cur_eqd;            /* in usecs */
        struct be_eq_obj be_eq[MAX_CPUS];
-       struct be_queue_info be_cq[MAX_CPUS];
+       struct be_queue_info be_cq[MAX_CPUS - 1];
 
        struct be_queue_info be_def_hdrq;
        struct be_queue_info be_def_dataq;
index aab5dd359e2c2cbd5a945becbbcb44dd5638d727..a6c2fe4b4d652a39fe4c13bfede7560a5fdad675 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
 #include <scsi/scsi_bsg_iscsi.h>
 #include "be_mgmt.h"
 #include "be_iscsi.h"
+#include "be_main.h"
+
+/* UE Status Low CSR */
+static const char * const desc_ue_status_low[] = {
+       "CEV",
+       "CTX",
+       "DBUF",
+       "ERX",
+       "Host",
+       "MPU",
+       "NDMA",
+       "PTC ",
+       "RDMA ",
+       "RXF ",
+       "RXIPS ",
+       "RXULP0 ",
+       "RXULP1 ",
+       "RXULP2 ",
+       "TIM ",
+       "TPOST ",
+       "TPRE ",
+       "TXIPS ",
+       "TXULP0 ",
+       "TXULP1 ",
+       "UC ",
+       "WDMA ",
+       "TXULP2 ",
+       "HOST1 ",
+       "P0_OB_LINK ",
+       "P1_OB_LINK ",
+       "HOST_GPIO ",
+       "MBOX ",
+       "AXGMAC0",
+       "AXGMAC1",
+       "JTAG",
+       "MPU_INTPEND"
+};
+
+/* UE Status High CSR */
+static const char * const desc_ue_status_hi[] = {
+       "LPCMEMHOST",
+       "MGMT_MAC",
+       "PCS0ONLINE",
+       "MPU_IRAM",
+       "PCS1ONLINE",
+       "PCTL0",
+       "PCTL1",
+       "PMEM",
+       "RR",
+       "TXPB",
+       "RXPP",
+       "XAUI",
+       "TXP",
+       "ARM",
+       "IPC",
+       "HOST2",
+       "HOST3",
+       "HOST4",
+       "HOST5",
+       "HOST6",
+       "HOST7",
+       "HOST8",
+       "HOST9",
+       "NETC",
+       "Unknown",
+       "Unknown",
+       "Unknown",
+       "Unknown",
+       "Unknown",
+       "Unknown",
+       "Unknown",
+       "Unknown"
+};
+
+/*
+ * beiscsi_ue_detec()- Detect Unrecoverable Error on adapter
+ * @phba: Driver priv structure
+ *
+ * Read registers linked to UE and check for the UE status
+ **/
+void beiscsi_ue_detect(struct beiscsi_hba *phba)
+{
+       uint32_t ue_hi = 0, ue_lo = 0;
+       uint32_t ue_mask_hi = 0, ue_mask_lo = 0;
+       uint8_t i = 0;
+
+       if (phba->ue_detected)
+               return;
+
+       pci_read_config_dword(phba->pcidev,
+                             PCICFG_UE_STATUS_LOW, &ue_lo);
+       pci_read_config_dword(phba->pcidev,
+                             PCICFG_UE_STATUS_MASK_LOW,
+                             &ue_mask_lo);
+       pci_read_config_dword(phba->pcidev,
+                             PCICFG_UE_STATUS_HIGH,
+                             &ue_hi);
+       pci_read_config_dword(phba->pcidev,
+                             PCICFG_UE_STATUS_MASK_HI,
+                             &ue_mask_hi);
+
+       ue_lo = (ue_lo & ~ue_mask_lo);
+       ue_hi = (ue_hi & ~ue_mask_hi);
+
+
+       if (ue_lo || ue_hi) {
+               phba->ue_detected = true;
+               beiscsi_log(phba, KERN_ERR,
+                           BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
+                           "BG_%d : Error detected on the adapter\n");
+       }
+
+       if (ue_lo) {
+               for (i = 0; ue_lo; ue_lo >>= 1, i++) {
+                       if (ue_lo & 1)
+                               beiscsi_log(phba, KERN_ERR,
+                                           BEISCSI_LOG_CONFIG,
+                                           "BG_%d : UE_LOW %s bit set\n",
+                                           desc_ue_status_low[i]);
+               }
+       }
+
+       if (ue_hi) {
+               for (i = 0; ue_hi; ue_hi >>= 1, i++) {
+                       if (ue_hi & 1)
+                               beiscsi_log(phba, KERN_ERR,
+                                           BEISCSI_LOG_CONFIG,
+                                           "BG_%d : UE_HIGH %s bit set\n",
+                                           desc_ue_status_hi[i]);
+               }
+       }
+}
 
 /**
  * mgmt_reopen_session()- Reopen a session based on reopen_type
@@ -575,13 +707,20 @@ unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba)
        return status;
 }
 
+/*
+ * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd
+ * @phba: Driver priv structure
+ * @nonemb_cmd: Address of the MBX command issued
+ * @resp_buf: Buffer to copy the MBX cmd response
+ * @resp_buf_len: respone lenght to be copied
+ *
+ **/
 static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
                                struct be_dma_mem *nonemb_cmd, void *resp_buf,
                                int resp_buf_len)
 {
        struct be_ctrl_info *ctrl = &phba->ctrl;
        struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
-       unsigned short status, extd_status;
        struct be_sge *sge;
        unsigned int tag;
        int rc = 0;
@@ -599,31 +738,25 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
 
        be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
        sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
-       sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
+       sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma));
        sge->len = cpu_to_le32(nonemb_cmd->size);
 
        be_mcc_notify(phba);
        spin_unlock(&ctrl->mbox_lock);
 
-       wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                phba->ctrl.mcc_numtag[tag]);
-
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-       if (status || extd_status) {
+       rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va);
+       if (rc) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-                           "BG_%d : mgmt_exec_nonemb_cmd Failed status = %d"
-                           "extd_status = %d\n", status, extd_status);
+                           "BG_%d : mgmt_exec_nonemb_cmd Failed status\n");
+
                rc = -EIO;
-               goto free_tag;
+               goto free_cmd;
        }
 
        if (resp_buf)
                memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
 
-free_tag:
-       free_mcc_tag(&phba->ctrl, tag);
 free_cmd:
        pci_free_consistent(ctrl->pdev, nonemb_cmd->size,
                            nonemb_cmd->va, nonemb_cmd->dma);
@@ -1009,10 +1142,9 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 {
        struct be_cmd_get_boot_target_resp *boot_resp;
        struct be_mcc_wrb *wrb;
-       unsigned int tag, wrb_num;
+       unsigned int tag;
        uint8_t boot_retry = 3;
-       unsigned short status, extd_status;
-       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+       int rc;
 
        do {
                /* Get the Boot Target Session Handle and Count*/
@@ -1022,24 +1154,16 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
                                    BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
                                    "BG_%d : Getting Boot Target Info Failed\n");
                        return -EAGAIN;
-               } else
-                       wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                                phba->ctrl.mcc_numtag[tag]);
-
-               wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-               extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-               status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-               if (status || extd_status) {
+               }
+
+               rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+               if (rc) {
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-                                   "BG_%d : mgmt_get_boot_target Failed"
-                                   " status = %d extd_status = %d\n",
-                                   status, extd_status);
-                       free_mcc_tag(&phba->ctrl, tag);
+                                   "BG_%d : MBX CMD get_boot_target Failed\n");
                        return -EBUSY;
                }
-               wrb = queue_get_wrb(mccq, wrb_num);
-               free_mcc_tag(&phba->ctrl, tag);
+
                boot_resp = embedded_payload(wrb);
 
                /* Check if the there are any Boot targets configured */
@@ -1064,24 +1188,15 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
                                    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
                                    "BG_%d : mgmt_reopen_session Failed\n");
                        return -EAGAIN;
-               } else
-                       wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                                phba->ctrl.mcc_numtag[tag]);
-
-               wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-               extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-               status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-               if (status || extd_status) {
+               }
+
+               rc = beiscsi_mccq_compl(phba, tag, NULL, NULL);
+               if (rc) {
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-                                   "BG_%d : mgmt_reopen_session Failed"
-                                   " status = %d extd_status = %d\n",
-                                   status, extd_status);
-                       free_mcc_tag(&phba->ctrl, tag);
-                       return -EBUSY;
+                                   "BG_%d : mgmt_reopen_session Failed");
+                       return rc;
                }
-               free_mcc_tag(&phba->ctrl, tag);
-
        } while (--boot_retry);
 
        /* Couldn't log into the boot target */
@@ -1106,8 +1221,9 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 int mgmt_set_vlan(struct beiscsi_hba *phba,
                   uint16_t vlan_tag)
 {
-       unsigned int tag, wrb_num;
-       unsigned short status, extd_status;
+       int rc;
+       unsigned int tag;
+       struct be_mcc_wrb *wrb = NULL;
 
        tag = be_cmd_set_vlan(phba, vlan_tag);
        if (!tag) {
@@ -1115,24 +1231,208 @@ int mgmt_set_vlan(struct beiscsi_hba *phba,
                            (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
                            "BG_%d : VLAN Setting Failed\n");
                return -EBUSY;
-       } else
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-
-       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+       }
 
-       if (status || extd_status) {
+       rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+       if (rc) {
                beiscsi_log(phba, KERN_ERR,
                            (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
-                           "BS_%d : status : %d extd_status : %d\n",
-                           status, extd_status);
+                           "BS_%d : VLAN MBX Cmd Failed\n");
+               return rc;
+       }
+       return rc;
+}
 
-               free_mcc_tag(&phba->ctrl, tag);
-               return -EAGAIN;
+/**
+ * beiscsi_drvr_ver_disp()- Display the driver Name and Version
+ * @dev: ptr to device not used.
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text driver name and version
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr,
+                      char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, BE_NAME "\n");
+}
+
+/**
+ * beiscsi_adap_family_disp()- Display adapter family.
+ * @dev: ptr to device to get priv structure
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text driver name and version
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       uint16_t dev_id = 0;
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+       dev_id = phba->pcidev->device;
+       switch (dev_id) {
+       case BE_DEVICE_ID1:
+       case OC_DEVICE_ID1:
+       case OC_DEVICE_ID2:
+               return snprintf(buf, PAGE_SIZE, "BE2 Adapter Family\n");
+               break;
+       case BE_DEVICE_ID2:
+       case OC_DEVICE_ID3:
+               return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n");
+               break;
+       case OC_SKH_ID1:
+               return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n");
+               break;
+       default:
+               return snprintf(buf, PAGE_SIZE,
+                               "Unkown Adapter Family: 0x%x\n", dev_id);
+               break;
        }
+}
 
-       free_mcc_tag(&phba->ctrl, tag);
-       return 0;
+
+void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
+                            struct wrb_handle *pwrb_handle,
+                            struct be_mem_descriptor *mem_descr)
+{
+       struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
+
+       memset(pwrb, 0, sizeof(*pwrb));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     max_send_data_segment_length, pwrb,
+                     params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     max_send_data_segment_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
+                     BE_TGT_CTX_UPDT_CMD);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     first_burst_length,
+                     pwrb,
+                     params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     first_burst_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     erl) / 32] & OFFLD_PARAMS_ERL));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                      dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
+                     pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     exp_statsn) / 32] + 1));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
+                     pwrb, pwrb_handle->wrb_index);
+
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     max_burst_length, pwrb, params->dw[offsetof
+                     (struct amap_beiscsi_offload_params,
+                     max_burst_length) / 32]);
+
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
+                     pwrb, pwrb_handle->nxt_wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     session_state, pwrb, 0);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
+                     pwrb, 1);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
+                     pwrb, 0);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
+                     0);
+
+       mem_descr += ISCSI_MEM_GLOBAL_HEADER;
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     pad_buffer_addr_hi, pwrb,
+                     mem_descr->mem_array[0].bus_address.u.a32.address_hi);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     pad_buffer_addr_lo, pwrb,
+                     mem_descr->mem_array[0].bus_address.u.a32.address_lo);
+}
+
+void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
+                            struct wrb_handle *pwrb_handle)
+{
+       struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
+
+       memset(pwrb, 0, sizeof(*pwrb));
+
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     max_burst_length, pwrb, params->dw[offsetof
+                     (struct amap_beiscsi_offload_params,
+                     max_burst_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     max_burst_length, pwrb, params->dw[offsetof
+                     (struct amap_beiscsi_offload_params,
+                     max_burst_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     type, pwrb,
+                     BE_TGT_CTX_UPDT_CMD);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     ptr2nextwrb,
+                     pwrb, pwrb_handle->nxt_wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
+                     pwrb, pwrb_handle->wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     max_send_data_segment_length, pwrb,
+                     params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     max_send_data_segment_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     first_burst_length, pwrb,
+                     params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     first_burst_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     max_recv_dataseg_len, pwrb, BEISCSI_MAX_RECV_DATASEG_LEN);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     max_cxns, pwrb, BEISCSI_MAX_CXNS);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     erl) / 32] & OFFLD_PARAMS_ERL));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     ir2t, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     data_seq_inorder,
+                     pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     data_seq_inorder) / 32] &
+                     OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                     pdu_seq_inorder,
+                     pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     pdu_seq_inorder) / 32] &
+                     OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t,
+                     pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     max_r2t) / 32] &
+                     OFFLD_PARAMS_MAX_R2T) >> 8);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn,
+                     pwrb,
+                    (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     exp_statsn) / 32] + 1));
 }
index c50cef6fec0db3921908638411d9749bb879cdf2..2e4968add799f7e91ab53e38edd21cd5e74eaa44 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
 #define IP_V6_LEN      16
 #define IP_V4_LEN      4
 
+/* UE Status and Mask register */
+#define PCICFG_UE_STATUS_LOW            0xA0
+#define PCICFG_UE_STATUS_HIGH           0xA4
+#define PCICFG_UE_STATUS_MASK_LOW       0xA8
+#define PCICFG_UE_STATUS_MASK_HI        0xAC
+
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field
@@ -301,4 +307,19 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba);
 
 int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
+
+ssize_t beiscsi_drvr_ver_disp(struct device *dev,
+                              struct device_attribute *attr, char *buf);
+
+ssize_t beiscsi_adap_family_disp(struct device *dev,
+                                 struct device_attribute *attr, char *buf);
+
+void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
+                            struct wrb_handle *pwrb_handle,
+                            struct be_mem_descriptor *mem_descr);
+
+void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
+                            struct wrb_handle *pwrb_handle);
+void beiscsi_ue_detect(struct beiscsi_hba *phba);
+
 #endif
index 6d6eee42ac7d4181c775c5617475720c4e50c231..ef60afa94d0e75c265a5010be1dc72c62b82166b 100644 (file)
@@ -296,7 +296,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
        ofld_req3.flags |= (interface->vlan_enabled <<
                            FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
 
-       /* C2_VALID and ACK flags are not set as they are not suppported */
+       /* C2_VALID and ACK flags are not set as they are not supported */
 
 
        /* Initialize offload request 4 structure */
index 3f9e7061258e4352c3ba84d11c244491ae5ead6f..b44d04e41b0d72d8bfd775241ee7ee58df29f21f 100644 (file)
@@ -800,7 +800,7 @@ extern struct device_attribute *bnx2i_dev_attributes[];
 /*
  * Function Prototypes
  */
-extern void bnx2i_identify_device(struct bnx2i_hba *hba);
+extern void bnx2i_identify_device(struct bnx2i_hba *hba, struct cnic_dev *dev);
 
 extern void bnx2i_ulp_init(struct cnic_dev *dev);
 extern void bnx2i_ulp_exit(struct cnic_dev *dev);
index b17637aab9a792a959558ef79184800f9f0280a2..ee009e4ad097949785c677b9b343f3eeb8abbc7a 100644 (file)
@@ -79,42 +79,33 @@ static struct notifier_block bnx2i_cpu_notifier = {
 /**
  * bnx2i_identify_device - identifies NetXtreme II device type
  * @hba:               Adapter structure pointer
+ * @cnic:              Corresponding cnic device
  *
  * This function identifies the NX2 device type and sets appropriate
  *     queue mailbox register access method, 5709 requires driver to
  *     access MBOX regs using *bin* mode
  */
-void bnx2i_identify_device(struct bnx2i_hba *hba)
+void bnx2i_identify_device(struct bnx2i_hba *hba, struct cnic_dev *dev)
 {
        hba->cnic_dev_type = 0;
-       if ((hba->pci_did == PCI_DEVICE_ID_NX2_5706) ||
-           (hba->pci_did == PCI_DEVICE_ID_NX2_5706S))
-               set_bit(BNX2I_NX2_DEV_5706, &hba->cnic_dev_type);
-       else if ((hba->pci_did == PCI_DEVICE_ID_NX2_5708) ||
-           (hba->pci_did == PCI_DEVICE_ID_NX2_5708S))
-               set_bit(BNX2I_NX2_DEV_5708, &hba->cnic_dev_type);
-       else if ((hba->pci_did == PCI_DEVICE_ID_NX2_5709) ||
-           (hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
-               set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
-               hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
-       } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710    ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57711    ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57711E   ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57712    ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57712E   ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57800    ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57800_MF ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57800_VF ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57810    ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57810_MF ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57810_VF ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57840    ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57840_MF ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57840_VF)
+       if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
+               if (hba->pci_did == PCI_DEVICE_ID_NX2_5706 ||
+                   hba->pci_did == PCI_DEVICE_ID_NX2_5706S) {
+                       set_bit(BNX2I_NX2_DEV_5706, &hba->cnic_dev_type);
+               } else if (hba->pci_did == PCI_DEVICE_ID_NX2_5708 ||
+                   hba->pci_did == PCI_DEVICE_ID_NX2_5708S) {
+                       set_bit(BNX2I_NX2_DEV_5708, &hba->cnic_dev_type);
+               } else if (hba->pci_did == PCI_DEVICE_ID_NX2_5709 ||
+                   hba->pci_did == PCI_DEVICE_ID_NX2_5709S) {
+                       set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
+                       hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
+               }
+       } else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
                set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
-       else
+       } else {
                printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
                                  hba->pci_did);
+       }
 }
 
 
index 3b34c13e2f0217cddd881be065cfc05bc2baa46b..0056e47bd56ecf05c2f9fa3ac9c0e0636471172b 100644 (file)
@@ -808,7 +808,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
        hba->pci_func = PCI_FUNC(hba->pcidev->devfn);
        hba->pci_devno = PCI_SLOT(hba->pcidev->devfn);
 
-       bnx2i_identify_device(hba);
+       bnx2i_identify_device(hba, cnic);
        bnx2i_setup_host_queue_size(hba, shost);
 
        hba->reg_base = pci_resource_start(hba->pcidev, 0);
diff --git a/drivers/scsi/csiostor/Kconfig b/drivers/scsi/csiostor/Kconfig
new file mode 100644 (file)
index 0000000..4d03b03
--- /dev/null
@@ -0,0 +1,19 @@
+config SCSI_CHELSIO_FCOE
+       tristate "Chelsio Communications FCoE support"
+       depends on PCI && SCSI
+       select SCSI_FC_ATTRS
+       select FW_LOADER
+       help
+         This driver supports FCoE Offload functionality over
+         Chelsio T4-based 10Gb Converged Network Adapters.
+
+         For general information about Chelsio and our products, visit
+         our website at <http://www.chelsio.com>.
+
+         For customer support, please visit our customer support page at
+         <http://www.chelsio.com/support.html>.
+
+         Please send feedback to <linux-bugs@chelsio.com>.
+
+         To compile this driver as a module choose M here; the module
+         will be called csiostor.
diff --git a/drivers/scsi/csiostor/Makefile b/drivers/scsi/csiostor/Makefile
new file mode 100644 (file)
index 0000000..b581966
--- /dev/null
@@ -0,0 +1,11 @@
+#
+## Chelsio FCoE driver
+#
+##
+
+ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
+
+obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor.o
+
+csiostor-objs := csio_attr.o csio_init.o csio_lnode.o csio_scsi.o \
+               csio_hw.o csio_isr.o csio_mb.o csio_rnode.o csio_wr.o
diff --git a/drivers/scsi/csiostor/csio_attr.c b/drivers/scsi/csiostor/csio_attr.c
new file mode 100644 (file)
index 0000000..065a87a
--- /dev/null
@@ -0,0 +1,796 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/jiffies.h>
+#include <scsi/fc/fc_fs.h>
+
+#include "csio_init.h"
+
+static void
+csio_vport_set_state(struct csio_lnode *ln);
+
+/*
+ * csio_reg_rnode - Register a remote port with FC transport.
+ * @rn: Rnode representing remote port.
+ *
+ * Call fc_remote_port_add() to register this remote port with FC transport.
+ * If remote port is Initiator OR Target OR both, change the role appropriately.
+ *
+ */
+void
+csio_reg_rnode(struct csio_rnode *rn)
+{
+       struct csio_lnode *ln           = csio_rnode_to_lnode(rn);
+       struct Scsi_Host *shost         = csio_ln_to_shost(ln);
+       struct fc_rport_identifiers ids;
+       struct fc_rport  *rport;
+       struct csio_service_parms *sp;
+
+       ids.node_name   = wwn_to_u64(csio_rn_wwnn(rn));
+       ids.port_name   = wwn_to_u64(csio_rn_wwpn(rn));
+       ids.port_id     = rn->nport_id;
+       ids.roles       = FC_RPORT_ROLE_UNKNOWN;
+
+       if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {
+               rport = rn->rport;
+               CSIO_ASSERT(rport != NULL);
+               goto update_role;
+       }
+
+       rn->rport = fc_remote_port_add(shost, 0, &ids);
+       if (!rn->rport) {
+               csio_ln_err(ln, "Failed to register rport = 0x%x.\n",
+                                       rn->nport_id);
+               return;
+       }
+
+       ln->num_reg_rnodes++;
+       rport = rn->rport;
+       spin_lock_irq(shost->host_lock);
+       *((struct csio_rnode **)rport->dd_data) = rn;
+       spin_unlock_irq(shost->host_lock);
+
+       sp = &rn->rn_sparm;
+       rport->maxframe_size = ntohs(sp->csp.sp_bb_data);
+       if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)
+               rport->supported_classes = FC_COS_CLASS3;
+       else
+               rport->supported_classes = FC_COS_UNSPECIFIED;
+update_role:
+       if (rn->role & CSIO_RNFR_INITIATOR)
+               ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+       if (rn->role & CSIO_RNFR_TARGET)
+               ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+
+       if (ids.roles != FC_RPORT_ROLE_UNKNOWN)
+               fc_remote_port_rolechg(rport, ids.roles);
+
+       rn->scsi_id = rport->scsi_target_id;
+
+       csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",
+               rn->nport_id, ids.roles);
+}
+
+/*
+ * csio_unreg_rnode - Unregister a remote port with FC transport.
+ * @rn: Rnode representing remote port.
+ *
+ * Call fc_remote_port_delete() to unregister this remote port with FC
+ * transport.
+ *
+ */
+void
+csio_unreg_rnode(struct csio_rnode *rn)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       struct fc_rport *rport = rn->rport;
+
+       rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);
+       fc_remote_port_delete(rport);
+       ln->num_reg_rnodes--;
+
+       csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);
+}
+
+/*
+ * csio_lnode_async_event - Async events from local port.
+ * @ln: lnode representing local port.
+ *
+ * Async events from local node that FC transport/SCSI ML
+ * should be made aware of (Eg: RSCN).
+ */
+void
+csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)
+{
+       switch (fc_evt) {
+       case CSIO_LN_FC_RSCN:
+               /* Get payload of rscn from ln */
+               /* For each RSCN entry */
+                       /*
+                        * fc_host_post_event(shost,
+                        *                    fc_get_event_number(),
+                        *                    FCH_EVT_RSCN,
+                        *                    rscn_entry);
+                        */
+               break;
+       case CSIO_LN_FC_LINKUP:
+               /* send fc_host_post_event */
+               /* set vport state */
+               if (csio_is_npiv_ln(ln))
+                       csio_vport_set_state(ln);
+
+               break;
+       case CSIO_LN_FC_LINKDOWN:
+               /* send fc_host_post_event */
+               /* set vport state */
+               if (csio_is_npiv_ln(ln))
+                       csio_vport_set_state(ln);
+
+               break;
+       case CSIO_LN_FC_ATTRIB_UPDATE:
+               csio_fchost_attr_init(ln);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * csio_fchost_attr_init - Initialize FC transport attributes
+ * @ln: Lnode.
+ *
+ */
+void
+csio_fchost_attr_init(struct csio_lnode *ln)
+{
+       struct Scsi_Host  *shost = csio_ln_to_shost(ln);
+
+       fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));
+       fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));
+
+       fc_host_supported_classes(shost) = FC_COS_CLASS3;
+       fc_host_max_npiv_vports(shost) =
+                       (csio_lnode_to_hw(ln))->fres_info.max_vnps;
+       fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |
+               FC_PORTSPEED_1GBIT;
+
+       fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data);
+       memset(fc_host_supported_fc4s(shost), 0,
+               sizeof(fc_host_supported_fc4s(shost)));
+       fc_host_supported_fc4s(shost)[7] = 1;
+
+       memset(fc_host_active_fc4s(shost), 0,
+               sizeof(fc_host_active_fc4s(shost)));
+       fc_host_active_fc4s(shost)[7] = 1;
+}
+
+/*
+ * csio_get_host_port_id - sysfs entries for nport_id is
+ * populated/cached from this function
+ */
+static void
+csio_get_host_port_id(struct Scsi_Host *shost)
+{
+       struct csio_lnode *ln   = shost_priv(shost);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       spin_lock_irq(&hw->lock);
+       fc_host_port_id(shost) = ln->nport_id;
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_port_type - Return FC local port type.
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_port_type(struct Scsi_Host *shost)
+{
+       struct csio_lnode *ln = shost_priv(shost);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       spin_lock_irq(&hw->lock);
+       if (csio_is_npiv_ln(ln))
+               fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+       else
+               fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_port_state - Return FC local port state.
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_port_state(struct Scsi_Host *shost)
+{
+       struct csio_lnode *ln = shost_priv(shost);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       char state[16];
+
+       spin_lock_irq(&hw->lock);
+
+       csio_lnode_state_to_str(ln, state);
+       if (!strcmp(state, "READY"))
+               fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+       else if (!strcmp(state, "OFFLINE"))
+               fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+       else
+               fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_host_speed - Return link speed to FC transport.
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_speed(struct Scsi_Host *shost)
+{
+       struct csio_lnode *ln = shost_priv(shost);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       spin_lock_irq(&hw->lock);
+       switch (hw->pport[ln->portid].link_speed) {
+       case FW_PORT_CAP_SPEED_1G:
+               fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+               break;
+       case FW_PORT_CAP_SPEED_10G:
+               fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+               break;
+       default:
+               fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+               break;
+       }
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_host_fabric_name - Return fabric name
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_fabric_name(struct Scsi_Host *shost)
+{
+       struct csio_lnode *ln = shost_priv(shost);
+       struct csio_rnode *rn = NULL;
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       spin_lock_irq(&hw->lock);
+       rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);
+       if (rn)
+               fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));
+       else
+               fc_host_fabric_name(shost) = 0;
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_host_speed - Return FC transport statistics.
+ * @ln: Lnode.
+ *
+ */
+static struct fc_host_statistics *
+csio_get_stats(struct Scsi_Host *shost)
+{
+       struct csio_lnode *ln = shost_priv(shost);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct fc_host_statistics *fhs = &ln->fch_stats;
+       struct fw_fcoe_port_stats fcoe_port_stats;
+       uint64_t seconds;
+
+       memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));
+       csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);
+
+       fhs->tx_frames  += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) +
+                           be64_to_cpu(fcoe_port_stats.tx_mcast_frames) +
+                           be64_to_cpu(fcoe_port_stats.tx_ucast_frames) +
+                           be64_to_cpu(fcoe_port_stats.tx_offload_frames));
+       fhs->tx_words  += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) +
+                          be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) +
+                          be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) +
+                          be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) /
+                                                       CSIO_WORD_TO_BYTE;
+       fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) +
+                          be64_to_cpu(fcoe_port_stats.rx_mcast_frames) +
+                          be64_to_cpu(fcoe_port_stats.rx_ucast_frames));
+       fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) +
+                         be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) +
+                         be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) /
+                                                       CSIO_WORD_TO_BYTE;
+       fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames);
+       fhs->fcp_input_requests +=  ln->stats.n_input_requests;
+       fhs->fcp_output_requests +=  ln->stats.n_output_requests;
+       fhs->fcp_control_requests +=  ln->stats.n_control_requests;
+       fhs->fcp_input_megabytes +=  ln->stats.n_input_bytes >> 20;
+       fhs->fcp_output_megabytes +=  ln->stats.n_output_bytes >> 20;
+       fhs->link_failure_count = ln->stats.n_link_down;
+       /* Reset stats for the device */
+       seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;
+       do_div(seconds, 1000);
+       fhs->seconds_since_last_reset = seconds;
+
+       return fhs;
+}
+
+/*
+ * csio_set_rport_loss_tmo - Set the rport dev loss timeout
+ * @rport: fc rport.
+ * @timeout: new value for dev loss tmo.
+ *
+ * If timeout is non zero set the dev_loss_tmo to timeout, else set
+ * dev_loss_tmo to one.
+ */
+static void
+csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+       if (timeout)
+               rport->dev_loss_tmo = timeout;
+       else
+               rport->dev_loss_tmo = 1;
+}
+
+static void
+csio_vport_set_state(struct csio_lnode *ln)
+{
+       struct fc_vport *fc_vport = ln->fc_vport;
+       struct csio_lnode  *pln = ln->pln;
+       char state[16];
+
+       /* Set fc vport state based on phyiscal lnode */
+       csio_lnode_state_to_str(pln, state);
+       if (strcmp(state, "READY")) {
+               fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
+               return;
+       }
+
+       if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {
+               fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);
+               return;
+       }
+
+       /* Set fc vport state based on virtual lnode */
+       csio_lnode_state_to_str(ln, state);
+       if (strcmp(state, "READY")) {
+               fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
+               return;
+       }
+       fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
+}
+
+static int
+csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)
+{
+       struct csio_lnode *pln;
+       struct csio_mb  *mbp;
+       struct fw_fcoe_vnp_cmd *rsp;
+       int ret = 0;
+       int retry = 0;
+
+       /* Issue VNP cmd to alloc vport */
+       /* Allocate Mbox request */
+       spin_lock_irq(&hw->lock);
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       pln = ln->pln;
+       ln->fcf_flowid = pln->fcf_flowid;
+       ln->portid = pln->portid;
+
+       csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+                                   pln->fcf_flowid, pln->vnp_flowid, 0,
+                                   csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);
+
+       for (retry = 0; retry < 3; retry++) {
+               /* FW is expected to complete vnp cmd in immediate mode
+                * without much delay.
+                * Otherwise, there will be increase in IO latency since HW
+                * lock is held till completion of vnp mbox cmd.
+                */
+               ret = csio_mb_issue(hw, mbp);
+               if (ret != -EBUSY)
+                       break;
+
+               /* Retry if mbox returns busy */
+               spin_unlock_irq(&hw->lock);
+               msleep(2000);
+               spin_lock_irq(&hw->lock);
+       }
+
+       if (ret) {
+               csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
+               goto out_free;
+       }
+
+       /* Process Mbox response of VNP command */
+       rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+       if (FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
+               csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",
+                           FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)));
+               ret = -EINVAL;
+               goto out_free;
+       }
+
+       ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(
+                               ntohl(rsp->gen_wwn_to_vnpi));
+       memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
+       memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
+
+       csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);
+       csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",
+                   ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],
+                   ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],
+                   ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],
+                   ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);
+       csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",
+                   ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],
+                   ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],
+                   ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],
+                   ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);
+
+out_free:
+       mempool_free(mbp, hw->mb_mempool);
+out:
+       spin_unlock_irq(&hw->lock);
+       return ret;
+}
+
+static int
+csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)
+{
+       struct csio_lnode *pln;
+       struct csio_mb  *mbp;
+       struct fw_fcoe_vnp_cmd *rsp;
+       int ret = 0;
+       int retry = 0;
+
+       /* Issue VNP cmd to free vport */
+       /* Allocate Mbox request */
+
+       spin_lock_irq(&hw->lock);
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       pln = ln->pln;
+
+       csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+                                  ln->fcf_flowid, ln->vnp_flowid,
+                                  NULL);
+
+       for (retry = 0; retry < 3; retry++) {
+               ret = csio_mb_issue(hw, mbp);
+               if (ret != -EBUSY)
+                       break;
+
+               /* Retry if mbox returns busy */
+               spin_unlock_irq(&hw->lock);
+               msleep(2000);
+               spin_lock_irq(&hw->lock);
+       }
+
+       if (ret) {
+               csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
+               goto out_free;
+       }
+
+       /* Process Mbox response of VNP command */
+       rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+       if (FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
+               csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
+                           FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)));
+               ret = -EINVAL;
+       }
+
+out_free:
+       mempool_free(mbp, hw->mb_mempool);
+out:
+       spin_unlock_irq(&hw->lock);
+       return ret;
+}
+
+static int
+csio_vport_create(struct fc_vport *fc_vport, bool disable)
+{
+       struct Scsi_Host *shost = fc_vport->shost;
+       struct csio_lnode *pln = shost_priv(shost);
+       struct csio_lnode *ln = NULL;
+       struct csio_hw *hw = csio_lnode_to_hw(pln);
+       uint8_t wwn[8];
+       int ret = -1;
+
+       ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
+       if (!ln)
+               goto error;
+
+       if (fc_vport->node_name != 0) {
+               u64_to_wwn(fc_vport->node_name, wwn);
+
+               if (!CSIO_VALID_WWN(wwn)) {
+                       csio_ln_err(ln,
+                                   "vport create failed. Invalid wwnn\n");
+                       goto error;
+               }
+               memcpy(csio_ln_wwnn(ln), wwn, 8);
+       }
+
+       if (fc_vport->port_name != 0) {
+               u64_to_wwn(fc_vport->port_name, wwn);
+
+               if (!CSIO_VALID_WWN(wwn)) {
+                       csio_ln_err(ln,
+                                   "vport create failed. Invalid wwpn\n");
+                       goto error;
+               }
+
+               if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
+                       csio_ln_err(ln,
+                           "vport create failed. wwpn already exists\n");
+                       goto error;
+               }
+               memcpy(csio_ln_wwpn(ln), wwn, 8);
+       }
+
+       fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+
+       if (csio_fcoe_alloc_vnp(hw, ln))
+               goto error;
+
+       *(struct csio_lnode **)fc_vport->dd_data = ln;
+       ln->fc_vport = fc_vport;
+       if (!fc_vport->node_name)
+               fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
+       if (!fc_vport->port_name)
+               fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
+       csio_fchost_attr_init(ln);
+       return 0;
+error:
+       if (ln)
+               csio_shost_exit(ln);
+
+       return ret;
+}
+
+static int
+csio_vport_delete(struct fc_vport *fc_vport)
+{
+       struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
+       struct Scsi_Host *shost = csio_ln_to_shost(ln);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       int rmv;
+
+       spin_lock_irq(&hw->lock);
+       rmv = csio_is_hw_removing(hw);
+       spin_unlock_irq(&hw->lock);
+
+       if (rmv) {
+               csio_shost_exit(ln);
+               return 0;
+       }
+
+       /* Quiesce ios and send remove event to lnode */
+       scsi_block_requests(shost);
+       spin_lock_irq(&hw->lock);
+       csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
+       csio_lnode_close(ln);
+       spin_unlock_irq(&hw->lock);
+       scsi_unblock_requests(shost);
+
+       /* Free vnp */
+       if (fc_vport->vport_state !=  FC_VPORT_DISABLED)
+               csio_fcoe_free_vnp(hw, ln);
+
+       csio_shost_exit(ln);
+       return 0;
+}
+
+static int
+csio_vport_disable(struct fc_vport *fc_vport, bool disable)
+{
+       struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
+       struct Scsi_Host *shost = csio_ln_to_shost(ln);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       /* disable vport */
+       if (disable) {
+               /* Quiesce ios and send stop event to lnode */
+               scsi_block_requests(shost);
+               spin_lock_irq(&hw->lock);
+               csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
+               csio_lnode_stop(ln);
+               spin_unlock_irq(&hw->lock);
+               scsi_unblock_requests(shost);
+
+               /* Free vnp */
+               csio_fcoe_free_vnp(hw, ln);
+               fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
+               csio_ln_err(ln, "vport disabled\n");
+               return 0;
+       } else {
+               /* enable vport */
+               fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+               if (csio_fcoe_alloc_vnp(hw, ln)) {
+                       csio_ln_err(ln, "vport enabled failed.\n");
+                       return -1;
+               }
+               csio_ln_err(ln, "vport enabled\n");
+               return 0;
+       }
+}
+
+static void
+csio_dev_loss_tmo_callbk(struct fc_rport *rport)
+{
+       struct csio_rnode *rn;
+       struct csio_hw *hw;
+       struct csio_lnode *ln;
+
+       rn = *((struct csio_rnode **)rport->dd_data);
+       ln = csio_rnode_to_lnode(rn);
+       hw = csio_lnode_to_hw(ln);
+
+       spin_lock_irq(&hw->lock);
+
+       /* return if driver is being removed or same rnode comes back online */
+       if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
+               goto out;
+
+       csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
+                   rn, rn->nport_id, csio_rn_flowid(rn));
+
+       CSIO_INC_STATS(ln, n_dev_loss_tmo);
+
+       /*
+        * enqueue devloss event to event worker thread to serialize all
+        * rnode events.
+        */
+       if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
+               CSIO_INC_STATS(hw, n_evt_drop);
+               goto out;
+       }
+
+       if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+               hw->flags |= CSIO_HWF_FWEVT_PENDING;
+               spin_unlock_irq(&hw->lock);
+               schedule_work(&hw->evtq_work);
+               return;
+       }
+
+out:
+       spin_unlock_irq(&hw->lock);
+}
+
+/* FC transport functions template - Physical port */
+struct fc_function_template csio_fc_transport_funcs = {
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_supported_fc4s = 1,
+       .show_host_maxframe_size = 1,
+
+       .get_host_port_id = csio_get_host_port_id,
+       .show_host_port_id = 1,
+
+       .get_host_port_type = csio_get_host_port_type,
+       .show_host_port_type = 1,
+
+       .get_host_port_state = csio_get_host_port_state,
+       .show_host_port_state = 1,
+
+       .show_host_active_fc4s = 1,
+       .get_host_speed = csio_get_host_speed,
+       .show_host_speed = 1,
+       .get_host_fabric_name = csio_get_host_fabric_name,
+       .show_host_fabric_name = 1,
+
+       .get_fc_host_stats = csio_get_stats,
+
+       .dd_fcrport_size = sizeof(struct csio_rnode *),
+       .show_rport_maxframe_size = 1,
+       .show_rport_supported_classes = 1,
+
+       .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
+       .show_rport_dev_loss_tmo = 1,
+
+       .show_starget_port_id = 1,
+       .show_starget_node_name = 1,
+       .show_starget_port_name = 1,
+
+       .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
+       .dd_fcvport_size = sizeof(struct csio_lnode *),
+
+       .vport_create = csio_vport_create,
+       .vport_disable = csio_vport_disable,
+       .vport_delete = csio_vport_delete,
+};
+
+/* FC transport functions template - Virtual  port */
+struct fc_function_template csio_fc_transport_vport_funcs = {
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_supported_fc4s = 1,
+       .show_host_maxframe_size = 1,
+
+       .get_host_port_id = csio_get_host_port_id,
+       .show_host_port_id = 1,
+
+       .get_host_port_type = csio_get_host_port_type,
+       .show_host_port_type = 1,
+
+       .get_host_port_state = csio_get_host_port_state,
+       .show_host_port_state = 1,
+       .show_host_active_fc4s = 1,
+
+       .get_host_speed = csio_get_host_speed,
+       .show_host_speed = 1,
+
+       .get_host_fabric_name = csio_get_host_fabric_name,
+       .show_host_fabric_name = 1,
+
+       .get_fc_host_stats = csio_get_stats,
+
+       .dd_fcrport_size = sizeof(struct csio_rnode *),
+       .show_rport_maxframe_size = 1,
+       .show_rport_supported_classes = 1,
+
+       .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
+       .show_rport_dev_loss_tmo = 1,
+
+       .show_starget_port_id = 1,
+       .show_starget_node_name = 1,
+       .show_starget_port_name = 1,
+
+       .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
+
+};
diff --git a/drivers/scsi/csiostor/csio_defs.h b/drivers/scsi/csiostor/csio_defs.h
new file mode 100644 (file)
index 0000000..c38017b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_DEFS_H__
+#define __CSIO_DEFS_H__
+
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+
+#define CSIO_INVALID_IDX               0xFFFFFFFF
+#define CSIO_INC_STATS(elem, val)      ((elem)->stats.val++)
+#define CSIO_DEC_STATS(elem, val)      ((elem)->stats.val--)
+#define CSIO_VALID_WWN(__n)            ((*__n >> 4) == 0x5 ? true : false)
+#define CSIO_DID_MASK                  0xFFFFFF
+#define CSIO_WORD_TO_BYTE              4
+
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+       return readl(addr) + ((u64)readl(addr + 4) << 32);
+}
+
+static inline void writeq(u64 val, void __iomem *addr)
+{
+       writel(val, addr);
+       writel(val >> 32, addr + 4);
+}
+#endif
+
+static inline int
+csio_list_deleted(struct list_head *list)
+{
+       return ((list->next == list) && (list->prev == list));
+}
+
+#define csio_list_next(elem)   (((struct list_head *)(elem))->next)
+#define csio_list_prev(elem)   (((struct list_head *)(elem))->prev)
+
+/* State machine */
+typedef void (*csio_sm_state_t)(void *, uint32_t);
+
+struct csio_sm {
+       struct list_head        sm_list;
+       csio_sm_state_t         sm_state;
+};
+
+static inline void
+csio_set_state(void *smp, void *state)
+{
+       ((struct csio_sm *)smp)->sm_state = (csio_sm_state_t)state;
+}
+
+static inline void
+csio_init_state(struct csio_sm *smp, void *state)
+{
+       csio_set_state(smp, state);
+}
+
+static inline void
+csio_post_event(void *smp, uint32_t evt)
+{
+       ((struct csio_sm *)smp)->sm_state(smp, evt);
+}
+
+static inline csio_sm_state_t
+csio_get_state(void *smp)
+{
+       return ((struct csio_sm *)smp)->sm_state;
+}
+
+static inline bool
+csio_match_state(void *smp, void *state)
+{
+       return (csio_get_state(smp) == (csio_sm_state_t)state);
+}
+
+#define        CSIO_ASSERT(cond)               BUG_ON(!(cond))
+
+#ifdef __CSIO_DEBUG__
+#define CSIO_DB_ASSERT(__c)            CSIO_ASSERT((__c))
+#else
+#define CSIO_DB_ASSERT(__c)
+#endif
+
+#endif /* ifndef __CSIO_DEFS_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
new file mode 100644 (file)
index 0000000..8ecdb94
--- /dev/null
@@ -0,0 +1,4395 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/firmware.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+
+int csio_force_master;
+int csio_dbg_level = 0xFEFF;
+unsigned int csio_port_mask = 0xf;
+
+/* Default FW event queue entries. */
+static uint32_t csio_evtq_sz = CSIO_EVTQ_SIZE;
+
+/* Default MSI param level */
+int csio_msi = 2;
+
+/* FCoE function instances */
+static int dev_num;
+
+/* FCoE Adapter types & its description */
+static const struct csio_adap_desc csio_fcoe_adapters[] = {
+       {"T440-Dbg 10G", "Chelsio T440-Dbg 10G [FCoE]"},
+       {"T420-CR 10G", "Chelsio T420-CR 10G [FCoE]"},
+       {"T422-CR 10G/1G", "Chelsio T422-CR 10G/1G [FCoE]"},
+       {"T440-CR 10G", "Chelsio T440-CR 10G [FCoE]"},
+       {"T420-BCH 10G", "Chelsio T420-BCH 10G [FCoE]"},
+       {"T440-BCH 10G", "Chelsio T440-BCH 10G [FCoE]"},
+       {"T440-CH 10G", "Chelsio T440-CH 10G [FCoE]"},
+       {"T420-SO 10G", "Chelsio T420-SO 10G [FCoE]"},
+       {"T420-CX4 10G", "Chelsio T420-CX4 10G [FCoE]"},
+       {"T420-BT 10G", "Chelsio T420-BT 10G [FCoE]"},
+       {"T404-BT 1G", "Chelsio T404-BT 1G [FCoE]"},
+       {"B420-SR 10G", "Chelsio B420-SR 10G [FCoE]"},
+       {"B404-BT 1G", "Chelsio B404-BT 1G [FCoE]"},
+       {"T480-CR 10G", "Chelsio T480-CR 10G [FCoE]"},
+       {"T440-LP-CR 10G", "Chelsio T440-LP-CR 10G [FCoE]"},
+       {"T4 FPGA", "Chelsio T4 FPGA [FCoE]"}
+};
+
+static void csio_mgmtm_cleanup(struct csio_mgmtm *);
+static void csio_hw_mbm_cleanup(struct csio_hw *);
+
+/* State machine forward declarations */
+static void csio_hws_uninit(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_configuring(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_initializing(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_ready(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_quiescing(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_quiesced(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_resetting(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_removing(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_pcierr(struct csio_hw *, enum csio_hw_ev);
+
+static void csio_hw_initialize(struct csio_hw *hw);
+static void csio_evtq_stop(struct csio_hw *hw);
+static void csio_evtq_start(struct csio_hw *hw);
+
+int csio_is_hw_ready(struct csio_hw *hw)
+{
+       return csio_match_state(hw, csio_hws_ready);
+}
+
+int csio_is_hw_removing(struct csio_hw *hw)
+{
+       return csio_match_state(hw, csio_hws_removing);
+}
+
+
+/*
+ *     csio_hw_wait_op_done_val - wait until an operation is completed
+ *     @hw: the HW module
+ *     @reg: the register to check for completion
+ *     @mask: a single-bit field within @reg that indicates completion
+ *     @polarity: the value of the field when the operation is completed
+ *     @attempts: number of check iterations
+ *     @delay: delay in usecs between iterations
+ *     @valp: where to store the value of the register at completion time
+ *
+ *     Wait until an operation is completed by checking a bit in a register
+ *     up to @attempts times.  If @valp is not NULL the value of the register
+ *     at the time it indicated completion is stored there.  Returns 0 if the
+ *     operation completes and -EAGAIN otherwise.
+ */
+static int
+csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask,
+                        int polarity, int attempts, int delay, uint32_t *valp)
+{
+       uint32_t val;
+       while (1) {
+               val = csio_rd_reg32(hw, reg);
+
+               if (!!(val & mask) == polarity) {
+                       if (valp)
+                               *valp = val;
+                       return 0;
+               }
+
+               if (--attempts == 0)
+                       return -EAGAIN;
+               if (delay)
+                       udelay(delay);
+       }
+}
+
+void
+csio_set_reg_field(struct csio_hw *hw, uint32_t reg, uint32_t mask,
+                  uint32_t value)
+{
+       uint32_t val = csio_rd_reg32(hw, reg) & ~mask;
+
+       csio_wr_reg32(hw, val | value, reg);
+       /* Flush */
+       csio_rd_reg32(hw, reg);
+
+}
+
+/*
+ *     csio_hw_mc_read - read from MC through backdoor accesses
+ *     @hw: the hw module
+ *     @addr: address of first byte requested
+ *     @data: 64 bytes of data containing the requested address
+ *     @ecc: where to store the corresponding 64-bit ECC word
+ *
+ *     Read 64 bytes of data from MC starting at a 64-byte-aligned address
+ *     that covers the requested address @addr.  If @parity is not %NULL it
+ *     is assigned the 64-bit ECC word for the read data.
+ */
+int
+csio_hw_mc_read(struct csio_hw *hw, uint32_t addr, __be32 *data,
+               uint64_t *ecc)
+{
+       int i;
+
+       if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
+               return -EBUSY;
+       csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
+       csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
+       csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
+       csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST |  BIST_CMD_GAP(1),
+                     MC_BIST_CMD);
+       i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
+                0, 10, 1, NULL);
+       if (i)
+               return i;
+
+#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+
+       for (i = 15; i >= 0; i--)
+               *data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
+       if (ecc)
+               *ecc = csio_rd_reg64(hw, MC_DATA(16));
+#undef MC_DATA
+       return 0;
+}
+
+/*
+ *     csio_hw_edc_read - read from EDC through backdoor accesses
+ *     @hw: the hw module
+ *     @idx: which EDC to access
+ *     @addr: address of first byte requested
+ *     @data: 64 bytes of data containing the requested address
+ *     @ecc: where to store the corresponding 64-bit ECC word
+ *
+ *     Read 64 bytes of data from EDC starting at a 64-byte-aligned address
+ *     that covers the requested address @addr.  If @parity is not %NULL it
+ *     is assigned the 64-bit ECC word for the read data.
+ */
+int
+csio_hw_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+               uint64_t *ecc)
+{
+       int i;
+
+       idx *= EDC_STRIDE;
+       if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
+               return -EBUSY;
+       csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
+       csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
+       csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
+       csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
+                    EDC_BIST_CMD + idx);
+       i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
+                0, 10, 1, NULL);
+       if (i)
+               return i;
+
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+
+       for (i = 15; i >= 0; i--)
+               *data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
+       if (ecc)
+               *ecc = csio_rd_reg64(hw, EDC_DATA(16));
+#undef EDC_DATA
+       return 0;
+}
+
+/*
+ *      csio_mem_win_rw - read/write memory through PCIE memory window
+ *      @hw: the adapter
+ *      @addr: address of first byte requested
+ *      @data: MEMWIN0_APERTURE bytes of data containing the requested address
+ *      @dir: direction of transfer 1 => read, 0 => write
+ *
+ *      Read/write MEMWIN0_APERTURE bytes of data from MC starting at a
+ *      MEMWIN0_APERTURE-byte-aligned address that covers the requested
+ *      address @addr.
+ */
+static int
+csio_mem_win_rw(struct csio_hw *hw, u32 addr, u32 *data, int dir)
+{
+       int i;
+
+       /*
+        * Setup offset into PCIE memory window.  Address must be a
+        * MEMWIN0_APERTURE-byte-aligned address.  (Read back MA register to
+        * ensure that changes propagate before we attempt to use the new
+        * values.)
+        */
+       csio_wr_reg32(hw, addr & ~(MEMWIN0_APERTURE - 1),
+                       PCIE_MEM_ACCESS_OFFSET);
+       csio_rd_reg32(hw, PCIE_MEM_ACCESS_OFFSET);
+
+       /* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
+       for (i = 0; i < MEMWIN0_APERTURE; i = i + sizeof(__be32)) {
+               if (dir)
+                       *data++ = csio_rd_reg32(hw, (MEMWIN0_BASE + i));
+               else
+                       csio_wr_reg32(hw, *data++, (MEMWIN0_BASE + i));
+       }
+
+       return 0;
+}
+
+/*
+ *      csio_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
+ *      @hw: the csio_hw
+ *      @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC
+ *      @addr: address within indicated memory type
+ *      @len: amount of memory to transfer
+ *      @buf: host memory buffer
+ *      @dir: direction of transfer 1 => read, 0 => write
+ *
+ *      Reads/writes an [almost] arbitrary memory region in the firmware: the
+ *      firmware memory address, length and host buffer must be aligned on
+ *      32-bit boudaries.  The memory is transferred as a raw byte sequence
+ *      from/to the firmware's memory.  If this memory contains data
+ *      structures which contain multi-byte integers, it's the callers
+ *      responsibility to perform appropriate byte order conversions.
+ */
+static int
+csio_memory_rw(struct csio_hw *hw, int mtype, u32 addr, u32 len,
+               uint32_t *buf, int dir)
+{
+       uint32_t pos, start, end, offset, memoffset;
+       int ret;
+       uint32_t *data;
+
+       /*
+        * Argument sanity checks ...
+        */
+       if ((addr & 0x3) || (len & 0x3))
+               return -EINVAL;
+
+       data = kzalloc(MEMWIN0_APERTURE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       /* Offset into the region of memory which is being accessed
+        * MEM_EDC0 = 0
+        * MEM_EDC1 = 1
+        * MEM_MC   = 2
+        */
+       memoffset = (mtype * (5 * 1024 * 1024));
+
+       /* Determine the PCIE_MEM_ACCESS_OFFSET */
+       addr = addr + memoffset;
+
+       /*
+        * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes
+        * at a time so we need to round down the start and round up the end.
+        * We'll start copying out of the first line at (addr - start) a word
+        * at a time.
+        */
+       start = addr & ~(MEMWIN0_APERTURE-1);
+       end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1);
+       offset = (addr - start)/sizeof(__be32);
+
+       for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
+               /*
+                * If we're writing, copy the data from the caller's memory
+                * buffer
+                */
+               if (!dir) {
+                       /*
+                        * If we're doing a partial write, then we need to do
+                        * a read-modify-write ...
+                        */
+                       if (offset || len < MEMWIN0_APERTURE) {
+                               ret = csio_mem_win_rw(hw, pos, data, 1);
+                               if (ret) {
+                                       kfree(data);
+                                       return ret;
+                               }
+                       }
+                       while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
+                                                               len > 0) {
+                               data[offset++] = *buf++;
+                               len -= sizeof(__be32);
+                       }
+               }
+
+               /*
+                * Transfer a block of memory and bail if there's an error.
+                */
+               ret = csio_mem_win_rw(hw, pos, data, dir);
+               if (ret) {
+                       kfree(data);
+                       return ret;
+               }
+
+               /*
+                * If we're reading, copy the data into the caller's memory
+                * buffer.
+                */
+               if (dir)
+                       while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
+                                                               len > 0) {
+                               *buf++ = data[offset++];
+                               len -= sizeof(__be32);
+                       }
+       }
+
+       kfree(data);
+
+       return 0;
+}
+
+static int
+csio_memory_write(struct csio_hw *hw, int mtype, u32 addr, u32 len, u32 *buf)
+{
+       return csio_memory_rw(hw, mtype, addr, len, buf, 0);
+}
+
+/*
+ * EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
+ */
+#define EEPROM_MAX_RD_POLL 40
+#define EEPROM_MAX_WR_POLL 6
+#define EEPROM_STAT_ADDR   0x7bfc
+#define VPD_BASE           0x400
+#define VPD_BASE_OLD      0
+#define VPD_LEN            512
+#define VPD_INFO_FLD_HDR_SIZE  3
+
+/*
+ *     csio_hw_seeprom_read - read a serial EEPROM location
+ *     @hw: hw to read
+ *     @addr: EEPROM virtual address
+ *     @data: where to store the read data
+ *
+ *     Read a 32-bit word from a location in serial EEPROM using the card's PCI
+ *     VPD capability.  Note that this function must be called with a virtual
+ *     address.
+ */
+static int
+csio_hw_seeprom_read(struct csio_hw *hw, uint32_t addr, uint32_t *data)
+{
+       uint16_t val = 0;
+       int attempts = EEPROM_MAX_RD_POLL;
+       uint32_t base = hw->params.pci.vpd_cap_addr;
+
+       if (addr >= EEPROMVSIZE || (addr & 3))
+               return -EINVAL;
+
+       pci_write_config_word(hw->pdev, base + PCI_VPD_ADDR, (uint16_t)addr);
+
+       do {
+               udelay(10);
+               pci_read_config_word(hw->pdev, base + PCI_VPD_ADDR, &val);
+       } while (!(val & PCI_VPD_ADDR_F) && --attempts);
+
+       if (!(val & PCI_VPD_ADDR_F)) {
+               csio_err(hw, "reading EEPROM address 0x%x failed\n", addr);
+               return -EINVAL;
+       }
+
+       pci_read_config_dword(hw->pdev, base + PCI_VPD_DATA, data);
+       *data = le32_to_cpu(*data);
+
+       return 0;
+}
+
+/*
+ * Partial EEPROM Vital Product Data structure.  Includes only the ID and
+ * VPD-R sections.
+ */
+struct t4_vpd_hdr {
+       u8  id_tag;
+       u8  id_len[2];
+       u8  id_data[ID_LEN];
+       u8  vpdr_tag;
+       u8  vpdr_len[2];
+};
+
+/*
+ *     csio_hw_get_vpd_keyword_val - Locates an information field keyword in
+ *                                   the VPD
+ *     @v: Pointer to buffered vpd data structure
+ *     @kw: The keyword to search for
+ *
+ *     Returns the value of the information field keyword or
+ *     -EINVAL otherwise.
+ */
+static int
+csio_hw_get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
+{
+       int32_t i;
+       int32_t offset , len;
+       const uint8_t *buf = &v->id_tag;
+       const uint8_t *vpdr_len = &v->vpdr_tag;
+       offset = sizeof(struct t4_vpd_hdr);
+       len =  (uint16_t)vpdr_len[1] + ((uint16_t)vpdr_len[2] << 8);
+
+       if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN)
+               return -EINVAL;
+
+       for (i = offset; (i + VPD_INFO_FLD_HDR_SIZE) <= (offset + len);) {
+               if (memcmp(buf + i , kw, 2) == 0) {
+                       i += VPD_INFO_FLD_HDR_SIZE;
+                       return i;
+               }
+
+               i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
+       }
+
+       return -EINVAL;
+}
+
+static int
+csio_pci_capability(struct pci_dev *pdev, int cap, int *pos)
+{
+       *pos = pci_find_capability(pdev, cap);
+       if (*pos)
+               return 0;
+
+       return -1;
+}
+
+/*
+ *     csio_hw_get_vpd_params - read VPD parameters from VPD EEPROM
+ *     @hw: HW module
+ *     @p: where to store the parameters
+ *
+ *     Reads card parameters stored in VPD EEPROM.
+ */
+static int
+csio_hw_get_vpd_params(struct csio_hw *hw, struct csio_vpd *p)
+{
+       int i, ret, ec, sn, addr;
+       uint8_t *vpd, csum;
+       const struct t4_vpd_hdr *v;
+       /* To get around compilation warning from strstrip */
+       char *s;
+
+       if (csio_is_valid_vpd(hw))
+               return 0;
+
+       ret = csio_pci_capability(hw->pdev, PCI_CAP_ID_VPD,
+                                 &hw->params.pci.vpd_cap_addr);
+       if (ret)
+               return -EINVAL;
+
+       vpd = kzalloc(VPD_LEN, GFP_ATOMIC);
+       if (vpd == NULL)
+               return -ENOMEM;
+
+       /*
+        * Card information normally starts at VPD_BASE but early cards had
+        * it at 0.
+        */
+       ret = csio_hw_seeprom_read(hw, VPD_BASE, (uint32_t *)(vpd));
+       addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
+
+       for (i = 0; i < VPD_LEN; i += 4) {
+               ret = csio_hw_seeprom_read(hw, addr + i, (uint32_t *)(vpd + i));
+               if (ret) {
+                       kfree(vpd);
+                       return ret;
+               }
+       }
+
+       /* Reset the VPD flag! */
+       hw->flags &= (~CSIO_HWF_VPD_VALID);
+
+       v = (const struct t4_vpd_hdr *)vpd;
+
+#define FIND_VPD_KW(var, name) do { \
+       var = csio_hw_get_vpd_keyword_val(v, name); \
+       if (var < 0) { \
+               csio_err(hw, "missing VPD keyword " name "\n"); \
+               kfree(vpd); \
+               return -EINVAL; \
+       } \
+} while (0)
+
+       FIND_VPD_KW(i, "RV");
+       for (csum = 0; i >= 0; i--)
+               csum += vpd[i];
+
+       if (csum) {
+               csio_err(hw, "corrupted VPD EEPROM, actual csum %u\n", csum);
+               kfree(vpd);
+               return -EINVAL;
+       }
+       FIND_VPD_KW(ec, "EC");
+       FIND_VPD_KW(sn, "SN");
+#undef FIND_VPD_KW
+
+       memcpy(p->id, v->id_data, ID_LEN);
+       s = strstrip(p->id);
+       memcpy(p->ec, vpd + ec, EC_LEN);
+       s = strstrip(p->ec);
+       i = vpd[sn - VPD_INFO_FLD_HDR_SIZE + 2];
+       memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
+       s = strstrip(p->sn);
+
+       csio_valid_vpd_copied(hw);
+
+       kfree(vpd);
+       return 0;
+}
+
+/*
+ *     csio_hw_sf1_read - read data from the serial flash
+ *     @hw: the HW module
+ *     @byte_cnt: number of bytes to read
+ *     @cont: whether another operation will be chained
+ *      @lock: whether to lock SF for PL access only
+ *     @valp: where to store the read data
+ *
+ *     Reads up to 4 bytes of data from the serial flash.  The location of
+ *     the read needs to be specified prior to calling this by issuing the
+ *     appropriate commands to the serial flash.
+ */
+static int
+csio_hw_sf1_read(struct csio_hw *hw, uint32_t byte_cnt, int32_t cont,
+                int32_t lock, uint32_t *valp)
+{
+       int ret;
+
+       if (!byte_cnt || byte_cnt > 4)
+               return -EINVAL;
+       if (csio_rd_reg32(hw, SF_OP) & SF_BUSY)
+               return -EBUSY;
+
+       cont = cont ? SF_CONT : 0;
+       lock = lock ? SF_LOCK : 0;
+
+       csio_wr_reg32(hw, lock | cont | BYTECNT(byte_cnt - 1), SF_OP);
+       ret = csio_hw_wait_op_done_val(hw, SF_OP, SF_BUSY, 0, SF_ATTEMPTS,
+                                        10, NULL);
+       if (!ret)
+               *valp = csio_rd_reg32(hw, SF_DATA);
+       return ret;
+}
+
+/*
+ *     csio_hw_sf1_write - write data to the serial flash
+ *     @hw: the HW module
+ *     @byte_cnt: number of bytes to write
+ *     @cont: whether another operation will be chained
+ *      @lock: whether to lock SF for PL access only
+ *     @val: value to write
+ *
+ *     Writes up to 4 bytes of data to the serial flash.  The location of
+ *     the write needs to be specified prior to calling this by issuing the
+ *     appropriate commands to the serial flash.
+ */
+static int
+csio_hw_sf1_write(struct csio_hw *hw, uint32_t byte_cnt, uint32_t cont,
+                 int32_t lock, uint32_t val)
+{
+       if (!byte_cnt || byte_cnt > 4)
+               return -EINVAL;
+       if (csio_rd_reg32(hw, SF_OP) & SF_BUSY)
+               return -EBUSY;
+
+       cont = cont ? SF_CONT : 0;
+       lock = lock ? SF_LOCK : 0;
+
+       csio_wr_reg32(hw, val, SF_DATA);
+       csio_wr_reg32(hw, cont | BYTECNT(byte_cnt - 1) | OP_WR | lock, SF_OP);
+
+       return csio_hw_wait_op_done_val(hw, SF_OP, SF_BUSY, 0, SF_ATTEMPTS,
+                                       10, NULL);
+}
+
+/*
+ *     csio_hw_flash_wait_op - wait for a flash operation to complete
+ *     @hw: the HW module
+ *     @attempts: max number of polls of the status register
+ *     @delay: delay between polls in ms
+ *
+ *     Wait for a flash operation to complete by polling the status register.
+ */
+static int
+csio_hw_flash_wait_op(struct csio_hw *hw, int32_t attempts, int32_t delay)
+{
+       int ret;
+       uint32_t status;
+
+       while (1) {
+               ret = csio_hw_sf1_write(hw, 1, 1, 1, SF_RD_STATUS);
+               if (ret != 0)
+                       return ret;
+
+               ret = csio_hw_sf1_read(hw, 1, 0, 1, &status);
+               if (ret != 0)
+                       return ret;
+
+               if (!(status & 1))
+                       return 0;
+               if (--attempts == 0)
+                       return -EAGAIN;
+               if (delay)
+                       msleep(delay);
+       }
+}
+
+/*
+ *     csio_hw_read_flash - read words from serial flash
+ *     @hw: the HW module
+ *     @addr: the start address for the read
+ *     @nwords: how many 32-bit words to read
+ *     @data: where to store the read data
+ *     @byte_oriented: whether to store data as bytes or as words
+ *
+ *     Read the specified number of 32-bit words from the serial flash.
+ *     If @byte_oriented is set the read data is stored as a byte array
+ *     (i.e., big-endian), otherwise as 32-bit words in the platform's
+ *     natural endianess.
+ */
+static int
+csio_hw_read_flash(struct csio_hw *hw, uint32_t addr, uint32_t nwords,
+                 uint32_t *data, int32_t byte_oriented)
+{
+       int ret;
+
+       if (addr + nwords * sizeof(uint32_t) > hw->params.sf_size || (addr & 3))
+               return -EINVAL;
+
+       addr = swab32(addr) | SF_RD_DATA_FAST;
+
+       ret = csio_hw_sf1_write(hw, 4, 1, 0, addr);
+       if (ret != 0)
+               return ret;
+
+       ret = csio_hw_sf1_read(hw, 1, 1, 0, data);
+       if (ret != 0)
+               return ret;
+
+       for ( ; nwords; nwords--, data++) {
+               ret = csio_hw_sf1_read(hw, 4, nwords > 1, nwords == 1, data);
+               if (nwords == 1)
+                       csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+               if (ret)
+                       return ret;
+               if (byte_oriented)
+                       *data = htonl(*data);
+       }
+       return 0;
+}
+
+/*
+ *     csio_hw_write_flash - write up to a page of data to the serial flash
+ *     @hw: the hw
+ *     @addr: the start address to write
+ *     @n: length of data to write in bytes
+ *     @data: the data to write
+ *
+ *     Writes up to a page of data (256 bytes) to the serial flash starting
+ *     at the given address.  All the data must be written to the same page.
+ */
+static int
+csio_hw_write_flash(struct csio_hw *hw, uint32_t addr,
+                   uint32_t n, const uint8_t *data)
+{
+       int ret = -EINVAL;
+       uint32_t buf[64];
+       uint32_t i, c, left, val, offset = addr & 0xff;
+
+       if (addr >= hw->params.sf_size || offset + n > SF_PAGE_SIZE)
+               return -EINVAL;
+
+       val = swab32(addr) | SF_PROG_PAGE;
+
+       ret = csio_hw_sf1_write(hw, 1, 0, 1, SF_WR_ENABLE);
+       if (ret != 0)
+               goto unlock;
+
+       ret = csio_hw_sf1_write(hw, 4, 1, 1, val);
+       if (ret != 0)
+               goto unlock;
+
+       for (left = n; left; left -= c) {
+               c = min(left, 4U);
+               for (val = 0, i = 0; i < c; ++i)
+                       val = (val << 8) + *data++;
+
+               ret = csio_hw_sf1_write(hw, c, c != left, 1, val);
+               if (ret)
+                       goto unlock;
+       }
+       ret = csio_hw_flash_wait_op(hw, 8, 1);
+       if (ret)
+               goto unlock;
+
+       csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+
+       /* Read the page to verify the write succeeded */
+       ret = csio_hw_read_flash(hw, addr & ~0xff, ARRAY_SIZE(buf), buf, 1);
+       if (ret)
+               return ret;
+
+       if (memcmp(data - n, (uint8_t *)buf + offset, n)) {
+               csio_err(hw,
+                        "failed to correctly write the flash page at %#x\n",
+                        addr);
+               return -EINVAL;
+       }
+
+       return 0;
+
+unlock:
+       csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+       return ret;
+}
+
+/*
+ *     csio_hw_flash_erase_sectors - erase a range of flash sectors
+ *     @hw: the HW module
+ *     @start: the first sector to erase
+ *     @end: the last sector to erase
+ *
+ *     Erases the sectors in the given inclusive range.
+ */
+static int
+csio_hw_flash_erase_sectors(struct csio_hw *hw, int32_t start, int32_t end)
+{
+       int ret = 0;
+
+       while (start <= end) {
+
+               ret = csio_hw_sf1_write(hw, 1, 0, 1, SF_WR_ENABLE);
+               if (ret != 0)
+                       goto out;
+
+               ret = csio_hw_sf1_write(hw, 4, 0, 1,
+                                       SF_ERASE_SECTOR | (start << 8));
+               if (ret != 0)
+                       goto out;
+
+               ret = csio_hw_flash_wait_op(hw, 14, 500);
+               if (ret != 0)
+                       goto out;
+
+               start++;
+       }
+out:
+       if (ret)
+               csio_err(hw, "erase of flash sector %d failed, error %d\n",
+                        start, ret);
+       csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+       return 0;
+}
+
+/*
+ *     csio_hw_flash_cfg_addr - return the address of the flash
+ *                             configuration file
+ *     @hw: the HW module
+ *
+ *     Return the address within the flash where the Firmware Configuration
+ *     File is stored.
+ */
+static unsigned int
+csio_hw_flash_cfg_addr(struct csio_hw *hw)
+{
+       if (hw->params.sf_size == 0x100000)
+               return FPGA_FLASH_CFG_OFFSET;
+       else
+               return FLASH_CFG_OFFSET;
+}
+
+static void
+csio_hw_print_fw_version(struct csio_hw *hw, char *str)
+{
+       csio_info(hw, "%s: %u.%u.%u.%u\n", str,
+                   FW_HDR_FW_VER_MAJOR_GET(hw->fwrev),
+                   FW_HDR_FW_VER_MINOR_GET(hw->fwrev),
+                   FW_HDR_FW_VER_MICRO_GET(hw->fwrev),
+                   FW_HDR_FW_VER_BUILD_GET(hw->fwrev));
+}
+
+/*
+ * csio_hw_get_fw_version - read the firmware version
+ * @hw: HW module
+ * @vers: where to place the version
+ *
+ * Reads the FW version from flash.
+ */
+static int
+csio_hw_get_fw_version(struct csio_hw *hw, uint32_t *vers)
+{
+       return csio_hw_read_flash(hw, FW_IMG_START +
+                                 offsetof(struct fw_hdr, fw_ver), 1,
+                                 vers, 0);
+}
+
+/*
+ *     csio_hw_get_tp_version - read the TP microcode version
+ *     @hw: HW module
+ *     @vers: where to place the version
+ *
+ *     Reads the TP microcode version from flash.
+ */
+static int
+csio_hw_get_tp_version(struct csio_hw *hw, u32 *vers)
+{
+       return csio_hw_read_flash(hw, FLASH_FW_START +
+                       offsetof(struct fw_hdr, tp_microcode_ver), 1,
+                       vers, 0);
+}
+
+/*
+ *     csio_hw_check_fw_version - check if the FW is compatible with
+ *                                this driver
+ *     @hw: HW module
+ *
+ *     Checks if an adapter's FW is compatible with the driver.  Returns 0
+ *     if there's exact match, a negative error if the version could not be
+ *     read or there's a major/minor version mismatch/minor.
+ */
+static int
+csio_hw_check_fw_version(struct csio_hw *hw)
+{
+       int ret, major, minor, micro;
+
+       ret = csio_hw_get_fw_version(hw, &hw->fwrev);
+       if (!ret)
+               ret = csio_hw_get_tp_version(hw, &hw->tp_vers);
+       if (ret)
+               return ret;
+
+       major = FW_HDR_FW_VER_MAJOR_GET(hw->fwrev);
+       minor = FW_HDR_FW_VER_MINOR_GET(hw->fwrev);
+       micro = FW_HDR_FW_VER_MICRO_GET(hw->fwrev);
+
+       if (major != FW_VERSION_MAJOR) {            /* major mismatch - fail */
+               csio_err(hw, "card FW has major version %u, driver wants %u\n",
+                        major, FW_VERSION_MAJOR);
+               return -EINVAL;
+       }
+
+       if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
+               return 0;        /* perfect match */
+
+       /* Minor/micro version mismatch */
+       return -EINVAL;
+}
+
+/*
+ * csio_hw_fw_dload - download firmware.
+ * @hw: HW module
+ * @fw_data: firmware image to write.
+ * @size: image size
+ *
+ * Write the supplied firmware image to the card's serial flash.
+ */
+static int
+csio_hw_fw_dload(struct csio_hw *hw, uint8_t *fw_data, uint32_t size)
+{
+       uint32_t csum;
+       int32_t addr;
+       int ret;
+       uint32_t i;
+       uint8_t first_page[SF_PAGE_SIZE];
+       const __be32 *p = (const __be32 *)fw_data;
+       struct fw_hdr *hdr = (struct fw_hdr *)fw_data;
+       uint32_t sf_sec_size;
+
+       if ((!hw->params.sf_size) || (!hw->params.sf_nsec)) {
+               csio_err(hw, "Serial Flash data invalid\n");
+               return -EINVAL;
+       }
+
+       if (!size) {
+               csio_err(hw, "FW image has no data\n");
+               return -EINVAL;
+       }
+
+       if (size & 511) {
+               csio_err(hw, "FW image size not multiple of 512 bytes\n");
+               return -EINVAL;
+       }
+
+       if (ntohs(hdr->len512) * 512 != size) {
+               csio_err(hw, "FW image size differs from size in FW header\n");
+               return -EINVAL;
+       }
+
+       if (size > FW_MAX_SIZE) {
+               csio_err(hw, "FW image too large, max is %u bytes\n",
+                           FW_MAX_SIZE);
+               return -EINVAL;
+       }
+
+       for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+               csum += ntohl(p[i]);
+
+       if (csum != 0xffffffff) {
+               csio_err(hw, "corrupted firmware image, checksum %#x\n", csum);
+               return -EINVAL;
+       }
+
+       sf_sec_size = hw->params.sf_size / hw->params.sf_nsec;
+       i = DIV_ROUND_UP(size, sf_sec_size);        /* # of sectors spanned */
+
+       csio_dbg(hw, "Erasing sectors... start:%d end:%d\n",
+                         FW_START_SEC, FW_START_SEC + i - 1);
+
+       ret = csio_hw_flash_erase_sectors(hw, FW_START_SEC,
+                                         FW_START_SEC + i - 1);
+       if (ret) {
+               csio_err(hw, "Flash Erase failed\n");
+               goto out;
+       }
+
+       /*
+        * We write the correct version at the end so the driver can see a bad
+        * version if the FW write fails.  Start by writing a copy of the
+        * first page with a bad version.
+        */
+       memcpy(first_page, fw_data, SF_PAGE_SIZE);
+       ((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff);
+       ret = csio_hw_write_flash(hw, FW_IMG_START, SF_PAGE_SIZE, first_page);
+       if (ret)
+               goto out;
+
+       csio_dbg(hw, "Writing Flash .. start:%d end:%d\n",
+                   FW_IMG_START, FW_IMG_START + size);
+
+       addr = FW_IMG_START;
+       for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
+               addr += SF_PAGE_SIZE;
+               fw_data += SF_PAGE_SIZE;
+               ret = csio_hw_write_flash(hw, addr, SF_PAGE_SIZE, fw_data);
+               if (ret)
+                       goto out;
+       }
+
+       ret = csio_hw_write_flash(hw,
+                                 FW_IMG_START +
+                                       offsetof(struct fw_hdr, fw_ver),
+                                 sizeof(hdr->fw_ver),
+                                 (const uint8_t *)&hdr->fw_ver);
+
+out:
+       if (ret)
+               csio_err(hw, "firmware download failed, error %d\n", ret);
+       return ret;
+}
+
+static int
+csio_hw_get_flash_params(struct csio_hw *hw)
+{
+       int ret;
+       uint32_t info = 0;
+
+       ret = csio_hw_sf1_write(hw, 1, 1, 0, SF_RD_ID);
+       if (!ret)
+               ret = csio_hw_sf1_read(hw, 3, 0, 1, &info);
+       csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+       if (ret != 0)
+               return ret;
+
+       if ((info & 0xff) != 0x20)              /* not a Numonix flash */
+               return -EINVAL;
+       info >>= 16;                            /* log2 of size */
+       if (info >= 0x14 && info < 0x18)
+               hw->params.sf_nsec = 1 << (info - 16);
+       else if (info == 0x18)
+               hw->params.sf_nsec = 64;
+       else
+               return -EINVAL;
+       hw->params.sf_size = 1 << info;
+
+       return 0;
+}
+
+static void
+csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
+{
+       uint16_t val;
+       uint32_t pcie_cap;
+
+       if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) {
+               pci_read_config_word(hw->pdev,
+                                    pcie_cap + PCI_EXP_DEVCTL2, &val);
+               val &= 0xfff0;
+               val |= range ;
+               pci_write_config_word(hw->pdev,
+                                     pcie_cap + PCI_EXP_DEVCTL2, val);
+       }
+}
+
+
+/*
+ * Return the specified PCI-E Configuration Space register from our Physical
+ * Function.  We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static uint32_t
+csio_read_pcie_cfg4(struct csio_hw *hw, int reg)
+{
+       u32 val = 0;
+       struct csio_mb *mbp;
+       int rv;
+       struct fw_ldst_cmd *ldst_cmd;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               pci_read_config_dword(hw->pdev, reg, &val);
+               return val;
+       }
+
+       csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
+
+       rv = csio_mb_issue(hw, mbp);
+
+       /*
+        * If the LDST Command suucceeded, exctract the returned register
+        * value.  Otherwise read it directly ourself.
+        */
+       if (rv == 0) {
+               ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
+               val = ntohl(ldst_cmd->u.pcie.data[0]);
+       } else
+               pci_read_config_dword(hw->pdev, reg, &val);
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return val;
+} /* csio_read_pcie_cfg4 */
+
+static int
+csio_hw_set_mem_win(struct csio_hw *hw)
+{
+       u32 bar0;
+
+       /*
+        * Truncation intentional: we only read the bottom 32-bits of the
+        * 64-bit BAR0/BAR1 ...  We use the hardware backdoor mechanism to
+        * read BAR0 instead of using pci_resource_start() because we could be
+        * operating from within a Virtual Machine which is trapping our
+        * accesses to our Configuration Space and we need to set up the PCI-E
+        * Memory Window decoders with the actual addresses which will be
+        * coming across the PCI-E link.
+        */
+       bar0 = csio_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
+       bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+       /*
+        * Set up memory window for accessing adapter memory ranges.  (Read
+        * back MA register to ensure that changes propagate before we attempt
+        * to use the new values.)
+        */
+       csio_wr_reg32(hw, (bar0 + MEMWIN0_BASE) | BIR(0) |
+               WINDOW(ilog2(MEMWIN0_APERTURE) - 10),
+               PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0));
+       csio_wr_reg32(hw, (bar0 + MEMWIN1_BASE) | BIR(0) |
+               WINDOW(ilog2(MEMWIN1_APERTURE) - 10),
+               PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1));
+       csio_wr_reg32(hw, (bar0 + MEMWIN2_BASE) | BIR(0) |
+               WINDOW(ilog2(MEMWIN2_APERTURE) - 10),
+               PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
+       csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
+       return 0;
+} /* csio_hw_set_mem_win */
+
+
+
+/*****************************************************************************/
+/* HW State machine assists                                                  */
+/*****************************************************************************/
+
+static int
+csio_hw_dev_ready(struct csio_hw *hw)
+{
+       uint32_t reg;
+       int cnt = 6;
+
+       while (((reg = csio_rd_reg32(hw, PL_WHOAMI)) == 0xFFFFFFFF) &&
+                                                               (--cnt != 0))
+               mdelay(100);
+
+       if ((cnt == 0) && (((int32_t)(SOURCEPF_GET(reg)) < 0) ||
+                           (SOURCEPF_GET(reg) >= CSIO_MAX_PFN))) {
+               csio_err(hw, "PL_WHOAMI returned 0x%x, cnt:%d\n", reg, cnt);
+               return -EIO;
+       }
+
+       hw->pfn = SOURCEPF_GET(reg);
+
+       return 0;
+}
+
+/*
+ * csio_do_hello - Perform the HELLO FW Mailbox command and process response.
+ * @hw: HW module
+ * @state: Device state
+ *
+ * FW_HELLO_CMD has to be polled for completion.
+ */
+static int
+csio_do_hello(struct csio_hw *hw, enum csio_dev_state *state)
+{
+       struct csio_mb  *mbp;
+       int     rv = 0;
+       enum csio_dev_master master;
+       enum fw_retval retval;
+       uint8_t mpfn;
+       char state_str[16];
+       int retries = FW_CMD_HELLO_RETRIES;
+
+       memset(state_str, 0, sizeof(state_str));
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               rv = -ENOMEM;
+               CSIO_INC_STATS(hw, n_err_nomem);
+               goto out;
+       }
+
+       master = csio_force_master ? CSIO_MASTER_MUST : CSIO_MASTER_MAY;
+
+retry:
+       csio_mb_hello(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn,
+                     hw->pfn, master, NULL);
+
+       rv = csio_mb_issue(hw, mbp);
+       if (rv) {
+               csio_err(hw, "failed to issue HELLO cmd. ret:%d.\n", rv);
+               goto out_free_mb;
+       }
+
+       csio_mb_process_hello_rsp(hw, mbp, &retval, state, &mpfn);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "HELLO cmd failed with ret: %d\n", retval);
+               rv = -EINVAL;
+               goto out_free_mb;
+       }
+
+       /* Firmware has designated us to be master */
+       if (hw->pfn == mpfn) {
+               hw->flags |= CSIO_HWF_MASTER;
+       } else if (*state == CSIO_DEV_STATE_UNINIT) {
+               /*
+                * If we're not the Master PF then we need to wait around for
+                * the Master PF Driver to finish setting up the adapter.
+                *
+                * Note that we also do this wait if we're a non-Master-capable
+                * PF and there is no current Master PF; a Master PF may show up
+                * momentarily and we wouldn't want to fail pointlessly.  (This
+                * can happen when an OS loads lots of different drivers rapidly
+                * at the same time). In this case, the Master PF returned by
+                * the firmware will be PCIE_FW_MASTER_MASK so the test below
+                * will work ...
+                */
+
+               int waiting = FW_CMD_HELLO_TIMEOUT;
+
+               /*
+                * Wait for the firmware to either indicate an error or
+                * initialized state.  If we see either of these we bail out
+                * and report the issue to the caller.  If we exhaust the
+                * "hello timeout" and we haven't exhausted our retries, try
+                * again.  Otherwise bail with a timeout error.
+                */
+               for (;;) {
+                       uint32_t pcie_fw;
+
+                       msleep(50);
+                       waiting -= 50;
+
+                       /*
+                        * If neither Error nor Initialialized are indicated
+                        * by the firmware keep waiting till we exaust our
+                        * timeout ... and then retry if we haven't exhausted
+                        * our retries ...
+                        */
+                       pcie_fw = csio_rd_reg32(hw, PCIE_FW);
+                       if (!(pcie_fw & (PCIE_FW_ERR|PCIE_FW_INIT))) {
+                               if (waiting <= 0) {
+                                       if (retries-- > 0)
+                                               goto retry;
+
+                                       rv = -ETIMEDOUT;
+                                       break;
+                               }
+                               continue;
+                       }
+
+                       /*
+                        * We either have an Error or Initialized condition
+                        * report errors preferentially.
+                        */
+                       if (state) {
+                               if (pcie_fw & PCIE_FW_ERR) {
+                                       *state = CSIO_DEV_STATE_ERR;
+                                       rv = -ETIMEDOUT;
+                               } else if (pcie_fw & PCIE_FW_INIT)
+                                       *state = CSIO_DEV_STATE_INIT;
+                       }
+
+                       /*
+                        * If we arrived before a Master PF was selected and
+                        * there's not a valid Master PF, grab its identity
+                        * for our caller.
+                        */
+                       if (mpfn == PCIE_FW_MASTER_MASK &&
+                           (pcie_fw & PCIE_FW_MASTER_VLD))
+                               mpfn = PCIE_FW_MASTER_GET(pcie_fw);
+                       break;
+               }
+               hw->flags &= ~CSIO_HWF_MASTER;
+       }
+
+       switch (*state) {
+       case CSIO_DEV_STATE_UNINIT:
+               strcpy(state_str, "Initializing");
+               break;
+       case CSIO_DEV_STATE_INIT:
+               strcpy(state_str, "Initialized");
+               break;
+       case CSIO_DEV_STATE_ERR:
+               strcpy(state_str, "Error");
+               break;
+       default:
+               strcpy(state_str, "Unknown");
+               break;
+       }
+
+       if (hw->pfn == mpfn)
+               csio_info(hw, "PF: %d, Coming up as MASTER, HW state: %s\n",
+                       hw->pfn, state_str);
+       else
+               csio_info(hw,
+                   "PF: %d, Coming up as SLAVE, Master PF: %d, HW state: %s\n",
+                   hw->pfn, mpfn, state_str);
+
+out_free_mb:
+       mempool_free(mbp, hw->mb_mempool);
+out:
+       return rv;
+}
+
+/*
+ * csio_do_bye - Perform the BYE FW Mailbox command and process response.
+ * @hw: HW module
+ *
+ */
+static int
+csio_do_bye(struct csio_hw *hw)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       csio_mb_bye(hw, mbp, CSIO_MB_DEFAULT_TMO, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of BYE command failed\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+/*
+ * csio_do_reset- Perform the device reset.
+ * @hw: HW module
+ * @fw_rst: FW reset
+ *
+ * If fw_rst is set, issues FW reset mbox cmd otherwise
+ * does PIO reset.
+ * Performs reset of the function.
+ */
+static int
+csio_do_reset(struct csio_hw *hw, bool fw_rst)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+
+       if (!fw_rst) {
+               /* PIO reset */
+               csio_wr_reg32(hw, PIORSTMODE | PIORST, PL_RST);
+               mdelay(2000);
+               return 0;
+       }
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       csio_mb_reset(hw, mbp, CSIO_MB_DEFAULT_TMO,
+                     PIORSTMODE | PIORST, 0, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of RESET command failed.n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "RESET cmd failed with ret:0x%x.\n", retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+static int
+csio_hw_validate_caps(struct csio_hw *hw, struct csio_mb *mbp)
+{
+       struct fw_caps_config_cmd *rsp = (struct fw_caps_config_cmd *)mbp->mb;
+       uint16_t caps;
+
+       caps = ntohs(rsp->fcoecaps);
+
+       if (!(caps & FW_CAPS_CONFIG_FCOE_INITIATOR)) {
+               csio_err(hw, "No FCoE Initiator capability in the firmware.\n");
+               return -EINVAL;
+       }
+
+       if (!(caps & FW_CAPS_CONFIG_FCOE_CTRL_OFLD)) {
+               csio_err(hw, "No FCoE Control Offload capability\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ *     csio_hw_fw_halt - issue a reset/halt to FW and put uP into RESET
+ *     @hw: the HW module
+ *     @mbox: mailbox to use for the FW RESET command (if desired)
+ *     @force: force uP into RESET even if FW RESET command fails
+ *
+ *     Issues a RESET command to firmware (if desired) with a HALT indication
+ *     and then puts the microprocessor into RESET state.  The RESET command
+ *     will only be issued if a legitimate mailbox is provided (mbox <=
+ *     PCIE_FW_MASTER_MASK).
+ *
+ *     This is generally used in order for the host to safely manipulate the
+ *     adapter without fear of conflicting with whatever the firmware might
+ *     be doing.  The only way out of this state is to RESTART the firmware
+ *     ...
+ */
+static int
+csio_hw_fw_halt(struct csio_hw *hw, uint32_t mbox, int32_t force)
+{
+       enum fw_retval retval = 0;
+
+       /*
+        * If a legitimate mailbox is provided, issue a RESET command
+        * with a HALT indication.
+        */
+       if (mbox <= PCIE_FW_MASTER_MASK) {
+               struct csio_mb  *mbp;
+
+               mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+               if (!mbp) {
+                       CSIO_INC_STATS(hw, n_err_nomem);
+                       return -ENOMEM;
+               }
+
+               csio_mb_reset(hw, mbp, CSIO_MB_DEFAULT_TMO,
+                             PIORSTMODE | PIORST, FW_RESET_CMD_HALT(1),
+                             NULL);
+
+               if (csio_mb_issue(hw, mbp)) {
+                       csio_err(hw, "Issue of RESET command failed!\n");
+                       mempool_free(mbp, hw->mb_mempool);
+                       return -EINVAL;
+               }
+
+               retval = csio_mb_fw_retval(mbp);
+               mempool_free(mbp, hw->mb_mempool);
+       }
+
+       /*
+        * Normally we won't complete the operation if the firmware RESET
+        * command fails but if our caller insists we'll go ahead and put the
+        * uP into RESET.  This can be useful if the firmware is hung or even
+        * missing ...  We'll have to take the risk of putting the uP into
+        * RESET without the cooperation of firmware in that case.
+        *
+        * We also force the firmware's HALT flag to be on in case we bypassed
+        * the firmware RESET command above or we're dealing with old firmware
+        * which doesn't have the HALT capability.  This will serve as a flag
+        * for the incoming firmware to know that it's coming out of a HALT
+        * rather than a RESET ... if it's new enough to understand that ...
+        */
+       if (retval == 0 || force) {
+               csio_set_reg_field(hw, CIM_BOOT_CFG, UPCRST, UPCRST);
+               csio_set_reg_field(hw, PCIE_FW, PCIE_FW_HALT, PCIE_FW_HALT);
+       }
+
+       /*
+        * And we always return the result of the firmware RESET command
+        * even when we force the uP into RESET ...
+        */
+       return retval ? -EINVAL : 0;
+}
+
+/*
+ *     csio_hw_fw_restart - restart the firmware by taking the uP out of RESET
+ *     @hw: the HW module
+ *     @reset: if we want to do a RESET to restart things
+ *
+ *     Restart firmware previously halted by csio_hw_fw_halt().  On successful
+ *     return the previous PF Master remains as the new PF Master and there
+ *     is no need to issue a new HELLO command, etc.
+ *
+ *     We do this in two ways:
+ *
+ *      1. If we're dealing with newer firmware we'll simply want to take
+ *         the chip's microprocessor out of RESET.  This will cause the
+ *         firmware to start up from its start vector.  And then we'll loop
+ *         until the firmware indicates it's started again (PCIE_FW.HALT
+ *         reset to 0) or we timeout.
+ *
+ *      2. If we're dealing with older firmware then we'll need to RESET
+ *         the chip since older firmware won't recognize the PCIE_FW.HALT
+ *         flag and automatically RESET itself on startup.
+ */
+static int
+csio_hw_fw_restart(struct csio_hw *hw, uint32_t mbox, int32_t reset)
+{
+       if (reset) {
+               /*
+                * Since we're directing the RESET instead of the firmware
+                * doing it automatically, we need to clear the PCIE_FW.HALT
+                * bit.
+                */
+               csio_set_reg_field(hw, PCIE_FW, PCIE_FW_HALT, 0);
+
+               /*
+                * If we've been given a valid mailbox, first try to get the
+                * firmware to do the RESET.  If that works, great and we can
+                * return success.  Otherwise, if we haven't been given a
+                * valid mailbox or the RESET command failed, fall back to
+                * hitting the chip with a hammer.
+                */
+               if (mbox <= PCIE_FW_MASTER_MASK) {
+                       csio_set_reg_field(hw, CIM_BOOT_CFG, UPCRST, 0);
+                       msleep(100);
+                       if (csio_do_reset(hw, true) == 0)
+                               return 0;
+               }
+
+               csio_wr_reg32(hw, PIORSTMODE | PIORST, PL_RST);
+               msleep(2000);
+       } else {
+               int ms;
+
+               csio_set_reg_field(hw, CIM_BOOT_CFG, UPCRST, 0);
+               for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) {
+                       if (!(csio_rd_reg32(hw, PCIE_FW) & PCIE_FW_HALT))
+                               return 0;
+                       msleep(100);
+                       ms += 100;
+               }
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+/*
+ *     csio_hw_fw_upgrade - perform all of the steps necessary to upgrade FW
+ *     @hw: the HW module
+ *     @mbox: mailbox to use for the FW RESET command (if desired)
+ *     @fw_data: the firmware image to write
+ *     @size: image size
+ *     @force: force upgrade even if firmware doesn't cooperate
+ *
+ *     Perform all of the steps necessary for upgrading an adapter's
+ *     firmware image.  Normally this requires the cooperation of the
+ *     existing firmware in order to halt all existing activities
+ *     but if an invalid mailbox token is passed in we skip that step
+ *     (though we'll still put the adapter microprocessor into RESET in
+ *     that case).
+ *
+ *     On successful return the new firmware will have been loaded and
+ *     the adapter will have been fully RESET losing all previous setup
+ *     state.  On unsuccessful return the adapter may be completely hosed ...
+ *     positive errno indicates that the adapter is ~probably~ intact, a
+ *     negative errno indicates that things are looking bad ...
+ */
+static int
+csio_hw_fw_upgrade(struct csio_hw *hw, uint32_t mbox,
+                 const u8 *fw_data, uint32_t size, int32_t force)
+{
+       const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
+       int reset, ret;
+
+       ret = csio_hw_fw_halt(hw, mbox, force);
+       if (ret != 0 && !force)
+               return ret;
+
+       ret = csio_hw_fw_dload(hw, (uint8_t *) fw_data, size);
+       if (ret != 0)
+               return ret;
+
+       /*
+        * Older versions of the firmware don't understand the new
+        * PCIE_FW.HALT flag and so won't know to perform a RESET when they
+        * restart.  So for newly loaded older firmware we'll have to do the
+        * RESET for it so it starts up on a clean slate.  We can tell if
+        * the newly loaded firmware will handle this right by checking
+        * its header flags to see if it advertises the capability.
+        */
+       reset = ((ntohl(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
+       return csio_hw_fw_restart(hw, mbox, reset);
+}
+
+
+/*
+ *     csio_hw_fw_config_file - setup an adapter via a Configuration File
+ *     @hw: the HW module
+ *     @mbox: mailbox to use for the FW command
+ *     @mtype: the memory type where the Configuration File is located
+ *     @maddr: the memory address where the Configuration File is located
+ *     @finiver: return value for CF [fini] version
+ *     @finicsum: return value for CF [fini] checksum
+ *     @cfcsum: return value for CF computed checksum
+ *
+ *     Issue a command to get the firmware to process the Configuration
+ *     File located at the specified mtype/maddress.  If the Configuration
+ *     File is processed successfully and return value pointers are
+ *     provided, the Configuration File "[fini] section version and
+ *     checksum values will be returned along with the computed checksum.
+ *     It's up to the caller to decide how it wants to respond to the
+ *     checksums not matching but it recommended that a prominant warning
+ *     be emitted in order to help people rapidly identify changed or
+ *     corrupted Configuration Files.
+ *
+ *     Also note that it's possible to modify things like "niccaps",
+ *     "toecaps",etc. between processing the Configuration File and telling
+ *     the firmware to use the new configuration.  Callers which want to
+ *     do this will need to "hand-roll" their own CAPS_CONFIGS commands for
+ *     Configuration Files if they want to do this.
+ */
+static int
+csio_hw_fw_config_file(struct csio_hw *hw,
+                     unsigned int mtype, unsigned int maddr,
+                     uint32_t *finiver, uint32_t *finicsum, uint32_t *cfcsum)
+{
+       struct csio_mb  *mbp;
+       struct fw_caps_config_cmd *caps_cmd;
+       int rv = -EINVAL;
+       enum fw_retval ret;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+       /*
+        * Tell the firmware to process the indicated Configuration File.
+        * If there are no errors and the caller has provided return value
+        * pointers for the [fini] section version, checksum and computed
+        * checksum, pass those back to the caller.
+        */
+       caps_cmd = (struct fw_caps_config_cmd *)(mbp->mb);
+       CSIO_INIT_MBP(mbp, caps_cmd, CSIO_MB_DEFAULT_TMO, hw, NULL, 1);
+       caps_cmd->op_to_write =
+               htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+                     FW_CMD_REQUEST |
+                     FW_CMD_READ);
+       caps_cmd->cfvalid_to_len16 =
+               htonl(FW_CAPS_CONFIG_CMD_CFVALID |
+                     FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
+                     FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
+                     FW_LEN16(*caps_cmd));
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD failed!\n");
+               goto out;
+       }
+
+       ret = csio_mb_fw_retval(mbp);
+       if (ret != FW_SUCCESS) {
+               csio_dbg(hw, "FW_CAPS_CONFIG_CMD returned %d!\n", rv);
+               goto out;
+       }
+
+       if (finiver)
+               *finiver = ntohl(caps_cmd->finiver);
+       if (finicsum)
+               *finicsum = ntohl(caps_cmd->finicsum);
+       if (cfcsum)
+               *cfcsum = ntohl(caps_cmd->cfcsum);
+
+       /* Validate device capabilities */
+       if (csio_hw_validate_caps(hw, mbp)) {
+               rv = -ENOENT;
+               goto out;
+       }
+
+       /*
+        * And now tell the firmware to use the configuration we just loaded.
+        */
+       caps_cmd->op_to_write =
+               htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+                     FW_CMD_REQUEST |
+                     FW_CMD_WRITE);
+       caps_cmd->cfvalid_to_len16 = htonl(FW_LEN16(*caps_cmd));
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD failed!\n");
+               goto out;
+       }
+
+       ret = csio_mb_fw_retval(mbp);
+       if (ret != FW_SUCCESS) {
+               csio_dbg(hw, "FW_CAPS_CONFIG_CMD returned %d!\n", rv);
+               goto out;
+       }
+
+       rv = 0;
+out:
+       mempool_free(mbp, hw->mb_mempool);
+       return rv;
+}
+
+/*
+ * csio_get_device_params - Get device parameters.
+ * @hw: HW module
+ *
+ */
+static int
+csio_get_device_params(struct csio_hw *hw)
+{
+       struct csio_wrm *wrm    = csio_hw_to_wrm(hw);
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+       u32 param[6];
+       int i, j = 0;
+
+       /* Initialize portids to -1 */
+       for (i = 0; i < CSIO_MAX_PPORTS; i++)
+               hw->pport[i].portid = -1;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /* Get port vec information. */
+       param[0] = FW_PARAM_DEV(PORTVEC);
+
+       /* Get Core clock. */
+       param[1] = FW_PARAM_DEV(CCLK);
+
+       /* Get EQ id start and end. */
+       param[2] = FW_PARAM_PFVF(EQ_START);
+       param[3] = FW_PARAM_PFVF(EQ_END);
+
+       /* Get IQ id start and end. */
+       param[4] = FW_PARAM_PFVF(IQFLINT_START);
+       param[5] = FW_PARAM_PFVF(IQFLINT_END);
+
+       csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0,
+                      ARRAY_SIZE(param), param, NULL, false, NULL);
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_PARAMS_CMD(read) failed!\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       csio_mb_process_read_params_rsp(hw, mbp, &retval,
+                       ARRAY_SIZE(param), param);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_PARAMS_CMD(read) failed with ret:0x%x!\n",
+                               retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       /* cache the information. */
+       hw->port_vec = param[0];
+       hw->vpd.cclk = param[1];
+       wrm->fw_eq_start = param[2];
+       wrm->fw_iq_start = param[4];
+
+       /* Using FW configured max iqs & eqs */
+       if ((hw->flags & CSIO_HWF_USING_SOFT_PARAMS) ||
+               !csio_is_hw_master(hw)) {
+               hw->cfg_niq = param[5] - param[4] + 1;
+               hw->cfg_neq = param[3] - param[2] + 1;
+               csio_dbg(hw, "Using fwconfig max niqs %d neqs %d\n",
+                       hw->cfg_niq, hw->cfg_neq);
+       }
+
+       hw->port_vec &= csio_port_mask;
+
+       hw->num_pports  = hweight32(hw->port_vec);
+
+       csio_dbg(hw, "Port vector: 0x%x, #ports: %d\n",
+                   hw->port_vec, hw->num_pports);
+
+       for (i = 0; i < hw->num_pports; i++) {
+               while ((hw->port_vec & (1 << j)) == 0)
+                       j++;
+               hw->pport[i].portid = j++;
+               csio_dbg(hw, "Found Port:%d\n", hw->pport[i].portid);
+       }
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+
+/*
+ * csio_config_device_caps - Get and set device capabilities.
+ * @hw: HW module
+ *
+ */
+static int
+csio_config_device_caps(struct csio_hw *hw)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+       int rv = -EINVAL;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /* Get device capabilities */
+       csio_mb_caps_config(hw, mbp, CSIO_MB_DEFAULT_TMO, 0, 0, 0, 0, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD(r) failed!\n");
+               goto out;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_CAPS_CONFIG_CMD(r) returned %d!\n", retval);
+               goto out;
+       }
+
+       /* Validate device capabilities */
+       if (csio_hw_validate_caps(hw, mbp))
+               goto out;
+
+       /* Don't config device capabilities if already configured */
+       if (hw->fw_state == CSIO_DEV_STATE_INIT) {
+               rv = 0;
+               goto out;
+       }
+
+       /* Write back desired device capabilities */
+       csio_mb_caps_config(hw, mbp, CSIO_MB_DEFAULT_TMO, true, true,
+                           false, true, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD(w) failed!\n");
+               goto out;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_CAPS_CONFIG_CMD(w) returned %d!\n", retval);
+               goto out;
+       }
+
+       rv = 0;
+out:
+       mempool_free(mbp, hw->mb_mempool);
+       return rv;
+}
+
+static int
+csio_config_global_rss(struct csio_hw *hw)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       csio_rss_glb_config(hw, mbp, CSIO_MB_DEFAULT_TMO,
+                           FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
+                           FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
+                           FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ |
+                           FW_RSS_GLB_CONFIG_CMD_TNLALLLKP,
+                           NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_RSS_GLB_CONFIG_CMD failed!\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_RSS_GLB_CONFIG_CMD returned 0x%x!\n", retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+/*
+ * csio_config_pfvf - Configure Physical/Virtual functions settings.
+ * @hw: HW module
+ *
+ */
+static int
+csio_config_pfvf(struct csio_hw *hw)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /*
+        * For now, allow all PFs to access to all ports using a pmask
+        * value of 0xF (M_FW_PFVF_CMD_PMASK). Once we have VFs, we will
+        * need to provide access based on some rule.
+        */
+       csio_mb_pfvf(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0, CSIO_NEQ,
+                    CSIO_NETH_CTRL, CSIO_NIQ_FLINT, 0, 0, CSIO_NVI, CSIO_CMASK,
+                    CSIO_PMASK, CSIO_NEXACTF, CSIO_R_CAPS, CSIO_WX_CAPS, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_PFVF_CMD failed!\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_PFVF_CMD returned 0x%x!\n", retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+/*
+ * csio_enable_ports - Bring up all available ports.
+ * @hw: HW module.
+ *
+ */
+static int
+csio_enable_ports(struct csio_hw *hw)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+       uint8_t portid;
+       int i;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < hw->num_pports; i++) {
+               portid = hw->pport[i].portid;
+
+               /* Read PORT information */
+               csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
+                            false, 0, 0, NULL);
+
+               if (csio_mb_issue(hw, mbp)) {
+                       csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n",
+                                portid);
+                       mempool_free(mbp, hw->mb_mempool);
+                       return -EINVAL;
+               }
+
+               csio_mb_process_read_port_rsp(hw, mbp, &retval,
+                                             &hw->pport[i].pcap);
+               if (retval != FW_SUCCESS) {
+                       csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n",
+                                portid, retval);
+                       mempool_free(mbp, hw->mb_mempool);
+                       return -EINVAL;
+               }
+
+               /* Write back PORT information */
+               csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, true,
+                            (PAUSE_RX | PAUSE_TX), hw->pport[i].pcap, NULL);
+
+               if (csio_mb_issue(hw, mbp)) {
+                       csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n",
+                                portid);
+                       mempool_free(mbp, hw->mb_mempool);
+                       return -EINVAL;
+               }
+
+               retval = csio_mb_fw_retval(mbp);
+               if (retval != FW_SUCCESS) {
+                       csio_err(hw, "FW_PORT_CMD(w) port:%d failed :0x%x\n",
+                                portid, retval);
+                       mempool_free(mbp, hw->mb_mempool);
+                       return -EINVAL;
+               }
+
+       } /* For all ports */
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+/*
+ * csio_get_fcoe_resinfo - Read fcoe fw resource info.
+ * @hw: HW module
+ * Issued with lock held.
+ */
+static int
+csio_get_fcoe_resinfo(struct csio_hw *hw)
+{
+       struct csio_fcoe_res_info *res_info = &hw->fres_info;
+       struct fw_fcoe_res_info_cmd *rsp;
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /* Get FCoE FW resource information */
+       csio_fcoe_read_res_info_init_mb(hw, mbp, CSIO_MB_DEFAULT_TMO, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "failed to issue FW_FCOE_RES_INFO_CMD\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       rsp = (struct fw_fcoe_res_info_cmd *)(mbp->mb);
+       retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_FCOE_RES_INFO_CMD failed with ret x%x\n",
+                        retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       res_info->e_d_tov = ntohs(rsp->e_d_tov);
+       res_info->r_a_tov_seq = ntohs(rsp->r_a_tov_seq);
+       res_info->r_a_tov_els = ntohs(rsp->r_a_tov_els);
+       res_info->r_r_tov = ntohs(rsp->r_r_tov);
+       res_info->max_xchgs = ntohl(rsp->max_xchgs);
+       res_info->max_ssns = ntohl(rsp->max_ssns);
+       res_info->used_xchgs = ntohl(rsp->used_xchgs);
+       res_info->used_ssns = ntohl(rsp->used_ssns);
+       res_info->max_fcfs = ntohl(rsp->max_fcfs);
+       res_info->max_vnps = ntohl(rsp->max_vnps);
+       res_info->used_fcfs = ntohl(rsp->used_fcfs);
+       res_info->used_vnps = ntohl(rsp->used_vnps);
+
+       csio_dbg(hw, "max ssns:%d max xchgs:%d\n", res_info->max_ssns,
+                                                 res_info->max_xchgs);
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+static int
+csio_hw_check_fwconfig(struct csio_hw *hw, u32 *param)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+       u32 _param[1];
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /*
+        * Find out whether we're dealing with a version of
+        * the firmware which has configuration file support.
+        */
+       _param[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+                    FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF));
+
+       csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0,
+                      ARRAY_SIZE(_param), _param, NULL, false, NULL);
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of FW_PARAMS_CMD(read) failed!\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       csio_mb_process_read_params_rsp(hw, mbp, &retval,
+                       ARRAY_SIZE(_param), _param);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FW_PARAMS_CMD(read) failed with ret:0x%x!\n",
+                               retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+       *param = _param[0];
+
+       return 0;
+}
+
+static int
+csio_hw_flash_config(struct csio_hw *hw, u32 *fw_cfg_param, char *path)
+{
+       int ret = 0;
+       const struct firmware *cf;
+       struct pci_dev *pci_dev = hw->pdev;
+       struct device *dev = &pci_dev->dev;
+       unsigned int mtype = 0, maddr = 0;
+       uint32_t *cfg_data;
+       int value_to_add = 0;
+
+       if (request_firmware(&cf, CSIO_CF_FNAME, dev) < 0) {
+               csio_err(hw, "could not find config file " CSIO_CF_FNAME
+                        ",err: %d\n", ret);
+               return -ENOENT;
+       }
+
+       if (cf->size%4 != 0)
+               value_to_add = 4 - (cf->size % 4);
+
+       cfg_data = kzalloc(cf->size+value_to_add, GFP_KERNEL);
+       if (cfg_data == NULL)
+               return -ENOMEM;
+
+       memcpy((void *)cfg_data, (const void *)cf->data, cf->size);
+
+       if (csio_hw_check_fwconfig(hw, fw_cfg_param) != 0)
+               return -EINVAL;
+
+       mtype = FW_PARAMS_PARAM_Y_GET(*fw_cfg_param);
+       maddr = FW_PARAMS_PARAM_Z_GET(*fw_cfg_param) << 16;
+
+       ret = csio_memory_write(hw, mtype, maddr,
+                               cf->size + value_to_add, cfg_data);
+       if (ret == 0) {
+               csio_info(hw, "config file upgraded to " CSIO_CF_FNAME "\n");
+               strncpy(path, "/lib/firmware/" CSIO_CF_FNAME, 64);
+       }
+
+       kfree(cfg_data);
+       release_firmware(cf);
+
+       return ret;
+}
+
+/*
+ * HW initialization: contact FW, obtain config, perform basic init.
+ *
+ * If the firmware we're dealing with has Configuration File support, then
+ * we use that to perform all configuration -- either using the configuration
+ * file stored in flash on the adapter or using a filesystem-local file
+ * if available.
+ *
+ * If we don't have configuration file support in the firmware, then we'll
+ * have to set things up the old fashioned way with hard-coded register
+ * writes and firmware commands ...
+ */
+
+/*
+ * Attempt to initialize the HW via a Firmware Configuration File.
+ */
+static int
+csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
+{
+       unsigned int mtype, maddr;
+       int rv;
+       uint32_t finiver, finicsum, cfcsum;
+       int using_flash;
+       char path[64];
+
+       /*
+        * Reset device if necessary
+        */
+       if (reset) {
+               rv = csio_do_reset(hw, true);
+               if (rv != 0)
+                       goto bye;
+       }
+
+       /*
+        * If we have a configuration file in host ,
+        * then use that.  Otherwise, use the configuration file stored
+        * in the HW flash ...
+        */
+       spin_unlock_irq(&hw->lock);
+       rv = csio_hw_flash_config(hw, fw_cfg_param, path);
+       spin_lock_irq(&hw->lock);
+       if (rv != 0) {
+               if (rv == -ENOENT) {
+                       /*
+                        * config file was not found. Use default
+                        * config file from flash.
+                        */
+                       mtype = FW_MEMTYPE_CF_FLASH;
+                       maddr = csio_hw_flash_cfg_addr(hw);
+                       using_flash = 1;
+               } else {
+                       /*
+                        * we revert back to the hardwired config if
+                        * flashing failed.
+                        */
+                       goto bye;
+               }
+       } else {
+               mtype = FW_PARAMS_PARAM_Y_GET(*fw_cfg_param);
+               maddr = FW_PARAMS_PARAM_Z_GET(*fw_cfg_param) << 16;
+               using_flash = 0;
+       }
+
+       hw->cfg_store = (uint8_t)mtype;
+
+       /*
+        * Issue a Capability Configuration command to the firmware to get it
+        * to parse the Configuration File.
+        */
+       rv = csio_hw_fw_config_file(hw, mtype, maddr, &finiver,
+               &finicsum, &cfcsum);
+       if (rv != 0)
+               goto bye;
+
+       hw->cfg_finiver         = finiver;
+       hw->cfg_finicsum        = finicsum;
+       hw->cfg_cfcsum          = cfcsum;
+       hw->cfg_csum_status     = true;
+
+       if (finicsum != cfcsum) {
+               csio_warn(hw,
+                     "Config File checksum mismatch: csum=%#x, computed=%#x\n",
+                     finicsum, cfcsum);
+
+               hw->cfg_csum_status = false;
+       }
+
+       /*
+        * Note that we're operating with parameters
+        * not supplied by the driver, rather than from hard-wired
+        * initialization constants buried in the driver.
+        */
+       hw->flags |= CSIO_HWF_USING_SOFT_PARAMS;
+
+       /* device parameters */
+       rv = csio_get_device_params(hw);
+       if (rv != 0)
+               goto bye;
+
+       /* Configure SGE */
+       csio_wr_sge_init(hw);
+
+       /*
+        * And finally tell the firmware to initialize itself using the
+        * parameters from the Configuration File.
+        */
+       /* Post event to notify completion of configuration */
+       csio_post_event(&hw->sm, CSIO_HWE_INIT);
+
+       csio_info(hw,
+        "Firmware Configuration File %s, version %#x, computed checksum %#x\n",
+                 (using_flash ? "in device FLASH" : path), finiver, cfcsum);
+
+       return 0;
+
+       /*
+        * Something bad happened.  Return the error ...
+        */
+bye:
+       hw->flags &= ~CSIO_HWF_USING_SOFT_PARAMS;
+       csio_dbg(hw, "Configuration file error %d\n", rv);
+       return rv;
+}
+
+/*
+ * Attempt to initialize the adapter via hard-coded, driver supplied
+ * parameters ...
+ */
+static int
+csio_hw_no_fwconfig(struct csio_hw *hw, int reset)
+{
+       int             rv;
+       /*
+        * Reset device if necessary
+        */
+       if (reset) {
+               rv = csio_do_reset(hw, true);
+               if (rv != 0)
+                       goto out;
+       }
+
+       /* Get and set device capabilities */
+       rv = csio_config_device_caps(hw);
+       if (rv != 0)
+               goto out;
+
+       /* Config Global RSS command */
+       rv = csio_config_global_rss(hw);
+       if (rv != 0)
+               goto out;
+
+       /* Configure PF/VF capabilities of device */
+       rv = csio_config_pfvf(hw);
+       if (rv != 0)
+               goto out;
+
+       /* device parameters */
+       rv = csio_get_device_params(hw);
+       if (rv != 0)
+               goto out;
+
+       /* Configure SGE */
+       csio_wr_sge_init(hw);
+
+       /* Post event to notify completion of configuration */
+       csio_post_event(&hw->sm, CSIO_HWE_INIT);
+
+out:
+       return rv;
+}
+
+/*
+ * Returns -EINVAL if attempts to flash the firmware failed
+ * else returns 0,
+ * if flashing was not attempted because the card had the
+ * latest firmware ECANCELED is returned
+ */
+static int
+csio_hw_flash_fw(struct csio_hw *hw)
+{
+       int ret = -ECANCELED;
+       const struct firmware *fw;
+       const struct fw_hdr *hdr;
+       u32 fw_ver;
+       struct pci_dev *pci_dev = hw->pdev;
+       struct device *dev = &pci_dev->dev ;
+
+       if (request_firmware(&fw, CSIO_FW_FNAME, dev) < 0) {
+               csio_err(hw, "could not find firmware image " CSIO_FW_FNAME
+               ",err: %d\n", ret);
+               return -EINVAL;
+       }
+
+       hdr = (const struct fw_hdr *)fw->data;
+       fw_ver = ntohl(hdr->fw_ver);
+       if (FW_HDR_FW_VER_MAJOR_GET(fw_ver) != FW_VERSION_MAJOR)
+               return -EINVAL;      /* wrong major version, won't do */
+
+       /*
+        * If the flash FW is unusable or we found something newer, load it.
+        */
+       if (FW_HDR_FW_VER_MAJOR_GET(hw->fwrev) != FW_VERSION_MAJOR ||
+           fw_ver > hw->fwrev) {
+               ret = csio_hw_fw_upgrade(hw, hw->pfn, fw->data, fw->size,
+                                   /*force=*/false);
+               if (!ret)
+                       csio_info(hw, "firmware upgraded to version %pI4 from "
+                                 CSIO_FW_FNAME "\n", &hdr->fw_ver);
+               else
+                       csio_err(hw, "firmware upgrade failed! err=%d\n", ret);
+       }
+
+       release_firmware(fw);
+
+       return ret;
+}
+
+
+/*
+ * csio_hw_configure - Configure HW
+ * @hw - HW module
+ *
+ */
+static void
+csio_hw_configure(struct csio_hw *hw)
+{
+       int reset = 1;
+       int rv;
+       u32 param[1];
+
+       rv = csio_hw_dev_ready(hw);
+       if (rv != 0) {
+               CSIO_INC_STATS(hw, n_err_fatal);
+               csio_post_event(&hw->sm, CSIO_HWE_FATAL);
+               goto out;
+       }
+
+       /* HW version */
+       hw->chip_ver = (char)csio_rd_reg32(hw, PL_REV);
+
+       /* Needed for FW download */
+       rv = csio_hw_get_flash_params(hw);
+       if (rv != 0) {
+               csio_err(hw, "Failed to get serial flash params rv:%d\n", rv);
+               csio_post_event(&hw->sm, CSIO_HWE_FATAL);
+               goto out;
+       }
+
+       /* Set pci completion timeout value to 4 seconds. */
+       csio_set_pcie_completion_timeout(hw, 0xd);
+
+       csio_hw_set_mem_win(hw);
+
+       rv = csio_hw_get_fw_version(hw, &hw->fwrev);
+       if (rv != 0)
+               goto out;
+
+       csio_hw_print_fw_version(hw, "Firmware revision");
+
+       rv = csio_do_hello(hw, &hw->fw_state);
+       if (rv != 0) {
+               CSIO_INC_STATS(hw, n_err_fatal);
+               csio_post_event(&hw->sm, CSIO_HWE_FATAL);
+               goto out;
+       }
+
+       /* Read vpd */
+       rv = csio_hw_get_vpd_params(hw, &hw->vpd);
+       if (rv != 0)
+               goto out;
+
+       if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
+               rv = csio_hw_check_fw_version(hw);
+               if (rv == -EINVAL) {
+
+                       /* Do firmware update */
+                       spin_unlock_irq(&hw->lock);
+                       rv = csio_hw_flash_fw(hw);
+                       spin_lock_irq(&hw->lock);
+
+                       if (rv == 0) {
+                               reset = 0;
+                               /*
+                                * Note that the chip was reset as part of the
+                                * firmware upgrade so we don't reset it again
+                                * below and grab the new firmware version.
+                                */
+                               rv = csio_hw_check_fw_version(hw);
+                       }
+               }
+               /*
+                * If the firmware doesn't support Configuration
+                * Files, use the old Driver-based, hard-wired
+                * initialization.  Otherwise, try using the
+                * Configuration File support and fall back to the
+                * Driver-based initialization if there's no
+                * Configuration File found.
+                */
+               if (csio_hw_check_fwconfig(hw, param) == 0) {
+                       rv = csio_hw_use_fwconfig(hw, reset, param);
+                       if (rv == -ENOENT)
+                               goto out;
+                       if (rv != 0) {
+                               csio_info(hw,
+                                   "No Configuration File present "
+                                   "on adapter.  Using hard-wired "
+                                   "configuration parameters.\n");
+                               rv = csio_hw_no_fwconfig(hw, reset);
+                       }
+               } else {
+                       rv = csio_hw_no_fwconfig(hw, reset);
+               }
+
+               if (rv != 0)
+                       goto out;
+
+       } else {
+               if (hw->fw_state == CSIO_DEV_STATE_INIT) {
+
+                       /* device parameters */
+                       rv = csio_get_device_params(hw);
+                       if (rv != 0)
+                               goto out;
+
+                       /* Get device capabilities */
+                       rv = csio_config_device_caps(hw);
+                       if (rv != 0)
+                               goto out;
+
+                       /* Configure SGE */
+                       csio_wr_sge_init(hw);
+
+                       /* Post event to notify completion of configuration */
+                       csio_post_event(&hw->sm, CSIO_HWE_INIT);
+                       goto out;
+               }
+       } /* if not master */
+
+out:
+       return;
+}
+
+/*
+ * csio_hw_initialize - Initialize HW
+ * @hw - HW module
+ *
+ */
+static void
+csio_hw_initialize(struct csio_hw *hw)
+{
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+       int rv;
+       int i;
+
+       if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
+               mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+               if (!mbp)
+                       goto out;
+
+               csio_mb_initialize(hw, mbp, CSIO_MB_DEFAULT_TMO, NULL);
+
+               if (csio_mb_issue(hw, mbp)) {
+                       csio_err(hw, "Issue of FW_INITIALIZE_CMD failed!\n");
+                       goto free_and_out;
+               }
+
+               retval = csio_mb_fw_retval(mbp);
+               if (retval != FW_SUCCESS) {
+                       csio_err(hw, "FW_INITIALIZE_CMD returned 0x%x!\n",
+                                retval);
+                       goto free_and_out;
+               }
+
+               mempool_free(mbp, hw->mb_mempool);
+       }
+
+       rv = csio_get_fcoe_resinfo(hw);
+       if (rv != 0) {
+               csio_err(hw, "Failed to read fcoe resource info: %d\n", rv);
+               goto out;
+       }
+
+       spin_unlock_irq(&hw->lock);
+       rv = csio_config_queues(hw);
+       spin_lock_irq(&hw->lock);
+
+       if (rv != 0) {
+               csio_err(hw, "Config of queues failed!: %d\n", rv);
+               goto out;
+       }
+
+       for (i = 0; i < hw->num_pports; i++)
+               hw->pport[i].mod_type = FW_PORT_MOD_TYPE_NA;
+
+       if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
+               rv = csio_enable_ports(hw);
+               if (rv != 0) {
+                       csio_err(hw, "Failed to enable ports: %d\n", rv);
+                       goto out;
+               }
+       }
+
+       csio_post_event(&hw->sm, CSIO_HWE_INIT_DONE);
+       return;
+
+free_and_out:
+       mempool_free(mbp, hw->mb_mempool);
+out:
+       return;
+}
+
+#define PF_INTR_MASK (PFSW | PFCIM)
+
+/*
+ * csio_hw_intr_enable - Enable HW interrupts
+ * @hw: Pointer to HW module.
+ *
+ * Enable interrupts in HW registers.
+ */
+static void
+csio_hw_intr_enable(struct csio_hw *hw)
+{
+       uint16_t vec = (uint16_t)csio_get_mb_intr_idx(csio_hw_to_mbm(hw));
+       uint32_t pf = SOURCEPF_GET(csio_rd_reg32(hw, PL_WHOAMI));
+       uint32_t pl = csio_rd_reg32(hw, PL_INT_ENABLE);
+
+       /*
+        * Set aivec for MSI/MSIX. PCIE_PF_CFG.INTXType is set up
+        * by FW, so do nothing for INTX.
+        */
+       if (hw->intr_mode == CSIO_IM_MSIX)
+               csio_set_reg_field(hw, MYPF_REG(PCIE_PF_CFG),
+                                  AIVEC(AIVEC_MASK), vec);
+       else if (hw->intr_mode == CSIO_IM_MSI)
+               csio_set_reg_field(hw, MYPF_REG(PCIE_PF_CFG),
+                                  AIVEC(AIVEC_MASK), 0);
+
+       csio_wr_reg32(hw, PF_INTR_MASK, MYPF_REG(PL_PF_INT_ENABLE));
+
+       /* Turn on MB interrupts - this will internally flush PIO as well */
+       csio_mb_intr_enable(hw);
+
+       /* These are common registers - only a master can modify them */
+       if (csio_is_hw_master(hw)) {
+               /*
+                * Disable the Serial FLASH interrupt, if enabled!
+                */
+               pl &= (~SF);
+               csio_wr_reg32(hw, pl, PL_INT_ENABLE);
+
+               csio_wr_reg32(hw, ERR_CPL_EXCEED_IQE_SIZE |
+                             EGRESS_SIZE_ERR | ERR_INVALID_CIDX_INC |
+                             ERR_CPL_OPCODE_0 | ERR_DROPPED_DB |
+                             ERR_DATA_CPL_ON_HIGH_QID1 |
+                             ERR_DATA_CPL_ON_HIGH_QID0 | ERR_BAD_DB_PIDX3 |
+                             ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
+                             ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
+                             ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR,
+                             SGE_INT_ENABLE3);
+               csio_set_reg_field(hw, PL_INT_MAP0, 0, 1 << pf);
+       }
+
+       hw->flags |= CSIO_HWF_HW_INTR_ENABLED;
+
+}
+
+/*
+ * csio_hw_intr_disable - Disable HW interrupts
+ * @hw: Pointer to HW module.
+ *
+ * Turn off Mailbox and PCI_PF_CFG interrupts.
+ */
+void
+csio_hw_intr_disable(struct csio_hw *hw)
+{
+       uint32_t pf = SOURCEPF_GET(csio_rd_reg32(hw, PL_WHOAMI));
+
+       if (!(hw->flags & CSIO_HWF_HW_INTR_ENABLED))
+               return;
+
+       hw->flags &= ~CSIO_HWF_HW_INTR_ENABLED;
+
+       csio_wr_reg32(hw, 0, MYPF_REG(PL_PF_INT_ENABLE));
+       if (csio_is_hw_master(hw))
+               csio_set_reg_field(hw, PL_INT_MAP0, 1 << pf, 0);
+
+       /* Turn off MB interrupts */
+       csio_mb_intr_disable(hw);
+
+}
+
+static void
+csio_hw_fatal_err(struct csio_hw *hw)
+{
+       csio_set_reg_field(hw, SGE_CONTROL, GLOBALENABLE, 0);
+       csio_hw_intr_disable(hw);
+
+       /* Do not reset HW, we may need FW state for debugging */
+       csio_fatal(hw, "HW Fatal error encountered!\n");
+}
+
+/*****************************************************************************/
+/* START: HW SM                                                              */
+/*****************************************************************************/
+/*
+ * csio_hws_uninit - Uninit state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_uninit(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_CFG:
+               csio_set_state(&hw->sm, csio_hws_configuring);
+               csio_hw_configure(hw);
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_configuring - Configuring state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_configuring(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_INIT:
+               csio_set_state(&hw->sm, csio_hws_initializing);
+               csio_hw_initialize(hw);
+               break;
+
+       case CSIO_HWE_INIT_DONE:
+               csio_set_state(&hw->sm, csio_hws_ready);
+               /* Fan out event to all lnode SMs */
+               csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWREADY);
+               break;
+
+       case CSIO_HWE_FATAL:
+               csio_set_state(&hw->sm, csio_hws_uninit);
+               break;
+
+       case CSIO_HWE_PCI_REMOVE:
+               csio_do_bye(hw);
+               break;
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_initializing - Initialiazing state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_initializing(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_INIT_DONE:
+               csio_set_state(&hw->sm, csio_hws_ready);
+
+               /* Fan out event to all lnode SMs */
+               csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWREADY);
+
+               /* Enable interrupts */
+               csio_hw_intr_enable(hw);
+               break;
+
+       case CSIO_HWE_FATAL:
+               csio_set_state(&hw->sm, csio_hws_uninit);
+               break;
+
+       case CSIO_HWE_PCI_REMOVE:
+               csio_do_bye(hw);
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_ready - Ready state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_ready(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       /* Remember the event */
+       hw->evtflag = evt;
+
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_HBA_RESET:
+       case CSIO_HWE_FW_DLOAD:
+       case CSIO_HWE_SUSPEND:
+       case CSIO_HWE_PCI_REMOVE:
+       case CSIO_HWE_PCIERR_DETECTED:
+               csio_set_state(&hw->sm, csio_hws_quiescing);
+               /* cleanup all outstanding cmds */
+               if (evt == CSIO_HWE_HBA_RESET ||
+                   evt == CSIO_HWE_PCIERR_DETECTED)
+                       csio_scsim_cleanup_io(csio_hw_to_scsim(hw), false);
+               else
+                       csio_scsim_cleanup_io(csio_hw_to_scsim(hw), true);
+
+               csio_hw_intr_disable(hw);
+               csio_hw_mbm_cleanup(hw);
+               csio_evtq_stop(hw);
+               csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWSTOP);
+               csio_evtq_flush(hw);
+               csio_mgmtm_cleanup(csio_hw_to_mgmtm(hw));
+               csio_post_event(&hw->sm, CSIO_HWE_QUIESCED);
+               break;
+
+       case CSIO_HWE_FATAL:
+               csio_set_state(&hw->sm, csio_hws_uninit);
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_quiescing - Quiescing state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_quiescing(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_QUIESCED:
+               switch (hw->evtflag) {
+               case CSIO_HWE_FW_DLOAD:
+                       csio_set_state(&hw->sm, csio_hws_resetting);
+                       /* Download firmware */
+                       /* Fall through */
+
+               case CSIO_HWE_HBA_RESET:
+                       csio_set_state(&hw->sm, csio_hws_resetting);
+                       /* Start reset of the HBA */
+                       csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWRESET);
+                       csio_wr_destroy_queues(hw, false);
+                       csio_do_reset(hw, false);
+                       csio_post_event(&hw->sm, CSIO_HWE_HBA_RESET_DONE);
+                       break;
+
+               case CSIO_HWE_PCI_REMOVE:
+                       csio_set_state(&hw->sm, csio_hws_removing);
+                       csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWREMOVE);
+                       csio_wr_destroy_queues(hw, true);
+                       /* Now send the bye command */
+                       csio_do_bye(hw);
+                       break;
+
+               case CSIO_HWE_SUSPEND:
+                       csio_set_state(&hw->sm, csio_hws_quiesced);
+                       break;
+
+               case CSIO_HWE_PCIERR_DETECTED:
+                       csio_set_state(&hw->sm, csio_hws_pcierr);
+                       csio_wr_destroy_queues(hw, false);
+                       break;
+
+               default:
+                       CSIO_INC_STATS(hw, n_evt_unexp);
+                       break;
+
+               }
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_quiesced - Quiesced state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_quiesced(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_RESUME:
+               csio_set_state(&hw->sm, csio_hws_configuring);
+               csio_hw_configure(hw);
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_resetting - HW Resetting state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_resetting(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_HBA_RESET_DONE:
+               csio_evtq_start(hw);
+               csio_set_state(&hw->sm, csio_hws_configuring);
+               csio_hw_configure(hw);
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_hws_removing - PCI Hotplug removing state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_removing(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_HBA_RESET:
+               if (!csio_is_hw_master(hw))
+                       break;
+               /*
+                * The BYE should have alerady been issued, so we cant
+                * use the mailbox interface. Hence we use the PL_RST
+                * register directly.
+                */
+               csio_err(hw, "Resetting HW and waiting 2 seconds...\n");
+               csio_wr_reg32(hw, PIORSTMODE | PIORST, PL_RST);
+               mdelay(2000);
+               break;
+
+       /* Should never receive any new events */
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+
+       }
+}
+
+/*
+ * csio_hws_pcierr - PCI Error state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_pcierr(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+       hw->prev_evt = hw->cur_evt;
+       hw->cur_evt = evt;
+       CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_HWE_PCIERR_SLOT_RESET:
+               csio_evtq_start(hw);
+               csio_set_state(&hw->sm, csio_hws_configuring);
+               csio_hw_configure(hw);
+               break;
+
+       default:
+               CSIO_INC_STATS(hw, n_evt_unexp);
+               break;
+       }
+}
+
+/*****************************************************************************/
+/* END: HW SM                                                                */
+/*****************************************************************************/
+
+/* Slow path handlers */
+struct intr_info {
+       unsigned int mask;       /* bits to check in interrupt status */
+       const char *msg;         /* message to print or NULL */
+       short stat_idx;          /* stat counter to increment or -1 */
+       unsigned short fatal;    /* whether the condition reported is fatal */
+};
+
+/*
+ *     csio_handle_intr_status - table driven interrupt handler
+ *     @hw: HW instance
+ *     @reg: the interrupt status register to process
+ *     @acts: table of interrupt actions
+ *
+ *     A table driven interrupt handler that applies a set of masks to an
+ *     interrupt status word and performs the corresponding actions if the
+ *     interrupts described by the mask have occured.  The actions include
+ *     optionally emitting a warning or alert message. The table is terminated
+ *     by an entry specifying mask 0.  Returns the number of fatal interrupt
+ *     conditions.
+ */
+static int
+csio_handle_intr_status(struct csio_hw *hw, unsigned int reg,
+                                const struct intr_info *acts)
+{
+       int fatal = 0;
+       unsigned int mask = 0;
+       unsigned int status = csio_rd_reg32(hw, reg);
+
+       for ( ; acts->mask; ++acts) {
+               if (!(status & acts->mask))
+                       continue;
+               if (acts->fatal) {
+                       fatal++;
+                       csio_fatal(hw, "Fatal %s (0x%x)\n",
+                                   acts->msg, status & acts->mask);
+               } else if (acts->msg)
+                       csio_info(hw, "%s (0x%x)\n",
+                                   acts->msg, status & acts->mask);
+               mask |= acts->mask;
+       }
+       status &= mask;
+       if (status)                           /* clear processed interrupts */
+               csio_wr_reg32(hw, status, reg);
+       return fatal;
+}
+
+/*
+ * Interrupt handler for the PCIE module.
+ */
+static void
+csio_pcie_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info sysbus_intr_info[] = {
+               { RNPP, "RXNP array parity error", -1, 1 },
+               { RPCP, "RXPC array parity error", -1, 1 },
+               { RCIP, "RXCIF array parity error", -1, 1 },
+               { RCCP, "Rx completions control array parity error", -1, 1 },
+               { RFTP, "RXFT array parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info pcie_port_intr_info[] = {
+               { TPCP, "TXPC array parity error", -1, 1 },
+               { TNPP, "TXNP array parity error", -1, 1 },
+               { TFTP, "TXFT array parity error", -1, 1 },
+               { TCAP, "TXCA array parity error", -1, 1 },
+               { TCIP, "TXCIF array parity error", -1, 1 },
+               { RCAP, "RXCA array parity error", -1, 1 },
+               { OTDD, "outbound request TLP discarded", -1, 1 },
+               { RDPE, "Rx data parity error", -1, 1 },
+               { TDUE, "Tx uncorrectable data error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info pcie_intr_info[] = {
+               { MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
+               { MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
+               { MSIDATAPERR, "MSI data parity error", -1, 1 },
+               { MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+               { MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+               { MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+               { MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+               { PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
+               { PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
+               { TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+               { CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
+               { CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+               { CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+               { DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
+               { DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+               { DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+               { HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
+               { HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+               { HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+               { CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+               { FIDPERR, "PCI FID parity error", -1, 1 },
+               { INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
+               { MATAGPERR, "PCI MA tag parity error", -1, 1 },
+               { PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+               { RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
+               { RXWRPERR, "PCI Rx write parity error", -1, 1 },
+               { RPLPERR, "PCI replay buffer parity error", -1, 1 },
+               { PCIESINT, "PCI core secondary fault", -1, 1 },
+               { PCIEPINT, "PCI core primary fault", -1, 1 },
+               { UNXSPLCPLERR, "PCI unexpected split completion error", -1,
+                 0 },
+               { 0, NULL, 0, 0 }
+       };
+
+       int fat;
+
+       fat = csio_handle_intr_status(hw,
+                                   PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+                                   sysbus_intr_info) +
+             csio_handle_intr_status(hw,
+                                   PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+                                   pcie_port_intr_info) +
+             csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
+       if (fat)
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * TP interrupt handler.
+ */
+static void csio_tp_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info tp_intr_info[] = {
+               { 0x3fffffff, "TP parity error", -1, 1 },
+               { FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, TP_INT_CAUSE, tp_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * SGE interrupt handler.
+ */
+static void csio_sge_intr_handler(struct csio_hw *hw)
+{
+       uint64_t v;
+
+       static struct intr_info sge_intr_info[] = {
+               { ERR_CPL_EXCEED_IQE_SIZE,
+                 "SGE received CPL exceeding IQE size", -1, 1 },
+               { ERR_INVALID_CIDX_INC,
+                 "SGE GTS CIDX increment too large", -1, 0 },
+               { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
+               { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
+               { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
+                 "SGE IQID > 1023 received CPL for FL", -1, 0 },
+               { ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
+                 0 },
+               { ERR_BAD_DB_PIDX2, "SGE DBP 2 pidx increment too large", -1,
+                 0 },
+               { ERR_BAD_DB_PIDX1, "SGE DBP 1 pidx increment too large", -1,
+                 0 },
+               { ERR_BAD_DB_PIDX0, "SGE DBP 0 pidx increment too large", -1,
+                 0 },
+               { ERR_ING_CTXT_PRIO,
+                 "SGE too many priority ingress contexts", -1, 0 },
+               { ERR_EGR_CTXT_PRIO,
+                 "SGE too many priority egress contexts", -1, 0 },
+               { INGRESS_SIZE_ERR, "SGE illegal ingress QID", -1, 0 },
+               { EGRESS_SIZE_ERR, "SGE illegal egress QID", -1, 0 },
+               { 0, NULL, 0, 0 }
+       };
+
+       v = (uint64_t)csio_rd_reg32(hw, SGE_INT_CAUSE1) |
+           ((uint64_t)csio_rd_reg32(hw, SGE_INT_CAUSE2) << 32);
+       if (v) {
+               csio_fatal(hw, "SGE parity error (%#llx)\n",
+                           (unsigned long long)v);
+               csio_wr_reg32(hw, (uint32_t)(v & 0xFFFFFFFF),
+                                               SGE_INT_CAUSE1);
+               csio_wr_reg32(hw, (uint32_t)(v >> 32), SGE_INT_CAUSE2);
+       }
+
+       v |= csio_handle_intr_status(hw, SGE_INT_CAUSE3, sge_intr_info);
+
+       if (csio_handle_intr_status(hw, SGE_INT_CAUSE3, sge_intr_info) ||
+           v != 0)
+               csio_hw_fatal_err(hw);
+}
+
+#define CIM_OBQ_INTR (OBQULP0PARERR | OBQULP1PARERR | OBQULP2PARERR |\
+                     OBQULP3PARERR | OBQSGEPARERR | OBQNCSIPARERR)
+#define CIM_IBQ_INTR (IBQTP0PARERR | IBQTP1PARERR | IBQULPPARERR |\
+                     IBQSGEHIPARERR | IBQSGELOPARERR | IBQNCSIPARERR)
+
+/*
+ * CIM interrupt handler.
+ */
+static void csio_cim_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info cim_intr_info[] = {
+               { PREFDROPINT, "CIM control register prefetch drop", -1, 1 },
+               { CIM_OBQ_INTR, "CIM OBQ parity error", -1, 1 },
+               { CIM_IBQ_INTR, "CIM IBQ parity error", -1, 1 },
+               { MBUPPARERR, "CIM mailbox uP parity error", -1, 1 },
+               { MBHOSTPARERR, "CIM mailbox host parity error", -1, 1 },
+               { TIEQINPARERRINT, "CIM TIEQ outgoing parity error", -1, 1 },
+               { TIEQOUTPARERRINT, "CIM TIEQ incoming parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info cim_upintr_info[] = {
+               { RSVDSPACEINT, "CIM reserved space access", -1, 1 },
+               { ILLTRANSINT, "CIM illegal transaction", -1, 1 },
+               { ILLWRINT, "CIM illegal write", -1, 1 },
+               { ILLRDINT, "CIM illegal read", -1, 1 },
+               { ILLRDBEINT, "CIM illegal read BE", -1, 1 },
+               { ILLWRBEINT, "CIM illegal write BE", -1, 1 },
+               { SGLRDBOOTINT, "CIM single read from boot space", -1, 1 },
+               { SGLWRBOOTINT, "CIM single write to boot space", -1, 1 },
+               { BLKWRBOOTINT, "CIM block write to boot space", -1, 1 },
+               { SGLRDFLASHINT, "CIM single read from flash space", -1, 1 },
+               { SGLWRFLASHINT, "CIM single write to flash space", -1, 1 },
+               { BLKWRFLASHINT, "CIM block write to flash space", -1, 1 },
+               { SGLRDEEPROMINT, "CIM single EEPROM read", -1, 1 },
+               { SGLWREEPROMINT, "CIM single EEPROM write", -1, 1 },
+               { BLKRDEEPROMINT, "CIM block EEPROM read", -1, 1 },
+               { BLKWREEPROMINT, "CIM block EEPROM write", -1, 1 },
+               { SGLRDCTLINT , "CIM single read from CTL space", -1, 1 },
+               { SGLWRCTLINT , "CIM single write to CTL space", -1, 1 },
+               { BLKRDCTLINT , "CIM block read from CTL space", -1, 1 },
+               { BLKWRCTLINT , "CIM block write to CTL space", -1, 1 },
+               { SGLRDPLINT , "CIM single read from PL space", -1, 1 },
+               { SGLWRPLINT , "CIM single write to PL space", -1, 1 },
+               { BLKRDPLINT , "CIM block read from PL space", -1, 1 },
+               { BLKWRPLINT , "CIM block write to PL space", -1, 1 },
+               { REQOVRLOOKUPINT , "CIM request FIFO overwrite", -1, 1 },
+               { RSPOVRLOOKUPINT , "CIM response FIFO overwrite", -1, 1 },
+               { TIMEOUTINT , "CIM PIF timeout", -1, 1 },
+               { TIMEOUTMAINT , "CIM PIF MA timeout", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       int fat;
+
+       fat = csio_handle_intr_status(hw, CIM_HOST_INT_CAUSE,
+                                   cim_intr_info) +
+             csio_handle_intr_status(hw, CIM_HOST_UPACC_INT_CAUSE,
+                                   cim_upintr_info);
+       if (fat)
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * ULP RX interrupt handler.
+ */
+static void csio_ulprx_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info ulprx_intr_info[] = {
+               { 0x1800000, "ULPRX context error", -1, 1 },
+               { 0x7fffff, "ULPRX parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, ULP_RX_INT_CAUSE, ulprx_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * ULP TX interrupt handler.
+ */
+static void csio_ulptx_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info ulptx_intr_info[] = {
+               { PBL_BOUND_ERR_CH3, "ULPTX channel 3 PBL out of bounds", -1,
+                 0 },
+               { PBL_BOUND_ERR_CH2, "ULPTX channel 2 PBL out of bounds", -1,
+                 0 },
+               { PBL_BOUND_ERR_CH1, "ULPTX channel 1 PBL out of bounds", -1,
+                 0 },
+               { PBL_BOUND_ERR_CH0, "ULPTX channel 0 PBL out of bounds", -1,
+                 0 },
+               { 0xfffffff, "ULPTX parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, ULP_TX_INT_CAUSE, ulptx_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * PM TX interrupt handler.
+ */
+static void csio_pmtx_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info pmtx_intr_info[] = {
+               { PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large", -1, 1 },
+               { PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large", -1, 1 },
+               { PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large", -1, 1 },
+               { ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1 },
+               { 0xffffff0, "PMTX framing error", -1, 1 },
+               { OESPI_PAR_ERROR, "PMTX oespi parity error", -1, 1 },
+               { DB_OPTIONS_PAR_ERROR, "PMTX db_options parity error", -1,
+                 1 },
+               { ICSPI_PAR_ERROR, "PMTX icspi parity error", -1, 1 },
+               { C_PCMD_PAR_ERROR, "PMTX c_pcmd parity error", -1, 1},
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, PM_TX_INT_CAUSE, pmtx_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * PM RX interrupt handler.
+ */
+static void csio_pmrx_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info pmrx_intr_info[] = {
+               { ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1 },
+               { 0x3ffff0, "PMRX framing error", -1, 1 },
+               { OCSPI_PAR_ERROR, "PMRX ocspi parity error", -1, 1 },
+               { DB_OPTIONS_PAR_ERROR, "PMRX db_options parity error", -1,
+                 1 },
+               { IESPI_PAR_ERROR, "PMRX iespi parity error", -1, 1 },
+               { E_PCMD_PAR_ERROR, "PMRX e_pcmd parity error", -1, 1},
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, PM_RX_INT_CAUSE, pmrx_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * CPL switch interrupt handler.
+ */
+static void csio_cplsw_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info cplsw_intr_info[] = {
+               { CIM_OP_MAP_PERR, "CPLSW CIM op_map parity error", -1, 1 },
+               { CIM_OVFL_ERROR, "CPLSW CIM overflow", -1, 1 },
+               { TP_FRAMING_ERROR, "CPLSW TP framing error", -1, 1 },
+               { SGE_FRAMING_ERROR, "CPLSW SGE framing error", -1, 1 },
+               { CIM_FRAMING_ERROR, "CPLSW CIM framing error", -1, 1 },
+               { ZERO_SWITCH_ERROR, "CPLSW no-switch error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, CPL_INTR_CAUSE, cplsw_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * LE interrupt handler.
+ */
+static void csio_le_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info le_intr_info[] = {
+               { LIPMISS, "LE LIP miss", -1, 0 },
+               { LIP0, "LE 0 LIP error", -1, 0 },
+               { PARITYERR, "LE parity error", -1, 1 },
+               { UNKNOWNCMD, "LE unknown command", -1, 1 },
+               { REQQPARERR, "LE request queue parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, LE_DB_INT_CAUSE, le_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * MPS interrupt handler.
+ */
+static void csio_mps_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info mps_rx_intr_info[] = {
+               { 0xffffff, "MPS Rx parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info mps_tx_intr_info[] = {
+               { TPFIFO, "MPS Tx TP FIFO parity error", -1, 1 },
+               { NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
+               { TXDATAFIFO, "MPS Tx data FIFO parity error", -1, 1 },
+               { TXDESCFIFO, "MPS Tx desc FIFO parity error", -1, 1 },
+               { BUBBLE, "MPS Tx underflow", -1, 1 },
+               { SECNTERR, "MPS Tx SOP/EOP error", -1, 1 },
+               { FRMERR, "MPS Tx framing error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info mps_trc_intr_info[] = {
+               { FILTMEM, "MPS TRC filter parity error", -1, 1 },
+               { PKTFIFO, "MPS TRC packet FIFO parity error", -1, 1 },
+               { MISCPERR, "MPS TRC misc parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info mps_stat_sram_intr_info[] = {
+               { 0x1fffff, "MPS statistics SRAM parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info mps_stat_tx_intr_info[] = {
+               { 0xfffff, "MPS statistics Tx FIFO parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info mps_stat_rx_intr_info[] = {
+               { 0xffffff, "MPS statistics Rx FIFO parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+       static struct intr_info mps_cls_intr_info[] = {
+               { MATCHSRAM, "MPS match SRAM parity error", -1, 1 },
+               { MATCHTCAM, "MPS match TCAM parity error", -1, 1 },
+               { HASHSRAM, "MPS hash SRAM parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       int fat;
+
+       fat = csio_handle_intr_status(hw, MPS_RX_PERR_INT_CAUSE,
+                                   mps_rx_intr_info) +
+             csio_handle_intr_status(hw, MPS_TX_INT_CAUSE,
+                                   mps_tx_intr_info) +
+             csio_handle_intr_status(hw, MPS_TRC_INT_CAUSE,
+                                   mps_trc_intr_info) +
+             csio_handle_intr_status(hw, MPS_STAT_PERR_INT_CAUSE_SRAM,
+                                   mps_stat_sram_intr_info) +
+             csio_handle_intr_status(hw, MPS_STAT_PERR_INT_CAUSE_TX_FIFO,
+                                   mps_stat_tx_intr_info) +
+             csio_handle_intr_status(hw, MPS_STAT_PERR_INT_CAUSE_RX_FIFO,
+                                   mps_stat_rx_intr_info) +
+             csio_handle_intr_status(hw, MPS_CLS_INT_CAUSE,
+                                   mps_cls_intr_info);
+
+       csio_wr_reg32(hw, 0, MPS_INT_CAUSE);
+       csio_rd_reg32(hw, MPS_INT_CAUSE);                    /* flush */
+       if (fat)
+               csio_hw_fatal_err(hw);
+}
+
+#define MEM_INT_MASK (PERR_INT_CAUSE | ECC_CE_INT_CAUSE | ECC_UE_INT_CAUSE)
+
+/*
+ * EDC/MC interrupt handler.
+ */
+static void csio_mem_intr_handler(struct csio_hw *hw, int idx)
+{
+       static const char name[3][5] = { "EDC0", "EDC1", "MC" };
+
+       unsigned int addr, cnt_addr, v;
+
+       if (idx <= MEM_EDC1) {
+               addr = EDC_REG(EDC_INT_CAUSE, idx);
+               cnt_addr = EDC_REG(EDC_ECC_STATUS, idx);
+       } else {
+               addr = MC_INT_CAUSE;
+               cnt_addr = MC_ECC_STATUS;
+       }
+
+       v = csio_rd_reg32(hw, addr) & MEM_INT_MASK;
+       if (v & PERR_INT_CAUSE)
+               csio_fatal(hw, "%s FIFO parity error\n", name[idx]);
+       if (v & ECC_CE_INT_CAUSE) {
+               uint32_t cnt = ECC_CECNT_GET(csio_rd_reg32(hw, cnt_addr));
+
+               csio_wr_reg32(hw, ECC_CECNT_MASK, cnt_addr);
+               csio_warn(hw, "%u %s correctable ECC data error%s\n",
+                           cnt, name[idx], cnt > 1 ? "s" : "");
+       }
+       if (v & ECC_UE_INT_CAUSE)
+               csio_fatal(hw, "%s uncorrectable ECC data error\n", name[idx]);
+
+       csio_wr_reg32(hw, v, addr);
+       if (v & (PERR_INT_CAUSE | ECC_UE_INT_CAUSE))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * MA interrupt handler.
+ */
+static void csio_ma_intr_handler(struct csio_hw *hw)
+{
+       uint32_t v, status = csio_rd_reg32(hw, MA_INT_CAUSE);
+
+       if (status & MEM_PERR_INT_CAUSE)
+               csio_fatal(hw, "MA parity error, parity status %#x\n",
+                           csio_rd_reg32(hw, MA_PARITY_ERROR_STATUS));
+       if (status & MEM_WRAP_INT_CAUSE) {
+               v = csio_rd_reg32(hw, MA_INT_WRAP_STATUS);
+               csio_fatal(hw,
+                  "MA address wrap-around error by client %u to address %#x\n",
+                  MEM_WRAP_CLIENT_NUM_GET(v), MEM_WRAP_ADDRESS_GET(v) << 4);
+       }
+       csio_wr_reg32(hw, status, MA_INT_CAUSE);
+       csio_hw_fatal_err(hw);
+}
+
+/*
+ * SMB interrupt handler.
+ */
+static void csio_smb_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info smb_intr_info[] = {
+               { MSTTXFIFOPARINT, "SMB master Tx FIFO parity error", -1, 1 },
+               { MSTRXFIFOPARINT, "SMB master Rx FIFO parity error", -1, 1 },
+               { SLVFIFOPARINT, "SMB slave FIFO parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, SMB_INT_CAUSE, smb_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * NC-SI interrupt handler.
+ */
+static void csio_ncsi_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info ncsi_intr_info[] = {
+               { CIM_DM_PRTY_ERR, "NC-SI CIM parity error", -1, 1 },
+               { MPS_DM_PRTY_ERR, "NC-SI MPS parity error", -1, 1 },
+               { TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error", -1, 1 },
+               { RXFIFO_PRTY_ERR, "NC-SI Rx FIFO parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, NCSI_INT_CAUSE, ncsi_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ * XGMAC interrupt handler.
+ */
+static void csio_xgmac_intr_handler(struct csio_hw *hw, int port)
+{
+       uint32_t v = csio_rd_reg32(hw, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+
+       v &= TXFIFO_PRTY_ERR | RXFIFO_PRTY_ERR;
+       if (!v)
+               return;
+
+       if (v & TXFIFO_PRTY_ERR)
+               csio_fatal(hw, "XGMAC %d Tx FIFO parity error\n", port);
+       if (v & RXFIFO_PRTY_ERR)
+               csio_fatal(hw, "XGMAC %d Rx FIFO parity error\n", port);
+       csio_wr_reg32(hw, v, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+       csio_hw_fatal_err(hw);
+}
+
+/*
+ * PL interrupt handler.
+ */
+static void csio_pl_intr_handler(struct csio_hw *hw)
+{
+       static struct intr_info pl_intr_info[] = {
+               { FATALPERR, "T4 fatal parity error", -1, 1 },
+               { PERRVFID, "PL VFID_MAP parity error", -1, 1 },
+               { 0, NULL, 0, 0 }
+       };
+
+       if (csio_handle_intr_status(hw, PL_PL_INT_CAUSE, pl_intr_info))
+               csio_hw_fatal_err(hw);
+}
+
+/*
+ *     csio_hw_slow_intr_handler - control path interrupt handler
+ *     @hw: HW module
+ *
+ *     Interrupt handler for non-data global interrupt events, e.g., errors.
+ *     The designation 'slow' is because it involves register reads, while
+ *     data interrupts typically don't involve any MMIOs.
+ */
+int
+csio_hw_slow_intr_handler(struct csio_hw *hw)
+{
+       uint32_t cause = csio_rd_reg32(hw, PL_INT_CAUSE);
+
+       if (!(cause & CSIO_GLBL_INTR_MASK)) {
+               CSIO_INC_STATS(hw, n_plint_unexp);
+               return 0;
+       }
+
+       csio_dbg(hw, "Slow interrupt! cause: 0x%x\n", cause);
+
+       CSIO_INC_STATS(hw, n_plint_cnt);
+
+       if (cause & CIM)
+               csio_cim_intr_handler(hw);
+
+       if (cause & MPS)
+               csio_mps_intr_handler(hw);
+
+       if (cause & NCSI)
+               csio_ncsi_intr_handler(hw);
+
+       if (cause & PL)
+               csio_pl_intr_handler(hw);
+
+       if (cause & SMB)
+               csio_smb_intr_handler(hw);
+
+       if (cause & XGMAC0)
+               csio_xgmac_intr_handler(hw, 0);
+
+       if (cause & XGMAC1)
+               csio_xgmac_intr_handler(hw, 1);
+
+       if (cause & XGMAC_KR0)
+               csio_xgmac_intr_handler(hw, 2);
+
+       if (cause & XGMAC_KR1)
+               csio_xgmac_intr_handler(hw, 3);
+
+       if (cause & PCIE)
+               csio_pcie_intr_handler(hw);
+
+       if (cause & MC)
+               csio_mem_intr_handler(hw, MEM_MC);
+
+       if (cause & EDC0)
+               csio_mem_intr_handler(hw, MEM_EDC0);
+
+       if (cause & EDC1)
+               csio_mem_intr_handler(hw, MEM_EDC1);
+
+       if (cause & LE)
+               csio_le_intr_handler(hw);
+
+       if (cause & TP)
+               csio_tp_intr_handler(hw);
+
+       if (cause & MA)
+               csio_ma_intr_handler(hw);
+
+       if (cause & PM_TX)
+               csio_pmtx_intr_handler(hw);
+
+       if (cause & PM_RX)
+               csio_pmrx_intr_handler(hw);
+
+       if (cause & ULP_RX)
+               csio_ulprx_intr_handler(hw);
+
+       if (cause & CPL_SWITCH)
+               csio_cplsw_intr_handler(hw);
+
+       if (cause & SGE)
+               csio_sge_intr_handler(hw);
+
+       if (cause & ULP_TX)
+               csio_ulptx_intr_handler(hw);
+
+       /* Clear the interrupts just processed for which we are the master. */
+       csio_wr_reg32(hw, cause & CSIO_GLBL_INTR_MASK, PL_INT_CAUSE);
+       csio_rd_reg32(hw, PL_INT_CAUSE); /* flush */
+
+       return 1;
+}
+
+/*****************************************************************************
+ * HW <--> mailbox interfacing routines.
+ ****************************************************************************/
+/*
+ * csio_mberr_worker - Worker thread (dpc) for mailbox/error completions
+ *
+ * @data: Private data pointer.
+ *
+ * Called from worker thread context.
+ */
+static void
+csio_mberr_worker(void *data)
+{
+       struct csio_hw *hw = (struct csio_hw *)data;
+       struct csio_mbm *mbm = &hw->mbm;
+       LIST_HEAD(cbfn_q);
+       struct csio_mb *mbp_next;
+       int rv;
+
+       del_timer_sync(&mbm->timer);
+
+       spin_lock_irq(&hw->lock);
+       if (list_empty(&mbm->cbfn_q)) {
+               spin_unlock_irq(&hw->lock);
+               return;
+       }
+
+       list_splice_tail_init(&mbm->cbfn_q, &cbfn_q);
+       mbm->stats.n_cbfnq = 0;
+
+       /* Try to start waiting mailboxes */
+       if (!list_empty(&mbm->req_q)) {
+               mbp_next = list_first_entry(&mbm->req_q, struct csio_mb, list);
+               list_del_init(&mbp_next->list);
+
+               rv = csio_mb_issue(hw, mbp_next);
+               if (rv != 0)
+                       list_add_tail(&mbp_next->list, &mbm->req_q);
+               else
+                       CSIO_DEC_STATS(mbm, n_activeq);
+       }
+       spin_unlock_irq(&hw->lock);
+
+       /* Now callback completions */
+       csio_mb_completions(hw, &cbfn_q);
+}
+
+/*
+ * csio_hw_mb_timer - Top-level Mailbox timeout handler.
+ *
+ * @data: private data pointer
+ *
+ **/
+static void
+csio_hw_mb_timer(uintptr_t data)
+{
+       struct csio_hw *hw = (struct csio_hw *)data;
+       struct csio_mb *mbp = NULL;
+
+       spin_lock_irq(&hw->lock);
+       mbp = csio_mb_tmo_handler(hw);
+       spin_unlock_irq(&hw->lock);
+
+       /* Call back the function for the timed-out Mailbox */
+       if (mbp)
+               mbp->mb_cbfn(hw, mbp);
+
+}
+
+/*
+ * csio_hw_mbm_cleanup - Cleanup Mailbox module.
+ * @hw: HW module
+ *
+ * Called with lock held, should exit with lock held.
+ * Cancels outstanding mailboxes (waiting, in-flight) and gathers them
+ * into a local queue. Drops lock and calls the completions. Holds
+ * lock and returns.
+ */
+static void
+csio_hw_mbm_cleanup(struct csio_hw *hw)
+{
+       LIST_HEAD(cbfn_q);
+
+       csio_mb_cancel_all(hw, &cbfn_q);
+
+       spin_unlock_irq(&hw->lock);
+       csio_mb_completions(hw, &cbfn_q);
+       spin_lock_irq(&hw->lock);
+}
+
+/*****************************************************************************
+ * Event handling
+ ****************************************************************************/
+int
+csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type, void *evt_msg,
+                       uint16_t len)
+{
+       struct csio_evt_msg *evt_entry = NULL;
+
+       if (type >= CSIO_EVT_MAX)
+               return -EINVAL;
+
+       if (len > CSIO_EVT_MSG_SIZE)
+               return -EINVAL;
+
+       if (hw->flags & CSIO_HWF_FWEVT_STOP)
+               return -EINVAL;
+
+       if (list_empty(&hw->evt_free_q)) {
+               csio_err(hw, "Failed to alloc evt entry, msg type %d len %d\n",
+                        type, len);
+               return -ENOMEM;
+       }
+
+       evt_entry = list_first_entry(&hw->evt_free_q,
+                                    struct csio_evt_msg, list);
+       list_del_init(&evt_entry->list);
+
+       /* copy event msg and queue the event */
+       evt_entry->type = type;
+       memcpy((void *)evt_entry->data, evt_msg, len);
+       list_add_tail(&evt_entry->list, &hw->evt_active_q);
+
+       CSIO_DEC_STATS(hw, n_evt_freeq);
+       CSIO_INC_STATS(hw, n_evt_activeq);
+
+       return 0;
+}
+
+static int
+csio_enqueue_evt_lock(struct csio_hw *hw, enum csio_evt type, void *evt_msg,
+                       uint16_t len, bool msg_sg)
+{
+       struct csio_evt_msg *evt_entry = NULL;
+       struct csio_fl_dma_buf *fl_sg;
+       uint32_t off = 0;
+       unsigned long flags;
+       int n, ret = 0;
+
+       if (type >= CSIO_EVT_MAX)
+               return -EINVAL;
+
+       if (len > CSIO_EVT_MSG_SIZE)
+               return -EINVAL;
+
+       spin_lock_irqsave(&hw->lock, flags);
+       if (hw->flags & CSIO_HWF_FWEVT_STOP) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (list_empty(&hw->evt_free_q)) {
+               csio_err(hw, "Failed to alloc evt entry, msg type %d len %d\n",
+                        type, len);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       evt_entry = list_first_entry(&hw->evt_free_q,
+                                    struct csio_evt_msg, list);
+       list_del_init(&evt_entry->list);
+
+       /* copy event msg and queue the event */
+       evt_entry->type = type;
+
+       /* If Payload in SG list*/
+       if (msg_sg) {
+               fl_sg = (struct csio_fl_dma_buf *) evt_msg;
+               for (n = 0; (n < CSIO_MAX_FLBUF_PER_IQWR && off < len); n++) {
+                       memcpy((void *)((uintptr_t)evt_entry->data + off),
+                               fl_sg->flbufs[n].vaddr,
+                               fl_sg->flbufs[n].len);
+                       off += fl_sg->flbufs[n].len;
+               }
+       } else
+               memcpy((void *)evt_entry->data, evt_msg, len);
+
+       list_add_tail(&evt_entry->list, &hw->evt_active_q);
+       CSIO_DEC_STATS(hw, n_evt_freeq);
+       CSIO_INC_STATS(hw, n_evt_activeq);
+out:
+       spin_unlock_irqrestore(&hw->lock, flags);
+       return ret;
+}
+
+static void
+csio_free_evt(struct csio_hw *hw, struct csio_evt_msg *evt_entry)
+{
+       if (evt_entry) {
+               spin_lock_irq(&hw->lock);
+               list_del_init(&evt_entry->list);
+               list_add_tail(&evt_entry->list, &hw->evt_free_q);
+               CSIO_DEC_STATS(hw, n_evt_activeq);
+               CSIO_INC_STATS(hw, n_evt_freeq);
+               spin_unlock_irq(&hw->lock);
+       }
+}
+
+void
+csio_evtq_flush(struct csio_hw *hw)
+{
+       uint32_t count;
+       count = 30;
+       while (hw->flags & CSIO_HWF_FWEVT_PENDING && count--) {
+               spin_unlock_irq(&hw->lock);
+               msleep(2000);
+               spin_lock_irq(&hw->lock);
+       }
+
+       CSIO_DB_ASSERT(!(hw->flags & CSIO_HWF_FWEVT_PENDING));
+}
+
+static void
+csio_evtq_stop(struct csio_hw *hw)
+{
+       hw->flags |= CSIO_HWF_FWEVT_STOP;
+}
+
+static void
+csio_evtq_start(struct csio_hw *hw)
+{
+       hw->flags &= ~CSIO_HWF_FWEVT_STOP;
+}
+
+static void
+csio_evtq_cleanup(struct csio_hw *hw)
+{
+       struct list_head *evt_entry, *next_entry;
+
+       /* Release outstanding events from activeq to freeq*/
+       if (!list_empty(&hw->evt_active_q))
+               list_splice_tail_init(&hw->evt_active_q, &hw->evt_free_q);
+
+       hw->stats.n_evt_activeq = 0;
+       hw->flags &= ~CSIO_HWF_FWEVT_PENDING;
+
+       /* Freeup event entry */
+       list_for_each_safe(evt_entry, next_entry, &hw->evt_free_q) {
+               kfree(evt_entry);
+               CSIO_DEC_STATS(hw, n_evt_freeq);
+       }
+
+       hw->stats.n_evt_freeq = 0;
+}
+
+
+static void
+csio_process_fwevtq_entry(struct csio_hw *hw, void *wr, uint32_t len,
+                         struct csio_fl_dma_buf *flb, void *priv)
+{
+       __u8 op;
+       __be64 *data;
+       void *msg = NULL;
+       uint32_t msg_len = 0;
+       bool msg_sg = 0;
+
+       op = ((struct rss_header *) wr)->opcode;
+       if (op == CPL_FW6_PLD) {
+               CSIO_INC_STATS(hw, n_cpl_fw6_pld);
+               if (!flb || !flb->totlen) {
+                       CSIO_INC_STATS(hw, n_cpl_unexp);
+                       return;
+               }
+
+               msg = (void *) flb;
+               msg_len = flb->totlen;
+               msg_sg = 1;
+
+               data = (__be64 *) msg;
+       } else if (op == CPL_FW6_MSG || op == CPL_FW4_MSG) {
+
+               CSIO_INC_STATS(hw, n_cpl_fw6_msg);
+               /* skip RSS header */
+               msg = (void *)((uintptr_t)wr + sizeof(__be64));
+               msg_len = (op == CPL_FW6_MSG) ? sizeof(struct cpl_fw6_msg) :
+                          sizeof(struct cpl_fw4_msg);
+
+               data = (__be64 *) msg;
+       } else {
+               csio_warn(hw, "unexpected CPL %#x on FW event queue\n", op);
+               CSIO_INC_STATS(hw, n_cpl_unexp);
+               return;
+       }
+
+       /*
+        * Enqueue event to EventQ. Events processing happens
+        * in Event worker thread context
+        */
+       if (csio_enqueue_evt_lock(hw, CSIO_EVT_FW, msg,
+                                 (uint16_t)msg_len, msg_sg))
+               CSIO_INC_STATS(hw, n_evt_drop);
+}
+
+void
+csio_evtq_worker(struct work_struct *work)
+{
+       struct csio_hw *hw = container_of(work, struct csio_hw, evtq_work);
+       struct list_head *evt_entry, *next_entry;
+       LIST_HEAD(evt_q);
+       struct csio_evt_msg     *evt_msg;
+       struct cpl_fw6_msg *msg;
+       struct csio_rnode *rn;
+       int rv = 0;
+       uint8_t evtq_stop = 0;
+
+       csio_dbg(hw, "event worker thread active evts#%d\n",
+                hw->stats.n_evt_activeq);
+
+       spin_lock_irq(&hw->lock);
+       while (!list_empty(&hw->evt_active_q)) {
+               list_splice_tail_init(&hw->evt_active_q, &evt_q);
+               spin_unlock_irq(&hw->lock);
+
+               list_for_each_safe(evt_entry, next_entry, &evt_q) {
+                       evt_msg = (struct csio_evt_msg *) evt_entry;
+
+                       /* Drop events if queue is STOPPED */
+                       spin_lock_irq(&hw->lock);
+                       if (hw->flags & CSIO_HWF_FWEVT_STOP)
+                               evtq_stop = 1;
+                       spin_unlock_irq(&hw->lock);
+                       if (evtq_stop) {
+                               CSIO_INC_STATS(hw, n_evt_drop);
+                               goto free_evt;
+                       }
+
+                       switch (evt_msg->type) {
+                       case CSIO_EVT_FW:
+                               msg = (struct cpl_fw6_msg *)(evt_msg->data);
+
+                               if ((msg->opcode == CPL_FW6_MSG ||
+                                    msg->opcode == CPL_FW4_MSG) &&
+                                   !msg->type) {
+                                       rv = csio_mb_fwevt_handler(hw,
+                                                               msg->data);
+                                       if (!rv)
+                                               break;
+                                       /* Handle any remaining fw events */
+                                       csio_fcoe_fwevt_handler(hw,
+                                                       msg->opcode, msg->data);
+                               } else if (msg->opcode == CPL_FW6_PLD) {
+
+                                       csio_fcoe_fwevt_handler(hw,
+                                                       msg->opcode, msg->data);
+                               } else {
+                                       csio_warn(hw,
+                                            "Unhandled FW msg op %x type %x\n",
+                                                 msg->opcode, msg->type);
+                                       CSIO_INC_STATS(hw, n_evt_drop);
+                               }
+                               break;
+
+                       case CSIO_EVT_MBX:
+                               csio_mberr_worker(hw);
+                               break;
+
+                       case CSIO_EVT_DEV_LOSS:
+                               memcpy(&rn, evt_msg->data, sizeof(rn));
+                               csio_rnode_devloss_handler(rn);
+                               break;
+
+                       default:
+                               csio_warn(hw, "Unhandled event %x on evtq\n",
+                                         evt_msg->type);
+                               CSIO_INC_STATS(hw, n_evt_unexp);
+                               break;
+                       }
+free_evt:
+                       csio_free_evt(hw, evt_msg);
+               }
+
+               spin_lock_irq(&hw->lock);
+       }
+       hw->flags &= ~CSIO_HWF_FWEVT_PENDING;
+       spin_unlock_irq(&hw->lock);
+}
+
+int
+csio_fwevtq_handler(struct csio_hw *hw)
+{
+       int rv;
+
+       if (csio_q_iqid(hw, hw->fwevt_iq_idx) == CSIO_MAX_QID) {
+               CSIO_INC_STATS(hw, n_int_stray);
+               return -EINVAL;
+       }
+
+       rv = csio_wr_process_iq_idx(hw, hw->fwevt_iq_idx,
+                          csio_process_fwevtq_entry, NULL);
+       return rv;
+}
+
+/****************************************************************************
+ * Entry points
+ ****************************************************************************/
+
+/* Management module */
+/*
+ * csio_mgmt_req_lookup - Lookup the given IO req exist in Active Q.
+ * mgmt - mgmt module
+ * @io_req - io request
+ *
+ * Return - 0:if given IO Req exists in active Q.
+ *          -EINVAL  :if lookup fails.
+ */
+int
+csio_mgmt_req_lookup(struct csio_mgmtm *mgmtm, struct csio_ioreq *io_req)
+{
+       struct list_head *tmp;
+
+       /* Lookup ioreq in the ACTIVEQ */
+       list_for_each(tmp, &mgmtm->active_q) {
+               if (io_req == (struct csio_ioreq *)tmp)
+                       return 0;
+       }
+       return -EINVAL;
+}
+
+#define        ECM_MIN_TMO     1000    /* Minimum timeout value for req */
+
+/*
+ * csio_mgmts_tmo_handler - MGMT IO Timeout handler.
+ * @data - Event data.
+ *
+ * Return - none.
+ */
+static void
+csio_mgmt_tmo_handler(uintptr_t data)
+{
+       struct csio_mgmtm *mgmtm = (struct csio_mgmtm *) data;
+       struct list_head *tmp;
+       struct csio_ioreq *io_req;
+
+       csio_dbg(mgmtm->hw, "Mgmt timer invoked!\n");
+
+       spin_lock_irq(&mgmtm->hw->lock);
+
+       list_for_each(tmp, &mgmtm->active_q) {
+               io_req = (struct csio_ioreq *) tmp;
+               io_req->tmo -= min_t(uint32_t, io_req->tmo, ECM_MIN_TMO);
+
+               if (!io_req->tmo) {
+                       /* Dequeue the request from retry Q. */
+                       tmp = csio_list_prev(tmp);
+                       list_del_init(&io_req->sm.sm_list);
+                       if (io_req->io_cbfn) {
+                               /* io_req will be freed by completion handler */
+                               io_req->wr_status = -ETIMEDOUT;
+                               io_req->io_cbfn(mgmtm->hw, io_req);
+                       } else {
+                               CSIO_DB_ASSERT(0);
+                       }
+               }
+       }
+
+       /* If retry queue is not empty, re-arm timer */
+       if (!list_empty(&mgmtm->active_q))
+               mod_timer(&mgmtm->mgmt_timer,
+                         jiffies + msecs_to_jiffies(ECM_MIN_TMO));
+       spin_unlock_irq(&mgmtm->hw->lock);
+}
+
+static void
+csio_mgmtm_cleanup(struct csio_mgmtm *mgmtm)
+{
+       struct csio_hw *hw = mgmtm->hw;
+       struct csio_ioreq *io_req;
+       struct list_head *tmp;
+       uint32_t count;
+
+       count = 30;
+       /* Wait for all outstanding req to complete gracefully */
+       while ((!list_empty(&mgmtm->active_q)) && count--) {
+               spin_unlock_irq(&hw->lock);
+               msleep(2000);
+               spin_lock_irq(&hw->lock);
+       }
+
+       /* release outstanding req from ACTIVEQ */
+       list_for_each(tmp, &mgmtm->active_q) {
+               io_req = (struct csio_ioreq *) tmp;
+               tmp = csio_list_prev(tmp);
+               list_del_init(&io_req->sm.sm_list);
+               mgmtm->stats.n_active--;
+               if (io_req->io_cbfn) {
+                       /* io_req will be freed by completion handler */
+                       io_req->wr_status = -ETIMEDOUT;
+                       io_req->io_cbfn(mgmtm->hw, io_req);
+               }
+       }
+}
+
+/*
+ * csio_mgmt_init - Mgmt module init entry point
+ * @mgmtsm - mgmt module
+ * @hw  - HW module
+ *
+ * Initialize mgmt timer, resource wait queue, active queue,
+ * completion q. Allocate Egress and Ingress
+ * WR queues and save off the queue index returned by the WR
+ * module for future use. Allocate and save off mgmt reqs in the
+ * mgmt_req_freelist for future use. Make sure their SM is initialized
+ * to uninit state.
+ * Returns: 0 - on success
+ *          -ENOMEM   - on error.
+ */
+static int
+csio_mgmtm_init(struct csio_mgmtm *mgmtm, struct csio_hw *hw)
+{
+       struct timer_list *timer = &mgmtm->mgmt_timer;
+
+       init_timer(timer);
+       timer->function = csio_mgmt_tmo_handler;
+       timer->data = (unsigned long)mgmtm;
+
+       INIT_LIST_HEAD(&mgmtm->active_q);
+       INIT_LIST_HEAD(&mgmtm->cbfn_q);
+
+       mgmtm->hw = hw;
+       /*mgmtm->iq_idx = hw->fwevt_iq_idx;*/
+
+       return 0;
+}
+
+/*
+ * csio_mgmtm_exit - MGMT module exit entry point
+ * @mgmtsm - mgmt module
+ *
+ * This function called during MGMT module uninit.
+ * Stop timers, free ioreqs allocated.
+ * Returns: None
+ *
+ */
+static void
+csio_mgmtm_exit(struct csio_mgmtm *mgmtm)
+{
+       del_timer_sync(&mgmtm->mgmt_timer);
+}
+
+
+/**
+ * csio_hw_start - Kicks off the HW State machine
+ * @hw:                Pointer to HW module.
+ *
+ * It is assumed that the initialization is a synchronous operation.
+ * So when we return afer posting the event, the HW SM should be in
+ * the ready state, if there were no errors during init.
+ */
+int
+csio_hw_start(struct csio_hw *hw)
+{
+       spin_lock_irq(&hw->lock);
+       csio_post_event(&hw->sm, CSIO_HWE_CFG);
+       spin_unlock_irq(&hw->lock);
+
+       if (csio_is_hw_ready(hw))
+               return 0;
+       else
+               return -EINVAL;
+}
+
+int
+csio_hw_stop(struct csio_hw *hw)
+{
+       csio_post_event(&hw->sm, CSIO_HWE_PCI_REMOVE);
+
+       if (csio_is_hw_removing(hw))
+               return 0;
+       else
+               return -EINVAL;
+}
+
+/* Max reset retries */
+#define CSIO_MAX_RESET_RETRIES 3
+
+/**
+ * csio_hw_reset - Reset the hardware
+ * @hw:                HW module.
+ *
+ * Caller should hold lock across this function.
+ */
+int
+csio_hw_reset(struct csio_hw *hw)
+{
+       if (!csio_is_hw_master(hw))
+               return -EPERM;
+
+       if (hw->rst_retries >= CSIO_MAX_RESET_RETRIES) {
+               csio_dbg(hw, "Max hw reset attempts reached..");
+               return -EINVAL;
+       }
+
+       hw->rst_retries++;
+       csio_post_event(&hw->sm, CSIO_HWE_HBA_RESET);
+
+       if (csio_is_hw_ready(hw)) {
+               hw->rst_retries = 0;
+               hw->stats.n_reset_start = jiffies_to_msecs(jiffies);
+               return 0;
+       } else
+               return -EINVAL;
+}
+
+/*
+ * csio_hw_get_device_id - Caches the Adapter's vendor & device id.
+ * @hw: HW module.
+ */
+static void
+csio_hw_get_device_id(struct csio_hw *hw)
+{
+       /* Is the adapter device id cached already ?*/
+       if (csio_is_dev_id_cached(hw))
+               return;
+
+       /* Get the PCI vendor & device id */
+       pci_read_config_word(hw->pdev, PCI_VENDOR_ID,
+                            &hw->params.pci.vendor_id);
+       pci_read_config_word(hw->pdev, PCI_DEVICE_ID,
+                            &hw->params.pci.device_id);
+
+       csio_dev_id_cached(hw);
+
+} /* csio_hw_get_device_id */
+
+/*
+ * csio_hw_set_description - Set the model, description of the hw.
+ * @hw: HW module.
+ * @ven_id: PCI Vendor ID
+ * @dev_id: PCI Device ID
+ */
+static void
+csio_hw_set_description(struct csio_hw *hw, uint16_t ven_id, uint16_t dev_id)
+{
+       uint32_t adap_type, prot_type;
+
+       if (ven_id == CSIO_VENDOR_ID) {
+               prot_type = (dev_id & CSIO_ASIC_DEVID_PROTO_MASK);
+               adap_type = (dev_id & CSIO_ASIC_DEVID_TYPE_MASK);
+
+               if (prot_type == CSIO_FPGA) {
+                       memcpy(hw->model_desc,
+                               csio_fcoe_adapters[13].description, 32);
+               } else if (prot_type == CSIO_T4_FCOE_ASIC) {
+                       memcpy(hw->hw_ver,
+                              csio_fcoe_adapters[adap_type].model_no, 16);
+                       memcpy(hw->model_desc,
+                               csio_fcoe_adapters[adap_type].description, 32);
+               } else {
+                       char tempName[32] = "Chelsio FCoE Controller";
+                       memcpy(hw->model_desc, tempName, 32);
+
+                       CSIO_DB_ASSERT(0);
+               }
+       }
+} /* csio_hw_set_description */
+
+/**
+ * csio_hw_init - Initialize HW module.
+ * @hw:                Pointer to HW module.
+ *
+ * Initialize the members of the HW module.
+ */
+int
+csio_hw_init(struct csio_hw *hw)
+{
+       int rv = -EINVAL;
+       uint32_t i;
+       uint16_t ven_id, dev_id;
+       struct csio_evt_msg     *evt_entry;
+
+       INIT_LIST_HEAD(&hw->sm.sm_list);
+       csio_init_state(&hw->sm, csio_hws_uninit);
+       spin_lock_init(&hw->lock);
+       INIT_LIST_HEAD(&hw->sln_head);
+
+       /* Get the PCI vendor & device id */
+       csio_hw_get_device_id(hw);
+
+       strcpy(hw->name, CSIO_HW_NAME);
+
+       /* Set the model & its description */
+
+       ven_id = hw->params.pci.vendor_id;
+       dev_id = hw->params.pci.device_id;
+
+       csio_hw_set_description(hw, ven_id, dev_id);
+
+       /* Initialize default log level */
+       hw->params.log_level = (uint32_t) csio_dbg_level;
+
+       csio_set_fwevt_intr_idx(hw, -1);
+       csio_set_nondata_intr_idx(hw, -1);
+
+       /* Init all the modules: Mailbox, WorkRequest and Transport */
+       if (csio_mbm_init(csio_hw_to_mbm(hw), hw, csio_hw_mb_timer))
+               goto err;
+
+       rv = csio_wrm_init(csio_hw_to_wrm(hw), hw);
+       if (rv)
+               goto err_mbm_exit;
+
+       rv = csio_scsim_init(csio_hw_to_scsim(hw), hw);
+       if (rv)
+               goto err_wrm_exit;
+
+       rv = csio_mgmtm_init(csio_hw_to_mgmtm(hw), hw);
+       if (rv)
+               goto err_scsim_exit;
+       /* Pre-allocate evtq and initialize them */
+       INIT_LIST_HEAD(&hw->evt_active_q);
+       INIT_LIST_HEAD(&hw->evt_free_q);
+       for (i = 0; i < csio_evtq_sz; i++) {
+
+               evt_entry = kzalloc(sizeof(struct csio_evt_msg), GFP_KERNEL);
+               if (!evt_entry) {
+                       csio_err(hw, "Failed to initialize eventq");
+                       goto err_evtq_cleanup;
+               }
+
+               list_add_tail(&evt_entry->list, &hw->evt_free_q);
+               CSIO_INC_STATS(hw, n_evt_freeq);
+       }
+
+       hw->dev_num = dev_num;
+       dev_num++;
+
+       return 0;
+
+err_evtq_cleanup:
+       csio_evtq_cleanup(hw);
+       csio_mgmtm_exit(csio_hw_to_mgmtm(hw));
+err_scsim_exit:
+       csio_scsim_exit(csio_hw_to_scsim(hw));
+err_wrm_exit:
+       csio_wrm_exit(csio_hw_to_wrm(hw), hw);
+err_mbm_exit:
+       csio_mbm_exit(csio_hw_to_mbm(hw));
+err:
+       return rv;
+}
+
+/**
+ * csio_hw_exit - Un-initialize HW module.
+ * @hw:                Pointer to HW module.
+ *
+ */
+void
+csio_hw_exit(struct csio_hw *hw)
+{
+       csio_evtq_cleanup(hw);
+       csio_mgmtm_exit(csio_hw_to_mgmtm(hw));
+       csio_scsim_exit(csio_hw_to_scsim(hw));
+       csio_wrm_exit(csio_hw_to_wrm(hw), hw);
+       csio_mbm_exit(csio_hw_to_mbm(hw));
+}
diff --git a/drivers/scsi/csiostor/csio_hw.h b/drivers/scsi/csiostor/csio_hw.h
new file mode 100644 (file)
index 0000000..9edcca4
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_HW_H__
+#define __CSIO_HW_H__
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/compiler.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/io.h>
+#include <linux/spinlock_types.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_wr.h"
+#include "csio_mb.h"
+#include "csio_scsi.h"
+#include "csio_defs.h"
+#include "t4_regs.h"
+#include "t4_msg.h"
+
+/*
+ * An error value used by host. Should not clash with FW defined return values.
+ */
+#define        FW_HOSTERROR                    255
+
+#define CSIO_FW_FNAME          "cxgb4/t4fw.bin"
+#define CSIO_CF_FNAME          "cxgb4/t4-config.txt"
+
+#define FW_VERSION_MAJOR       1
+#define FW_VERSION_MINOR       2
+#define FW_VERSION_MICRO       8
+
+#define CSIO_HW_NAME           "Chelsio FCoE Adapter"
+#define CSIO_MAX_PFN           8
+#define CSIO_MAX_PPORTS                4
+
+#define CSIO_MAX_LUN           0xFFFF
+#define CSIO_MAX_QUEUE         2048
+#define CSIO_MAX_CMD_PER_LUN   32
+#define CSIO_MAX_DDP_BUF_SIZE  (1024 * 1024)
+#define CSIO_MAX_SECTOR_SIZE   128
+
+/* Interrupts */
+#define CSIO_EXTRA_MSI_IQS     2       /* Extra iqs for INTX/MSI mode
+                                        * (Forward intr iq + fw iq) */
+#define CSIO_EXTRA_VECS                2       /* non-data + FW evt */
+#define CSIO_MAX_SCSI_CPU      128
+#define CSIO_MAX_SCSI_QSETS    (CSIO_MAX_SCSI_CPU * CSIO_MAX_PPORTS)
+#define CSIO_MAX_MSIX_VECS     (CSIO_MAX_SCSI_QSETS + CSIO_EXTRA_VECS)
+
+/* Queues */
+enum {
+       CSIO_INTR_WRSIZE = 128,
+       CSIO_INTR_IQSIZE = ((CSIO_MAX_MSIX_VECS + 1) * CSIO_INTR_WRSIZE),
+       CSIO_FWEVT_WRSIZE = 128,
+       CSIO_FWEVT_IQLEN = 128,
+       CSIO_FWEVT_FLBUFS = 64,
+       CSIO_FWEVT_IQSIZE = (CSIO_FWEVT_WRSIZE * CSIO_FWEVT_IQLEN),
+       CSIO_HW_NIQ = 1,
+       CSIO_HW_NFLQ = 1,
+       CSIO_HW_NEQ = 1,
+       CSIO_HW_NINTXQ = 1,
+};
+
+struct csio_msix_entries {
+       unsigned short  vector;         /* Vector assigned by pci_enable_msix */
+       void            *dev_id;        /* Priv object associated w/ this msix*/
+       char            desc[24];       /* Description of this vector */
+};
+
+struct csio_scsi_qset {
+       int             iq_idx;         /* Ingress index */
+       int             eq_idx;         /* Egress index */
+       uint32_t        intr_idx;       /* MSIX Vector index */
+};
+
+struct csio_scsi_cpu_info {
+       int16_t max_cpus;
+};
+
+extern int csio_dbg_level;
+extern int csio_force_master;
+extern unsigned int csio_port_mask;
+extern int csio_msi;
+
+#define CSIO_VENDOR_ID                         0x1425
+#define CSIO_ASIC_DEVID_PROTO_MASK             0xFF00
+#define CSIO_ASIC_DEVID_TYPE_MASK              0x00FF
+#define CSIO_FPGA                              0xA000
+#define CSIO_T4_FCOE_ASIC                      0x4600
+
+#define CSIO_GLBL_INTR_MASK            (CIM | MPS | PL | PCIE | MC | EDC0 | \
+                                        EDC1 | LE | TP | MA | PM_TX | PM_RX | \
+                                        ULP_RX | CPL_SWITCH | SGE | \
+                                        ULP_TX | SF)
+
+/*
+ * Hard parameters used to initialize the card in the absence of a
+ * configuration file.
+ */
+enum {
+       /* General */
+       CSIO_SGE_DBFIFO_INT_THRESH      = 10,
+
+       CSIO_SGE_RX_DMA_OFFSET          = 2,
+
+       CSIO_SGE_FLBUF_SIZE1            = 65536,
+       CSIO_SGE_FLBUF_SIZE2            = 1536,
+       CSIO_SGE_FLBUF_SIZE3            = 9024,
+       CSIO_SGE_FLBUF_SIZE4            = 9216,
+       CSIO_SGE_FLBUF_SIZE5            = 2048,
+       CSIO_SGE_FLBUF_SIZE6            = 128,
+       CSIO_SGE_FLBUF_SIZE7            = 8192,
+       CSIO_SGE_FLBUF_SIZE8            = 16384,
+
+       CSIO_SGE_TIMER_VAL_0            = 5,
+       CSIO_SGE_TIMER_VAL_1            = 10,
+       CSIO_SGE_TIMER_VAL_2            = 20,
+       CSIO_SGE_TIMER_VAL_3            = 50,
+       CSIO_SGE_TIMER_VAL_4            = 100,
+       CSIO_SGE_TIMER_VAL_5            = 200,
+
+       CSIO_SGE_INT_CNT_VAL_0          = 1,
+       CSIO_SGE_INT_CNT_VAL_1          = 4,
+       CSIO_SGE_INT_CNT_VAL_2          = 8,
+       CSIO_SGE_INT_CNT_VAL_3          = 16,
+
+       /* Storage specific - used by FW_PFVF_CMD */
+       CSIO_WX_CAPS                    = FW_CMD_CAP_PF, /* w/x all */
+       CSIO_R_CAPS                     = FW_CMD_CAP_PF, /* r all */
+       CSIO_NVI                        = 4,
+       CSIO_NIQ_FLINT                  = 34,
+       CSIO_NETH_CTRL                  = 32,
+       CSIO_NEQ                        = 66,
+       CSIO_NEXACTF                    = 32,
+       CSIO_CMASK                      = FW_PFVF_CMD_CMASK_MASK,
+       CSIO_PMASK                      = FW_PFVF_CMD_PMASK_MASK,
+};
+
+/* Slowpath events */
+enum csio_evt {
+       CSIO_EVT_FW  = 0,       /* FW event */
+       CSIO_EVT_MBX,           /* MBX event */
+       CSIO_EVT_SCN,           /* State change notification */
+       CSIO_EVT_DEV_LOSS,      /* Device loss event */
+       CSIO_EVT_MAX,           /* Max supported event */
+};
+
+#define CSIO_EVT_MSG_SIZE      512
+#define CSIO_EVTQ_SIZE         512
+
+/* Event msg  */
+struct csio_evt_msg {
+       struct list_head        list;   /* evt queue*/
+       enum csio_evt           type;
+       uint8_t                 data[CSIO_EVT_MSG_SIZE];
+};
+
+enum {
+       EEPROMVSIZE    = 32768, /* Serial EEPROM virtual address space size */
+       SERNUM_LEN     = 16,    /* Serial # length */
+       EC_LEN         = 16,    /* E/C length */
+       ID_LEN         = 16,    /* ID length */
+       TRACE_LEN      = 112,   /* length of trace data and mask */
+};
+
+enum {
+       SF_PAGE_SIZE = 256,           /* serial flash page size */
+       SF_SEC_SIZE = 64 * 1024,      /* serial flash sector size */
+       SF_SIZE = SF_SEC_SIZE * 16,   /* serial flash size */
+};
+
+enum { MEM_EDC0, MEM_EDC1, MEM_MC };
+
+enum {
+       MEMWIN0_APERTURE = 2048,
+       MEMWIN0_BASE     = 0x1b800,
+       MEMWIN1_APERTURE = 32768,
+       MEMWIN1_BASE     = 0x28000,
+       MEMWIN2_APERTURE = 65536,
+       MEMWIN2_BASE     = 0x30000,
+};
+
+/* serial flash and firmware constants */
+enum {
+       SF_ATTEMPTS = 10,             /* max retries for SF operations */
+
+       /* flash command opcodes */
+       SF_PROG_PAGE    = 2,          /* program page */
+       SF_WR_DISABLE   = 4,          /* disable writes */
+       SF_RD_STATUS    = 5,          /* read status register */
+       SF_WR_ENABLE    = 6,          /* enable writes */
+       SF_RD_DATA_FAST = 0xb,        /* read flash */
+       SF_RD_ID        = 0x9f,       /* read ID */
+       SF_ERASE_SECTOR = 0xd8,       /* erase sector */
+
+       FW_START_SEC = 8,             /* first flash sector for FW */
+       FW_END_SEC = 15,              /* last flash sector for FW */
+       FW_IMG_START = FW_START_SEC * SF_SEC_SIZE,
+       FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE,
+
+       FLASH_CFG_MAX_SIZE    = 0x10000 , /* max size of the flash config file*/
+       FLASH_CFG_OFFSET      = 0x1f0000,
+       FLASH_CFG_START_SEC   = FLASH_CFG_OFFSET / SF_SEC_SIZE,
+       FPGA_FLASH_CFG_OFFSET = 0xf0000 , /* if FPGA mode, then cfg file is
+                                          * at 1MB - 64KB */
+       FPGA_FLASH_CFG_START_SEC  = FPGA_FLASH_CFG_OFFSET / SF_SEC_SIZE,
+};
+
+/*
+ * Flash layout.
+ */
+#define FLASH_START(start)     ((start) * SF_SEC_SIZE)
+#define FLASH_MAX_SIZE(nsecs)  ((nsecs) * SF_SEC_SIZE)
+
+enum {
+       /*
+        * Location of firmware image in FLASH.
+        */
+       FLASH_FW_START_SEC = 8,
+       FLASH_FW_NSECS = 8,
+       FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
+       FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
+
+};
+
+#undef FLASH_START
+#undef FLASH_MAX_SIZE
+
+/* Management module */
+enum {
+       CSIO_MGMT_EQ_WRSIZE = 512,
+       CSIO_MGMT_IQ_WRSIZE = 128,
+       CSIO_MGMT_EQLEN = 64,
+       CSIO_MGMT_IQLEN = 64,
+};
+
+#define CSIO_MGMT_EQSIZE       (CSIO_MGMT_EQLEN * CSIO_MGMT_EQ_WRSIZE)
+#define CSIO_MGMT_IQSIZE       (CSIO_MGMT_IQLEN * CSIO_MGMT_IQ_WRSIZE)
+
+/* mgmt module stats */
+struct csio_mgmtm_stats {
+       uint32_t        n_abort_req;            /* Total abort request */
+       uint32_t        n_abort_rsp;            /* Total abort response */
+       uint32_t        n_close_req;            /* Total close request */
+       uint32_t        n_close_rsp;            /* Total close response */
+       uint32_t        n_err;                  /* Total Errors */
+       uint32_t        n_drop;                 /* Total request dropped */
+       uint32_t        n_active;               /* Count of active_q */
+       uint32_t        n_cbfn;                 /* Count of cbfn_q */
+};
+
+/* MGMT module */
+struct csio_mgmtm {
+       struct  csio_hw         *hw;            /* Pointer to HW moduel */
+       int                     eq_idx;         /* Egress queue index */
+       int                     iq_idx;         /* Ingress queue index */
+       int                     msi_vec;        /* MSI vector */
+       struct list_head        active_q;       /* Outstanding ELS/CT */
+       struct list_head        abort_q;        /* Outstanding abort req */
+       struct list_head        cbfn_q;         /* Completion queue */
+       struct list_head        mgmt_req_freelist; /* Free poll of reqs */
+                                               /* ELSCT request freelist*/
+       struct timer_list       mgmt_timer;     /* MGMT timer */
+       struct csio_mgmtm_stats stats;          /* ELS/CT stats */
+};
+
+struct csio_adap_desc {
+       char model_no[16];
+       char description[32];
+};
+
+struct pci_params {
+       uint16_t   vendor_id;
+       uint16_t   device_id;
+       uint32_t   vpd_cap_addr;
+       uint16_t   speed;
+       uint8_t    width;
+};
+
+/* User configurable hw parameters */
+struct csio_hw_params {
+       uint32_t                sf_size;                /* serial flash
+                                                        * size in bytes
+                                                        */
+       uint32_t                sf_nsec;                /* # of flash sectors */
+       struct pci_params       pci;
+       uint32_t                log_level;              /* Module-level for
+                                                        * debug log.
+                                                        */
+};
+
+struct csio_vpd {
+       uint32_t cclk;
+       uint8_t ec[EC_LEN + 1];
+       uint8_t sn[SERNUM_LEN + 1];
+       uint8_t id[ID_LEN + 1];
+};
+
+struct csio_pport {
+       uint16_t        pcap;
+       uint8_t         portid;
+       uint8_t         link_status;
+       uint16_t        link_speed;
+       uint8_t         mac[6];
+       uint8_t         mod_type;
+       uint8_t         rsvd1;
+       uint8_t         rsvd2;
+       uint8_t         rsvd3;
+};
+
+/* fcoe resource information */
+struct csio_fcoe_res_info {
+       uint16_t        e_d_tov;
+       uint16_t        r_a_tov_seq;
+       uint16_t        r_a_tov_els;
+       uint16_t        r_r_tov;
+       uint32_t        max_xchgs;
+       uint32_t        max_ssns;
+       uint32_t        used_xchgs;
+       uint32_t        used_ssns;
+       uint32_t        max_fcfs;
+       uint32_t        max_vnps;
+       uint32_t        used_fcfs;
+       uint32_t        used_vnps;
+};
+
+/* HW State machine Events */
+enum csio_hw_ev {
+       CSIO_HWE_CFG = (uint32_t)1, /* Starts off the State machine */
+       CSIO_HWE_INIT,           /* Config done, start Init      */
+       CSIO_HWE_INIT_DONE,      /* Init Mailboxes sent, HW ready */
+       CSIO_HWE_FATAL,          /* Fatal error during initialization */
+       CSIO_HWE_PCIERR_DETECTED,/* PCI error recovery detetced */
+       CSIO_HWE_PCIERR_SLOT_RESET, /* Slot reset after PCI recoviery */
+       CSIO_HWE_PCIERR_RESUME,  /* Resume after PCI error recovery */
+       CSIO_HWE_QUIESCED,       /* HBA quiesced */
+       CSIO_HWE_HBA_RESET,      /* HBA reset requested */
+       CSIO_HWE_HBA_RESET_DONE, /* HBA reset completed */
+       CSIO_HWE_FW_DLOAD,       /* FW download requested */
+       CSIO_HWE_PCI_REMOVE,     /* PCI de-instantiation */
+       CSIO_HWE_SUSPEND,        /* HW suspend for Online(hot) replacement */
+       CSIO_HWE_RESUME,         /* HW resume for Online(hot) replacement */
+       CSIO_HWE_MAX,            /* Max HW event */
+};
+
+/* hw stats */
+struct csio_hw_stats {
+       uint32_t        n_evt_activeq;  /* Number of event in active Q */
+       uint32_t        n_evt_freeq;    /* Number of event in free Q */
+       uint32_t        n_evt_drop;     /* Number of event droped */
+       uint32_t        n_evt_unexp;    /* Number of unexpected events */
+       uint32_t        n_pcich_offline;/* Number of pci channel offline */
+       uint32_t        n_lnlkup_miss;  /* Number of lnode lookup miss */
+       uint32_t        n_cpl_fw6_msg;  /* Number of cpl fw6 message*/
+       uint32_t        n_cpl_fw6_pld;  /* Number of cpl fw6 payload*/
+       uint32_t        n_cpl_unexp;    /* Number of unexpected cpl */
+       uint32_t        n_mbint_unexp;  /* Number of unexpected mbox */
+                                       /* interrupt */
+       uint32_t        n_plint_unexp;  /* Number of unexpected PL */
+                                       /* interrupt */
+       uint32_t        n_plint_cnt;    /* Number of PL interrupt */
+       uint32_t        n_int_stray;    /* Number of stray interrupt */
+       uint32_t        n_err;          /* Number of hw errors */
+       uint32_t        n_err_fatal;    /* Number of fatal errors */
+       uint32_t        n_err_nomem;    /* Number of memory alloc failure */
+       uint32_t        n_err_io;       /* Number of IO failure */
+       enum csio_hw_ev n_evt_sm[CSIO_HWE_MAX]; /* Number of sm events */
+       uint64_t        n_reset_start;  /* Start time after the reset */
+       uint32_t        rsvd1;
+};
+
+/* Defines for hw->flags */
+#define CSIO_HWF_MASTER                        0x00000001      /* This is the Master
+                                                        * function for the
+                                                        * card.
+                                                        */
+#define        CSIO_HWF_HW_INTR_ENABLED        0x00000002      /* Are HW Interrupt
+                                                        * enable bit set?
+                                                        */
+#define        CSIO_HWF_FWEVT_PENDING          0x00000004      /* FW events pending */
+#define        CSIO_HWF_Q_MEM_ALLOCED          0x00000008      /* Queues have been
+                                                        * allocated memory.
+                                                        */
+#define        CSIO_HWF_Q_FW_ALLOCED           0x00000010      /* Queues have been
+                                                        * allocated in FW.
+                                                        */
+#define CSIO_HWF_VPD_VALID             0x00000020      /* Valid VPD copied */
+#define CSIO_HWF_DEVID_CACHED          0X00000040      /* PCI vendor & device
+                                                        * id cached */
+#define        CSIO_HWF_FWEVT_STOP             0x00000080      /* Stop processing
+                                                        * FW events
+                                                        */
+#define CSIO_HWF_USING_SOFT_PARAMS     0x00000100      /* Using FW config
+                                                        * params
+                                                        */
+#define        CSIO_HWF_HOST_INTR_ENABLED      0x00000200      /* Are host interrupts
+                                                        * enabled?
+                                                        */
+
+#define csio_is_hw_intr_enabled(__hw)  \
+                               ((__hw)->flags & CSIO_HWF_HW_INTR_ENABLED)
+#define csio_is_host_intr_enabled(__hw)        \
+                               ((__hw)->flags & CSIO_HWF_HOST_INTR_ENABLED)
+#define csio_is_hw_master(__hw)                ((__hw)->flags & CSIO_HWF_MASTER)
+#define csio_is_valid_vpd(__hw)                ((__hw)->flags & CSIO_HWF_VPD_VALID)
+#define csio_is_dev_id_cached(__hw)    ((__hw)->flags & CSIO_HWF_DEVID_CACHED)
+#define csio_valid_vpd_copied(__hw)    ((__hw)->flags |= CSIO_HWF_VPD_VALID)
+#define csio_dev_id_cached(__hw)       ((__hw)->flags |= CSIO_HWF_DEVID_CACHED)
+
+/* Defines for intr_mode */
+enum csio_intr_mode {
+       CSIO_IM_NONE = 0,
+       CSIO_IM_INTX = 1,
+       CSIO_IM_MSI  = 2,
+       CSIO_IM_MSIX = 3,
+};
+
+/* Master HW structure: One per function */
+struct csio_hw {
+       struct csio_sm          sm;                     /* State machine: should
+                                                        * be the 1st member.
+                                                        */
+       spinlock_t              lock;                   /* Lock for hw */
+
+       struct csio_scsim       scsim;                  /* SCSI module*/
+       struct csio_wrm         wrm;                    /* Work request module*/
+       struct pci_dev          *pdev;                  /* PCI device */
+
+       void __iomem            *regstart;              /* Virtual address of
+                                                        * register map
+                                                        */
+       /* SCSI queue sets */
+       uint32_t                num_sqsets;             /* Number of SCSI
+                                                        * queue sets */
+       uint32_t                num_scsi_msix_cpus;     /* Number of CPUs that
+                                                        * will be used
+                                                        * for ingress
+                                                        * processing.
+                                                        */
+
+       struct csio_scsi_qset   sqset[CSIO_MAX_PPORTS][CSIO_MAX_SCSI_CPU];
+       struct csio_scsi_cpu_info scsi_cpu_info[CSIO_MAX_PPORTS];
+
+       uint32_t                evtflag;                /* Event flag  */
+       uint32_t                flags;                  /* HW flags */
+
+       struct csio_mgmtm       mgmtm;                  /* management module */
+       struct csio_mbm         mbm;                    /* Mailbox module */
+
+       /* Lnodes */
+       uint32_t                num_lns;                /* Number of lnodes */
+       struct csio_lnode       *rln;                   /* Root lnode */
+       struct list_head        sln_head;               /* Sibling node list
+                                                        * list
+                                                        */
+       int                     intr_iq_idx;            /* Forward interrupt
+                                                        * queue.
+                                                        */
+       int                     fwevt_iq_idx;           /* FW evt queue */
+       struct work_struct      evtq_work;              /* Worker thread for
+                                                        * HW events.
+                                                        */
+       struct list_head        evt_free_q;             /* freelist of evt
+                                                        * elements
+                                                        */
+       struct list_head        evt_active_q;           /* active evt queue*/
+
+       /* board related info */
+       char                    name[32];
+       char                    hw_ver[16];
+       char                    model_desc[32];
+       char                    drv_version[32];
+       char                    fwrev_str[32];
+       uint32_t                optrom_ver;
+       uint32_t                fwrev;
+       uint32_t                tp_vers;
+       char                    chip_ver;
+       uint32_t                cfg_finiver;
+       uint32_t                cfg_finicsum;
+       uint32_t                cfg_cfcsum;
+       uint8_t                 cfg_csum_status;
+       uint8_t                 cfg_store;
+       enum csio_dev_state     fw_state;
+       struct csio_vpd         vpd;
+
+       uint8_t                 pfn;                    /* Physical Function
+                                                        * number
+                                                        */
+       uint32_t                port_vec;               /* Port vector */
+       uint8_t                 num_pports;             /* Number of physical
+                                                        * ports.
+                                                        */
+       uint8_t                 rst_retries;            /* Reset retries */
+       uint8_t                 cur_evt;                /* current s/m evt */
+       uint8_t                 prev_evt;               /* Previous s/m evt */
+       uint32_t                dev_num;                /* device number */
+       struct csio_pport       pport[CSIO_MAX_PPORTS]; /* Ports (XGMACs) */
+       struct csio_hw_params   params;                 /* Hw parameters */
+
+       struct pci_pool         *scsi_pci_pool;         /* PCI pool for SCSI */
+       mempool_t               *mb_mempool;            /* Mailbox memory pool*/
+       mempool_t               *rnode_mempool;         /* rnode memory pool */
+
+       /* Interrupt */
+       enum csio_intr_mode     intr_mode;              /* INTx, MSI, MSIX */
+       uint32_t                fwevt_intr_idx;         /* FW evt MSIX/interrupt
+                                                        * index
+                                                        */
+       uint32_t                nondata_intr_idx;       /* nondata MSIX/intr
+                                                        * idx
+                                                        */
+
+       uint8_t                 cfg_neq;                /* FW configured no of
+                                                        * egress queues
+                                                        */
+       uint8_t                 cfg_niq;                /* FW configured no of
+                                                        * iq queues.
+                                                        */
+
+       struct csio_fcoe_res_info  fres_info;           /* Fcoe resource info */
+
+       /* MSIX vectors */
+       struct csio_msix_entries msix_entries[CSIO_MAX_MSIX_VECS];
+
+       struct dentry           *debugfs_root;          /* Debug FS */
+       struct csio_hw_stats    stats;                  /* Hw statistics */
+};
+
+/* Register access macros */
+#define csio_reg(_b, _r)               ((_b) + (_r))
+
+#define        csio_rd_reg8(_h, _r)            readb(csio_reg((_h)->regstart, (_r)))
+#define        csio_rd_reg16(_h, _r)           readw(csio_reg((_h)->regstart, (_r)))
+#define        csio_rd_reg32(_h, _r)           readl(csio_reg((_h)->regstart, (_r)))
+#define        csio_rd_reg64(_h, _r)           readq(csio_reg((_h)->regstart, (_r)))
+
+#define        csio_wr_reg8(_h, _v, _r)        writeb((_v), \
+                                               csio_reg((_h)->regstart, (_r)))
+#define        csio_wr_reg16(_h, _v, _r)       writew((_v), \
+                                               csio_reg((_h)->regstart, (_r)))
+#define        csio_wr_reg32(_h, _v, _r)       writel((_v), \
+                                               csio_reg((_h)->regstart, (_r)))
+#define        csio_wr_reg64(_h, _v, _r)       writeq((_v), \
+                                               csio_reg((_h)->regstart, (_r)))
+
+void csio_set_reg_field(struct csio_hw *, uint32_t, uint32_t, uint32_t);
+
+/* Core clocks <==> uSecs */
+static inline uint32_t
+csio_core_ticks_to_us(struct csio_hw *hw, uint32_t ticks)
+{
+       /* add Core Clock / 2 to round ticks to nearest uS */
+       return (ticks * 1000 + hw->vpd.cclk/2) / hw->vpd.cclk;
+}
+
+static inline uint32_t
+csio_us_to_core_ticks(struct csio_hw *hw, uint32_t us)
+{
+       return (us * hw->vpd.cclk) / 1000;
+}
+
+/* Easy access macros */
+#define csio_hw_to_wrm(hw)             ((struct csio_wrm *)(&(hw)->wrm))
+#define csio_hw_to_mbm(hw)             ((struct csio_mbm *)(&(hw)->mbm))
+#define csio_hw_to_scsim(hw)           ((struct csio_scsim *)(&(hw)->scsim))
+#define csio_hw_to_mgmtm(hw)           ((struct csio_mgmtm *)(&(hw)->mgmtm))
+
+#define CSIO_PCI_BUS(hw)               ((hw)->pdev->bus->number)
+#define CSIO_PCI_DEV(hw)               (PCI_SLOT((hw)->pdev->devfn))
+#define CSIO_PCI_FUNC(hw)              (PCI_FUNC((hw)->pdev->devfn))
+
+#define csio_set_fwevt_intr_idx(_h, _i)                ((_h)->fwevt_intr_idx = (_i))
+#define csio_get_fwevt_intr_idx(_h)            ((_h)->fwevt_intr_idx)
+#define csio_set_nondata_intr_idx(_h, _i)      ((_h)->nondata_intr_idx = (_i))
+#define csio_get_nondata_intr_idx(_h)          ((_h)->nondata_intr_idx)
+
+/* Printing/logging */
+#define CSIO_DEVID(__dev)              ((__dev)->dev_num)
+#define CSIO_DEVID_LO(__dev)           (CSIO_DEVID((__dev)) & 0xFFFF)
+#define CSIO_DEVID_HI(__dev)           ((CSIO_DEVID((__dev)) >> 16) & 0xFFFF)
+
+#define csio_info(__hw, __fmt, ...)                                    \
+                       dev_info(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_fatal(__hw, __fmt, ...)                                   \
+                       dev_crit(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_err(__hw, __fmt, ...)                                     \
+                       dev_err(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_warn(__hw, __fmt, ...)                                    \
+                       dev_warn(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#ifdef __CSIO_DEBUG__
+#define csio_dbg(__hw, __fmt, ...)                                     \
+                       csio_info((__hw), __fmt, ##__VA_ARGS__);
+#else
+#define csio_dbg(__hw, __fmt, ...)
+#endif
+
+int csio_mgmt_req_lookup(struct csio_mgmtm *, struct csio_ioreq *);
+void csio_hw_intr_disable(struct csio_hw *);
+int csio_hw_slow_intr_handler(struct csio_hw *hw);
+int csio_hw_start(struct csio_hw *);
+int csio_hw_stop(struct csio_hw *);
+int csio_hw_reset(struct csio_hw *);
+int csio_is_hw_ready(struct csio_hw *);
+int csio_is_hw_removing(struct csio_hw *);
+
+int csio_fwevtq_handler(struct csio_hw *);
+void csio_evtq_worker(struct work_struct *);
+int csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type,
+                               void *evt_msg, uint16_t len);
+void csio_evtq_flush(struct csio_hw *hw);
+
+int csio_request_irqs(struct csio_hw *);
+void csio_intr_enable(struct csio_hw *);
+void csio_intr_disable(struct csio_hw *, bool);
+
+struct csio_lnode *csio_lnode_alloc(struct csio_hw *);
+int csio_config_queues(struct csio_hw *);
+
+int csio_hw_mc_read(struct csio_hw *, uint32_t, __be32 *, uint64_t *);
+int csio_hw_edc_read(struct csio_hw *, int, uint32_t, __be32 *, uint64_t *);
+int csio_hw_init(struct csio_hw *);
+void csio_hw_exit(struct csio_hw *);
+#endif /* ifndef __CSIO_HW_H__ */
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
new file mode 100644 (file)
index 0000000..fdd408f
--- /dev/null
@@ -0,0 +1,1274 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/kdebug.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/string.h>
+#include <linux/export.h>
+
+#include "csio_init.h"
+#include "csio_defs.h"
+
+#define CSIO_MIN_MEMPOOL_SZ    64
+
+static struct dentry *csio_debugfs_root;
+
+static struct scsi_transport_template *csio_fcoe_transport;
+static struct scsi_transport_template *csio_fcoe_transport_vport;
+
+/*
+ * debugfs support
+ */
+static int
+csio_mem_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t
+csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+       loff_t pos = *ppos;
+       loff_t avail = file->f_path.dentry->d_inode->i_size;
+       unsigned int mem = (uintptr_t)file->private_data & 3;
+       struct csio_hw *hw = file->private_data - mem;
+
+       if (pos < 0)
+               return -EINVAL;
+       if (pos >= avail)
+               return 0;
+       if (count > avail - pos)
+               count = avail - pos;
+
+       while (count) {
+               size_t len;
+               int ret, ofst;
+               __be32 data[16];
+
+               if (mem == MEM_MC)
+                       ret = csio_hw_mc_read(hw, pos, data, NULL);
+               else
+                       ret = csio_hw_edc_read(hw, mem, pos, data, NULL);
+               if (ret)
+                       return ret;
+
+               ofst = pos % sizeof(data);
+               len = min(count, sizeof(data) - ofst);
+               if (copy_to_user(buf, (u8 *)data + ofst, len))
+                       return -EFAULT;
+
+               buf += len;
+               pos += len;
+               count -= len;
+       }
+       count = pos - *ppos;
+       *ppos = pos;
+       return count;
+}
+
+static const struct file_operations csio_mem_debugfs_fops = {
+       .owner   = THIS_MODULE,
+       .open    = csio_mem_open,
+       .read    = csio_mem_read,
+       .llseek  = default_llseek,
+};
+
+static void __devinit
+csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
+                    unsigned int idx, unsigned int size_mb)
+{
+       struct dentry *de;
+
+       de = debugfs_create_file(name, S_IRUSR, hw->debugfs_root,
+                                (void *)hw + idx, &csio_mem_debugfs_fops);
+       if (de && de->d_inode)
+               de->d_inode->i_size = size_mb << 20;
+}
+
+static int __devinit
+csio_setup_debugfs(struct csio_hw *hw)
+{
+       int i;
+
+       if (IS_ERR_OR_NULL(hw->debugfs_root))
+               return -1;
+
+       i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
+       if (i & EDRAM0_ENABLE)
+               csio_add_debugfs_mem(hw, "edc0", MEM_EDC0, 5);
+       if (i & EDRAM1_ENABLE)
+               csio_add_debugfs_mem(hw, "edc1", MEM_EDC1, 5);
+       if (i & EXT_MEM_ENABLE)
+               csio_add_debugfs_mem(hw, "mc", MEM_MC,
+                     EXT_MEM_SIZE_GET(csio_rd_reg32(hw, MA_EXT_MEMORY_BAR)));
+       return 0;
+}
+
+/*
+ * csio_dfs_create - Creates and sets up per-hw debugfs.
+ *
+ */
+static int
+csio_dfs_create(struct csio_hw *hw)
+{
+       if (csio_debugfs_root) {
+               hw->debugfs_root = debugfs_create_dir(pci_name(hw->pdev),
+                                                       csio_debugfs_root);
+               csio_setup_debugfs(hw);
+       }
+
+       return 0;
+}
+
+/*
+ * csio_dfs_destroy - Destroys per-hw debugfs.
+ */
+static int
+csio_dfs_destroy(struct csio_hw *hw)
+{
+       if (hw->debugfs_root)
+               debugfs_remove_recursive(hw->debugfs_root);
+
+       return 0;
+}
+
+/*
+ * csio_dfs_init - Debug filesystem initialization for the module.
+ *
+ */
+static int
+csio_dfs_init(void)
+{
+       csio_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+       if (!csio_debugfs_root)
+               pr_warn("Could not create debugfs entry, continuing\n");
+
+       return 0;
+}
+
+/*
+ * csio_dfs_exit - debugfs cleanup for the module.
+ */
+static void
+csio_dfs_exit(void)
+{
+       debugfs_remove(csio_debugfs_root);
+}
+
+/*
+ * csio_pci_init - PCI initialization.
+ * @pdev: PCI device.
+ * @bars: Bitmask of bars to be requested.
+ *
+ * Initializes the PCI function by enabling MMIO, setting bus
+ * mastership and setting DMA mask.
+ */
+static int
+csio_pci_init(struct pci_dev *pdev, int *bars)
+{
+       int rv = -ENODEV;
+
+       *bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+       if (pci_enable_device_mem(pdev))
+               goto err;
+
+       if (pci_request_selected_regions(pdev, *bars, KBUILD_MODNAME))
+               goto err_disable_device;
+
+       pci_set_master(pdev);
+       pci_try_set_mwi(pdev);
+
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       } else {
+               dev_err(&pdev->dev, "No suitable DMA available.\n");
+               goto err_release_regions;
+       }
+
+       return 0;
+
+err_release_regions:
+       pci_release_selected_regions(pdev, *bars);
+err_disable_device:
+       pci_disable_device(pdev);
+err:
+       return rv;
+
+}
+
+/*
+ * csio_pci_exit - PCI unitialization.
+ * @pdev: PCI device.
+ * @bars: Bars to be released.
+ *
+ */
+static void
+csio_pci_exit(struct pci_dev *pdev, int *bars)
+{
+       pci_release_selected_regions(pdev, *bars);
+       pci_disable_device(pdev);
+}
+
+/*
+ * csio_hw_init_workers - Initialize the HW module's worker threads.
+ * @hw: HW module.
+ *
+ */
+static void
+csio_hw_init_workers(struct csio_hw *hw)
+{
+       INIT_WORK(&hw->evtq_work, csio_evtq_worker);
+}
+
+static void
+csio_hw_exit_workers(struct csio_hw *hw)
+{
+       cancel_work_sync(&hw->evtq_work);
+       flush_scheduled_work();
+}
+
+static int
+csio_create_queues(struct csio_hw *hw)
+{
+       int i, j;
+       struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+       int rv;
+       struct csio_scsi_cpu_info *info;
+
+       if (hw->flags & CSIO_HWF_Q_FW_ALLOCED)
+               return 0;
+
+       if (hw->intr_mode != CSIO_IM_MSIX) {
+               rv = csio_wr_iq_create(hw, NULL, hw->intr_iq_idx,
+                                       0, hw->pport[0].portid, false, NULL);
+               if (rv != 0) {
+                       csio_err(hw, " Forward Interrupt IQ failed!: %d\n", rv);
+                       return rv;
+               }
+       }
+
+       /* FW event queue */
+       rv = csio_wr_iq_create(hw, NULL, hw->fwevt_iq_idx,
+                              csio_get_fwevt_intr_idx(hw),
+                              hw->pport[0].portid, true, NULL);
+       if (rv != 0) {
+               csio_err(hw, "FW event IQ config failed!: %d\n", rv);
+               return rv;
+       }
+
+       /* Create mgmt queue */
+       rv = csio_wr_eq_create(hw, NULL, mgmtm->eq_idx,
+                       mgmtm->iq_idx, hw->pport[0].portid, NULL);
+
+       if (rv != 0) {
+               csio_err(hw, "Mgmt EQ create failed!: %d\n", rv);
+               goto err;
+       }
+
+       /* Create SCSI queues */
+       for (i = 0; i < hw->num_pports; i++) {
+               info = &hw->scsi_cpu_info[i];
+
+               for (j = 0; j < info->max_cpus; j++) {
+                       struct csio_scsi_qset *sqset = &hw->sqset[i][j];
+
+                       rv = csio_wr_iq_create(hw, NULL, sqset->iq_idx,
+                                              sqset->intr_idx, i, false, NULL);
+                       if (rv != 0) {
+                               csio_err(hw,
+                                  "SCSI module IQ config failed [%d][%d]:%d\n",
+                                  i, j, rv);
+                               goto err;
+                       }
+                       rv = csio_wr_eq_create(hw, NULL, sqset->eq_idx,
+                                              sqset->iq_idx, i, NULL);
+                       if (rv != 0) {
+                               csio_err(hw,
+                                  "SCSI module EQ config failed [%d][%d]:%d\n",
+                                  i, j, rv);
+                               goto err;
+                       }
+               } /* for all CPUs */
+       } /* For all ports */
+
+       hw->flags |= CSIO_HWF_Q_FW_ALLOCED;
+       return 0;
+err:
+       csio_wr_destroy_queues(hw, true);
+       return -EINVAL;
+}
+
+/*
+ * csio_config_queues - Configure the DMA queues.
+ * @hw: HW module.
+ *
+ * Allocates memory for queues are registers them with FW.
+ */
+int
+csio_config_queues(struct csio_hw *hw)
+{
+       int i, j, idx, k = 0;
+       int rv;
+       struct csio_scsi_qset *sqset;
+       struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+       struct csio_scsi_qset *orig;
+       struct csio_scsi_cpu_info *info;
+
+       if (hw->flags & CSIO_HWF_Q_MEM_ALLOCED)
+               return csio_create_queues(hw);
+
+       /* Calculate number of SCSI queues for MSIX we would like */
+       hw->num_scsi_msix_cpus = num_online_cpus();
+       hw->num_sqsets = num_online_cpus() * hw->num_pports;
+
+       if (hw->num_sqsets > CSIO_MAX_SCSI_QSETS) {
+               hw->num_sqsets = CSIO_MAX_SCSI_QSETS;
+               hw->num_scsi_msix_cpus = CSIO_MAX_SCSI_CPU;
+       }
+
+       /* Initialize max_cpus, may get reduced during msix allocations */
+       for (i = 0; i < hw->num_pports; i++)
+               hw->scsi_cpu_info[i].max_cpus = hw->num_scsi_msix_cpus;
+
+       csio_dbg(hw, "nsqsets:%d scpus:%d\n",
+                   hw->num_sqsets, hw->num_scsi_msix_cpus);
+
+       csio_intr_enable(hw);
+
+       if (hw->intr_mode != CSIO_IM_MSIX) {
+
+               /* Allocate Forward interrupt iq. */
+               hw->intr_iq_idx = csio_wr_alloc_q(hw, CSIO_INTR_IQSIZE,
+                                               CSIO_INTR_WRSIZE, CSIO_INGRESS,
+                                               (void *)hw, 0, 0, NULL);
+               if (hw->intr_iq_idx == -1) {
+                       csio_err(hw,
+                                "Forward interrupt queue creation failed\n");
+                       goto intr_disable;
+               }
+       }
+
+       /* Allocate the FW evt queue */
+       hw->fwevt_iq_idx = csio_wr_alloc_q(hw, CSIO_FWEVT_IQSIZE,
+                                          CSIO_FWEVT_WRSIZE,
+                                          CSIO_INGRESS, (void *)hw,
+                                          CSIO_FWEVT_FLBUFS, 0,
+                                          csio_fwevt_intx_handler);
+       if (hw->fwevt_iq_idx == -1) {
+               csio_err(hw, "FW evt queue creation failed\n");
+               goto intr_disable;
+       }
+
+       /* Allocate the mgmt queue */
+       mgmtm->eq_idx = csio_wr_alloc_q(hw, CSIO_MGMT_EQSIZE,
+                                     CSIO_MGMT_EQ_WRSIZE,
+                                     CSIO_EGRESS, (void *)hw, 0, 0, NULL);
+       if (mgmtm->eq_idx == -1) {
+               csio_err(hw, "Failed to alloc egress queue for mgmt module\n");
+               goto intr_disable;
+       }
+
+       /* Use FW IQ for MGMT req completion */
+       mgmtm->iq_idx = hw->fwevt_iq_idx;
+
+       /* Allocate SCSI queues */
+       for (i = 0; i < hw->num_pports; i++) {
+               info = &hw->scsi_cpu_info[i];
+
+               for (j = 0; j < hw->num_scsi_msix_cpus; j++) {
+                       sqset = &hw->sqset[i][j];
+
+                       if (j >= info->max_cpus) {
+                               k = j % info->max_cpus;
+                               orig = &hw->sqset[i][k];
+                               sqset->eq_idx = orig->eq_idx;
+                               sqset->iq_idx = orig->iq_idx;
+                               continue;
+                       }
+
+                       idx = csio_wr_alloc_q(hw, csio_scsi_eqsize, 0,
+                                             CSIO_EGRESS, (void *)hw, 0, 0,
+                                             NULL);
+                       if (idx == -1) {
+                               csio_err(hw, "EQ creation failed for idx:%d\n",
+                                           idx);
+                               goto intr_disable;
+                       }
+
+                       sqset->eq_idx = idx;
+
+                       idx = csio_wr_alloc_q(hw, CSIO_SCSI_IQSIZE,
+                                            CSIO_SCSI_IQ_WRSZ, CSIO_INGRESS,
+                                            (void *)hw, 0, 0,
+                                            csio_scsi_intx_handler);
+                       if (idx == -1) {
+                               csio_err(hw, "IQ creation failed for idx:%d\n",
+                                           idx);
+                               goto intr_disable;
+                       }
+                       sqset->iq_idx = idx;
+               } /* for all CPUs */
+       } /* For all ports */
+
+       hw->flags |= CSIO_HWF_Q_MEM_ALLOCED;
+
+       rv = csio_create_queues(hw);
+       if (rv != 0)
+               goto intr_disable;
+
+       /*
+        * Now request IRQs for the vectors. In the event of a failure,
+        * cleanup is handled internally by this function.
+        */
+       rv = csio_request_irqs(hw);
+       if (rv != 0)
+               return -EINVAL;
+
+       return 0;
+
+intr_disable:
+       csio_intr_disable(hw, false);
+
+       return -EINVAL;
+}
+
+static int
+csio_resource_alloc(struct csio_hw *hw)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       int rv = -ENOMEM;
+
+       wrm->num_q = ((CSIO_MAX_SCSI_QSETS * 2) + CSIO_HW_NIQ +
+                      CSIO_HW_NEQ + CSIO_HW_NFLQ + CSIO_HW_NINTXQ);
+
+       hw->mb_mempool = mempool_create_kmalloc_pool(CSIO_MIN_MEMPOOL_SZ,
+                                                 sizeof(struct csio_mb));
+       if (!hw->mb_mempool)
+               goto err;
+
+       hw->rnode_mempool = mempool_create_kmalloc_pool(CSIO_MIN_MEMPOOL_SZ,
+                                                    sizeof(struct csio_rnode));
+       if (!hw->rnode_mempool)
+               goto err_free_mb_mempool;
+
+       hw->scsi_pci_pool = pci_pool_create("csio_scsi_pci_pool", hw->pdev,
+                                           CSIO_SCSI_RSP_LEN, 8, 0);
+       if (!hw->scsi_pci_pool)
+               goto err_free_rn_pool;
+
+       return 0;
+
+err_free_rn_pool:
+       mempool_destroy(hw->rnode_mempool);
+       hw->rnode_mempool = NULL;
+err_free_mb_mempool:
+       mempool_destroy(hw->mb_mempool);
+       hw->mb_mempool = NULL;
+err:
+       return rv;
+}
+
+static void
+csio_resource_free(struct csio_hw *hw)
+{
+       pci_pool_destroy(hw->scsi_pci_pool);
+       hw->scsi_pci_pool = NULL;
+       mempool_destroy(hw->rnode_mempool);
+       hw->rnode_mempool = NULL;
+       mempool_destroy(hw->mb_mempool);
+       hw->mb_mempool = NULL;
+}
+
+/*
+ * csio_hw_alloc - Allocate and initialize the HW module.
+ * @pdev: PCI device.
+ *
+ * Allocates HW structure, DMA, memory resources, maps BARS to
+ * host memory and initializes HW module.
+ */
+static struct csio_hw * __devinit
+csio_hw_alloc(struct pci_dev *pdev)
+{
+       struct csio_hw *hw;
+
+       hw = kzalloc(sizeof(struct csio_hw), GFP_KERNEL);
+       if (!hw)
+               goto err;
+
+       hw->pdev = pdev;
+       strncpy(hw->drv_version, CSIO_DRV_VERSION, 32);
+
+       /* memory pool/DMA pool allocation */
+       if (csio_resource_alloc(hw))
+               goto err_free_hw;
+
+       /* Get the start address of registers from BAR 0 */
+       hw->regstart = ioremap_nocache(pci_resource_start(pdev, 0),
+                                      pci_resource_len(pdev, 0));
+       if (!hw->regstart) {
+               csio_err(hw, "Could not map BAR 0, regstart = %p\n",
+                        hw->regstart);
+               goto err_resource_free;
+       }
+
+       csio_hw_init_workers(hw);
+
+       if (csio_hw_init(hw))
+               goto err_unmap_bar;
+
+       csio_dfs_create(hw);
+
+       csio_dbg(hw, "hw:%p\n", hw);
+
+       return hw;
+
+err_unmap_bar:
+       csio_hw_exit_workers(hw);
+       iounmap(hw->regstart);
+err_resource_free:
+       csio_resource_free(hw);
+err_free_hw:
+       kfree(hw);
+err:
+       return NULL;
+}
+
+/*
+ * csio_hw_free - Uninitialize and free the HW module.
+ * @hw: The HW module
+ *
+ * Disable interrupts, uninit the HW module, free resources, free hw.
+ */
+static void
+csio_hw_free(struct csio_hw *hw)
+{
+       csio_intr_disable(hw, true);
+       csio_hw_exit_workers(hw);
+       csio_hw_exit(hw);
+       iounmap(hw->regstart);
+       csio_dfs_destroy(hw);
+       csio_resource_free(hw);
+       kfree(hw);
+}
+
+/**
+ * csio_shost_init - Create and initialize the lnode module.
+ * @hw:                The HW module.
+ * @dev:       The device associated with this invocation.
+ * @probe:     Called from probe context or not?
+ * @os_pln:    Parent lnode if any.
+ *
+ * Allocates lnode structure via scsi_host_alloc, initializes
+ * shost, initializes lnode module and registers with SCSI ML
+ * via scsi_host_add. This function is shared between physical and
+ * virtual node ports.
+ */
+struct csio_lnode *
+csio_shost_init(struct csio_hw *hw, struct device *dev,
+                 bool probe, struct csio_lnode *pln)
+{
+       struct Scsi_Host  *shost = NULL;
+       struct csio_lnode *ln;
+
+       csio_fcoe_shost_template.cmd_per_lun = csio_lun_qdepth;
+       csio_fcoe_shost_vport_template.cmd_per_lun = csio_lun_qdepth;
+
+       /*
+        * hw->pdev is the physical port's PCI dev structure,
+        * which will be different from the NPIV dev structure.
+        */
+       if (dev == &hw->pdev->dev)
+               shost = scsi_host_alloc(
+                               &csio_fcoe_shost_template,
+                               sizeof(struct csio_lnode));
+       else
+               shost = scsi_host_alloc(
+                               &csio_fcoe_shost_vport_template,
+                               sizeof(struct csio_lnode));
+
+       if (!shost)
+               goto err;
+
+       ln = shost_priv(shost);
+       memset(ln, 0, sizeof(struct csio_lnode));
+
+       /* Link common lnode to this lnode */
+       ln->dev_num = (shost->host_no << 16);
+
+       shost->can_queue = CSIO_MAX_QUEUE;
+       shost->this_id = -1;
+       shost->unique_id = shost->host_no;
+       shost->max_cmd_len = 16; /* Max CDB length supported */
+       shost->max_id = min_t(uint32_t, csio_fcoe_rnodes,
+                             hw->fres_info.max_ssns);
+       shost->max_lun = CSIO_MAX_LUN;
+       if (dev == &hw->pdev->dev)
+               shost->transportt = csio_fcoe_transport;
+       else
+               shost->transportt = csio_fcoe_transport_vport;
+
+       /* root lnode */
+       if (!hw->rln)
+               hw->rln = ln;
+
+       /* Other initialization here: Common, Transport specific */
+       if (csio_lnode_init(ln, hw, pln))
+               goto err_shost_put;
+
+       if (scsi_add_host(shost, dev))
+               goto err_lnode_exit;
+
+       return ln;
+
+err_lnode_exit:
+       csio_lnode_exit(ln);
+err_shost_put:
+       scsi_host_put(shost);
+err:
+       return NULL;
+}
+
+/**
+ * csio_shost_exit - De-instantiate the shost.
+ * @ln:                The lnode module corresponding to the shost.
+ *
+ */
+void
+csio_shost_exit(struct csio_lnode *ln)
+{
+       struct Scsi_Host *shost = csio_ln_to_shost(ln);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       /* Inform transport */
+       fc_remove_host(shost);
+
+       /* Inform SCSI ML */
+       scsi_remove_host(shost);
+
+       /* Flush all the events, so that any rnode removal events
+        * already queued are all handled, before we remove the lnode.
+        */
+       spin_lock_irq(&hw->lock);
+       csio_evtq_flush(hw);
+       spin_unlock_irq(&hw->lock);
+
+       csio_lnode_exit(ln);
+       scsi_host_put(shost);
+}
+
+struct csio_lnode *
+csio_lnode_alloc(struct csio_hw *hw)
+{
+       return csio_shost_init(hw, &hw->pdev->dev, false, NULL);
+}
+
+void
+csio_lnodes_block_request(struct csio_hw *hw)
+{
+       struct Scsi_Host  *shost;
+       struct csio_lnode *sln;
+       struct csio_lnode *ln;
+       struct list_head *cur_ln, *cur_cln;
+       struct csio_lnode **lnode_list;
+       int cur_cnt = 0, ii;
+
+       lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+                       GFP_KERNEL);
+       if (!lnode_list) {
+               csio_err(hw, "Failed to allocate lnodes_list");
+               return;
+       }
+
+       spin_lock_irq(&hw->lock);
+       /* Traverse sibling lnodes */
+       list_for_each(cur_ln, &hw->sln_head) {
+               sln = (struct csio_lnode *) cur_ln;
+               lnode_list[cur_cnt++] = sln;
+
+               /* Traverse children lnodes */
+               list_for_each(cur_cln, &sln->cln_head)
+                       lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+       }
+       spin_unlock_irq(&hw->lock);
+
+       for (ii = 0; ii < cur_cnt; ii++) {
+               csio_dbg(hw, "Blocking IOs on lnode: %p\n", lnode_list[ii]);
+               ln = lnode_list[ii];
+               shost = csio_ln_to_shost(ln);
+               scsi_block_requests(shost);
+
+       }
+       kfree(lnode_list);
+}
+
+void
+csio_lnodes_unblock_request(struct csio_hw *hw)
+{
+       struct csio_lnode *ln;
+       struct Scsi_Host  *shost;
+       struct csio_lnode *sln;
+       struct list_head *cur_ln, *cur_cln;
+       struct csio_lnode **lnode_list;
+       int cur_cnt = 0, ii;
+
+       lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+                       GFP_KERNEL);
+       if (!lnode_list) {
+               csio_err(hw, "Failed to allocate lnodes_list");
+               return;
+       }
+
+       spin_lock_irq(&hw->lock);
+       /* Traverse sibling lnodes */
+       list_for_each(cur_ln, &hw->sln_head) {
+               sln = (struct csio_lnode *) cur_ln;
+               lnode_list[cur_cnt++] = sln;
+
+               /* Traverse children lnodes */
+               list_for_each(cur_cln, &sln->cln_head)
+                       lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+       }
+       spin_unlock_irq(&hw->lock);
+
+       for (ii = 0; ii < cur_cnt; ii++) {
+               csio_dbg(hw, "unblocking IOs on lnode: %p\n", lnode_list[ii]);
+               ln = lnode_list[ii];
+               shost = csio_ln_to_shost(ln);
+               scsi_unblock_requests(shost);
+       }
+       kfree(lnode_list);
+}
+
+void
+csio_lnodes_block_by_port(struct csio_hw *hw, uint8_t portid)
+{
+       struct csio_lnode *ln;
+       struct Scsi_Host  *shost;
+       struct csio_lnode *sln;
+       struct list_head *cur_ln, *cur_cln;
+       struct csio_lnode **lnode_list;
+       int cur_cnt = 0, ii;
+
+       lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+                       GFP_KERNEL);
+       if (!lnode_list) {
+               csio_err(hw, "Failed to allocate lnodes_list");
+               return;
+       }
+
+       spin_lock_irq(&hw->lock);
+       /* Traverse sibling lnodes */
+       list_for_each(cur_ln, &hw->sln_head) {
+               sln = (struct csio_lnode *) cur_ln;
+               if (sln->portid != portid)
+                       continue;
+
+               lnode_list[cur_cnt++] = sln;
+
+               /* Traverse children lnodes */
+               list_for_each(cur_cln, &sln->cln_head)
+                       lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+       }
+       spin_unlock_irq(&hw->lock);
+
+       for (ii = 0; ii < cur_cnt; ii++) {
+               csio_dbg(hw, "Blocking IOs on lnode: %p\n", lnode_list[ii]);
+               ln = lnode_list[ii];
+               shost = csio_ln_to_shost(ln);
+               scsi_block_requests(shost);
+       }
+       kfree(lnode_list);
+}
+
+void
+csio_lnodes_unblock_by_port(struct csio_hw *hw, uint8_t portid)
+{
+       struct csio_lnode *ln;
+       struct Scsi_Host  *shost;
+       struct csio_lnode *sln;
+       struct list_head *cur_ln, *cur_cln;
+       struct csio_lnode **lnode_list;
+       int cur_cnt = 0, ii;
+
+       lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+                       GFP_KERNEL);
+       if (!lnode_list) {
+               csio_err(hw, "Failed to allocate lnodes_list");
+               return;
+       }
+
+       spin_lock_irq(&hw->lock);
+       /* Traverse sibling lnodes */
+       list_for_each(cur_ln, &hw->sln_head) {
+               sln = (struct csio_lnode *) cur_ln;
+               if (sln->portid != portid)
+                       continue;
+               lnode_list[cur_cnt++] = sln;
+
+               /* Traverse children lnodes */
+               list_for_each(cur_cln, &sln->cln_head)
+                       lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+       }
+       spin_unlock_irq(&hw->lock);
+
+       for (ii = 0; ii < cur_cnt; ii++) {
+               csio_dbg(hw, "unblocking IOs on lnode: %p\n", lnode_list[ii]);
+               ln = lnode_list[ii];
+               shost = csio_ln_to_shost(ln);
+               scsi_unblock_requests(shost);
+       }
+       kfree(lnode_list);
+}
+
+void
+csio_lnodes_exit(struct csio_hw *hw, bool npiv)
+{
+       struct csio_lnode *sln;
+       struct csio_lnode *ln;
+       struct list_head *cur_ln, *cur_cln;
+       struct csio_lnode **lnode_list;
+       int cur_cnt = 0, ii;
+
+       lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+                       GFP_KERNEL);
+       if (!lnode_list) {
+               csio_err(hw, "lnodes_exit: Failed to allocate lnodes_list.\n");
+               return;
+       }
+
+       /* Get all child lnodes(NPIV ports) */
+       spin_lock_irq(&hw->lock);
+       list_for_each(cur_ln, &hw->sln_head) {
+               sln = (struct csio_lnode *) cur_ln;
+
+               /* Traverse children lnodes */
+               list_for_each(cur_cln, &sln->cln_head)
+                       lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+       }
+       spin_unlock_irq(&hw->lock);
+
+       /* Delete NPIV lnodes */
+       for (ii = 0; ii < cur_cnt; ii++) {
+               csio_dbg(hw, "Deleting child lnode: %p\n", lnode_list[ii]);
+               ln = lnode_list[ii];
+               fc_vport_terminate(ln->fc_vport);
+       }
+
+       /* Delete only npiv lnodes */
+       if (npiv)
+               goto free_lnodes;
+
+       cur_cnt = 0;
+       /* Get all physical lnodes */
+       spin_lock_irq(&hw->lock);
+       /* Traverse sibling lnodes */
+       list_for_each(cur_ln, &hw->sln_head) {
+               sln = (struct csio_lnode *) cur_ln;
+               lnode_list[cur_cnt++] = sln;
+       }
+       spin_unlock_irq(&hw->lock);
+
+       /* Delete physical lnodes */
+       for (ii = 0; ii < cur_cnt; ii++) {
+               csio_dbg(hw, "Deleting parent lnode: %p\n", lnode_list[ii]);
+               csio_shost_exit(lnode_list[ii]);
+       }
+
+free_lnodes:
+       kfree(lnode_list);
+}
+
+/*
+ * csio_lnode_init_post: Set lnode attributes after starting HW.
+ * @ln: lnode.
+ *
+ */
+static void
+csio_lnode_init_post(struct csio_lnode *ln)
+{
+       struct Scsi_Host  *shost = csio_ln_to_shost(ln);
+
+       csio_fchost_attr_init(ln);
+
+       scsi_scan_host(shost);
+}
+
+/*
+ * csio_probe_one - Instantiate this function.
+ * @pdev: PCI device
+ * @id: Device ID
+ *
+ * This is the .probe() callback of the driver. This function:
+ * - Initializes the PCI function by enabling MMIO, setting bus
+ *   mastership and setting DMA mask.
+ * - Allocates HW structure, DMA, memory resources, maps BARS to
+ *   host memory and initializes HW module.
+ * - Allocates lnode structure via scsi_host_alloc, initializes
+ *   shost, initialized lnode module and registers with SCSI ML
+ *   via scsi_host_add.
+ * - Enables interrupts, and starts the chip by kicking off the
+ *   HW state machine.
+ * - Once hardware is ready, initiated scan of the host via
+ *   scsi_scan_host.
+ */
+static int __devinit
+csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       int rv;
+       int bars;
+       int i;
+       struct csio_hw *hw;
+       struct csio_lnode *ln;
+
+       rv = csio_pci_init(pdev, &bars);
+       if (rv)
+               goto err;
+
+       hw = csio_hw_alloc(pdev);
+       if (!hw) {
+               rv = -ENODEV;
+               goto err_pci_exit;
+       }
+
+       pci_set_drvdata(pdev, hw);
+
+       if (csio_hw_start(hw) != 0) {
+               dev_err(&pdev->dev,
+                       "Failed to start FW, continuing in debug mode.\n");
+               return 0;
+       }
+
+       sprintf(hw->fwrev_str, "%u.%u.%u.%u\n",
+                   FW_HDR_FW_VER_MAJOR_GET(hw->fwrev),
+                   FW_HDR_FW_VER_MINOR_GET(hw->fwrev),
+                   FW_HDR_FW_VER_MICRO_GET(hw->fwrev),
+                   FW_HDR_FW_VER_BUILD_GET(hw->fwrev));
+
+       for (i = 0; i < hw->num_pports; i++) {
+               ln = csio_shost_init(hw, &pdev->dev, true, NULL);
+               if (!ln) {
+                       rv = -ENODEV;
+                       break;
+               }
+               /* Initialize portid */
+               ln->portid = hw->pport[i].portid;
+
+               spin_lock_irq(&hw->lock);
+               if (csio_lnode_start(ln) != 0)
+                       rv = -ENODEV;
+               spin_unlock_irq(&hw->lock);
+
+               if (rv)
+                       break;
+
+               csio_lnode_init_post(ln);
+       }
+
+       if (rv)
+               goto err_lnode_exit;
+
+       return 0;
+
+err_lnode_exit:
+       csio_lnodes_block_request(hw);
+       spin_lock_irq(&hw->lock);
+       csio_hw_stop(hw);
+       spin_unlock_irq(&hw->lock);
+       csio_lnodes_unblock_request(hw);
+       pci_set_drvdata(hw->pdev, NULL);
+       csio_lnodes_exit(hw, 0);
+       csio_hw_free(hw);
+err_pci_exit:
+       csio_pci_exit(pdev, &bars);
+err:
+       dev_err(&pdev->dev, "probe of device failed: %d\n", rv);
+       return rv;
+}
+
+/*
+ * csio_remove_one - Remove one instance of the driver at this PCI function.
+ * @pdev: PCI device
+ *
+ * Used during hotplug operation.
+ */
+static void __devexit
+csio_remove_one(struct pci_dev *pdev)
+{
+       struct csio_hw *hw = pci_get_drvdata(pdev);
+       int bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+       csio_lnodes_block_request(hw);
+       spin_lock_irq(&hw->lock);
+
+       /* Stops lnode, Rnode s/m
+        * Quiesce IOs.
+        * All sessions with remote ports are unregistered.
+        */
+       csio_hw_stop(hw);
+       spin_unlock_irq(&hw->lock);
+       csio_lnodes_unblock_request(hw);
+
+       csio_lnodes_exit(hw, 0);
+       csio_hw_free(hw);
+       pci_set_drvdata(pdev, NULL);
+       csio_pci_exit(pdev, &bars);
+}
+
+/*
+ * csio_pci_error_detected - PCI error was detected
+ * @pdev: PCI device
+ *
+ */
+static pci_ers_result_t
+csio_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+       struct csio_hw *hw = pci_get_drvdata(pdev);
+
+       csio_lnodes_block_request(hw);
+       spin_lock_irq(&hw->lock);
+
+       /* Post PCI error detected evt to HW s/m
+        * HW s/m handles this evt by quiescing IOs, unregisters rports
+        * and finally takes the device to offline.
+        */
+       csio_post_event(&hw->sm, CSIO_HWE_PCIERR_DETECTED);
+       spin_unlock_irq(&hw->lock);
+       csio_lnodes_unblock_request(hw);
+       csio_lnodes_exit(hw, 0);
+       csio_intr_disable(hw, true);
+       pci_disable_device(pdev);
+       return state == pci_channel_io_perm_failure ?
+               PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * csio_pci_slot_reset - PCI slot has been reset.
+ * @pdev: PCI device
+ *
+ */
+static pci_ers_result_t
+csio_pci_slot_reset(struct pci_dev *pdev)
+{
+       struct csio_hw *hw = pci_get_drvdata(pdev);
+       int ready;
+
+       if (pci_enable_device(pdev)) {
+               dev_err(&pdev->dev, "cannot re-enable device in slot reset\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       pci_set_master(pdev);
+       pci_restore_state(pdev);
+       pci_save_state(pdev);
+       pci_cleanup_aer_uncorrect_error_status(pdev);
+
+       /* Bring HW s/m to ready state.
+        * but don't resume IOs.
+        */
+       spin_lock_irq(&hw->lock);
+       csio_post_event(&hw->sm, CSIO_HWE_PCIERR_SLOT_RESET);
+       ready = csio_is_hw_ready(hw);
+       spin_unlock_irq(&hw->lock);
+
+       if (ready) {
+               return PCI_ERS_RESULT_RECOVERED;
+       } else {
+               dev_err(&pdev->dev, "Can't initialize HW when in slot reset\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+}
+
+/*
+ * csio_pci_resume - Resume normal operations
+ * @pdev: PCI device
+ *
+ */
+static void
+csio_pci_resume(struct pci_dev *pdev)
+{
+       struct csio_hw *hw = pci_get_drvdata(pdev);
+       struct csio_lnode *ln;
+       int rv = 0;
+       int i;
+
+       /* Bring the LINK UP and Resume IO */
+
+       for (i = 0; i < hw->num_pports; i++) {
+               ln = csio_shost_init(hw, &pdev->dev, true, NULL);
+               if (!ln) {
+                       rv = -ENODEV;
+                       break;
+               }
+               /* Initialize portid */
+               ln->portid = hw->pport[i].portid;
+
+               spin_lock_irq(&hw->lock);
+               if (csio_lnode_start(ln) != 0)
+                       rv = -ENODEV;
+               spin_unlock_irq(&hw->lock);
+
+               if (rv)
+                       break;
+
+               csio_lnode_init_post(ln);
+       }
+
+       if (rv)
+               goto err_resume_exit;
+
+       return;
+
+err_resume_exit:
+       csio_lnodes_block_request(hw);
+       spin_lock_irq(&hw->lock);
+       csio_hw_stop(hw);
+       spin_unlock_irq(&hw->lock);
+       csio_lnodes_unblock_request(hw);
+       csio_lnodes_exit(hw, 0);
+       csio_hw_free(hw);
+       dev_err(&pdev->dev, "resume of device failed: %d\n", rv);
+}
+
+static struct pci_error_handlers csio_err_handler = {
+       .error_detected = csio_pci_error_detected,
+       .slot_reset     = csio_pci_slot_reset,
+       .resume         = csio_pci_resume,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
+       CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0),        /* T440DBG FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0),         /* T420CR FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0),         /* T422CR FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T440CR_FCOE, 0),         /* T440CR FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T420BCH_FCOE, 0),        /* T420BCH FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T440BCH_FCOE, 0),        /* T440BCH FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T440CH_FCOE, 0),         /* T440CH FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T420SO_FCOE, 0),         /* T420SO FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T420CX_FCOE, 0),         /* T420CX FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T420BT_FCOE, 0),         /* T420BT FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T404BT_FCOE, 0),         /* T404BT FCOE */
+       CSIO_DEVICE(CSIO_DEVID_B420_FCOE, 0),           /* B420 FCOE */
+       CSIO_DEVICE(CSIO_DEVID_B404_FCOE, 0),           /* B404 FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T480CR_FCOE, 0),         /* T480 CR FCOE */
+       CSIO_DEVICE(CSIO_DEVID_T440LPCR_FCOE, 0),       /* T440 LP-CR FCOE */
+       CSIO_DEVICE(CSIO_DEVID_PE10K, 0),               /* PE10K FCOE */
+       CSIO_DEVICE(CSIO_DEVID_PE10K_PF1, 0),   /* PE10K FCOE on PF1 */
+       { 0, 0, 0, 0, 0, 0, 0 }
+};
+
+
+static struct pci_driver csio_pci_driver = {
+       .name           = KBUILD_MODNAME,
+       .driver         = {
+               .owner  = THIS_MODULE,
+       },
+       .id_table       = csio_pci_tbl,
+       .probe          = csio_probe_one,
+       .remove         = csio_remove_one,
+       .err_handler    = &csio_err_handler,
+};
+
+/*
+ * csio_init - Chelsio storage driver initialization function.
+ *
+ */
+static int __init
+csio_init(void)
+{
+       int rv = -ENOMEM;
+
+       pr_info("%s %s\n", CSIO_DRV_DESC, CSIO_DRV_VERSION);
+
+       csio_dfs_init();
+
+       csio_fcoe_transport = fc_attach_transport(&csio_fc_transport_funcs);
+       if (!csio_fcoe_transport)
+               goto err;
+
+       csio_fcoe_transport_vport =
+                       fc_attach_transport(&csio_fc_transport_vport_funcs);
+       if (!csio_fcoe_transport_vport)
+               goto err_vport;
+
+       rv = pci_register_driver(&csio_pci_driver);
+       if (rv)
+               goto err_pci;
+
+       return 0;
+
+err_pci:
+       fc_release_transport(csio_fcoe_transport_vport);
+err_vport:
+       fc_release_transport(csio_fcoe_transport);
+err:
+       csio_dfs_exit();
+       return rv;
+}
+
+/*
+ * csio_exit - Chelsio storage driver uninitialization .
+ *
+ * Function that gets called in the unload path.
+ */
+static void __exit
+csio_exit(void)
+{
+       pci_unregister_driver(&csio_pci_driver);
+       csio_dfs_exit();
+       fc_release_transport(csio_fcoe_transport_vport);
+       fc_release_transport(csio_fcoe_transport);
+}
+
+module_init(csio_init);
+module_exit(csio_exit);
+MODULE_AUTHOR(CSIO_DRV_AUTHOR);
+MODULE_DESCRIPTION(CSIO_DRV_DESC);
+MODULE_LICENSE(CSIO_DRV_LICENSE);
+MODULE_DEVICE_TABLE(pci, csio_pci_tbl);
+MODULE_VERSION(CSIO_DRV_VERSION);
+MODULE_FIRMWARE(CSIO_FW_FNAME);
diff --git a/drivers/scsi/csiostor/csio_init.h b/drivers/scsi/csiostor/csio_init.h
new file mode 100644 (file)
index 0000000..0838fd7
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_INIT_H__
+#define __CSIO_INIT_H__
+
+#include <linux/pci.h>
+#include <linux/if_ether.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_scsi.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_hw.h"
+
+#define CSIO_DRV_AUTHOR                        "Chelsio Communications"
+#define CSIO_DRV_LICENSE               "Dual BSD/GPL"
+#define CSIO_DRV_DESC                  "Chelsio FCoE driver"
+#define CSIO_DRV_VERSION               "1.0.0"
+
+#define CSIO_DEVICE(devid, idx)                                        \
+{ PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
+
+#define CSIO_IS_T4_FPGA(_dev)          (((_dev) == CSIO_DEVID_PE10K) ||\
+                                        ((_dev) == CSIO_DEVID_PE10K_PF1))
+
+/* FCoE device IDs */
+#define CSIO_DEVID_PE10K               0xA000
+#define CSIO_DEVID_PE10K_PF1           0xA001
+#define CSIO_DEVID_T440DBG_FCOE                0x4600
+#define CSIO_DEVID_T420CR_FCOE         0x4601
+#define CSIO_DEVID_T422CR_FCOE         0x4602
+#define CSIO_DEVID_T440CR_FCOE         0x4603
+#define CSIO_DEVID_T420BCH_FCOE                0x4604
+#define CSIO_DEVID_T440BCH_FCOE                0x4605
+#define CSIO_DEVID_T440CH_FCOE         0x4606
+#define CSIO_DEVID_T420SO_FCOE         0x4607
+#define CSIO_DEVID_T420CX_FCOE         0x4608
+#define CSIO_DEVID_T420BT_FCOE         0x4609
+#define CSIO_DEVID_T404BT_FCOE         0x460A
+#define CSIO_DEVID_B420_FCOE           0x460B
+#define CSIO_DEVID_B404_FCOE           0x460C
+#define CSIO_DEVID_T480CR_FCOE         0x460D
+#define CSIO_DEVID_T440LPCR_FCOE       0x460E
+
+extern struct fc_function_template csio_fc_transport_funcs;
+extern struct fc_function_template csio_fc_transport_vport_funcs;
+
+void csio_fchost_attr_init(struct csio_lnode *);
+
+/* INTx handlers */
+void csio_scsi_intx_handler(struct csio_hw *, void *, uint32_t,
+                              struct csio_fl_dma_buf *, void *);
+
+void csio_fwevt_intx_handler(struct csio_hw *, void *, uint32_t,
+                               struct csio_fl_dma_buf *, void *);
+
+/* Common os lnode APIs */
+void csio_lnodes_block_request(struct csio_hw *);
+void csio_lnodes_unblock_request(struct csio_hw *);
+void csio_lnodes_block_by_port(struct csio_hw *, uint8_t);
+void csio_lnodes_unblock_by_port(struct csio_hw *, uint8_t);
+
+struct csio_lnode *csio_shost_init(struct csio_hw *, struct device *, bool,
+                                       struct csio_lnode *);
+void csio_shost_exit(struct csio_lnode *);
+void csio_lnodes_exit(struct csio_hw *, bool);
+
+static inline struct Scsi_Host *
+csio_ln_to_shost(struct csio_lnode *ln)
+{
+       return container_of((void *)ln, struct Scsi_Host, hostdata[0]);
+}
+
+/* SCSI -- locking version of get/put ioreqs  */
+static inline struct csio_ioreq *
+csio_get_scsi_ioreq_lock(struct csio_hw *hw, struct csio_scsim *scsim)
+{
+       struct csio_ioreq *ioreq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&scsim->freelist_lock, flags);
+       ioreq = csio_get_scsi_ioreq(scsim);
+       spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+
+       return ioreq;
+}
+
+static inline void
+csio_put_scsi_ioreq_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+                        struct csio_ioreq *ioreq)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&scsim->freelist_lock, flags);
+       csio_put_scsi_ioreq(scsim, ioreq);
+       spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+}
+
+/* Called in interrupt context */
+static inline void
+csio_put_scsi_ioreq_list_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+                             struct list_head *reqlist, int n)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&scsim->freelist_lock, flags);
+       csio_put_scsi_ioreq_list(scsim, reqlist, n);
+       spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+}
+
+/* Called in interrupt context */
+static inline void
+csio_put_scsi_ddp_list_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+                             struct list_head *reqlist, int n)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hw->lock, flags);
+       csio_put_scsi_ddp_list(scsim, reqlist, n);
+       spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+#endif /* ifndef __CSIO_INIT_H__ */
diff --git a/drivers/scsi/csiostor/csio_isr.c b/drivers/scsi/csiostor/csio_isr.c
new file mode 100644 (file)
index 0000000..7ee9777
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+
+#include "csio_init.h"
+#include "csio_hw.h"
+
+static irqreturn_t
+csio_nondata_isr(int irq, void *dev_id)
+{
+       struct csio_hw *hw = (struct csio_hw *) dev_id;
+       int rv;
+       unsigned long flags;
+
+       if (unlikely(!hw))
+               return IRQ_NONE;
+
+       if (unlikely(pci_channel_offline(hw->pdev))) {
+               CSIO_INC_STATS(hw, n_pcich_offline);
+               return IRQ_NONE;
+       }
+
+       spin_lock_irqsave(&hw->lock, flags);
+       csio_hw_slow_intr_handler(hw);
+       rv = csio_mb_isr_handler(hw);
+
+       if (rv == 0 && !(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+               hw->flags |= CSIO_HWF_FWEVT_PENDING;
+               spin_unlock_irqrestore(&hw->lock, flags);
+               schedule_work(&hw->evtq_work);
+               return IRQ_HANDLED;
+       }
+       spin_unlock_irqrestore(&hw->lock, flags);
+       return IRQ_HANDLED;
+}
+
+/*
+ * csio_fwevt_handler - Common FW event handler routine.
+ * @hw: HW module.
+ *
+ * This is the ISR for FW events. It is shared b/w MSIX
+ * and INTx handlers.
+ */
+static void
+csio_fwevt_handler(struct csio_hw *hw)
+{
+       int rv;
+       unsigned long flags;
+
+       rv = csio_fwevtq_handler(hw);
+
+       spin_lock_irqsave(&hw->lock, flags);
+       if (rv == 0 && !(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+               hw->flags |= CSIO_HWF_FWEVT_PENDING;
+               spin_unlock_irqrestore(&hw->lock, flags);
+               schedule_work(&hw->evtq_work);
+               return;
+       }
+       spin_unlock_irqrestore(&hw->lock, flags);
+
+} /* csio_fwevt_handler */
+
+/*
+ * csio_fwevt_isr() - FW events MSIX ISR
+ * @irq:
+ * @dev_id:
+ *
+ * Process WRs on the FW event queue.
+ *
+ */
+static irqreturn_t
+csio_fwevt_isr(int irq, void *dev_id)
+{
+       struct csio_hw *hw = (struct csio_hw *) dev_id;
+
+       if (unlikely(!hw))
+               return IRQ_NONE;
+
+       if (unlikely(pci_channel_offline(hw->pdev))) {
+               CSIO_INC_STATS(hw, n_pcich_offline);
+               return IRQ_NONE;
+       }
+
+       csio_fwevt_handler(hw);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * csio_fwevt_isr() - INTx wrapper for handling FW events.
+ * @irq:
+ * @dev_id:
+ */
+void
+csio_fwevt_intx_handler(struct csio_hw *hw, void *wr, uint32_t len,
+                          struct csio_fl_dma_buf *flb, void *priv)
+{
+       csio_fwevt_handler(hw);
+} /* csio_fwevt_intx_handler */
+
+/*
+ * csio_process_scsi_cmpl - Process a SCSI WR completion.
+ * @hw: HW module.
+ * @wr: The completed WR from the ingress queue.
+ * @len: Length of the WR.
+ * @flb: Freelist buffer array.
+ *
+ */
+static void
+csio_process_scsi_cmpl(struct csio_hw *hw, void *wr, uint32_t len,
+                       struct csio_fl_dma_buf *flb, void *cbfn_q)
+{
+       struct csio_ioreq *ioreq;
+       uint8_t *scsiwr;
+       uint8_t subop;
+       void *cmnd;
+       unsigned long flags;
+
+       ioreq = csio_scsi_cmpl_handler(hw, wr, len, flb, NULL, &scsiwr);
+       if (likely(ioreq)) {
+               if (unlikely(*scsiwr == FW_SCSI_ABRT_CLS_WR)) {
+                       subop = FW_SCSI_ABRT_CLS_WR_SUB_OPCODE_GET(
+                                       ((struct fw_scsi_abrt_cls_wr *)
+                                           scsiwr)->sub_opcode_to_chk_all_io);
+
+                       csio_dbg(hw, "%s cmpl recvd ioreq:%p status:%d\n",
+                                   subop ? "Close" : "Abort",
+                                   ioreq, ioreq->wr_status);
+
+                       spin_lock_irqsave(&hw->lock, flags);
+                       if (subop)
+                               csio_scsi_closed(ioreq,
+                                                (struct list_head *)cbfn_q);
+                       else
+                               csio_scsi_aborted(ioreq,
+                                                 (struct list_head *)cbfn_q);
+                       /*
+                        * We call scsi_done for I/Os that driver thinks aborts
+                        * have timed out. If there is a race caused by FW
+                        * completing abort at the exact same time that the
+                        * driver has deteced the abort timeout, the following
+                        * check prevents calling of scsi_done twice for the
+                        * same command: once from the eh_abort_handler, another
+                        * from csio_scsi_isr_handler(). This also avoids the
+                        * need to check if csio_scsi_cmnd(req) is NULL in the
+                        * fast path.
+                        */
+                       cmnd = csio_scsi_cmnd(ioreq);
+                       if (unlikely(cmnd == NULL))
+                               list_del_init(&ioreq->sm.sm_list);
+
+                       spin_unlock_irqrestore(&hw->lock, flags);
+
+                       if (unlikely(cmnd == NULL))
+                               csio_put_scsi_ioreq_lock(hw,
+                                               csio_hw_to_scsim(hw), ioreq);
+               } else {
+                       spin_lock_irqsave(&hw->lock, flags);
+                       csio_scsi_completed(ioreq, (struct list_head *)cbfn_q);
+                       spin_unlock_irqrestore(&hw->lock, flags);
+               }
+       }
+}
+
+/*
+ * csio_scsi_isr_handler() - Common SCSI ISR handler.
+ * @iq: Ingress queue pointer.
+ *
+ * Processes SCSI completions on the SCSI IQ indicated by scm->iq_idx
+ * by calling csio_wr_process_iq_idx. If there are completions on the
+ * isr_cbfn_q, yank them out into a local queue and call their io_cbfns.
+ * Once done, add these completions onto the freelist.
+ * This routine is shared b/w MSIX and INTx.
+ */
+static inline irqreturn_t
+csio_scsi_isr_handler(struct csio_q *iq)
+{
+       struct csio_hw *hw = (struct csio_hw *)iq->owner;
+       LIST_HEAD(cbfn_q);
+       struct list_head *tmp;
+       struct csio_scsim *scm;
+       struct csio_ioreq *ioreq;
+       int isr_completions = 0;
+
+       scm = csio_hw_to_scsim(hw);
+
+       if (unlikely(csio_wr_process_iq(hw, iq, csio_process_scsi_cmpl,
+                                       &cbfn_q) != 0))
+               return IRQ_NONE;
+
+       /* Call back the completion routines */
+       list_for_each(tmp, &cbfn_q) {
+               ioreq = (struct csio_ioreq *)tmp;
+               isr_completions++;
+               ioreq->io_cbfn(hw, ioreq);
+               /* Release ddp buffer if used for this req */
+               if (unlikely(ioreq->dcopy))
+                       csio_put_scsi_ddp_list_lock(hw, scm, &ioreq->gen_list,
+                                                   ioreq->nsge);
+       }
+
+       if (isr_completions) {
+               /* Return the ioreqs back to ioreq->freelist */
+               csio_put_scsi_ioreq_list_lock(hw, scm, &cbfn_q,
+                                             isr_completions);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * csio_scsi_isr() - SCSI MSIX handler
+ * @irq:
+ * @dev_id:
+ *
+ * This is the top level SCSI MSIX handler. Calls csio_scsi_isr_handler()
+ * for handling SCSI completions.
+ */
+static irqreturn_t
+csio_scsi_isr(int irq, void *dev_id)
+{
+       struct csio_q *iq = (struct csio_q *) dev_id;
+       struct csio_hw *hw;
+
+       if (unlikely(!iq))
+               return IRQ_NONE;
+
+       hw = (struct csio_hw *)iq->owner;
+
+       if (unlikely(pci_channel_offline(hw->pdev))) {
+               CSIO_INC_STATS(hw, n_pcich_offline);
+               return IRQ_NONE;
+       }
+
+       csio_scsi_isr_handler(iq);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * csio_scsi_intx_handler() - SCSI INTx handler
+ * @irq:
+ * @dev_id:
+ *
+ * This is the top level SCSI INTx handler. Calls csio_scsi_isr_handler()
+ * for handling SCSI completions.
+ */
+void
+csio_scsi_intx_handler(struct csio_hw *hw, void *wr, uint32_t len,
+                       struct csio_fl_dma_buf *flb, void *priv)
+{
+       struct csio_q *iq = priv;
+
+       csio_scsi_isr_handler(iq);
+
+} /* csio_scsi_intx_handler */
+
+/*
+ * csio_fcoe_isr() - INTx/MSI interrupt service routine for FCoE.
+ * @irq:
+ * @dev_id:
+ *
+ *
+ */
+static irqreturn_t
+csio_fcoe_isr(int irq, void *dev_id)
+{
+       struct csio_hw *hw = (struct csio_hw *) dev_id;
+       struct csio_q *intx_q = NULL;
+       int rv;
+       irqreturn_t ret = IRQ_NONE;
+       unsigned long flags;
+
+       if (unlikely(!hw))
+               return IRQ_NONE;
+
+       if (unlikely(pci_channel_offline(hw->pdev))) {
+               CSIO_INC_STATS(hw, n_pcich_offline);
+               return IRQ_NONE;
+       }
+
+       /* Disable the interrupt for this PCI function. */
+       if (hw->intr_mode == CSIO_IM_INTX)
+               csio_wr_reg32(hw, 0, MYPF_REG(PCIE_PF_CLI));
+
+       /*
+        * The read in the following function will flush the
+        * above write.
+        */
+       if (csio_hw_slow_intr_handler(hw))
+               ret = IRQ_HANDLED;
+
+       /* Get the INTx Forward interrupt IQ. */
+       intx_q = csio_get_q(hw, hw->intr_iq_idx);
+
+       CSIO_DB_ASSERT(intx_q);
+
+       /* IQ handler is not possible for intx_q, hence pass in NULL */
+       if (likely(csio_wr_process_iq(hw, intx_q, NULL, NULL) == 0))
+               ret = IRQ_HANDLED;
+
+       spin_lock_irqsave(&hw->lock, flags);
+       rv = csio_mb_isr_handler(hw);
+       if (rv == 0 && !(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+               hw->flags |= CSIO_HWF_FWEVT_PENDING;
+               spin_unlock_irqrestore(&hw->lock, flags);
+               schedule_work(&hw->evtq_work);
+               return IRQ_HANDLED;
+       }
+       spin_unlock_irqrestore(&hw->lock, flags);
+
+       return ret;
+}
+
+static void
+csio_add_msix_desc(struct csio_hw *hw)
+{
+       int i;
+       struct csio_msix_entries *entryp = &hw->msix_entries[0];
+       int k = CSIO_EXTRA_VECS;
+       int len = sizeof(entryp->desc) - 1;
+       int cnt = hw->num_sqsets + k;
+
+       /* Non-data vector */
+       memset(entryp->desc, 0, len + 1);
+       snprintf(entryp->desc, len, "csio-%02x:%02x:%x-nondata",
+                CSIO_PCI_BUS(hw), CSIO_PCI_DEV(hw), CSIO_PCI_FUNC(hw));
+
+       entryp++;
+       memset(entryp->desc, 0, len + 1);
+       snprintf(entryp->desc, len, "csio-%02x:%02x:%x-fwevt",
+                CSIO_PCI_BUS(hw), CSIO_PCI_DEV(hw), CSIO_PCI_FUNC(hw));
+       entryp++;
+
+       /* Name SCSI vecs */
+       for (i = k; i < cnt; i++, entryp++) {
+               memset(entryp->desc, 0, len + 1);
+               snprintf(entryp->desc, len, "csio-%02x:%02x:%x-scsi%d",
+                        CSIO_PCI_BUS(hw), CSIO_PCI_DEV(hw),
+                        CSIO_PCI_FUNC(hw), i - CSIO_EXTRA_VECS);
+       }
+}
+
+int
+csio_request_irqs(struct csio_hw *hw)
+{
+       int rv, i, j, k = 0;
+       struct csio_msix_entries *entryp = &hw->msix_entries[0];
+       struct csio_scsi_cpu_info *info;
+
+       if (hw->intr_mode != CSIO_IM_MSIX) {
+               rv = request_irq(hw->pdev->irq, csio_fcoe_isr,
+                                       (hw->intr_mode == CSIO_IM_MSI) ?
+                                                       0 : IRQF_SHARED,
+                                       KBUILD_MODNAME, hw);
+               if (rv) {
+                       if (hw->intr_mode == CSIO_IM_MSI)
+                               pci_disable_msi(hw->pdev);
+                       csio_err(hw, "Failed to allocate interrupt line.\n");
+                       return -EINVAL;
+               }
+
+               goto out;
+       }
+
+       /* Add the MSIX vector descriptions */
+       csio_add_msix_desc(hw);
+
+       rv = request_irq(entryp[k].vector, csio_nondata_isr, 0,
+                        entryp[k].desc, hw);
+       if (rv) {
+               csio_err(hw, "IRQ request failed for vec %d err:%d\n",
+                        entryp[k].vector, rv);
+               goto err;
+       }
+
+       entryp[k++].dev_id = (void *)hw;
+
+       rv = request_irq(entryp[k].vector, csio_fwevt_isr, 0,
+                        entryp[k].desc, hw);
+       if (rv) {
+               csio_err(hw, "IRQ request failed for vec %d err:%d\n",
+                        entryp[k].vector, rv);
+               goto err;
+       }
+
+       entryp[k++].dev_id = (void *)hw;
+
+       /* Allocate IRQs for SCSI */
+       for (i = 0; i < hw->num_pports; i++) {
+               info = &hw->scsi_cpu_info[i];
+               for (j = 0; j < info->max_cpus; j++, k++) {
+                       struct csio_scsi_qset *sqset = &hw->sqset[i][j];
+                       struct csio_q *q = hw->wrm.q_arr[sqset->iq_idx];
+
+                       rv = request_irq(entryp[k].vector, csio_scsi_isr, 0,
+                                        entryp[k].desc, q);
+                       if (rv) {
+                               csio_err(hw,
+                                      "IRQ request failed for vec %d err:%d\n",
+                                      entryp[k].vector, rv);
+                               goto err;
+                       }
+
+                       entryp[k].dev_id = (void *)q;
+
+               } /* for all scsi cpus */
+       } /* for all ports */
+
+out:
+       hw->flags |= CSIO_HWF_HOST_INTR_ENABLED;
+
+       return 0;
+
+err:
+       for (i = 0; i < k; i++) {
+               entryp = &hw->msix_entries[i];
+               free_irq(entryp->vector, entryp->dev_id);
+       }
+       pci_disable_msix(hw->pdev);
+
+       return -EINVAL;
+}
+
+static void
+csio_disable_msix(struct csio_hw *hw, bool free)
+{
+       int i;
+       struct csio_msix_entries *entryp;
+       int cnt = hw->num_sqsets + CSIO_EXTRA_VECS;
+
+       if (free) {
+               for (i = 0; i < cnt; i++) {
+                       entryp = &hw->msix_entries[i];
+                       free_irq(entryp->vector, entryp->dev_id);
+               }
+       }
+       pci_disable_msix(hw->pdev);
+}
+
+/* Reduce per-port max possible CPUs */
+static void
+csio_reduce_sqsets(struct csio_hw *hw, int cnt)
+{
+       int i;
+       struct csio_scsi_cpu_info *info;
+
+       while (cnt < hw->num_sqsets) {
+               for (i = 0; i < hw->num_pports; i++) {
+                       info = &hw->scsi_cpu_info[i];
+                       if (info->max_cpus > 1) {
+                               info->max_cpus--;
+                               hw->num_sqsets--;
+                               if (hw->num_sqsets <= cnt)
+                                       break;
+                       }
+               }
+       }
+
+       csio_dbg(hw, "Reduced sqsets to %d\n", hw->num_sqsets);
+}
+
+static int
+csio_enable_msix(struct csio_hw *hw)
+{
+       int rv, i, j, k, n, min, cnt;
+       struct csio_msix_entries *entryp;
+       struct msix_entry *entries;
+       int extra = CSIO_EXTRA_VECS;
+       struct csio_scsi_cpu_info *info;
+
+       min = hw->num_pports + extra;
+       cnt = hw->num_sqsets + extra;
+
+       /* Max vectors required based on #niqs configured in fw */
+       if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS || !csio_is_hw_master(hw))
+               cnt = min_t(uint8_t, hw->cfg_niq, cnt);
+
+       entries = kzalloc(sizeof(struct msix_entry) * cnt, GFP_KERNEL);
+       if (!entries)
+               return -ENOMEM;
+
+       for (i = 0; i < cnt; i++)
+               entries[i].entry = (uint16_t)i;
+
+       csio_dbg(hw, "FW supp #niq:%d, trying %d msix's\n", hw->cfg_niq, cnt);
+
+       while ((rv = pci_enable_msix(hw->pdev, entries, cnt)) >= min)
+               cnt = rv;
+       if (!rv) {
+               if (cnt < (hw->num_sqsets + extra)) {
+                       csio_dbg(hw, "Reducing sqsets to %d\n", cnt - extra);
+                       csio_reduce_sqsets(hw, cnt - extra);
+               }
+       } else {
+               if (rv > 0) {
+                       pci_disable_msix(hw->pdev);
+                       csio_info(hw, "Not using MSI-X, remainder:%d\n", rv);
+               }
+
+               kfree(entries);
+               return -ENOMEM;
+       }
+
+       /* Save off vectors */
+       for (i = 0; i < cnt; i++) {
+               entryp = &hw->msix_entries[i];
+               entryp->vector = entries[i].vector;
+       }
+
+       /* Distribute vectors */
+       k = 0;
+       csio_set_nondata_intr_idx(hw, entries[k].entry);
+       csio_set_mb_intr_idx(csio_hw_to_mbm(hw), entries[k++].entry);
+       csio_set_fwevt_intr_idx(hw, entries[k++].entry);
+
+       for (i = 0; i < hw->num_pports; i++) {
+               info = &hw->scsi_cpu_info[i];
+
+               for (j = 0; j < hw->num_scsi_msix_cpus; j++) {
+                       n = (j % info->max_cpus) +  k;
+                       hw->sqset[i][j].intr_idx = entries[n].entry;
+               }
+
+               k += info->max_cpus;
+       }
+
+       kfree(entries);
+       return 0;
+}
+
+void
+csio_intr_enable(struct csio_hw *hw)
+{
+       hw->intr_mode = CSIO_IM_NONE;
+       hw->flags &= ~CSIO_HWF_HOST_INTR_ENABLED;
+
+       /* Try MSIX, then MSI or fall back to INTx */
+       if ((csio_msi == 2) && !csio_enable_msix(hw))
+               hw->intr_mode = CSIO_IM_MSIX;
+       else {
+               /* Max iqs required based on #niqs configured in fw */
+               if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS ||
+                       !csio_is_hw_master(hw)) {
+                       int extra = CSIO_EXTRA_MSI_IQS;
+
+                       if (hw->cfg_niq < (hw->num_sqsets + extra)) {
+                               csio_dbg(hw, "Reducing sqsets to %d\n",
+                                        hw->cfg_niq - extra);
+                               csio_reduce_sqsets(hw, hw->cfg_niq - extra);
+                       }
+               }
+
+               if ((csio_msi == 1) && !pci_enable_msi(hw->pdev))
+                       hw->intr_mode = CSIO_IM_MSI;
+               else
+                       hw->intr_mode = CSIO_IM_INTX;
+       }
+
+       csio_dbg(hw, "Using %s interrupt mode.\n",
+               (hw->intr_mode == CSIO_IM_MSIX) ? "MSIX" :
+               ((hw->intr_mode == CSIO_IM_MSI) ? "MSI" : "INTx"));
+}
+
+void
+csio_intr_disable(struct csio_hw *hw, bool free)
+{
+       csio_hw_intr_disable(hw);
+
+       switch (hw->intr_mode) {
+       case CSIO_IM_MSIX:
+               csio_disable_msix(hw, free);
+               break;
+       case CSIO_IM_MSI:
+               if (free)
+                       free_irq(hw->pdev->irq, hw);
+               pci_disable_msi(hw->pdev);
+               break;
+       case CSIO_IM_INTX:
+               if (free)
+                       free_irq(hw->pdev->irq, hw);
+               break;
+       default:
+               break;
+       }
+       hw->intr_mode = CSIO_IM_NONE;
+       hw->flags &= ~CSIO_HWF_HOST_INTR_ENABLED;
+}
diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c
new file mode 100644 (file)
index 0000000..ffe9be0
--- /dev/null
@@ -0,0 +1,2135 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/utsname.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+#include <asm/unaligned.h>
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_gs.h>
+#include <scsi/fc/fc_ms.h>
+
+#include "csio_hw.h"
+#include "csio_mb.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+
+int csio_fcoe_rnodes = 1024;
+int csio_fdmi_enable = 1;
+
+#define PORT_ID_PTR(_x)         ((uint8_t *)(&_x) + 1)
+
+/* Lnode SM declarations */
+static void csio_lns_uninit(struct csio_lnode *, enum csio_ln_ev);
+static void csio_lns_online(struct csio_lnode *, enum csio_ln_ev);
+static void csio_lns_ready(struct csio_lnode *, enum csio_ln_ev);
+static void csio_lns_offline(struct csio_lnode *, enum csio_ln_ev);
+
+static int csio_ln_mgmt_submit_req(struct csio_ioreq *,
+               void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *),
+               enum fcoe_cmn_type, struct csio_dma_buf *, uint32_t);
+
+/* LN event mapping */
+static enum csio_ln_ev fwevt_to_lnevt[] = {
+       CSIO_LNE_NONE,          /* None */
+       CSIO_LNE_NONE,          /* PLOGI_ACC_RCVD  */
+       CSIO_LNE_NONE,          /* PLOGI_RJT_RCVD  */
+       CSIO_LNE_NONE,          /* PLOGI_RCVD      */
+       CSIO_LNE_NONE,          /* PLOGO_RCVD      */
+       CSIO_LNE_NONE,          /* PRLI_ACC_RCVD   */
+       CSIO_LNE_NONE,          /* PRLI_RJT_RCVD   */
+       CSIO_LNE_NONE,          /* PRLI_RCVD       */
+       CSIO_LNE_NONE,          /* PRLO_RCVD       */
+       CSIO_LNE_NONE,          /* NPORT_ID_CHGD   */
+       CSIO_LNE_LOGO,          /* FLOGO_RCVD      */
+       CSIO_LNE_LOGO,          /* CLR_VIRT_LNK_RCVD */
+       CSIO_LNE_FAB_INIT_DONE,/* FLOGI_ACC_RCVD   */
+       CSIO_LNE_NONE,          /* FLOGI_RJT_RCVD   */
+       CSIO_LNE_FAB_INIT_DONE,/* FDISC_ACC_RCVD   */
+       CSIO_LNE_NONE,          /* FDISC_RJT_RCVD   */
+       CSIO_LNE_NONE,          /* FLOGI_TMO_MAX_RETRY */
+       CSIO_LNE_NONE,          /* IMPL_LOGO_ADISC_ACC */
+       CSIO_LNE_NONE,          /* IMPL_LOGO_ADISC_RJT */
+       CSIO_LNE_NONE,          /* IMPL_LOGO_ADISC_CNFLT */
+       CSIO_LNE_NONE,          /* PRLI_TMO             */
+       CSIO_LNE_NONE,          /* ADISC_TMO            */
+       CSIO_LNE_NONE,          /* RSCN_DEV_LOST */
+       CSIO_LNE_NONE,          /* SCR_ACC_RCVD */
+       CSIO_LNE_NONE,          /* ADISC_RJT_RCVD */
+       CSIO_LNE_NONE,          /* LOGO_SNT */
+       CSIO_LNE_NONE,          /* PROTO_ERR_IMPL_LOGO */
+};
+
+#define CSIO_FWE_TO_LNE(_evt)  ((_evt > PROTO_ERR_IMPL_LOGO) ?         \
+                                               CSIO_LNE_NONE : \
+                                               fwevt_to_lnevt[_evt])
+
+#define csio_ct_rsp(cp)                (((struct fc_ct_hdr *)cp)->ct_cmd)
+#define csio_ct_reason(cp)     (((struct fc_ct_hdr *)cp)->ct_reason)
+#define csio_ct_expl(cp)       (((struct fc_ct_hdr *)cp)->ct_explan)
+#define csio_ct_get_pld(cp)    ((void *)(((uint8_t *)cp) + FC_CT_HDR_LEN))
+
+/*
+ * csio_ln_match_by_portid - lookup lnode using given portid.
+ * @hw: HW module
+ * @portid: port-id.
+ *
+ * If found, returns lnode matching given portid otherwise returns NULL.
+ */
+static struct csio_lnode *
+csio_ln_lookup_by_portid(struct csio_hw *hw, uint8_t portid)
+{
+       struct csio_lnode *ln = hw->rln;
+       struct list_head *tmp;
+
+       /* Match siblings lnode with portid */
+       list_for_each(tmp, &hw->sln_head) {
+               ln = (struct csio_lnode *) tmp;
+               if (ln->portid == portid)
+                       return ln;
+       }
+
+       return NULL;
+}
+
+/*
+ * csio_ln_lookup_by_vnpi - Lookup lnode using given vnp id.
+ * @hw - HW module
+ * @vnpi - vnp index.
+ * Returns - If found, returns lnode matching given vnp id
+ * otherwise returns NULL.
+ */
+static struct csio_lnode *
+csio_ln_lookup_by_vnpi(struct csio_hw *hw, uint32_t vnp_id)
+{
+       struct list_head *tmp1, *tmp2;
+       struct csio_lnode *sln = NULL, *cln = NULL;
+
+       if (list_empty(&hw->sln_head)) {
+               CSIO_INC_STATS(hw, n_lnlkup_miss);
+               return NULL;
+       }
+       /* Traverse sibling lnodes */
+       list_for_each(tmp1, &hw->sln_head) {
+               sln = (struct csio_lnode *) tmp1;
+
+               /* Match sibling lnode */
+               if (sln->vnp_flowid == vnp_id)
+                       return sln;
+
+               if (list_empty(&sln->cln_head))
+                       continue;
+
+               /* Traverse children lnodes */
+               list_for_each(tmp2, &sln->cln_head) {
+                       cln = (struct csio_lnode *) tmp2;
+
+                       if (cln->vnp_flowid == vnp_id)
+                               return cln;
+               }
+       }
+       CSIO_INC_STATS(hw, n_lnlkup_miss);
+       return NULL;
+}
+
+/**
+ * csio_lnode_lookup_by_wwpn - Lookup lnode using given wwpn.
+ * @hw:                HW module.
+ * @wwpn:      WWPN.
+ *
+ * If found, returns lnode matching given wwpn, returns NULL otherwise.
+ */
+struct csio_lnode *
+csio_lnode_lookup_by_wwpn(struct csio_hw *hw, uint8_t *wwpn)
+{
+       struct list_head *tmp1, *tmp2;
+       struct csio_lnode *sln = NULL, *cln = NULL;
+
+       if (list_empty(&hw->sln_head)) {
+               CSIO_INC_STATS(hw, n_lnlkup_miss);
+               return NULL;
+       }
+       /* Traverse sibling lnodes */
+       list_for_each(tmp1, &hw->sln_head) {
+               sln = (struct csio_lnode *) tmp1;
+
+               /* Match sibling lnode */
+               if (!memcmp(csio_ln_wwpn(sln), wwpn, 8))
+                       return sln;
+
+               if (list_empty(&sln->cln_head))
+                       continue;
+
+               /* Traverse children lnodes */
+               list_for_each(tmp2, &sln->cln_head) {
+                       cln = (struct csio_lnode *) tmp2;
+
+                       if (!memcmp(csio_ln_wwpn(cln), wwpn, 8))
+                               return cln;
+               }
+       }
+       return NULL;
+}
+
+/* FDMI */
+static void
+csio_fill_ct_iu(void *buf, uint8_t type, uint8_t sub_type, uint16_t op)
+{
+       struct fc_ct_hdr *cmd = (struct fc_ct_hdr *)buf;
+       cmd->ct_rev = FC_CT_REV;
+       cmd->ct_fs_type = type;
+       cmd->ct_fs_subtype = sub_type;
+       cmd->ct_cmd = htons(op);
+}
+
+static int
+csio_hostname(uint8_t *buf, size_t buf_len)
+{
+       if (snprintf(buf, buf_len, "%s", init_utsname()->nodename) > 0)
+               return 0;
+       return -1;
+}
+
+static int
+csio_osname(uint8_t *buf, size_t buf_len)
+{
+       if (snprintf(buf, buf_len, "%s %s %s",
+                    init_utsname()->sysname,
+                    init_utsname()->release,
+                    init_utsname()->version) > 0)
+               return 0;
+
+       return -1;
+}
+
+static inline void
+csio_append_attrib(uint8_t **ptr, uint16_t type, uint8_t *val, uint16_t len)
+{
+       struct fc_fdmi_attr_entry *ae = (struct fc_fdmi_attr_entry *)*ptr;
+       ae->type = htons(type);
+       len += 4;               /* includes attribute type and length */
+       len = (len + 3) & ~3;   /* should be multiple of 4 bytes */
+       ae->len = htons(len);
+       memcpy(ae->value, val, len);
+       *ptr += len;
+}
+
+/*
+ * csio_ln_fdmi_done - FDMI registeration completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_done(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+       void *cmd;
+       struct csio_lnode *ln = fdmi_req->lnode;
+
+       if (fdmi_req->wr_status != FW_SUCCESS) {
+               csio_ln_dbg(ln, "WR error:%x in processing fdmi rpa cmd\n",
+                           fdmi_req->wr_status);
+               CSIO_INC_STATS(ln, n_fdmi_err);
+       }
+
+       cmd = fdmi_req->dma_buf.vaddr;
+       if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+               csio_ln_dbg(ln, "fdmi rpa cmd rejected reason %x expl %x\n",
+                           csio_ct_reason(cmd), csio_ct_expl(cmd));
+       }
+}
+
+/*
+ * csio_ln_fdmi_rhba_cbfn - RHBA completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+       void *cmd;
+       uint8_t *pld;
+       uint32_t len = 0;
+       __be32 val;
+       __be16 mfs;
+       uint32_t numattrs = 0;
+       struct csio_lnode *ln = fdmi_req->lnode;
+       struct fs_fdmi_attrs *attrib_blk;
+       struct fc_fdmi_port_name *port_name;
+       uint8_t buf[64];
+       uint8_t *fc4_type;
+
+       if (fdmi_req->wr_status != FW_SUCCESS) {
+               csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n",
+                           fdmi_req->wr_status);
+               CSIO_INC_STATS(ln, n_fdmi_err);
+       }
+
+       cmd = fdmi_req->dma_buf.vaddr;
+       if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+               csio_ln_dbg(ln, "fdmi rhba cmd rejected reason %x expl %x\n",
+                           csio_ct_reason(cmd), csio_ct_expl(cmd));
+       }
+
+       if (!csio_is_rnode_ready(fdmi_req->rnode)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               return;
+       }
+
+       /* Prepare CT hdr for RPA cmd */
+       memset(cmd, 0, FC_CT_HDR_LEN);
+       csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_RPA);
+
+       /* Prepare RPA payload */
+       pld = (uint8_t *)csio_ct_get_pld(cmd);
+       port_name = (struct fc_fdmi_port_name *)pld;
+       memcpy(&port_name->portname, csio_ln_wwpn(ln), 8);
+       pld += sizeof(*port_name);
+
+       /* Start appending Port attributes */
+       attrib_blk = (struct fs_fdmi_attrs *)pld;
+       attrib_blk->numattrs = 0;
+       len += sizeof(attrib_blk->numattrs);
+       pld += sizeof(attrib_blk->numattrs);
+
+       fc4_type = &buf[0];
+       memset(fc4_type, 0, FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
+       fc4_type[2] = 1;
+       fc4_type[7] = 1;
+       csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_FC4TYPES,
+                          fc4_type, FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
+       numattrs++;
+       val = htonl(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+       csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
+                          (uint8_t *)&val,
+                          FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
+       numattrs++;
+
+       if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_1G)
+               val = htonl(FC_PORTSPEED_1GBIT);
+       else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G)
+               val = htonl(FC_PORTSPEED_10GBIT);
+       else
+               val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
+       csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
+                          (uint8_t *)&val,
+                          FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
+       numattrs++;
+
+       mfs = ln->ln_sparm.csp.sp_bb_data;
+       csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
+                          (uint8_t *)&mfs, FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
+       numattrs++;
+
+       strcpy(buf, "csiostor");
+       csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf,
+                          (uint16_t)strlen(buf));
+       numattrs++;
+
+       if (!csio_hostname(buf, sizeof(buf))) {
+               csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_HOSTNAME,
+                                  buf, (uint16_t)strlen(buf));
+               numattrs++;
+       }
+       attrib_blk->numattrs = htonl(numattrs);
+       len = (uint32_t)(pld - (uint8_t *)cmd);
+
+       /* Submit FDMI RPA request */
+       spin_lock_irq(&hw->lock);
+       if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done,
+                               FCOE_CT, &fdmi_req->dma_buf, len)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n");
+       }
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_ln_fdmi_dprt_cbfn - DPRT completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+       void *cmd;
+       uint8_t *pld;
+       uint32_t len = 0;
+       uint32_t numattrs = 0;
+       __be32  maxpayload = htonl(65536);
+       struct fc_fdmi_hba_identifier *hbaid;
+       struct csio_lnode *ln = fdmi_req->lnode;
+       struct fc_fdmi_rpl *reg_pl;
+       struct fs_fdmi_attrs *attrib_blk;
+       uint8_t buf[64];
+
+       if (fdmi_req->wr_status != FW_SUCCESS) {
+               csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n",
+                           fdmi_req->wr_status);
+               CSIO_INC_STATS(ln, n_fdmi_err);
+       }
+
+       if (!csio_is_rnode_ready(fdmi_req->rnode)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               return;
+       }
+       cmd = fdmi_req->dma_buf.vaddr;
+       if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+               csio_ln_dbg(ln, "fdmi dprt cmd rejected reason %x expl %x\n",
+                           csio_ct_reason(cmd), csio_ct_expl(cmd));
+       }
+
+       /* Prepare CT hdr for RHBA cmd */
+       memset(cmd, 0, FC_CT_HDR_LEN);
+       csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_RHBA);
+       len = FC_CT_HDR_LEN;
+
+       /* Prepare RHBA payload */
+       pld = (uint8_t *)csio_ct_get_pld(cmd);
+       hbaid = (struct fc_fdmi_hba_identifier *)pld;
+       memcpy(&hbaid->id, csio_ln_wwpn(ln), 8); /* HBA identifer */
+       pld += sizeof(*hbaid);
+
+       /* Register one port per hba */
+       reg_pl = (struct fc_fdmi_rpl *)pld;
+       reg_pl->numport = htonl(1);
+       memcpy(&reg_pl->port[0].portname, csio_ln_wwpn(ln), 8);
+       pld += sizeof(*reg_pl);
+
+       /* Start appending HBA attributes hba */
+       attrib_blk = (struct fs_fdmi_attrs *)pld;
+       attrib_blk->numattrs = 0;
+       len += sizeof(attrib_blk->numattrs);
+       pld += sizeof(attrib_blk->numattrs);
+
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_NODENAME, csio_ln_wwnn(ln),
+                          FC_FDMI_HBA_ATTR_NODENAME_LEN);
+       numattrs++;
+
+       memset(buf, 0, sizeof(buf));
+
+       strcpy(buf, "Chelsio Communications");
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MANUFACTURER, buf,
+                          (uint16_t)strlen(buf));
+       numattrs++;
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_SERIALNUMBER,
+                          hw->vpd.sn, (uint16_t)sizeof(hw->vpd.sn));
+       numattrs++;
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id,
+                          (uint16_t)sizeof(hw->vpd.id));
+       numattrs++;
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
+                          hw->model_desc, (uint16_t)strlen(hw->model_desc));
+       numattrs++;
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_HARDWAREVERSION,
+                          hw->hw_ver, (uint16_t)sizeof(hw->hw_ver));
+       numattrs++;
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
+                          hw->fwrev_str, (uint16_t)strlen(hw->fwrev_str));
+       numattrs++;
+
+       if (!csio_osname(buf, sizeof(buf))) {
+               csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_OSNAMEVERSION,
+                                  buf, (uint16_t)strlen(buf));
+               numattrs++;
+       }
+
+       csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
+                          (uint8_t *)&maxpayload,
+                          FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
+       len = (uint32_t)(pld - (uint8_t *)cmd);
+       numattrs++;
+       attrib_blk->numattrs = htonl(numattrs);
+
+       /* Submit FDMI RHBA request */
+       spin_lock_irq(&hw->lock);
+       if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn,
+                               FCOE_CT, &fdmi_req->dma_buf, len)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n");
+       }
+       spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_ln_fdmi_dhba_cbfn - DHBA completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+       struct csio_lnode *ln = fdmi_req->lnode;
+       void *cmd;
+       struct fc_fdmi_port_name *port_name;
+       uint32_t len;
+
+       if (fdmi_req->wr_status != FW_SUCCESS) {
+               csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n",
+                           fdmi_req->wr_status);
+               CSIO_INC_STATS(ln, n_fdmi_err);
+       }
+
+       if (!csio_is_rnode_ready(fdmi_req->rnode)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               return;
+       }
+       cmd = fdmi_req->dma_buf.vaddr;
+       if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+               csio_ln_dbg(ln, "fdmi dhba cmd rejected reason %x expl %x\n",
+                           csio_ct_reason(cmd), csio_ct_expl(cmd));
+       }
+
+       /* Send FDMI cmd to de-register any Port attributes if registered
+        * before
+        */
+
+       /* Prepare FDMI DPRT cmd */
+       memset(cmd, 0, FC_CT_HDR_LEN);
+       csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_DPRT);
+       len = FC_CT_HDR_LEN;
+       port_name = (struct fc_fdmi_port_name *)csio_ct_get_pld(cmd);
+       memcpy(&port_name->portname, csio_ln_wwpn(ln), 8);
+       len += sizeof(*port_name);
+
+       /* Submit FDMI request */
+       spin_lock_irq(&hw->lock);
+       if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn,
+                               FCOE_CT, &fdmi_req->dma_buf, len)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n");
+       }
+       spin_unlock_irq(&hw->lock);
+}
+
+/**
+ * csio_ln_fdmi_start - Start an FDMI request.
+ * @ln:                lnode
+ * @context:   session context
+ *
+ * Issued with lock held.
+ */
+int
+csio_ln_fdmi_start(struct csio_lnode *ln, void *context)
+{
+       struct csio_ioreq *fdmi_req;
+       struct csio_rnode *fdmi_rn = (struct csio_rnode *)context;
+       void *cmd;
+       struct fc_fdmi_hba_identifier *hbaid;
+       uint32_t len;
+
+       if (!(ln->flags & CSIO_LNF_FDMI_ENABLE))
+               return -EPROTONOSUPPORT;
+
+       if (!csio_is_rnode_ready(fdmi_rn))
+               CSIO_INC_STATS(ln, n_fdmi_err);
+
+       /* Send FDMI cmd to de-register any HBA attributes if registered
+        * before
+        */
+
+       fdmi_req = ln->mgmt_req;
+       fdmi_req->lnode = ln;
+       fdmi_req->rnode = fdmi_rn;
+
+       /* Prepare FDMI DHBA cmd */
+       cmd = fdmi_req->dma_buf.vaddr;
+       memset(cmd, 0, FC_CT_HDR_LEN);
+       csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_DHBA);
+       len = FC_CT_HDR_LEN;
+
+       hbaid = (struct fc_fdmi_hba_identifier *)csio_ct_get_pld(cmd);
+       memcpy(&hbaid->id, csio_ln_wwpn(ln), 8);
+       len += sizeof(*hbaid);
+
+       /* Submit FDMI request */
+       if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dhba_cbfn,
+                                       FCOE_CT, &fdmi_req->dma_buf, len)) {
+               CSIO_INC_STATS(ln, n_fdmi_err);
+               csio_ln_dbg(ln, "Failed to issue fdmi dhba req\n");
+       }
+
+       return 0;
+}
+
+/*
+ * csio_ln_vnp_read_cbfn - vnp read completion handler.
+ * @hw: HW lnode
+ * @cbfn: Completion handler.
+ *
+ * Reads vnp response and updates ln parameters.
+ */
+static void
+csio_ln_vnp_read_cbfn(struct csio_hw *hw, struct csio_mb *mbp)
+{
+       struct csio_lnode *ln = ((struct csio_lnode *)mbp->priv);
+       struct fw_fcoe_vnp_cmd *rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+       struct fc_els_csp *csp;
+       struct fc_els_cssp *clsp;
+       enum fw_retval retval;
+       __be32 nport_id;
+
+       retval = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "FCOE VNP read cmd returned error:0x%x\n", retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return;
+       }
+
+       spin_lock_irq(&hw->lock);
+
+       memcpy(ln->mac, rsp->vnport_mac, sizeof(ln->mac));
+       memcpy(&nport_id, &rsp->vnport_mac[3], sizeof(uint8_t)*3);
+       ln->nport_id = ntohl(nport_id);
+       ln->nport_id = ln->nport_id >> 8;
+
+       /* Update WWNs */
+       /*
+        * This may look like a duplication of what csio_fcoe_enable_link()
+        * does, but is absolutely necessary if the vnpi changes between
+        * a FCOE LINK UP and FCOE LINK DOWN.
+        */
+       memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
+       memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
+
+       /* Copy common sparam */
+       csp = (struct fc_els_csp *)rsp->cmn_srv_parms;
+       ln->ln_sparm.csp.sp_hi_ver = csp->sp_hi_ver;
+       ln->ln_sparm.csp.sp_lo_ver = csp->sp_lo_ver;
+       ln->ln_sparm.csp.sp_bb_cred = csp->sp_bb_cred;
+       ln->ln_sparm.csp.sp_features = csp->sp_features;
+       ln->ln_sparm.csp.sp_bb_data = csp->sp_bb_data;
+       ln->ln_sparm.csp.sp_r_a_tov = csp->sp_r_a_tov;
+       ln->ln_sparm.csp.sp_e_d_tov = csp->sp_e_d_tov;
+
+       /* Copy word 0 & word 1 of class sparam */
+       clsp = (struct fc_els_cssp *)rsp->clsp_word_0_1;
+       ln->ln_sparm.clsp[2].cp_class = clsp->cp_class;
+       ln->ln_sparm.clsp[2].cp_init = clsp->cp_init;
+       ln->ln_sparm.clsp[2].cp_recip = clsp->cp_recip;
+       ln->ln_sparm.clsp[2].cp_rdfs = clsp->cp_rdfs;
+
+       spin_unlock_irq(&hw->lock);
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       /* Send an event to update local attribs */
+       csio_lnode_async_event(ln, CSIO_LN_FC_ATTRIB_UPDATE);
+}
+
+/*
+ * csio_ln_vnp_read - Read vnp params.
+ * @ln: lnode
+ * @cbfn: Completion handler.
+ *
+ * Issued with lock held.
+ */
+static int
+csio_ln_vnp_read(struct csio_lnode *ln,
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct csio_hw *hw = ln->hwp;
+       struct csio_mb  *mbp;
+
+       /* Allocate Mbox request */
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /* Prepare VNP Command */
+       csio_fcoe_vnp_read_init_mb(ln, mbp,
+                                   CSIO_MB_DEFAULT_TMO,
+                                   ln->fcf_flowid,
+                                   ln->vnp_flowid,
+                                   cbfn);
+
+       /* Issue MBOX cmd */
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Failed to issue mbox FCoE VNP command\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * csio_fcoe_enable_link - Enable fcoe link.
+ * @ln: lnode
+ * @enable: enable/disable
+ * Issued with lock held.
+ * Issues mbox cmd to bring up FCOE link on port associated with given ln.
+ */
+static int
+csio_fcoe_enable_link(struct csio_lnode *ln, bool enable)
+{
+       struct csio_hw *hw = ln->hwp;
+       struct csio_mb  *mbp;
+       enum fw_retval retval;
+       uint8_t portid;
+       uint8_t sub_op;
+       struct fw_fcoe_link_cmd *lcmd;
+       int i;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       portid = ln->portid;
+       sub_op = enable ? FCOE_LINK_UP : FCOE_LINK_DOWN;
+
+       csio_dbg(hw, "bringing FCOE LINK %s on Port:%d\n",
+                sub_op ? "UP" : "DOWN", portid);
+
+       csio_write_fcoe_link_cond_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+                                         portid, sub_op, 0, 0, 0, NULL);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "failed to issue FCOE LINK cmd on port[%d]\n",
+                       portid);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       retval = csio_mb_fw_retval(mbp);
+       if (retval != FW_SUCCESS) {
+               csio_err(hw,
+                        "FCOE LINK %s cmd on port[%d] failed with "
+                        "ret:x%x\n", sub_op ? "UP" : "DOWN", portid, retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       if (!enable)
+               goto out;
+
+       lcmd = (struct fw_fcoe_link_cmd *)mbp->mb;
+
+       memcpy(csio_ln_wwnn(ln), lcmd->vnport_wwnn, 8);
+       memcpy(csio_ln_wwpn(ln), lcmd->vnport_wwpn, 8);
+
+       for (i = 0; i < CSIO_MAX_PPORTS; i++)
+               if (hw->pport[i].portid == portid)
+                       memcpy(hw->pport[i].mac, lcmd->phy_mac, 6);
+
+out:
+       mempool_free(mbp, hw->mb_mempool);
+       return 0;
+}
+
+/*
+ * csio_ln_read_fcf_cbfn - Read fcf parameters
+ * @ln: lnode
+ *
+ * read fcf response and Update ln fcf information.
+ */
+static void
+csio_ln_read_fcf_cbfn(struct csio_hw *hw, struct csio_mb *mbp)
+{
+       struct csio_lnode *ln = (struct csio_lnode *)mbp->priv;
+       struct csio_fcf_info    *fcf_info;
+       struct fw_fcoe_fcf_cmd *rsp =
+                               (struct fw_fcoe_fcf_cmd *)(mbp->mb);
+       enum fw_retval retval;
+
+       retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+       if (retval != FW_SUCCESS) {
+               csio_ln_err(ln, "FCOE FCF cmd failed with ret x%x\n",
+                               retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return;
+       }
+
+       spin_lock_irq(&hw->lock);
+       fcf_info = ln->fcfinfo;
+       fcf_info->priority = FW_FCOE_FCF_CMD_PRIORITY_GET(
+                                       ntohs(rsp->priority_pkd));
+       fcf_info->vf_id = ntohs(rsp->vf_id);
+       fcf_info->vlan_id = rsp->vlan_id;
+       fcf_info->max_fcoe_size = ntohs(rsp->max_fcoe_size);
+       fcf_info->fka_adv = be32_to_cpu(rsp->fka_adv);
+       fcf_info->fcfi = FW_FCOE_FCF_CMD_FCFI_GET(ntohl(rsp->op_to_fcfi));
+       fcf_info->fpma = FW_FCOE_FCF_CMD_FPMA_GET(rsp->fpma_to_portid);
+       fcf_info->spma = FW_FCOE_FCF_CMD_SPMA_GET(rsp->fpma_to_portid);
+       fcf_info->login = FW_FCOE_FCF_CMD_LOGIN_GET(rsp->fpma_to_portid);
+       fcf_info->portid = FW_FCOE_FCF_CMD_PORTID_GET(rsp->fpma_to_portid);
+       memcpy(fcf_info->fc_map, rsp->fc_map, sizeof(fcf_info->fc_map));
+       memcpy(fcf_info->mac, rsp->mac, sizeof(fcf_info->mac));
+       memcpy(fcf_info->name_id, rsp->name_id, sizeof(fcf_info->name_id));
+       memcpy(fcf_info->fabric, rsp->fabric, sizeof(fcf_info->fabric));
+       memcpy(fcf_info->spma_mac, rsp->spma_mac, sizeof(fcf_info->spma_mac));
+
+       spin_unlock_irq(&hw->lock);
+
+       mempool_free(mbp, hw->mb_mempool);
+}
+
+/*
+ * csio_ln_read_fcf_entry - Read fcf entry.
+ * @ln: lnode
+ * @cbfn: Completion handler.
+ *
+ * Issued with lock held.
+ */
+static int
+csio_ln_read_fcf_entry(struct csio_lnode *ln,
+                       void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct csio_hw *hw = ln->hwp;
+       struct csio_mb  *mbp;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /* Get FCoE FCF information */
+       csio_fcoe_read_fcf_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+                                     ln->portid, ln->fcf_flowid, cbfn);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "failed to issue FCOE FCF cmd\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * csio_handle_link_up - Logical Linkup event.
+ * @hw - HW module.
+ * @portid - Physical port number
+ * @fcfi - FCF index.
+ * @vnpi - VNP index.
+ * Returns - none.
+ *
+ * This event is received from FW, when virtual link is established between
+ * Physical port[ENode] and FCF. If its new vnpi, then local node object is
+ * created on this FCF and set to [ONLINE] state.
+ * Lnode waits for FW_RDEV_CMD event to be received indicating that
+ * Fabric login is completed and lnode moves to [READY] state.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_handle_link_up(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
+                   uint32_t vnpi)
+{
+       struct csio_lnode *ln = NULL;
+
+       /* Lookup lnode based on vnpi */
+       ln = csio_ln_lookup_by_vnpi(hw, vnpi);
+       if (!ln) {
+               /* Pick lnode based on portid */
+               ln = csio_ln_lookup_by_portid(hw, portid);
+               if (!ln) {
+                       csio_err(hw, "failed to lookup fcoe lnode on port:%d\n",
+                               portid);
+                       CSIO_DB_ASSERT(0);
+                       return;
+               }
+
+               /* Check if lnode has valid vnp flowid */
+               if (ln->vnp_flowid != CSIO_INVALID_IDX) {
+                       /* New VN-Port */
+                       spin_unlock_irq(&hw->lock);
+                       csio_lnode_alloc(hw);
+                       spin_lock_irq(&hw->lock);
+                       if (!ln) {
+                               csio_err(hw,
+                                        "failed to allocate fcoe lnode"
+                                        "for port:%d vnpi:x%x\n",
+                                        portid, vnpi);
+                               CSIO_DB_ASSERT(0);
+                               return;
+                       }
+                       ln->portid = portid;
+               }
+               ln->vnp_flowid = vnpi;
+               ln->dev_num &= ~0xFFFF;
+               ln->dev_num |= vnpi;
+       }
+
+       /*Initialize fcfi */
+       ln->fcf_flowid = fcfi;
+
+       csio_info(hw, "Port:%d - FCOE LINK UP\n", portid);
+
+       CSIO_INC_STATS(ln, n_link_up);
+
+       /* Send LINKUP event to SM */
+       csio_post_event(&ln->sm, CSIO_LNE_LINKUP);
+}
+
+/*
+ * csio_post_event_rns
+ * @ln - FCOE lnode
+ * @evt - Given rnode event
+ * Returns - none
+ *
+ * Posts given rnode event to all FCOE rnodes connected with given Lnode.
+ * This routine is invoked when lnode receives LINK_DOWN/DOWN_LINK/CLOSE
+ * event.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_post_event_rns(struct csio_lnode *ln, enum csio_rn_ev evt)
+{
+       struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+       struct list_head *tmp, *next;
+       struct csio_rnode *rn;
+
+       list_for_each_safe(tmp, next, &rnhead->sm.sm_list) {
+               rn = (struct csio_rnode *) tmp;
+               csio_post_event(&rn->sm, evt);
+       }
+}
+
+/*
+ * csio_cleanup_rns
+ * @ln - FCOE lnode
+ * Returns - none
+ *
+ * Frees all FCOE rnodes connected with given Lnode.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_cleanup_rns(struct csio_lnode *ln)
+{
+       struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+       struct list_head *tmp, *next_rn;
+       struct csio_rnode *rn;
+
+       list_for_each_safe(tmp, next_rn, &rnhead->sm.sm_list) {
+               rn = (struct csio_rnode *) tmp;
+               csio_put_rnode(ln, rn);
+       }
+
+}
+
+/*
+ * csio_post_event_lns
+ * @ln - FCOE lnode
+ * @evt - Given lnode event
+ * Returns - none
+ *
+ * Posts given lnode event to all FCOE lnodes connected with given Lnode.
+ * This routine is invoked when lnode receives LINK_DOWN/DOWN_LINK/CLOSE
+ * event.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_post_event_lns(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+       struct list_head *tmp;
+       struct csio_lnode *cln, *sln;
+
+       /* If NPIV lnode, send evt only to that and return */
+       if (csio_is_npiv_ln(ln)) {
+               csio_post_event(&ln->sm, evt);
+               return;
+       }
+
+       sln = ln;
+       /* Traverse children lnodes list and send evt */
+       list_for_each(tmp, &sln->cln_head) {
+               cln = (struct csio_lnode *) tmp;
+               csio_post_event(&cln->sm, evt);
+       }
+
+       /* Send evt to parent lnode */
+       csio_post_event(&ln->sm, evt);
+}
+
+/*
+ * csio_ln_down - Lcoal nport is down
+ * @ln - FCOE Lnode
+ * Returns - none
+ *
+ * Sends LINK_DOWN events to Lnode and its associated NPIVs lnodes.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_ln_down(struct csio_lnode *ln)
+{
+       csio_post_event_lns(ln, CSIO_LNE_LINK_DOWN);
+}
+
+/*
+ * csio_handle_link_down - Logical Linkdown event.
+ * @hw - HW module.
+ * @portid - Physical port number
+ * @fcfi - FCF index.
+ * @vnpi - VNP index.
+ * Returns - none
+ *
+ * This event is received from FW, when virtual link goes down between
+ * Physical port[ENode] and FCF. Lnode and its associated NPIVs lnode hosted on
+ * this vnpi[VN-Port] will be de-instantiated.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_handle_link_down(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
+                     uint32_t vnpi)
+{
+       struct csio_fcf_info *fp;
+       struct csio_lnode *ln;
+
+       /* Lookup lnode based on vnpi */
+       ln = csio_ln_lookup_by_vnpi(hw, vnpi);
+       if (ln) {
+               fp = ln->fcfinfo;
+               CSIO_INC_STATS(ln, n_link_down);
+
+               /*Warn if linkdown received if lnode is not in ready state */
+               if (!csio_is_lnode_ready(ln)) {
+                       csio_ln_warn(ln,
+                               "warn: FCOE link is already in offline "
+                               "Ignoring Fcoe linkdown event on portid %d\n",
+                                portid);
+                       CSIO_INC_STATS(ln, n_evt_drop);
+                       return;
+               }
+
+               /* Verify portid */
+               if (fp->portid != portid) {
+                       csio_ln_warn(ln,
+                               "warn: FCOE linkdown recv with "
+                               "invalid port %d\n", portid);
+                       CSIO_INC_STATS(ln, n_evt_drop);
+                       return;
+               }
+
+               /* verify fcfi */
+               if (ln->fcf_flowid != fcfi) {
+                       csio_ln_warn(ln,
+                               "warn: FCOE linkdown recv with "
+                               "invalid fcfi x%x\n", fcfi);
+                       CSIO_INC_STATS(ln, n_evt_drop);
+                       return;
+               }
+
+               csio_info(hw, "Port:%d - FCOE LINK DOWN\n", portid);
+
+               /* Send LINK_DOWN event to lnode s/m */
+               csio_ln_down(ln);
+
+               return;
+       } else {
+               csio_warn(hw,
+                         "warn: FCOE linkdown recv with invalid vnpi x%x\n",
+                         vnpi);
+               CSIO_INC_STATS(hw, n_evt_drop);
+       }
+}
+
+/*
+ * csio_is_lnode_ready - Checks FCOE lnode is in ready state.
+ * @ln: Lnode module
+ *
+ * Returns True if FCOE lnode is in ready state.
+ */
+int
+csio_is_lnode_ready(struct csio_lnode *ln)
+{
+       return (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready));
+}
+
+/*****************************************************************************/
+/* START: Lnode SM                                                           */
+/*****************************************************************************/
+/*
+ * csio_lns_uninit - The request in uninit state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "uninit" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_uninit(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct csio_lnode *rln = hw->rln;
+       int rv;
+
+       CSIO_INC_STATS(ln, n_evt_sm[evt]);
+       switch (evt) {
+       case CSIO_LNE_LINKUP:
+               csio_set_state(&ln->sm, csio_lns_online);
+               /* Read FCF only for physical lnode */
+               if (csio_is_phys_ln(ln)) {
+                       rv = csio_ln_read_fcf_entry(ln,
+                                       csio_ln_read_fcf_cbfn);
+                       if (rv != 0) {
+                               /* TODO: Send HW RESET event */
+                               CSIO_INC_STATS(ln, n_err);
+                               break;
+                       }
+
+                       /* Add FCF record */
+                       list_add_tail(&ln->fcfinfo->list, &rln->fcf_lsthead);
+               }
+
+               rv = csio_ln_vnp_read(ln, csio_ln_vnp_read_cbfn);
+               if (rv != 0) {
+                       /* TODO: Send HW RESET event */
+                       CSIO_INC_STATS(ln, n_err);
+               }
+               break;
+
+       case CSIO_LNE_DOWN_LINK:
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                           "unexp ln event %d recv from did:x%x in "
+                           "ln state[uninit].\n", evt, ln->nport_id);
+               CSIO_INC_STATS(ln, n_evt_unexp);
+               break;
+       } /* switch event */
+}
+
+/*
+ * csio_lns_online - The request in online state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "online" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_online(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       CSIO_INC_STATS(ln, n_evt_sm[evt]);
+       switch (evt) {
+       case CSIO_LNE_LINKUP:
+               csio_ln_warn(ln,
+                            "warn: FCOE link is up already "
+                            "Ignoring linkup on port:%d\n", ln->portid);
+               CSIO_INC_STATS(ln, n_evt_drop);
+               break;
+
+       case CSIO_LNE_FAB_INIT_DONE:
+               csio_set_state(&ln->sm, csio_lns_ready);
+
+               spin_unlock_irq(&hw->lock);
+               csio_lnode_async_event(ln, CSIO_LN_FC_LINKUP);
+               spin_lock_irq(&hw->lock);
+
+               break;
+
+       case CSIO_LNE_LINK_DOWN:
+               /* Fall through */
+       case CSIO_LNE_DOWN_LINK:
+               csio_set_state(&ln->sm, csio_lns_uninit);
+               if (csio_is_phys_ln(ln)) {
+                       /* Remove FCF entry */
+                       list_del_init(&ln->fcfinfo->list);
+               }
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                           "unexp ln event %d recv from did:x%x in "
+                           "ln state[uninit].\n", evt, ln->nport_id);
+               CSIO_INC_STATS(ln, n_evt_unexp);
+
+               break;
+       } /* switch event */
+}
+
+/*
+ * csio_lns_ready - The request in ready state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "ready" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_ready(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       CSIO_INC_STATS(ln, n_evt_sm[evt]);
+       switch (evt) {
+       case CSIO_LNE_FAB_INIT_DONE:
+               csio_ln_dbg(ln,
+                           "ignoring event %d recv from did x%x"
+                           "in ln state[ready].\n", evt, ln->nport_id);
+               CSIO_INC_STATS(ln, n_evt_drop);
+               break;
+
+       case CSIO_LNE_LINK_DOWN:
+               csio_set_state(&ln->sm, csio_lns_offline);
+               csio_post_event_rns(ln, CSIO_RNFE_DOWN);
+
+               spin_unlock_irq(&hw->lock);
+               csio_lnode_async_event(ln, CSIO_LN_FC_LINKDOWN);
+               spin_lock_irq(&hw->lock);
+
+               if (csio_is_phys_ln(ln)) {
+                       /* Remove FCF entry */
+                       list_del_init(&ln->fcfinfo->list);
+               }
+               break;
+
+       case CSIO_LNE_DOWN_LINK:
+               csio_set_state(&ln->sm, csio_lns_offline);
+               csio_post_event_rns(ln, CSIO_RNFE_DOWN);
+
+               /* Host need to issue aborts in case if FW has not returned
+                * WRs with status "ABORTED"
+                */
+               spin_unlock_irq(&hw->lock);
+               csio_lnode_async_event(ln, CSIO_LN_FC_LINKDOWN);
+               spin_lock_irq(&hw->lock);
+
+               if (csio_is_phys_ln(ln)) {
+                       /* Remove FCF entry */
+                       list_del_init(&ln->fcfinfo->list);
+               }
+               break;
+
+       case CSIO_LNE_CLOSE:
+               csio_set_state(&ln->sm, csio_lns_uninit);
+               csio_post_event_rns(ln, CSIO_RNFE_CLOSE);
+               break;
+
+       case CSIO_LNE_LOGO:
+               csio_set_state(&ln->sm, csio_lns_offline);
+               csio_post_event_rns(ln, CSIO_RNFE_DOWN);
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                           "unexp ln event %d recv from did:x%x in "
+                           "ln state[uninit].\n", evt, ln->nport_id);
+               CSIO_INC_STATS(ln, n_evt_unexp);
+               CSIO_DB_ASSERT(0);
+               break;
+       } /* switch event */
+}
+
+/*
+ * csio_lns_offline - The request in offline state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "offline" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_offline(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct csio_lnode *rln = hw->rln;
+       int rv;
+
+       CSIO_INC_STATS(ln, n_evt_sm[evt]);
+       switch (evt) {
+       case CSIO_LNE_LINKUP:
+               csio_set_state(&ln->sm, csio_lns_online);
+               /* Read FCF only for physical lnode */
+               if (csio_is_phys_ln(ln)) {
+                       rv = csio_ln_read_fcf_entry(ln,
+                                       csio_ln_read_fcf_cbfn);
+                       if (rv != 0) {
+                               /* TODO: Send HW RESET event */
+                               CSIO_INC_STATS(ln, n_err);
+                               break;
+                       }
+
+                       /* Add FCF record */
+                       list_add_tail(&ln->fcfinfo->list, &rln->fcf_lsthead);
+               }
+
+               rv = csio_ln_vnp_read(ln, csio_ln_vnp_read_cbfn);
+               if (rv != 0) {
+                       /* TODO: Send HW RESET event */
+                       CSIO_INC_STATS(ln, n_err);
+               }
+               break;
+
+       case CSIO_LNE_LINK_DOWN:
+       case CSIO_LNE_DOWN_LINK:
+       case CSIO_LNE_LOGO:
+               csio_ln_dbg(ln,
+                           "ignoring event %d recv from did x%x"
+                           "in ln state[offline].\n", evt, ln->nport_id);
+               CSIO_INC_STATS(ln, n_evt_drop);
+               break;
+
+       case CSIO_LNE_CLOSE:
+               csio_set_state(&ln->sm, csio_lns_uninit);
+               csio_post_event_rns(ln, CSIO_RNFE_CLOSE);
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                           "unexp ln event %d recv from did:x%x in "
+                           "ln state[offline]\n", evt, ln->nport_id);
+               CSIO_INC_STATS(ln, n_evt_unexp);
+               CSIO_DB_ASSERT(0);
+               break;
+       } /* switch event */
+}
+
+/*****************************************************************************/
+/* END: Lnode SM                                                             */
+/*****************************************************************************/
+
+static void
+csio_free_fcfinfo(struct kref *kref)
+{
+       struct csio_fcf_info *fcfinfo = container_of(kref,
+                                               struct csio_fcf_info, kref);
+       kfree(fcfinfo);
+}
+
+/* Helper routines for attributes  */
+/*
+ * csio_lnode_state_to_str - Get current state of FCOE lnode.
+ * @ln - lnode
+ * @str - state of lnode.
+ *
+ */
+void
+csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str)
+{
+       if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_uninit)) {
+               strcpy(str, "UNINIT");
+               return;
+       }
+       if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready)) {
+               strcpy(str, "READY");
+               return;
+       }
+       if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_offline)) {
+               strcpy(str, "OFFLINE");
+               return;
+       }
+       strcpy(str, "UNKNOWN");
+} /* csio_lnode_state_to_str */
+
+
+int
+csio_get_phy_port_stats(struct csio_hw *hw, uint8_t portid,
+                       struct fw_fcoe_port_stats *port_stats)
+{
+       struct csio_mb  *mbp;
+       struct fw_fcoe_port_cmd_params portparams;
+       enum fw_retval retval;
+       int idx;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               csio_err(hw, "FCoE FCF PARAMS command out of memory!\n");
+               return -EINVAL;
+       }
+       portparams.portid = portid;
+
+       for (idx = 1; idx <= 3; idx++) {
+               portparams.idx = (idx-1)*6 + 1;
+               portparams.nstats = 6;
+               if (idx == 3)
+                       portparams.nstats = 4;
+               csio_fcoe_read_portparams_init_mb(hw, mbp, CSIO_MB_DEFAULT_TMO,
+                                                       &portparams, NULL);
+               if (csio_mb_issue(hw, mbp)) {
+                       csio_err(hw, "Issue of FCoE port params failed!\n");
+                       mempool_free(mbp, hw->mb_mempool);
+                       return -EINVAL;
+               }
+               csio_mb_process_portparams_rsp(hw, mbp, &retval,
+                                               &portparams, port_stats);
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+       return 0;
+}
+
+/*
+ * csio_ln_mgmt_wr_handler -Mgmt Work Request handler.
+ * @wr - WR.
+ * @len - WR len.
+ * This handler is invoked when an outstanding mgmt WR is completed.
+ * Its invoked in the context of FW event worker thread for every
+ * mgmt event received.
+ * Return - none.
+ */
+
+static void
+csio_ln_mgmt_wr_handler(struct csio_hw *hw, void *wr, uint32_t len)
+{
+       struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+       struct csio_ioreq *io_req = NULL;
+       struct fw_fcoe_els_ct_wr *wr_cmd;
+
+
+       wr_cmd = (struct fw_fcoe_els_ct_wr *) wr;
+
+       if (len < sizeof(struct fw_fcoe_els_ct_wr)) {
+               csio_err(mgmtm->hw,
+                        "Invalid ELS CT WR length recvd, len:%x\n", len);
+               mgmtm->stats.n_err++;
+               return;
+       }
+
+       io_req = (struct csio_ioreq *) ((uintptr_t) wr_cmd->cookie);
+       io_req->wr_status = csio_wr_status(wr_cmd);
+
+       /* lookup ioreq exists in our active Q */
+       spin_lock_irq(&hw->lock);
+       if (csio_mgmt_req_lookup(mgmtm, io_req) != 0) {
+               csio_err(mgmtm->hw,
+                       "Error- Invalid IO handle recv in WR. handle: %p\n",
+                       io_req);
+               mgmtm->stats.n_err++;
+               spin_unlock_irq(&hw->lock);
+               return;
+       }
+
+       mgmtm = csio_hw_to_mgmtm(hw);
+
+       /* Dequeue from active queue */
+       list_del_init(&io_req->sm.sm_list);
+       mgmtm->stats.n_active--;
+       spin_unlock_irq(&hw->lock);
+
+       /* io_req will be freed by completion handler */
+       if (io_req->io_cbfn)
+               io_req->io_cbfn(hw, io_req);
+}
+
+/**
+ * csio_fcoe_fwevt_handler - Event handler for Firmware FCoE events.
+ * @hw:                HW module
+ * @cpl_op:    CPL opcode
+ * @cmd:       FW cmd/WR.
+ *
+ * Process received FCoE cmd/WR event from FW.
+ */
+void
+csio_fcoe_fwevt_handler(struct csio_hw *hw, __u8 cpl_op, __be64 *cmd)
+{
+       struct csio_lnode *ln;
+       struct csio_rnode *rn;
+       uint8_t portid, opcode = *(uint8_t *)cmd;
+       struct fw_fcoe_link_cmd *lcmd;
+       struct fw_wr_hdr *wr;
+       struct fw_rdev_wr *rdev_wr;
+       enum fw_fcoe_link_status lstatus;
+       uint32_t fcfi, rdev_flowid, vnpi;
+       enum csio_ln_ev evt;
+
+       if (cpl_op == CPL_FW6_MSG && opcode == FW_FCOE_LINK_CMD) {
+
+               lcmd = (struct fw_fcoe_link_cmd *)cmd;
+               lstatus = lcmd->lstatus;
+               portid = FW_FCOE_LINK_CMD_PORTID_GET(
+                                       ntohl(lcmd->op_to_portid));
+               fcfi = FW_FCOE_LINK_CMD_FCFI_GET(ntohl(lcmd->sub_opcode_fcfi));
+               vnpi = FW_FCOE_LINK_CMD_VNPI_GET(ntohl(lcmd->vnpi_pkd));
+
+               if (lstatus == FCOE_LINKUP) {
+
+                       /* HW lock here */
+                       spin_lock_irq(&hw->lock);
+                       csio_handle_link_up(hw, portid, fcfi, vnpi);
+                       spin_unlock_irq(&hw->lock);
+                       /* HW un lock here */
+
+               } else if (lstatus == FCOE_LINKDOWN) {
+
+                       /* HW lock here */
+                       spin_lock_irq(&hw->lock);
+                       csio_handle_link_down(hw, portid, fcfi, vnpi);
+                       spin_unlock_irq(&hw->lock);
+                       /* HW un lock here */
+               } else {
+                       csio_warn(hw, "Unexpected FCOE LINK status:0x%x\n",
+                                 lcmd->lstatus);
+                       CSIO_INC_STATS(hw, n_cpl_unexp);
+               }
+       } else if (cpl_op == CPL_FW6_PLD) {
+               wr = (struct fw_wr_hdr *) (cmd + 4);
+               if (FW_WR_OP_GET(be32_to_cpu(wr->hi))
+                       == FW_RDEV_WR) {
+
+                       rdev_wr = (struct fw_rdev_wr *) (cmd + 4);
+
+                       rdev_flowid = FW_RDEV_WR_FLOWID_GET(
+                                       ntohl(rdev_wr->alloc_to_len16));
+                       vnpi = FW_RDEV_WR_ASSOC_FLOWID_GET(
+                                   ntohl(rdev_wr->flags_to_assoc_flowid));
+
+                       csio_dbg(hw,
+                               "FW_RDEV_WR: flowid:x%x ev_cause:x%x "
+                               "vnpi:0x%x\n", rdev_flowid,
+                               rdev_wr->event_cause, vnpi);
+
+                       if (rdev_wr->protocol != PROT_FCOE) {
+                               csio_err(hw,
+                                       "FW_RDEV_WR: invalid proto:x%x "
+                                       "received with flowid:x%x\n",
+                                       rdev_wr->protocol,
+                                       rdev_flowid);
+                               CSIO_INC_STATS(hw, n_evt_drop);
+                               return;
+                       }
+
+                       /* HW lock here */
+                       spin_lock_irq(&hw->lock);
+                       ln = csio_ln_lookup_by_vnpi(hw, vnpi);
+                       if (!ln) {
+                               csio_err(hw,
+                                       "FW_DEV_WR: invalid vnpi:x%x received "
+                                       "with flowid:x%x\n", vnpi, rdev_flowid);
+                               CSIO_INC_STATS(hw, n_evt_drop);
+                               goto out_pld;
+                       }
+
+                       rn = csio_confirm_rnode(ln, rdev_flowid,
+                                       &rdev_wr->u.fcoe_rdev);
+                       if (!rn) {
+                               csio_ln_dbg(ln,
+                                       "Failed to confirm rnode "
+                                       "for flowid:x%x\n", rdev_flowid);
+                               CSIO_INC_STATS(hw, n_evt_drop);
+                               goto out_pld;
+                       }
+
+                       /* save previous event for debugging */
+                       ln->prev_evt = ln->cur_evt;
+                       ln->cur_evt = rdev_wr->event_cause;
+                       CSIO_INC_STATS(ln, n_evt_fw[rdev_wr->event_cause]);
+
+                       /* Translate all the fabric events to lnode SM events */
+                       evt = CSIO_FWE_TO_LNE(rdev_wr->event_cause);
+                       if (evt) {
+                               csio_ln_dbg(ln,
+                                       "Posting event to lnode event:%d "
+                                       "cause:%d flowid:x%x\n", evt,
+                                       rdev_wr->event_cause, rdev_flowid);
+                               csio_post_event(&ln->sm, evt);
+                       }
+
+                       /* Handover event to rn SM here. */
+                       csio_rnode_fwevt_handler(rn, rdev_wr->event_cause);
+out_pld:
+                       spin_unlock_irq(&hw->lock);
+                       return;
+               } else {
+                       csio_warn(hw, "unexpected WR op(0x%x) recv\n",
+                               FW_WR_OP_GET(be32_to_cpu((wr->hi))));
+                       CSIO_INC_STATS(hw, n_cpl_unexp);
+               }
+       } else if (cpl_op == CPL_FW6_MSG) {
+               wr = (struct fw_wr_hdr *) (cmd);
+               if (FW_WR_OP_GET(be32_to_cpu(wr->hi)) == FW_FCOE_ELS_CT_WR) {
+                       csio_ln_mgmt_wr_handler(hw, wr,
+                                       sizeof(struct fw_fcoe_els_ct_wr));
+               } else {
+                       csio_warn(hw, "unexpected WR op(0x%x) recv\n",
+                               FW_WR_OP_GET(be32_to_cpu((wr->hi))));
+                       CSIO_INC_STATS(hw, n_cpl_unexp);
+               }
+       } else {
+               csio_warn(hw, "unexpected CPL op(0x%x) recv\n", opcode);
+               CSIO_INC_STATS(hw, n_cpl_unexp);
+       }
+}
+
+/**
+ * csio_lnode_start - Kickstart lnode discovery.
+ * @ln:                lnode
+ *
+ * This routine kickstarts the discovery by issuing an FCOE_LINK (up) command.
+ */
+int
+csio_lnode_start(struct csio_lnode *ln)
+{
+       int rv = 0;
+       if (csio_is_phys_ln(ln) && !(ln->flags & CSIO_LNF_LINK_ENABLE)) {
+               rv = csio_fcoe_enable_link(ln, 1);
+               ln->flags |= CSIO_LNF_LINK_ENABLE;
+       }
+
+       return rv;
+}
+
+/**
+ * csio_lnode_stop - Stop the lnode.
+ * @ln:                lnode
+ *
+ * This routine is invoked by HW module to stop lnode and its associated NPIV
+ * lnodes.
+ */
+void
+csio_lnode_stop(struct csio_lnode *ln)
+{
+       csio_post_event_lns(ln, CSIO_LNE_DOWN_LINK);
+       if (csio_is_phys_ln(ln) && (ln->flags & CSIO_LNF_LINK_ENABLE)) {
+               csio_fcoe_enable_link(ln, 0);
+               ln->flags &= ~CSIO_LNF_LINK_ENABLE;
+       }
+       csio_ln_dbg(ln, "stopping ln :%p\n", ln);
+}
+
+/**
+ * csio_lnode_close - Close an lnode.
+ * @ln:                lnode
+ *
+ * This routine is invoked by HW module to close an lnode and its
+ * associated NPIV lnodes. Lnode and its associated NPIV lnodes are
+ * set to uninitialized state.
+ */
+void
+csio_lnode_close(struct csio_lnode *ln)
+{
+       csio_post_event_lns(ln, CSIO_LNE_CLOSE);
+       if (csio_is_phys_ln(ln))
+               ln->vnp_flowid = CSIO_INVALID_IDX;
+
+       csio_ln_dbg(ln, "closed ln :%p\n", ln);
+}
+
+/*
+ * csio_ln_prep_ecwr - Prepare ELS/CT WR.
+ * @io_req - IO request.
+ * @wr_len - WR len
+ * @immd_len - WR immediate data
+ * @sub_op - Sub opcode
+ * @sid - source portid.
+ * @did - destination portid
+ * @flow_id - flowid
+ * @fw_wr - ELS/CT WR to be prepared.
+ * Returns: 0 - on success
+ */
+static int
+csio_ln_prep_ecwr(struct csio_ioreq *io_req, uint32_t wr_len,
+                     uint32_t immd_len, uint8_t sub_op, uint32_t sid,
+                     uint32_t did, uint32_t flow_id, uint8_t *fw_wr)
+{
+       struct fw_fcoe_els_ct_wr *wr;
+       __be32 port_id;
+
+       wr  = (struct fw_fcoe_els_ct_wr *)fw_wr;
+       wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_FCOE_ELS_CT_WR) |
+                                    FW_FCOE_ELS_CT_WR_IMMDLEN(immd_len));
+
+       wr_len =  DIV_ROUND_UP(wr_len, 16);
+       wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(flow_id) |
+                                         FW_WR_LEN16(wr_len));
+       wr->els_ct_type = sub_op;
+       wr->ctl_pri = 0;
+       wr->cp_en_class = 0;
+       wr->cookie = io_req->fw_handle;
+       wr->iqid = cpu_to_be16(csio_q_physiqid(
+                                       io_req->lnode->hwp, io_req->iq_idx));
+       wr->fl_to_sp =  FW_FCOE_ELS_CT_WR_SP(1);
+       wr->tmo_val = (uint8_t) io_req->tmo;
+       port_id = htonl(sid);
+       memcpy(wr->l_id, PORT_ID_PTR(port_id), 3);
+       port_id = htonl(did);
+       memcpy(wr->r_id, PORT_ID_PTR(port_id), 3);
+
+       /* Prepare RSP SGL */
+       wr->rsp_dmalen = cpu_to_be32(io_req->dma_buf.len);
+       wr->rsp_dmaaddr = cpu_to_be64(io_req->dma_buf.paddr);
+       return 0;
+}
+
+/*
+ * csio_ln_mgmt_submit_wr - Post elsct work request.
+ * @mgmtm - mgmtm
+ * @io_req - io request.
+ * @sub_op - ELS or CT request type
+ * @pld - Dma Payload buffer
+ * @pld_len - Payload len
+ * Prepares ELSCT Work request and sents it to FW.
+ * Returns: 0 - on success
+ */
+static int
+csio_ln_mgmt_submit_wr(struct csio_mgmtm *mgmtm, struct csio_ioreq *io_req,
+               uint8_t sub_op, struct csio_dma_buf *pld,
+               uint32_t pld_len)
+{
+       struct csio_wr_pair wrp;
+       struct csio_lnode *ln = io_req->lnode;
+       struct csio_rnode *rn = io_req->rnode;
+       struct  csio_hw *hw = mgmtm->hw;
+       uint8_t fw_wr[64];
+       struct ulptx_sgl dsgl;
+       uint32_t wr_size = 0;
+       uint8_t im_len = 0;
+       uint32_t wr_off = 0;
+
+       int ret = 0;
+
+       /* Calculate WR Size for this ELS REQ */
+       wr_size = sizeof(struct fw_fcoe_els_ct_wr);
+
+       /* Send as immediate data if pld < 256 */
+       if (pld_len < 256) {
+               wr_size += ALIGN(pld_len, 8);
+               im_len = (uint8_t)pld_len;
+       } else
+               wr_size += sizeof(struct ulptx_sgl);
+
+       /* Roundup WR size in units of 16 bytes */
+       wr_size = ALIGN(wr_size, 16);
+
+       /* Get WR to send ELS REQ */
+       ret = csio_wr_get(hw, mgmtm->eq_idx, wr_size, &wrp);
+       if (ret != 0) {
+               csio_err(hw, "Failed to get WR for ec_req %p ret:%d\n",
+                       io_req, ret);
+               return ret;
+       }
+
+       /* Prepare Generic WR used by all ELS/CT cmd */
+       csio_ln_prep_ecwr(io_req, wr_size, im_len, sub_op,
+                               ln->nport_id, rn->nport_id,
+                               csio_rn_flowid(rn),
+                               &fw_wr[0]);
+
+       /* Copy ELS/CT WR CMD */
+       csio_wr_copy_to_wrp(&fw_wr[0], &wrp, wr_off,
+                       sizeof(struct fw_fcoe_els_ct_wr));
+       wr_off += sizeof(struct fw_fcoe_els_ct_wr);
+
+       /* Copy payload to Immediate section of WR */
+       if (im_len)
+               csio_wr_copy_to_wrp(pld->vaddr, &wrp, wr_off, im_len);
+       else {
+               /* Program DSGL to dma payload */
+               dsgl.cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) |
+                                       ULPTX_MORE | ULPTX_NSGE(1));
+               dsgl.len0 = cpu_to_be32(pld_len);
+               dsgl.addr0 = cpu_to_be64(pld->paddr);
+               csio_wr_copy_to_wrp(&dsgl, &wrp, ALIGN(wr_off, 8),
+                                  sizeof(struct ulptx_sgl));
+       }
+
+       /* Issue work request to xmit ELS/CT req to FW */
+       csio_wr_issue(mgmtm->hw, mgmtm->eq_idx, false);
+       return ret;
+}
+
+/*
+ * csio_ln_mgmt_submit_req - Submit FCOE Mgmt request.
+ * @io_req - IO Request
+ * @io_cbfn - Completion handler.
+ * @req_type - ELS or CT request type
+ * @pld - Dma Payload buffer
+ * @pld_len - Payload len
+ *
+ *
+ * This API used submit managment ELS/CT request.
+ * This called with hw lock held
+ * Returns: 0 - on success
+ *         -ENOMEM     - on error.
+ */
+static int
+csio_ln_mgmt_submit_req(struct csio_ioreq *io_req,
+               void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *),
+               enum fcoe_cmn_type req_type, struct csio_dma_buf *pld,
+               uint32_t pld_len)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(io_req->lnode);
+       struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+       int rv;
+
+       io_req->io_cbfn = io_cbfn;      /* Upper layer callback handler */
+       io_req->fw_handle = (uintptr_t) (io_req);
+       io_req->eq_idx = mgmtm->eq_idx;
+       io_req->iq_idx = mgmtm->iq_idx;
+
+       rv = csio_ln_mgmt_submit_wr(mgmtm, io_req, req_type, pld, pld_len);
+       if (rv == 0) {
+               list_add_tail(&io_req->sm.sm_list, &mgmtm->active_q);
+               mgmtm->stats.n_active++;
+       }
+       return rv;
+}
+
+/*
+ * csio_ln_fdmi_init - FDMI Init entry point.
+ * @ln: lnode
+ */
+static int
+csio_ln_fdmi_init(struct csio_lnode *ln)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct csio_dma_buf     *dma_buf;
+
+       /* Allocate MGMT request required for FDMI */
+       ln->mgmt_req = kzalloc(sizeof(struct csio_ioreq), GFP_KERNEL);
+       if (!ln->mgmt_req) {
+               csio_ln_err(ln, "Failed to alloc ioreq for FDMI\n");
+               CSIO_INC_STATS(hw, n_err_nomem);
+               return -ENOMEM;
+       }
+
+       /* Allocate Dma buffers for FDMI response Payload */
+       dma_buf = &ln->mgmt_req->dma_buf;
+       dma_buf->len = 2048;
+       dma_buf->vaddr = pci_alloc_consistent(hw->pdev, dma_buf->len,
+                                               &dma_buf->paddr);
+       if (!dma_buf->vaddr) {
+               csio_err(hw, "Failed to alloc DMA buffer for FDMI!\n");
+               kfree(ln->mgmt_req);
+               ln->mgmt_req = NULL;
+               return -ENOMEM;
+       }
+
+       ln->flags |= CSIO_LNF_FDMI_ENABLE;
+       return 0;
+}
+
+/*
+ * csio_ln_fdmi_exit - FDMI exit entry point.
+ * @ln: lnode
+ */
+static int
+csio_ln_fdmi_exit(struct csio_lnode *ln)
+{
+       struct csio_dma_buf *dma_buf;
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       if (!ln->mgmt_req)
+               return 0;
+
+       dma_buf = &ln->mgmt_req->dma_buf;
+       if (dma_buf->vaddr)
+               pci_free_consistent(hw->pdev, dma_buf->len, dma_buf->vaddr,
+                                   dma_buf->paddr);
+
+       kfree(ln->mgmt_req);
+       return 0;
+}
+
+int
+csio_scan_done(struct csio_lnode *ln, unsigned long ticks,
+               unsigned long time, unsigned long max_scan_ticks,
+               unsigned long delta_scan_ticks)
+{
+       int rv = 0;
+
+       if (time >= max_scan_ticks)
+               return 1;
+
+       if (!ln->tgt_scan_tick)
+               ln->tgt_scan_tick = ticks;
+
+       if (((ticks - ln->tgt_scan_tick) >= delta_scan_ticks)) {
+               if (!ln->last_scan_ntgts)
+                       ln->last_scan_ntgts = ln->n_scsi_tgts;
+               else {
+                       if (ln->last_scan_ntgts == ln->n_scsi_tgts)
+                               return 1;
+
+                       ln->last_scan_ntgts = ln->n_scsi_tgts;
+               }
+               ln->tgt_scan_tick = ticks;
+       }
+       return rv;
+}
+
+/*
+ * csio_notify_lnodes:
+ * @hw: HW module
+ * @note: Notification
+ *
+ * Called from the HW SM to fan out notifications to the
+ * Lnode SM. Since the HW SM is entered with lock held,
+ * there is no need to hold locks here.
+ *
+ */
+void
+csio_notify_lnodes(struct csio_hw *hw, enum csio_ln_notify note)
+{
+       struct list_head *tmp;
+       struct csio_lnode *ln;
+
+       csio_dbg(hw, "Notifying all nodes of event %d\n", note);
+
+       /* Traverse children lnodes list and send evt */
+       list_for_each(tmp, &hw->sln_head) {
+               ln = (struct csio_lnode *) tmp;
+
+               switch (note) {
+               case CSIO_LN_NOTIFY_HWREADY:
+                       csio_lnode_start(ln);
+                       break;
+
+               case CSIO_LN_NOTIFY_HWRESET:
+               case CSIO_LN_NOTIFY_HWREMOVE:
+                       csio_lnode_close(ln);
+                       break;
+
+               case CSIO_LN_NOTIFY_HWSTOP:
+                       csio_lnode_stop(ln);
+                       break;
+
+               default:
+                       break;
+
+               }
+       }
+}
+
+/*
+ * csio_disable_lnodes:
+ * @hw: HW module
+ * @portid:port id
+ * @disable: disable/enable flag.
+ * If disable=1, disables all lnode hosted on given physical port.
+ * otherwise enables all the lnodes on given phsysical port.
+ * This routine need to called with hw lock held.
+ */
+void
+csio_disable_lnodes(struct csio_hw *hw, uint8_t portid, bool disable)
+{
+       struct list_head *tmp;
+       struct csio_lnode *ln;
+
+       csio_dbg(hw, "Notifying event to all nodes of port:%d\n", portid);
+
+       /* Traverse sibling lnodes list and send evt */
+       list_for_each(tmp, &hw->sln_head) {
+               ln = (struct csio_lnode *) tmp;
+               if (ln->portid != portid)
+                       continue;
+
+               if (disable)
+                       csio_lnode_stop(ln);
+               else
+                       csio_lnode_start(ln);
+       }
+}
+
+/*
+ * csio_ln_init - Initialize an lnode.
+ * @ln:                lnode
+ *
+ */
+static int
+csio_ln_init(struct csio_lnode *ln)
+{
+       int rv = -EINVAL;
+       struct csio_lnode *rln, *pln;
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       csio_init_state(&ln->sm, csio_lns_uninit);
+       ln->vnp_flowid = CSIO_INVALID_IDX;
+       ln->fcf_flowid = CSIO_INVALID_IDX;
+
+       if (csio_is_root_ln(ln)) {
+
+               /* This is the lnode used during initialization */
+
+               ln->fcfinfo = kzalloc(sizeof(struct csio_fcf_info), GFP_KERNEL);
+               if (!ln->fcfinfo) {
+                       csio_ln_err(ln, "Failed to alloc FCF record\n");
+                       CSIO_INC_STATS(hw, n_err_nomem);
+                       goto err;
+               }
+
+               INIT_LIST_HEAD(&ln->fcf_lsthead);
+               kref_init(&ln->fcfinfo->kref);
+
+               if (csio_fdmi_enable && csio_ln_fdmi_init(ln))
+                       goto err;
+
+       } else { /* Either a non-root physical or a virtual lnode */
+
+               /*
+                * THe rest is common for non-root physical and NPIV lnodes.
+                * Just get references to all other modules
+                */
+               rln = csio_root_lnode(ln);
+
+               if (csio_is_npiv_ln(ln)) {
+                       /* NPIV */
+                       pln = csio_parent_lnode(ln);
+                       kref_get(&pln->fcfinfo->kref);
+                       ln->fcfinfo = pln->fcfinfo;
+               } else {
+                       /* Another non-root physical lnode (FCF) */
+                       ln->fcfinfo = kzalloc(sizeof(struct csio_fcf_info),
+                                                               GFP_KERNEL);
+                       if (!ln->fcfinfo) {
+                               csio_ln_err(ln, "Failed to alloc FCF info\n");
+                               CSIO_INC_STATS(hw, n_err_nomem);
+                               goto err;
+                       }
+
+                       kref_init(&ln->fcfinfo->kref);
+
+                       if (csio_fdmi_enable && csio_ln_fdmi_init(ln))
+                               goto err;
+               }
+
+       } /* if (!csio_is_root_ln(ln)) */
+
+       return 0;
+err:
+       return rv;
+}
+
+static void
+csio_ln_exit(struct csio_lnode *ln)
+{
+       struct csio_lnode *pln;
+
+       csio_cleanup_rns(ln);
+       if (csio_is_npiv_ln(ln)) {
+               pln = csio_parent_lnode(ln);
+               kref_put(&pln->fcfinfo->kref, csio_free_fcfinfo);
+       } else {
+               kref_put(&ln->fcfinfo->kref, csio_free_fcfinfo);
+               if (csio_fdmi_enable)
+                       csio_ln_fdmi_exit(ln);
+       }
+       ln->fcfinfo = NULL;
+}
+
+/**
+ * csio_lnode_init - Initialize the members of an lnode.
+ * @ln:                lnode
+ *
+ */
+int
+csio_lnode_init(struct csio_lnode *ln, struct csio_hw *hw,
+               struct csio_lnode *pln)
+{
+       int rv = -EINVAL;
+
+       /* Link this lnode to hw */
+       csio_lnode_to_hw(ln)    = hw;
+
+       /* Link child to parent if child lnode */
+       if (pln)
+               ln->pln = pln;
+       else
+               ln->pln = NULL;
+
+       /* Initialize scsi_tgt and timers to zero */
+       ln->n_scsi_tgts = 0;
+       ln->last_scan_ntgts = 0;
+       ln->tgt_scan_tick = 0;
+
+       /* Initialize rnode list */
+       INIT_LIST_HEAD(&ln->rnhead);
+       INIT_LIST_HEAD(&ln->cln_head);
+
+       /* Initialize log level for debug */
+       ln->params.log_level    = hw->params.log_level;
+
+       if (csio_ln_init(ln))
+               goto err;
+
+       /* Add lnode to list of sibling or children lnodes */
+       spin_lock_irq(&hw->lock);
+       list_add_tail(&ln->sm.sm_list, pln ? &pln->cln_head : &hw->sln_head);
+       if (pln)
+               pln->num_vports++;
+       spin_unlock_irq(&hw->lock);
+
+       hw->num_lns++;
+
+       return 0;
+err:
+       csio_lnode_to_hw(ln) = NULL;
+       return rv;
+}
+
+/**
+ * csio_lnode_exit - De-instantiate an lnode.
+ * @ln:                lnode
+ *
+ */
+void
+csio_lnode_exit(struct csio_lnode *ln)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       csio_ln_exit(ln);
+
+       /* Remove this lnode from hw->sln_head */
+       spin_lock_irq(&hw->lock);
+
+       list_del_init(&ln->sm.sm_list);
+
+       /* If it is children lnode, decrement the
+        * counter in its parent lnode
+        */
+       if (ln->pln)
+               ln->pln->num_vports--;
+
+       /* Update root lnode pointer */
+       if (list_empty(&hw->sln_head))
+               hw->rln = NULL;
+       else
+               hw->rln = (struct csio_lnode *)csio_list_next(&hw->sln_head);
+
+       spin_unlock_irq(&hw->lock);
+
+       csio_lnode_to_hw(ln)    = NULL;
+       hw->num_lns--;
+}
diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h
new file mode 100644 (file)
index 0000000..8d84988
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_LNODE_H__
+#define __CSIO_LNODE_H__
+
+#include <linux/kref.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <scsi/fc/fc_els.h>
+
+
+#include "csio_defs.h"
+#include "csio_hw.h"
+
+#define CSIO_FCOE_MAX_NPIV     128
+#define CSIO_FCOE_MAX_RNODES   2048
+
+/* FDMI port attribute unknown speed */
+#define CSIO_HBA_PORTSPEED_UNKNOWN     0x8000
+
+extern int csio_fcoe_rnodes;
+extern int csio_fdmi_enable;
+
+/* State machine evets */
+enum csio_ln_ev {
+       CSIO_LNE_NONE = (uint32_t)0,
+       CSIO_LNE_LINKUP,
+       CSIO_LNE_FAB_INIT_DONE,
+       CSIO_LNE_LINK_DOWN,
+       CSIO_LNE_DOWN_LINK,
+       CSIO_LNE_LOGO,
+       CSIO_LNE_CLOSE,
+       CSIO_LNE_MAX_EVENT,
+};
+
+
+struct csio_fcf_info {
+       struct list_head        list;
+       uint8_t                 priority;
+       uint8_t                 mac[6];
+       uint8_t                 name_id[8];
+       uint8_t                 fabric[8];
+       uint16_t                vf_id;
+       uint8_t                 vlan_id;
+       uint16_t                max_fcoe_size;
+       uint8_t                 fc_map[3];
+       uint32_t                fka_adv;
+       uint32_t                fcfi;
+       uint8_t                 get_next:1;
+       uint8_t                 link_aff:1;
+       uint8_t                 fpma:1;
+       uint8_t                 spma:1;
+       uint8_t                 login:1;
+       uint8_t                 portid;
+       uint8_t                 spma_mac[6];
+       struct kref             kref;
+};
+
+/* Defines for flags */
+#define        CSIO_LNF_FIPSUPP                0x00000001      /* Fip Supported */
+#define        CSIO_LNF_NPIVSUPP               0x00000002      /* NPIV supported */
+#define CSIO_LNF_LINK_ENABLE           0x00000004      /* Link enabled */
+#define        CSIO_LNF_FDMI_ENABLE            0x00000008      /* FDMI support */
+
+/* Transport events */
+enum csio_ln_fc_evt {
+       CSIO_LN_FC_LINKUP = 1,
+       CSIO_LN_FC_LINKDOWN,
+       CSIO_LN_FC_RSCN,
+       CSIO_LN_FC_ATTRIB_UPDATE,
+};
+
+/* Lnode stats */
+struct csio_lnode_stats {
+       uint32_t        n_link_up;      /* Link down */
+       uint32_t        n_link_down;    /* Link up */
+       uint32_t        n_err;          /* error */
+       uint32_t        n_err_nomem;    /* memory not available */
+       uint32_t        n_inval_parm;   /* Invalid parameters */
+       uint32_t        n_evt_unexp;    /* unexpected event */
+       uint32_t        n_evt_drop;     /* dropped event */
+       uint32_t        n_rnode_match;  /* matched rnode */
+       uint32_t        n_dev_loss_tmo; /* Device loss timeout */
+       uint32_t        n_fdmi_err;     /* fdmi err */
+       uint32_t        n_evt_fw[RSCN_DEV_LOST];        /* fw events */
+       enum csio_ln_ev n_evt_sm[CSIO_LNE_MAX_EVENT];   /* State m/c events */
+       uint32_t        n_rnode_alloc;  /* rnode allocated */
+       uint32_t        n_rnode_free;   /* rnode freed */
+       uint32_t        n_rnode_nomem;  /* rnode alloc failure */
+       uint32_t        n_input_requests; /* Input Requests */
+       uint32_t        n_output_requests; /* Output Requests */
+       uint32_t        n_control_requests; /* Control Requests */
+       uint32_t        n_input_bytes; /* Input Bytes */
+       uint32_t        n_output_bytes; /* Output Bytes */
+       uint32_t        rsvd1;
+};
+
+/* Common Lnode params */
+struct csio_lnode_params {
+       uint32_t        ra_tov;
+       uint32_t        fcfi;
+       uint32_t        log_level;      /* Module level for debugging */
+};
+
+struct csio_service_parms {
+       struct fc_els_csp       csp;            /* Common service parms */
+       uint8_t                 wwpn[8];        /* WWPN */
+       uint8_t                 wwnn[8];        /* WWNN */
+       struct fc_els_cssp      clsp[4];        /* Class service params */
+       uint8_t                 vvl[16];        /* Vendor version level */
+};
+
+/* Lnode */
+struct csio_lnode {
+       struct csio_sm          sm;             /* State machine + sibling
+                                                * lnode list.
+                                                */
+       struct csio_hw          *hwp;           /* Pointer to the HW module */
+       uint8_t                 portid;         /* Port ID */
+       uint8_t                 rsvd1;
+       uint16_t                rsvd2;
+       uint32_t                dev_num;        /* Device number */
+       uint32_t                flags;          /* Flags */
+       struct list_head        fcf_lsthead;    /* FCF entries */
+       struct csio_fcf_info    *fcfinfo;       /* FCF in use */
+       struct csio_ioreq       *mgmt_req;      /* MGMT request */
+
+       /* FCoE identifiers */
+       uint8_t                 mac[6];
+       uint32_t                nport_id;
+       struct csio_service_parms ln_sparm;     /* Service parms */
+
+       /* Firmware identifiers */
+       uint32_t                fcf_flowid;     /*fcf flowid */
+       uint32_t                vnp_flowid;
+       uint16_t                ssn_cnt;        /* Registered Session */
+       uint8_t                 cur_evt;        /* Current event */
+       uint8_t                 prev_evt;       /* Previous event */
+
+       /* Children */
+       struct list_head        cln_head;       /* Head of the children lnode
+                                                * list.
+                                                */
+       uint32_t                num_vports;     /* Total NPIV/children LNodes*/
+       struct csio_lnode       *pln;           /* Parent lnode of child
+                                                * lnodes.
+                                                */
+       struct list_head        cmpl_q;         /* Pending I/Os on this lnode */
+
+       /* Remote node information */
+       struct list_head        rnhead;         /* Head of rnode list */
+       uint32_t                num_reg_rnodes; /* Number of rnodes registered
+                                                * with the host.
+                                                */
+       uint32_t                n_scsi_tgts;    /* Number of scsi targets
+                                                * found
+                                                */
+       uint32_t                last_scan_ntgts;/* Number of scsi targets
+                                                * found per last scan.
+                                                */
+       uint32_t                tgt_scan_tick;  /* timer started after
+                                                * new tgt found
+                                                */
+       /* FC transport data */
+       struct fc_vport         *fc_vport;
+       struct fc_host_statistics fch_stats;
+
+       struct csio_lnode_stats stats;          /* Common lnode stats */
+       struct csio_lnode_params params;        /* Common lnode params */
+};
+
+#define        csio_lnode_to_hw(ln)    ((ln)->hwp)
+#define csio_root_lnode(ln)    (csio_lnode_to_hw((ln))->rln)
+#define csio_parent_lnode(ln)  ((ln)->pln)
+#define        csio_ln_flowid(ln)      ((ln)->vnp_flowid)
+#define csio_ln_wwpn(ln)       ((ln)->ln_sparm.wwpn)
+#define csio_ln_wwnn(ln)       ((ln)->ln_sparm.wwnn)
+
+#define csio_is_root_ln(ln)    (((ln) == csio_root_lnode((ln))) ? 1 : 0)
+#define csio_is_phys_ln(ln)    (((ln)->pln == NULL) ? 1 : 0)
+#define csio_is_npiv_ln(ln)    (((ln)->pln != NULL) ? 1 : 0)
+
+
+#define csio_ln_dbg(_ln, _fmt, ...)    \
+       csio_dbg(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+                CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+#define csio_ln_err(_ln, _fmt, ...)    \
+       csio_err(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+                CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+#define csio_ln_warn(_ln, _fmt, ...)   \
+       csio_warn(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+                CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+/* HW->Lnode notifications */
+enum csio_ln_notify {
+       CSIO_LN_NOTIFY_HWREADY = 1,
+       CSIO_LN_NOTIFY_HWSTOP,
+       CSIO_LN_NOTIFY_HWREMOVE,
+       CSIO_LN_NOTIFY_HWRESET,
+};
+
+void csio_fcoe_fwevt_handler(struct csio_hw *,  __u8 cpl_op, __be64 *);
+int csio_is_lnode_ready(struct csio_lnode *);
+void csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str);
+struct csio_lnode *csio_lnode_lookup_by_wwpn(struct csio_hw *, uint8_t *);
+int csio_get_phy_port_stats(struct csio_hw *, uint8_t ,
+                                     struct fw_fcoe_port_stats *);
+int csio_scan_done(struct csio_lnode *, unsigned long, unsigned long,
+                  unsigned long, unsigned long);
+void csio_notify_lnodes(struct csio_hw *, enum csio_ln_notify);
+void csio_disable_lnodes(struct csio_hw *, uint8_t, bool);
+void csio_lnode_async_event(struct csio_lnode *, enum csio_ln_fc_evt);
+int csio_ln_fdmi_start(struct csio_lnode *, void *);
+int csio_lnode_start(struct csio_lnode *);
+void csio_lnode_stop(struct csio_lnode *);
+void csio_lnode_close(struct csio_lnode *);
+int csio_lnode_init(struct csio_lnode *, struct csio_hw *,
+                             struct csio_lnode *);
+void csio_lnode_exit(struct csio_lnode *);
+
+#endif /* ifndef __CSIO_LNODE_H__ */
diff --git a/drivers/scsi/csiostor/csio_mb.c b/drivers/scsi/csiostor/csio_mb.c
new file mode 100644 (file)
index 0000000..5b27c48
--- /dev/null
@@ -0,0 +1,1750 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_mb.h"
+#include "csio_wr.h"
+
+#define csio_mb_is_host_owner(__owner)         ((__owner) == CSIO_MBOWNER_PL)
+
+/* MB Command/Response Helpers */
+/*
+ * csio_mb_fw_retval - FW return value from a mailbox response.
+ * @mbp: Mailbox structure
+ *
+ */
+enum fw_retval
+csio_mb_fw_retval(struct csio_mb *mbp)
+{
+       struct fw_cmd_hdr *hdr;
+
+       hdr = (struct fw_cmd_hdr *)(mbp->mb);
+
+       return FW_CMD_RETVAL_GET(ntohl(hdr->lo));
+}
+
+/*
+ * csio_mb_hello - FW HELLO command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @m_mbox: Master mailbox number, if any.
+ * @a_mbox: Mailbox number for asycn notifications.
+ * @master: Device mastership.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_hello(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+             uint32_t m_mbox, uint32_t a_mbox, enum csio_dev_master master,
+             void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_hello_cmd *cmdp = (struct fw_hello_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_write = htonl(FW_CMD_OP(FW_HELLO_CMD) |
+                                      FW_CMD_REQUEST | FW_CMD_WRITE);
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->err_to_clearinit = htonl(
+               FW_HELLO_CMD_MASTERDIS(master == CSIO_MASTER_CANT)      |
+               FW_HELLO_CMD_MASTERFORCE(master == CSIO_MASTER_MUST)    |
+               FW_HELLO_CMD_MBMASTER(master == CSIO_MASTER_MUST ?
+                               m_mbox : FW_HELLO_CMD_MBMASTER_MASK)    |
+               FW_HELLO_CMD_MBASYNCNOT(a_mbox) |
+               FW_HELLO_CMD_STAGE(fw_hello_cmd_stage_os) |
+               FW_HELLO_CMD_CLEARINIT);
+
+}
+
+/*
+ * csio_mb_process_hello_rsp - FW HELLO response processing helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @retval: Mailbox return value from Firmware
+ * @state: State that the function is in.
+ * @mpfn: Master pfn
+ *
+ */
+void
+csio_mb_process_hello_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+                         enum fw_retval *retval, enum csio_dev_state *state,
+                         uint8_t *mpfn)
+{
+       struct fw_hello_cmd *rsp = (struct fw_hello_cmd *)(mbp->mb);
+       uint32_t value;
+
+       *retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+
+       if (*retval == FW_SUCCESS) {
+               hw->fwrev = ntohl(rsp->fwrev);
+
+               value = ntohl(rsp->err_to_clearinit);
+               *mpfn = FW_HELLO_CMD_MBMASTER_GET(value);
+
+               if (value & FW_HELLO_CMD_INIT)
+                       *state = CSIO_DEV_STATE_INIT;
+               else if (value & FW_HELLO_CMD_ERR)
+                       *state = CSIO_DEV_STATE_ERR;
+               else
+                       *state = CSIO_DEV_STATE_UNINIT;
+       }
+}
+
+/*
+ * csio_mb_bye - FW BYE command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_bye(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+           void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_bye_cmd *cmdp = (struct fw_bye_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_write = htonl(FW_CMD_OP(FW_BYE_CMD) |
+                                      FW_CMD_REQUEST | FW_CMD_WRITE);
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+}
+
+/*
+ * csio_mb_reset - FW RESET command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @reset: Type of reset.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_reset(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+             int reset, int halt,
+             void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_reset_cmd *cmdp = (struct fw_reset_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_write = htonl(FW_CMD_OP(FW_RESET_CMD) |
+                                 FW_CMD_REQUEST | FW_CMD_WRITE);
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->val = htonl(reset);
+       cmdp->halt_pkd = htonl(halt);
+
+}
+
+/*
+ * csio_mb_params - FW PARAMS command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: Command timeout.
+ * @pf: PF number.
+ * @vf: VF number.
+ * @nparams: Number of paramters
+ * @params: Parameter mnemonic array.
+ * @val: Parameter value array.
+ * @wr: Write/Read PARAMS.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_params(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+              unsigned int pf, unsigned int vf, unsigned int nparams,
+              const u32 *params, u32 *val, bool wr,
+              void (*cbfn)(struct csio_hw *, struct csio_mb *))
+{
+       uint32_t i;
+       uint32_t temp_params = 0, temp_val = 0;
+       struct fw_params_cmd *cmdp = (struct fw_params_cmd *)(mbp->mb);
+       __be32 *p = &cmdp->param[0].mnem;
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD)                |
+                               FW_CMD_REQUEST                          |
+                               (wr ? FW_CMD_WRITE : FW_CMD_READ)       |
+                               FW_PARAMS_CMD_PFN(pf)                   |
+                               FW_PARAMS_CMD_VFN(vf));
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       /* Write Params */
+       if (wr) {
+               while (nparams--) {
+                       temp_params = *params++;
+                       temp_val = *val++;
+
+                       *p++ = htonl(temp_params);
+                       *p++ = htonl(temp_val);
+               }
+       } else {
+               for (i = 0; i < nparams; i++, p += 2) {
+                       temp_params = *params++;
+                       *p = htonl(temp_params);
+               }
+       }
+
+}
+
+/*
+ * csio_mb_process_read_params_rsp - FW PARAMS response processing helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @retval: Mailbox return value from Firmware
+ * @nparams: Number of parameters
+ * @val: Parameter value array.
+ *
+ */
+void
+csio_mb_process_read_params_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+                          enum fw_retval *retval, unsigned int nparams,
+                          u32 *val)
+{
+       struct fw_params_cmd *rsp = (struct fw_params_cmd *)(mbp->mb);
+       uint32_t i;
+       __be32 *p = &rsp->param[0].val;
+
+       *retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+
+       if (*retval == FW_SUCCESS)
+               for (i = 0; i < nparams; i++, p += 2)
+                       *val++ = ntohl(*p);
+}
+
+/*
+ * csio_mb_ldst - FW LDST command
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: timeout
+ * @reg: register
+ *
+ */
+void
+csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, int reg)
+{
+       struct fw_ldst_cmd *ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
+       CSIO_INIT_MBP(mbp, ldst_cmd, tmo, hw, NULL, 1);
+
+       /*
+        * Construct and send the Firmware LDST Command to retrieve the
+        * specified PCI-E Configuration Space register.
+        */
+       ldst_cmd->op_to_addrspace =
+                       htonl(FW_CMD_OP(FW_LDST_CMD)    |
+                       FW_CMD_REQUEST                  |
+                       FW_CMD_READ                     |
+                       FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
+       ldst_cmd->cycles_to_len16 = htonl(FW_LEN16(struct fw_ldst_cmd));
+       ldst_cmd->u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
+       ldst_cmd->u.pcie.ctrl_to_fn =
+               (FW_LDST_CMD_LC | FW_LDST_CMD_FN(hw->pfn));
+       ldst_cmd->u.pcie.r = (uint8_t)reg;
+}
+
+/*
+ *
+ * csio_mb_caps_config - FW Read/Write Capabilities command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @wr: Write if 1, Read if 0
+ * @init: Turn on initiator mode.
+ * @tgt: Turn on target mode.
+ * @cofld:  If 1, Control Offload for FCoE
+ * @cbfn: Callback, if any.
+ *
+ * This helper assumes that cmdp has MB payload from a previous CAPS
+ * read command.
+ */
+void
+csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+                   bool wr, bool init, bool tgt, bool cofld,
+                   void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_caps_config_cmd *cmdp =
+                               (struct fw_caps_config_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, wr ? 0 : 1);
+
+       cmdp->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+                                 FW_CMD_REQUEST                |
+                                 (wr ? FW_CMD_WRITE : FW_CMD_READ));
+       cmdp->cfvalid_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       /* Read config */
+       if (!wr)
+               return;
+
+       /* Write config */
+       cmdp->fcoecaps = 0;
+
+       if (cofld)
+               cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_CTRL_OFLD);
+       if (init)
+               cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_INITIATOR);
+       if (tgt)
+               cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
+}
+
+void
+csio_rss_glb_config(struct csio_hw *hw, struct csio_mb *mbp,
+                   uint32_t tmo, uint8_t mode, unsigned int flags,
+                   void (*cbfn)(struct csio_hw *, struct csio_mb *))
+{
+       struct fw_rss_glb_config_cmd *cmdp =
+                               (struct fw_rss_glb_config_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
+                                 FW_CMD_REQUEST | FW_CMD_WRITE);
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
+               cmdp->u.manual.mode_pkd =
+                       htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
+       } else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
+               cmdp->u.basicvirtual.mode_pkd =
+                       htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
+               cmdp->u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags);
+       }
+}
+
+
+/*
+ * csio_mb_pfvf - FW Write PF/VF capabilities command helper.
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @pf:
+ * @vf:
+ * @txq:
+ * @txq_eht_ctrl:
+ * @rxqi:
+ * @rxq:
+ * @tc:
+ * @vi:
+ * @pmask:
+ * @rcaps:
+ * @wxcaps:
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_pfvf(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+            unsigned int pf, unsigned int vf, unsigned int txq,
+            unsigned int txq_eth_ctrl, unsigned int rxqi,
+            unsigned int rxq, unsigned int tc, unsigned int vi,
+            unsigned int cmask, unsigned int pmask, unsigned int nexactf,
+            unsigned int rcaps, unsigned int wxcaps,
+            void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_pfvf_cmd *cmdp = (struct fw_pfvf_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD)                  |
+                               FW_CMD_REQUEST                          |
+                               FW_CMD_WRITE                            |
+                               FW_PFVF_CMD_PFN(pf)                     |
+                               FW_PFVF_CMD_VFN(vf));
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi)           |
+                                            FW_PFVF_CMD_NIQ(rxq));
+
+       cmdp->type_to_neq = htonl(FW_PFVF_CMD_TYPE                      |
+                                 FW_PFVF_CMD_CMASK(cmask)              |
+                                 FW_PFVF_CMD_PMASK(pmask)              |
+                                 FW_PFVF_CMD_NEQ(txq));
+       cmdp->tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc)                  |
+                                   FW_PFVF_CMD_NVI(vi)                 |
+                                   FW_PFVF_CMD_NEXACTF(nexactf));
+       cmdp->r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps)      |
+                                        FW_PFVF_CMD_WX_CAPS(wxcaps)    |
+                                        FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
+}
+
+#define CSIO_ADVERT_MASK     (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
+                             FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG)
+
+/*
+ * csio_mb_port- FW PORT command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: COmmand timeout
+ * @portid: Port ID to get/set info
+ * @wr: Write/Read PORT information.
+ * @fc: Flow control
+ * @caps: Port capabilites to set.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+            uint8_t portid, bool wr, uint32_t fc, uint16_t caps,
+            void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb);
+       unsigned int lfc = 0, mdi = FW_PORT_MDI(FW_PORT_MDI_AUTO);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn,  1);
+
+       cmdp->op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD)               |
+                                  FW_CMD_REQUEST                       |
+                                  (wr ? FW_CMD_EXEC : FW_CMD_READ)     |
+                                  FW_PORT_CMD_PORTID(portid));
+       if (!wr) {
+               cmdp->action_to_len16 = htonl(
+                       FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
+                       FW_CMD_LEN16(sizeof(*cmdp) / 16));
+               return;
+       }
+
+       /* Set port */
+       cmdp->action_to_len16 = htonl(
+                       FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
+                       FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       if (fc & PAUSE_RX)
+               lfc |= FW_PORT_CAP_FC_RX;
+       if (fc & PAUSE_TX)
+               lfc |= FW_PORT_CAP_FC_TX;
+
+       if (!(caps & FW_PORT_CAP_ANEG))
+               cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc);
+       else
+               cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) |
+                                                               lfc | mdi);
+}
+
+/*
+ * csio_mb_process_read_port_rsp - FW PORT command response processing helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @retval: Mailbox return value from Firmware
+ * @caps: port capabilities
+ *
+ */
+void
+csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+                        enum fw_retval *retval, uint16_t *caps)
+{
+       struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
+
+       *retval = FW_CMD_RETVAL_GET(ntohl(rsp->action_to_len16));
+
+       if (*retval == FW_SUCCESS)
+               *caps = ntohs(rsp->u.info.pcap);
+}
+
+/*
+ * csio_mb_initialize - FW INITIALIZE command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: COmmand timeout
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_initialize(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+                  void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_initialize_cmd *cmdp = (struct fw_initialize_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+       cmdp->op_to_write = htonl(FW_CMD_OP(FW_INITIALIZE_CMD)  |
+                                 FW_CMD_REQUEST | FW_CMD_WRITE);
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+}
+
+/*
+ * csio_mb_iq_alloc - Initializes the mailbox to allocate an
+ *                             Ingress DMA queue in the firmware.
+ *
+ * @hw: The hw structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private object
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @iq_params: Ingress queue params needed for allocation.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+static void
+csio_mb_iq_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+                uint32_t mb_tmo, struct csio_iq_params *iq_params,
+                void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+       cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD)            |
+                               FW_CMD_REQUEST | FW_CMD_EXEC    |
+                               FW_IQ_CMD_PFN(iq_params->pfn)   |
+                               FW_IQ_CMD_VFN(iq_params->vfn));
+
+       cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC            |
+                               FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       cmdp->type_to_iqandstindex = htonl(
+                               FW_IQ_CMD_VIID(iq_params->viid) |
+                               FW_IQ_CMD_TYPE(iq_params->type) |
+                               FW_IQ_CMD_IQASYNCH(iq_params->iqasynch));
+
+       cmdp->fl0size = htons(iq_params->fl0size);
+       cmdp->fl0size = htons(iq_params->fl1size);
+
+} /* csio_mb_iq_alloc */
+
+/*
+ * csio_mb_iq_write - Initializes the mailbox for writing into an
+ *                             Ingress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private object
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cascaded_req: TRUE - if this request is cascased with iq-alloc request.
+ * @iq_params: Ingress queue params needed for writing.
+ * @cbfn: The call-back function
+ *
+ * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating,
+ * because this IQ write request can be cascaded with a previous
+ * IQ alloc request, and we dont want to over-write the bits set by
+ * that request. This logic will work even in a non-cascaded case, since the
+ * cmdp structure is zeroed out by CSIO_INIT_MBP.
+ */
+static void
+csio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+                uint32_t mb_tmo, bool cascaded_req,
+                struct csio_iq_params *iq_params,
+                void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
+
+       uint32_t iq_start_stop = (iq_params->iq_start)  ?
+                                       FW_IQ_CMD_IQSTART(1) :
+                                       FW_IQ_CMD_IQSTOP(1);
+
+       /*
+        * If this IQ write is cascaded with IQ alloc request, do not
+        * re-initialize with 0's.
+        *
+        */
+       if (!cascaded_req)
+               CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+       cmdp->op_to_vfn |= htonl(FW_CMD_OP(FW_IQ_CMD)           |
+                               FW_CMD_REQUEST | FW_CMD_WRITE   |
+                               FW_IQ_CMD_PFN(iq_params->pfn)   |
+                               FW_IQ_CMD_VFN(iq_params->vfn));
+       cmdp->alloc_to_len16 |= htonl(iq_start_stop |
+                               FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->iqid |= htons(iq_params->iqid);
+       cmdp->fl0id |= htons(iq_params->fl0id);
+       cmdp->fl1id |= htons(iq_params->fl1id);
+       cmdp->type_to_iqandstindex |= htonl(
+                       FW_IQ_CMD_IQANDST(iq_params->iqandst)   |
+                       FW_IQ_CMD_IQANUS(iq_params->iqanus)     |
+                       FW_IQ_CMD_IQANUD(iq_params->iqanud)     |
+                       FW_IQ_CMD_IQANDSTINDEX(iq_params->iqandstindex));
+       cmdp->iqdroprss_to_iqesize |= htons(
+                       FW_IQ_CMD_IQPCIECH(iq_params->iqpciech)         |
+                       FW_IQ_CMD_IQDCAEN(iq_params->iqdcaen)           |
+                       FW_IQ_CMD_IQDCACPU(iq_params->iqdcacpu)         |
+                       FW_IQ_CMD_IQINTCNTTHRESH(iq_params->iqintcntthresh) |
+                       FW_IQ_CMD_IQCPRIO(iq_params->iqcprio)           |
+                       FW_IQ_CMD_IQESIZE(iq_params->iqesize));
+
+       cmdp->iqsize |= htons(iq_params->iqsize);
+       cmdp->iqaddr |= cpu_to_be64(iq_params->iqaddr);
+
+       if (iq_params->type == 0) {
+               cmdp->iqns_to_fl0congen |= htonl(
+                       FW_IQ_CMD_IQFLINTIQHSEN(iq_params->iqflintiqhsen)|
+                       FW_IQ_CMD_IQFLINTCONGEN(iq_params->iqflintcongen));
+       }
+
+       if (iq_params->fl0size && iq_params->fl0addr &&
+           (iq_params->fl0id != 0xFFFF)) {
+
+               cmdp->iqns_to_fl0congen |= htonl(
+                       FW_IQ_CMD_FL0HOSTFCMODE(iq_params->fl0hostfcmode)|
+                       FW_IQ_CMD_FL0CPRIO(iq_params->fl0cprio)         |
+                       FW_IQ_CMD_FL0PADEN(iq_params->fl0paden)         |
+                       FW_IQ_CMD_FL0PACKEN(iq_params->fl0packen));
+               cmdp->fl0dcaen_to_fl0cidxfthresh |= htons(
+                       FW_IQ_CMD_FL0DCAEN(iq_params->fl0dcaen)         |
+                       FW_IQ_CMD_FL0DCACPU(iq_params->fl0dcacpu)       |
+                       FW_IQ_CMD_FL0FBMIN(iq_params->fl0fbmin)         |
+                       FW_IQ_CMD_FL0FBMAX(iq_params->fl0fbmax)         |
+                       FW_IQ_CMD_FL0CIDXFTHRESH(iq_params->fl0cidxfthresh));
+               cmdp->fl0size |= htons(iq_params->fl0size);
+               cmdp->fl0addr |= cpu_to_be64(iq_params->fl0addr);
+       }
+} /* csio_mb_iq_write */
+
+/*
+ * csio_mb_iq_alloc_write - Initializes the mailbox for allocating an
+ *                             Ingress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @iq_params: Ingress queue params needed for allocation & writing.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_iq_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+                      uint32_t mb_tmo, struct csio_iq_params *iq_params,
+                      void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       csio_mb_iq_alloc(hw, mbp, priv, mb_tmo, iq_params, cbfn);
+       csio_mb_iq_write(hw, mbp, priv, mb_tmo, true, iq_params, cbfn);
+} /* csio_mb_iq_alloc_write */
+
+/*
+ * csio_mb_iq_alloc_write_rsp - Process the allocation & writing
+ *                             of ingress DMA queue mailbox's response.
+ *
+ * @hw: The HW structure.
+ * @mbp: Mailbox structure to initialize.
+ * @retval: Firmware return value.
+ * @iq_params: Ingress queue parameters, after allocation and write.
+ *
+ */
+void
+csio_mb_iq_alloc_write_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+                          enum fw_retval *ret_val,
+                          struct csio_iq_params *iq_params)
+{
+       struct fw_iq_cmd *rsp = (struct fw_iq_cmd *)(mbp->mb);
+
+       *ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
+       if (*ret_val == FW_SUCCESS) {
+               iq_params->physiqid = ntohs(rsp->physiqid);
+               iq_params->iqid = ntohs(rsp->iqid);
+               iq_params->fl0id = ntohs(rsp->fl0id);
+               iq_params->fl1id = ntohs(rsp->fl1id);
+       } else {
+               iq_params->physiqid = iq_params->iqid =
+               iq_params->fl0id = iq_params->fl1id = 0;
+       }
+} /* csio_mb_iq_alloc_write_rsp */
+
+/*
+ * csio_mb_iq_free - Initializes the mailbox for freeing a
+ *                             specified Ingress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @iq_params: Parameters of ingress queue, that is to be freed.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_iq_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+               uint32_t mb_tmo, struct csio_iq_params *iq_params,
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+       cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD)            |
+                               FW_CMD_REQUEST | FW_CMD_EXEC    |
+                               FW_IQ_CMD_PFN(iq_params->pfn)   |
+                               FW_IQ_CMD_VFN(iq_params->vfn));
+       cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_FREE             |
+                               FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(iq_params->type));
+
+       cmdp->iqid = htons(iq_params->iqid);
+       cmdp->fl0id = htons(iq_params->fl0id);
+       cmdp->fl1id = htons(iq_params->fl1id);
+
+} /* csio_mb_iq_free */
+
+/*
+ * csio_mb_eq_ofld_alloc - Initializes the mailbox for allocating
+ *                             an offload-egress queue.
+ *
+ * @hw: The HW  structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+static void
+csio_mb_eq_ofld_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+               uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params,
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+       cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD)               |
+                               FW_CMD_REQUEST | FW_CMD_EXEC            |
+                               FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) |
+                               FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn));
+       cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC       |
+                               FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_mb_eq_ofld_alloc */
+
+/*
+ * csio_mb_eq_ofld_write - Initializes the mailbox for writing
+ *                             an alloacted offload-egress queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cascaded_req: TRUE - if this request is cascased with Eq-alloc request.
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @cbfn: The call-back function
+ *
+ *
+ * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating,
+ * because this EQ write request can be cascaded with a previous
+ * EQ alloc request, and we dont want to over-write the bits set by
+ * that request. This logic will work even in a non-cascaded case, since the
+ * cmdp structure is zeroed out by CSIO_INIT_MBP.
+ */
+static void
+csio_mb_eq_ofld_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+                     uint32_t mb_tmo, bool cascaded_req,
+                     struct csio_eq_params *eq_ofld_params,
+                     void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+       uint32_t eq_start_stop = (eq_ofld_params->eqstart)      ?
+                               FW_EQ_OFLD_CMD_EQSTART  : FW_EQ_OFLD_CMD_EQSTOP;
+
+       /*
+        * If this EQ write is cascaded with EQ alloc request, do not
+        * re-initialize with 0's.
+        *
+        */
+       if (!cascaded_req)
+               CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+       cmdp->op_to_vfn |= htonl(FW_CMD_OP(FW_EQ_OFLD_CMD)      |
+                               FW_CMD_REQUEST | FW_CMD_WRITE   |
+                               FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) |
+                               FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn));
+       cmdp->alloc_to_len16 |= htonl(eq_start_stop             |
+                                     FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       cmdp->eqid_pkd |= htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid));
+
+       cmdp->fetchszm_to_iqid |= htonl(
+               FW_EQ_OFLD_CMD_HOSTFCMODE(eq_ofld_params->hostfcmode)   |
+               FW_EQ_OFLD_CMD_CPRIO(eq_ofld_params->cprio)             |
+               FW_EQ_OFLD_CMD_PCIECHN(eq_ofld_params->pciechn)         |
+               FW_EQ_OFLD_CMD_IQID(eq_ofld_params->iqid));
+
+       cmdp->dcaen_to_eqsize |= htonl(
+               FW_EQ_OFLD_CMD_DCAEN(eq_ofld_params->dcaen)             |
+               FW_EQ_OFLD_CMD_DCACPU(eq_ofld_params->dcacpu)           |
+               FW_EQ_OFLD_CMD_FBMIN(eq_ofld_params->fbmin)             |
+               FW_EQ_OFLD_CMD_FBMAX(eq_ofld_params->fbmax)             |
+               FW_EQ_OFLD_CMD_CIDXFTHRESHO(eq_ofld_params->cidxfthresho) |
+               FW_EQ_OFLD_CMD_CIDXFTHRESH(eq_ofld_params->cidxfthresh) |
+               FW_EQ_OFLD_CMD_EQSIZE(eq_ofld_params->eqsize));
+
+       cmdp->eqaddr |= cpu_to_be64(eq_ofld_params->eqaddr);
+
+} /* csio_mb_eq_ofld_write */
+
+/*
+ * csio_mb_eq_ofld_alloc_write - Initializes the mailbox for allocation
+ *                             writing into an Engress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_eq_ofld_alloc_write(struct csio_hw *hw, struct csio_mb *mbp,
+                           void *priv, uint32_t mb_tmo,
+                           struct csio_eq_params *eq_ofld_params,
+                           void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       csio_mb_eq_ofld_alloc(hw, mbp, priv, mb_tmo, eq_ofld_params, cbfn);
+       csio_mb_eq_ofld_write(hw, mbp, priv, mb_tmo, true,
+                             eq_ofld_params, cbfn);
+} /* csio_mb_eq_ofld_alloc_write */
+
+/*
+ * csio_mb_eq_ofld_alloc_write_rsp - Process the allocation
+ *                             & write egress DMA queue mailbox's response.
+ *
+ * @hw: The HW structure.
+ * @mbp: Mailbox structure to initialize.
+ * @retval: Firmware return value.
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ *
+ */
+void
+csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *hw,
+                               struct csio_mb *mbp, enum fw_retval *ret_val,
+                               struct csio_eq_params *eq_ofld_params)
+{
+       struct fw_eq_ofld_cmd *rsp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+       *ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
+
+       if (*ret_val == FW_SUCCESS) {
+               eq_ofld_params->eqid = FW_EQ_OFLD_CMD_EQID_GET(
+                                               ntohl(rsp->eqid_pkd));
+               eq_ofld_params->physeqid = FW_EQ_OFLD_CMD_PHYSEQID_GET(
+                                               ntohl(rsp->physeqid_pkd));
+       } else
+               eq_ofld_params->eqid = 0;
+
+} /* csio_mb_eq_ofld_alloc_write_rsp */
+
+/*
+ * csio_mb_eq_ofld_free - Initializes the mailbox for freeing a
+ *                             specified Engress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data area.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @eq_ofld_params: (Offload) Egress queue paramters, that is to be freed.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_eq_ofld_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+                    uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params,
+                    void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+       cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD)       |
+                               FW_CMD_REQUEST | FW_CMD_EXEC    |
+                               FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) |
+                               FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn));
+       cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE |
+                               FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid));
+
+} /* csio_mb_eq_ofld_free */
+
+/*
+ * csio_write_fcoe_link_cond_init_mb - Initialize Mailbox to write FCoE link
+ *                              condition.
+ *
+ * @ln: The Lnode structure
+ * @mbp: Mailbox structure to initialize
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cbfn: The call back function.
+ *
+ *
+ */
+void
+csio_write_fcoe_link_cond_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+                       uint32_t mb_tmo, uint8_t port_id, uint32_t sub_opcode,
+                       uint8_t cos, bool link_status, uint32_t fcfi,
+                       void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_fcoe_link_cmd *cmdp =
+                               (struct fw_fcoe_link_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+       cmdp->op_to_portid = htonl((
+                       FW_CMD_OP(FW_FCOE_LINK_CMD)             |
+                       FW_CMD_REQUEST                          |
+                       FW_CMD_WRITE                            |
+                       FW_FCOE_LINK_CMD_PORTID(port_id)));
+       cmdp->sub_opcode_fcfi = htonl(
+                       FW_FCOE_LINK_CMD_SUB_OPCODE(sub_opcode) |
+                       FW_FCOE_LINK_CMD_FCFI(fcfi));
+       cmdp->lstatus = link_status;
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_write_fcoe_link_cond_init_mb */
+
+/*
+ * csio_fcoe_read_res_info_init_mb - Initializes the mailbox for reading FCoE
+ *                             resource information(FW_GET_RES_INFO_CMD).
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_fcoe_read_res_info_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
+                       uint32_t mb_tmo,
+                       void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_fcoe_res_info_cmd *cmdp =
+                       (struct fw_fcoe_res_info_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
+
+       cmdp->op_to_read = htonl((FW_CMD_OP(FW_FCOE_RES_INFO_CMD)       |
+                                 FW_CMD_REQUEST                        |
+                                 FW_CMD_READ));
+
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_fcoe_read_res_info_init_mb */
+
+/*
+ * csio_fcoe_vnp_alloc_init_mb - Initializes the mailbox for allocating VNP
+ *                             in the firmware (FW_FCOE_VNP_CMD).
+ *
+ * @ln: The Lnode structure.
+ * @mbp: Mailbox structure to initialize.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcfi: FCF Index.
+ * @vnpi: vnpi
+ * @iqid: iqid
+ * @vnport_wwnn: vnport WWNN
+ * @vnport_wwpn: vnport WWPN
+ * @cbfn: The call-back function.
+ *
+ *
+ */
+void
+csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+               uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, uint16_t iqid,
+               uint8_t vnport_wwnn[8], uint8_t vnport_wwpn[8],
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_fcoe_vnp_cmd *cmdp =
+                       (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+       cmdp->op_to_fcfi = htonl((FW_CMD_OP(FW_FCOE_VNP_CMD)            |
+                                 FW_CMD_REQUEST                        |
+                                 FW_CMD_EXEC                           |
+                                 FW_FCOE_VNP_CMD_FCFI(fcfi)));
+
+       cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_ALLOC              |
+                                    FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+       cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
+
+       cmdp->iqid = htons(iqid);
+
+       if (!wwn_to_u64(vnport_wwnn) && !wwn_to_u64(vnport_wwpn))
+               cmdp->gen_wwn_to_vnpi |= htonl(FW_FCOE_VNP_CMD_GEN_WWN);
+
+       if (vnport_wwnn)
+               memcpy(cmdp->vnport_wwnn, vnport_wwnn, 8);
+       if (vnport_wwpn)
+               memcpy(cmdp->vnport_wwpn, vnport_wwpn, 8);
+
+} /* csio_fcoe_vnp_alloc_init_mb */
+
+/*
+ * csio_fcoe_vnp_read_init_mb - Prepares VNP read cmd.
+ * @ln: The Lnode structure.
+ * @mbp: Mailbox structure to initialize.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcfi: FCF Index.
+ * @vnpi: vnpi
+ * @cbfn: The call-back handler.
+ */
+void
+csio_fcoe_vnp_read_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+               uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi,
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_fcoe_vnp_cmd *cmdp =
+                       (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+       cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD)     |
+                                FW_CMD_REQUEST                 |
+                                FW_CMD_READ                    |
+                                FW_FCOE_VNP_CMD_FCFI(fcfi));
+       cmdp->alloc_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
+}
+
+/*
+ * csio_fcoe_vnp_free_init_mb - Initializes the mailbox for freeing an
+ *                     alloacted VNP in the firmware (FW_FCOE_VNP_CMD).
+ *
+ * @ln: The Lnode structure.
+ * @mbp: Mailbox structure to initialize.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcfi: FCF flow id
+ * @vnpi: VNP flow id
+ * @cbfn: The call-back function.
+ * Return: None
+ */
+void
+csio_fcoe_vnp_free_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+               uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi,
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_fcoe_vnp_cmd *cmdp =
+                       (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+       cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD)     |
+                                FW_CMD_REQUEST                 |
+                                FW_CMD_EXEC                    |
+                                FW_FCOE_VNP_CMD_FCFI(fcfi));
+       cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_FREE       |
+                                    FW_CMD_LEN16(sizeof(*cmdp) / 16));
+       cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
+}
+
+/*
+ * csio_fcoe_read_fcf_init_mb - Initializes the mailbox to read the
+ *                             FCF records.
+ *
+ * @ln: The Lnode structure
+ * @mbp: Mailbox structure to initialize
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcf_params: FC-Forwarder parameters.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_fcoe_read_fcf_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+               uint32_t mb_tmo, uint32_t portid, uint32_t fcfi,
+               void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct fw_fcoe_fcf_cmd *cmdp =
+                       (struct fw_fcoe_fcf_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+       cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_FCF_CMD)     |
+                                FW_CMD_REQUEST                 |
+                                FW_CMD_READ                    |
+                                FW_FCOE_FCF_CMD_FCFI(fcfi));
+       cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_fcoe_read_fcf_init_mb */
+
+void
+csio_fcoe_read_portparams_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
+                               uint32_t mb_tmo,
+                               struct fw_fcoe_port_cmd_params *portparams,
+                               void (*cbfn)(struct csio_hw *,
+                                            struct csio_mb *))
+{
+       struct fw_fcoe_stats_cmd *cmdp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
+
+       CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
+       mbp->mb_size = 64;
+
+       cmdp->op_to_flowid = htonl(FW_CMD_OP(FW_FCOE_STATS_CMD)         |
+                                  FW_CMD_REQUEST | FW_CMD_READ);
+       cmdp->free_to_len16 = htonl(FW_CMD_LEN16(CSIO_MAX_MB_SIZE/16));
+
+       cmdp->u.ctl.nstats_port = FW_FCOE_STATS_CMD_NSTATS(portparams->nstats) |
+                                 FW_FCOE_STATS_CMD_PORT(portparams->portid);
+
+       cmdp->u.ctl.port_valid_ix = FW_FCOE_STATS_CMD_IX(portparams->idx)    |
+                                   FW_FCOE_STATS_CMD_PORT_VALID;
+
+} /* csio_fcoe_read_portparams_init_mb */
+
+void
+csio_mb_process_portparams_rsp(struct csio_hw *hw,
+                               struct csio_mb *mbp,
+                               enum fw_retval *retval,
+                               struct fw_fcoe_port_cmd_params *portparams,
+                               struct fw_fcoe_port_stats *portstats)
+{
+       struct fw_fcoe_stats_cmd *rsp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
+       struct fw_fcoe_port_stats stats;
+       uint8_t *src;
+       uint8_t *dst;
+
+       *retval = FW_CMD_RETVAL_GET(ntohl(rsp->free_to_len16));
+
+       memset(&stats, 0, sizeof(struct fw_fcoe_port_stats));
+
+       if (*retval == FW_SUCCESS) {
+               dst = (uint8_t *)(&stats) + ((portparams->idx - 1) * 8);
+               src = (uint8_t *)rsp + (CSIO_STATS_OFFSET * 8);
+               memcpy(dst, src, (portparams->nstats * 8));
+               if (portparams->idx == 1) {
+                       /* Get the first 6 flits from the Mailbox */
+                       portstats->tx_bcast_bytes = stats.tx_bcast_bytes;
+                       portstats->tx_bcast_frames = stats.tx_bcast_frames;
+                       portstats->tx_mcast_bytes = stats.tx_mcast_bytes;
+                       portstats->tx_mcast_frames = stats.tx_mcast_frames;
+                       portstats->tx_ucast_bytes = stats.tx_ucast_bytes;
+                       portstats->tx_ucast_frames = stats.tx_ucast_frames;
+               }
+               if (portparams->idx == 7) {
+                       /* Get the second 6 flits from the Mailbox */
+                       portstats->tx_drop_frames = stats.tx_drop_frames;
+                       portstats->tx_offload_bytes = stats.tx_offload_bytes;
+                       portstats->tx_offload_frames = stats.tx_offload_frames;
+#if 0
+                       portstats->rx_pf_bytes = stats.rx_pf_bytes;
+                       portstats->rx_pf_frames = stats.rx_pf_frames;
+#endif
+                       portstats->rx_bcast_bytes = stats.rx_bcast_bytes;
+                       portstats->rx_bcast_frames = stats.rx_bcast_frames;
+                       portstats->rx_mcast_bytes = stats.rx_mcast_bytes;
+               }
+               if (portparams->idx == 13) {
+                       /* Get the last 4 flits from the Mailbox */
+                       portstats->rx_mcast_frames = stats.rx_mcast_frames;
+                       portstats->rx_ucast_bytes = stats.rx_ucast_bytes;
+                       portstats->rx_ucast_frames = stats.rx_ucast_frames;
+                       portstats->rx_err_frames = stats.rx_err_frames;
+               }
+       }
+}
+
+/* Entry points/APIs for MB module                                          */
+/*
+ * csio_mb_intr_enable - Enable Interrupts from mailboxes.
+ * @hw: The HW structure
+ *
+ * Enables CIM interrupt bit in appropriate INT_ENABLE registers.
+ */
+void
+csio_mb_intr_enable(struct csio_hw *hw)
+{
+       csio_wr_reg32(hw, MBMSGRDYINTEN(1), MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+       csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+}
+
+/*
+ * csio_mb_intr_disable - Disable Interrupts from mailboxes.
+ * @hw: The HW structure
+ *
+ * Disable bit in HostInterruptEnable CIM register.
+ */
+void
+csio_mb_intr_disable(struct csio_hw *hw)
+{
+       csio_wr_reg32(hw, MBMSGRDYINTEN(0), MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+       csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+}
+
+static void
+csio_mb_dump_fw_dbg(struct csio_hw *hw, __be64 *cmd)
+{
+       struct fw_debug_cmd *dbg = (struct fw_debug_cmd *)cmd;
+
+       if ((FW_DEBUG_CMD_TYPE_GET(ntohl(dbg->op_type))) == 1) {
+               csio_info(hw, "FW print message:\n");
+               csio_info(hw, "\tdebug->dprtstridx = %d\n",
+                           ntohs(dbg->u.prt.dprtstridx));
+               csio_info(hw, "\tdebug->dprtstrparam0 = 0x%x\n",
+                           ntohl(dbg->u.prt.dprtstrparam0));
+               csio_info(hw, "\tdebug->dprtstrparam1 = 0x%x\n",
+                           ntohl(dbg->u.prt.dprtstrparam1));
+               csio_info(hw, "\tdebug->dprtstrparam2 = 0x%x\n",
+                           ntohl(dbg->u.prt.dprtstrparam2));
+               csio_info(hw, "\tdebug->dprtstrparam3 = 0x%x\n",
+                           ntohl(dbg->u.prt.dprtstrparam3));
+       } else {
+               /* This is a FW assertion */
+               csio_fatal(hw, "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
+                           dbg->u.assert.filename_0_7,
+                           ntohl(dbg->u.assert.line),
+                           ntohl(dbg->u.assert.x),
+                           ntohl(dbg->u.assert.y));
+       }
+}
+
+static void
+csio_mb_debug_cmd_handler(struct csio_hw *hw)
+{
+       int i;
+       __be64 cmd[CSIO_MB_MAX_REGS];
+       uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL);
+       uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA);
+       int size = sizeof(struct fw_debug_cmd);
+
+       /* Copy mailbox data */
+       for (i = 0; i < size; i += 8)
+               cmd[i / 8] = cpu_to_be64(csio_rd_reg64(hw, data_reg + i));
+
+       csio_mb_dump_fw_dbg(hw, cmd);
+
+       /* Notify FW of mailbox by setting owner as UP */
+       csio_wr_reg32(hw, MBMSGVALID | MBINTREQ | MBOWNER(CSIO_MBOWNER_FW),
+                     ctl_reg);
+
+       csio_rd_reg32(hw, ctl_reg);
+       wmb();
+}
+
+/*
+ * csio_mb_issue - generic routine for issuing Mailbox commands.
+ * @hw: The HW structure
+ * @mbp: Mailbox command to issue
+ *
+ *  Caller should hold hw lock across this call.
+ */
+int
+csio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp)
+{
+       uint32_t owner, ctl;
+       int i;
+       uint32_t ii;
+       __be64 *cmd = mbp->mb;
+       __be64 hdr;
+       struct csio_mbm *mbm = &hw->mbm;
+       uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL);
+       uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA);
+       int size = mbp->mb_size;
+       int rv = -EINVAL;
+       struct fw_cmd_hdr *fw_hdr;
+
+       /* Determine mode */
+       if (mbp->mb_cbfn == NULL) {
+               /* Need to issue/get results in the same context */
+               if (mbp->tmo < CSIO_MB_POLL_FREQ) {
+                       csio_err(hw, "Invalid tmo: 0x%x\n", mbp->tmo);
+                       goto error_out;
+               }
+       } else if (!csio_is_host_intr_enabled(hw) ||
+                  !csio_is_hw_intr_enabled(hw)) {
+               csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n",
+                        *((uint8_t *)mbp->mb));
+                       goto error_out;
+       }
+
+       if (mbm->mcurrent != NULL) {
+               /* Queue mbox cmd, if another mbox cmd is active */
+               if (mbp->mb_cbfn == NULL) {
+                       rv = -EBUSY;
+                       csio_dbg(hw, "Couldnt own Mailbox %x op:0x%x\n",
+                                   hw->pfn, *((uint8_t *)mbp->mb));
+
+                       goto error_out;
+               } else {
+                       list_add_tail(&mbp->list, &mbm->req_q);
+                       CSIO_INC_STATS(mbm, n_activeq);
+
+                       return 0;
+               }
+       }
+
+       /* Now get ownership of mailbox */
+       owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg));
+
+       if (!csio_mb_is_host_owner(owner)) {
+
+               for (i = 0; (owner == CSIO_MBOWNER_NONE) && (i < 3); i++)
+                       owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg));
+               /*
+                * Mailbox unavailable. In immediate mode, fail the command.
+                * In other modes, enqueue the request.
+                */
+               if (!csio_mb_is_host_owner(owner)) {
+                       if (mbp->mb_cbfn == NULL) {
+                               rv = owner ? -EBUSY : -ETIMEDOUT;
+
+                               csio_dbg(hw,
+                                        "Couldnt own Mailbox %x op:0x%x "
+                                        "owner:%x\n",
+                                        hw->pfn, *((uint8_t *)mbp->mb), owner);
+                               goto error_out;
+                       } else {
+                               if (mbm->mcurrent == NULL) {
+                                       csio_err(hw,
+                                                "Couldnt own Mailbox %x "
+                                                "op:0x%x owner:%x\n",
+                                                hw->pfn, *((uint8_t *)mbp->mb),
+                                                owner);
+                                       csio_err(hw,
+                                                "No outstanding driver"
+                                                " mailbox as well\n");
+                                       goto error_out;
+                               }
+                       }
+               }
+       }
+
+       /* Mailbox is available, copy mailbox data into it */
+       for (i = 0; i < size; i += 8) {
+               csio_wr_reg64(hw, be64_to_cpu(*cmd), data_reg + i);
+               cmd++;
+       }
+
+       CSIO_DUMP_MB(hw, hw->pfn, data_reg);
+
+       /* Start completion timers in non-immediate modes and notify FW */
+       if (mbp->mb_cbfn != NULL) {
+               mbm->mcurrent = mbp;
+               mod_timer(&mbm->timer, jiffies + msecs_to_jiffies(mbp->tmo));
+               csio_wr_reg32(hw, MBMSGVALID | MBINTREQ |
+                             MBOWNER(CSIO_MBOWNER_FW), ctl_reg);
+       } else
+               csio_wr_reg32(hw, MBMSGVALID | MBOWNER(CSIO_MBOWNER_FW),
+                             ctl_reg);
+
+       /* Flush posted writes */
+       csio_rd_reg32(hw, ctl_reg);
+       wmb();
+
+       CSIO_INC_STATS(mbm, n_req);
+
+       if (mbp->mb_cbfn)
+               return 0;
+
+       /* Poll for completion in immediate mode */
+       cmd = mbp->mb;
+
+       for (ii = 0; ii < mbp->tmo; ii += CSIO_MB_POLL_FREQ) {
+               mdelay(CSIO_MB_POLL_FREQ);
+
+               /* Check for response */
+               ctl = csio_rd_reg32(hw, ctl_reg);
+               if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) {
+
+                       if (!(ctl & MBMSGVALID)) {
+                               csio_wr_reg32(hw, 0, ctl_reg);
+                               continue;
+                       }
+
+                       CSIO_DUMP_MB(hw, hw->pfn, data_reg);
+
+                       hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
+                       fw_hdr = (struct fw_cmd_hdr *)&hdr;
+
+                       switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) {
+                       case FW_DEBUG_CMD:
+                               csio_mb_debug_cmd_handler(hw);
+                               continue;
+                       }
+
+                       /* Copy response */
+                       for (i = 0; i < size; i += 8)
+                               *cmd++ = cpu_to_be64(csio_rd_reg64
+                                                         (hw, data_reg + i));
+                       csio_wr_reg32(hw, 0, ctl_reg);
+
+                       if (csio_mb_fw_retval(mbp) != FW_SUCCESS)
+                               CSIO_INC_STATS(mbm, n_err);
+
+                       CSIO_INC_STATS(mbm, n_rsp);
+                       return 0;
+               }
+       }
+
+       CSIO_INC_STATS(mbm, n_tmo);
+
+       csio_err(hw, "Mailbox %x op:0x%x timed out!\n",
+                hw->pfn, *((uint8_t *)cmd));
+
+       return -ETIMEDOUT;
+
+error_out:
+       CSIO_INC_STATS(mbm, n_err);
+       return rv;
+}
+
+/*
+ * csio_mb_completions - Completion handler for Mailbox commands
+ * @hw: The HW structure
+ * @cbfn_q: Completion queue.
+ *
+ */
+void
+csio_mb_completions(struct csio_hw *hw, struct list_head *cbfn_q)
+{
+       struct csio_mb *mbp;
+       struct csio_mbm *mbm = &hw->mbm;
+       enum fw_retval rv;
+
+       while (!list_empty(cbfn_q)) {
+               mbp = list_first_entry(cbfn_q, struct csio_mb, list);
+               list_del_init(&mbp->list);
+
+               rv = csio_mb_fw_retval(mbp);
+               if ((rv != FW_SUCCESS) && (rv != FW_HOSTERROR))
+                       CSIO_INC_STATS(mbm, n_err);
+               else if (rv != FW_HOSTERROR)
+                       CSIO_INC_STATS(mbm, n_rsp);
+
+               if (mbp->mb_cbfn)
+                       mbp->mb_cbfn(hw, mbp);
+       }
+}
+
+static void
+csio_mb_portmod_changed(struct csio_hw *hw, uint8_t port_id)
+{
+       static char *mod_str[] = {
+               NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM"
+       };
+
+       struct csio_pport *port = &hw->pport[port_id];
+
+       if (port->mod_type == FW_PORT_MOD_TYPE_NONE)
+               csio_info(hw, "Port:%d - port module unplugged\n", port_id);
+       else if (port->mod_type < ARRAY_SIZE(mod_str))
+               csio_info(hw, "Port:%d - %s port module inserted\n", port_id,
+                         mod_str[port->mod_type]);
+       else if (port->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
+               csio_info(hw,
+                         "Port:%d - unsupported optical port module "
+                         "inserted\n", port_id);
+       else if (port->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
+               csio_info(hw,
+                         "Port:%d - unknown port module inserted, forcing "
+                         "TWINAX\n", port_id);
+       else if (port->mod_type == FW_PORT_MOD_TYPE_ERROR)
+               csio_info(hw, "Port:%d - transceiver module error\n", port_id);
+       else
+               csio_info(hw, "Port:%d - unknown module type %d inserted\n",
+                         port_id, port->mod_type);
+}
+
+int
+csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
+{
+       uint8_t opcode = *(uint8_t *)cmd;
+       struct fw_port_cmd *pcmd;
+       uint8_t port_id;
+       uint32_t link_status;
+       uint16_t action;
+       uint8_t mod_type;
+
+       if (opcode == FW_PORT_CMD) {
+               pcmd = (struct fw_port_cmd *)cmd;
+               port_id = FW_PORT_CMD_PORTID_GET(
+                               ntohl(pcmd->op_to_portid));
+               action = FW_PORT_CMD_ACTION_GET(
+                               ntohl(pcmd->action_to_len16));
+               if (action != FW_PORT_ACTION_GET_PORT_INFO) {
+                       csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n",
+                               action);
+                       return -EINVAL;
+               }
+
+               link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
+               mod_type = FW_PORT_CMD_MODTYPE_GET(link_status);
+
+               hw->pport[port_id].link_status =
+                       FW_PORT_CMD_LSTATUS_GET(link_status);
+               hw->pport[port_id].link_speed =
+                       FW_PORT_CMD_LSPEED_GET(link_status);
+
+               csio_info(hw, "Port:%x - LINK %s\n", port_id,
+                       FW_PORT_CMD_LSTATUS_GET(link_status) ? "UP" : "DOWN");
+
+               if (mod_type != hw->pport[port_id].mod_type) {
+                       hw->pport[port_id].mod_type = mod_type;
+                       csio_mb_portmod_changed(hw, port_id);
+               }
+       } else if (opcode == FW_DEBUG_CMD) {
+               csio_mb_dump_fw_dbg(hw, cmd);
+       } else {
+               csio_dbg(hw, "Gen MB can't handle op:0x%x on evtq.\n", opcode);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * csio_mb_isr_handler - Handle mailboxes related interrupts.
+ * @hw: The HW structure
+ *
+ * Called from the ISR to handle Mailbox related interrupts.
+ * HW Lock should be held across this call.
+ */
+int
+csio_mb_isr_handler(struct csio_hw *hw)
+{
+       struct csio_mbm         *mbm = &hw->mbm;
+       struct csio_mb          *mbp =  mbm->mcurrent;
+       __be64                  *cmd;
+       uint32_t                ctl, cim_cause, pl_cause;
+       int                     i;
+       uint32_t                ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL);
+       uint32_t                data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA);
+       int                     size;
+       __be64                  hdr;
+       struct fw_cmd_hdr       *fw_hdr;
+
+       pl_cause = csio_rd_reg32(hw, MYPF_REG(PL_PF_INT_CAUSE));
+       cim_cause = csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_CAUSE));
+
+       if (!(pl_cause & PFCIM) || !(cim_cause & MBMSGRDYINT)) {
+               CSIO_INC_STATS(hw, n_mbint_unexp);
+               return -EINVAL;
+       }
+
+       /*
+        * The cause registers below HAVE to be cleared in the SAME
+        * order as below: The low level cause register followed by
+        * the upper level cause register. In other words, CIM-cause
+        * first followed by PL-Cause next.
+        */
+       csio_wr_reg32(hw, MBMSGRDYINT, MYPF_REG(CIM_PF_HOST_INT_CAUSE));
+       csio_wr_reg32(hw, PFCIM, MYPF_REG(PL_PF_INT_CAUSE));
+
+       ctl = csio_rd_reg32(hw, ctl_reg);
+
+       if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) {
+
+               CSIO_DUMP_MB(hw, hw->pfn, data_reg);
+
+               if (!(ctl & MBMSGVALID)) {
+                       csio_warn(hw,
+                                 "Stray mailbox interrupt recvd,"
+                                 " mailbox data not valid\n");
+                       csio_wr_reg32(hw, 0, ctl_reg);
+                       /* Flush */
+                       csio_rd_reg32(hw, ctl_reg);
+                       return -EINVAL;
+               }
+
+               hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
+               fw_hdr = (struct fw_cmd_hdr *)&hdr;
+
+               switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) {
+               case FW_DEBUG_CMD:
+                       csio_mb_debug_cmd_handler(hw);
+                       return -EINVAL;
+#if 0
+               case FW_ERROR_CMD:
+               case FW_INITIALIZE_CMD: /* When we are not master */
+#endif
+               }
+
+               CSIO_ASSERT(mbp != NULL);
+
+               cmd = mbp->mb;
+               size = mbp->mb_size;
+               /* Get response */
+               for (i = 0; i < size; i += 8)
+                       *cmd++ = cpu_to_be64(csio_rd_reg64
+                                                 (hw, data_reg + i));
+
+               csio_wr_reg32(hw, 0, ctl_reg);
+               /* Flush */
+               csio_rd_reg32(hw, ctl_reg);
+
+               mbm->mcurrent = NULL;
+
+               /* Add completion to tail of cbfn queue */
+               list_add_tail(&mbp->list, &mbm->cbfn_q);
+               CSIO_INC_STATS(mbm, n_cbfnq);
+
+               /*
+                * Enqueue event to EventQ. Events processing happens
+                * in Event worker thread context
+                */
+               if (csio_enqueue_evt(hw, CSIO_EVT_MBX, mbp, sizeof(mbp)))
+                       CSIO_INC_STATS(hw, n_evt_drop);
+
+               return 0;
+
+       } else {
+               /*
+                * We can get here if mailbox MSIX vector is shared,
+                * or in INTx case. Or a stray interrupt.
+                */
+               csio_dbg(hw, "Host not owner, no mailbox interrupt\n");
+               CSIO_INC_STATS(hw, n_int_stray);
+               return -EINVAL;
+       }
+}
+
+/*
+ * csio_mb_tmo_handler - Timeout handler
+ * @hw: The HW structure
+ *
+ */
+struct csio_mb *
+csio_mb_tmo_handler(struct csio_hw *hw)
+{
+       struct csio_mbm *mbm = &hw->mbm;
+       struct csio_mb *mbp =  mbm->mcurrent;
+       struct fw_cmd_hdr *fw_hdr;
+
+       /*
+        * Could be a race b/w the completion handler and the timer
+        * and the completion handler won that race.
+        */
+       if (mbp == NULL) {
+               CSIO_DB_ASSERT(0);
+               return NULL;
+       }
+
+       fw_hdr = (struct fw_cmd_hdr *)(mbp->mb);
+
+       csio_dbg(hw, "Mailbox num:%x op:0x%x timed out\n", hw->pfn,
+                   FW_CMD_OP_GET(ntohl(fw_hdr->hi)));
+
+       mbm->mcurrent = NULL;
+       CSIO_INC_STATS(mbm, n_tmo);
+       fw_hdr->lo = htonl(FW_CMD_RETVAL(FW_ETIMEDOUT));
+
+       return mbp;
+}
+
+/*
+ * csio_mb_cancel_all - Cancel all waiting commands.
+ * @hw: The HW structure
+ * @cbfn_q: The callback queue.
+ *
+ * Caller should hold hw lock across this call.
+ */
+void
+csio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q)
+{
+       struct csio_mb *mbp;
+       struct csio_mbm *mbm = &hw->mbm;
+       struct fw_cmd_hdr *hdr;
+       struct list_head *tmp;
+
+       if (mbm->mcurrent) {
+               mbp = mbm->mcurrent;
+
+               /* Stop mailbox completion timer */
+               del_timer_sync(&mbm->timer);
+
+               /* Add completion to tail of cbfn queue */
+               list_add_tail(&mbp->list, cbfn_q);
+               mbm->mcurrent = NULL;
+       }
+
+       if (!list_empty(&mbm->req_q)) {
+               list_splice_tail_init(&mbm->req_q, cbfn_q);
+               mbm->stats.n_activeq = 0;
+       }
+
+       if (!list_empty(&mbm->cbfn_q)) {
+               list_splice_tail_init(&mbm->cbfn_q, cbfn_q);
+               mbm->stats.n_cbfnq = 0;
+       }
+
+       if (list_empty(cbfn_q))
+               return;
+
+       list_for_each(tmp, cbfn_q) {
+               mbp = (struct csio_mb *)tmp;
+               hdr = (struct fw_cmd_hdr *)(mbp->mb);
+
+               csio_dbg(hw, "Cancelling pending mailbox num %x op:%x\n",
+                           hw->pfn, FW_CMD_OP_GET(ntohl(hdr->hi)));
+
+               CSIO_INC_STATS(mbm, n_cancel);
+               hdr->lo = htonl(FW_CMD_RETVAL(FW_HOSTERROR));
+       }
+}
+
+/*
+ * csio_mbm_init - Initialize Mailbox module
+ * @mbm: Mailbox module
+ * @hw: The HW structure
+ * @timer: Timing function for interrupting mailboxes
+ *
+ * Initialize timer and the request/response queues.
+ */
+int
+csio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw,
+             void (*timer_fn)(uintptr_t))
+{
+       struct timer_list *timer = &mbm->timer;
+
+       init_timer(timer);
+       timer->function = timer_fn;
+       timer->data = (unsigned long)hw;
+
+       INIT_LIST_HEAD(&mbm->req_q);
+       INIT_LIST_HEAD(&mbm->cbfn_q);
+       csio_set_mb_intr_idx(mbm, -1);
+
+       return 0;
+}
+
+/*
+ * csio_mbm_exit - Uninitialize mailbox module
+ * @mbm: Mailbox module
+ *
+ * Stop timer.
+ */
+void
+csio_mbm_exit(struct csio_mbm *mbm)
+{
+       del_timer_sync(&mbm->timer);
+
+       CSIO_DB_ASSERT(mbm->mcurrent == NULL);
+       CSIO_DB_ASSERT(list_empty(&mbm->req_q));
+       CSIO_DB_ASSERT(list_empty(&mbm->cbfn_q));
+}
diff --git a/drivers/scsi/csiostor/csio_mb.h b/drivers/scsi/csiostor/csio_mb.h
new file mode 100644 (file)
index 0000000..1788ea5
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_MB_H__
+#define __CSIO_MB_H__
+
+#include <linux/timer.h>
+#include <linux/completion.h>
+
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+#include "csio_defs.h"
+
+#define CSIO_STATS_OFFSET (2)
+#define CSIO_NUM_STATS_PER_MB (6)
+
+struct fw_fcoe_port_cmd_params {
+       uint8_t         portid;
+       uint8_t         idx;
+       uint8_t         nstats;
+};
+
+#define CSIO_DUMP_MB(__hw, __num, __mb)                                        \
+       csio_dbg(__hw, "\t%llx %llx %llx %llx %llx %llx %llx %llx\n",   \
+               (unsigned long long)csio_rd_reg64(__hw, __mb),          \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 8),      \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 16),     \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 24),     \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 32),     \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 40),     \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 48),     \
+               (unsigned long long)csio_rd_reg64(__hw, __mb + 56))
+
+#define CSIO_MB_MAX_REGS       8
+#define CSIO_MAX_MB_SIZE       64
+#define CSIO_MB_POLL_FREQ      5               /*  5 ms */
+#define CSIO_MB_DEFAULT_TMO    FW_CMD_MAX_TIMEOUT
+
+/* Device master in HELLO command */
+enum csio_dev_master { CSIO_MASTER_CANT, CSIO_MASTER_MAY, CSIO_MASTER_MUST };
+
+enum csio_mb_owner { CSIO_MBOWNER_NONE, CSIO_MBOWNER_FW, CSIO_MBOWNER_PL };
+
+enum csio_dev_state {
+       CSIO_DEV_STATE_UNINIT,
+       CSIO_DEV_STATE_INIT,
+       CSIO_DEV_STATE_ERR
+};
+
+#define FW_PARAM_DEV(param) \
+       (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
+        FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
+
+#define FW_PARAM_PFVF(param) \
+       (FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
+        FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)|  \
+        FW_PARAMS_PARAM_Y(0) | \
+        FW_PARAMS_PARAM_Z(0))
+
+enum {
+       PAUSE_RX      = 1 << 0,
+       PAUSE_TX      = 1 << 1,
+       PAUSE_AUTONEG = 1 << 2
+};
+
+#define CSIO_INIT_MBP(__mbp, __cp,  __tmo, __priv, __fn, __clear)      \
+do {                                                                   \
+       if (__clear)                                                    \
+               memset((__cp), 0,                                       \
+                           CSIO_MB_MAX_REGS * sizeof(__be64));         \
+       INIT_LIST_HEAD(&(__mbp)->list);                                 \
+       (__mbp)->tmo            = (__tmo);                              \
+       (__mbp)->priv           = (void *)(__priv);                     \
+       (__mbp)->mb_cbfn        = (__fn);                               \
+       (__mbp)->mb_size        = sizeof(*(__cp));                      \
+} while (0)
+
+struct csio_mbm_stats {
+       uint32_t        n_req;          /* number of mbox req */
+       uint32_t        n_rsp;          /* number of mbox rsp */
+       uint32_t        n_activeq;      /* number of mbox req active Q */
+       uint32_t        n_cbfnq;        /* number of mbox req cbfn Q */
+       uint32_t        n_tmo;          /* number of mbox timeout */
+       uint32_t        n_cancel;       /* number of mbox cancel */
+       uint32_t        n_err;          /* number of mbox error */
+};
+
+/* Driver version of Mailbox */
+struct csio_mb {
+       struct list_head        list;                   /* for req/resp */
+                                                       /* queue in driver */
+       __be64                  mb[CSIO_MB_MAX_REGS];   /* MB in HW format */
+       int                     mb_size;                /* Size of this
+                                                        * mailbox.
+                                                        */
+       uint32_t                tmo;                    /* Timeout */
+       struct completion       cmplobj;                /* MB Completion
+                                                        * object
+                                                        */
+       void                    (*mb_cbfn) (struct csio_hw *, struct csio_mb *);
+                                                       /* Callback fn */
+       void                    *priv;                  /* Owner private ptr */
+};
+
+struct csio_mbm {
+       uint32_t                a_mbox;                 /* Async mbox num */
+       uint32_t                intr_idx;               /* Interrupt index */
+       struct timer_list       timer;                  /* Mbox timer */
+       struct list_head        req_q;                  /* Mbox request queue */
+       struct list_head        cbfn_q;                 /* Mbox completion q */
+       struct csio_mb          *mcurrent;              /* Current mailbox */
+       uint32_t                req_q_cnt;              /* Outstanding mbox
+                                                        * cmds
+                                                        */
+       struct csio_mbm_stats   stats;                  /* Statistics */
+};
+
+#define csio_set_mb_intr_idx(_m, _i)   ((_m)->intr_idx = (_i))
+#define csio_get_mb_intr_idx(_m)       ((_m)->intr_idx)
+
+struct csio_iq_params;
+struct csio_eq_params;
+
+enum fw_retval csio_mb_fw_retval(struct csio_mb *);
+
+/* MB helpers */
+void csio_mb_hello(struct csio_hw *, struct csio_mb *, uint32_t,
+                  uint32_t, uint32_t, enum csio_dev_master,
+                  void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_hello_rsp(struct csio_hw *, struct csio_mb *,
+                              enum fw_retval *, enum csio_dev_state *,
+                              uint8_t *);
+
+void csio_mb_bye(struct csio_hw *, struct csio_mb *, uint32_t,
+                void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_reset(struct csio_hw *, struct csio_mb *, uint32_t, int, int,
+                  void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_params(struct csio_hw *, struct csio_mb *, uint32_t, unsigned int,
+                   unsigned int, unsigned int, const u32 *, u32 *, bool,
+                   void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_read_params_rsp(struct csio_hw *, struct csio_mb *,
+                               enum fw_retval *, unsigned int , u32 *);
+
+void csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+                 int reg);
+
+void csio_mb_caps_config(struct csio_hw *, struct csio_mb *, uint32_t,
+                           bool, bool, bool, bool,
+                           void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_rss_glb_config(struct csio_hw *, struct csio_mb *,
+                        uint32_t, uint8_t, unsigned int,
+                        void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_pfvf(struct csio_hw *, struct csio_mb *, uint32_t,
+                 unsigned int, unsigned int, unsigned int,
+                 unsigned int, unsigned int, unsigned int,
+                 unsigned int, unsigned int, unsigned int,
+                 unsigned int, unsigned int, unsigned int,
+                 unsigned int, void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
+                 uint8_t, bool, uint32_t, uint16_t,
+                 void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_read_port_rsp(struct csio_hw *, struct csio_mb *,
+                                  enum fw_retval *, uint16_t *);
+
+void csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t,
+                       void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_iq_alloc_write(struct csio_hw *, struct csio_mb *, void *,
+                       uint32_t, struct csio_iq_params *,
+                       void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_iq_alloc_write_rsp(struct csio_hw *, struct csio_mb *,
+                               enum fw_retval *, struct csio_iq_params *);
+
+void csio_mb_iq_free(struct csio_hw *, struct csio_mb *, void *,
+                    uint32_t, struct csio_iq_params *,
+                    void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_eq_ofld_alloc_write(struct csio_hw *, struct csio_mb *, void *,
+                                uint32_t, struct csio_eq_params *,
+                                void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *, struct csio_mb *,
+                                    enum fw_retval *, struct csio_eq_params *);
+
+void csio_mb_eq_ofld_free(struct csio_hw *, struct csio_mb *, void *,
+                         uint32_t , struct csio_eq_params *,
+                         void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_res_info_init_mb(struct csio_hw *, struct csio_mb *,
+                       uint32_t,
+                       void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_write_fcoe_link_cond_init_mb(struct csio_lnode *, struct csio_mb *,
+                       uint32_t, uint8_t, uint32_t, uint8_t, bool, uint32_t,
+                       void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *, struct csio_mb *,
+                       uint32_t, uint32_t , uint32_t , uint16_t,
+                       uint8_t [8], uint8_t [8],
+                       void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_read_init_mb(struct csio_lnode *, struct csio_mb *,
+                       uint32_t, uint32_t , uint32_t ,
+                       void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_free_init_mb(struct csio_lnode *, struct csio_mb *,
+                       uint32_t , uint32_t, uint32_t ,
+                       void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_fcf_init_mb(struct csio_lnode *, struct csio_mb *,
+                       uint32_t, uint32_t, uint32_t,
+                       void (*cbfn) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_portparams_init_mb(struct csio_hw *hw,
+                       struct csio_mb *mbp, uint32_t mb_tmo,
+                       struct fw_fcoe_port_cmd_params *portparams,
+                       void (*cbfn)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_portparams_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+                               enum fw_retval *retval,
+                               struct fw_fcoe_port_cmd_params *portparams,
+                               struct fw_fcoe_port_stats *portstats);
+
+/* MB module functions */
+int csio_mbm_init(struct csio_mbm *, struct csio_hw *,
+                           void (*)(uintptr_t));
+void csio_mbm_exit(struct csio_mbm *);
+void csio_mb_intr_enable(struct csio_hw *);
+void csio_mb_intr_disable(struct csio_hw *);
+
+int csio_mb_issue(struct csio_hw *, struct csio_mb *);
+void csio_mb_completions(struct csio_hw *, struct list_head *);
+int csio_mb_fwevt_handler(struct csio_hw *, __be64 *);
+int csio_mb_isr_handler(struct csio_hw *);
+struct csio_mb *csio_mb_tmo_handler(struct csio_hw *);
+void csio_mb_cancel_all(struct csio_hw *, struct list_head *);
+
+#endif /* ifndef __CSIO_MB_H__ */
diff --git a/drivers/scsi/csiostor/csio_rnode.c b/drivers/scsi/csiostor/csio_rnode.c
new file mode 100644 (file)
index 0000000..51c6a38
--- /dev/null
@@ -0,0 +1,913 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/string.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+
+static int csio_rnode_init(struct csio_rnode *, struct csio_lnode *);
+static void csio_rnode_exit(struct csio_rnode *);
+
+/* Static machine forward declarations */
+static void csio_rns_uninit(struct csio_rnode *, enum csio_rn_ev);
+static void csio_rns_ready(struct csio_rnode *, enum csio_rn_ev);
+static void csio_rns_offline(struct csio_rnode *, enum csio_rn_ev);
+static void csio_rns_disappeared(struct csio_rnode *, enum csio_rn_ev);
+
+/* RNF event mapping */
+static enum csio_rn_ev fwevt_to_rnevt[] = {
+       CSIO_RNFE_NONE,         /* None */
+       CSIO_RNFE_LOGGED_IN,    /* PLOGI_ACC_RCVD  */
+       CSIO_RNFE_NONE,         /* PLOGI_RJT_RCVD  */
+       CSIO_RNFE_PLOGI_RECV,   /* PLOGI_RCVD      */
+       CSIO_RNFE_LOGO_RECV,    /* PLOGO_RCVD      */
+       CSIO_RNFE_PRLI_DONE,    /* PRLI_ACC_RCVD   */
+       CSIO_RNFE_NONE,         /* PRLI_RJT_RCVD   */
+       CSIO_RNFE_PRLI_RECV,    /* PRLI_RCVD       */
+       CSIO_RNFE_PRLO_RECV,    /* PRLO_RCVD       */
+       CSIO_RNFE_NONE,         /* NPORT_ID_CHGD   */
+       CSIO_RNFE_LOGO_RECV,    /* FLOGO_RCVD      */
+       CSIO_RNFE_NONE,         /* CLR_VIRT_LNK_RCVD */
+       CSIO_RNFE_LOGGED_IN,    /* FLOGI_ACC_RCVD   */
+       CSIO_RNFE_NONE,         /* FLOGI_RJT_RCVD   */
+       CSIO_RNFE_LOGGED_IN,    /* FDISC_ACC_RCVD   */
+       CSIO_RNFE_NONE,         /* FDISC_RJT_RCVD   */
+       CSIO_RNFE_NONE,         /* FLOGI_TMO_MAX_RETRY */
+       CSIO_RNFE_NONE,         /* IMPL_LOGO_ADISC_ACC */
+       CSIO_RNFE_NONE,         /* IMPL_LOGO_ADISC_RJT */
+       CSIO_RNFE_NONE,         /* IMPL_LOGO_ADISC_CNFLT */
+       CSIO_RNFE_NONE,         /* PRLI_TMO             */
+       CSIO_RNFE_NONE,         /* ADISC_TMO            */
+       CSIO_RNFE_NAME_MISSING, /* RSCN_DEV_LOST  */
+       CSIO_RNFE_NONE,         /* SCR_ACC_RCVD */
+       CSIO_RNFE_NONE,         /* ADISC_RJT_RCVD */
+       CSIO_RNFE_NONE,         /* LOGO_SNT */
+       CSIO_RNFE_LOGO_RECV,    /* PROTO_ERR_IMPL_LOGO */
+};
+
+#define CSIO_FWE_TO_RNFE(_evt) ((_evt > PROTO_ERR_IMPL_LOGO) ?         \
+                                               CSIO_RNFE_NONE :        \
+                                               fwevt_to_rnevt[_evt])
+int
+csio_is_rnode_ready(struct csio_rnode *rn)
+{
+       return csio_match_state(rn, csio_rns_ready);
+}
+
+static int
+csio_is_rnode_uninit(struct csio_rnode *rn)
+{
+       return csio_match_state(rn, csio_rns_uninit);
+}
+
+static int
+csio_is_rnode_wka(uint8_t rport_type)
+{
+       if ((rport_type == FLOGI_VFPORT) ||
+           (rport_type == FDISC_VFPORT) ||
+           (rport_type == NS_VNPORT) ||
+           (rport_type == FDMI_VNPORT))
+               return 1;
+
+       return 0;
+}
+
+/*
+ * csio_rn_lookup - Finds the rnode with the given flowid
+ * @ln - lnode
+ * @flowid - flowid.
+ *
+ * Does the rnode lookup on the given lnode and flowid.If no matching entry
+ * found, NULL is returned.
+ */
+static struct csio_rnode *
+csio_rn_lookup(struct csio_lnode *ln, uint32_t flowid)
+{
+       struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+       struct list_head *tmp;
+       struct csio_rnode *rn;
+
+       list_for_each(tmp, &rnhead->sm.sm_list) {
+               rn = (struct csio_rnode *) tmp;
+               if (rn->flowid == flowid)
+                       return rn;
+       }
+
+       return NULL;
+}
+
+/*
+ * csio_rn_lookup_wwpn - Finds the rnode with the given wwpn
+ * @ln: lnode
+ * @wwpn: wwpn
+ *
+ * Does the rnode lookup on the given lnode and wwpn. If no matching entry
+ * found, NULL is returned.
+ */
+static struct csio_rnode *
+csio_rn_lookup_wwpn(struct csio_lnode *ln, uint8_t *wwpn)
+{
+       struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+       struct list_head *tmp;
+       struct csio_rnode *rn;
+
+       list_for_each(tmp, &rnhead->sm.sm_list) {
+               rn = (struct csio_rnode *) tmp;
+               if (!memcmp(csio_rn_wwpn(rn), wwpn, 8))
+                       return rn;
+       }
+
+       return NULL;
+}
+
+/**
+ * csio_rnode_lookup_portid - Finds the rnode with the given portid
+ * @ln:                lnode
+ * @portid:    port id
+ *
+ * Lookup the rnode list for a given portid. If no matching entry
+ * found, NULL is returned.
+ */
+struct csio_rnode *
+csio_rnode_lookup_portid(struct csio_lnode *ln, uint32_t portid)
+{
+       struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+       struct list_head *tmp;
+       struct csio_rnode *rn;
+
+       list_for_each(tmp, &rnhead->sm.sm_list) {
+               rn = (struct csio_rnode *) tmp;
+               if (rn->nport_id == portid)
+                       return rn;
+       }
+
+       return NULL;
+}
+
+static int
+csio_rn_dup_flowid(struct csio_lnode *ln, uint32_t rdev_flowid,
+                   uint32_t *vnp_flowid)
+{
+       struct csio_rnode *rnhead;
+       struct list_head *tmp, *tmp1;
+       struct csio_rnode *rn;
+       struct csio_lnode *ln_tmp;
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       list_for_each(tmp1, &hw->sln_head) {
+               ln_tmp = (struct csio_lnode *) tmp1;
+               if (ln_tmp == ln)
+                       continue;
+
+               rnhead = (struct csio_rnode *)&ln_tmp->rnhead;
+               list_for_each(tmp, &rnhead->sm.sm_list) {
+
+                       rn = (struct csio_rnode *) tmp;
+                       if (csio_is_rnode_ready(rn)) {
+                               if (rn->flowid == rdev_flowid) {
+                                       *vnp_flowid = csio_ln_flowid(ln_tmp);
+                                       return 1;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static struct csio_rnode *
+csio_alloc_rnode(struct csio_lnode *ln)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       struct csio_rnode *rn = mempool_alloc(hw->rnode_mempool, GFP_ATOMIC);
+       if (!rn)
+               goto err;
+
+       memset(rn, 0, sizeof(struct csio_rnode));
+       if (csio_rnode_init(rn, ln))
+               goto err_free;
+
+       CSIO_INC_STATS(ln, n_rnode_alloc);
+
+       return rn;
+
+err_free:
+       mempool_free(rn, hw->rnode_mempool);
+err:
+       CSIO_INC_STATS(ln, n_rnode_nomem);
+       return NULL;
+}
+
+static void
+csio_free_rnode(struct csio_rnode *rn)
+{
+       struct csio_hw *hw = csio_lnode_to_hw(csio_rnode_to_lnode(rn));
+
+       csio_rnode_exit(rn);
+       CSIO_INC_STATS(rn->lnp, n_rnode_free);
+       mempool_free(rn, hw->rnode_mempool);
+}
+
+/*
+ * csio_get_rnode - Gets rnode with the given flowid
+ * @ln - lnode
+ * @flowid - flow id.
+ *
+ * Does the rnode lookup on the given lnode and flowid. If no matching
+ * rnode found, then new rnode with given npid is allocated and returned.
+ */
+static struct csio_rnode *
+csio_get_rnode(struct csio_lnode *ln, uint32_t flowid)
+{
+       struct csio_rnode *rn;
+
+       rn = csio_rn_lookup(ln, flowid);
+       if (!rn) {
+               rn = csio_alloc_rnode(ln);
+               if (!rn)
+                       return NULL;
+
+               rn->flowid = flowid;
+       }
+
+       return rn;
+}
+
+/*
+ * csio_put_rnode - Frees the given rnode
+ * @ln - lnode
+ * @flowid - flow id.
+ *
+ * Does the rnode lookup on the given lnode and flowid. If no matching
+ * rnode found, then new rnode with given npid is allocated and returned.
+ */
+void
+csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn)
+{
+       CSIO_DB_ASSERT(csio_is_rnode_uninit(rn) != 0);
+       csio_free_rnode(rn);
+}
+
+/*
+ * csio_confirm_rnode - confirms rnode based on wwpn.
+ * @ln: lnode
+ * @rdev_flowid: remote device flowid
+ * @rdevp: remote device params
+ * This routines searches other rnode in list having same wwpn of new rnode.
+ * If there is a match, then matched rnode is returned and otherwise new rnode
+ * is returned.
+ * returns rnode.
+ */
+struct csio_rnode *
+csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
+                  struct fcoe_rdev_entry *rdevp)
+{
+       uint8_t rport_type;
+       struct csio_rnode *rn, *match_rn;
+       uint32_t vnp_flowid;
+       __be32 *port_id;
+
+       port_id = (__be32 *)&rdevp->r_id[0];
+       rport_type =
+               FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
+
+       /* Drop rdev event for cntrl port */
+       if (rport_type == FAB_CTLR_VNPORT) {
+               csio_ln_dbg(ln,
+                           "Unhandled rport_type:%d recv in rdev evt "
+                           "ssni:x%x\n", rport_type, rdev_flowid);
+               return NULL;
+       }
+
+       /* Lookup on flowid */
+       rn = csio_rn_lookup(ln, rdev_flowid);
+       if (!rn) {
+
+               /* Drop events with duplicate flowid */
+               if (csio_rn_dup_flowid(ln, rdev_flowid, &vnp_flowid)) {
+                       csio_ln_warn(ln,
+                                    "ssni:%x already active on vnpi:%x",
+                                    rdev_flowid, vnp_flowid);
+                       return NULL;
+               }
+
+               /* Lookup on wwpn for NPORTs */
+               rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
+               if (!rn)
+                       goto alloc_rnode;
+
+       } else {
+               /* Lookup well-known ports with nport id */
+               if (csio_is_rnode_wka(rport_type)) {
+                       match_rn = csio_rnode_lookup_portid(ln,
+                                     ((ntohl(*port_id) >> 8) & CSIO_DID_MASK));
+                       if (match_rn == NULL) {
+                               csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+                               goto alloc_rnode;
+                       }
+
+                       /*
+                        * Now compare the wwpn to confirm that
+                        * same port relogged in. If so update the matched rn.
+                        * Else, go ahead and alloc a new rnode.
+                        */
+                       if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
+                               if (csio_is_rnode_ready(rn)) {
+                                       csio_ln_warn(ln,
+                                                    "rnode is already"
+                                                    "active ssni:x%x\n",
+                                                    rdev_flowid);
+                                       CSIO_ASSERT(0);
+                               }
+                               csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+                               rn = match_rn;
+
+                               /* Update rn */
+                               goto found_rnode;
+                       }
+                       csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+                       goto alloc_rnode;
+               }
+
+               /* wwpn match */
+               if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
+                       goto found_rnode;
+
+               /* Search for rnode that have same wwpn */
+               match_rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
+               if (match_rn != NULL) {
+                       csio_ln_dbg(ln,
+                               "ssni:x%x changed for rport name(wwpn):%llx "
+                               "did:x%x\n", rdev_flowid,
+                               wwn_to_u64(rdevp->wwpn),
+                               match_rn->nport_id);
+                       csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+                       rn = match_rn;
+               } else {
+                       csio_ln_dbg(ln,
+                               "rnode wwpn mismatch found ssni:x%x "
+                               "name(wwpn):%llx\n",
+                               rdev_flowid,
+                               wwn_to_u64(csio_rn_wwpn(rn)));
+                       if (csio_is_rnode_ready(rn)) {
+                               csio_ln_warn(ln,
+                                            "rnode is already active "
+                                            "wwpn:%llx ssni:x%x\n",
+                                            wwn_to_u64(csio_rn_wwpn(rn)),
+                                            rdev_flowid);
+                               CSIO_ASSERT(0);
+                       }
+                       csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+                       goto alloc_rnode;
+               }
+       }
+
+found_rnode:
+       csio_ln_dbg(ln, "found rnode:%p ssni:x%x name(wwpn):%llx\n",
+               rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
+
+       /* Update flowid */
+       csio_rn_flowid(rn) = rdev_flowid;
+
+       /* update rdev entry */
+       rn->rdev_entry = rdevp;
+       CSIO_INC_STATS(ln, n_rnode_match);
+       return rn;
+
+alloc_rnode:
+       rn = csio_get_rnode(ln, rdev_flowid);
+       if (!rn)
+               return NULL;
+
+       csio_ln_dbg(ln, "alloc rnode:%p ssni:x%x name(wwpn):%llx\n",
+               rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
+
+       /* update rdev entry */
+       rn->rdev_entry = rdevp;
+       return rn;
+}
+
+/*
+ * csio_rn_verify_rparams - verify rparams.
+ * @ln: lnode
+ * @rn: rnode
+ * @rdevp: remote device params
+ * returns success if rparams are verified.
+ */
+static int
+csio_rn_verify_rparams(struct csio_lnode *ln, struct csio_rnode *rn,
+                       struct fcoe_rdev_entry *rdevp)
+{
+       uint8_t null[8];
+       uint8_t rport_type;
+       uint8_t fc_class;
+       __be32 *did;
+
+       did = (__be32 *) &rdevp->r_id[0];
+       rport_type =
+               FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
+       switch (rport_type) {
+       case FLOGI_VFPORT:
+               rn->role = CSIO_RNFR_FABRIC;
+               if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_FLOGI) {
+                       csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
+                               csio_rn_flowid(rn));
+                       return -EINVAL;
+               }
+               /* NPIV support */
+               if (FW_RDEV_WR_NPIV_GET(rdevp->vft_to_qos))
+                       ln->flags |= CSIO_LNF_NPIVSUPP;
+
+               break;
+
+       case NS_VNPORT:
+               rn->role = CSIO_RNFR_NS;
+               if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_DIR_SERV) {
+                       csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
+                               csio_rn_flowid(rn));
+                       return -EINVAL;
+               }
+               break;
+
+       case REG_FC4_VNPORT:
+       case REG_VNPORT:
+               rn->role = CSIO_RNFR_NPORT;
+               if (rdevp->event_cause == PRLI_ACC_RCVD ||
+                       rdevp->event_cause == PRLI_RCVD) {
+                       if (FW_RDEV_WR_TASK_RETRY_ID_GET(
+                                                       rdevp->enh_disc_to_tgt))
+                               rn->fcp_flags |= FCP_SPPF_OVLY_ALLOW;
+
+                       if (FW_RDEV_WR_RETRY_GET(rdevp->enh_disc_to_tgt))
+                               rn->fcp_flags |= FCP_SPPF_RETRY;
+
+                       if (FW_RDEV_WR_CONF_CMPL_GET(rdevp->enh_disc_to_tgt))
+                               rn->fcp_flags |= FCP_SPPF_CONF_COMPL;
+
+                       if (FW_RDEV_WR_TGT_GET(rdevp->enh_disc_to_tgt))
+                               rn->role |= CSIO_RNFR_TARGET;
+
+                       if (FW_RDEV_WR_INI_GET(rdevp->enh_disc_to_tgt))
+                               rn->role |= CSIO_RNFR_INITIATOR;
+               }
+
+               break;
+
+       case FDMI_VNPORT:
+       case FAB_CTLR_VNPORT:
+               rn->role = 0;
+               break;
+
+       default:
+               csio_ln_err(ln, "ssni:x%x invalid rport type recv x%x\n",
+                       csio_rn_flowid(rn), rport_type);
+               return -EINVAL;
+       }
+
+       /* validate wwpn/wwnn for Name server/remote port */
+       if (rport_type == REG_VNPORT || rport_type == NS_VNPORT) {
+               memset(null, 0, 8);
+               if (!memcmp(rdevp->wwnn, null, 8)) {
+                       csio_ln_err(ln,
+                                   "ssni:x%x invalid wwnn received from"
+                                   " rport did:x%x\n",
+                                   csio_rn_flowid(rn),
+                                   (ntohl(*did) & CSIO_DID_MASK));
+                       return -EINVAL;
+               }
+
+               if (!memcmp(rdevp->wwpn, null, 8)) {
+                       csio_ln_err(ln,
+                                   "ssni:x%x invalid wwpn received from"
+                                   " rport did:x%x\n",
+                                   csio_rn_flowid(rn),
+                                   (ntohl(*did) & CSIO_DID_MASK));
+                       return -EINVAL;
+               }
+
+       }
+
+       /* Copy wwnn, wwpn and nport id */
+       rn->nport_id = (ntohl(*did) >> 8) & CSIO_DID_MASK;
+       memcpy(csio_rn_wwnn(rn), rdevp->wwnn, 8);
+       memcpy(csio_rn_wwpn(rn), rdevp->wwpn, 8);
+       rn->rn_sparm.csp.sp_bb_data = rdevp->rcv_fr_sz;
+       fc_class = FW_RDEV_WR_CLASS_GET(rdevp->vft_to_qos);
+       rn->rn_sparm.clsp[fc_class - 1].cp_class = htons(FC_CPC_VALID);
+
+       return 0;
+}
+
+static void
+__csio_reg_rnode(struct csio_rnode *rn)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       spin_unlock_irq(&hw->lock);
+       csio_reg_rnode(rn);
+       spin_lock_irq(&hw->lock);
+
+       if (rn->role & CSIO_RNFR_TARGET)
+               ln->n_scsi_tgts++;
+
+       if (rn->nport_id == FC_FID_MGMT_SERV)
+               csio_ln_fdmi_start(ln, (void *) rn);
+}
+
+static void
+__csio_unreg_rnode(struct csio_rnode *rn)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       LIST_HEAD(tmp_q);
+       int cmpl = 0;
+
+       if (!list_empty(&rn->host_cmpl_q)) {
+               csio_dbg(hw, "Returning completion queue I/Os\n");
+               list_splice_tail_init(&rn->host_cmpl_q, &tmp_q);
+               cmpl = 1;
+       }
+
+       if (rn->role & CSIO_RNFR_TARGET) {
+               ln->n_scsi_tgts--;
+               ln->last_scan_ntgts--;
+       }
+
+       spin_unlock_irq(&hw->lock);
+       csio_unreg_rnode(rn);
+       spin_lock_irq(&hw->lock);
+
+       /* Cleanup I/Os that were waiting for rnode to unregister */
+       if (cmpl)
+               csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
+
+}
+
+/*****************************************************************************/
+/* START: Rnode SM                                                           */
+/*****************************************************************************/
+
+/*
+ * csio_rns_uninit -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_uninit(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       int ret = 0;
+
+       CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_RNFE_LOGGED_IN:
+       case CSIO_RNFE_PLOGI_RECV:
+               ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+               if (!ret) {
+                       csio_set_state(&rn->sm, csio_rns_ready);
+                       __csio_reg_rnode(rn);
+               } else {
+                       CSIO_INC_STATS(rn, n_err_inval);
+               }
+               break;
+       case CSIO_RNFE_LOGO_RECV:
+               csio_ln_dbg(ln,
+                           "ssni:x%x Ignoring event %d recv "
+                           "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
+               CSIO_INC_STATS(rn, n_evt_drop);
+               break;
+       default:
+               csio_ln_dbg(ln,
+                           "ssni:x%x unexp event %d recv "
+                           "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
+               CSIO_INC_STATS(rn, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_rns_ready -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_ready(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       int ret = 0;
+
+       CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_RNFE_LOGGED_IN:
+       case CSIO_RNFE_PLOGI_RECV:
+               csio_ln_dbg(ln,
+                       "ssni:x%x Ignoring event %d recv from did:x%x "
+                       "in rn state[ready]\n", csio_rn_flowid(rn), evt,
+                       rn->nport_id);
+               CSIO_INC_STATS(rn, n_evt_drop);
+               break;
+
+       case CSIO_RNFE_PRLI_DONE:
+       case CSIO_RNFE_PRLI_RECV:
+               ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+               if (!ret)
+                       __csio_reg_rnode(rn);
+               else
+                       CSIO_INC_STATS(rn, n_err_inval);
+
+               break;
+       case CSIO_RNFE_DOWN:
+               csio_set_state(&rn->sm, csio_rns_offline);
+               __csio_unreg_rnode(rn);
+
+               /* FW expected to internally aborted outstanding SCSI WRs
+                * and return all SCSI WRs to host with status "ABORTED".
+                */
+               break;
+
+       case CSIO_RNFE_LOGO_RECV:
+               csio_set_state(&rn->sm, csio_rns_offline);
+
+               __csio_unreg_rnode(rn);
+
+               /* FW expected to internally aborted outstanding SCSI WRs
+                * and return all SCSI WRs to host with status "ABORTED".
+                */
+               break;
+
+       case CSIO_RNFE_CLOSE:
+               /*
+                * Each rnode receives CLOSE event when driver is removed or
+                * device is reset
+                * Note: All outstanding IOs on remote port need to returned
+                * to uppper layer with appropriate error before sending
+                * CLOSE event
+                */
+               csio_set_state(&rn->sm, csio_rns_uninit);
+               __csio_unreg_rnode(rn);
+               break;
+
+       case CSIO_RNFE_NAME_MISSING:
+               csio_set_state(&rn->sm, csio_rns_disappeared);
+               __csio_unreg_rnode(rn);
+
+               /*
+                * FW expected to internally aborted outstanding SCSI WRs
+                * and return all SCSI WRs to host with status "ABORTED".
+                */
+
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                       "ssni:x%x unexp event %d recv from did:x%x "
+                       "in rn state[uninit]\n", csio_rn_flowid(rn), evt,
+                       rn->nport_id);
+               CSIO_INC_STATS(rn, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_rns_offline -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_offline(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       int ret = 0;
+
+       CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_RNFE_LOGGED_IN:
+       case CSIO_RNFE_PLOGI_RECV:
+               ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+               if (!ret) {
+                       csio_set_state(&rn->sm, csio_rns_ready);
+                       __csio_reg_rnode(rn);
+               } else {
+                       CSIO_INC_STATS(rn, n_err_inval);
+                       csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
+               }
+               break;
+
+       case CSIO_RNFE_DOWN:
+               csio_ln_dbg(ln,
+                       "ssni:x%x Ignoring event %d recv from did:x%x "
+                       "in rn state[offline]\n", csio_rn_flowid(rn), evt,
+                       rn->nport_id);
+               CSIO_INC_STATS(rn, n_evt_drop);
+               break;
+
+       case CSIO_RNFE_CLOSE:
+               /* Each rnode receives CLOSE event when driver is removed or
+                * device is reset
+                * Note: All outstanding IOs on remote port need to returned
+                * to uppper layer with appropriate error before sending
+                * CLOSE event
+                */
+               csio_set_state(&rn->sm, csio_rns_uninit);
+               break;
+
+       case CSIO_RNFE_NAME_MISSING:
+               csio_set_state(&rn->sm, csio_rns_disappeared);
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                       "ssni:x%x unexp event %d recv from did:x%x "
+                       "in rn state[offline]\n", csio_rn_flowid(rn), evt,
+                       rn->nport_id);
+               CSIO_INC_STATS(rn, n_evt_unexp);
+               break;
+       }
+}
+
+/*
+ * csio_rns_disappeared -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_disappeared(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       int ret = 0;
+
+       CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+       switch (evt) {
+       case CSIO_RNFE_LOGGED_IN:
+       case CSIO_RNFE_PLOGI_RECV:
+               ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+               if (!ret) {
+                       csio_set_state(&rn->sm, csio_rns_ready);
+                       __csio_reg_rnode(rn);
+               } else {
+                       CSIO_INC_STATS(rn, n_err_inval);
+                       csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
+               }
+               break;
+
+       case CSIO_RNFE_CLOSE:
+               /* Each rnode receives CLOSE event when driver is removed or
+                * device is reset.
+                * Note: All outstanding IOs on remote port need to returned
+                * to uppper layer with appropriate error before sending
+                * CLOSE event
+                */
+               csio_set_state(&rn->sm, csio_rns_uninit);
+               break;
+
+       case CSIO_RNFE_DOWN:
+       case CSIO_RNFE_NAME_MISSING:
+               csio_ln_dbg(ln,
+                       "ssni:x%x Ignoring event %d recv from did x%x"
+                       "in rn state[disappeared]\n", csio_rn_flowid(rn),
+                       evt, rn->nport_id);
+               break;
+
+       default:
+               csio_ln_dbg(ln,
+                       "ssni:x%x unexp event %d recv from did x%x"
+                       "in rn state[disappeared]\n", csio_rn_flowid(rn),
+                       evt, rn->nport_id);
+               CSIO_INC_STATS(rn, n_evt_unexp);
+               break;
+       }
+}
+
+/*****************************************************************************/
+/* END: Rnode SM                                                             */
+/*****************************************************************************/
+
+/*
+ * csio_rnode_devloss_handler - Device loss event handler
+ * @rn: rnode
+ *
+ * Post event to close rnode SM and free rnode.
+ */
+void
+csio_rnode_devloss_handler(struct csio_rnode *rn)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+
+       /* ignore if same rnode came back as online */
+       if (csio_is_rnode_ready(rn))
+               return;
+
+       csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
+
+       /* Free rn if in uninit state */
+       if (csio_is_rnode_uninit(rn))
+               csio_put_rnode(ln, rn);
+}
+
+/**
+ * csio_rnode_fwevt_handler - Event handler for firmware rnode events.
+ * @rn:                rnode
+ *
+ */
+void
+csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
+{
+       struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+       enum csio_rn_ev evt;
+
+       evt = CSIO_FWE_TO_RNFE(fwevt);
+       if (!evt) {
+               csio_ln_err(ln, "ssni:x%x Unhandled FW Rdev event: %d\n",
+                           csio_rn_flowid(rn), fwevt);
+               CSIO_INC_STATS(rn, n_evt_unexp);
+               return;
+       }
+       CSIO_INC_STATS(rn, n_evt_fw[fwevt]);
+
+       /* Track previous & current events for debugging */
+       rn->prev_evt = rn->cur_evt;
+       rn->cur_evt = fwevt;
+
+       /* Post event to rnode SM */
+       csio_post_event(&rn->sm, evt);
+
+       /* Free rn if in uninit state */
+       if (csio_is_rnode_uninit(rn))
+               csio_put_rnode(ln, rn);
+}
+
+/*
+ * csio_rnode_init - Initialize rnode.
+ * @rn: RNode
+ * @ln: Associated lnode
+ *
+ * Caller is responsible for holding the lock. The lock is required
+ * to be held for inserting the rnode in ln->rnhead list.
+ */
+static int
+csio_rnode_init(struct csio_rnode *rn, struct csio_lnode *ln)
+{
+       csio_rnode_to_lnode(rn) = ln;
+       csio_init_state(&rn->sm, csio_rns_uninit);
+       INIT_LIST_HEAD(&rn->host_cmpl_q);
+       csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+
+       /* Add rnode to list of lnodes->rnhead */
+       list_add_tail(&rn->sm.sm_list, &ln->rnhead);
+
+       return 0;
+}
+
+static void
+csio_rnode_exit(struct csio_rnode *rn)
+{
+       list_del_init(&rn->sm.sm_list);
+       CSIO_DB_ASSERT(list_empty(&rn->host_cmpl_q));
+}
diff --git a/drivers/scsi/csiostor/csio_rnode.h b/drivers/scsi/csiostor/csio_rnode.h
new file mode 100644 (file)
index 0000000..a3b434c
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_RNODE_H__
+#define __CSIO_RNODE_H__
+
+#include "csio_defs.h"
+
+/* State machine evets */
+enum csio_rn_ev {
+       CSIO_RNFE_NONE = (uint32_t)0,                   /* None */
+       CSIO_RNFE_LOGGED_IN,                            /* [N/F]Port login
+                                                        * complete.
+                                                        */
+       CSIO_RNFE_PRLI_DONE,                            /* PRLI completed */
+       CSIO_RNFE_PLOGI_RECV,                           /* Received PLOGI */
+       CSIO_RNFE_PRLI_RECV,                            /* Received PLOGI */
+       CSIO_RNFE_LOGO_RECV,                            /* Received LOGO */
+       CSIO_RNFE_PRLO_RECV,                            /* Received PRLO */
+       CSIO_RNFE_DOWN,                                 /* Rnode is down */
+       CSIO_RNFE_CLOSE,                                /* Close rnode */
+       CSIO_RNFE_NAME_MISSING,                         /* Rnode name missing
+                                                        * in name server.
+                                                        */
+       CSIO_RNFE_MAX_EVENT,
+};
+
+/* rnode stats */
+struct csio_rnode_stats {
+       uint32_t        n_err;          /* error */
+       uint32_t        n_err_inval;    /* invalid parameter */
+       uint32_t        n_err_nomem;    /* error nomem */
+       uint32_t        n_evt_unexp;    /* unexpected event */
+       uint32_t        n_evt_drop;     /* unexpected event */
+       uint32_t        n_evt_fw[RSCN_DEV_LOST];        /* fw events */
+       enum csio_rn_ev n_evt_sm[CSIO_RNFE_MAX_EVENT];  /* State m/c events */
+       uint32_t        n_lun_rst;      /* Number of resets of
+                                        * of LUNs under this
+                                        * target
+                                        */
+       uint32_t        n_lun_rst_fail; /* Number of LUN reset
+                                        * failures.
+                                        */
+       uint32_t        n_tgt_rst;      /* Number of target resets */
+       uint32_t        n_tgt_rst_fail; /* Number of target reset
+                                        * failures.
+                                        */
+};
+
+/* Defines for rnode role */
+#define        CSIO_RNFR_INITIATOR     0x1
+#define        CSIO_RNFR_TARGET        0x2
+#define CSIO_RNFR_FABRIC       0x4
+#define        CSIO_RNFR_NS            0x8
+#define CSIO_RNFR_NPORT                0x10
+
+struct csio_rnode {
+       struct csio_sm          sm;                     /* State machine -
+                                                        * should be the
+                                                        * 1st member
+                                                        */
+       struct csio_lnode       *lnp;                   /* Pointer to owning
+                                                        * Lnode */
+       uint32_t                flowid;                 /* Firmware ID */
+       struct list_head        host_cmpl_q;            /* SCSI IOs
+                                                        * pending to completed
+                                                        * to Mid-layer.
+                                                        */
+       /* FC identifiers for remote node */
+       uint32_t                nport_id;
+       uint16_t                fcp_flags;              /* FCP Flags */
+       uint8_t                 cur_evt;                /* Current event */
+       uint8_t                 prev_evt;               /* Previous event */
+       uint32_t                role;                   /* Fabric/Target/
+                                                        * Initiator/NS
+                                                        */
+       struct fcoe_rdev_entry          *rdev_entry;    /* Rdev entry */
+       struct csio_service_parms       rn_sparm;
+
+       /* FC transport attributes */
+       struct fc_rport         *rport;         /* FC transport rport */
+       uint32_t                supp_classes;   /* Supported FC classes */
+       uint32_t                maxframe_size;  /* Max Frame size */
+       uint32_t                scsi_id;        /* Transport given SCSI id */
+
+       struct csio_rnode_stats stats;          /* Common rnode stats */
+};
+
+#define csio_rn_flowid(rn)                     ((rn)->flowid)
+#define csio_rn_wwpn(rn)                       ((rn)->rn_sparm.wwpn)
+#define csio_rn_wwnn(rn)                       ((rn)->rn_sparm.wwnn)
+#define csio_rnode_to_lnode(rn)                        ((rn)->lnp)
+
+int csio_is_rnode_ready(struct csio_rnode *rn);
+void csio_rnode_state_to_str(struct csio_rnode *rn, int8_t *str);
+
+struct csio_rnode *csio_rnode_lookup_portid(struct csio_lnode *, uint32_t);
+struct csio_rnode *csio_confirm_rnode(struct csio_lnode *,
+                                         uint32_t, struct fcoe_rdev_entry *);
+
+void csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt);
+
+void csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn);
+
+void csio_reg_rnode(struct csio_rnode *);
+void csio_unreg_rnode(struct csio_rnode *);
+
+void csio_rnode_devloss_handler(struct csio_rnode *);
+
+#endif /* ifndef __CSIO_RNODE_H__ */
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
new file mode 100644 (file)
index 0000000..ddd38e5
--- /dev/null
@@ -0,0 +1,2555 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+#include <asm/page.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_scsi.h"
+#include "csio_init.h"
+
+int csio_scsi_eqsize = 65536;
+int csio_scsi_iqlen = 128;
+int csio_scsi_ioreqs = 2048;
+uint32_t csio_max_scan_tmo;
+uint32_t csio_delta_scan_tmo = 5;
+int csio_lun_qdepth = 32;
+
+static int csio_ddp_descs = 128;
+
+static int csio_do_abrt_cls(struct csio_hw *,
+                                     struct csio_ioreq *, bool);
+
+static void csio_scsis_uninit(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_io_active(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_tm_active(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_aborting(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_closing(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_shost_cmpl_await(struct csio_ioreq *, enum csio_scsi_ev);
+
+/*
+ * csio_scsi_match_io - Match an ioreq with the given SCSI level data.
+ * @ioreq: The I/O request
+ * @sld: Level information
+ *
+ * Should be called with lock held.
+ *
+ */
+static bool
+csio_scsi_match_io(struct csio_ioreq *ioreq, struct csio_scsi_level_data *sld)
+{
+       struct scsi_cmnd *scmnd = csio_scsi_cmnd(ioreq);
+
+       switch (sld->level) {
+       case CSIO_LEV_LUN:
+               if (scmnd == NULL)
+                       return false;
+
+               return ((ioreq->lnode == sld->lnode) &&
+                       (ioreq->rnode == sld->rnode) &&
+                       ((uint64_t)scmnd->device->lun == sld->oslun));
+
+       case CSIO_LEV_RNODE:
+               return ((ioreq->lnode == sld->lnode) &&
+                               (ioreq->rnode == sld->rnode));
+       case CSIO_LEV_LNODE:
+               return (ioreq->lnode == sld->lnode);
+       case CSIO_LEV_ALL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+/*
+ * csio_scsi_gather_active_ios - Gather active I/Os based on level
+ * @scm: SCSI module
+ * @sld: Level information
+ * @dest: The queue where these I/Os have to be gathered.
+ *
+ * Should be called with lock held.
+ */
+static void
+csio_scsi_gather_active_ios(struct csio_scsim *scm,
+                           struct csio_scsi_level_data *sld,
+                           struct list_head *dest)
+{
+       struct list_head *tmp, *next;
+
+       if (list_empty(&scm->active_q))
+               return;
+
+       /* Just splice the entire active_q into dest */
+       if (sld->level == CSIO_LEV_ALL) {
+               list_splice_tail_init(&scm->active_q, dest);
+               return;
+       }
+
+       list_for_each_safe(tmp, next, &scm->active_q) {
+               if (csio_scsi_match_io((struct csio_ioreq *)tmp, sld)) {
+                       list_del_init(tmp);
+                       list_add_tail(tmp, dest);
+               }
+       }
+}
+
+static inline bool
+csio_scsi_itnexus_loss_error(uint16_t error)
+{
+       switch (error) {
+       case FW_ERR_LINK_DOWN:
+       case FW_RDEV_NOT_READY:
+       case FW_ERR_RDEV_LOST:
+       case FW_ERR_RDEV_LOGO:
+       case FW_ERR_RDEV_IMPL_LOGO:
+               return 1;
+       }
+       return 0;
+}
+
+static inline void
+csio_scsi_tag(struct scsi_cmnd *scmnd, uint8_t *tag, uint8_t hq,
+             uint8_t oq, uint8_t sq)
+{
+       char stag[2];
+
+       if (scsi_populate_tag_msg(scmnd, stag)) {
+               switch (stag[0]) {
+               case HEAD_OF_QUEUE_TAG:
+                       *tag = hq;
+                       break;
+               case ORDERED_QUEUE_TAG:
+                       *tag = oq;
+                       break;
+               default:
+                       *tag = sq;
+                       break;
+               }
+       } else
+               *tag = 0;
+}
+
+/*
+ * csio_scsi_fcp_cmnd - Frame the SCSI FCP command paylod.
+ * @req: IO req structure.
+ * @addr: DMA location to place the payload.
+ *
+ * This routine is shared between FCP_WRITE, FCP_READ and FCP_CMD requests.
+ */
+static inline void
+csio_scsi_fcp_cmnd(struct csio_ioreq *req, void *addr)
+{
+       struct fcp_cmnd *fcp_cmnd = (struct fcp_cmnd *)addr;
+       struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+       /* Check for Task Management */
+       if (likely(scmnd->SCp.Message == 0)) {
+               int_to_scsilun(scmnd->device->lun, &fcp_cmnd->fc_lun);
+               fcp_cmnd->fc_tm_flags = 0;
+               fcp_cmnd->fc_cmdref = 0;
+               fcp_cmnd->fc_pri_ta = 0;
+
+               memcpy(fcp_cmnd->fc_cdb, scmnd->cmnd, 16);
+               csio_scsi_tag(scmnd, &fcp_cmnd->fc_pri_ta,
+                             FCP_PTA_HEADQ, FCP_PTA_ORDERED, FCP_PTA_SIMPLE);
+               fcp_cmnd->fc_dl = cpu_to_be32(scsi_bufflen(scmnd));
+
+               if (req->nsge)
+                       if (req->datadir == DMA_TO_DEVICE)
+                               fcp_cmnd->fc_flags = FCP_CFL_WRDATA;
+                       else
+                               fcp_cmnd->fc_flags = FCP_CFL_RDDATA;
+               else
+                       fcp_cmnd->fc_flags = 0;
+       } else {
+               memset(fcp_cmnd, 0, sizeof(*fcp_cmnd));
+               int_to_scsilun(scmnd->device->lun, &fcp_cmnd->fc_lun);
+               fcp_cmnd->fc_tm_flags = (uint8_t)scmnd->SCp.Message;
+       }
+}
+
+/*
+ * csio_scsi_init_cmd_wr - Initialize the SCSI CMD WR.
+ * @req: IO req structure.
+ * @addr: DMA location to place the payload.
+ * @size: Size of WR (including FW WR + immed data + rsp SG entry
+ *
+ * Wrapper for populating fw_scsi_cmd_wr.
+ */
+static inline void
+csio_scsi_init_cmd_wr(struct csio_ioreq *req, void *addr, uint32_t size)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_rnode *rn = req->rnode;
+       struct fw_scsi_cmd_wr *wr = (struct fw_scsi_cmd_wr *)addr;
+       struct csio_dma_buf *dma_buf;
+       uint8_t imm = csio_hw_to_scsim(hw)->proto_cmd_len;
+
+       wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_CMD_WR) |
+                                         FW_SCSI_CMD_WR_IMMDLEN(imm));
+       wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+                                           FW_WR_LEN16(
+                                               DIV_ROUND_UP(size, 16)));
+
+       wr->cookie = (uintptr_t) req;
+       wr->iqid = cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+       wr->tmo_val = (uint8_t) req->tmo;
+       wr->r3 = 0;
+       memset(&wr->r5, 0, 8);
+
+       /* Get RSP DMA buffer */
+       dma_buf = &req->dma_buf;
+
+       /* Prepare RSP SGL */
+       wr->rsp_dmalen = cpu_to_be32(dma_buf->len);
+       wr->rsp_dmaaddr = cpu_to_be64(dma_buf->paddr);
+
+       wr->r6 = 0;
+
+       wr->u.fcoe.ctl_pri = 0;
+       wr->u.fcoe.cp_en_class = 0;
+       wr->u.fcoe.r4_lo[0] = 0;
+       wr->u.fcoe.r4_lo[1] = 0;
+
+       /* Frame a FCP command */
+       csio_scsi_fcp_cmnd(req, (void *)((uintptr_t)addr +
+                                   sizeof(struct fw_scsi_cmd_wr)));
+}
+
+#define CSIO_SCSI_CMD_WR_SZ(_imm)                                      \
+       (sizeof(struct fw_scsi_cmd_wr) +                /* WR size */   \
+        ALIGN((_imm), 16))                             /* Immed data */
+
+#define CSIO_SCSI_CMD_WR_SZ_16(_imm)                                   \
+                       (ALIGN(CSIO_SCSI_CMD_WR_SZ((_imm)), 16))
+
+/*
+ * csio_scsi_cmd - Create a SCSI CMD WR.
+ * @req: IO req structure.
+ *
+ * Gets a WR slot in the ingress queue and initializes it with SCSI CMD WR.
+ *
+ */
+static inline void
+csio_scsi_cmd(struct csio_ioreq *req)
+{
+       struct csio_wr_pair wrp;
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+       uint32_t size = CSIO_SCSI_CMD_WR_SZ_16(scsim->proto_cmd_len);
+
+       req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+       if (unlikely(req->drv_status != 0))
+               return;
+
+       if (wrp.size1 >= size) {
+               /* Initialize WR in one shot */
+               csio_scsi_init_cmd_wr(req, wrp.addr1, size);
+       } else {
+               uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+
+               /*
+                * Make a temporary copy of the WR and write back
+                * the copy into the WR pair.
+                */
+               csio_scsi_init_cmd_wr(req, (void *)tmpwr, size);
+               memcpy(wrp.addr1, tmpwr, wrp.size1);
+               memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+       }
+}
+
+/*
+ * csio_scsi_init_ulptx_dsgl - Fill in a ULP_TX_SC_DSGL
+ * @hw: HW module
+ * @req: IO request
+ * @sgl: ULP TX SGL pointer.
+ *
+ */
+static inline void
+csio_scsi_init_ultptx_dsgl(struct csio_hw *hw, struct csio_ioreq *req,
+                          struct ulptx_sgl *sgl)
+{
+       struct ulptx_sge_pair *sge_pair = NULL;
+       struct scatterlist *sgel;
+       uint32_t i = 0;
+       uint32_t xfer_len;
+       struct list_head *tmp;
+       struct csio_dma_buf *dma_buf;
+       struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+       sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_MORE |
+                                    ULPTX_NSGE(req->nsge));
+       /* Now add the data SGLs */
+       if (likely(!req->dcopy)) {
+               scsi_for_each_sg(scmnd, sgel, req->nsge, i) {
+                       if (i == 0) {
+                               sgl->addr0 = cpu_to_be64(sg_dma_address(sgel));
+                               sgl->len0 = cpu_to_be32(sg_dma_len(sgel));
+                               sge_pair = (struct ulptx_sge_pair *)(sgl + 1);
+                               continue;
+                       }
+                       if ((i - 1) & 0x1) {
+                               sge_pair->addr[1] = cpu_to_be64(
+                                                       sg_dma_address(sgel));
+                               sge_pair->len[1] = cpu_to_be32(
+                                                       sg_dma_len(sgel));
+                               sge_pair++;
+                       } else {
+                               sge_pair->addr[0] = cpu_to_be64(
+                                                       sg_dma_address(sgel));
+                               sge_pair->len[0] = cpu_to_be32(
+                                                       sg_dma_len(sgel));
+                       }
+               }
+       } else {
+               /* Program sg elements with driver's DDP buffer */
+               xfer_len = scsi_bufflen(scmnd);
+               list_for_each(tmp, &req->gen_list) {
+                       dma_buf = (struct csio_dma_buf *)tmp;
+                       if (i == 0) {
+                               sgl->addr0 = cpu_to_be64(dma_buf->paddr);
+                               sgl->len0 = cpu_to_be32(
+                                               min(xfer_len, dma_buf->len));
+                               sge_pair = (struct ulptx_sge_pair *)(sgl + 1);
+                       } else if ((i - 1) & 0x1) {
+                               sge_pair->addr[1] = cpu_to_be64(dma_buf->paddr);
+                               sge_pair->len[1] = cpu_to_be32(
+                                               min(xfer_len, dma_buf->len));
+                               sge_pair++;
+                       } else {
+                               sge_pair->addr[0] = cpu_to_be64(dma_buf->paddr);
+                               sge_pair->len[0] = cpu_to_be32(
+                                               min(xfer_len, dma_buf->len));
+                       }
+                       xfer_len -= min(xfer_len, dma_buf->len);
+                       i++;
+               }
+       }
+}
+
+/*
+ * csio_scsi_init_read_wr - Initialize the READ SCSI WR.
+ * @req: IO req structure.
+ * @wrp: DMA location to place the payload.
+ * @size: Size of WR (including FW WR + immed data + rsp SG entry + data SGL
+ *
+ * Wrapper for populating fw_scsi_read_wr.
+ */
+static inline void
+csio_scsi_init_read_wr(struct csio_ioreq *req, void *wrp, uint32_t size)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_rnode *rn = req->rnode;
+       struct fw_scsi_read_wr *wr = (struct fw_scsi_read_wr *)wrp;
+       struct ulptx_sgl *sgl;
+       struct csio_dma_buf *dma_buf;
+       uint8_t imm = csio_hw_to_scsim(hw)->proto_cmd_len;
+       struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+       wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_READ_WR) |
+                                    FW_SCSI_READ_WR_IMMDLEN(imm));
+       wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+                                      FW_WR_LEN16(DIV_ROUND_UP(size, 16)));
+       wr->cookie = (uintptr_t)req;
+       wr->iqid = cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+       wr->tmo_val = (uint8_t)(req->tmo);
+       wr->use_xfer_cnt = 1;
+       wr->xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+       wr->ini_xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+       /* Get RSP DMA buffer */
+       dma_buf = &req->dma_buf;
+
+       /* Prepare RSP SGL */
+       wr->rsp_dmalen = cpu_to_be32(dma_buf->len);
+       wr->rsp_dmaaddr = cpu_to_be64(dma_buf->paddr);
+
+       wr->r4 = 0;
+
+       wr->u.fcoe.ctl_pri = 0;
+       wr->u.fcoe.cp_en_class = 0;
+       wr->u.fcoe.r3_lo[0] = 0;
+       wr->u.fcoe.r3_lo[1] = 0;
+       csio_scsi_fcp_cmnd(req, (void *)((uintptr_t)wrp +
+                                       sizeof(struct fw_scsi_read_wr)));
+
+       /* Move WR pointer past command and immediate data */
+       sgl = (struct ulptx_sgl *)((uintptr_t)wrp +
+                             sizeof(struct fw_scsi_read_wr) + ALIGN(imm, 16));
+
+       /* Fill in the DSGL */
+       csio_scsi_init_ultptx_dsgl(hw, req, sgl);
+}
+
+/*
+ * csio_scsi_init_write_wr - Initialize the WRITE SCSI WR.
+ * @req: IO req structure.
+ * @wrp: DMA location to place the payload.
+ * @size: Size of WR (including FW WR + immed data + rsp SG entry + data SGL
+ *
+ * Wrapper for populating fw_scsi_write_wr.
+ */
+static inline void
+csio_scsi_init_write_wr(struct csio_ioreq *req, void *wrp, uint32_t size)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_rnode *rn = req->rnode;
+       struct fw_scsi_write_wr *wr = (struct fw_scsi_write_wr *)wrp;
+       struct ulptx_sgl *sgl;
+       struct csio_dma_buf *dma_buf;
+       uint8_t imm = csio_hw_to_scsim(hw)->proto_cmd_len;
+       struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+       wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_WRITE_WR) |
+                                    FW_SCSI_WRITE_WR_IMMDLEN(imm));
+       wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+                                      FW_WR_LEN16(DIV_ROUND_UP(size, 16)));
+       wr->cookie = (uintptr_t)req;
+       wr->iqid = cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+       wr->tmo_val = (uint8_t)(req->tmo);
+       wr->use_xfer_cnt = 1;
+       wr->xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+       wr->ini_xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+       /* Get RSP DMA buffer */
+       dma_buf = &req->dma_buf;
+
+       /* Prepare RSP SGL */
+       wr->rsp_dmalen = cpu_to_be32(dma_buf->len);
+       wr->rsp_dmaaddr = cpu_to_be64(dma_buf->paddr);
+
+       wr->r4 = 0;
+
+       wr->u.fcoe.ctl_pri = 0;
+       wr->u.fcoe.cp_en_class = 0;
+       wr->u.fcoe.r3_lo[0] = 0;
+       wr->u.fcoe.r3_lo[1] = 0;
+       csio_scsi_fcp_cmnd(req, (void *)((uintptr_t)wrp +
+                                       sizeof(struct fw_scsi_write_wr)));
+
+       /* Move WR pointer past command and immediate data */
+       sgl = (struct ulptx_sgl *)((uintptr_t)wrp +
+                             sizeof(struct fw_scsi_write_wr) + ALIGN(imm, 16));
+
+       /* Fill in the DSGL */
+       csio_scsi_init_ultptx_dsgl(hw, req, sgl);
+}
+
+/* Calculate WR size needed for fw_scsi_read_wr/fw_scsi_write_wr */
+#define CSIO_SCSI_DATA_WRSZ(req, oper, sz, imm)                                       \
+do {                                                                          \
+       (sz) = sizeof(struct fw_scsi_##oper##_wr) +     /* WR size */          \
+              ALIGN((imm), 16) +                       /* Immed data */       \
+              sizeof(struct ulptx_sgl);                /* ulptx_sgl */        \
+                                                                              \
+       if (unlikely((req)->nsge > 1))                                         \
+               (sz) += (sizeof(struct ulptx_sge_pair) *                       \
+                               (ALIGN(((req)->nsge - 1), 2) / 2));            \
+                                                       /* Data SGE */         \
+} while (0)
+
+/*
+ * csio_scsi_read - Create a SCSI READ WR.
+ * @req: IO req structure.
+ *
+ * Gets a WR slot in the ingress queue and initializes it with
+ * SCSI READ WR.
+ *
+ */
+static inline void
+csio_scsi_read(struct csio_ioreq *req)
+{
+       struct csio_wr_pair wrp;
+       uint32_t size;
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+
+       CSIO_SCSI_DATA_WRSZ(req, read, size, scsim->proto_cmd_len);
+       size = ALIGN(size, 16);
+
+       req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+       if (likely(req->drv_status == 0)) {
+               if (likely(wrp.size1 >= size)) {
+                       /* Initialize WR in one shot */
+                       csio_scsi_init_read_wr(req, wrp.addr1, size);
+               } else {
+                       uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+                       /*
+                        * Make a temporary copy of the WR and write back
+                        * the copy into the WR pair.
+                        */
+                       csio_scsi_init_read_wr(req, (void *)tmpwr, size);
+                       memcpy(wrp.addr1, tmpwr, wrp.size1);
+                       memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+               }
+       }
+}
+
+/*
+ * csio_scsi_write - Create a SCSI WRITE WR.
+ * @req: IO req structure.
+ *
+ * Gets a WR slot in the ingress queue and initializes it with
+ * SCSI WRITE WR.
+ *
+ */
+static inline void
+csio_scsi_write(struct csio_ioreq *req)
+{
+       struct csio_wr_pair wrp;
+       uint32_t size;
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+
+       CSIO_SCSI_DATA_WRSZ(req, write, size, scsim->proto_cmd_len);
+       size = ALIGN(size, 16);
+
+       req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+       if (likely(req->drv_status == 0)) {
+               if (likely(wrp.size1 >= size)) {
+                       /* Initialize WR in one shot */
+                       csio_scsi_init_write_wr(req, wrp.addr1, size);
+               } else {
+                       uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+                       /*
+                        * Make a temporary copy of the WR and write back
+                        * the copy into the WR pair.
+                        */
+                       csio_scsi_init_write_wr(req, (void *)tmpwr, size);
+                       memcpy(wrp.addr1, tmpwr, wrp.size1);
+                       memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+               }
+       }
+}
+
+/*
+ * csio_setup_ddp - Setup DDP buffers for Read request.
+ * @req: IO req structure.
+ *
+ * Checks SGLs/Data buffers are virtually contiguous required for DDP.
+ * If contiguous,driver posts SGLs in the WR otherwise post internal
+ * buffers for such request for DDP.
+ */
+static inline void
+csio_setup_ddp(struct csio_scsim *scsim, struct csio_ioreq *req)
+{
+#ifdef __CSIO_DEBUG__
+       struct csio_hw *hw = req->lnode->hwp;
+#endif
+       struct scatterlist *sgel = NULL;
+       struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+       uint64_t sg_addr = 0;
+       uint32_t ddp_pagesz = 4096;
+       uint32_t buf_off;
+       struct csio_dma_buf *dma_buf = NULL;
+       uint32_t alloc_len = 0;
+       uint32_t xfer_len = 0;
+       uint32_t sg_len = 0;
+       uint32_t i;
+
+       scsi_for_each_sg(scmnd, sgel, req->nsge, i) {
+               sg_addr = sg_dma_address(sgel);
+               sg_len  = sg_dma_len(sgel);
+
+               buf_off = sg_addr & (ddp_pagesz - 1);
+
+               /* Except 1st buffer,all buffer addr have to be Page aligned */
+               if (i != 0 && buf_off) {
+                       csio_dbg(hw, "SGL addr not DDP aligned (%llx:%d)\n",
+                                sg_addr, sg_len);
+                       goto unaligned;
+               }
+
+               /* Except last buffer,all buffer must end on page boundary */
+               if ((i != (req->nsge - 1)) &&
+                       ((buf_off + sg_len) & (ddp_pagesz - 1))) {
+                       csio_dbg(hw,
+                                "SGL addr not ending on page boundary"
+                                "(%llx:%d)\n", sg_addr, sg_len);
+                       goto unaligned;
+               }
+       }
+
+       /* SGL's are virtually contiguous. HW will DDP to SGLs */
+       req->dcopy = 0;
+       csio_scsi_read(req);
+
+       return;
+
+unaligned:
+       CSIO_INC_STATS(scsim, n_unaligned);
+       /*
+        * For unaligned SGLs, driver will allocate internal DDP buffer.
+        * Once command is completed data from DDP buffer copied to SGLs
+        */
+       req->dcopy = 1;
+
+       /* Use gen_list to store the DDP buffers */
+       INIT_LIST_HEAD(&req->gen_list);
+       xfer_len = scsi_bufflen(scmnd);
+
+       i = 0;
+       /* Allocate ddp buffers for this request */
+       while (alloc_len < xfer_len) {
+               dma_buf = csio_get_scsi_ddp(scsim);
+               if (dma_buf == NULL || i > scsim->max_sge) {
+                       req->drv_status = -EBUSY;
+                       break;
+               }
+               alloc_len += dma_buf->len;
+               /* Added to IO req */
+               list_add_tail(&dma_buf->list, &req->gen_list);
+               i++;
+       }
+
+       if (!req->drv_status) {
+               /* set number of ddp bufs used */
+               req->nsge = i;
+               csio_scsi_read(req);
+               return;
+       }
+
+        /* release dma descs */
+       if (i > 0)
+               csio_put_scsi_ddp_list(scsim, &req->gen_list, i);
+}
+
+/*
+ * csio_scsi_init_abrt_cls_wr - Initialize an ABORT/CLOSE WR.
+ * @req: IO req structure.
+ * @addr: DMA location to place the payload.
+ * @size: Size of WR
+ * @abort: abort OR close
+ *
+ * Wrapper for populating fw_scsi_cmd_wr.
+ */
+static inline void
+csio_scsi_init_abrt_cls_wr(struct csio_ioreq *req, void *addr, uint32_t size,
+                          bool abort)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_rnode *rn = req->rnode;
+       struct fw_scsi_abrt_cls_wr *wr = (struct fw_scsi_abrt_cls_wr *)addr;
+
+       wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_ABRT_CLS_WR));
+       wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+                                           FW_WR_LEN16(
+                                               DIV_ROUND_UP(size, 16)));
+
+       wr->cookie = (uintptr_t) req;
+       wr->iqid = cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+       wr->tmo_val = (uint8_t) req->tmo;
+       /* 0 for CHK_ALL_IO tells FW to look up t_cookie */
+       wr->sub_opcode_to_chk_all_io =
+                               (FW_SCSI_ABRT_CLS_WR_SUB_OPCODE(abort) |
+                                FW_SCSI_ABRT_CLS_WR_CHK_ALL_IO(0));
+       wr->r3[0] = 0;
+       wr->r3[1] = 0;
+       wr->r3[2] = 0;
+       wr->r3[3] = 0;
+       /* Since we re-use the same ioreq for abort as well */
+       wr->t_cookie = (uintptr_t) req;
+}
+
+static inline void
+csio_scsi_abrt_cls(struct csio_ioreq *req, bool abort)
+{
+       struct csio_wr_pair wrp;
+       struct csio_hw *hw = req->lnode->hwp;
+       uint32_t size = ALIGN(sizeof(struct fw_scsi_abrt_cls_wr), 16);
+
+       req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+       if (req->drv_status != 0)
+               return;
+
+       if (wrp.size1 >= size) {
+               /* Initialize WR in one shot */
+               csio_scsi_init_abrt_cls_wr(req, wrp.addr1, size, abort);
+       } else {
+               uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+               /*
+                * Make a temporary copy of the WR and write back
+                * the copy into the WR pair.
+                */
+               csio_scsi_init_abrt_cls_wr(req, (void *)tmpwr, size, abort);
+               memcpy(wrp.addr1, tmpwr, wrp.size1);
+               memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+       }
+}
+
+/*****************************************************************************/
+/* START: SCSI SM                                                            */
+/*****************************************************************************/
+static void
+csio_scsis_uninit(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+
+       switch (evt) {
+       case CSIO_SCSIE_START_IO:
+
+               if (req->nsge) {
+                       if (req->datadir == DMA_TO_DEVICE) {
+                               req->dcopy = 0;
+                               csio_scsi_write(req);
+                       } else
+                               csio_setup_ddp(scsim, req);
+               } else {
+                       csio_scsi_cmd(req);
+               }
+
+               if (likely(req->drv_status == 0)) {
+                       /* change state and enqueue on active_q */
+                       csio_set_state(&req->sm, csio_scsis_io_active);
+                       list_add_tail(&req->sm.sm_list, &scsim->active_q);
+                       csio_wr_issue(hw, req->eq_idx, false);
+                       CSIO_INC_STATS(scsim, n_active);
+
+                       return;
+               }
+               break;
+
+       case CSIO_SCSIE_START_TM:
+               csio_scsi_cmd(req);
+               if (req->drv_status == 0) {
+                       /*
+                        * NOTE: We collect the affected I/Os prior to issuing
+                        * LUN reset, and not after it. This is to prevent
+                        * aborting I/Os that get issued after the LUN reset,
+                        * but prior to LUN reset completion (in the event that
+                        * the host stack has not blocked I/Os to a LUN that is
+                        * being reset.
+                        */
+                       csio_set_state(&req->sm, csio_scsis_tm_active);
+                       list_add_tail(&req->sm.sm_list, &scsim->active_q);
+                       csio_wr_issue(hw, req->eq_idx, false);
+                       CSIO_INC_STATS(scsim, n_tm_active);
+               }
+               return;
+
+       case CSIO_SCSIE_ABORT:
+       case CSIO_SCSIE_CLOSE:
+               /*
+                * NOTE:
+                * We could get here due to  :
+                * - a window in the cleanup path of the SCSI module
+                *   (csio_scsi_abort_io()). Please see NOTE in this function.
+                * - a window in the time we tried to issue an abort/close
+                *   of a request to FW, and the FW completed the request
+                *   itself.
+                *   Print a message for now, and return INVAL either way.
+                */
+               req->drv_status = -EINVAL;
+               csio_warn(hw, "Trying to abort/close completed IO:%p!\n", req);
+               break;
+
+       default:
+               csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+               CSIO_DB_ASSERT(0);
+       }
+}
+
+static void
+csio_scsis_io_active(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scm = csio_hw_to_scsim(hw);
+       struct csio_rnode *rn;
+
+       switch (evt) {
+       case CSIO_SCSIE_COMPLETED:
+               CSIO_DEC_STATS(scm, n_active);
+               list_del_init(&req->sm.sm_list);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               /*
+                * In MSIX mode, with multiple queues, the SCSI compeltions
+                * could reach us sooner than the FW events sent to indicate
+                * I-T nexus loss (link down, remote device logo etc). We
+                * dont want to be returning such I/Os to the upper layer
+                * immediately, since we wouldnt have reported the I-T nexus
+                * loss itself. This forces us to serialize such completions
+                * with the reporting of the I-T nexus loss. Therefore, we
+                * internally queue up such up such completions in the rnode.
+                * The reporting of I-T nexus loss to the upper layer is then
+                * followed by the returning of I/Os in this internal queue.
+                * Having another state alongwith another queue helps us take
+                * actions for events such as ABORT received while we are
+                * in this rnode queue.
+                */
+               if (unlikely(req->wr_status != FW_SUCCESS)) {
+                       rn = req->rnode;
+                       /*
+                        * FW says remote device is lost, but rnode
+                        * doesnt reflect it.
+                        */
+                       if (csio_scsi_itnexus_loss_error(req->wr_status) &&
+                                               csio_is_rnode_ready(rn)) {
+                               csio_set_state(&req->sm,
+                                               csio_scsis_shost_cmpl_await);
+                               list_add_tail(&req->sm.sm_list,
+                                             &rn->host_cmpl_q);
+                       }
+               }
+
+               break;
+
+       case CSIO_SCSIE_ABORT:
+               csio_scsi_abrt_cls(req, SCSI_ABORT);
+               if (req->drv_status == 0) {
+                       csio_wr_issue(hw, req->eq_idx, false);
+                       csio_set_state(&req->sm, csio_scsis_aborting);
+               }
+               break;
+
+       case CSIO_SCSIE_CLOSE:
+               csio_scsi_abrt_cls(req, SCSI_CLOSE);
+               if (req->drv_status == 0) {
+                       csio_wr_issue(hw, req->eq_idx, false);
+                       csio_set_state(&req->sm, csio_scsis_closing);
+               }
+               break;
+
+       case CSIO_SCSIE_DRVCLEANUP:
+               req->wr_status = FW_HOSTERROR;
+               CSIO_DEC_STATS(scm, n_active);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+
+       default:
+               csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+               CSIO_DB_ASSERT(0);
+       }
+}
+
+static void
+csio_scsis_tm_active(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+       switch (evt) {
+       case CSIO_SCSIE_COMPLETED:
+               CSIO_DEC_STATS(scm, n_tm_active);
+               list_del_init(&req->sm.sm_list);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+
+               break;
+
+       case CSIO_SCSIE_ABORT:
+               csio_scsi_abrt_cls(req, SCSI_ABORT);
+               if (req->drv_status == 0) {
+                       csio_wr_issue(hw, req->eq_idx, false);
+                       csio_set_state(&req->sm, csio_scsis_aborting);
+               }
+               break;
+
+
+       case CSIO_SCSIE_CLOSE:
+               csio_scsi_abrt_cls(req, SCSI_CLOSE);
+               if (req->drv_status == 0) {
+                       csio_wr_issue(hw, req->eq_idx, false);
+                       csio_set_state(&req->sm, csio_scsis_closing);
+               }
+               break;
+
+       case CSIO_SCSIE_DRVCLEANUP:
+               req->wr_status = FW_HOSTERROR;
+               CSIO_DEC_STATS(scm, n_tm_active);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+
+       default:
+               csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+               CSIO_DB_ASSERT(0);
+       }
+}
+
+static void
+csio_scsis_aborting(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+       switch (evt) {
+       case CSIO_SCSIE_COMPLETED:
+               csio_dbg(hw,
+                        "ioreq %p recvd cmpltd (wr_status:%d) "
+                        "in aborting st\n", req, req->wr_status);
+               /*
+                * Use -ECANCELED to explicitly tell the ABORTED event that
+                * the original I/O was returned to driver by FW.
+                * We dont really care if the I/O was returned with success by
+                * FW (because the ABORT and completion of the I/O crossed each
+                * other), or any other return value. Once we are in aborting
+                * state, the success or failure of the I/O is unimportant to
+                * us.
+                */
+               req->drv_status = -ECANCELED;
+               break;
+
+       case CSIO_SCSIE_ABORT:
+               CSIO_INC_STATS(scm, n_abrt_dups);
+               break;
+
+       case CSIO_SCSIE_ABORTED:
+
+               csio_dbg(hw, "abort of %p return status:0x%x drv_status:%x\n",
+                        req, req->wr_status, req->drv_status);
+               /*
+                * Check if original I/O WR completed before the Abort
+                * completion.
+                */
+               if (req->drv_status != -ECANCELED) {
+                       csio_warn(hw,
+                                 "Abort completed before original I/O,"
+                                  " req:%p\n", req);
+                       CSIO_DB_ASSERT(0);
+               }
+
+               /*
+                * There are the following possible scenarios:
+                * 1. The abort completed successfully, FW returned FW_SUCCESS.
+                * 2. The completion of an I/O and the receipt of
+                *    abort for that I/O by the FW crossed each other.
+                *    The FW returned FW_EINVAL. The original I/O would have
+                *    returned with FW_SUCCESS or any other SCSI error.
+                * 3. The FW couldnt sent the abort out on the wire, as there
+                *    was an I-T nexus loss (link down, remote device logged
+                *    out etc). FW sent back an appropriate IT nexus loss status
+                *    for the abort.
+                * 4. FW sent an abort, but abort timed out (remote device
+                *    didnt respond). FW replied back with
+                *    FW_SCSI_ABORT_TIMEDOUT.
+                * 5. FW couldnt genuinely abort the request for some reason,
+                *    and sent us an error.
+                *
+                * The first 3 scenarios are treated as  succesful abort
+                * operations by the host, while the last 2 are failed attempts
+                * to abort. Manipulate the return value of the request
+                * appropriately, so that host can convey these results
+                * back to the upper layer.
+                */
+               if ((req->wr_status == FW_SUCCESS) ||
+                   (req->wr_status == FW_EINVAL) ||
+                   csio_scsi_itnexus_loss_error(req->wr_status))
+                       req->wr_status = FW_SCSI_ABORT_REQUESTED;
+
+               CSIO_DEC_STATS(scm, n_active);
+               list_del_init(&req->sm.sm_list);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+
+       case CSIO_SCSIE_DRVCLEANUP:
+               req->wr_status = FW_HOSTERROR;
+               CSIO_DEC_STATS(scm, n_active);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+
+       case CSIO_SCSIE_CLOSE:
+               /*
+                * We can receive this event from the module
+                * cleanup paths, if the FW forgot to reply to the ABORT WR
+                * and left this ioreq in this state. For now, just ignore
+                * the event. The CLOSE event is sent to this state, as
+                * the LINK may have already gone down.
+                */
+               break;
+
+       default:
+               csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+               CSIO_DB_ASSERT(0);
+       }
+}
+
+static void
+csio_scsis_closing(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+       struct csio_hw *hw = req->lnode->hwp;
+       struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+       switch (evt) {
+       case CSIO_SCSIE_COMPLETED:
+               csio_dbg(hw,
+                        "ioreq %p recvd cmpltd (wr_status:%d) "
+                        "in closing st\n", req, req->wr_status);
+               /*
+                * Use -ECANCELED to explicitly tell the CLOSED event that
+                * the original I/O was returned to driver by FW.
+                * We dont really care if the I/O was returned with success by
+                * FW (because the CLOSE and completion of the I/O crossed each
+                * other), or any other return value. Once we are in aborting
+                * state, the success or failure of the I/O is unimportant to
+                * us.
+                */
+               req->drv_status = -ECANCELED;
+               break;
+
+       case CSIO_SCSIE_CLOSED:
+               /*
+                * Check if original I/O WR completed before the Close
+                * completion.
+                */
+               if (req->drv_status != -ECANCELED) {
+                       csio_fatal(hw,
+                                  "Close completed before original I/O,"
+                                  " req:%p\n", req);
+                       CSIO_DB_ASSERT(0);
+               }
+
+               /*
+                * Either close succeeded, or we issued close to FW at the
+                * same time FW compelted it to us. Either way, the I/O
+                * is closed.
+                */
+               CSIO_DB_ASSERT((req->wr_status == FW_SUCCESS) ||
+                                       (req->wr_status == FW_EINVAL));
+               req->wr_status = FW_SCSI_CLOSE_REQUESTED;
+
+               CSIO_DEC_STATS(scm, n_active);
+               list_del_init(&req->sm.sm_list);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+
+       case CSIO_SCSIE_CLOSE:
+               break;
+
+       case CSIO_SCSIE_DRVCLEANUP:
+               req->wr_status = FW_HOSTERROR;
+               CSIO_DEC_STATS(scm, n_active);
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+
+       default:
+               csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+               CSIO_DB_ASSERT(0);
+       }
+}
+
+static void
+csio_scsis_shost_cmpl_await(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+       switch (evt) {
+       case CSIO_SCSIE_ABORT:
+       case CSIO_SCSIE_CLOSE:
+               /*
+                * Just succeed the abort request, and hope that
+                * the remote device unregister path will cleanup
+                * this I/O to the upper layer within a sane
+                * amount of time.
+                */
+               /*
+                * A close can come in during a LINK DOWN. The FW would have
+                * returned us the I/O back, but not the remote device lost
+                * FW event. In this interval, if the I/O times out at the upper
+                * layer, a close can come in. Take the same action as abort:
+                * return success, and hope that the remote device unregister
+                * path will cleanup this I/O. If the FW still doesnt send
+                * the msg, the close times out, and the upper layer resorts
+                * to the next level of error recovery.
+                */
+               req->drv_status = 0;
+               break;
+       case CSIO_SCSIE_DRVCLEANUP:
+               csio_set_state(&req->sm, csio_scsis_uninit);
+               break;
+       default:
+               csio_dbg(req->lnode->hwp, "Unhandled event:%d sent to req:%p\n",
+                        evt, req);
+               CSIO_DB_ASSERT(0);
+       }
+}
+
+/*
+ * csio_scsi_cmpl_handler - WR completion handler for SCSI.
+ * @hw: HW module.
+ * @wr: The completed WR from the ingress queue.
+ * @len: Length of the WR.
+ * @flb: Freelist buffer array.
+ * @priv: Private object
+ * @scsiwr: Pointer to SCSI WR.
+ *
+ * This is the WR completion handler called per completion from the
+ * ISR. It is called with lock held. It walks past the RSS and CPL message
+ * header where the actual WR is present.
+ * It then gets the status, WR handle (ioreq pointer) and the len of
+ * the WR, based on WR opcode. Only on a non-good status is the entire
+ * WR copied into the WR cache (ioreq->fw_wr).
+ * The ioreq corresponding to the WR is returned to the caller.
+ * NOTE: The SCSI queue doesnt allocate a freelist today, hence
+ * no freelist buffer is expected.
+ */
+struct csio_ioreq *
+csio_scsi_cmpl_handler(struct csio_hw *hw, void *wr, uint32_t len,
+                    struct csio_fl_dma_buf *flb, void *priv, uint8_t **scsiwr)
+{
+       struct csio_ioreq *ioreq = NULL;
+       struct cpl_fw6_msg *cpl;
+       uint8_t *tempwr;
+       uint8_t status;
+       struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+       /* skip RSS header */
+       cpl = (struct cpl_fw6_msg *)((uintptr_t)wr + sizeof(__be64));
+
+       if (unlikely(cpl->opcode != CPL_FW6_MSG)) {
+               csio_warn(hw, "Error: Invalid CPL msg %x recvd on SCSI q\n",
+                         cpl->opcode);
+               CSIO_INC_STATS(scm, n_inval_cplop);
+               return NULL;
+       }
+
+       tempwr = (uint8_t *)(cpl->data);
+       status = csio_wr_status(tempwr);
+       *scsiwr = tempwr;
+
+       if (likely((*tempwr == FW_SCSI_READ_WR) ||
+                       (*tempwr == FW_SCSI_WRITE_WR) ||
+                       (*tempwr == FW_SCSI_CMD_WR))) {
+               ioreq = (struct csio_ioreq *)((uintptr_t)
+                                (((struct fw_scsi_read_wr *)tempwr)->cookie));
+               CSIO_DB_ASSERT(virt_addr_valid(ioreq));
+
+               ioreq->wr_status = status;
+
+               return ioreq;
+       }
+
+       if (*tempwr == FW_SCSI_ABRT_CLS_WR) {
+               ioreq = (struct csio_ioreq *)((uintptr_t)
+                        (((struct fw_scsi_abrt_cls_wr *)tempwr)->cookie));
+               CSIO_DB_ASSERT(virt_addr_valid(ioreq));
+
+               ioreq->wr_status = status;
+               return ioreq;
+       }
+
+       csio_warn(hw, "WR with invalid opcode in SCSI IQ: %x\n", *tempwr);
+       CSIO_INC_STATS(scm, n_inval_scsiop);
+       return NULL;
+}
+
+/*
+ * csio_scsi_cleanup_io_q - Cleanup the given queue.
+ * @scm: SCSI module.
+ * @q: Queue to be cleaned up.
+ *
+ * Called with lock held. Has to exit with lock held.
+ */
+void
+csio_scsi_cleanup_io_q(struct csio_scsim *scm, struct list_head *q)
+{
+       struct csio_hw *hw = scm->hw;
+       struct csio_ioreq *ioreq;
+       struct list_head *tmp, *next;
+       struct scsi_cmnd *scmnd;
+
+       /* Call back the completion routines of the active_q */
+       list_for_each_safe(tmp, next, q) {
+               ioreq = (struct csio_ioreq *)tmp;
+               csio_scsi_drvcleanup(ioreq);
+               list_del_init(&ioreq->sm.sm_list);
+               scmnd = csio_scsi_cmnd(ioreq);
+               spin_unlock_irq(&hw->lock);
+
+               /*
+                * Upper layers may have cleared this command, hence this
+                * check to avoid accessing stale references.
+                */
+               if (scmnd != NULL)
+                       ioreq->io_cbfn(hw, ioreq);
+
+               spin_lock_irq(&scm->freelist_lock);
+               csio_put_scsi_ioreq(scm, ioreq);
+               spin_unlock_irq(&scm->freelist_lock);
+
+               spin_lock_irq(&hw->lock);
+       }
+}
+
+#define CSIO_SCSI_ABORT_Q_POLL_MS              2000
+
+static void
+csio_abrt_cls(struct csio_ioreq *ioreq, struct scsi_cmnd *scmnd)
+{
+       struct csio_lnode *ln = ioreq->lnode;
+       struct csio_hw *hw = ln->hwp;
+       int ready = 0;
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+       int rv;
+
+       if (csio_scsi_cmnd(ioreq) != scmnd) {
+               CSIO_INC_STATS(scsim, n_abrt_race_comp);
+               return;
+       }
+
+       ready = csio_is_lnode_ready(ln);
+
+       rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE));
+       if (rv != 0) {
+               if (ready)
+                       CSIO_INC_STATS(scsim, n_abrt_busy_error);
+               else
+                       CSIO_INC_STATS(scsim, n_cls_busy_error);
+       }
+}
+
+/*
+ * csio_scsi_abort_io_q - Abort all I/Os on given queue
+ * @scm: SCSI module.
+ * @q: Queue to abort.
+ * @tmo: Timeout in ms
+ *
+ * Attempt to abort all I/Os on given queue, and wait for a max
+ * of tmo milliseconds for them to complete. Returns success
+ * if all I/Os are aborted. Else returns -ETIMEDOUT.
+ * Should be entered with lock held. Exits with lock held.
+ * NOTE:
+ * Lock has to be held across the loop that aborts I/Os, since dropping the lock
+ * in between can cause the list to be corrupted. As a result, the caller
+ * of this function has to ensure that the number of I/os to be aborted
+ * is finite enough to not cause lock-held-for-too-long issues.
+ */
+static int
+csio_scsi_abort_io_q(struct csio_scsim *scm, struct list_head *q, uint32_t tmo)
+{
+       struct csio_hw *hw = scm->hw;
+       struct list_head *tmp, *next;
+       int count = DIV_ROUND_UP(tmo, CSIO_SCSI_ABORT_Q_POLL_MS);
+       struct scsi_cmnd *scmnd;
+
+       if (list_empty(q))
+               return 0;
+
+       csio_dbg(hw, "Aborting SCSI I/Os\n");
+
+       /* Now abort/close I/Os in the queue passed */
+       list_for_each_safe(tmp, next, q) {
+               scmnd = csio_scsi_cmnd((struct csio_ioreq *)tmp);
+               csio_abrt_cls((struct csio_ioreq *)tmp, scmnd);
+       }
+
+       /* Wait till all active I/Os are completed/aborted/closed */
+       while (!list_empty(q) && count--) {
+               spin_unlock_irq(&hw->lock);
+               msleep(CSIO_SCSI_ABORT_Q_POLL_MS);
+               spin_lock_irq(&hw->lock);
+       }
+
+       /* all aborts completed */
+       if (list_empty(q))
+               return 0;
+
+       return -ETIMEDOUT;
+}
+
+/*
+ * csio_scsim_cleanup_io - Cleanup all I/Os in SCSI module.
+ * @scm: SCSI module.
+ * @abort: abort required.
+ * Called with lock held, should exit with lock held.
+ * Can sleep when waiting for I/Os to complete.
+ */
+int
+csio_scsim_cleanup_io(struct csio_scsim *scm, bool abort)
+{
+       struct csio_hw *hw = scm->hw;
+       int rv = 0;
+       int count = DIV_ROUND_UP(60 * 1000, CSIO_SCSI_ABORT_Q_POLL_MS);
+
+       /* No I/Os pending */
+       if (list_empty(&scm->active_q))
+               return 0;
+
+       /* Wait until all active I/Os are completed */
+       while (!list_empty(&scm->active_q) && count--) {
+               spin_unlock_irq(&hw->lock);
+               msleep(CSIO_SCSI_ABORT_Q_POLL_MS);
+               spin_lock_irq(&hw->lock);
+       }
+
+       /* all I/Os completed */
+       if (list_empty(&scm->active_q))
+               return 0;
+
+       /* Else abort */
+       if (abort) {
+               rv = csio_scsi_abort_io_q(scm, &scm->active_q, 30000);
+               if (rv == 0)
+                       return rv;
+               csio_dbg(hw, "Some I/O aborts timed out, cleaning up..\n");
+       }
+
+       csio_scsi_cleanup_io_q(scm, &scm->active_q);
+
+       CSIO_DB_ASSERT(list_empty(&scm->active_q));
+
+       return rv;
+}
+
+/*
+ * csio_scsim_cleanup_io_lnode - Cleanup all I/Os of given lnode.
+ * @scm: SCSI module.
+ * @lnode: lnode
+ *
+ * Called with lock held, should exit with lock held.
+ * Can sleep (with dropped lock) when waiting for I/Os to complete.
+ */
+int
+csio_scsim_cleanup_io_lnode(struct csio_scsim *scm, struct csio_lnode *ln)
+{
+       struct csio_hw *hw = scm->hw;
+       struct csio_scsi_level_data sld;
+       int rv;
+       int count = DIV_ROUND_UP(60 * 1000, CSIO_SCSI_ABORT_Q_POLL_MS);
+
+       csio_dbg(hw, "Gathering all SCSI I/Os on lnode %p\n", ln);
+
+       sld.level = CSIO_LEV_LNODE;
+       sld.lnode = ln;
+       INIT_LIST_HEAD(&ln->cmpl_q);
+       csio_scsi_gather_active_ios(scm, &sld, &ln->cmpl_q);
+
+       /* No I/Os pending on this lnode  */
+       if (list_empty(&ln->cmpl_q))
+               return 0;
+
+       /* Wait until all active I/Os on this lnode are completed */
+       while (!list_empty(&ln->cmpl_q) && count--) {
+               spin_unlock_irq(&hw->lock);
+               msleep(CSIO_SCSI_ABORT_Q_POLL_MS);
+               spin_lock_irq(&hw->lock);
+       }
+
+       /* all I/Os completed */
+       if (list_empty(&ln->cmpl_q))
+               return 0;
+
+       csio_dbg(hw, "Some I/Os pending on ln:%p, aborting them..\n", ln);
+
+       /* I/Os are pending, abort them */
+       rv = csio_scsi_abort_io_q(scm, &ln->cmpl_q, 30000);
+       if (rv != 0) {
+               csio_dbg(hw, "Some I/O aborts timed out, cleaning up..\n");
+               csio_scsi_cleanup_io_q(scm, &ln->cmpl_q);
+       }
+
+       CSIO_DB_ASSERT(list_empty(&ln->cmpl_q));
+
+       return rv;
+}
+
+static ssize_t
+csio_show_hw_state(struct device *dev,
+                  struct device_attribute *attr, char *buf)
+{
+       struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       if (csio_is_hw_ready(hw))
+               return snprintf(buf, PAGE_SIZE, "ready\n");
+       else
+               return snprintf(buf, PAGE_SIZE, "not ready\n");
+}
+
+/* Device reset */
+static ssize_t
+csio_device_reset(struct device *dev,
+                  struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+       if (*buf != '1')
+               return -EINVAL;
+
+       /* Delete NPIV lnodes */
+        csio_lnodes_exit(hw, 1);
+
+       /* Block upper IOs */
+       csio_lnodes_block_request(hw);
+
+       spin_lock_irq(&hw->lock);
+       csio_hw_reset(hw);
+       spin_unlock_irq(&hw->lock);
+
+       /* Unblock upper IOs */
+       csio_lnodes_unblock_request(hw);
+       return count;
+}
+
+/* disable port */
+static ssize_t
+csio_disable_port(struct device *dev,
+                  struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       bool disable;
+
+       if (*buf == '1' || *buf == '0')
+               disable = (*buf == '1') ? true : false;
+       else
+               return -EINVAL;
+
+       /* Block upper IOs */
+       csio_lnodes_block_by_port(hw, ln->portid);
+
+       spin_lock_irq(&hw->lock);
+       csio_disable_lnodes(hw, ln->portid, disable);
+       spin_unlock_irq(&hw->lock);
+
+       /* Unblock upper IOs */
+       csio_lnodes_unblock_by_port(hw, ln->portid);
+       return count;
+}
+
+/* Show debug level */
+static ssize_t
+csio_show_dbg_level(struct device *dev,
+                  struct device_attribute *attr, char *buf)
+{
+       struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", ln->params.log_level);
+}
+
+/* Store debug level */
+static ssize_t
+csio_store_dbg_level(struct device *dev,
+                  struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       uint32_t dbg_level = 0;
+
+       if (!isdigit(buf[0]))
+               return -EINVAL;
+
+       if (sscanf(buf, "%i", &dbg_level))
+               return -EINVAL;
+
+       ln->params.log_level = dbg_level;
+       hw->params.log_level = dbg_level;
+
+       return 0;
+}
+
+static DEVICE_ATTR(hw_state, S_IRUGO, csio_show_hw_state, NULL);
+static DEVICE_ATTR(device_reset, S_IRUGO | S_IWUSR, NULL, csio_device_reset);
+static DEVICE_ATTR(disable_port, S_IRUGO | S_IWUSR, NULL, csio_disable_port);
+static DEVICE_ATTR(dbg_level, S_IRUGO | S_IWUSR, csio_show_dbg_level,
+                 csio_store_dbg_level);
+
+static struct device_attribute *csio_fcoe_lport_attrs[] = {
+       &dev_attr_hw_state,
+       &dev_attr_device_reset,
+       &dev_attr_disable_port,
+       &dev_attr_dbg_level,
+       NULL,
+};
+
+static ssize_t
+csio_show_num_reg_rnodes(struct device *dev,
+                    struct device_attribute *attr, char *buf)
+{
+       struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", ln->num_reg_rnodes);
+}
+
+static DEVICE_ATTR(num_reg_rnodes, S_IRUGO, csio_show_num_reg_rnodes, NULL);
+
+static struct device_attribute *csio_fcoe_vport_attrs[] = {
+       &dev_attr_num_reg_rnodes,
+       &dev_attr_dbg_level,
+       NULL,
+};
+
+static inline uint32_t
+csio_scsi_copy_to_sgl(struct csio_hw *hw, struct csio_ioreq *req)
+{
+       struct scsi_cmnd *scmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+       struct scatterlist *sg;
+       uint32_t bytes_left;
+       uint32_t bytes_copy;
+       uint32_t buf_off = 0;
+       uint32_t start_off = 0;
+       uint32_t sg_off = 0;
+       void *sg_addr;
+       void *buf_addr;
+       struct csio_dma_buf *dma_buf;
+
+       bytes_left = scsi_bufflen(scmnd);
+       sg = scsi_sglist(scmnd);
+       dma_buf = (struct csio_dma_buf *)csio_list_next(&req->gen_list);
+
+       /* Copy data from driver buffer to SGs of SCSI CMD */
+       while (bytes_left > 0 && sg && dma_buf) {
+               if (buf_off >= dma_buf->len) {
+                       buf_off = 0;
+                       dma_buf = (struct csio_dma_buf *)
+                                       csio_list_next(dma_buf);
+                       continue;
+               }
+
+               if (start_off >= sg->length) {
+                       start_off -= sg->length;
+                       sg = sg_next(sg);
+                       continue;
+               }
+
+               buf_addr = dma_buf->vaddr + buf_off;
+               sg_off = sg->offset + start_off;
+               bytes_copy = min((dma_buf->len - buf_off),
+                               sg->length - start_off);
+               bytes_copy = min((uint32_t)(PAGE_SIZE - (sg_off & ~PAGE_MASK)),
+                                bytes_copy);
+
+               sg_addr = kmap_atomic(sg_page(sg) + (sg_off >> PAGE_SHIFT));
+               if (!sg_addr) {
+                       csio_err(hw, "failed to kmap sg:%p of ioreq:%p\n",
+                               sg, req);
+                       break;
+               }
+
+               csio_dbg(hw, "copy_to_sgl:sg_addr %p sg_off %d buf %p len %d\n",
+                               sg_addr, sg_off, buf_addr, bytes_copy);
+               memcpy(sg_addr + (sg_off & ~PAGE_MASK), buf_addr, bytes_copy);
+               kunmap_atomic(sg_addr);
+
+               start_off +=  bytes_copy;
+               buf_off += bytes_copy;
+               bytes_left -= bytes_copy;
+       }
+
+       if (bytes_left > 0)
+               return DID_ERROR;
+       else
+               return DID_OK;
+}
+
+/*
+ * csio_scsi_err_handler - SCSI error handler.
+ * @hw: HW module.
+ * @req: IO request.
+ *
+ */
+static inline void
+csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req)
+{
+       struct scsi_cmnd *cmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+       struct csio_scsim *scm = csio_hw_to_scsim(hw);
+       struct fcp_resp_with_ext *fcp_resp;
+       struct fcp_resp_rsp_info *rsp_info;
+       struct csio_dma_buf *dma_buf;
+       uint8_t flags, scsi_status = 0;
+       uint32_t host_status = DID_OK;
+       uint32_t rsp_len = 0, sns_len = 0;
+       struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+
+
+       switch (req->wr_status) {
+       case FW_HOSTERROR:
+               if (unlikely(!csio_is_hw_ready(hw)))
+                       return;
+
+               host_status = DID_ERROR;
+               CSIO_INC_STATS(scm, n_hosterror);
+
+               break;
+       case FW_SCSI_RSP_ERR:
+               dma_buf = &req->dma_buf;
+               fcp_resp = (struct fcp_resp_with_ext *)dma_buf->vaddr;
+               rsp_info = (struct fcp_resp_rsp_info *)(fcp_resp + 1);
+               flags = fcp_resp->resp.fr_flags;
+               scsi_status = fcp_resp->resp.fr_status;
+
+               if (flags & FCP_RSP_LEN_VAL) {
+                       rsp_len = be32_to_cpu(fcp_resp->ext.fr_rsp_len);
+                       if ((rsp_len != 0 && rsp_len != 4 && rsp_len != 8) ||
+                               (rsp_info->rsp_code != FCP_TMF_CMPL)) {
+                               host_status = DID_ERROR;
+                               goto out;
+                       }
+               }
+
+               if ((flags & FCP_SNS_LEN_VAL) && fcp_resp->ext.fr_sns_len) {
+                       sns_len = be32_to_cpu(fcp_resp->ext.fr_sns_len);
+                       if (sns_len > SCSI_SENSE_BUFFERSIZE)
+                               sns_len = SCSI_SENSE_BUFFERSIZE;
+
+                       memcpy(cmnd->sense_buffer,
+                              &rsp_info->_fr_resvd[0] + rsp_len, sns_len);
+                       CSIO_INC_STATS(scm, n_autosense);
+               }
+
+               scsi_set_resid(cmnd, 0);
+
+               /* Under run */
+               if (flags & FCP_RESID_UNDER) {
+                       scsi_set_resid(cmnd,
+                                      be32_to_cpu(fcp_resp->ext.fr_resid));
+
+                       if (!(flags & FCP_SNS_LEN_VAL) &&
+                           (scsi_status == SAM_STAT_GOOD) &&
+                           ((scsi_bufflen(cmnd) - scsi_get_resid(cmnd))
+                                                       < cmnd->underflow))
+                               host_status = DID_ERROR;
+               } else if (flags & FCP_RESID_OVER)
+                       host_status = DID_ERROR;
+
+               CSIO_INC_STATS(scm, n_rsperror);
+               break;
+
+       case FW_SCSI_OVER_FLOW_ERR:
+               csio_warn(hw,
+                         "Over-flow error,cmnd:0x%x expected len:0x%x"
+                         " resid:0x%x\n", cmnd->cmnd[0],
+                         scsi_bufflen(cmnd), scsi_get_resid(cmnd));
+               host_status = DID_ERROR;
+               CSIO_INC_STATS(scm, n_ovflerror);
+               break;
+
+       case FW_SCSI_UNDER_FLOW_ERR:
+               csio_warn(hw,
+                         "Under-flow error,cmnd:0x%x expected"
+                         " len:0x%x resid:0x%x lun:0x%x ssn:0x%x\n",
+                         cmnd->cmnd[0], scsi_bufflen(cmnd),
+                         scsi_get_resid(cmnd), cmnd->device->lun,
+                         rn->flowid);
+               host_status = DID_ERROR;
+               CSIO_INC_STATS(scm, n_unflerror);
+               break;
+
+       case FW_SCSI_ABORT_REQUESTED:
+       case FW_SCSI_ABORTED:
+       case FW_SCSI_CLOSE_REQUESTED:
+               csio_dbg(hw, "Req %p cmd:%p op:%x %s\n", req, cmnd,
+                            cmnd->cmnd[0],
+                           (req->wr_status == FW_SCSI_CLOSE_REQUESTED) ?
+                           "closed" : "aborted");
+               /*
+                * csio_eh_abort_handler checks this value to
+                * succeed or fail the abort request.
+                */
+               host_status = DID_REQUEUE;
+               if (req->wr_status == FW_SCSI_CLOSE_REQUESTED)
+                       CSIO_INC_STATS(scm, n_closed);
+               else
+                       CSIO_INC_STATS(scm, n_aborted);
+               break;
+
+       case FW_SCSI_ABORT_TIMEDOUT:
+               /* FW timed out the abort itself */
+               csio_dbg(hw, "FW timed out abort req:%p cmnd:%p status:%x\n",
+                        req, cmnd, req->wr_status);
+               host_status = DID_ERROR;
+               CSIO_INC_STATS(scm, n_abrt_timedout);
+               break;
+
+       case FW_RDEV_NOT_READY:
+               /*
+                * In firmware, a RDEV can get into this state
+                * temporarily, before moving into dissapeared/lost
+                * state. So, the driver should complete the request equivalent
+                * to device-disappeared!
+                */
+               CSIO_INC_STATS(scm, n_rdev_nr_error);
+               host_status = DID_ERROR;
+               break;
+
+       case FW_ERR_RDEV_LOST:
+               CSIO_INC_STATS(scm, n_rdev_lost_error);
+               host_status = DID_ERROR;
+               break;
+
+       case FW_ERR_RDEV_LOGO:
+               CSIO_INC_STATS(scm, n_rdev_logo_error);
+               host_status = DID_ERROR;
+               break;
+
+       case FW_ERR_RDEV_IMPL_LOGO:
+               host_status = DID_ERROR;
+               break;
+
+       case FW_ERR_LINK_DOWN:
+               CSIO_INC_STATS(scm, n_link_down_error);
+               host_status = DID_ERROR;
+               break;
+
+       case FW_FCOE_NO_XCHG:
+               CSIO_INC_STATS(scm, n_no_xchg_error);
+               host_status = DID_ERROR;
+               break;
+
+       default:
+               csio_err(hw, "Unknown SCSI FW WR status:%d req:%p cmnd:%p\n",
+                           req->wr_status, req, cmnd);
+               CSIO_DB_ASSERT(0);
+
+               CSIO_INC_STATS(scm, n_unknown_error);
+               host_status = DID_ERROR;
+               break;
+       }
+
+out:
+       if (req->nsge > 0)
+               scsi_dma_unmap(cmnd);
+
+       cmnd->result = (((host_status) << 16) | scsi_status);
+       cmnd->scsi_done(cmnd);
+
+       /* Wake up waiting threads */
+       csio_scsi_cmnd(req) = NULL;
+       complete_all(&req->cmplobj);
+}
+
+/*
+ * csio_scsi_cbfn - SCSI callback function.
+ * @hw: HW module.
+ * @req: IO request.
+ *
+ */
+static void
+csio_scsi_cbfn(struct csio_hw *hw, struct csio_ioreq *req)
+{
+       struct scsi_cmnd *cmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+       uint8_t scsi_status = SAM_STAT_GOOD;
+       uint32_t host_status = DID_OK;
+
+       if (likely(req->wr_status == FW_SUCCESS)) {
+               if (req->nsge > 0) {
+                       scsi_dma_unmap(cmnd);
+                       if (req->dcopy)
+                               host_status = csio_scsi_copy_to_sgl(hw, req);
+               }
+
+               cmnd->result = (((host_status) << 16) | scsi_status);
+               cmnd->scsi_done(cmnd);
+               csio_scsi_cmnd(req) = NULL;
+               CSIO_INC_STATS(csio_hw_to_scsim(hw), n_tot_success);
+       } else {
+               /* Error handling */
+               csio_scsi_err_handler(hw, req);
+       }
+}
+
+/**
+ * csio_queuecommand - Entry point to kickstart an I/O request.
+ * @host:      The scsi_host pointer.
+ * @cmnd:      The I/O request from ML.
+ *
+ * This routine does the following:
+ *     - Checks for HW and Rnode module readiness.
+ *     - Gets a free ioreq structure (which is already initialized
+ *       to uninit during its allocation).
+ *     - Maps SG elements.
+ *     - Initializes ioreq members.
+ *     - Kicks off the SCSI state machine for this IO.
+ *     - Returns busy status on error.
+ */
+static int
+csio_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmnd)
+{
+       struct csio_lnode *ln = shost_priv(host);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+       struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+       struct csio_ioreq *ioreq = NULL;
+       unsigned long flags;
+       int nsge = 0;
+       int rv = SCSI_MLQUEUE_HOST_BUSY, nr;
+       int retval;
+       int cpu;
+       struct csio_scsi_qset *sqset;
+       struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+
+       if (!blk_rq_cpu_valid(cmnd->request))
+               cpu = smp_processor_id();
+       else
+               cpu = cmnd->request->cpu;
+
+       sqset = &hw->sqset[ln->portid][cpu];
+
+       nr = fc_remote_port_chkready(rport);
+       if (nr) {
+               cmnd->result = nr;
+               CSIO_INC_STATS(scsim, n_rn_nr_error);
+               goto err_done;
+       }
+
+       if (unlikely(!csio_is_hw_ready(hw))) {
+               cmnd->result = (DID_REQUEUE << 16);
+               CSIO_INC_STATS(scsim, n_hw_nr_error);
+               goto err_done;
+       }
+
+       /* Get req->nsge, if there are SG elements to be mapped  */
+       nsge = scsi_dma_map(cmnd);
+       if (unlikely(nsge < 0)) {
+               CSIO_INC_STATS(scsim, n_dmamap_error);
+               goto err;
+       }
+
+       /* Do we support so many mappings? */
+       if (unlikely(nsge > scsim->max_sge)) {
+               csio_warn(hw,
+                         "More SGEs than can be supported."
+                         " SGEs: %d, Max SGEs: %d\n", nsge, scsim->max_sge);
+               CSIO_INC_STATS(scsim, n_unsupp_sge_error);
+               goto err_dma_unmap;
+       }
+
+       /* Get a free ioreq structure - SM is already set to uninit */
+       ioreq = csio_get_scsi_ioreq_lock(hw, scsim);
+       if (!ioreq) {
+               csio_err(hw, "Out of I/O request elements. Active #:%d\n",
+                        scsim->stats.n_active);
+               CSIO_INC_STATS(scsim, n_no_req_error);
+               goto err_dma_unmap;
+       }
+
+       ioreq->nsge             = nsge;
+       ioreq->lnode            = ln;
+       ioreq->rnode            = rn;
+       ioreq->iq_idx           = sqset->iq_idx;
+       ioreq->eq_idx           = sqset->eq_idx;
+       ioreq->wr_status        = 0;
+       ioreq->drv_status       = 0;
+       csio_scsi_cmnd(ioreq)   = (void *)cmnd;
+       ioreq->tmo              = 0;
+       ioreq->datadir          = cmnd->sc_data_direction;
+
+       if (cmnd->sc_data_direction == DMA_TO_DEVICE) {
+               CSIO_INC_STATS(ln, n_output_requests);
+               ln->stats.n_output_bytes += scsi_bufflen(cmnd);
+       } else if (cmnd->sc_data_direction == DMA_FROM_DEVICE) {
+               CSIO_INC_STATS(ln, n_input_requests);
+               ln->stats.n_input_bytes += scsi_bufflen(cmnd);
+       } else
+               CSIO_INC_STATS(ln, n_control_requests);
+
+       /* Set cbfn */
+       ioreq->io_cbfn = csio_scsi_cbfn;
+
+       /* Needed during abort */
+       cmnd->host_scribble = (unsigned char *)ioreq;
+       cmnd->SCp.Message = 0;
+
+       /* Kick off SCSI IO SM on the ioreq */
+       spin_lock_irqsave(&hw->lock, flags);
+       retval = csio_scsi_start_io(ioreq);
+       spin_unlock_irqrestore(&hw->lock, flags);
+
+       if (retval != 0) {
+               csio_err(hw, "ioreq: %p couldnt be started, status:%d\n",
+                        ioreq, retval);
+               CSIO_INC_STATS(scsim, n_busy_error);
+               goto err_put_req;
+       }
+
+       return 0;
+
+err_put_req:
+       csio_put_scsi_ioreq_lock(hw, scsim, ioreq);
+err_dma_unmap:
+       if (nsge > 0)
+               scsi_dma_unmap(cmnd);
+err:
+       return rv;
+
+err_done:
+       cmnd->scsi_done(cmnd);
+       return 0;
+}
+
+static int
+csio_do_abrt_cls(struct csio_hw *hw, struct csio_ioreq *ioreq, bool abort)
+{
+       int rv;
+       int cpu = smp_processor_id();
+       struct csio_lnode *ln = ioreq->lnode;
+       struct csio_scsi_qset *sqset = &hw->sqset[ln->portid][cpu];
+
+       ioreq->tmo = CSIO_SCSI_ABRT_TMO_MS;
+       /*
+        * Use current processor queue for posting the abort/close, but retain
+        * the ingress queue ID of the original I/O being aborted/closed - we
+        * need the abort/close completion to be received on the same queue
+        * as the original I/O.
+        */
+       ioreq->eq_idx = sqset->eq_idx;
+
+       if (abort == SCSI_ABORT)
+               rv = csio_scsi_abort(ioreq);
+       else
+               rv = csio_scsi_close(ioreq);
+
+       return rv;
+}
+
+static int
+csio_eh_abort_handler(struct scsi_cmnd *cmnd)
+{
+       struct csio_ioreq *ioreq;
+       struct csio_lnode *ln = shost_priv(cmnd->device->host);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+       int ready = 0, ret;
+       unsigned long tmo = 0;
+       int rv;
+       struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+
+       ret = fc_block_scsi_eh(cmnd);
+       if (ret)
+               return ret;
+
+       ioreq = (struct csio_ioreq *)cmnd->host_scribble;
+       if (!ioreq)
+               return SUCCESS;
+
+       if (!rn)
+               return FAILED;
+
+       csio_dbg(hw,
+                "Request to abort ioreq:%p cmd:%p cdb:%08llx"
+                " ssni:0x%x lun:%d iq:0x%x\n",
+               ioreq, cmnd, *((uint64_t *)cmnd->cmnd), rn->flowid,
+               cmnd->device->lun, csio_q_physiqid(hw, ioreq->iq_idx));
+
+       if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) != cmnd) {
+               CSIO_INC_STATS(scsim, n_abrt_race_comp);
+               return SUCCESS;
+       }
+
+       ready = csio_is_lnode_ready(ln);
+       tmo = CSIO_SCSI_ABRT_TMO_MS;
+
+       spin_lock_irq(&hw->lock);
+       rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE));
+       spin_unlock_irq(&hw->lock);
+
+       if (rv != 0) {
+               if (rv == -EINVAL) {
+                       /* Return success, if abort/close request issued on
+                        * already completed IO
+                        */
+                       return SUCCESS;
+               }
+               if (ready)
+                       CSIO_INC_STATS(scsim, n_abrt_busy_error);
+               else
+                       CSIO_INC_STATS(scsim, n_cls_busy_error);
+
+               goto inval_scmnd;
+       }
+
+       /* Wait for completion */
+       init_completion(&ioreq->cmplobj);
+       wait_for_completion_timeout(&ioreq->cmplobj, msecs_to_jiffies(tmo));
+
+       /* FW didnt respond to abort within our timeout */
+       if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) {
+
+               csio_err(hw, "Abort timed out -- req: %p\n", ioreq);
+               CSIO_INC_STATS(scsim, n_abrt_timedout);
+
+inval_scmnd:
+               if (ioreq->nsge > 0)
+                       scsi_dma_unmap(cmnd);
+
+               spin_lock_irq(&hw->lock);
+               csio_scsi_cmnd(ioreq) = NULL;
+               spin_unlock_irq(&hw->lock);
+
+               cmnd->result = (DID_ERROR << 16);
+               cmnd->scsi_done(cmnd);
+
+               return FAILED;
+       }
+
+       /* FW successfully aborted the request */
+       if (host_byte(cmnd->result) == DID_REQUEUE) {
+               csio_info(hw,
+                       "Aborted SCSI command to (%d:%d) serial#:0x%lx\n",
+                       cmnd->device->id, cmnd->device->lun,
+                       cmnd->serial_number);
+               return SUCCESS;
+       } else {
+               csio_info(hw,
+                       "Failed to abort SCSI command, (%d:%d) serial#:0x%lx\n",
+                       cmnd->device->id, cmnd->device->lun,
+                       cmnd->serial_number);
+               return FAILED;
+       }
+}
+
+/*
+ * csio_tm_cbfn - TM callback function.
+ * @hw: HW module.
+ * @req: IO request.
+ *
+ * Cache the result in 'cmnd', since ioreq will be freed soon
+ * after we return from here, and the waiting thread shouldnt trust
+ * the ioreq contents.
+ */
+static void
+csio_tm_cbfn(struct csio_hw *hw, struct csio_ioreq *req)
+{
+       struct scsi_cmnd *cmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+       struct csio_dma_buf *dma_buf;
+       uint8_t flags = 0;
+       struct fcp_resp_with_ext *fcp_resp;
+       struct fcp_resp_rsp_info *rsp_info;
+
+       csio_dbg(hw, "req: %p in csio_tm_cbfn status: %d\n",
+                     req, req->wr_status);
+
+       /* Cache FW return status */
+       cmnd->SCp.Status = req->wr_status;
+
+       /* Special handling based on FCP response */
+
+       /*
+        * FW returns us this error, if flags were set. FCP4 says
+        * FCP_RSP_LEN_VAL in flags shall be set for TM completions.
+        * So if a target were to set this bit, we expect that the
+        * rsp_code is set to FCP_TMF_CMPL for a successful TM
+        * completion. Any other rsp_code means TM operation failed.
+        * If a target were to just ignore setting flags, we treat
+        * the TM operation as success, and FW returns FW_SUCCESS.
+        */
+       if (req->wr_status == FW_SCSI_RSP_ERR) {
+               dma_buf = &req->dma_buf;
+               fcp_resp = (struct fcp_resp_with_ext *)dma_buf->vaddr;
+               rsp_info = (struct fcp_resp_rsp_info *)(fcp_resp + 1);
+
+               flags = fcp_resp->resp.fr_flags;
+
+               /* Modify return status if flags indicate success */
+               if (flags & FCP_RSP_LEN_VAL)
+                       if (rsp_info->rsp_code == FCP_TMF_CMPL)
+                               cmnd->SCp.Status = FW_SUCCESS;
+
+               csio_dbg(hw, "TM FCP rsp code: %d\n", rsp_info->rsp_code);
+       }
+
+       /* Wake up the TM handler thread */
+       csio_scsi_cmnd(req) = NULL;
+}
+
+static int
+csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
+{
+       struct csio_lnode *ln = shost_priv(cmnd->device->host);
+       struct csio_hw *hw = csio_lnode_to_hw(ln);
+       struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+       struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+       struct csio_ioreq *ioreq = NULL;
+       struct csio_scsi_qset *sqset;
+       unsigned long flags;
+       int retval;
+       int count, ret;
+       LIST_HEAD(local_q);
+       struct csio_scsi_level_data sld;
+
+       if (!rn)
+               goto fail;
+
+       csio_dbg(hw, "Request to reset LUN:%d (ssni:0x%x tgtid:%d)\n",
+                     cmnd->device->lun, rn->flowid, rn->scsi_id);
+
+       if (!csio_is_lnode_ready(ln)) {
+               csio_err(hw,
+                        "LUN reset cannot be issued on non-ready"
+                        " local node vnpi:0x%x (LUN:%d)\n",
+                        ln->vnp_flowid, cmnd->device->lun);
+               goto fail;
+       }
+
+       /* Lnode is ready, now wait on rport node readiness */
+       ret = fc_block_scsi_eh(cmnd);
+       if (ret)
+               return ret;
+
+       /*
+        * If we have blocked in the previous call, at this point, either the
+        * remote node has come back online, or device loss timer has fired
+        * and the remote node is destroyed. Allow the LUN reset only for
+        * the former case, since LUN reset is a TMF I/O on the wire, and we
+        * need a valid session to issue it.
+        */
+       if (fc_remote_port_chkready(rn->rport)) {
+               csio_err(hw,
+                        "LUN reset cannot be issued on non-ready"
+                        " remote node ssni:0x%x (LUN:%d)\n",
+                        rn->flowid, cmnd->device->lun);
+               goto fail;
+       }
+
+       /* Get a free ioreq structure - SM is already set to uninit */
+       ioreq = csio_get_scsi_ioreq_lock(hw, scsim);
+
+       if (!ioreq) {
+               csio_err(hw, "Out of IO request elements. Active # :%d\n",
+                        scsim->stats.n_active);
+               goto fail;
+       }
+
+       sqset                   = &hw->sqset[ln->portid][smp_processor_id()];
+       ioreq->nsge             = 0;
+       ioreq->lnode            = ln;
+       ioreq->rnode            = rn;
+       ioreq->iq_idx           = sqset->iq_idx;
+       ioreq->eq_idx           = sqset->eq_idx;
+
+       csio_scsi_cmnd(ioreq)   = cmnd;
+       cmnd->host_scribble     = (unsigned char *)ioreq;
+       cmnd->SCp.Status        = 0;
+
+       cmnd->SCp.Message       = FCP_TMF_LUN_RESET;
+       ioreq->tmo              = CSIO_SCSI_LUNRST_TMO_MS / 1000;
+
+       /*
+        * FW times the LUN reset for ioreq->tmo, so we got to wait a little
+        * longer (10s for now) than that to allow FW to return the timed
+        * out command.
+        */
+       count = DIV_ROUND_UP((ioreq->tmo + 10) * 1000, CSIO_SCSI_TM_POLL_MS);
+
+       /* Set cbfn */
+       ioreq->io_cbfn = csio_tm_cbfn;
+
+       /* Save of the ioreq info for later use */
+       sld.level = CSIO_LEV_LUN;
+       sld.lnode = ioreq->lnode;
+       sld.rnode = ioreq->rnode;
+       sld.oslun = (uint64_t)cmnd->device->lun;
+
+       spin_lock_irqsave(&hw->lock, flags);
+       /* Kick off TM SM on the ioreq */
+       retval = csio_scsi_start_tm(ioreq);
+       spin_unlock_irqrestore(&hw->lock, flags);
+
+       if (retval != 0) {
+               csio_err(hw, "Failed to issue LUN reset, req:%p, status:%d\n",
+                           ioreq, retval);
+               goto fail_ret_ioreq;
+       }
+
+       csio_dbg(hw, "Waiting max %d secs for LUN reset completion\n",
+                   count * (CSIO_SCSI_TM_POLL_MS / 1000));
+       /* Wait for completion */
+       while ((((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd)
+                                                               && count--)
+               msleep(CSIO_SCSI_TM_POLL_MS);
+
+       /* LUN reset timed-out */
+       if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) {
+               csio_err(hw, "LUN reset (%d:%d) timed out\n",
+                        cmnd->device->id, cmnd->device->lun);
+
+               spin_lock_irq(&hw->lock);
+               csio_scsi_drvcleanup(ioreq);
+               list_del_init(&ioreq->sm.sm_list);
+               spin_unlock_irq(&hw->lock);
+
+               goto fail_ret_ioreq;
+       }
+
+       /* LUN reset returned, check cached status */
+       if (cmnd->SCp.Status != FW_SUCCESS) {
+               csio_err(hw, "LUN reset failed (%d:%d), status: %d\n",
+                        cmnd->device->id, cmnd->device->lun, cmnd->SCp.Status);
+               goto fail;
+       }
+
+       /* LUN reset succeeded, Start aborting affected I/Os */
+       /*
+        * Since the host guarantees during LUN reset that there
+        * will not be any more I/Os to that LUN, until the LUN reset
+        * completes, we gather pending I/Os after the LUN reset.
+        */
+       spin_lock_irq(&hw->lock);
+       csio_scsi_gather_active_ios(scsim, &sld, &local_q);
+
+       retval = csio_scsi_abort_io_q(scsim, &local_q, 30000);
+       spin_unlock_irq(&hw->lock);
+
+       /* Aborts may have timed out */
+       if (retval != 0) {
+               csio_err(hw,
+                        "Attempt to abort I/Os during LUN reset of %d"
+                        " returned %d\n", cmnd->device->lun, retval);
+               /* Return I/Os back to active_q */
+               spin_lock_irq(&hw->lock);
+               list_splice_tail_init(&local_q, &scsim->active_q);
+               spin_unlock_irq(&hw->lock);
+               goto fail;
+       }
+
+       CSIO_INC_STATS(rn, n_lun_rst);
+
+       csio_info(hw, "LUN reset occurred (%d:%d)\n",
+                 cmnd->device->id, cmnd->device->lun);
+
+       return SUCCESS;
+
+fail_ret_ioreq:
+       csio_put_scsi_ioreq_lock(hw, scsim, ioreq);
+fail:
+       CSIO_INC_STATS(rn, n_lun_rst_fail);
+       return FAILED;
+}
+
+static int
+csio_slave_alloc(struct scsi_device *sdev)
+{
+       struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+
+       if (!rport || fc_remote_port_chkready(rport))
+               return -ENXIO;
+
+       sdev->hostdata = *((struct csio_lnode **)(rport->dd_data));
+
+       return 0;
+}
+
+static int
+csio_slave_configure(struct scsi_device *sdev)
+{
+       if (sdev->tagged_supported)
+               scsi_activate_tcq(sdev, csio_lun_qdepth);
+       else
+               scsi_deactivate_tcq(sdev, csio_lun_qdepth);
+
+       return 0;
+}
+
+static void
+csio_slave_destroy(struct scsi_device *sdev)
+{
+       sdev->hostdata = NULL;
+}
+
+static int
+csio_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+       struct csio_lnode *ln = shost_priv(shost);
+       int rv = 1;
+
+       spin_lock_irq(shost->host_lock);
+       if (!ln->hwp || csio_list_deleted(&ln->sm.sm_list))
+               goto out;
+
+       rv = csio_scan_done(ln, jiffies, time, csio_max_scan_tmo * HZ,
+                           csio_delta_scan_tmo * HZ);
+out:
+       spin_unlock_irq(shost->host_lock);
+
+       return rv;
+}
+
+struct scsi_host_template csio_fcoe_shost_template = {
+       .module                 = THIS_MODULE,
+       .name                   = CSIO_DRV_DESC,
+       .proc_name              = KBUILD_MODNAME,
+       .queuecommand           = csio_queuecommand,
+       .eh_abort_handler       = csio_eh_abort_handler,
+       .eh_device_reset_handler = csio_eh_lun_reset_handler,
+       .slave_alloc            = csio_slave_alloc,
+       .slave_configure        = csio_slave_configure,
+       .slave_destroy          = csio_slave_destroy,
+       .scan_finished          = csio_scan_finished,
+       .this_id                = -1,
+       .sg_tablesize           = CSIO_SCSI_MAX_SGE,
+       .cmd_per_lun            = CSIO_MAX_CMD_PER_LUN,
+       .use_clustering         = ENABLE_CLUSTERING,
+       .shost_attrs            = csio_fcoe_lport_attrs,
+       .max_sectors            = CSIO_MAX_SECTOR_SIZE,
+};
+
+struct scsi_host_template csio_fcoe_shost_vport_template = {
+       .module                 = THIS_MODULE,
+       .name                   = CSIO_DRV_DESC,
+       .proc_name              = KBUILD_MODNAME,
+       .queuecommand           = csio_queuecommand,
+       .eh_abort_handler       = csio_eh_abort_handler,
+       .eh_device_reset_handler = csio_eh_lun_reset_handler,
+       .slave_alloc            = csio_slave_alloc,
+       .slave_configure        = csio_slave_configure,
+       .slave_destroy          = csio_slave_destroy,
+       .scan_finished          = csio_scan_finished,
+       .this_id                = -1,
+       .sg_tablesize           = CSIO_SCSI_MAX_SGE,
+       .cmd_per_lun            = CSIO_MAX_CMD_PER_LUN,
+       .use_clustering         = ENABLE_CLUSTERING,
+       .shost_attrs            = csio_fcoe_vport_attrs,
+       .max_sectors            = CSIO_MAX_SECTOR_SIZE,
+};
+
+/*
+ * csio_scsi_alloc_ddp_bufs - Allocate buffers for DDP of unaligned SGLs.
+ * @scm: SCSI Module
+ * @hw: HW device.
+ * @buf_size: buffer size
+ * @num_buf : Number of buffers.
+ *
+ * This routine allocates DMA buffers required for SCSI Data xfer, if
+ * each SGL buffer for a SCSI Read request posted by SCSI midlayer are
+ * not virtually contiguous.
+ */
+static int
+csio_scsi_alloc_ddp_bufs(struct csio_scsim *scm, struct csio_hw *hw,
+                        int buf_size, int num_buf)
+{
+       int n = 0;
+       struct list_head *tmp;
+       struct csio_dma_buf *ddp_desc = NULL;
+       uint32_t unit_size = 0;
+
+       if (!num_buf)
+               return 0;
+
+       if (!buf_size)
+               return -EINVAL;
+
+       INIT_LIST_HEAD(&scm->ddp_freelist);
+
+       /* Align buf size to page size */
+       buf_size = (buf_size + PAGE_SIZE - 1) & PAGE_MASK;
+       /* Initialize dma descriptors */
+       for (n = 0; n < num_buf; n++) {
+               /* Set unit size to request size */
+               unit_size = buf_size;
+               ddp_desc = kzalloc(sizeof(struct csio_dma_buf), GFP_KERNEL);
+               if (!ddp_desc) {
+                       csio_err(hw,
+                                "Failed to allocate ddp descriptors,"
+                                " Num allocated = %d.\n",
+                                scm->stats.n_free_ddp);
+                       goto no_mem;
+               }
+
+               /* Allocate Dma buffers for DDP */
+               ddp_desc->vaddr = pci_alloc_consistent(hw->pdev, unit_size,
+                                                       &ddp_desc->paddr);
+               if (!ddp_desc->vaddr) {
+                       csio_err(hw,
+                                "SCSI response DMA buffer (ddp) allocation"
+                                " failed!\n");
+                       kfree(ddp_desc);
+                       goto no_mem;
+               }
+
+               ddp_desc->len = unit_size;
+
+               /* Added it to scsi ddp freelist */
+               list_add_tail(&ddp_desc->list, &scm->ddp_freelist);
+               CSIO_INC_STATS(scm, n_free_ddp);
+       }
+
+       return 0;
+no_mem:
+       /* release dma descs back to freelist and free dma memory */
+       list_for_each(tmp, &scm->ddp_freelist) {
+               ddp_desc = (struct csio_dma_buf *) tmp;
+               tmp = csio_list_prev(tmp);
+               pci_free_consistent(hw->pdev, ddp_desc->len, ddp_desc->vaddr,
+                                   ddp_desc->paddr);
+               list_del_init(&ddp_desc->list);
+               kfree(ddp_desc);
+       }
+       scm->stats.n_free_ddp = 0;
+
+       return -ENOMEM;
+}
+
+/*
+ * csio_scsi_free_ddp_bufs - free DDP buffers of unaligned SGLs.
+ * @scm: SCSI Module
+ * @hw: HW device.
+ *
+ * This routine frees ddp buffers.
+ */
+static void
+csio_scsi_free_ddp_bufs(struct csio_scsim *scm, struct csio_hw *hw)
+{
+       struct list_head *tmp;
+       struct csio_dma_buf *ddp_desc;
+
+       /* release dma descs back to freelist and free dma memory */
+       list_for_each(tmp, &scm->ddp_freelist) {
+               ddp_desc = (struct csio_dma_buf *) tmp;
+               tmp = csio_list_prev(tmp);
+               pci_free_consistent(hw->pdev, ddp_desc->len, ddp_desc->vaddr,
+                                   ddp_desc->paddr);
+               list_del_init(&ddp_desc->list);
+               kfree(ddp_desc);
+       }
+       scm->stats.n_free_ddp = 0;
+}
+
+/**
+ * csio_scsim_init - Initialize SCSI Module
+ * @scm:       SCSI Module
+ * @hw:                HW module
+ *
+ */
+int
+csio_scsim_init(struct csio_scsim *scm, struct csio_hw *hw)
+{
+       int i;
+       struct csio_ioreq *ioreq;
+       struct csio_dma_buf *dma_buf;
+
+       INIT_LIST_HEAD(&scm->active_q);
+       scm->hw = hw;
+
+       scm->proto_cmd_len = sizeof(struct fcp_cmnd);
+       scm->proto_rsp_len = CSIO_SCSI_RSP_LEN;
+       scm->max_sge = CSIO_SCSI_MAX_SGE;
+
+       spin_lock_init(&scm->freelist_lock);
+
+       /* Pre-allocate ioreqs and initialize them */
+       INIT_LIST_HEAD(&scm->ioreq_freelist);
+       for (i = 0; i < csio_scsi_ioreqs; i++) {
+
+               ioreq = kzalloc(sizeof(struct csio_ioreq), GFP_KERNEL);
+               if (!ioreq) {
+                       csio_err(hw,
+                                "I/O request element allocation failed, "
+                                " Num allocated = %d.\n",
+                                scm->stats.n_free_ioreq);
+
+                       goto free_ioreq;
+               }
+
+               /* Allocate Dma buffers for Response Payload */
+               dma_buf = &ioreq->dma_buf;
+               dma_buf->vaddr = pci_pool_alloc(hw->scsi_pci_pool, GFP_KERNEL,
+                                               &dma_buf->paddr);
+               if (!dma_buf->vaddr) {
+                       csio_err(hw,
+                                "SCSI response DMA buffer allocation"
+                                " failed!\n");
+                       kfree(ioreq);
+                       goto free_ioreq;
+               }
+
+               dma_buf->len = scm->proto_rsp_len;
+
+               /* Set state to uninit */
+               csio_init_state(&ioreq->sm, csio_scsis_uninit);
+               INIT_LIST_HEAD(&ioreq->gen_list);
+               init_completion(&ioreq->cmplobj);
+
+               list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist);
+               CSIO_INC_STATS(scm, n_free_ioreq);
+       }
+
+       if (csio_scsi_alloc_ddp_bufs(scm, hw, PAGE_SIZE, csio_ddp_descs))
+               goto free_ioreq;
+
+       return 0;
+
+free_ioreq:
+       /*
+        * Free up existing allocations, since an error
+        * from here means we are returning for good
+        */
+       while (!list_empty(&scm->ioreq_freelist)) {
+               struct csio_sm *tmp;
+
+               tmp = list_first_entry(&scm->ioreq_freelist,
+                                      struct csio_sm, sm_list);
+               list_del_init(&tmp->sm_list);
+               ioreq = (struct csio_ioreq *)tmp;
+
+               dma_buf = &ioreq->dma_buf;
+               pci_pool_free(hw->scsi_pci_pool, dma_buf->vaddr,
+                             dma_buf->paddr);
+
+               kfree(ioreq);
+       }
+
+       scm->stats.n_free_ioreq = 0;
+
+       return -ENOMEM;
+}
+
+/**
+ * csio_scsim_exit: Uninitialize SCSI Module
+ * @scm: SCSI Module
+ *
+ */
+void
+csio_scsim_exit(struct csio_scsim *scm)
+{
+       struct csio_ioreq *ioreq;
+       struct csio_dma_buf *dma_buf;
+
+       while (!list_empty(&scm->ioreq_freelist)) {
+               struct csio_sm *tmp;
+
+               tmp = list_first_entry(&scm->ioreq_freelist,
+                                      struct csio_sm, sm_list);
+               list_del_init(&tmp->sm_list);
+               ioreq = (struct csio_ioreq *)tmp;
+
+               dma_buf = &ioreq->dma_buf;
+               pci_pool_free(scm->hw->scsi_pci_pool, dma_buf->vaddr,
+                             dma_buf->paddr);
+
+               kfree(ioreq);
+       }
+
+       scm->stats.n_free_ioreq = 0;
+
+       csio_scsi_free_ddp_bufs(scm, scm->hw);
+}
diff --git a/drivers/scsi/csiostor/csio_scsi.h b/drivers/scsi/csiostor/csio_scsi.h
new file mode 100644 (file)
index 0000000..2257c3d
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_SCSI_H__
+#define __CSIO_SCSI_H__
+
+#include <linux/spinlock_types.h>
+#include <linux/completion.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/fc/fc_fcp.h>
+
+#include "csio_defs.h"
+#include "csio_wr.h"
+
+extern struct scsi_host_template csio_fcoe_shost_template;
+extern struct scsi_host_template csio_fcoe_shost_vport_template;
+
+extern int csio_scsi_eqsize;
+extern int csio_scsi_iqlen;
+extern int csio_scsi_ioreqs;
+extern uint32_t csio_max_scan_tmo;
+extern uint32_t csio_delta_scan_tmo;
+extern int csio_lun_qdepth;
+
+/*
+ **************************** NOTE *******************************
+ * How do we calculate MAX FCoE SCSI SGEs? Here is the math:
+ * Max Egress WR size = 512 bytes
+ * One SCSI egress WR has the following fixed no of bytes:
+ *      48 (sizeof(struct fw_scsi_write[read]_wr)) - FW WR
+ *    + 32 (sizeof(struct fc_fcp_cmnd)) - Immediate FCP_CMD
+ *    ------
+ *      80
+ *    ------
+ * That leaves us with 512 - 96 = 432 bytes for data SGE. Using
+ * struct ulptx_sgl header for the SGE consumes:
+ *     - 4 bytes for cmnd_sge.
+ *     - 12 bytes for the first SGL.
+ * That leaves us with 416 bytes for the remaining SGE pairs. Which is
+ * is 416 / 24 (size(struct ulptx_sge_pair)) = 17 SGE pairs,
+ * or 34 SGEs. Adding the first SGE fetches us 35 SGEs.
+ */
+#define CSIO_SCSI_MAX_SGE              35
+#define CSIO_SCSI_ABRT_TMO_MS          60000
+#define CSIO_SCSI_LUNRST_TMO_MS                60000
+#define CSIO_SCSI_TM_POLL_MS           2000    /* should be less than
+                                                * all TM timeouts.
+                                                */
+#define CSIO_SCSI_IQ_WRSZ              128
+#define CSIO_SCSI_IQSIZE               (csio_scsi_iqlen * CSIO_SCSI_IQ_WRSZ)
+
+#define        CSIO_MAX_SNS_LEN                128
+#define        CSIO_SCSI_RSP_LEN       (FCP_RESP_WITH_EXT + 4 + CSIO_MAX_SNS_LEN)
+
+/* Reference to scsi_cmnd */
+#define csio_scsi_cmnd(req)            ((req)->scratch1)
+
+struct csio_scsi_stats {
+       uint64_t                n_tot_success;  /* Total number of good I/Os */
+       uint32_t                n_rn_nr_error;  /* No. of remote-node-not-
+                                                * ready errors
+                                                */
+       uint32_t                n_hw_nr_error;  /* No. of hw-module-not-
+                                                * ready errors
+                                                */
+       uint32_t                n_dmamap_error; /* No. of DMA map erros */
+       uint32_t                n_unsupp_sge_error; /* No. of too-many-SGes
+                                                    * errors.
+                                                    */
+       uint32_t                n_no_req_error; /* No. of Out-of-ioreqs error */
+       uint32_t                n_busy_error;   /* No. of -EBUSY errors */
+       uint32_t                n_hosterror;    /* No. of FW_HOSTERROR I/O */
+       uint32_t                n_rsperror;     /* No. of response errors */
+       uint32_t                n_autosense;    /* No. of auto sense replies */
+       uint32_t                n_ovflerror;    /* No. of overflow errors */
+       uint32_t                n_unflerror;    /* No. of underflow errors */
+       uint32_t                n_rdev_nr_error;/* No. of rdev not
+                                                * ready errors
+                                                */
+       uint32_t                n_rdev_lost_error;/* No. of rdev lost errors */
+       uint32_t                n_rdev_logo_error;/* No. of rdev logo errors */
+       uint32_t                n_link_down_error;/* No. of link down errors */
+       uint32_t                n_no_xchg_error; /* No. no exchange error */
+       uint32_t                n_unknown_error;/* No. of unhandled errors */
+       uint32_t                n_aborted;      /* No. of aborted I/Os */
+       uint32_t                n_abrt_timedout; /* No. of abort timedouts */
+       uint32_t                n_abrt_fail;    /* No. of abort failures */
+       uint32_t                n_abrt_dups;    /* No. of duplicate aborts */
+       uint32_t                n_abrt_race_comp; /* No. of aborts that raced
+                                                  * with completions.
+                                                  */
+       uint32_t                n_abrt_busy_error;/* No. of abort failures
+                                                  * due to -EBUSY.
+                                                  */
+       uint32_t                n_closed;       /* No. of closed I/Os */
+       uint32_t                n_cls_busy_error; /* No. of close failures
+                                                  * due to -EBUSY.
+                                                  */
+       uint32_t                n_active;       /* No. of IOs in active_q */
+       uint32_t                n_tm_active;    /* No. of TMs in active_q */
+       uint32_t                n_wcbfn;        /* No. of I/Os in worker
+                                                * cbfn q
+                                                */
+       uint32_t                n_free_ioreq;   /* No. of freelist entries */
+       uint32_t                n_free_ddp;     /* No. of DDP freelist */
+       uint32_t                n_unaligned;    /* No. of Unaligned SGls */
+       uint32_t                n_inval_cplop;  /* No. invalid CPL op's in IQ */
+       uint32_t                n_inval_scsiop; /* No. invalid scsi op's in IQ*/
+};
+
+struct csio_scsim {
+       struct csio_hw          *hw;            /* Pointer to HW moduel */
+       uint8_t                 max_sge;        /* Max SGE */
+       uint8_t                 proto_cmd_len;  /* Proto specific SCSI
+                                                * cmd length
+                                                */
+       uint16_t                proto_rsp_len;  /* Proto specific SCSI
+                                                * response length
+                                                */
+       spinlock_t              freelist_lock;  /* Lock for ioreq freelist */
+       struct list_head        active_q;       /* Outstanding SCSI I/Os */
+       struct list_head        ioreq_freelist; /* Free list of ioreq's */
+       struct list_head        ddp_freelist;   /* DDP descriptor freelist */
+       struct csio_scsi_stats  stats;          /* This module's statistics */
+};
+
+/* State machine defines */
+enum csio_scsi_ev {
+       CSIO_SCSIE_START_IO = 1,                /* Start a regular SCSI IO */
+       CSIO_SCSIE_START_TM,                    /* Start a TM IO */
+       CSIO_SCSIE_COMPLETED,                   /* IO Completed */
+       CSIO_SCSIE_ABORT,                       /* Abort IO */
+       CSIO_SCSIE_ABORTED,                     /* IO Aborted */
+       CSIO_SCSIE_CLOSE,                       /* Close exchange */
+       CSIO_SCSIE_CLOSED,                      /* Exchange closed */
+       CSIO_SCSIE_DRVCLEANUP,                  /* Driver wants to manually
+                                                * cleanup this I/O.
+                                                */
+};
+
+enum csio_scsi_lev {
+       CSIO_LEV_ALL = 1,
+       CSIO_LEV_LNODE,
+       CSIO_LEV_RNODE,
+       CSIO_LEV_LUN,
+};
+
+struct csio_scsi_level_data {
+       enum csio_scsi_lev      level;
+       struct csio_rnode       *rnode;
+       struct csio_lnode       *lnode;
+       uint64_t                oslun;
+};
+
+static inline struct csio_ioreq *
+csio_get_scsi_ioreq(struct csio_scsim *scm)
+{
+       struct csio_sm *req;
+
+       if (likely(!list_empty(&scm->ioreq_freelist))) {
+               req = list_first_entry(&scm->ioreq_freelist,
+                                      struct csio_sm, sm_list);
+               list_del_init(&req->sm_list);
+               CSIO_DEC_STATS(scm, n_free_ioreq);
+               return (struct csio_ioreq *)req;
+       } else
+               return NULL;
+}
+
+static inline void
+csio_put_scsi_ioreq(struct csio_scsim *scm, struct csio_ioreq *ioreq)
+{
+       list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist);
+       CSIO_INC_STATS(scm, n_free_ioreq);
+}
+
+static inline void
+csio_put_scsi_ioreq_list(struct csio_scsim *scm, struct list_head *reqlist,
+                        int n)
+{
+       list_splice_init(reqlist, &scm->ioreq_freelist);
+       scm->stats.n_free_ioreq += n;
+}
+
+static inline struct csio_dma_buf *
+csio_get_scsi_ddp(struct csio_scsim *scm)
+{
+       struct csio_dma_buf *ddp;
+
+       if (likely(!list_empty(&scm->ddp_freelist))) {
+               ddp = list_first_entry(&scm->ddp_freelist,
+                                      struct csio_dma_buf, list);
+               list_del_init(&ddp->list);
+               CSIO_DEC_STATS(scm, n_free_ddp);
+               return ddp;
+       } else
+               return NULL;
+}
+
+static inline void
+csio_put_scsi_ddp(struct csio_scsim *scm, struct csio_dma_buf *ddp)
+{
+       list_add_tail(&ddp->list, &scm->ddp_freelist);
+       CSIO_INC_STATS(scm, n_free_ddp);
+}
+
+static inline void
+csio_put_scsi_ddp_list(struct csio_scsim *scm, struct list_head *reqlist,
+                        int n)
+{
+       list_splice_tail_init(reqlist, &scm->ddp_freelist);
+       scm->stats.n_free_ddp += n;
+}
+
+static inline void
+csio_scsi_completed(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_COMPLETED);
+       if (csio_list_deleted(&ioreq->sm.sm_list))
+               list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_aborted(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORTED);
+       list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_closed(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSED);
+       list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_drvcleanup(struct csio_ioreq *ioreq)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_DRVCLEANUP);
+}
+
+/*
+ * csio_scsi_start_io - Kick starts the IO SM.
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_start_io(struct csio_ioreq *ioreq)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_START_IO);
+       return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_start_tm - Kicks off the Task management IO SM.
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_start_tm(struct csio_ioreq *ioreq)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_START_TM);
+       return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_abort - Abort an IO request
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_abort(struct csio_ioreq *ioreq)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORT);
+       return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_close - Close an IO request
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_close(struct csio_ioreq *ioreq)
+{
+       csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSE);
+       return ioreq->drv_status;
+}
+
+void csio_scsi_cleanup_io_q(struct csio_scsim *, struct list_head *);
+int csio_scsim_cleanup_io(struct csio_scsim *, bool abort);
+int csio_scsim_cleanup_io_lnode(struct csio_scsim *,
+                                         struct csio_lnode *);
+struct csio_ioreq *csio_scsi_cmpl_handler(struct csio_hw *, void *, uint32_t,
+                                         struct csio_fl_dma_buf *,
+                                         void *, uint8_t **);
+int csio_scsi_qconfig(struct csio_hw *);
+int csio_scsim_init(struct csio_scsim *, struct csio_hw *);
+void csio_scsim_exit(struct csio_scsim *);
+
+#endif /* __CSIO_SCSI_H__ */
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
new file mode 100644 (file)
index 0000000..c32df1b
--- /dev/null
@@ -0,0 +1,1632 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <asm/page.h>
+#include <linux/cache.h>
+
+#include "csio_hw.h"
+#include "csio_wr.h"
+#include "csio_mb.h"
+#include "csio_defs.h"
+
+int csio_intr_coalesce_cnt;            /* value:SGE_INGRESS_RX_THRESHOLD[0] */
+static int csio_sge_thresh_reg;                /* SGE_INGRESS_RX_THRESHOLD[0] */
+
+int csio_intr_coalesce_time = 10;      /* value:SGE_TIMER_VALUE_1 */
+static int csio_sge_timer_reg = 1;
+
+#define CSIO_SET_FLBUF_SIZE(_hw, _reg, _val)                           \
+       csio_wr_reg32((_hw), (_val), SGE_FL_BUFFER_SIZE##_reg)
+
+static void
+csio_get_flbuf_size(struct csio_hw *hw, struct csio_sge *sge, uint32_t reg)
+{
+       sge->sge_fl_buf_size[reg] = csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE0 +
+                                                       reg * sizeof(uint32_t));
+}
+
+/* Free list buffer size */
+static inline uint32_t
+csio_wr_fl_bufsz(struct csio_sge *sge, struct csio_dma_buf *buf)
+{
+       return sge->sge_fl_buf_size[buf->paddr & 0xF];
+}
+
+/* Size of the egress queue status page */
+static inline uint32_t
+csio_wr_qstat_pgsz(struct csio_hw *hw)
+{
+       return (hw->wrm.sge.sge_control & EGRSTATUSPAGESIZE(1)) ?  128 : 64;
+}
+
+/* Ring freelist doorbell */
+static inline void
+csio_wr_ring_fldb(struct csio_hw *hw, struct csio_q *flq)
+{
+       /*
+        * Ring the doorbell only when we have atleast CSIO_QCREDIT_SZ
+        * number of bytes in the freelist queue. This translates to atleast
+        * 8 freelist buffer pointers (since each pointer is 8 bytes).
+        */
+       if (flq->inc_idx >= 8) {
+               csio_wr_reg32(hw, DBPRIO(1) | QID(flq->un.fl.flid) |
+                             PIDX(flq->inc_idx / 8),
+                             MYPF_REG(SGE_PF_KDOORBELL));
+               flq->inc_idx &= 7;
+       }
+}
+
+/* Write a 0 cidx increment value to enable SGE interrupts for this queue */
+static void
+csio_wr_sge_intr_enable(struct csio_hw *hw, uint16_t iqid)
+{
+       csio_wr_reg32(hw, CIDXINC(0)            |
+                         INGRESSQID(iqid)      |
+                         TIMERREG(X_TIMERREG_RESTART_COUNTER),
+                         MYPF_REG(SGE_PF_GTS));
+}
+
+/*
+ * csio_wr_fill_fl - Populate the FL buffers of a FL queue.
+ * @hw: HW module.
+ * @flq: Freelist queue.
+ *
+ * Fill up freelist buffer entries with buffers of size specified
+ * in the size register.
+ *
+ */
+static int
+csio_wr_fill_fl(struct csio_hw *hw, struct csio_q *flq)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_sge *sge = &wrm->sge;
+       __be64 *d = (__be64 *)(flq->vstart);
+       struct csio_dma_buf *buf = &flq->un.fl.bufs[0];
+       uint64_t paddr;
+       int sreg = flq->un.fl.sreg;
+       int n = flq->credits;
+
+       while (n--) {
+               buf->len = sge->sge_fl_buf_size[sreg];
+               buf->vaddr = pci_alloc_consistent(hw->pdev, buf->len,
+                                                 &buf->paddr);
+               if (!buf->vaddr) {
+                       csio_err(hw, "Could only fill %d buffers!\n", n + 1);
+                       return -ENOMEM;
+               }
+
+               paddr = buf->paddr | (sreg & 0xF);
+
+               *d++ = cpu_to_be64(paddr);
+               buf++;
+       }
+
+       return 0;
+}
+
+/*
+ * csio_wr_update_fl -
+ * @hw: HW module.
+ * @flq: Freelist queue.
+ *
+ *
+ */
+static inline void
+csio_wr_update_fl(struct csio_hw *hw, struct csio_q *flq, uint16_t n)
+{
+
+       flq->inc_idx += n;
+       flq->pidx += n;
+       if (unlikely(flq->pidx >= flq->credits))
+               flq->pidx -= (uint16_t)flq->credits;
+
+       CSIO_INC_STATS(flq, n_flq_refill);
+}
+
+/*
+ * csio_wr_alloc_q - Allocate a WR queue and initialize it.
+ * @hw: HW module
+ * @qsize: Size of the queue in bytes
+ * @wrsize: Since of WR in this queue, if fixed.
+ * @type: Type of queue (Ingress/Egress/Freelist)
+ * @owner: Module that owns this queue.
+ * @nflb: Number of freelist buffers for FL.
+ * @sreg: What is the FL buffer size register?
+ * @iq_int_handler: Ingress queue handler in INTx mode.
+ *
+ * This function allocates and sets up a queue for the caller
+ * of size qsize, aligned at the required boundary. This is subject to
+ * be free entries being available in the queue array. If one is found,
+ * it is initialized with the allocated queue, marked as being used (owner),
+ * and a handle returned to the caller in form of the queue's index
+ * into the q_arr array.
+ * If user has indicated a freelist (by specifying nflb > 0), create
+ * another queue (with its own index into q_arr) for the freelist. Allocate
+ * memory for DMA buffer metadata (vaddr, len etc). Save off the freelist
+ * idx in the ingress queue's flq.idx. This is how a Freelist is associated
+ * with its owning ingress queue.
+ */
+int
+csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
+               uint16_t type, void *owner, uint32_t nflb, int sreg,
+               iq_handler_t iq_intx_handler)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_q   *q, *flq;
+       int             free_idx = wrm->free_qidx;
+       int             ret_idx = free_idx;
+       uint32_t        qsz;
+       int flq_idx;
+
+       if (free_idx >= wrm->num_q) {
+               csio_err(hw, "No more free queues.\n");
+               return -1;
+       }
+
+       switch (type) {
+       case CSIO_EGRESS:
+               qsz = ALIGN(qsize, CSIO_QCREDIT_SZ) + csio_wr_qstat_pgsz(hw);
+               break;
+       case CSIO_INGRESS:
+               switch (wrsize) {
+               case 16:
+               case 32:
+               case 64:
+               case 128:
+                       break;
+               default:
+                       csio_err(hw, "Invalid Ingress queue WR size:%d\n",
+                                   wrsize);
+                       return -1;
+               }
+
+               /*
+                * Number of elements must be a multiple of 16
+                * So this includes status page size
+                */
+               qsz = ALIGN(qsize/wrsize, 16) * wrsize;
+
+               break;
+       case CSIO_FREELIST:
+               qsz = ALIGN(qsize/wrsize, 8) * wrsize + csio_wr_qstat_pgsz(hw);
+               break;
+       default:
+               csio_err(hw, "Invalid queue type: 0x%x\n", type);
+               return -1;
+       }
+
+       q = wrm->q_arr[free_idx];
+
+       q->vstart = pci_alloc_consistent(hw->pdev, qsz, &q->pstart);
+       if (!q->vstart) {
+               csio_err(hw,
+                        "Failed to allocate DMA memory for "
+                        "queue at id: %d size: %d\n", free_idx, qsize);
+               return -1;
+       }
+
+       /*
+        * We need to zero out the contents, importantly for ingress,
+        * since we start with a generatiom bit of 1 for ingress.
+        */
+       memset(q->vstart, 0, qsz);
+
+       q->type         = type;
+       q->owner        = owner;
+       q->pidx         = q->cidx = q->inc_idx = 0;
+       q->size         = qsz;
+       q->wr_sz        = wrsize;       /* If using fixed size WRs */
+
+       wrm->free_qidx++;
+
+       if (type == CSIO_INGRESS) {
+               /* Since queue area is set to zero */
+               q->un.iq.genbit = 1;
+
+               /*
+                * Ingress queue status page size is always the size of
+                * the ingress queue entry.
+                */
+               q->credits      = (qsz - q->wr_sz) / q->wr_sz;
+               q->vwrap        = (void *)((uintptr_t)(q->vstart) + qsz
+                                                       - q->wr_sz);
+
+               /* Allocate memory for FL if requested */
+               if (nflb > 0) {
+                       flq_idx = csio_wr_alloc_q(hw, nflb * sizeof(__be64),
+                                                 sizeof(__be64), CSIO_FREELIST,
+                                                 owner, 0, sreg, NULL);
+                       if (flq_idx == -1) {
+                               csio_err(hw,
+                                        "Failed to allocate FL queue"
+                                        " for IQ idx:%d\n", free_idx);
+                               return -1;
+                       }
+
+                       /* Associate the new FL with the Ingress quue */
+                       q->un.iq.flq_idx = flq_idx;
+
+                       flq = wrm->q_arr[q->un.iq.flq_idx];
+                       flq->un.fl.bufs = kzalloc(flq->credits *
+                                                 sizeof(struct csio_dma_buf),
+                                                 GFP_KERNEL);
+                       if (!flq->un.fl.bufs) {
+                               csio_err(hw,
+                                        "Failed to allocate FL queue bufs"
+                                        " for IQ idx:%d\n", free_idx);
+                               return -1;
+                       }
+
+                       flq->un.fl.packen = 0;
+                       flq->un.fl.offset = 0;
+                       flq->un.fl.sreg = sreg;
+
+                       /* Fill up the free list buffers */
+                       if (csio_wr_fill_fl(hw, flq))
+                               return -1;
+
+                       /*
+                        * Make sure in a FLQ, atleast 1 credit (8 FL buffers)
+                        * remains unpopulated,otherwise HW thinks
+                        * FLQ is empty.
+                        */
+                       flq->pidx = flq->inc_idx = flq->credits - 8;
+               } else {
+                       q->un.iq.flq_idx = -1;
+               }
+
+               /* Associate the IQ INTx handler. */
+               q->un.iq.iq_intx_handler = iq_intx_handler;
+
+               csio_q_iqid(hw, ret_idx) = CSIO_MAX_QID;
+
+       } else if (type == CSIO_EGRESS) {
+               q->credits = (qsz - csio_wr_qstat_pgsz(hw)) / CSIO_QCREDIT_SZ;
+               q->vwrap   = (void *)((uintptr_t)(q->vstart) + qsz
+                                               - csio_wr_qstat_pgsz(hw));
+               csio_q_eqid(hw, ret_idx) = CSIO_MAX_QID;
+       } else { /* Freelist */
+               q->credits = (qsz - csio_wr_qstat_pgsz(hw)) / sizeof(__be64);
+               q->vwrap   = (void *)((uintptr_t)(q->vstart) + qsz
+                                               - csio_wr_qstat_pgsz(hw));
+               csio_q_flid(hw, ret_idx) = CSIO_MAX_QID;
+       }
+
+       return ret_idx;
+}
+
+/*
+ * csio_wr_iq_create_rsp - Response handler for IQ creation.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @iq_idx: Ingress queue that got created.
+ *
+ * Handle FW_IQ_CMD mailbox completion. Save off the assigned IQ/FL ids.
+ */
+static int
+csio_wr_iq_create_rsp(struct csio_hw *hw, struct csio_mb *mbp, int iq_idx)
+{
+       struct csio_iq_params iqp;
+       enum fw_retval retval;
+       uint32_t iq_id;
+       int flq_idx;
+
+       memset(&iqp, 0, sizeof(struct csio_iq_params));
+
+       csio_mb_iq_alloc_write_rsp(hw, mbp, &retval, &iqp);
+
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "IQ cmd returned 0x%x!\n", retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       csio_q_iqid(hw, iq_idx)         = iqp.iqid;
+       csio_q_physiqid(hw, iq_idx)     = iqp.physiqid;
+       csio_q_pidx(hw, iq_idx)         = csio_q_cidx(hw, iq_idx) = 0;
+       csio_q_inc_idx(hw, iq_idx)      = 0;
+
+       /* Actual iq-id. */
+       iq_id = iqp.iqid - hw->wrm.fw_iq_start;
+
+       /* Set the iq-id to iq map table. */
+       if (iq_id >= CSIO_MAX_IQ) {
+               csio_err(hw,
+                        "Exceeding MAX_IQ(%d) supported!"
+                        " iqid:%d rel_iqid:%d FW iq_start:%d\n",
+                        CSIO_MAX_IQ, iq_id, iqp.iqid, hw->wrm.fw_iq_start);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+       csio_q_set_intr_map(hw, iq_idx, iq_id);
+
+       /*
+        * During FW_IQ_CMD, FW sets interrupt_sent bit to 1 in the SGE
+        * ingress context of this queue. This will block interrupts to
+        * this queue until the next GTS write. Therefore, we do a
+        * 0-cidx increment GTS write for this queue just to clear the
+        * interrupt_sent bit. This will re-enable interrupts to this
+        * queue.
+        */
+       csio_wr_sge_intr_enable(hw, iqp.physiqid);
+
+       flq_idx = csio_q_iq_flq_idx(hw, iq_idx);
+       if (flq_idx != -1) {
+               struct csio_q *flq = hw->wrm.q_arr[flq_idx];
+
+               csio_q_flid(hw, flq_idx) = iqp.fl0id;
+               csio_q_cidx(hw, flq_idx) = 0;
+               csio_q_pidx(hw, flq_idx)    = csio_q_credits(hw, flq_idx) - 8;
+               csio_q_inc_idx(hw, flq_idx) = csio_q_credits(hw, flq_idx) - 8;
+
+               /* Now update SGE about the buffers allocated during init */
+               csio_wr_ring_fldb(hw, flq);
+       }
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+/*
+ * csio_wr_iq_create - Configure an Ingress queue with FW.
+ * @hw: The HW module.
+ * @priv: Private data object.
+ * @iq_idx: Ingress queue index in the WR module.
+ * @vec: MSIX vector.
+ * @portid: PCIE Channel to be associated with this queue.
+ * @async: Is this a FW asynchronous message handling queue?
+ * @cbfn: Completion callback.
+ *
+ * This API configures an ingress queue with FW by issuing a FW_IQ_CMD mailbox
+ * with alloc/write bits set.
+ */
+int
+csio_wr_iq_create(struct csio_hw *hw, void *priv, int iq_idx,
+                 uint32_t vec, uint8_t portid, bool async,
+                 void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct csio_mb  *mbp;
+       struct csio_iq_params iqp;
+       int flq_idx;
+
+       memset(&iqp, 0, sizeof(struct csio_iq_params));
+       csio_q_portid(hw, iq_idx) = portid;
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               csio_err(hw, "IQ command out of memory!\n");
+               return -ENOMEM;
+       }
+
+       switch (hw->intr_mode) {
+       case CSIO_IM_INTX:
+       case CSIO_IM_MSI:
+               /* For interrupt forwarding queue only */
+               if (hw->intr_iq_idx == iq_idx)
+                       iqp.iqandst     = X_INTERRUPTDESTINATION_PCIE;
+               else
+                       iqp.iqandst     = X_INTERRUPTDESTINATION_IQ;
+               iqp.iqandstindex        =
+                       csio_q_physiqid(hw, hw->intr_iq_idx);
+               break;
+       case CSIO_IM_MSIX:
+               iqp.iqandst             = X_INTERRUPTDESTINATION_PCIE;
+               iqp.iqandstindex        = (uint16_t)vec;
+               break;
+       case CSIO_IM_NONE:
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       /* Pass in the ingress queue cmd parameters */
+       iqp.pfn                 = hw->pfn;
+       iqp.vfn                 = 0;
+       iqp.iq_start            = 1;
+       iqp.viid                = 0;
+       iqp.type                = FW_IQ_TYPE_FL_INT_CAP;
+       iqp.iqasynch            = async;
+       if (csio_intr_coalesce_cnt)
+               iqp.iqanus      = X_UPDATESCHEDULING_COUNTER_OPTTIMER;
+       else
+               iqp.iqanus      = X_UPDATESCHEDULING_TIMER;
+       iqp.iqanud              = X_UPDATEDELIVERY_INTERRUPT;
+       iqp.iqpciech            = portid;
+       iqp.iqintcntthresh      = (uint8_t)csio_sge_thresh_reg;
+
+       switch (csio_q_wr_sz(hw, iq_idx)) {
+       case 16:
+               iqp.iqesize = 0; break;
+       case 32:
+               iqp.iqesize = 1; break;
+       case 64:
+               iqp.iqesize = 2; break;
+       case 128:
+               iqp.iqesize = 3; break;
+       }
+
+       iqp.iqsize              = csio_q_size(hw, iq_idx) /
+                                               csio_q_wr_sz(hw, iq_idx);
+       iqp.iqaddr              = csio_q_pstart(hw, iq_idx);
+
+       flq_idx = csio_q_iq_flq_idx(hw, iq_idx);
+       if (flq_idx != -1) {
+               struct csio_q *flq = hw->wrm.q_arr[flq_idx];
+
+               iqp.fl0paden    = 1;
+               iqp.fl0packen   = flq->un.fl.packen ? 1 : 0;
+               iqp.fl0fbmin    = X_FETCHBURSTMIN_64B;
+               iqp.fl0fbmax    = X_FETCHBURSTMAX_512B;
+               iqp.fl0size     = csio_q_size(hw, flq_idx) / CSIO_QCREDIT_SZ;
+               iqp.fl0addr     = csio_q_pstart(hw, flq_idx);
+       }
+
+       csio_mb_iq_alloc_write(hw, mbp, priv, CSIO_MB_DEFAULT_TMO, &iqp, cbfn);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of IQ cmd failed!\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       if (cbfn != NULL)
+               return 0;
+
+       return csio_wr_iq_create_rsp(hw, mbp, iq_idx);
+}
+
+/*
+ * csio_wr_eq_create_rsp - Response handler for EQ creation.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @eq_idx: Egress queue that got created.
+ *
+ * Handle FW_EQ_OFLD_CMD mailbox completion. Save off the assigned EQ ids.
+ */
+static int
+csio_wr_eq_cfg_rsp(struct csio_hw *hw, struct csio_mb *mbp, int eq_idx)
+{
+       struct csio_eq_params eqp;
+       enum fw_retval retval;
+
+       memset(&eqp, 0, sizeof(struct csio_eq_params));
+
+       csio_mb_eq_ofld_alloc_write_rsp(hw, mbp, &retval, &eqp);
+
+       if (retval != FW_SUCCESS) {
+               csio_err(hw, "EQ OFLD cmd returned 0x%x!\n", retval);
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       csio_q_eqid(hw, eq_idx) = (uint16_t)eqp.eqid;
+       csio_q_physeqid(hw, eq_idx) = (uint16_t)eqp.physeqid;
+       csio_q_pidx(hw, eq_idx) = csio_q_cidx(hw, eq_idx) = 0;
+       csio_q_inc_idx(hw, eq_idx) = 0;
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return 0;
+}
+
+/*
+ * csio_wr_eq_create - Configure an Egress queue with FW.
+ * @hw: HW module.
+ * @priv: Private data.
+ * @eq_idx: Egress queue index in the WR module.
+ * @iq_idx: Associated ingress queue index.
+ * @cbfn: Completion callback.
+ *
+ * This API configures a offload egress queue with FW by issuing a
+ * FW_EQ_OFLD_CMD  (with alloc + write ) mailbox.
+ */
+int
+csio_wr_eq_create(struct csio_hw *hw, void *priv, int eq_idx,
+                 int iq_idx, uint8_t portid,
+                 void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       struct csio_mb  *mbp;
+       struct csio_eq_params eqp;
+
+       memset(&eqp, 0, sizeof(struct csio_eq_params));
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp) {
+               csio_err(hw, "EQ command out of memory!\n");
+               return -ENOMEM;
+       }
+
+       eqp.pfn                 = hw->pfn;
+       eqp.vfn                 = 0;
+       eqp.eqstart             = 1;
+       eqp.hostfcmode          = X_HOSTFCMODE_STATUS_PAGE;
+       eqp.iqid                = csio_q_iqid(hw, iq_idx);
+       eqp.fbmin               = X_FETCHBURSTMIN_64B;
+       eqp.fbmax               = X_FETCHBURSTMAX_512B;
+       eqp.cidxfthresh         = 0;
+       eqp.pciechn             = portid;
+       eqp.eqsize              = csio_q_size(hw, eq_idx) / CSIO_QCREDIT_SZ;
+       eqp.eqaddr              = csio_q_pstart(hw, eq_idx);
+
+       csio_mb_eq_ofld_alloc_write(hw, mbp, priv, CSIO_MB_DEFAULT_TMO,
+                                   &eqp, cbfn);
+
+       if (csio_mb_issue(hw, mbp)) {
+               csio_err(hw, "Issue of EQ OFLD cmd failed!\n");
+               mempool_free(mbp, hw->mb_mempool);
+               return -EINVAL;
+       }
+
+       if (cbfn != NULL)
+               return 0;
+
+       return csio_wr_eq_cfg_rsp(hw, mbp, eq_idx);
+}
+
+/*
+ * csio_wr_iq_destroy_rsp - Response handler for IQ removal.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @iq_idx: Ingress queue that was freed.
+ *
+ * Handle FW_IQ_CMD (free) mailbox completion.
+ */
+static int
+csio_wr_iq_destroy_rsp(struct csio_hw *hw, struct csio_mb *mbp, int iq_idx)
+{
+       enum fw_retval retval = csio_mb_fw_retval(mbp);
+       int rv = 0;
+
+       if (retval != FW_SUCCESS)
+               rv = -EINVAL;
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return rv;
+}
+
+/*
+ * csio_wr_iq_destroy - Free an ingress queue.
+ * @hw: The HW module.
+ * @priv: Private data object.
+ * @iq_idx: Ingress queue index to destroy
+ * @cbfn: Completion callback.
+ *
+ * This API frees an ingress queue by issuing the FW_IQ_CMD
+ * with the free bit set.
+ */
+static int
+csio_wr_iq_destroy(struct csio_hw *hw, void *priv, int iq_idx,
+                  void (*cbfn)(struct csio_hw *, struct csio_mb *))
+{
+       int rv = 0;
+       struct csio_mb  *mbp;
+       struct csio_iq_params iqp;
+       int flq_idx;
+
+       memset(&iqp, 0, sizeof(struct csio_iq_params));
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp)
+               return -ENOMEM;
+
+       iqp.pfn         = hw->pfn;
+       iqp.vfn         = 0;
+       iqp.iqid        = csio_q_iqid(hw, iq_idx);
+       iqp.type        = FW_IQ_TYPE_FL_INT_CAP;
+
+       flq_idx = csio_q_iq_flq_idx(hw, iq_idx);
+       if (flq_idx != -1)
+               iqp.fl0id = csio_q_flid(hw, flq_idx);
+       else
+               iqp.fl0id = 0xFFFF;
+
+       iqp.fl1id = 0xFFFF;
+
+       csio_mb_iq_free(hw, mbp, priv, CSIO_MB_DEFAULT_TMO, &iqp, cbfn);
+
+       rv = csio_mb_issue(hw, mbp);
+       if (rv != 0) {
+               mempool_free(mbp, hw->mb_mempool);
+               return rv;
+       }
+
+       if (cbfn != NULL)
+               return 0;
+
+       return csio_wr_iq_destroy_rsp(hw, mbp, iq_idx);
+}
+
+/*
+ * csio_wr_eq_destroy_rsp - Response handler for OFLD EQ creation.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @eq_idx: Egress queue that was freed.
+ *
+ * Handle FW_OFLD_EQ_CMD (free) mailbox completion.
+ */
+static int
+csio_wr_eq_destroy_rsp(struct csio_hw *hw, struct csio_mb *mbp, int eq_idx)
+{
+       enum fw_retval retval = csio_mb_fw_retval(mbp);
+       int rv = 0;
+
+       if (retval != FW_SUCCESS)
+               rv = -EINVAL;
+
+       mempool_free(mbp, hw->mb_mempool);
+
+       return rv;
+}
+
+/*
+ * csio_wr_eq_destroy - Free an Egress queue.
+ * @hw: The HW module.
+ * @priv: Private data object.
+ * @eq_idx: Egress queue index to destroy
+ * @cbfn: Completion callback.
+ *
+ * This API frees an Egress queue by issuing the FW_EQ_OFLD_CMD
+ * with the free bit set.
+ */
+static int
+csio_wr_eq_destroy(struct csio_hw *hw, void *priv, int eq_idx,
+                  void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+       int rv = 0;
+       struct csio_mb  *mbp;
+       struct csio_eq_params eqp;
+
+       memset(&eqp, 0, sizeof(struct csio_eq_params));
+
+       mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+       if (!mbp)
+               return -ENOMEM;
+
+       eqp.pfn         = hw->pfn;
+       eqp.vfn         = 0;
+       eqp.eqid        = csio_q_eqid(hw, eq_idx);
+
+       csio_mb_eq_ofld_free(hw, mbp, priv, CSIO_MB_DEFAULT_TMO, &eqp, cbfn);
+
+       rv = csio_mb_issue(hw, mbp);
+       if (rv != 0) {
+               mempool_free(mbp, hw->mb_mempool);
+               return rv;
+       }
+
+       if (cbfn != NULL)
+               return 0;
+
+       return csio_wr_eq_destroy_rsp(hw, mbp, eq_idx);
+}
+
+/*
+ * csio_wr_cleanup_eq_stpg - Cleanup Egress queue status page
+ * @hw: HW module
+ * @qidx: Egress queue index
+ *
+ * Cleanup the Egress queue status page.
+ */
+static void
+csio_wr_cleanup_eq_stpg(struct csio_hw *hw, int qidx)
+{
+       struct csio_q   *q = csio_hw_to_wrm(hw)->q_arr[qidx];
+       struct csio_qstatus_page *stp = (struct csio_qstatus_page *)q->vwrap;
+
+       memset(stp, 0, sizeof(*stp));
+}
+
+/*
+ * csio_wr_cleanup_iq_ftr - Cleanup Footer entries in IQ
+ * @hw: HW module
+ * @qidx: Ingress queue index
+ *
+ * Cleanup the footer entries in the given ingress queue,
+ * set to 1 the internal copy of genbit.
+ */
+static void
+csio_wr_cleanup_iq_ftr(struct csio_hw *hw, int qidx)
+{
+       struct csio_wrm *wrm    = csio_hw_to_wrm(hw);
+       struct csio_q   *q      = wrm->q_arr[qidx];
+       void *wr;
+       struct csio_iqwr_footer *ftr;
+       uint32_t i = 0;
+
+       /* set to 1 since we are just about zero out genbit */
+       q->un.iq.genbit = 1;
+
+       for (i = 0; i < q->credits; i++) {
+               /* Get the WR */
+               wr = (void *)((uintptr_t)q->vstart +
+                                          (i * q->wr_sz));
+               /* Get the footer */
+               ftr = (struct csio_iqwr_footer *)((uintptr_t)wr +
+                                         (q->wr_sz - sizeof(*ftr)));
+               /* Zero out footer */
+               memset(ftr, 0, sizeof(*ftr));
+       }
+}
+
+int
+csio_wr_destroy_queues(struct csio_hw *hw, bool cmd)
+{
+       int i, flq_idx;
+       struct csio_q *q;
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       int rv;
+
+       for (i = 0; i < wrm->free_qidx; i++) {
+               q = wrm->q_arr[i];
+
+               switch (q->type) {
+               case CSIO_EGRESS:
+                       if (csio_q_eqid(hw, i) != CSIO_MAX_QID) {
+                               csio_wr_cleanup_eq_stpg(hw, i);
+                               if (!cmd) {
+                                       csio_q_eqid(hw, i) = CSIO_MAX_QID;
+                                       continue;
+                               }
+
+                               rv = csio_wr_eq_destroy(hw, NULL, i, NULL);
+                               if ((rv == -EBUSY) || (rv == -ETIMEDOUT))
+                                       cmd = false;
+
+                               csio_q_eqid(hw, i) = CSIO_MAX_QID;
+                       }
+               case CSIO_INGRESS:
+                       if (csio_q_iqid(hw, i) != CSIO_MAX_QID) {
+                               csio_wr_cleanup_iq_ftr(hw, i);
+                               if (!cmd) {
+                                       csio_q_iqid(hw, i) = CSIO_MAX_QID;
+                                       flq_idx = csio_q_iq_flq_idx(hw, i);
+                                       if (flq_idx != -1)
+                                               csio_q_flid(hw, flq_idx) =
+                                                               CSIO_MAX_QID;
+                                       continue;
+                               }
+
+                               rv = csio_wr_iq_destroy(hw, NULL, i, NULL);
+                               if ((rv == -EBUSY) || (rv == -ETIMEDOUT))
+                                       cmd = false;
+
+                               csio_q_iqid(hw, i) = CSIO_MAX_QID;
+                               flq_idx = csio_q_iq_flq_idx(hw, i);
+                               if (flq_idx != -1)
+                                       csio_q_flid(hw, flq_idx) = CSIO_MAX_QID;
+                       }
+               default:
+                       break;
+               }
+       }
+
+       hw->flags &= ~CSIO_HWF_Q_FW_ALLOCED;
+
+       return 0;
+}
+
+/*
+ * csio_wr_get - Get requested size of WR entry/entries from queue.
+ * @hw: HW module.
+ * @qidx: Index of queue.
+ * @size: Cumulative size of Work request(s).
+ * @wrp: Work request pair.
+ *
+ * If requested credits are available, return the start address of the
+ * work request in the work request pair. Set pidx accordingly and
+ * return.
+ *
+ * NOTE about WR pair:
+ * ==================
+ * A WR can start towards the end of a queue, and then continue at the
+ * beginning, since the queue is considered to be circular. This will
+ * require a pair of address/size to be passed back to the caller -
+ * hence Work request pair format.
+ */
+int
+csio_wr_get(struct csio_hw *hw, int qidx, uint32_t size,
+           struct csio_wr_pair *wrp)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_q *q = wrm->q_arr[qidx];
+       void *cwr = (void *)((uintptr_t)(q->vstart) +
+                                               (q->pidx * CSIO_QCREDIT_SZ));
+       struct csio_qstatus_page *stp = (struct csio_qstatus_page *)q->vwrap;
+       uint16_t cidx = q->cidx = ntohs(stp->cidx);
+       uint16_t pidx = q->pidx;
+       uint32_t req_sz = ALIGN(size, CSIO_QCREDIT_SZ);
+       int req_credits = req_sz / CSIO_QCREDIT_SZ;
+       int credits;
+
+       CSIO_DB_ASSERT(q->owner != NULL);
+       CSIO_DB_ASSERT((qidx >= 0) && (qidx < wrm->free_qidx));
+       CSIO_DB_ASSERT(cidx <= q->credits);
+
+       /* Calculate credits */
+       if (pidx > cidx) {
+               credits = q->credits - (pidx - cidx) - 1;
+       } else if (cidx > pidx) {
+               credits = cidx - pidx - 1;
+       } else {
+               /* cidx == pidx, empty queue */
+               credits = q->credits;
+               CSIO_INC_STATS(q, n_qempty);
+       }
+
+       /*
+        * Check if we have enough credits.
+        * credits = 1 implies queue is full.
+        */
+       if (!credits || (req_credits > credits)) {
+               CSIO_INC_STATS(q, n_qfull);
+               return -EBUSY;
+       }
+
+       /*
+        * If we are here, we have enough credits to satisfy the
+        * request. Check if we are near the end of q, and if WR spills over.
+        * If it does, use the first addr/size to cover the queue until
+        * the end. Fit the remainder portion of the request at the top
+        * of queue and return it in the second addr/len. Set pidx
+        * accordingly.
+        */
+       if (unlikely(((uintptr_t)cwr + req_sz) > (uintptr_t)(q->vwrap))) {
+               wrp->addr1 = cwr;
+               wrp->size1 = (uint32_t)((uintptr_t)q->vwrap - (uintptr_t)cwr);
+               wrp->addr2 = q->vstart;
+               wrp->size2 = req_sz - wrp->size1;
+               q->pidx = (uint16_t)(ALIGN(wrp->size2, CSIO_QCREDIT_SZ) /
+                                                       CSIO_QCREDIT_SZ);
+               CSIO_INC_STATS(q, n_qwrap);
+               CSIO_INC_STATS(q, n_eq_wr_split);
+       } else {
+               wrp->addr1 = cwr;
+               wrp->size1 = req_sz;
+               wrp->addr2 = NULL;
+               wrp->size2 = 0;
+               q->pidx += (uint16_t)req_credits;
+
+               /* We are the end of queue, roll back pidx to top of queue */
+               if (unlikely(q->pidx == q->credits)) {
+                       q->pidx = 0;
+                       CSIO_INC_STATS(q, n_qwrap);
+               }
+       }
+
+       q->inc_idx = (uint16_t)req_credits;
+
+       CSIO_INC_STATS(q, n_tot_reqs);
+
+       return 0;
+}
+
+/*
+ * csio_wr_copy_to_wrp - Copies given data into WR.
+ * @data_buf - Data buffer
+ * @wrp - Work request pair.
+ * @wr_off - Work request offset.
+ * @data_len - Data length.
+ *
+ * Copies the given data in Work Request. Work request pair(wrp) specifies
+ * address information of Work request.
+ * Returns: none
+ */
+void
+csio_wr_copy_to_wrp(void *data_buf, struct csio_wr_pair *wrp,
+                  uint32_t wr_off, uint32_t data_len)
+{
+       uint32_t nbytes;
+
+       /* Number of space available in buffer addr1 of WRP */
+       nbytes = ((wrp->size1 - wr_off) >= data_len) ?
+                                       data_len : (wrp->size1 - wr_off);
+
+       memcpy((uint8_t *) wrp->addr1 + wr_off, data_buf, nbytes);
+       data_len -= nbytes;
+
+       /* Write the remaining data from the begining of circular buffer */
+       if (data_len) {
+               CSIO_DB_ASSERT(data_len <= wrp->size2);
+               CSIO_DB_ASSERT(wrp->addr2 != NULL);
+               memcpy(wrp->addr2, (uint8_t *) data_buf + nbytes, data_len);
+       }
+}
+
+/*
+ * csio_wr_issue - Notify chip of Work request.
+ * @hw: HW module.
+ * @qidx: Index of queue.
+ * @prio: 0: Low priority, 1: High priority
+ *
+ * Rings the SGE Doorbell by writing the current producer index of the passed
+ * in queue into the register.
+ *
+ */
+int
+csio_wr_issue(struct csio_hw *hw, int qidx, bool prio)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_q *q = wrm->q_arr[qidx];
+
+       CSIO_DB_ASSERT((qidx >= 0) && (qidx < wrm->free_qidx));
+
+       wmb();
+       /* Ring SGE Doorbell writing q->pidx into it */
+       csio_wr_reg32(hw, DBPRIO(prio) | QID(q->un.eq.physeqid) |
+                     PIDX(q->inc_idx), MYPF_REG(SGE_PF_KDOORBELL));
+       q->inc_idx = 0;
+
+       return 0;
+}
+
+static inline uint32_t
+csio_wr_avail_qcredits(struct csio_q *q)
+{
+       if (q->pidx > q->cidx)
+               return q->pidx - q->cidx;
+       else if (q->cidx > q->pidx)
+               return q->credits - (q->cidx - q->pidx);
+       else
+               return 0;       /* cidx == pidx, empty queue */
+}
+
+/*
+ * csio_wr_inval_flq_buf - Invalidate a free list buffer entry.
+ * @hw: HW module.
+ * @flq: The freelist queue.
+ *
+ * Invalidate the driver's version of a freelist buffer entry,
+ * without freeing the associated the DMA memory. The entry
+ * to be invalidated is picked up from the current Free list
+ * queue cidx.
+ *
+ */
+static inline void
+csio_wr_inval_flq_buf(struct csio_hw *hw, struct csio_q *flq)
+{
+       flq->cidx++;
+       if (flq->cidx == flq->credits) {
+               flq->cidx = 0;
+               CSIO_INC_STATS(flq, n_qwrap);
+       }
+}
+
+/*
+ * csio_wr_process_fl - Process a freelist completion.
+ * @hw: HW module.
+ * @q: The ingress queue attached to the Freelist.
+ * @wr: The freelist completion WR in the ingress queue.
+ * @len_to_qid: The lower 32-bits of the first flit of the RSP footer
+ * @iq_handler: Caller's handler for this completion.
+ * @priv: Private pointer of caller
+ *
+ */
+static inline void
+csio_wr_process_fl(struct csio_hw *hw, struct csio_q *q,
+                  void *wr, uint32_t len_to_qid,
+                  void (*iq_handler)(struct csio_hw *, void *,
+                                     uint32_t, struct csio_fl_dma_buf *,
+                                     void *),
+                  void *priv)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_sge *sge = &wrm->sge;
+       struct csio_fl_dma_buf flb;
+       struct csio_dma_buf *buf, *fbuf;
+       uint32_t bufsz, len, lastlen = 0;
+       int n;
+       struct csio_q *flq = hw->wrm.q_arr[q->un.iq.flq_idx];
+
+       CSIO_DB_ASSERT(flq != NULL);
+
+       len = len_to_qid;
+
+       if (len & IQWRF_NEWBUF) {
+               if (flq->un.fl.offset > 0) {
+                       csio_wr_inval_flq_buf(hw, flq);
+                       flq->un.fl.offset = 0;
+               }
+               len = IQWRF_LEN_GET(len);
+       }
+
+       CSIO_DB_ASSERT(len != 0);
+
+       flb.totlen = len;
+
+       /* Consume all freelist buffers used for len bytes */
+       for (n = 0, fbuf = flb.flbufs; ; n++, fbuf++) {
+               buf = &flq->un.fl.bufs[flq->cidx];
+               bufsz = csio_wr_fl_bufsz(sge, buf);
+
+               fbuf->paddr     = buf->paddr;
+               fbuf->vaddr     = buf->vaddr;
+
+               flb.offset      = flq->un.fl.offset;
+               lastlen         = min(bufsz, len);
+               fbuf->len       = lastlen;
+
+               len -= lastlen;
+               if (!len)
+                       break;
+               csio_wr_inval_flq_buf(hw, flq);
+       }
+
+       flb.defer_free = flq->un.fl.packen ? 0 : 1;
+
+       iq_handler(hw, wr, q->wr_sz - sizeof(struct csio_iqwr_footer),
+                  &flb, priv);
+
+       if (flq->un.fl.packen)
+               flq->un.fl.offset += ALIGN(lastlen, sge->csio_fl_align);
+       else
+               csio_wr_inval_flq_buf(hw, flq);
+
+}
+
+/*
+ * csio_is_new_iqwr - Is this a new Ingress queue entry ?
+ * @q: Ingress quueue.
+ * @ftr: Ingress queue WR SGE footer.
+ *
+ * The entry is new if our generation bit matches the corresponding
+ * bit in the footer of the current WR.
+ */
+static inline bool
+csio_is_new_iqwr(struct csio_q *q, struct csio_iqwr_footer *ftr)
+{
+       return (q->un.iq.genbit == (ftr->u.type_gen >> IQWRF_GEN_SHIFT));
+}
+
+/*
+ * csio_wr_process_iq - Process elements in Ingress queue.
+ * @hw:  HW pointer
+ * @qidx: Index of queue
+ * @iq_handler: Handler for this queue
+ * @priv: Caller's private pointer
+ *
+ * This routine walks through every entry of the ingress queue, calling
+ * the provided iq_handler with the entry, until the generation bit
+ * flips.
+ */
+int
+csio_wr_process_iq(struct csio_hw *hw, struct csio_q *q,
+                  void (*iq_handler)(struct csio_hw *, void *,
+                                     uint32_t, struct csio_fl_dma_buf *,
+                                     void *),
+                  void *priv)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       void *wr = (void *)((uintptr_t)q->vstart + (q->cidx * q->wr_sz));
+       struct csio_iqwr_footer *ftr;
+       uint32_t wr_type, fw_qid, qid;
+       struct csio_q *q_completed;
+       struct csio_q *flq = csio_iq_has_fl(q) ?
+                                       wrm->q_arr[q->un.iq.flq_idx] : NULL;
+       int rv = 0;
+
+       /* Get the footer */
+       ftr = (struct csio_iqwr_footer *)((uintptr_t)wr +
+                                         (q->wr_sz - sizeof(*ftr)));
+
+       /*
+        * When q wrapped around last time, driver should have inverted
+        * ic.genbit as well.
+        */
+       while (csio_is_new_iqwr(q, ftr)) {
+
+               CSIO_DB_ASSERT(((uintptr_t)wr + q->wr_sz) <=
+                                               (uintptr_t)q->vwrap);
+               rmb();
+               wr_type = IQWRF_TYPE_GET(ftr->u.type_gen);
+
+               switch (wr_type) {
+               case X_RSPD_TYPE_CPL:
+                       /* Subtract footer from WR len */
+                       iq_handler(hw, wr, q->wr_sz - sizeof(*ftr), NULL, priv);
+                       break;
+               case X_RSPD_TYPE_FLBUF:
+                       csio_wr_process_fl(hw, q, wr,
+                                          ntohl(ftr->pldbuflen_qid),
+                                          iq_handler, priv);
+                       break;
+               case X_RSPD_TYPE_INTR:
+                       fw_qid = ntohl(ftr->pldbuflen_qid);
+                       qid = fw_qid - wrm->fw_iq_start;
+                       q_completed = hw->wrm.intr_map[qid];
+
+                       if (unlikely(qid ==
+                                       csio_q_physiqid(hw, hw->intr_iq_idx))) {
+                               /*
+                                * We are already in the Forward Interrupt
+                                * Interrupt Queue Service! Do-not service
+                                * again!
+                                *
+                                */
+                       } else {
+                               CSIO_DB_ASSERT(q_completed);
+                               CSIO_DB_ASSERT(
+                                       q_completed->un.iq.iq_intx_handler);
+
+                               /* Call the queue handler. */
+                               q_completed->un.iq.iq_intx_handler(hw, NULL,
+                                               0, NULL, (void *)q_completed);
+                       }
+                       break;
+               default:
+                       csio_warn(hw, "Unknown resp type 0x%x received\n",
+                                wr_type);
+                       CSIO_INC_STATS(q, n_rsp_unknown);
+                       break;
+               }
+
+               /*
+                * Ingress *always* has fixed size WR entries. Therefore,
+                * there should always be complete WRs towards the end of
+                * queue.
+                */
+               if (((uintptr_t)wr + q->wr_sz) == (uintptr_t)q->vwrap) {
+
+                       /* Roll over to start of queue */
+                       q->cidx = 0;
+                       wr      = q->vstart;
+
+                       /* Toggle genbit */
+                       q->un.iq.genbit ^= 0x1;
+
+                       CSIO_INC_STATS(q, n_qwrap);
+               } else {
+                       q->cidx++;
+                       wr      = (void *)((uintptr_t)(q->vstart) +
+                                          (q->cidx * q->wr_sz));
+               }
+
+               ftr = (struct csio_iqwr_footer *)((uintptr_t)wr +
+                                                 (q->wr_sz - sizeof(*ftr)));
+               q->inc_idx++;
+
+       } /* while (q->un.iq.genbit == hdr->genbit) */
+
+       /*
+        * We need to re-arm SGE interrupts in case we got a stray interrupt,
+        * especially in msix mode. With INTx, this may be a common occurence.
+        */
+       if (unlikely(!q->inc_idx)) {
+               CSIO_INC_STATS(q, n_stray_comp);
+               rv = -EINVAL;
+               goto restart;
+       }
+
+       /* Replenish free list buffers if pending falls below low water mark */
+       if (flq) {
+               uint32_t avail  = csio_wr_avail_qcredits(flq);
+               if (avail <= 16) {
+                       /* Make sure in FLQ, atleast 1 credit (8 FL buffers)
+                        * remains unpopulated otherwise HW thinks
+                        * FLQ is empty.
+                        */
+                       csio_wr_update_fl(hw, flq, (flq->credits - 8) - avail);
+                       csio_wr_ring_fldb(hw, flq);
+               }
+       }
+
+restart:
+       /* Now inform SGE about our incremental index value */
+       csio_wr_reg32(hw, CIDXINC(q->inc_idx)           |
+                         INGRESSQID(q->un.iq.physiqid) |
+                         TIMERREG(csio_sge_timer_reg),
+                         MYPF_REG(SGE_PF_GTS));
+       q->stats.n_tot_rsps += q->inc_idx;
+
+       q->inc_idx = 0;
+
+       return rv;
+}
+
+int
+csio_wr_process_iq_idx(struct csio_hw *hw, int qidx,
+                  void (*iq_handler)(struct csio_hw *, void *,
+                                     uint32_t, struct csio_fl_dma_buf *,
+                                     void *),
+                  void *priv)
+{
+       struct csio_wrm *wrm    = csio_hw_to_wrm(hw);
+       struct csio_q   *iq     = wrm->q_arr[qidx];
+
+       return csio_wr_process_iq(hw, iq, iq_handler, priv);
+}
+
+static int
+csio_closest_timer(struct csio_sge *s, int time)
+{
+       int i, delta, match = 0, min_delta = INT_MAX;
+
+       for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) {
+               delta = time - s->timer_val[i];
+               if (delta < 0)
+                       delta = -delta;
+               if (delta < min_delta) {
+                       min_delta = delta;
+                       match = i;
+               }
+       }
+       return match;
+}
+
+static int
+csio_closest_thresh(struct csio_sge *s, int cnt)
+{
+       int i, delta, match = 0, min_delta = INT_MAX;
+
+       for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) {
+               delta = cnt - s->counter_val[i];
+               if (delta < 0)
+                       delta = -delta;
+               if (delta < min_delta) {
+                       min_delta = delta;
+                       match = i;
+               }
+       }
+       return match;
+}
+
+static void
+csio_wr_fixup_host_params(struct csio_hw *hw)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_sge *sge = &wrm->sge;
+       uint32_t clsz = L1_CACHE_BYTES;
+       uint32_t s_hps = PAGE_SHIFT - 10;
+       uint32_t ingpad = 0;
+       uint32_t stat_len = clsz > 64 ? 128 : 64;
+
+       csio_wr_reg32(hw, HOSTPAGESIZEPF0(s_hps) | HOSTPAGESIZEPF1(s_hps) |
+                     HOSTPAGESIZEPF2(s_hps) | HOSTPAGESIZEPF3(s_hps) |
+                     HOSTPAGESIZEPF4(s_hps) | HOSTPAGESIZEPF5(s_hps) |
+                     HOSTPAGESIZEPF6(s_hps) | HOSTPAGESIZEPF7(s_hps),
+                     SGE_HOST_PAGE_SIZE);
+
+       sge->csio_fl_align = clsz < 32 ? 32 : clsz;
+       ingpad = ilog2(sge->csio_fl_align) - 5;
+
+       csio_set_reg_field(hw, SGE_CONTROL, INGPADBOUNDARY_MASK |
+                                           EGRSTATUSPAGESIZE(1),
+                          INGPADBOUNDARY(ingpad) |
+                          EGRSTATUSPAGESIZE(stat_len != 64));
+
+       /* FL BUFFER SIZE#0 is Page size i,e already aligned to cache line */
+       csio_wr_reg32(hw, PAGE_SIZE, SGE_FL_BUFFER_SIZE0);
+       csio_wr_reg32(hw,
+                     (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE2) +
+                     sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+                     SGE_FL_BUFFER_SIZE2);
+       csio_wr_reg32(hw,
+                     (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE3) +
+                     sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+                     SGE_FL_BUFFER_SIZE3);
+
+       csio_wr_reg32(hw, HPZ0(PAGE_SHIFT - 12), ULP_RX_TDDP_PSZ);
+
+       /* default value of rx_dma_offset of the NIC driver */
+       csio_set_reg_field(hw, SGE_CONTROL, PKTSHIFT_MASK,
+                          PKTSHIFT(CSIO_SGE_RX_DMA_OFFSET));
+}
+
+static void
+csio_init_intr_coalesce_parms(struct csio_hw *hw)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_sge *sge = &wrm->sge;
+
+       csio_sge_thresh_reg = csio_closest_thresh(sge, csio_intr_coalesce_cnt);
+       if (csio_intr_coalesce_cnt) {
+               csio_sge_thresh_reg = 0;
+               csio_sge_timer_reg = X_TIMERREG_RESTART_COUNTER;
+               return;
+       }
+
+       csio_sge_timer_reg = csio_closest_timer(sge, csio_intr_coalesce_time);
+}
+
+/*
+ * csio_wr_get_sge - Get SGE register values.
+ * @hw: HW module.
+ *
+ * Used by non-master functions and by master-functions relying on config file.
+ */
+static void
+csio_wr_get_sge(struct csio_hw *hw)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_sge *sge = &wrm->sge;
+       uint32_t ingpad;
+       int i;
+       u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5;
+       u32 ingress_rx_threshold;
+
+       sge->sge_control = csio_rd_reg32(hw, SGE_CONTROL);
+
+       ingpad = INGPADBOUNDARY_GET(sge->sge_control);
+
+       switch (ingpad) {
+       case X_INGPCIEBOUNDARY_32B:
+               sge->csio_fl_align = 32; break;
+       case X_INGPCIEBOUNDARY_64B:
+               sge->csio_fl_align = 64; break;
+       case X_INGPCIEBOUNDARY_128B:
+               sge->csio_fl_align = 128; break;
+       case X_INGPCIEBOUNDARY_256B:
+               sge->csio_fl_align = 256; break;
+       case X_INGPCIEBOUNDARY_512B:
+               sge->csio_fl_align = 512; break;
+       case X_INGPCIEBOUNDARY_1024B:
+               sge->csio_fl_align = 1024; break;
+       case X_INGPCIEBOUNDARY_2048B:
+               sge->csio_fl_align = 2048; break;
+       case X_INGPCIEBOUNDARY_4096B:
+               sge->csio_fl_align = 4096; break;
+       }
+
+       for (i = 0; i < CSIO_SGE_FL_SIZE_REGS; i++)
+               csio_get_flbuf_size(hw, sge, i);
+
+       timer_value_0_and_1 = csio_rd_reg32(hw, SGE_TIMER_VALUE_0_AND_1);
+       timer_value_2_and_3 = csio_rd_reg32(hw, SGE_TIMER_VALUE_2_AND_3);
+       timer_value_4_and_5 = csio_rd_reg32(hw, SGE_TIMER_VALUE_4_AND_5);
+
+       sge->timer_val[0] = (uint16_t)csio_core_ticks_to_us(hw,
+                                       TIMERVALUE0_GET(timer_value_0_and_1));
+       sge->timer_val[1] = (uint16_t)csio_core_ticks_to_us(hw,
+                                       TIMERVALUE1_GET(timer_value_0_and_1));
+       sge->timer_val[2] = (uint16_t)csio_core_ticks_to_us(hw,
+                                       TIMERVALUE2_GET(timer_value_2_and_3));
+       sge->timer_val[3] = (uint16_t)csio_core_ticks_to_us(hw,
+                                       TIMERVALUE3_GET(timer_value_2_and_3));
+       sge->timer_val[4] = (uint16_t)csio_core_ticks_to_us(hw,
+                                       TIMERVALUE4_GET(timer_value_4_and_5));
+       sge->timer_val[5] = (uint16_t)csio_core_ticks_to_us(hw,
+                                       TIMERVALUE5_GET(timer_value_4_and_5));
+
+       ingress_rx_threshold = csio_rd_reg32(hw, SGE_INGRESS_RX_THRESHOLD);
+       sge->counter_val[0] = THRESHOLD_0_GET(ingress_rx_threshold);
+       sge->counter_val[1] = THRESHOLD_1_GET(ingress_rx_threshold);
+       sge->counter_val[2] = THRESHOLD_2_GET(ingress_rx_threshold);
+       sge->counter_val[3] = THRESHOLD_3_GET(ingress_rx_threshold);
+
+       csio_init_intr_coalesce_parms(hw);
+}
+
+/*
+ * csio_wr_set_sge - Initialize SGE registers
+ * @hw: HW module.
+ *
+ * Used by Master function to initialize SGE registers in the absence
+ * of a config file.
+ */
+static void
+csio_wr_set_sge(struct csio_hw *hw)
+{
+       struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+       struct csio_sge *sge = &wrm->sge;
+       int i;
+
+       /*
+        * Set up our basic SGE mode to deliver CPL messages to our Ingress
+        * Queue and Packet Date to the Free List.
+        */
+       csio_set_reg_field(hw, SGE_CONTROL, RXPKTCPLMODE(1), RXPKTCPLMODE(1));
+
+       sge->sge_control = csio_rd_reg32(hw, SGE_CONTROL);
+
+       /* sge->csio_fl_align is set up by csio_wr_fixup_host_params(). */
+
+       /*
+        * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
+        * and generate an interrupt when this occurs so we can recover.
+        */
+       csio_set_reg_field(hw, SGE_DBFIFO_STATUS,
+                          HP_INT_THRESH(HP_INT_THRESH_MASK) |
+                          LP_INT_THRESH(LP_INT_THRESH_MASK),
+                          HP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH) |
+                          LP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH));
+       csio_set_reg_field(hw, SGE_DOORBELL_CONTROL, ENABLE_DROP,
+                          ENABLE_DROP);
+
+       /* SGE_FL_BUFFER_SIZE0 is set up by csio_wr_fixup_host_params(). */
+
+       CSIO_SET_FLBUF_SIZE(hw, 1, CSIO_SGE_FLBUF_SIZE1);
+       CSIO_SET_FLBUF_SIZE(hw, 2, CSIO_SGE_FLBUF_SIZE2);
+       CSIO_SET_FLBUF_SIZE(hw, 3, CSIO_SGE_FLBUF_SIZE3);
+       CSIO_SET_FLBUF_SIZE(hw, 4, CSIO_SGE_FLBUF_SIZE4);
+       CSIO_SET_FLBUF_SIZE(hw, 5, CSIO_SGE_FLBUF_SIZE5);
+       CSIO_SET_FLBUF_SIZE(hw, 6, CSIO_SGE_FLBUF_SIZE6);
+       CSIO_SET_FLBUF_SIZE(hw, 7, CSIO_SGE_FLBUF_SIZE7);
+       CSIO_SET_FLBUF_SIZE(hw, 8, CSIO_SGE_FLBUF_SIZE8);
+
+       for (i = 0; i < CSIO_SGE_FL_SIZE_REGS; i++)
+               csio_get_flbuf_size(hw, sge, i);
+
+       /* Initialize interrupt coalescing attributes */
+       sge->timer_val[0] = CSIO_SGE_TIMER_VAL_0;
+       sge->timer_val[1] = CSIO_SGE_TIMER_VAL_1;
+       sge->timer_val[2] = CSIO_SGE_TIMER_VAL_2;
+       sge->timer_val[3] = CSIO_SGE_TIMER_VAL_3;
+       sge->timer_val[4] = CSIO_SGE_TIMER_VAL_4;
+       sge->timer_val[5] = CSIO_SGE_TIMER_VAL_5;
+
+       sge->counter_val[0] = CSIO_SGE_INT_CNT_VAL_0;
+       sge->counter_val[1] = CSIO_SGE_INT_CNT_VAL_1;
+       sge->counter_val[2] = CSIO_SGE_INT_CNT_VAL_2;
+       sge->counter_val[3] = CSIO_SGE_INT_CNT_VAL_3;
+
+       csio_wr_reg32(hw, THRESHOLD_0(sge->counter_val[0]) |
+                     THRESHOLD_1(sge->counter_val[1]) |
+                     THRESHOLD_2(sge->counter_val[2]) |
+                     THRESHOLD_3(sge->counter_val[3]),
+                     SGE_INGRESS_RX_THRESHOLD);
+
+       csio_wr_reg32(hw,
+                  TIMERVALUE0(csio_us_to_core_ticks(hw, sge->timer_val[0])) |
+                  TIMERVALUE1(csio_us_to_core_ticks(hw, sge->timer_val[1])),
+                  SGE_TIMER_VALUE_0_AND_1);
+
+       csio_wr_reg32(hw,
+                  TIMERVALUE2(csio_us_to_core_ticks(hw, sge->timer_val[2])) |
+                  TIMERVALUE3(csio_us_to_core_ticks(hw, sge->timer_val[3])),
+                  SGE_TIMER_VALUE_2_AND_3);
+
+       csio_wr_reg32(hw,
+                  TIMERVALUE4(csio_us_to_core_ticks(hw, sge->timer_val[4])) |
+                  TIMERVALUE5(csio_us_to_core_ticks(hw, sge->timer_val[5])),
+                  SGE_TIMER_VALUE_4_AND_5);
+
+       csio_init_intr_coalesce_parms(hw);
+}
+
+void
+csio_wr_sge_init(struct csio_hw *hw)
+{
+       /*
+        * If we are master:
+        *    - If we plan to use the config file, we need to fixup some
+        *      host specific registers, and read the rest of the SGE
+        *      configuration.
+        *    - If we dont plan to use the config file, we need to initialize
+        *      SGE entirely, including fixing the host specific registers.
+        * If we arent the master, we are only allowed to read and work off of
+        *      the already initialized SGE values.
+        *
+        * Therefore, before calling this function, we assume that the master-
+        * ship of the card, and whether to use config file or not, have
+        * already been decided. In other words, CSIO_HWF_USING_SOFT_PARAMS and
+        * CSIO_HWF_MASTER should be set/unset.
+        */
+       if (csio_is_hw_master(hw)) {
+               csio_wr_fixup_host_params(hw);
+
+               if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS)
+                       csio_wr_get_sge(hw);
+               else
+                       csio_wr_set_sge(hw);
+       } else
+               csio_wr_get_sge(hw);
+}
+
+/*
+ * csio_wrm_init - Initialize Work request module.
+ * @wrm: WR module
+ * @hw: HW pointer
+ *
+ * Allocates memory for an array of queue pointers starting at q_arr.
+ */
+int
+csio_wrm_init(struct csio_wrm *wrm, struct csio_hw *hw)
+{
+       int i;
+
+       if (!wrm->num_q) {
+               csio_err(hw, "Num queues is not set\n");
+               return -EINVAL;
+       }
+
+       wrm->q_arr = kzalloc(sizeof(struct csio_q *) * wrm->num_q, GFP_KERNEL);
+       if (!wrm->q_arr)
+               goto err;
+
+       for (i = 0; i < wrm->num_q; i++) {
+               wrm->q_arr[i] = kzalloc(sizeof(struct csio_q), GFP_KERNEL);
+               if (!wrm->q_arr[i]) {
+                       while (--i >= 0)
+                               kfree(wrm->q_arr[i]);
+                       goto err_free_arr;
+               }
+       }
+       wrm->free_qidx  = 0;
+
+       return 0;
+
+err_free_arr:
+       kfree(wrm->q_arr);
+err:
+       return -ENOMEM;
+}
+
+/*
+ * csio_wrm_exit - Initialize Work request module.
+ * @wrm: WR module
+ * @hw: HW module
+ *
+ * Uninitialize WR module. Free q_arr and pointers in it.
+ * We have the additional job of freeing the DMA memory associated
+ * with the queues.
+ */
+void
+csio_wrm_exit(struct csio_wrm *wrm, struct csio_hw *hw)
+{
+       int i;
+       uint32_t j;
+       struct csio_q *q;
+       struct csio_dma_buf *buf;
+
+       for (i = 0; i < wrm->num_q; i++) {
+               q = wrm->q_arr[i];
+
+               if (wrm->free_qidx && (i < wrm->free_qidx)) {
+                       if (q->type == CSIO_FREELIST) {
+                               if (!q->un.fl.bufs)
+                                       continue;
+                               for (j = 0; j < q->credits; j++) {
+                                       buf = &q->un.fl.bufs[j];
+                                       if (!buf->vaddr)
+                                               continue;
+                                       pci_free_consistent(hw->pdev, buf->len,
+                                                           buf->vaddr,
+                                                           buf->paddr);
+                               }
+                               kfree(q->un.fl.bufs);
+                       }
+                       pci_free_consistent(hw->pdev, q->size,
+                                           q->vstart, q->pstart);
+               }
+               kfree(q);
+       }
+
+       hw->flags &= ~CSIO_HWF_Q_MEM_ALLOCED;
+
+       kfree(wrm->q_arr);
+}
diff --git a/drivers/scsi/csiostor/csio_wr.h b/drivers/scsi/csiostor/csio_wr.h
new file mode 100644 (file)
index 0000000..8d30e7a
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_WR_H__
+#define __CSIO_WR_H__
+
+#include <linux/cache.h>
+
+#include "csio_defs.h"
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+
+/*
+ * SGE register field values.
+ */
+#define X_INGPCIEBOUNDARY_32B          0
+#define X_INGPCIEBOUNDARY_64B          1
+#define X_INGPCIEBOUNDARY_128B         2
+#define X_INGPCIEBOUNDARY_256B         3
+#define X_INGPCIEBOUNDARY_512B         4
+#define X_INGPCIEBOUNDARY_1024B                5
+#define X_INGPCIEBOUNDARY_2048B                6
+#define X_INGPCIEBOUNDARY_4096B                7
+
+/* GTS register */
+#define X_TIMERREG_COUNTER0            0
+#define X_TIMERREG_COUNTER1            1
+#define X_TIMERREG_COUNTER2            2
+#define X_TIMERREG_COUNTER3            3
+#define X_TIMERREG_COUNTER4            4
+#define X_TIMERREG_COUNTER5            5
+#define X_TIMERREG_RESTART_COUNTER     6
+#define X_TIMERREG_UPDATE_CIDX         7
+
+/*
+ * Egress Context field values
+ */
+#define X_FETCHBURSTMIN_16B            0
+#define X_FETCHBURSTMIN_32B            1
+#define X_FETCHBURSTMIN_64B            2
+#define X_FETCHBURSTMIN_128B           3
+
+#define X_FETCHBURSTMAX_64B            0
+#define X_FETCHBURSTMAX_128B           1
+#define X_FETCHBURSTMAX_256B           2
+#define X_FETCHBURSTMAX_512B           3
+
+#define X_HOSTFCMODE_NONE              0
+#define X_HOSTFCMODE_INGRESS_QUEUE     1
+#define X_HOSTFCMODE_STATUS_PAGE       2
+#define X_HOSTFCMODE_BOTH              3
+
+/*
+ * Ingress Context field values
+ */
+#define X_UPDATESCHEDULING_TIMER       0
+#define X_UPDATESCHEDULING_COUNTER_OPTTIMER    1
+
+#define X_UPDATEDELIVERY_NONE          0
+#define X_UPDATEDELIVERY_INTERRUPT     1
+#define X_UPDATEDELIVERY_STATUS_PAGE   2
+#define X_UPDATEDELIVERY_BOTH          3
+
+#define X_INTERRUPTDESTINATION_PCIE    0
+#define X_INTERRUPTDESTINATION_IQ      1
+
+#define X_RSPD_TYPE_FLBUF              0
+#define X_RSPD_TYPE_CPL                        1
+#define X_RSPD_TYPE_INTR               2
+
+/* WR status is at the same position as retval in a CMD header */
+#define csio_wr_status(_wr)            \
+               (FW_CMD_RETVAL_GET(ntohl(((struct fw_cmd_hdr *)(_wr))->lo)))
+
+struct csio_hw;
+
+extern int csio_intr_coalesce_cnt;
+extern int csio_intr_coalesce_time;
+
+/* Ingress queue params */
+struct csio_iq_params {
+
+       uint8_t         iq_start:1;
+       uint8_t         iq_stop:1;
+       uint8_t         pfn:3;
+
+       uint8_t         vfn;
+
+       uint16_t        physiqid;
+       uint16_t        iqid;
+
+       uint16_t        fl0id;
+       uint16_t        fl1id;
+
+       uint8_t         viid;
+
+       uint8_t         type;
+       uint8_t         iqasynch;
+       uint8_t         reserved4;
+
+       uint8_t         iqandst;
+       uint8_t         iqanus;
+       uint8_t         iqanud;
+
+       uint16_t        iqandstindex;
+
+       uint8_t         iqdroprss;
+       uint8_t         iqpciech;
+       uint8_t         iqdcaen;
+
+       uint8_t         iqdcacpu;
+       uint8_t         iqintcntthresh;
+       uint8_t         iqo;
+
+       uint8_t         iqcprio;
+       uint8_t         iqesize;
+
+       uint16_t        iqsize;
+
+       uint64_t        iqaddr;
+
+       uint8_t         iqflintiqhsen;
+       uint8_t         reserved5;
+       uint8_t         iqflintcongen;
+       uint8_t         iqflintcngchmap;
+
+       uint32_t        reserved6;
+
+       uint8_t         fl0hostfcmode;
+       uint8_t         fl0cprio;
+       uint8_t         fl0paden;
+       uint8_t         fl0packen;
+       uint8_t         fl0congen;
+       uint8_t         fl0dcaen;
+
+       uint8_t         fl0dcacpu;
+       uint8_t         fl0fbmin;
+
+       uint8_t         fl0fbmax;
+       uint8_t         fl0cidxfthresho;
+       uint8_t         fl0cidxfthresh;
+
+       uint16_t        fl0size;
+
+       uint64_t        fl0addr;
+
+       uint64_t        reserved7;
+
+       uint8_t         fl1hostfcmode;
+       uint8_t         fl1cprio;
+       uint8_t         fl1paden;
+       uint8_t         fl1packen;
+       uint8_t         fl1congen;
+       uint8_t         fl1dcaen;
+
+       uint8_t         fl1dcacpu;
+       uint8_t         fl1fbmin;
+
+       uint8_t         fl1fbmax;
+       uint8_t         fl1cidxfthresho;
+       uint8_t         fl1cidxfthresh;
+
+       uint16_t        fl1size;
+
+       uint64_t        fl1addr;
+};
+
+/* Egress queue params */
+struct csio_eq_params {
+
+       uint8_t         pfn;
+       uint8_t         vfn;
+
+       uint8_t         eqstart:1;
+       uint8_t         eqstop:1;
+
+       uint16_t        physeqid;
+       uint32_t        eqid;
+
+       uint8_t         hostfcmode:2;
+       uint8_t         cprio:1;
+       uint8_t         pciechn:3;
+
+       uint16_t        iqid;
+
+       uint8_t         dcaen:1;
+       uint8_t         dcacpu:5;
+
+       uint8_t         fbmin:3;
+       uint8_t         fbmax:3;
+
+       uint8_t         cidxfthresho:1;
+       uint8_t         cidxfthresh:3;
+
+       uint16_t        eqsize;
+
+       uint64_t        eqaddr;
+};
+
+struct csio_dma_buf {
+       struct list_head        list;
+       void                    *vaddr;         /* Virtual address */
+       dma_addr_t              paddr;          /* Physical address */
+       uint32_t                len;            /* Buffer size */
+};
+
+/* Generic I/O request structure */
+struct csio_ioreq {
+       struct csio_sm          sm;             /* SM, List
+                                                * should be the first member
+                                                */
+       int                     iq_idx;         /* Ingress queue index */
+       int                     eq_idx;         /* Egress queue index */
+       uint32_t                nsge;           /* Number of SG elements */
+       uint32_t                tmo;            /* Driver timeout */
+       uint32_t                datadir;        /* Data direction */
+       struct csio_dma_buf     dma_buf;        /* Req/resp DMA buffers */
+       uint16_t                wr_status;      /* WR completion status */
+       int16_t                 drv_status;     /* Driver internal status */
+       struct csio_lnode       *lnode;         /* Owner lnode */
+       struct csio_rnode       *rnode;         /* Src/destination rnode */
+       void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *);
+                                               /* completion callback */
+       void                    *scratch1;      /* Scratch area 1.
+                                                */
+       void                    *scratch2;      /* Scratch area 2. */
+       struct list_head        gen_list;       /* Any list associated with
+                                                * this ioreq.
+                                                */
+       uint64_t                fw_handle;      /* Unique handle passed
+                                                * to FW
+                                                */
+       uint8_t                 dcopy;          /* Data copy required */
+       uint8_t                 reserved1;
+       uint16_t                reserved2;
+       struct completion       cmplobj;        /* ioreq completion object */
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Egress status page for egress cidx updates
+ */
+struct csio_qstatus_page {
+       __be32 qid;
+       __be16 cidx;
+       __be16 pidx;
+};
+
+
+enum {
+       CSIO_MAX_FLBUF_PER_IQWR = 4,
+       CSIO_QCREDIT_SZ  = 64,                  /* pidx/cidx increments
+                                                * in bytes
+                                                */
+       CSIO_MAX_QID = 0xFFFF,
+       CSIO_MAX_IQ = 128,
+
+       CSIO_SGE_NTIMERS = 6,
+       CSIO_SGE_NCOUNTERS = 4,
+       CSIO_SGE_FL_SIZE_REGS = 16,
+};
+
+/* Defines for type */
+enum {
+       CSIO_EGRESS     = 1,
+       CSIO_INGRESS    = 2,
+       CSIO_FREELIST   = 3,
+};
+
+/*
+ * Structure for footer (last 2 flits) of Ingress Queue Entry.
+ */
+struct csio_iqwr_footer {
+       __be32                  hdrbuflen_pidx;
+       __be32                  pldbuflen_qid;
+       union {
+               u8              type_gen;
+               __be64          last_flit;
+       } u;
+};
+
+#define IQWRF_NEWBUF           (1 << 31)
+#define IQWRF_LEN_GET(x)       (((x) >> 0) & 0x7fffffffU)
+#define IQWRF_GEN_SHIFT                7
+#define IQWRF_TYPE_GET(x)      (((x) >> 4) & 0x3U)
+
+
+/*
+ * WR pair:
+ * ========
+ * A WR can start towards the end of a queue, and then continue at the
+ * beginning, since the queue is considered to be circular. This will
+ * require a pair of address/len to be passed back to the caller -
+ * hence the Work request pair structure.
+ */
+struct csio_wr_pair {
+       void                    *addr1;
+       uint32_t                size1;
+       void                    *addr2;
+       uint32_t                size2;
+};
+
+/*
+ * The following structure is used by ingress processing to return the
+ * free list buffers to consumers.
+ */
+struct csio_fl_dma_buf {
+       struct csio_dma_buf     flbufs[CSIO_MAX_FLBUF_PER_IQWR];
+                                               /* Freelist DMA buffers */
+       int                     offset;         /* Offset within the
+                                                * first FL buf.
+                                                */
+       uint32_t                totlen;         /* Total length */
+       uint8_t                 defer_free;     /* Free of buffer can
+                                                * deferred
+                                                */
+};
+
+/* Data-types */
+typedef void (*iq_handler_t)(struct csio_hw *, void *, uint32_t,
+                            struct csio_fl_dma_buf *, void *);
+
+struct csio_iq {
+       uint16_t                iqid;           /* Queue ID */
+       uint16_t                physiqid;       /* Physical Queue ID */
+       uint16_t                genbit;         /* Generation bit,
+                                                * initially set to 1
+                                                */
+       int                     flq_idx;        /* Freelist queue index */
+       iq_handler_t            iq_intx_handler; /* IQ INTx handler routine */
+};
+
+struct csio_eq {
+       uint16_t                eqid;           /* Qid */
+       uint16_t                physeqid;       /* Physical Queue ID */
+       uint8_t                 wrap[512];      /* Temp area for q-wrap around*/
+};
+
+struct csio_fl {
+       uint16_t                flid;           /* Qid */
+       uint16_t                packen;         /* Packing enabled? */
+       int                     offset;         /* Offset within FL buf */
+       int                     sreg;           /* Size register */
+       struct csio_dma_buf     *bufs;          /* Free list buffer ptr array
+                                                * indexed using flq->cidx/pidx
+                                                */
+};
+
+struct csio_qstats {
+       uint32_t        n_tot_reqs;             /* Total no. of Requests */
+       uint32_t        n_tot_rsps;             /* Total no. of responses */
+       uint32_t        n_qwrap;                /* Queue wraps */
+       uint32_t        n_eq_wr_split;          /* Number of split EQ WRs */
+       uint32_t        n_qentry;               /* Queue entry */
+       uint32_t        n_qempty;               /* Queue empty */
+       uint32_t        n_qfull;                /* Queue fulls */
+       uint32_t        n_rsp_unknown;          /* Unknown response type */
+       uint32_t        n_stray_comp;           /* Stray completion intr */
+       uint32_t        n_flq_refill;           /* Number of FL refills */
+};
+
+/* Queue metadata */
+struct csio_q {
+       uint16_t                type;           /* Type: Ingress/Egress/FL */
+       uint16_t                pidx;           /* producer index */
+       uint16_t                cidx;           /* consumer index */
+       uint16_t                inc_idx;        /* Incremental index */
+       uint32_t                wr_sz;          /* Size of all WRs in this q
+                                                * if fixed
+                                                */
+       void                    *vstart;        /* Base virtual address
+                                                * of queue
+                                                */
+       void                    *vwrap;         /* Virtual end address to
+                                                * wrap around at
+                                                */
+       uint32_t                credits;        /* Size of queue in credits */
+       void                    *owner;         /* Owner */
+       union {                                 /* Queue contexts */
+               struct csio_iq  iq;
+               struct csio_eq  eq;
+               struct csio_fl  fl;
+       } un;
+
+       dma_addr_t              pstart;         /* Base physical address of
+                                                * queue
+                                                */
+       uint32_t                portid;         /* PCIE Channel */
+       uint32_t                size;           /* Size of queue in bytes */
+       struct csio_qstats      stats;          /* Statistics */
+} ____cacheline_aligned_in_smp;
+
+struct csio_sge {
+       uint32_t        csio_fl_align;          /* Calculated and cached
+                                                * for fast path
+                                                */
+       uint32_t        sge_control;            /* padding, boundaries,
+                                                * lengths, etc.
+                                                */
+       uint32_t        sge_host_page_size;     /* Host page size */
+       uint32_t        sge_fl_buf_size[CSIO_SGE_FL_SIZE_REGS];
+                                               /* free list buffer sizes */
+       uint16_t        timer_val[CSIO_SGE_NTIMERS];
+       uint8_t         counter_val[CSIO_SGE_NCOUNTERS];
+};
+
+/* Work request module */
+struct csio_wrm {
+       int                     num_q;          /* Number of queues */
+       struct csio_q           **q_arr;        /* Array of queue pointers
+                                                * allocated dynamically
+                                                * based on configured values
+                                                */
+       uint32_t                fw_iq_start;    /* Start ID of IQ for this fn*/
+       uint32_t                fw_eq_start;    /* Start ID of EQ for this fn*/
+       struct csio_q           *intr_map[CSIO_MAX_IQ];
+                                               /* IQ-id to IQ map table. */
+       int                     free_qidx;      /* queue idx of free queue */
+       struct csio_sge         sge;            /* SGE params */
+};
+
+#define csio_get_q(__hw, __idx)                ((__hw)->wrm.q_arr[__idx])
+#define        csio_q_type(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->type)
+#define        csio_q_pidx(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->pidx)
+#define        csio_q_cidx(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->cidx)
+#define        csio_q_inc_idx(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->inc_idx)
+#define        csio_q_vstart(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->vstart)
+#define        csio_q_pstart(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->pstart)
+#define        csio_q_size(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->size)
+#define        csio_q_credits(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->credits)
+#define        csio_q_portid(__hw, __idx)      ((__hw)->wrm.q_arr[(__idx)]->portid)
+#define        csio_q_wr_sz(__hw, __idx)       ((__hw)->wrm.q_arr[(__idx)]->wr_sz)
+#define        csio_q_iqid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.iq.iqid)
+#define csio_q_physiqid(__hw, __idx)                                   \
+                               ((__hw)->wrm.q_arr[(__idx)]->un.iq.physiqid)
+#define csio_q_iq_flq_idx(__hw, __idx)                                 \
+                               ((__hw)->wrm.q_arr[(__idx)]->un.iq.flq_idx)
+#define        csio_q_eqid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.eq.eqid)
+#define        csio_q_flid(__hw, __idx)        ((__hw)->wrm.q_arr[(__idx)]->un.fl.flid)
+
+#define csio_q_physeqid(__hw, __idx)                                   \
+                               ((__hw)->wrm.q_arr[(__idx)]->un.eq.physeqid)
+#define csio_iq_has_fl(__iq)           ((__iq)->un.iq.flq_idx != -1)
+
+#define csio_q_iq_to_flid(__hw, __iq_idx)                              \
+       csio_q_flid((__hw), (__hw)->wrm.q_arr[(__iq_qidx)]->un.iq.flq_idx)
+#define csio_q_set_intr_map(__hw, __iq_idx, __rel_iq_id)               \
+               (__hw)->wrm.intr_map[__rel_iq_id] = csio_get_q(__hw, __iq_idx)
+#define        csio_q_eq_wrap(__hw, __idx)     ((__hw)->wrm.q_arr[(__idx)]->un.eq.wrap)
+
+struct csio_mb;
+
+int csio_wr_alloc_q(struct csio_hw *, uint32_t, uint32_t,
+                   uint16_t, void *, uint32_t, int, iq_handler_t);
+int csio_wr_iq_create(struct csio_hw *, void *, int,
+                               uint32_t, uint8_t, bool,
+                               void (*)(struct csio_hw *, struct csio_mb *));
+int csio_wr_eq_create(struct csio_hw *, void *, int, int, uint8_t,
+                               void (*)(struct csio_hw *, struct csio_mb *));
+int csio_wr_destroy_queues(struct csio_hw *, bool cmd);
+
+
+int csio_wr_get(struct csio_hw *, int, uint32_t,
+                         struct csio_wr_pair *);
+void csio_wr_copy_to_wrp(void *, struct csio_wr_pair *, uint32_t, uint32_t);
+int csio_wr_issue(struct csio_hw *, int, bool);
+int csio_wr_process_iq(struct csio_hw *, struct csio_q *,
+                                void (*)(struct csio_hw *, void *,
+                                         uint32_t, struct csio_fl_dma_buf *,
+                                         void *),
+                                void *);
+int csio_wr_process_iq_idx(struct csio_hw *, int,
+                                void (*)(struct csio_hw *, void *,
+                                         uint32_t, struct csio_fl_dma_buf *,
+                                         void *),
+                                void *);
+
+void csio_wr_sge_init(struct csio_hw *);
+int csio_wrm_init(struct csio_wrm *, struct csio_hw *);
+void csio_wrm_exit(struct csio_wrm *, struct csio_hw *);
+
+#endif /* ifndef __CSIO_WR_H__ */
diff --git a/drivers/scsi/csiostor/t4fw_api_stor.h b/drivers/scsi/csiostor/t4fw_api_stor.h
new file mode 100644 (file)
index 0000000..1223e0d
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _T4FW_API_STOR_H_
+#define _T4FW_API_STOR_H_
+
+
+/******************************************************************************
+ *   R E T U R N   V A L U E S
+ ********************************/
+
+enum fw_retval {
+       FW_SUCCESS              = 0,    /* completed sucessfully */
+       FW_EPERM                = 1,    /* operation not permitted */
+       FW_ENOENT               = 2,    /* no such file or directory */
+       FW_EIO                  = 5,    /* input/output error; hw bad */
+       FW_ENOEXEC              = 8,    /* exec format error; inv microcode */
+       FW_EAGAIN               = 11,   /* try again */
+       FW_ENOMEM               = 12,   /* out of memory */
+       FW_EFAULT               = 14,   /* bad address; fw bad */
+       FW_EBUSY                = 16,   /* resource busy */
+       FW_EEXIST               = 17,   /* file exists */
+       FW_EINVAL               = 22,   /* invalid argument */
+       FW_ENOSPC               = 28,   /* no space left on device */
+       FW_ENOSYS               = 38,   /* functionality not implemented */
+       FW_EPROTO               = 71,   /* protocol error */
+       FW_EADDRINUSE           = 98,   /* address already in use */
+       FW_EADDRNOTAVAIL        = 99,   /* cannot assigned requested address */
+       FW_ENETDOWN             = 100,  /* network is down */
+       FW_ENETUNREACH          = 101,  /* network is unreachable */
+       FW_ENOBUFS              = 105,  /* no buffer space available */
+       FW_ETIMEDOUT            = 110,  /* timeout */
+       FW_EINPROGRESS          = 115,  /* fw internal */
+       FW_SCSI_ABORT_REQUESTED = 128,  /* */
+       FW_SCSI_ABORT_TIMEDOUT  = 129,  /* */
+       FW_SCSI_ABORTED         = 130,  /* */
+       FW_SCSI_CLOSE_REQUESTED = 131,  /* */
+       FW_ERR_LINK_DOWN        = 132,  /* */
+       FW_RDEV_NOT_READY       = 133,  /* */
+       FW_ERR_RDEV_LOST        = 134,  /* */
+       FW_ERR_RDEV_LOGO        = 135,  /* */
+       FW_FCOE_NO_XCHG         = 136,  /* */
+       FW_SCSI_RSP_ERR         = 137,  /* */
+       FW_ERR_RDEV_IMPL_LOGO   = 138,  /* */
+       FW_SCSI_UNDER_FLOW_ERR  = 139,  /* */
+       FW_SCSI_OVER_FLOW_ERR   = 140,  /* */
+       FW_SCSI_DDP_ERR         = 141,  /* DDP error*/
+       FW_SCSI_TASK_ERR        = 142,  /* No SCSI tasks available */
+};
+
+enum fw_fcoe_link_sub_op {
+       FCOE_LINK_DOWN  = 0x0,
+       FCOE_LINK_UP    = 0x1,
+       FCOE_LINK_COND  = 0x2,
+};
+
+enum fw_fcoe_link_status {
+       FCOE_LINKDOWN   = 0x0,
+       FCOE_LINKUP     = 0x1,
+};
+
+enum fw_ofld_prot {
+       PROT_FCOE       = 0x1,
+       PROT_ISCSI      = 0x2,
+};
+
+enum rport_type_fcoe {
+       FLOGI_VFPORT    = 0x1,          /* 0xfffffe */
+       FDISC_VFPORT    = 0x2,          /* 0xfffffe */
+       NS_VNPORT       = 0x3,          /* 0xfffffc */
+       REG_FC4_VNPORT  = 0x4,          /* any FC4 type VN_PORT */
+       REG_VNPORT      = 0x5,          /* 0xfffxxx - non FC4 port in switch */
+       FDMI_VNPORT     = 0x6,          /* 0xfffffa */
+       FAB_CTLR_VNPORT = 0x7,          /* 0xfffffd */
+};
+
+enum event_cause_fcoe {
+       PLOGI_ACC_RCVD          = 0x01,
+       PLOGI_RJT_RCVD          = 0x02,
+       PLOGI_RCVD              = 0x03,
+       PLOGO_RCVD              = 0x04,
+       PRLI_ACC_RCVD           = 0x05,
+       PRLI_RJT_RCVD           = 0x06,
+       PRLI_RCVD               = 0x07,
+       PRLO_RCVD               = 0x08,
+       NPORT_ID_CHGD           = 0x09,
+       FLOGO_RCVD              = 0x0a,
+       CLR_VIRT_LNK_RCVD       = 0x0b,
+       FLOGI_ACC_RCVD          = 0x0c,
+       FLOGI_RJT_RCVD          = 0x0d,
+       FDISC_ACC_RCVD          = 0x0e,
+       FDISC_RJT_RCVD          = 0x0f,
+       FLOGI_TMO_MAX_RETRY     = 0x10,
+       IMPL_LOGO_ADISC_ACC     = 0x11,
+       IMPL_LOGO_ADISC_RJT     = 0x12,
+       IMPL_LOGO_ADISC_CNFLT   = 0x13,
+       PRLI_TMO                = 0x14,
+       ADISC_TMO               = 0x15,
+       RSCN_DEV_LOST           = 0x16,
+       SCR_ACC_RCVD            = 0x17,
+       ADISC_RJT_RCVD          = 0x18,
+       LOGO_SNT                = 0x19,
+       PROTO_ERR_IMPL_LOGO     = 0x1a,
+};
+
+enum fcoe_cmn_type {
+       FCOE_ELS,
+       FCOE_CT,
+       FCOE_SCSI_CMD,
+       FCOE_UNSOL_ELS,
+};
+
+enum fw_wr_stor_opcodes {
+       FW_RDEV_WR                     = 0x38,
+       FW_FCOE_ELS_CT_WR              = 0x30,
+       FW_SCSI_WRITE_WR               = 0x31,
+       FW_SCSI_READ_WR                = 0x32,
+       FW_SCSI_CMD_WR                 = 0x33,
+       FW_SCSI_ABRT_CLS_WR            = 0x34,
+};
+
+struct fw_rdev_wr {
+       __be32 op_to_immdlen;
+       __be32 alloc_to_len16;
+       __be64 cookie;
+       u8     protocol;
+       u8     event_cause;
+       u8     cur_state;
+       u8     prev_state;
+       __be32 flags_to_assoc_flowid;
+       union rdev_entry {
+               struct fcoe_rdev_entry {
+                       __be32 flowid;
+                       u8     protocol;
+                       u8     event_cause;
+                       u8     flags;
+                       u8     rjt_reason;
+                       u8     cur_login_st;
+                       u8     prev_login_st;
+                       __be16 rcv_fr_sz;
+                       u8     rd_xfer_rdy_to_rport_type;
+                       u8     vft_to_qos;
+                       u8     org_proc_assoc_to_acc_rsp_code;
+                       u8     enh_disc_to_tgt;
+                       u8     wwnn[8];
+                       u8     wwpn[8];
+                       __be16 iqid;
+                       u8     fc_oui[3];
+                       u8     r_id[3];
+               } fcoe_rdev;
+               struct iscsi_rdev_entry {
+                       __be32 flowid;
+                       u8     protocol;
+                       u8     event_cause;
+                       u8     flags;
+                       u8     r3;
+                       __be16 iscsi_opts;
+                       __be16 tcp_opts;
+                       __be16 ip_opts;
+                       __be16 max_rcv_len;
+                       __be16 max_snd_len;
+                       __be16 first_brst_len;
+                       __be16 max_brst_len;
+                       __be16 r4;
+                       __be16 def_time2wait;
+                       __be16 def_time2ret;
+                       __be16 nop_out_intrvl;
+                       __be16 non_scsi_to;
+                       __be16 isid;
+                       __be16 tsid;
+                       __be16 port;
+                       __be16 tpgt;
+                       u8     r5[6];
+                       __be16 iqid;
+               } iscsi_rdev;
+       } u;
+};
+
+#define FW_RDEV_WR_FLOWID_GET(x)       (((x) >> 8) & 0xfffff)
+#define FW_RDEV_WR_ASSOC_FLOWID_GET(x) (((x) >> 0) & 0xfffff)
+#define FW_RDEV_WR_RPORT_TYPE_GET(x)   (((x) >> 0) & 0x1f)
+#define FW_RDEV_WR_NPIV_GET(x)         (((x) >> 6) & 0x1)
+#define FW_RDEV_WR_CLASS_GET(x)                (((x) >> 4) & 0x3)
+#define FW_RDEV_WR_TASK_RETRY_ID_GET(x)        (((x) >> 5) & 0x1)
+#define FW_RDEV_WR_RETRY_GET(x)                (((x) >> 4) & 0x1)
+#define FW_RDEV_WR_CONF_CMPL_GET(x)    (((x) >> 3) & 0x1)
+#define FW_RDEV_WR_INI_GET(x)          (((x) >> 1) & 0x1)
+#define FW_RDEV_WR_TGT_GET(x)          (((x) >> 0) & 0x1)
+
+struct fw_fcoe_els_ct_wr {
+       __be32 op_immdlen;
+       __be32 flowid_len16;
+       u64    cookie;
+       __be16 iqid;
+       u8     tmo_val;
+       u8     els_ct_type;
+       u8     ctl_pri;
+       u8     cp_en_class;
+       __be16 xfer_cnt;
+       u8     fl_to_sp;
+       u8     l_id[3];
+       u8     r5;
+       u8     r_id[3];
+       __be64 rsp_dmaaddr;
+       __be32 rsp_dmalen;
+       __be32 r6;
+};
+
+#define FW_FCOE_ELS_CT_WR_OPCODE(x)            ((x) << 24)
+#define FW_FCOE_ELS_CT_WR_OPCODE_GET(x)                (((x) >> 24) & 0xff)
+#define FW_FCOE_ELS_CT_WR_IMMDLEN(x)           ((x) << 0)
+#define FW_FCOE_ELS_CT_WR_IMMDLEN_GET(x)       (((x) >> 0) & 0xff)
+#define FW_FCOE_ELS_CT_WR_SP(x)                        ((x) << 0)
+
+struct fw_scsi_write_wr {
+       __be32 op_immdlen;
+       __be32 flowid_len16;
+       u64    cookie;
+       __be16 iqid;
+       u8     tmo_val;
+       u8     use_xfer_cnt;
+       union fw_scsi_write_priv {
+               struct fcoe_write_priv {
+                       u8   ctl_pri;
+                       u8   cp_en_class;
+                       u8   r3_lo[2];
+               } fcoe;
+               struct iscsi_write_priv {
+                       u8   r3[4];
+               } iscsi;
+       } u;
+       __be32 xfer_cnt;
+       __be32 ini_xfer_cnt;
+       __be64 rsp_dmaaddr;
+       __be32 rsp_dmalen;
+       __be32 r4;
+};
+
+#define FW_SCSI_WRITE_WR_IMMDLEN(x)    ((x) << 0)
+
+struct fw_scsi_read_wr {
+       __be32 op_immdlen;
+       __be32 flowid_len16;
+       u64    cookie;
+       __be16 iqid;
+       u8     tmo_val;
+       u8     use_xfer_cnt;
+       union fw_scsi_read_priv {
+               struct fcoe_read_priv {
+                       u8   ctl_pri;
+                       u8   cp_en_class;
+                       u8   r3_lo[2];
+               } fcoe;
+               struct iscsi_read_priv {
+                       u8   r3[4];
+               } iscsi;
+       } u;
+       __be32 xfer_cnt;
+       __be32 ini_xfer_cnt;
+       __be64 rsp_dmaaddr;
+       __be32 rsp_dmalen;
+       __be32 r4;
+};
+
+#define FW_SCSI_READ_WR_IMMDLEN(x)     ((x) << 0)
+
+struct fw_scsi_cmd_wr {
+       __be32 op_immdlen;
+       __be32 flowid_len16;
+       u64    cookie;
+       __be16 iqid;
+       u8     tmo_val;
+       u8     r3;
+       union fw_scsi_cmd_priv {
+               struct fcoe_cmd_priv {
+                       u8   ctl_pri;
+                       u8   cp_en_class;
+                       u8   r4_lo[2];
+               } fcoe;
+               struct iscsi_cmd_priv {
+                       u8   r4[4];
+               } iscsi;
+       } u;
+       u8     r5[8];
+       __be64 rsp_dmaaddr;
+       __be32 rsp_dmalen;
+       __be32 r6;
+};
+
+#define FW_SCSI_CMD_WR_IMMDLEN(x)      ((x) << 0)
+
+#define SCSI_ABORT 0
+#define SCSI_CLOSE 1
+
+struct fw_scsi_abrt_cls_wr {
+       __be32 op_immdlen;
+       __be32 flowid_len16;
+       u64    cookie;
+       __be16 iqid;
+       u8     tmo_val;
+       u8     sub_opcode_to_chk_all_io;
+       u8     r3[4];
+       u64    t_cookie;
+};
+
+#define FW_SCSI_ABRT_CLS_WR_SUB_OPCODE(x)      ((x) << 2)
+#define FW_SCSI_ABRT_CLS_WR_SUB_OPCODE_GET(x)  (((x) >> 2) & 0x3f)
+#define FW_SCSI_ABRT_CLS_WR_CHK_ALL_IO(x)      ((x) << 0)
+
+enum fw_cmd_stor_opcodes {
+       FW_FCOE_RES_INFO_CMD           = 0x31,
+       FW_FCOE_LINK_CMD               = 0x32,
+       FW_FCOE_VNP_CMD                = 0x33,
+       FW_FCOE_SPARAMS_CMD            = 0x35,
+       FW_FCOE_STATS_CMD              = 0x37,
+       FW_FCOE_FCF_CMD                = 0x38,
+};
+
+struct fw_fcoe_res_info_cmd {
+       __be32 op_to_read;
+       __be32 retval_len16;
+       __be16 e_d_tov;
+       __be16 r_a_tov_seq;
+       __be16 r_a_tov_els;
+       __be16 r_r_tov;
+       __be32 max_xchgs;
+       __be32 max_ssns;
+       __be32 used_xchgs;
+       __be32 used_ssns;
+       __be32 max_fcfs;
+       __be32 max_vnps;
+       __be32 used_fcfs;
+       __be32 used_vnps;
+};
+
+struct fw_fcoe_link_cmd {
+       __be32 op_to_portid;
+       __be32 retval_len16;
+       __be32 sub_opcode_fcfi;
+       u8     r3;
+       u8     lstatus;
+       __be16 flags;
+       u8     r4;
+       u8     set_vlan;
+       __be16 vlan_id;
+       __be32 vnpi_pkd;
+       __be16 r6;
+       u8     phy_mac[6];
+       u8     vnport_wwnn[8];
+       u8     vnport_wwpn[8];
+};
+
+#define FW_FCOE_LINK_CMD_PORTID(x)     ((x) << 0)
+#define FW_FCOE_LINK_CMD_PORTID_GET(x) (((x) >> 0) & 0xf)
+#define FW_FCOE_LINK_CMD_SUB_OPCODE(x)  ((x) << 24U)
+#define FW_FCOE_LINK_CMD_FCFI(x)       ((x) << 0)
+#define FW_FCOE_LINK_CMD_FCFI_GET(x)   (((x) >> 0) & 0xffffff)
+#define FW_FCOE_LINK_CMD_VNPI_GET(x)   (((x) >> 0) & 0xfffff)
+
+struct fw_fcoe_vnp_cmd {
+       __be32 op_to_fcfi;
+       __be32 alloc_to_len16;
+       __be32 gen_wwn_to_vnpi;
+       __be32 vf_id;
+       __be16 iqid;
+       u8   vnport_mac[6];
+       u8   vnport_wwnn[8];
+       u8   vnport_wwpn[8];
+       u8   cmn_srv_parms[16];
+       u8   clsp_word_0_1[8];
+};
+
+#define FW_FCOE_VNP_CMD_FCFI(x)                ((x) << 0)
+#define FW_FCOE_VNP_CMD_ALLOC          (1U << 31)
+#define FW_FCOE_VNP_CMD_FREE           (1U << 30)
+#define FW_FCOE_VNP_CMD_MODIFY         (1U << 29)
+#define FW_FCOE_VNP_CMD_GEN_WWN                (1U << 22)
+#define FW_FCOE_VNP_CMD_VFID_EN                (1U << 20)
+#define FW_FCOE_VNP_CMD_VNPI(x)                ((x) << 0)
+#define FW_FCOE_VNP_CMD_VNPI_GET(x)    (((x) >> 0) & 0xfffff)
+
+struct fw_fcoe_sparams_cmd {
+       __be32 op_to_portid;
+       __be32 retval_len16;
+       u8     r3[7];
+       u8     cos;
+       u8     lport_wwnn[8];
+       u8     lport_wwpn[8];
+       u8     cmn_srv_parms[16];
+       u8     cls_srv_parms[16];
+};
+
+#define FW_FCOE_SPARAMS_CMD_PORTID(x)  ((x) << 0)
+
+struct fw_fcoe_stats_cmd {
+       __be32 op_to_flowid;
+       __be32 free_to_len16;
+       union fw_fcoe_stats {
+               struct fw_fcoe_stats_ctl {
+                       u8   nstats_port;
+                       u8   port_valid_ix;
+                       __be16 r6;
+                       __be32 r7;
+                       __be64 stat0;
+                       __be64 stat1;
+                       __be64 stat2;
+                       __be64 stat3;
+                       __be64 stat4;
+                       __be64 stat5;
+               } ctl;
+               struct fw_fcoe_port_stats {
+                       __be64 tx_bcast_bytes;
+                       __be64 tx_bcast_frames;
+                       __be64 tx_mcast_bytes;
+                       __be64 tx_mcast_frames;
+                       __be64 tx_ucast_bytes;
+                       __be64 tx_ucast_frames;
+                       __be64 tx_drop_frames;
+                       __be64 tx_offload_bytes;
+                       __be64 tx_offload_frames;
+                       __be64 rx_bcast_bytes;
+                       __be64 rx_bcast_frames;
+                       __be64 rx_mcast_bytes;
+                       __be64 rx_mcast_frames;
+                       __be64 rx_ucast_bytes;
+                       __be64 rx_ucast_frames;
+                       __be64 rx_err_frames;
+               } port_stats;
+               struct fw_fcoe_fcf_stats {
+                       __be32 fip_tx_bytes;
+                       __be32 fip_tx_fr;
+                       __be64 fcf_ka;
+                       __be64 mcast_adv_rcvd;
+                       __be16 ucast_adv_rcvd;
+                       __be16 sol_sent;
+                       __be16 vlan_req;
+                       __be16 vlan_rpl;
+                       __be16 clr_vlink;
+                       __be16 link_down;
+                       __be16 link_up;
+                       __be16 logo;
+                       __be16 flogi_req;
+                       __be16 flogi_rpl;
+                       __be16 fdisc_req;
+                       __be16 fdisc_rpl;
+                       __be16 fka_prd_chg;
+                       __be16 fc_map_chg;
+                       __be16 vfid_chg;
+                       u8   no_fka_req;
+                       u8   no_vnp;
+               } fcf_stats;
+               struct fw_fcoe_pcb_stats {
+                       __be64 tx_bytes;
+                       __be64 tx_frames;
+                       __be64 rx_bytes;
+                       __be64 rx_frames;
+                       __be32 vnp_ka;
+                       __be32 unsol_els_rcvd;
+                       __be64 unsol_cmd_rcvd;
+                       __be16 implicit_logo;
+                       __be16 flogi_inv_sparm;
+                       __be16 fdisc_inv_sparm;
+                       __be16 flogi_rjt;
+                       __be16 fdisc_rjt;
+                       __be16 no_ssn;
+                       __be16 mac_flt_fail;
+                       __be16 inv_fr_rcvd;
+               } pcb_stats;
+               struct fw_fcoe_scb_stats {
+                       __be64 tx_bytes;
+                       __be64 tx_frames;
+                       __be64 rx_bytes;
+                       __be64 rx_frames;
+                       __be32 host_abrt_req;
+                       __be32 adap_auto_abrt;
+                       __be32 adap_abrt_rsp;
+                       __be32 host_ios_req;
+                       __be16 ssn_offl_ios;
+                       __be16 ssn_not_rdy_ios;
+                       u8   rx_data_ddp_err;
+                       u8   ddp_flt_set_err;
+                       __be16 rx_data_fr_err;
+                       u8   bad_st_abrt_req;
+                       u8   no_io_abrt_req;
+                       u8   abort_tmo;
+                       u8   abort_tmo_2;
+                       __be32 abort_req;
+                       u8   no_ppod_res_tmo;
+                       u8   bp_tmo;
+                       u8   adap_auto_cls;
+                       u8   no_io_cls_req;
+                       __be32 host_cls_req;
+                       __be64 unsol_cmd_rcvd;
+                       __be32 plogi_req_rcvd;
+                       __be32 prli_req_rcvd;
+                       __be16 logo_req_rcvd;
+                       __be16 prlo_req_rcvd;
+                       __be16 plogi_rjt_rcvd;
+                       __be16 prli_rjt_rcvd;
+                       __be32 adisc_req_rcvd;
+                       __be32 rscn_rcvd;
+                       __be32 rrq_req_rcvd;
+                       __be32 unsol_els_rcvd;
+                       u8   adisc_rjt_rcvd;
+                       u8   scr_rjt;
+                       u8   ct_rjt;
+                       u8   inval_bls_rcvd;
+                       __be32 ba_rjt_rcvd;
+               } scb_stats;
+       } u;
+};
+
+#define FW_FCOE_STATS_CMD_FLOWID(x)    ((x) << 0)
+#define FW_FCOE_STATS_CMD_FREE         (1U << 30)
+#define FW_FCOE_STATS_CMD_NSTATS(x)    ((x) << 4)
+#define FW_FCOE_STATS_CMD_PORT(x)      ((x) << 0)
+#define FW_FCOE_STATS_CMD_PORT_VALID   (1U << 7)
+#define FW_FCOE_STATS_CMD_IX(x)                ((x) << 0)
+
+struct fw_fcoe_fcf_cmd {
+       __be32 op_to_fcfi;
+       __be32 retval_len16;
+       __be16 priority_pkd;
+       u8     mac[6];
+       u8     name_id[8];
+       u8     fabric[8];
+       __be16 vf_id;
+       __be16 max_fcoe_size;
+       u8     vlan_id;
+       u8     fc_map[3];
+       __be32 fka_adv;
+       __be32 r6;
+       u8     r7_hi;
+       u8     fpma_to_portid;
+       u8     spma_mac[6];
+       __be64 r8;
+};
+
+#define FW_FCOE_FCF_CMD_FCFI(x)                ((x) << 0)
+#define FW_FCOE_FCF_CMD_FCFI_GET(x)    (((x) >> 0) & 0xfffff)
+#define FW_FCOE_FCF_CMD_PRIORITY_GET(x)        (((x) >> 0) & 0xff)
+#define FW_FCOE_FCF_CMD_FPMA_GET(x)    (((x) >> 6) & 0x1)
+#define FW_FCOE_FCF_CMD_SPMA_GET(x)    (((x) >> 5) & 0x1)
+#define FW_FCOE_FCF_CMD_LOGIN_GET(x)   (((x) >> 4) & 0x1)
+#define FW_FCOE_FCF_CMD_PORTID_GET(x)  (((x) >> 0) & 0xf)
+
+#endif /* _T4FW_API_STOR_H_ */
index 192724ed7a323a574c20a3cd5864ff1494516c7e..138e573f37ef5b08ceadafbe90ec39701507704e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");
 
 static char driver_name[] = "hptiop";
 static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";
-static const char driver_ver[] = "v1.6 (091225)";
+static const char driver_ver[] = "v1.8";
 
 static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec);
 static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
@@ -77,6 +77,11 @@ static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec)
        return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
 }
 
+static int iop_wait_ready_mvfrey(struct hptiop_hba *hba, u32 millisec)
+{
+       return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
+}
+
 static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag)
 {
        if (tag & IOPMU_QUEUE_ADDR_HOST_BIT)
@@ -230,6 +235,74 @@ static int iop_intr_mv(struct hptiop_hba *hba)
        return ret;
 }
 
+static void hptiop_request_callback_mvfrey(struct hptiop_hba *hba, u32 _tag)
+{
+       u32 req_type = _tag & 0xf;
+       struct hpt_iop_request_scsi_command *req;
+
+       switch (req_type) {
+       case IOP_REQUEST_TYPE_GET_CONFIG:
+       case IOP_REQUEST_TYPE_SET_CONFIG:
+               hba->msg_done = 1;
+               break;
+
+       case IOP_REQUEST_TYPE_SCSI_COMMAND:
+               req = hba->reqs[(_tag >> 4) & 0xff].req_virt;
+               if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))
+                       req->header.result = IOP_RESULT_SUCCESS;
+               hptiop_finish_scsi_req(hba, (_tag >> 4) & 0xff, req);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static int iop_intr_mvfrey(struct hptiop_hba *hba)
+{
+       u32 _tag, status, cptr, cur_rptr;
+       int ret = 0;
+
+       if (hba->initialized)
+               writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+
+       status = readl(&(hba->u.mvfrey.mu->f0_doorbell));
+       if (status) {
+               writel(status, &(hba->u.mvfrey.mu->f0_doorbell));
+               if (status & CPU_TO_F0_DRBL_MSG_BIT) {
+                       u32 msg = readl(&(hba->u.mvfrey.mu->cpu_to_f0_msg_a));
+                       dprintk("received outbound msg %x\n", msg);
+                       hptiop_message_callback(hba, msg);
+               }
+               ret = 1;
+       }
+
+       status = readl(&(hba->u.mvfrey.mu->isr_cause));
+       if (status) {
+               writel(status, &(hba->u.mvfrey.mu->isr_cause));
+               do {
+                       cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
+                       cur_rptr = hba->u.mvfrey.outlist_rptr;
+                       while (cur_rptr != cptr) {
+                               cur_rptr++;
+                               if (cur_rptr == hba->u.mvfrey.list_count)
+                                       cur_rptr = 0;
+
+                               _tag = hba->u.mvfrey.outlist[cur_rptr].val;
+                               BUG_ON(!(_tag & IOPMU_QUEUE_MASK_HOST_BITS));
+                               hptiop_request_callback_mvfrey(hba, _tag);
+                               ret = 1;
+                       }
+                       hba->u.mvfrey.outlist_rptr = cur_rptr;
+               } while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
+       }
+
+       if (hba->initialized)
+               writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+
+       return ret;
+}
+
 static int iop_send_sync_request_itl(struct hptiop_hba *hba,
                                        void __iomem *_req, u32 millisec)
 {
@@ -272,6 +345,26 @@ static int iop_send_sync_request_mv(struct hptiop_hba *hba,
        return -1;
 }
 
+static int iop_send_sync_request_mvfrey(struct hptiop_hba *hba,
+                                       u32 size_bits, u32 millisec)
+{
+       struct hpt_iop_request_header *reqhdr =
+               hba->u.mvfrey.internal_req.req_virt;
+       u32 i;
+
+       hba->msg_done = 0;
+       reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST);
+       hba->ops->post_req(hba, &(hba->u.mvfrey.internal_req));
+
+       for (i = 0; i < millisec; i++) {
+               iop_intr_mvfrey(hba);
+               if (hba->msg_done)
+                       break;
+               msleep(1);
+       }
+       return hba->msg_done ? 0 : -1;
+}
+
 static void hptiop_post_msg_itl(struct hptiop_hba *hba, u32 msg)
 {
        writel(msg, &hba->u.itl.iop->inbound_msgaddr0);
@@ -285,11 +378,18 @@ static void hptiop_post_msg_mv(struct hptiop_hba *hba, u32 msg)
        readl(&hba->u.mv.regs->inbound_doorbell);
 }
 
+static void hptiop_post_msg_mvfrey(struct hptiop_hba *hba, u32 msg)
+{
+       writel(msg, &(hba->u.mvfrey.mu->f0_to_cpu_msg_a));
+       readl(&(hba->u.mvfrey.mu->f0_to_cpu_msg_a));
+}
+
 static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
 {
        u32 i;
 
        hba->msg_done = 0;
+       hba->ops->disable_intr(hba);
        hba->ops->post_msg(hba, msg);
 
        for (i = 0; i < millisec; i++) {
@@ -301,6 +401,7 @@ static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
                msleep(1);
        }
 
+       hba->ops->enable_intr(hba);
        return hba->msg_done? 0 : -1;
 }
 
@@ -354,6 +455,28 @@ static int iop_get_config_mv(struct hptiop_hba *hba,
        return 0;
 }
 
+static int iop_get_config_mvfrey(struct hptiop_hba *hba,
+                               struct hpt_iop_request_get_config *config)
+{
+       struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
+
+       if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
+                       info->header.type != IOP_REQUEST_TYPE_GET_CONFIG)
+               return -1;
+
+       config->interface_version = info->interface_version;
+       config->firmware_version = info->firmware_version;
+       config->max_requests = info->max_requests;
+       config->request_size = info->request_size;
+       config->max_sg_count = info->max_sg_count;
+       config->data_transfer_length = info->data_transfer_length;
+       config->alignment_mask = info->alignment_mask;
+       config->max_devices = info->max_devices;
+       config->sdram_size = info->sdram_size;
+
+       return 0;
+}
+
 static int iop_set_config_itl(struct hptiop_hba *hba,
                                struct hpt_iop_request_set_config *config)
 {
@@ -408,6 +531,29 @@ static int iop_set_config_mv(struct hptiop_hba *hba,
        return 0;
 }
 
+static int iop_set_config_mvfrey(struct hptiop_hba *hba,
+                               struct hpt_iop_request_set_config *config)
+{
+       struct hpt_iop_request_set_config *req =
+               hba->u.mvfrey.internal_req.req_virt;
+
+       memcpy(req, config, sizeof(struct hpt_iop_request_set_config));
+       req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
+       req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG);
+       req->header.size =
+               cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
+       req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+       req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
+       req->header.context_hi32 = 0;
+
+       if (iop_send_sync_request_mvfrey(hba, 0, 20000)) {
+               dprintk("Set config send cmd failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 static void hptiop_enable_intr_itl(struct hptiop_hba *hba)
 {
        writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),
@@ -420,6 +566,13 @@ static void hptiop_enable_intr_mv(struct hptiop_hba *hba)
                &hba->u.mv.regs->outbound_intmask);
 }
 
+static void hptiop_enable_intr_mvfrey(struct hptiop_hba *hba)
+{
+       writel(CPU_TO_F0_DRBL_MSG_BIT, &(hba->u.mvfrey.mu->f0_doorbell_enable));
+       writel(0x1, &(hba->u.mvfrey.mu->isr_enable));
+       writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+}
+
 static int hptiop_initialize_iop(struct hptiop_hba *hba)
 {
        /* enable interrupts */
@@ -502,17 +655,39 @@ static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba)
        return 0;
 }
 
+static int hptiop_map_pci_bar_mvfrey(struct hptiop_hba *hba)
+{
+       hba->u.mvfrey.config = hptiop_map_pci_bar(hba, 0);
+       if (hba->u.mvfrey.config == NULL)
+               return -1;
+
+       hba->u.mvfrey.mu = hptiop_map_pci_bar(hba, 2);
+       if (hba->u.mvfrey.mu == NULL) {
+               iounmap(hba->u.mvfrey.config);
+               return -1;
+       }
+
+       return 0;
+}
+
 static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba)
 {
        iounmap(hba->u.mv.regs);
        iounmap(hba->u.mv.mu);
 }
 
+static void hptiop_unmap_pci_bar_mvfrey(struct hptiop_hba *hba)
+{
+       iounmap(hba->u.mvfrey.config);
+       iounmap(hba->u.mvfrey.mu);
+}
+
 static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)
 {
        dprintk("iop message 0x%x\n", msg);
 
-       if (msg == IOPMU_INBOUND_MSG0_NOP)
+       if (msg == IOPMU_INBOUND_MSG0_NOP ||
+               msg == IOPMU_INBOUND_MSG0_RESET_COMM)
                hba->msg_done = 1;
 
        if (!hba->initialized)
@@ -592,6 +767,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
                memcpy(scp->sense_buffer, &req->sg_list,
                                min_t(size_t, SCSI_SENSE_BUFFERSIZE,
                                        le32_to_cpu(req->dataxfer_length)));
+               goto skip_resid;
                break;
 
        default:
@@ -599,6 +775,10 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
                break;
        }
 
+       scsi_set_resid(scp,
+               scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
+
+skip_resid:
        dprintk("scsi_done(%p)\n", scp);
        scp->scsi_done(scp);
        free_req(hba, &hba->reqs[tag]);
@@ -692,7 +872,8 @@ static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg)
        BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
 
        scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {
-               psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg));
+               psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg)) |
+                       hba->ops->host_phy_flag;
                psg[idx].size = cpu_to_le32(sg_dma_len(sg));
                psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
                        cpu_to_le32(1) : 0;
@@ -751,6 +932,78 @@ static void hptiop_post_req_mv(struct hptiop_hba *hba,
                MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bit, hba);
 }
 
+static void hptiop_post_req_mvfrey(struct hptiop_hba *hba,
+                                       struct hptiop_request *_req)
+{
+       struct hpt_iop_request_header *reqhdr = _req->req_virt;
+       u32 index;
+
+       reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT |
+                       IOP_REQUEST_FLAG_ADDR_BITS |
+                       ((_req->req_shifted_phy >> 11) & 0xffff0000));
+       reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
+                       (_req->index << 4) | reqhdr->type);
+       reqhdr->context_hi32 = cpu_to_le32((_req->req_shifted_phy << 5) &
+                       0xffffffff);
+
+       hba->u.mvfrey.inlist_wptr++;
+       index = hba->u.mvfrey.inlist_wptr & 0x3fff;
+
+       if (index == hba->u.mvfrey.list_count) {
+               index = 0;
+               hba->u.mvfrey.inlist_wptr &= ~0x3fff;
+               hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
+       }
+
+       hba->u.mvfrey.inlist[index].addr =
+                       (dma_addr_t)_req->req_shifted_phy << 5;
+       hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
+       writel(hba->u.mvfrey.inlist_wptr,
+               &(hba->u.mvfrey.mu->inbound_write_ptr));
+       readl(&(hba->u.mvfrey.mu->inbound_write_ptr));
+}
+
+static int hptiop_reset_comm_itl(struct hptiop_hba *hba)
+{
+       return 0;
+}
+
+static int hptiop_reset_comm_mv(struct hptiop_hba *hba)
+{
+       return 0;
+}
+
+static int hptiop_reset_comm_mvfrey(struct hptiop_hba *hba)
+{
+       u32 list_count = hba->u.mvfrey.list_count;
+
+       if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
+               return -1;
+
+       /* wait 100ms for MCU ready */
+       msleep(100);
+
+       writel(cpu_to_le32(hba->u.mvfrey.inlist_phy & 0xffffffff),
+                       &(hba->u.mvfrey.mu->inbound_base));
+       writel(cpu_to_le32((hba->u.mvfrey.inlist_phy >> 16) >> 16),
+                       &(hba->u.mvfrey.mu->inbound_base_high));
+
+       writel(cpu_to_le32(hba->u.mvfrey.outlist_phy & 0xffffffff),
+                       &(hba->u.mvfrey.mu->outbound_base));
+       writel(cpu_to_le32((hba->u.mvfrey.outlist_phy >> 16) >> 16),
+                       &(hba->u.mvfrey.mu->outbound_base_high));
+
+       writel(cpu_to_le32(hba->u.mvfrey.outlist_cptr_phy & 0xffffffff),
+                       &(hba->u.mvfrey.mu->outbound_shadow_base));
+       writel(cpu_to_le32((hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16),
+                       &(hba->u.mvfrey.mu->outbound_shadow_base_high));
+
+       hba->u.mvfrey.inlist_wptr = (list_count - 1) | CL_POINTER_TOGGLE;
+       *hba->u.mvfrey.outlist_cptr = (list_count - 1) | CL_POINTER_TOGGLE;
+       hba->u.mvfrey.outlist_rptr = list_count - 1;
+       return 0;
+}
+
 static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
                                void (*done)(struct scsi_cmnd *))
 {
@@ -771,14 +1024,15 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
 
        _req->scp = scp;
 
-       dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) "
+       dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%08x-%08x-%08x-%08x) "
                        "req_index=%d, req=%p\n",
                        scp,
                        host->host_no, scp->device->channel,
                        scp->device->id, scp->device->lun,
-                       ((u32 *)scp->cmnd)[0],
-                       ((u32 *)scp->cmnd)[1],
-                       ((u32 *)scp->cmnd)[2],
+                       cpu_to_be32(((u32 *)scp->cmnd)[0]),
+                       cpu_to_be32(((u32 *)scp->cmnd)[1]),
+                       cpu_to_be32(((u32 *)scp->cmnd)[2]),
+                       cpu_to_be32(((u32 *)scp->cmnd)[3]),
                        _req->index, _req->req_virt);
 
        scp->result = 0;
@@ -933,6 +1187,11 @@ static struct scsi_host_template driver_template = {
        .change_queue_depth         = hptiop_adjust_disk_queue_depth,
 };
 
+static int hptiop_internal_memalloc_itl(struct hptiop_hba *hba)
+{
+       return 0;
+}
+
 static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba)
 {
        hba->u.mv.internal_req = dma_alloc_coherent(&hba->pcidev->dev,
@@ -943,6 +1202,63 @@ static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba)
                return -1;
 }
 
+static int hptiop_internal_memalloc_mvfrey(struct hptiop_hba *hba)
+{
+       u32 list_count = readl(&hba->u.mvfrey.mu->inbound_conf_ctl);
+       char *p;
+       dma_addr_t phy;
+
+       BUG_ON(hba->max_request_size == 0);
+
+       if (list_count == 0) {
+               BUG_ON(1);
+               return -1;
+       }
+
+       list_count >>= 16;
+
+       hba->u.mvfrey.list_count = list_count;
+       hba->u.mvfrey.internal_mem_size = 0x800 +
+                       list_count * sizeof(struct mvfrey_inlist_entry) +
+                       list_count * sizeof(struct mvfrey_outlist_entry) +
+                       sizeof(int);
+
+       p = dma_alloc_coherent(&hba->pcidev->dev,
+                       hba->u.mvfrey.internal_mem_size, &phy, GFP_KERNEL);
+       if (!p)
+               return -1;
+
+       hba->u.mvfrey.internal_req.req_virt = p;
+       hba->u.mvfrey.internal_req.req_shifted_phy = phy >> 5;
+       hba->u.mvfrey.internal_req.scp = NULL;
+       hba->u.mvfrey.internal_req.next = NULL;
+
+       p += 0x800;
+       phy += 0x800;
+
+       hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
+       hba->u.mvfrey.inlist_phy = phy;
+
+       p += list_count * sizeof(struct mvfrey_inlist_entry);
+       phy += list_count * sizeof(struct mvfrey_inlist_entry);
+
+       hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
+       hba->u.mvfrey.outlist_phy = phy;
+
+       p += list_count * sizeof(struct mvfrey_outlist_entry);
+       phy += list_count * sizeof(struct mvfrey_outlist_entry);
+
+       hba->u.mvfrey.outlist_cptr = (__le32 *)p;
+       hba->u.mvfrey.outlist_cptr_phy = phy;
+
+       return 0;
+}
+
+static int hptiop_internal_memfree_itl(struct hptiop_hba *hba)
+{
+       return 0;
+}
+
 static int hptiop_internal_memfree_mv(struct hptiop_hba *hba)
 {
        if (hba->u.mv.internal_req) {
@@ -953,6 +1269,19 @@ static int hptiop_internal_memfree_mv(struct hptiop_hba *hba)
                return -1;
 }
 
+static int hptiop_internal_memfree_mvfrey(struct hptiop_hba *hba)
+{
+       if (hba->u.mvfrey.internal_req.req_virt) {
+               dma_free_coherent(&hba->pcidev->dev,
+                       hba->u.mvfrey.internal_mem_size,
+                       hba->u.mvfrey.internal_req.req_virt,
+                       (dma_addr_t)
+                       hba->u.mvfrey.internal_req.req_shifted_phy << 5);
+               return 0;
+       } else
+               return -1;
+}
+
 static int __devinit hptiop_probe(struct pci_dev *pcidev,
                                        const struct pci_device_id *id)
 {
@@ -1027,7 +1356,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
                goto unmap_pci_bar;
        }
 
-       if (hba->ops->internal_memalloc) {
+       if (hba->ops->family == MV_BASED_IOP) {
                if (hba->ops->internal_memalloc(hba)) {
                        printk(KERN_ERR "scsi%d: internal_memalloc failed\n",
                                hba->host->host_no);
@@ -1050,6 +1379,19 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        hba->interface_version = le32_to_cpu(iop_config.interface_version);
        hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
 
+       if (hba->ops->family == MVFREY_BASED_IOP) {
+               if (hba->ops->internal_memalloc(hba)) {
+                       printk(KERN_ERR "scsi%d: internal_memalloc failed\n",
+                               hba->host->host_no);
+                       goto unmap_pci_bar;
+               }
+               if (hba->ops->reset_comm(hba)) {
+                       printk(KERN_ERR "scsi%d: reset comm failed\n",
+                                       hba->host->host_no);
+                       goto unmap_pci_bar;
+               }
+       }
+
        if (hba->firmware_version > 0x01020000 ||
                        hba->interface_version > 0x01020000)
                hba->iopintf_v2 = 1;
@@ -1104,14 +1446,13 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
        hba->dma_coherent = start_virt;
        hba->dma_coherent_handle = start_phy;
 
-       if ((start_phy & 0x1f) != 0)
-       {
+       if ((start_phy & 0x1f) != 0) {
                offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
                start_phy += offset;
                start_virt += offset;
        }
 
-       hba->req_list = start_virt;
+       hba->req_list = NULL;
        for (i = 0; i < hba->max_requests; i++) {
                hba->reqs[i].next = NULL;
                hba->reqs[i].req_virt = start_virt;
@@ -1132,7 +1473,6 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
                goto free_request_mem;
        }
 
-
        scsi_scan_host(host);
 
        dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no);
@@ -1147,8 +1487,7 @@ free_request_irq:
        free_irq(hba->pcidev->irq, hba);
 
 unmap_pci_bar:
-       if (hba->ops->internal_memfree)
-               hba->ops->internal_memfree(hba);
+       hba->ops->internal_memfree(hba);
 
        hba->ops->unmap_pci_bar(hba);
 
@@ -1198,6 +1537,16 @@ static void hptiop_disable_intr_mv(struct hptiop_hba *hba)
        readl(&hba->u.mv.regs->outbound_intmask);
 }
 
+static void hptiop_disable_intr_mvfrey(struct hptiop_hba *hba)
+{
+       writel(0, &(hba->u.mvfrey.mu->f0_doorbell_enable));
+       readl(&(hba->u.mvfrey.mu->f0_doorbell_enable));
+       writel(0, &(hba->u.mvfrey.mu->isr_enable));
+       readl(&(hba->u.mvfrey.mu->isr_enable));
+       writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+       readl(&(hba->u.mvfrey.mu->pcie_f0_int_enable));
+}
+
 static void hptiop_remove(struct pci_dev *pcidev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pcidev);
@@ -1216,8 +1565,7 @@ static void hptiop_remove(struct pci_dev *pcidev)
                        hba->dma_coherent,
                        hba->dma_coherent_handle);
 
-       if (hba->ops->internal_memfree)
-               hba->ops->internal_memfree(hba);
+       hba->ops->internal_memfree(hba);
 
        hba->ops->unmap_pci_bar(hba);
 
@@ -1229,9 +1577,10 @@ static void hptiop_remove(struct pci_dev *pcidev)
 }
 
 static struct hptiop_adapter_ops hptiop_itl_ops = {
+       .family            = INTEL_BASED_IOP,
        .iop_wait_ready    = iop_wait_ready_itl,
-       .internal_memalloc = NULL,
-       .internal_memfree  = NULL,
+       .internal_memalloc = hptiop_internal_memalloc_itl,
+       .internal_memfree  = hptiop_internal_memfree_itl,
        .map_pci_bar       = hptiop_map_pci_bar_itl,
        .unmap_pci_bar     = hptiop_unmap_pci_bar_itl,
        .enable_intr       = hptiop_enable_intr_itl,
@@ -1242,9 +1591,12 @@ static struct hptiop_adapter_ops hptiop_itl_ops = {
        .post_msg          = hptiop_post_msg_itl,
        .post_req          = hptiop_post_req_itl,
        .hw_dma_bit_mask   = 64,
+       .reset_comm        = hptiop_reset_comm_itl,
+       .host_phy_flag     = cpu_to_le64(0),
 };
 
 static struct hptiop_adapter_ops hptiop_mv_ops = {
+       .family            = MV_BASED_IOP,
        .iop_wait_ready    = iop_wait_ready_mv,
        .internal_memalloc = hptiop_internal_memalloc_mv,
        .internal_memfree  = hptiop_internal_memfree_mv,
@@ -1258,6 +1610,27 @@ static struct hptiop_adapter_ops hptiop_mv_ops = {
        .post_msg          = hptiop_post_msg_mv,
        .post_req          = hptiop_post_req_mv,
        .hw_dma_bit_mask   = 33,
+       .reset_comm        = hptiop_reset_comm_mv,
+       .host_phy_flag     = cpu_to_le64(0),
+};
+
+static struct hptiop_adapter_ops hptiop_mvfrey_ops = {
+       .family            = MVFREY_BASED_IOP,
+       .iop_wait_ready    = iop_wait_ready_mvfrey,
+       .internal_memalloc = hptiop_internal_memalloc_mvfrey,
+       .internal_memfree  = hptiop_internal_memfree_mvfrey,
+       .map_pci_bar       = hptiop_map_pci_bar_mvfrey,
+       .unmap_pci_bar     = hptiop_unmap_pci_bar_mvfrey,
+       .enable_intr       = hptiop_enable_intr_mvfrey,
+       .disable_intr      = hptiop_disable_intr_mvfrey,
+       .get_config        = iop_get_config_mvfrey,
+       .set_config        = iop_set_config_mvfrey,
+       .iop_intr          = iop_intr_mvfrey,
+       .post_msg          = hptiop_post_msg_mvfrey,
+       .post_req          = hptiop_post_req_mvfrey,
+       .hw_dma_bit_mask   = 64,
+       .reset_comm        = hptiop_reset_comm_mvfrey,
+       .host_phy_flag     = cpu_to_le64(1),
 };
 
 static struct pci_device_id hptiop_id_table[] = {
@@ -1283,6 +1656,8 @@ static struct pci_device_id hptiop_id_table[] = {
        { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },
+       { PCI_VDEVICE(TTI, 0x4520), (kernel_ulong_t)&hptiop_mvfrey_ops },
+       { PCI_VDEVICE(TTI, 0x4522), (kernel_ulong_t)&hptiop_mvfrey_ops },
        {},
 };
 
index baa648d87fde72636bf3ee71168ffa48846ddbe4..020619d60b081d4d393f9ed10565c96e844f96ce 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -75,6 +75,45 @@ struct hpt_iopmv_regs {
        __le32 outbound_intmask;
 };
 
+#pragma pack(1)
+struct hpt_iopmu_mvfrey {
+       __le32 reserved0[(0x4000 - 0) / 4];
+       __le32 inbound_base;
+       __le32 inbound_base_high;
+       __le32 reserved1[(0x4018 - 0x4008) / 4];
+       __le32 inbound_write_ptr;
+       __le32 reserved2[(0x402c - 0x401c) / 4];
+       __le32 inbound_conf_ctl;
+       __le32 reserved3[(0x4050 - 0x4030) / 4];
+       __le32 outbound_base;
+       __le32 outbound_base_high;
+       __le32 outbound_shadow_base;
+       __le32 outbound_shadow_base_high;
+       __le32 reserved4[(0x4088 - 0x4060) / 4];
+       __le32 isr_cause;
+       __le32 isr_enable;
+       __le32 reserved5[(0x1020c - 0x4090) / 4];
+       __le32 pcie_f0_int_enable;
+       __le32 reserved6[(0x10400 - 0x10210) / 4];
+       __le32 f0_to_cpu_msg_a;
+       __le32 reserved7[(0x10420 - 0x10404) / 4];
+       __le32 cpu_to_f0_msg_a;
+       __le32 reserved8[(0x10480 - 0x10424) / 4];
+       __le32 f0_doorbell;
+       __le32 f0_doorbell_enable;
+};
+
+struct mvfrey_inlist_entry {
+       dma_addr_t addr;
+       __le32 intrfc_len;
+       __le32 reserved;
+};
+
+struct mvfrey_outlist_entry {
+       __le32 val;
+};
+#pragma pack()
+
 #define MVIOP_MU_QUEUE_ADDR_HOST_MASK   (~(0x1full))
 #define MVIOP_MU_QUEUE_ADDR_HOST_BIT    4
 
@@ -87,6 +126,9 @@ struct hpt_iopmv_regs {
 #define MVIOP_MU_OUTBOUND_INT_MSG       1
 #define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2
 
+#define CL_POINTER_TOGGLE        0x00004000
+#define CPU_TO_F0_DRBL_MSG_BIT   0x02000000
+
 enum hpt_iopmu_message {
        /* host-to-iop messages */
        IOPMU_INBOUND_MSG0_NOP = 0,
@@ -95,6 +137,7 @@ enum hpt_iopmu_message {
        IOPMU_INBOUND_MSG0_SHUTDOWN,
        IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
        IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
+       IOPMU_INBOUND_MSG0_RESET_COMM,
        IOPMU_INBOUND_MSG0_MAX = 0xff,
        /* iop-to-host messages */
        IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
@@ -118,6 +161,7 @@ struct hpt_iop_request_header {
 #define IOP_REQUEST_FLAG_BIST_REQUEST 2
 #define IOP_REQUEST_FLAG_REMAPPED     4
 #define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8
+#define IOP_REQUEST_FLAG_ADDR_BITS 0x40 /* flags[31:16] is phy_addr[47:32] */
 
 enum hpt_iop_request_type {
        IOP_REQUEST_TYPE_GET_CONFIG = 0,
@@ -223,6 +267,13 @@ struct hpt_scsi_pointer {
 
 #define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp)
 
+enum hptiop_family {
+       UNKNOWN_BASED_IOP,
+       INTEL_BASED_IOP,
+       MV_BASED_IOP,
+       MVFREY_BASED_IOP
+} ;
+
 struct hptiop_hba {
        struct hptiop_adapter_ops *ops;
        union {
@@ -236,6 +287,22 @@ struct hptiop_hba {
                        void *internal_req;
                        dma_addr_t internal_req_phy;
                } mv;
+               struct {
+                       struct hpt_iop_request_get_config __iomem *config;
+                       struct hpt_iopmu_mvfrey __iomem *mu;
+
+                       int internal_mem_size;
+                       struct hptiop_request internal_req;
+                       int list_count;
+                       struct mvfrey_inlist_entry *inlist;
+                       dma_addr_t inlist_phy;
+                       __le32 inlist_wptr;
+                       struct mvfrey_outlist_entry *outlist;
+                       dma_addr_t outlist_phy;
+                       __le32 *outlist_cptr; /* copy pointer shadow */
+                       dma_addr_t outlist_cptr_phy;
+                       __le32 outlist_rptr;
+               } mvfrey;
        } u;
 
        struct Scsi_Host *host;
@@ -283,6 +350,7 @@ struct hpt_ioctl_k {
 };
 
 struct hptiop_adapter_ops {
+       enum hptiop_family family;
        int  (*iop_wait_ready)(struct hptiop_hba *hba, u32 millisec);
        int  (*internal_memalloc)(struct hptiop_hba *hba);
        int  (*internal_memfree)(struct hptiop_hba *hba);
@@ -298,6 +366,8 @@ struct hptiop_adapter_ops {
        void (*post_msg)(struct hptiop_hba *hba, u32 msg);
        void (*post_req)(struct hptiop_hba *hba, struct hptiop_request *_req);
        int  hw_dma_bit_mask;
+       int  (*reset_comm)(struct hptiop_hba *hba);
+       __le64  host_phy_flag;
 };
 
 #define HPT_IOCTL_RESULT_OK         0
index efc6e72f09f34fefdf6faa947bdf74ab588f2a5d..aec2e0da50164ca688cc9e2ea95355f0aeaf4669 100644 (file)
@@ -1800,7 +1800,7 @@ out:
  * @dev:domain device to be detect.
  * @src_dev: the device which originated BROADCAST(CHANGE).
  *
- * Add self-configuration expander suport. Suppose two expander cascading,
+ * Add self-configuration expander support. Suppose two expander cascading,
  * when the first level expander is self-configuring, hotplug the disks in
  * second level expander, BROADCAST(CHANGE) will not only be originated
  * in the second level expander, but also be originated in the first level
index 69b59935b53f57787c6763ceae545886db641d43..df4c13a5534c07fe2b166d3898a0906699c018a8 100644 (file)
@@ -689,6 +689,7 @@ struct lpfc_hba {
 #define LPFC_FCF_PRIORITY 2    /* Priority fcf failover */
        uint32_t cfg_fcf_failover_policy;
        uint32_t cfg_fcp_io_sched;
+       uint32_t cfg_fcp2_no_tgt_reset;
        uint32_t cfg_cr_delay;
        uint32_t cfg_cr_count;
        uint32_t cfg_multi_ring_support;
@@ -714,6 +715,7 @@ struct lpfc_hba {
        uint32_t cfg_log_verbose;
        uint32_t cfg_aer_support;
        uint32_t cfg_sriov_nr_virtfn;
+       uint32_t cfg_request_firmware_upgrade;
        uint32_t cfg_iocb_cnt;
        uint32_t cfg_suppress_link_up;
 #define LPFC_INITIALIZE_LINK              0    /* do normal init_link mbox */
index ad16e54ac383107749cfb783648fb932708a55b1..a364cae9e98496acf310696be38c2acd5d206dea 100644 (file)
@@ -3617,6 +3617,77 @@ lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val)
 static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR,
                   lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store);
 
+/**
+ * lpfc_request_firmware_store - Request for Linux generic firmware upgrade
+ *
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: containing the string the number of vfs to be enabled.
+ * @count: unused variable.
+ *
+ * Description:
+ *
+ * Returns:
+ * length of the buf on success if val is in range the intended mode
+ * is supported.
+ * -EINVAL if val out of range or intended mode is not supported.
+ **/
+static ssize_t
+lpfc_request_firmware_upgrade_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+       struct lpfc_hba *phba = vport->phba;
+       int val = 0, rc = -EINVAL;
+
+       /* Sanity check on user data */
+       if (!isdigit(buf[0]))
+               return -EINVAL;
+       if (sscanf(buf, "%i", &val) != 1)
+               return -EINVAL;
+       if (val != 1)
+               return -EINVAL;
+
+       rc = lpfc_sli4_request_firmware_update(phba, RUN_FW_UPGRADE);
+       if (rc)
+               rc = -EPERM;
+       else
+               rc = strlen(buf);
+       return rc;
+}
+
+static int lpfc_req_fw_upgrade;
+module_param(lpfc_req_fw_upgrade, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(lpfc_req_fw_upgrade, "Enable Linux generic firmware upgrade");
+lpfc_param_show(request_firmware_upgrade)
+
+/**
+ * lpfc_request_firmware_upgrade_init - Enable initial linux generic fw upgrade
+ * @phba: lpfc_hba pointer.
+ * @val: 0 or 1.
+ *
+ * Description:
+ * Set the initial Linux generic firmware upgrade enable or disable flag.
+ *
+ * Returns:
+ * zero if val saved.
+ * -EINVAL val out of range
+ **/
+static int
+lpfc_request_firmware_upgrade_init(struct lpfc_hba *phba, int val)
+{
+       if (val >= 0 && val <= 1) {
+               phba->cfg_request_firmware_upgrade = val;
+               return 0;
+       }
+       return -EINVAL;
+}
+static DEVICE_ATTR(lpfc_req_fw_upgrade, S_IRUGO | S_IWUSR,
+                  lpfc_request_firmware_upgrade_show,
+                  lpfc_request_firmware_upgrade_store);
+
 /**
  * lpfc_fcp_imax_store
  *
@@ -3787,6 +3858,16 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
 LPFC_ATTR_RW(fcp_io_sched, 0, 0, 1, "Determine scheduling algrithmn for "
                "issuing commands [0] - Round Robin, [1] - Current CPU");
 
+/*
+# lpfc_fcp2_no_tgt_reset: Determine bus reset behavior
+# range is [0,1]. Default value is 0.
+# For [0], bus reset issues target reset to ALL devices
+# For [1], bus reset issues target reset to non-FCP2 devices
+*/
+LPFC_ATTR_RW(fcp2_no_tgt_reset, 0, 0, 1, "Determine bus reset behavior for "
+            "FCP2 devices [0] - issue tgt reset, [1] - no tgt reset");
+
+
 /*
 # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
 # cr_delay (msec) or cr_count outstanding commands. cr_delay can take
@@ -4029,6 +4110,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_scan_down,
        &dev_attr_lpfc_link_speed,
        &dev_attr_lpfc_fcp_io_sched,
+       &dev_attr_lpfc_fcp2_no_tgt_reset,
        &dev_attr_lpfc_cr_delay,
        &dev_attr_lpfc_cr_count,
        &dev_attr_lpfc_multi_ring_support,
@@ -4069,6 +4151,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_aer_support,
        &dev_attr_lpfc_aer_state_cleanup,
        &dev_attr_lpfc_sriov_nr_virtfn,
+       &dev_attr_lpfc_req_fw_upgrade,
        &dev_attr_lpfc_suppress_link_up,
        &dev_attr_lpfc_iocb_cnt,
        &dev_attr_iocb_hw,
@@ -5019,6 +5102,7 @@ void
 lpfc_get_cfgparam(struct lpfc_hba *phba)
 {
        lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
+       lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
        lpfc_cr_delay_init(phba, lpfc_cr_delay);
        lpfc_cr_count_init(phba, lpfc_cr_count);
        lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support);
@@ -5051,6 +5135,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
        lpfc_aer_support_init(phba, lpfc_aer_support);
        lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
+       lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
        lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
        lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
        phba->cfg_enable_dss = 1;
index 4380a44000bc71df81f252b504f93a732991b12e..69d66e3662cb6fc821614ddaaeebec0435231e37 100644 (file)
@@ -468,3 +468,4 @@ 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 *);
+int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
index 7ffabb7e3afa536cb42f6aef511e80979ddb17c6..65f9fb6862e6b36ddde7cbf80074eefcb2593e31 100644 (file)
@@ -634,7 +634,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                /* Check for retry */
                if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
                        if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
-                           (irsp->un.ulpWord[4] && IOERR_PARAM_MASK) !=
+                           (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
                            IOERR_NO_RESOURCES)
                                vport->fc_ns_retry++;
 
index f19e9b6f9f133de56e484bc275109377dbc58664..b9440deaad459a59bb9cc912dfb9f2e5e5ef5db4 100644 (file)
@@ -1182,8 +1182,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        sp->cmn.w2.r_a_tov = 0;
        sp->cmn.virtual_fabric_support = 0;
        sp->cls1.classValid = 0;
-       sp->cls2.seqDelivery = 1;
-       sp->cls3.seqDelivery = 1;
        if (sp->cmn.fcphLow < FC_PH3)
                sp->cmn.fcphLow = FC_PH3;
        if (sp->cmn.fcphHigh < FC_PH3)
@@ -1198,7 +1196,13 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        /* Set the fcfi to the fcfi we registered with */
                        elsiocb->iocb.ulpContext = phba->fcf.fcfi;
                }
+               /* Can't do SLI4 class2 without support sequence coalescing */
+               sp->cls2.classValid = 0;
+               sp->cls2.seqDelivery = 0;
        } else {
+               /* Historical, setting sequential-delivery bit for SLI3 */
+               sp->cls2.seqDelivery = (sp->cls2.classValid) ? 1 : 0;
+               sp->cls3.seqDelivery = (sp->cls3.classValid) ? 1 : 0;
                if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
                        sp->cmn.request_multiple_Nport = 1;
                        /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
index 2cdeb5434fb7760457761bab3f6c40607fc7d0f6..a47cfbdd05f28d4497ea6eab982cd13d86dde803 100644 (file)
@@ -3219,6 +3219,9 @@ struct wqe_common {
 #define wqe_dif_SHIFT         0
 #define wqe_dif_MASK          0x00000003
 #define wqe_dif_WORD          word7
+#define LPFC_WQE_DIF_PASSTHRU  1
+#define LPFC_WQE_DIF_STRIP     2
+#define LPFC_WQE_DIF_INSERT    3
 #define wqe_ct_SHIFT          2
 #define wqe_ct_MASK           0x00000003
 #define wqe_ct_WORD           word7
index 7dc4218d9c4c53c2ea57d81cee7f0b9d8803d21b..c20eec78adc16e6b75f1df76536b5cbacb3c777b 100644 (file)
@@ -3854,7 +3854,7 @@ static void
 lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
 {
        char port_name;
-       char message[80];
+       char message[128];
        uint8_t status;
        struct lpfc_acqe_misconfigured_event *misconfigured;
 
@@ -9450,7 +9450,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
        struct lpfc_dmabuf *dmabuf, *next;
        uint32_t offset = 0, temp_offset = 0;
 
-       /* It can be null, sanity check */
+       /* It can be null in no-wait mode, sanity check */
        if (!fw) {
                rc = -ENXIO;
                goto out;
@@ -9528,10 +9528,47 @@ release_out:
        release_firmware(fw);
 out:
        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                       "3024 Firmware update done: %d.", rc);
+                       "3024 Firmware update done: %d.\n", rc);
        return;
 }
 
+/**
+ * lpfc_sli4_request_firmware_update - Request linux generic firmware upgrade
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is called to perform Linux generic firmware upgrade on device
+ * that supports such feature.
+ **/
+int
+lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
+{
+       uint8_t file_name[ELX_MODEL_NAME_SIZE];
+       int ret;
+       const struct firmware *fw;
+
+       /* Only supported on SLI4 interface type 2 for now */
+       if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
+           LPFC_SLI_INTF_IF_TYPE_2)
+               return -EPERM;
+
+       snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName);
+
+       if (fw_upgrade == INT_FW_UPGRADE) {
+               ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                                       file_name, &phba->pcidev->dev,
+                                       GFP_KERNEL, (void *)phba,
+                                       lpfc_write_firmware);
+       } else if (fw_upgrade == RUN_FW_UPGRADE) {
+               ret = request_firmware(&fw, file_name, &phba->pcidev->dev);
+               if (!ret)
+                       lpfc_write_firmware(fw, (void *)phba);
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
 /**
  * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys
  * @pdev: pointer to PCI device
@@ -9560,7 +9597,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        uint32_t cfg_mode, intr_mode;
        int mcnt;
        int adjusted_fcp_io_channel;
-       uint8_t file_name[ELX_MODEL_NAME_SIZE];
 
        /* Allocate memory for HBA structure */
        phba = lpfc_hba_alloc(pdev);
@@ -9703,16 +9739,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        /* Perform post initialization setup */
        lpfc_post_init_setup(phba);
 
-       /* 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, 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 for firmware upgrade or downgrade */
+       if (phba->cfg_request_firmware_upgrade)
+               ret = lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
 
        /* Check if there are static vports to be created. */
        lpfc_create_static_vport(phba);
index 7f45ac9964a9222dff88a4de4a56cacc80ae7932..60e5a177644ce4215e84d417dc27df2e5937b1d0 100644 (file)
@@ -3227,6 +3227,21 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
                }
        }
 
+       switch (scsi_get_prot_op(scsi_cmnd)) {
+       case SCSI_PROT_WRITE_STRIP:
+       case SCSI_PROT_READ_STRIP:
+               lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_STRIP;
+               break;
+       case SCSI_PROT_WRITE_INSERT:
+       case SCSI_PROT_READ_INSERT:
+               lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_INSERT;
+               break;
+       case SCSI_PROT_WRITE_PASS:
+       case SCSI_PROT_READ_PASS:
+               lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_PASS;
+               break;
+       }
+
        fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
 
        fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
@@ -3236,7 +3251,6 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
         * we need to set word 4 of IOCB here
         */
        iocb_cmd->un.fcpi.fcpi_parm = fcpdl;
-       lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF;
 
        return 0;
 err:
@@ -4914,6 +4928,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
                list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
                        if (!NLP_CHK_NODE_ACT(ndlp))
                                continue;
+                       if (vport->phba->cfg_fcp2_no_tgt_reset &&
+                           (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))
+                               continue;
                        if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
                            ndlp->nlp_sid == i &&
                            ndlp->rport) {
index d7f3313ef8869d2d72a975b47c4cb5987a48f43d..624eab370396d8bfc0bf8dea421f5370646d6087 100644 (file)
@@ -8068,10 +8068,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                       LPFC_WQE_LENLOC_WORD4);
                bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0);
                bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU);
-               if (iocbq->iocb_flag & LPFC_IO_DIF) {
-                       iocbq->iocb_flag &= ~LPFC_IO_DIF;
-                       bf_set(wqe_dif, &wqe->generic.wqe_com, 1);
-               }
                bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1);
                break;
        case CMD_FCP_IREAD64_CR:
@@ -8091,10 +8087,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                       LPFC_WQE_LENLOC_WORD4);
                bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0);
                bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU);
-               if (iocbq->iocb_flag & LPFC_IO_DIF) {
-                       iocbq->iocb_flag &= ~LPFC_IO_DIF;
-                       bf_set(wqe_dif, &wqe->generic.wqe_com, 1);
-               }
                bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1);
                break;
        case CMD_FCP_ICMND64_CR:
@@ -8304,6 +8296,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                break;
        }
 
+       if (iocbq->iocb_flag & LPFC_IO_DIF_PASS)
+               bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU);
+       else if (iocbq->iocb_flag & LPFC_IO_DIF_STRIP)
+               bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP);
+       else if (iocbq->iocb_flag & LPFC_IO_DIF_INSERT)
+               bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT);
+       iocbq->iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP |
+                             LPFC_IO_DIF_INSERT);
        bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
        bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
        wqe->generic.wqe_com.abort_tag = abort_tag;
index 2f48d000a3b430f5db5da07eb188ac8ba1c02b72..9d2e0c6fe3342f7027bc5e8fbf50ec6e3a411e5a 100644 (file)
@@ -69,7 +69,9 @@ struct lpfc_iocbq {
 #define LPFC_USE_FCPWQIDX      0x80    /* Submit to specified FCPWQ index */
 #define DSS_SECURITY_OP                0x100   /* security IO */
 #define LPFC_IO_ON_TXCMPLQ     0x200   /* The IO is still on the TXCMPLQ */
-#define LPFC_IO_DIF            0x400   /* T10 DIF IO */
+#define LPFC_IO_DIF_PASS       0x400   /* T10 DIF IO pass-thru prot */
+#define LPFC_IO_DIF_STRIP      0x800   /* T10 DIF IO strip prot */
+#define LPFC_IO_DIF_INSERT     0x1000  /* T10 DIF IO insert prot */
 
 #define LPFC_FIP_ELS_ID_MASK   0xc000  /* ELS_ID range 0-3, non-shifted mask */
 #define LPFC_FIP_ELS_ID_SHIFT  14
index f44a06a4c6e743fc32af95b1984d0e824865e3c0..44c427a45d664fce9089ca60cf5e03386707fbf5 100644 (file)
@@ -82,6 +82,9 @@
 
 #define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000
 
+#define INT_FW_UPGRADE 0
+#define RUN_FW_UPGRADE 1
+
 enum lpfc_sli4_queue_type {
        LPFC_EQ,
        LPFC_GCQ,
index 0c2149189dda625769cee4ec88ee579ec8f51456..ba596e854bbc6827b7d755ac9dbd78ca0d8dfa92 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.35"
+#define LPFC_DRIVER_VERSION "8.3.36"
 #define LPFC_DRIVER_NAME               "lpfc"
 
 /* Used for SLI 2/3 */
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig
new file mode 100644 (file)
index 0000000..81471bf
--- /dev/null
@@ -0,0 +1,67 @@
+#
+# Kernel configuration file for the MPT3SAS
+#
+# This code is based on drivers/scsi/mpt3sas/Kconfig
+# Copyright (C) 2012  LSI Corporation
+#  (mailto:DL-MPTFusionLinux@lsi.com)
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# NO WARRANTY
+# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+# solely responsible for determining the appropriateness of using and
+# distributing the Program and assumes all risks associated with its
+# exercise of rights under this Agreement, including but not limited to
+# the risks and costs of program errors, damage to or loss of data,
+# programs or equipment, and unavailability or interruption of operations.
+
+# DISCLAIMER OF LIABILITY
+# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+# 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.
+
+config SCSI_MPT3SAS
+       tristate "LSI MPT Fusion SAS 3.0 Device Driver"
+       depends on PCI && SCSI
+       select SCSI_SAS_ATTRS
+       select RAID_ATTRS
+       ---help---
+       This driver supports PCI-Express SAS 12Gb/s Host Adapters.
+
+config SCSI_MPT3SAS_MAX_SGE
+       int "LSI MPT Fusion Max number of SG Entries (16 - 256)"
+       depends on PCI && SCSI && SCSI_MPT3SAS
+       default "128"
+       range 16 256
+       ---help---
+       This option allows you to specify the maximum number of scatter-
+       gather entries per I/O. The driver default is 128, which matches
+       MAX_PHYS_SEGMENTS in most kernels.  However in SuSE kernels this
+       can be 256. However, it may decreased down to 16.  Decreasing this
+       parameter will reduce memory requirements on a per controller instance.
+
+config SCSI_MPT3SAS_LOGGING
+       bool "LSI MPT Fusion logging facility"
+       depends on PCI && SCSI && SCSI_MPT3SAS
+       ---help---
+       This turns on a logging facility.
diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile
new file mode 100644 (file)
index 0000000..4c1d2e7
--- /dev/null
@@ -0,0 +1,8 @@
+# mpt3sas makefile
+obj-m += mpt3sas.o
+mpt3sas-y +=  mpt3sas_base.o     \
+               mpt3sas_config.o \
+               mpt3sas_scsih.o      \
+               mpt3sas_transport.o     \
+               mpt3sas_ctl.o   \
+               mpt3sas_trigger_diag.o
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
new file mode 100644 (file)
index 0000000..03317ff
--- /dev/null
@@ -0,0 +1,1164 @@
+/*
+ * Copyright (c) 2000-2012 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2.h
+ *         Title:  MPI Message independent structures and definitions
+ *                 including System Interface Register Set and
+ *                 scatter/gather formats.
+ * Creation Date:  June 21, 2006
+ *
+ * mpi2.h Version:  02.00.26
+ *
+ * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
+ *       prefix are for use only on MPI v2.5 products, and must not be used
+ *       with MPI v2.0 products. Unless otherwise noted, names beginning with
+ *       MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-04-07  02.00.01  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 06-26-07  02.00.02  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 08-31-07  02.00.03  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Moved ReplyPostHostIndex register to offset 0x6C of the
+ *                     MPI2_SYSTEM_INTERFACE_REGS and modified the define for
+ *                     MPI2_REPLY_POST_HOST_INDEX_OFFSET.
+ *                     Added union of request descriptors.
+ *                     Added union of reply descriptors.
+ * 10-31-07  02.00.04  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added define for MPI2_VERSION_02_00.
+ *                     Fixed the size of the FunctionDependent5 field in the
+ *                     MPI2_DEFAULT_REPLY structure.
+ * 12-18-07  02.00.05  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Removed the MPI-defined Fault Codes and extended the
+ *                     product specific codes up to 0xEFFF.
+ *                     Added a sixth key value for the WriteSequence register
+ *                     and changed the flush value to 0x0.
+ *                     Added message function codes for Diagnostic Buffer Post
+ *                     and Diagnsotic Release.
+ *                     New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
+ *                     Moved MPI2_VERSION_UNION from mpi2_ioc.h.
+ * 02-29-08  02.00.06  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 03-03-08  02.00.07  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 05-21-08  02.00.08  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added #defines for marking a reply descriptor as unused.
+ * 06-27-08  02.00.09  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Moved LUN field defines from mpi2_init.h.
+ * 01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     In all request and reply descriptors, replaced VF_ID
+ *                     field with MSIxIndex field.
+ *                     Removed DevHandle field from
+ *                     MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
+ *                     bytes reserved.
+ *                     Added RAID Accelerator functionality.
+ * 07-30-09  02.00.13  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 10-28-09  02.00.14  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added MSI-x index mask and shift for Reply Post Host
+ *                     Index register.
+ *                     Added function code for Host Based Discovery Action.
+ * 02-10-10  02.00.15  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
+ *                     Added defines for product-specific range of message
+ *                     function codes, 0xF0 to 0xFF.
+ * 05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added alternative defines for the SGE Direction bit.
+ * 08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-10-10  02.00.18  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
+ * 02-23-11  02.00.19  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added MPI2_FUNCTION_SEND_HOST_MESSAGE.
+ * 03-09-11  02.00.20  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 05-25-11  02.00.21  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 08-24-11  02.00.22  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-18-11  02.00.23  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Incorporating additions for MPI v2.5.
+ * 02-06-12  02.00.24  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 03-29-12  02.00.25  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                     Added Hard Reset delay timings.
+ * 07-10-12  02.00.26  Bumped MPI2_HEADER_VERSION_UNIT.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_H
+#define MPI2_H
+
+/*****************************************************************************
+*
+*       MPI Version Definitions
+*
+*****************************************************************************/
+
+#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT            (8)
+#define MPI2_VERSION_MINOR_MASK             (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT            (0)
+
+/*major version for all MPI v2.x */
+#define MPI2_VERSION_MAJOR                  (0x02)
+
+/*minor version for MPI v2.0 compatible products */
+#define MPI2_VERSION_MINOR                  (0x00)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
+                                       MPI2_VERSION_MINOR)
+#define MPI2_VERSION_02_00                  (0x0200)
+
+/*minor version for MPI v2.5 compatible products */
+#define MPI25_VERSION_MINOR                 (0x05)
+#define MPI25_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
+                                       MPI25_VERSION_MINOR)
+#define MPI2_VERSION_02_05                  (0x0205)
+
+/*Unit and Dev versioning for this MPI header set */
+#define MPI2_HEADER_VERSION_UNIT            (0x1A)
+#define MPI2_HEADER_VERSION_DEV             (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
+#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \
+                                       MPI2_HEADER_VERSION_DEV)
+
+/*****************************************************************************
+*
+*       IOC State Definitions
+*
+*****************************************************************************/
+
+#define MPI2_IOC_STATE_RESET               (0x00000000)
+#define MPI2_IOC_STATE_READY               (0x10000000)
+#define MPI2_IOC_STATE_OPERATIONAL         (0x20000000)
+#define MPI2_IOC_STATE_FAULT               (0x40000000)
+
+#define MPI2_IOC_STATE_MASK                (0xF0000000)
+#define MPI2_IOC_STATE_SHIFT               (28)
+
+/*Fault state range for prodcut specific codes */
+#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN                 (0x0000)
+#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX                 (0xEFFF)
+
+/*****************************************************************************
+*
+*       System Interface Register Definitions
+*
+*****************************************************************************/
+
+typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
+       U32 Doorbell;           /*0x00 */
+       U32 WriteSequence;      /*0x04 */
+       U32 HostDiagnostic;     /*0x08 */
+       U32 Reserved1;          /*0x0C */
+       U32 DiagRWData;         /*0x10 */
+       U32 DiagRWAddressLow;   /*0x14 */
+       U32 DiagRWAddressHigh;  /*0x18 */
+       U32 Reserved2[5];       /*0x1C */
+       U32 HostInterruptStatus;        /*0x30 */
+       U32 HostInterruptMask;  /*0x34 */
+       U32 DCRData;            /*0x38 */
+       U32 DCRAddress;         /*0x3C */
+       U32 Reserved3[2];       /*0x40 */
+       U32 ReplyFreeHostIndex; /*0x48 */
+       U32 Reserved4[8];       /*0x4C */
+       U32 ReplyPostHostIndex; /*0x6C */
+       U32 Reserved5;          /*0x70 */
+       U32 HCBSize;            /*0x74 */
+       U32 HCBAddressLow;      /*0x78 */
+       U32 HCBAddressHigh;     /*0x7C */
+       U32 Reserved6[16];      /*0x80 */
+       U32 RequestDescriptorPostLow;   /*0xC0 */
+       U32 RequestDescriptorPostHigh;  /*0xC4 */
+       U32 Reserved7[14];      /*0xC8 */
+} MPI2_SYSTEM_INTERFACE_REGS,
+       *PTR_MPI2_SYSTEM_INTERFACE_REGS,
+       Mpi2SystemInterfaceRegs_t,
+       *pMpi2SystemInterfaceRegs_t;
+
+/*
+ *Defines for working with the Doorbell register.
+ */
+#define MPI2_DOORBELL_OFFSET                    (0x00000000)
+
+/*IOC --> System values */
+#define MPI2_DOORBELL_USED                      (0x08000000)
+#define MPI2_DOORBELL_WHO_INIT_MASK             (0x07000000)
+#define MPI2_DOORBELL_WHO_INIT_SHIFT            (24)
+#define MPI2_DOORBELL_FAULT_CODE_MASK           (0x0000FFFF)
+#define MPI2_DOORBELL_DATA_MASK                 (0x0000FFFF)
+
+/*System --> IOC values */
+#define MPI2_DOORBELL_FUNCTION_MASK             (0xFF000000)
+#define MPI2_DOORBELL_FUNCTION_SHIFT            (24)
+#define MPI2_DOORBELL_ADD_DWORDS_MASK           (0x00FF0000)
+#define MPI2_DOORBELL_ADD_DWORDS_SHIFT          (16)
+
+/*
+ *Defines for the WriteSequence register
+ */
+#define MPI2_WRITE_SEQUENCE_OFFSET              (0x00000004)
+#define MPI2_WRSEQ_KEY_VALUE_MASK               (0x0000000F)
+#define MPI2_WRSEQ_FLUSH_KEY_VALUE              (0x0)
+#define MPI2_WRSEQ_1ST_KEY_VALUE                (0xF)
+#define MPI2_WRSEQ_2ND_KEY_VALUE                (0x4)
+#define MPI2_WRSEQ_3RD_KEY_VALUE                (0xB)
+#define MPI2_WRSEQ_4TH_KEY_VALUE                (0x2)
+#define MPI2_WRSEQ_5TH_KEY_VALUE                (0x7)
+#define MPI2_WRSEQ_6TH_KEY_VALUE                (0xD)
+
+/*
+ *Defines for the HostDiagnostic register
+ */
+#define MPI2_HOST_DIAGNOSTIC_OFFSET             (0x00000008)
+
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK       (0x00001800)
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT    (0x00000000)
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW       (0x00000800)
+
+#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG           (0x00000400)
+#define MPI2_DIAG_FORCE_HCB_ON_RESET            (0x00000200)
+#define MPI2_DIAG_HCB_MODE                      (0x00000100)
+#define MPI2_DIAG_DIAG_WRITE_ENABLE             (0x00000080)
+#define MPI2_DIAG_FLASH_BAD_SIG                 (0x00000040)
+#define MPI2_DIAG_RESET_HISTORY                 (0x00000020)
+#define MPI2_DIAG_DIAG_RW_ENABLE                (0x00000010)
+#define MPI2_DIAG_RESET_ADAPTER                 (0x00000004)
+#define MPI2_DIAG_HOLD_IOC_RESET                (0x00000002)
+
+/*
+ *Offsets for DiagRWData and address
+ */
+#define MPI2_DIAG_RW_DATA_OFFSET                (0x00000010)
+#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET         (0x00000014)
+#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET        (0x00000018)
+
+/*
+ *Defines for the HostInterruptStatus register
+ */
+#define MPI2_HOST_INTERRUPT_STATUS_OFFSET       (0x00000030)
+#define MPI2_HIS_SYS2IOC_DB_STATUS              (0x80000000)
+#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS
+#define MPI2_HIS_RESET_IRQ_STATUS               (0x40000000)
+#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT     (0x00000008)
+#define MPI2_HIS_IOC2SYS_DB_STATUS              (0x00000001)
+#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS
+
+/*
+ *Defines for the HostInterruptMask register
+ */
+#define MPI2_HOST_INTERRUPT_MASK_OFFSET         (0x00000034)
+#define MPI2_HIM_RESET_IRQ_MASK                 (0x40000000)
+#define MPI2_HIM_REPLY_INT_MASK                 (0x00000008)
+#define MPI2_HIM_RIM                            MPI2_HIM_REPLY_INT_MASK
+#define MPI2_HIM_IOC2SYS_DB_MASK                (0x00000001)
+#define MPI2_HIM_DIM                            MPI2_HIM_IOC2SYS_DB_MASK
+
+/*
+ *Offsets for DCRData and address
+ */
+#define MPI2_DCR_DATA_OFFSET                    (0x00000038)
+#define MPI2_DCR_ADDRESS_OFFSET                 (0x0000003C)
+
+/*
+ *Offset for the Reply Free Queue
+ */
+#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET       (0x00000048)
+
+/*
+ *Defines for the Reply Descriptor Post Queue
+ */
+#define MPI2_REPLY_POST_HOST_INDEX_OFFSET       (0x0000006C)
+#define MPI2_REPLY_POST_HOST_INDEX_MASK         (0x00FFFFFF)
+#define MPI2_RPHI_MSIX_INDEX_MASK               (0xFF000000)
+#define MPI2_RPHI_MSIX_INDEX_SHIFT              (24)
+
+/*
+ *Defines for the HCBSize and address
+ */
+#define MPI2_HCB_SIZE_OFFSET                    (0x00000074)
+#define MPI2_HCB_SIZE_SIZE_MASK                 (0xFFFFF000)
+#define MPI2_HCB_SIZE_HCB_ENABLE                (0x00000001)
+
+#define MPI2_HCB_ADDRESS_LOW_OFFSET             (0x00000078)
+#define MPI2_HCB_ADDRESS_HIGH_OFFSET            (0x0000007C)
+
+/*
+ *Offsets for the Request Queue
+ */
+#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET     (0x000000C0)
+#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET    (0x000000C4)
+
+/*Hard Reset delay timings */
+#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC     (50000)
+#define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC    (255000)
+#define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC    (256000)
+
+/*****************************************************************************
+*
+*       Message Descriptors
+*
+*****************************************************************************/
+
+/*Request Descriptors */
+
+/*Default Request Descriptor */
+typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR {
+       U8 RequestFlags;        /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U16 LMID;               /*0x04 */
+       U16 DescriptorTypeDependent;    /*0x06 */
+} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+       *PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+       Mpi2DefaultRequestDescriptor_t,
+       *pMpi2DefaultRequestDescriptor_t;
+
+/*defines for the RequestFlags field */
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK               (0x0E)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET             (0x02)
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE            (0x08)
+#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR        (0x0A)
+#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO      (0x0C)
+
+#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
+
+/*High Priority Request Descriptor */
+typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
+       U8 RequestFlags;        /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U16 LMID;               /*0x04 */
+       U16 Reserved1;          /*0x06 */
+} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+       *PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+       Mpi2HighPriorityRequestDescriptor_t,
+       *pMpi2HighPriorityRequestDescriptor_t;
+
+/*SCSI IO Request Descriptor */
+typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR {
+       U8 RequestFlags;        /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U16 LMID;               /*0x04 */
+       U16 DevHandle;          /*0x06 */
+} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+       *PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+       Mpi2SCSIIORequestDescriptor_t,
+       *pMpi2SCSIIORequestDescriptor_t;
+
+/*SCSI Target Request Descriptor */
+typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR {
+       U8 RequestFlags;        /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U16 LMID;               /*0x04 */
+       U16 IoIndex;            /*0x06 */
+} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+       *PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+       Mpi2SCSITargetRequestDescriptor_t,
+       *pMpi2SCSITargetRequestDescriptor_t;
+
+/*RAID Accelerator Request Descriptor */
+typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
+       U8 RequestFlags;        /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U16 LMID;               /*0x04 */
+       U16 Reserved;           /*0x06 */
+} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+       *PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+       Mpi2RAIDAcceleratorRequestDescriptor_t,
+       *pMpi2RAIDAcceleratorRequestDescriptor_t;
+
+/*Fast Path SCSI IO Request Descriptor */
+typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR
+       MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR,
+       *PTR_MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR,
+       Mpi25FastPathSCSIIORequestDescriptor_t,
+       *pMpi25FastPathSCSIIORequestDescriptor_t;
+
+/*union of Request Descriptors */
+typedef union _MPI2_REQUEST_DESCRIPTOR_UNION {
+       MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
+       MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
+       MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
+       MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
+       MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
+       MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO;
+       U64 Words;
+} MPI2_REQUEST_DESCRIPTOR_UNION,
+       *PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
+       Mpi2RequestDescriptorUnion_t,
+       *pMpi2RequestDescriptorUnion_t;
+
+/*Reply Descriptors */
+
+/*Default Reply Descriptor */
+typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR {
+       U8 ReplyFlags;          /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 DescriptorTypeDependent1;   /*0x02 */
+       U32 DescriptorTypeDependent2;   /*0x04 */
+} MPI2_DEFAULT_REPLY_DESCRIPTOR,
+       *PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
+       Mpi2DefaultReplyDescriptor_t,
+       *pMpi2DefaultReplyDescriptor_t;
+
+/*defines for the ReplyFlags field */
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK                   (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS             (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY               (0x01)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS        (0x02)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER       (0x03)
+#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS    (0x05)
+#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS  (0x06)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED                      (0x0F)
+
+/*values for marking a reply descriptor as unused */
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK             (0xFFFFFFFF)
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK             (0xFFFFFFFF)
+
+/*Address Reply Descriptor */
+typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR {
+       U8 ReplyFlags;          /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U32 ReplyFrameAddress;  /*0x04 */
+} MPI2_ADDRESS_REPLY_DESCRIPTOR,
+       *PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
+       Mpi2AddressReplyDescriptor_t,
+       *pMpi2AddressReplyDescriptor_t;
+
+#define MPI2_ADDRESS_REPLY_SMID_INVALID                 (0x00)
+
+/*SCSI IO Success Reply Descriptor */
+typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR {
+       U8 ReplyFlags;          /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U16 TaskTag;            /*0x04 */
+       U16 Reserved1;          /*0x06 */
+} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+       *PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+       Mpi2SCSIIOSuccessReplyDescriptor_t,
+       *pMpi2SCSIIOSuccessReplyDescriptor_t;
+
+/*TargetAssist Success Reply Descriptor */
+typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR {
+       U8 ReplyFlags;          /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U8 SequenceNumber;      /*0x04 */
+       U8 Reserved1;           /*0x05 */
+       U16 IoIndex;            /*0x06 */
+} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+       *PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+       Mpi2TargetAssistSuccessReplyDescriptor_t,
+       *pMpi2TargetAssistSuccessReplyDescriptor_t;
+
+/*Target Command Buffer Reply Descriptor */
+typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR {
+       U8 ReplyFlags;          /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U8 VP_ID;               /*0x02 */
+       U8 Flags;               /*0x03 */
+       U16 InitiatorDevHandle; /*0x04 */
+       U16 IoIndex;            /*0x06 */
+} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+       *PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+       Mpi2TargetCommandBufferReplyDescriptor_t,
+       *pMpi2TargetCommandBufferReplyDescriptor_t;
+
+/*defines for Flags field */
+#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK     (0x3F)
+
+/*RAID Accelerator Success Reply Descriptor */
+typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
+       U8 ReplyFlags;          /*0x00 */
+       U8 MSIxIndex;           /*0x01 */
+       U16 SMID;               /*0x02 */
+       U32 Reserved;           /*0x04 */
+} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+       *PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+       Mpi2RAIDAcceleratorSuccessReplyDescriptor_t,
+       *pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
+
+/*Fast Path SCSI IO Success Reply Descriptor */
+typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
+       MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+       *PTR_MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+       Mpi25FastPathSCSIIOSuccessReplyDescriptor_t,
+       *pMpi25FastPathSCSIIOSuccessReplyDescriptor_t;
+
+/*union of Reply Descriptors */
+typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
+       MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
+       MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
+       MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
+       MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
+       MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
+       MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
+       MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess;
+       U64 Words;
+} MPI2_REPLY_DESCRIPTORS_UNION,
+       *PTR_MPI2_REPLY_DESCRIPTORS_UNION,
+       Mpi2ReplyDescriptorsUnion_t,
+       *pMpi2ReplyDescriptorsUnion_t;
+
+/*****************************************************************************
+*
+*       Message Functions
+*
+*****************************************************************************/
+
+#define MPI2_FUNCTION_SCSI_IO_REQUEST              (0x00)
+#define MPI2_FUNCTION_SCSI_TASK_MGMT               (0x01)
+#define MPI2_FUNCTION_IOC_INIT                      (0x02)
+#define MPI2_FUNCTION_IOC_FACTS                     (0x03)
+#define MPI2_FUNCTION_CONFIG                        (0x04)
+#define MPI2_FUNCTION_PORT_FACTS                    (0x05)
+#define MPI2_FUNCTION_PORT_ENABLE                   (0x06)
+#define MPI2_FUNCTION_EVENT_NOTIFICATION            (0x07)
+#define MPI2_FUNCTION_EVENT_ACK                     (0x08)
+#define MPI2_FUNCTION_FW_DOWNLOAD                   (0x09)
+#define MPI2_FUNCTION_TARGET_ASSIST                 (0x0B)
+#define MPI2_FUNCTION_TARGET_STATUS_SEND            (0x0C)
+#define MPI2_FUNCTION_TARGET_MODE_ABORT             (0x0D)
+#define MPI2_FUNCTION_FW_UPLOAD                     (0x12)
+#define MPI2_FUNCTION_RAID_ACTION                   (0x15)
+#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH      (0x16)
+#define MPI2_FUNCTION_TOOLBOX                       (0x17)
+#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR      (0x18)
+#define MPI2_FUNCTION_SMP_PASSTHROUGH               (0x1A)
+#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL           (0x1B)
+#define MPI2_FUNCTION_SATA_PASSTHROUGH              (0x1C)
+#define MPI2_FUNCTION_DIAG_BUFFER_POST              (0x1D)
+#define MPI2_FUNCTION_DIAG_RELEASE                  (0x1E)
+#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST      (0x24)
+#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST      (0x25)
+#define MPI2_FUNCTION_RAID_ACCELERATOR              (0x2C)
+#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION   (0x2F)
+#define MPI2_FUNCTION_PWR_MGMT_CONTROL              (0x30)
+#define MPI2_FUNCTION_SEND_HOST_MESSAGE             (0x31)
+#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC          (0xF0)
+#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC          (0xFF)
+
+/*Doorbell functions */
+#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET        (0x40)
+#define MPI2_FUNCTION_HANDSHAKE                     (0x42)
+
+/*****************************************************************************
+*
+*       IOC Status Values
+*
+*****************************************************************************/
+
+/*mask for IOCStatus status value */
+#define MPI2_IOCSTATUS_MASK                     (0x7FFF)
+
+/****************************************************************************
+* Common IOCStatus values for all replies
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SUCCESS                      (0x0000)
+#define MPI2_IOCSTATUS_INVALID_FUNCTION             (0x0001)
+#define MPI2_IOCSTATUS_BUSY                         (0x0002)
+#define MPI2_IOCSTATUS_INVALID_SGL                  (0x0003)
+#define MPI2_IOCSTATUS_INTERNAL_ERROR               (0x0004)
+#define MPI2_IOCSTATUS_INVALID_VPID                 (0x0005)
+#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES       (0x0006)
+#define MPI2_IOCSTATUS_INVALID_FIELD                (0x0007)
+#define MPI2_IOCSTATUS_INVALID_STATE                (0x0008)
+#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED       (0x0009)
+
+/****************************************************************************
+* Config IOCStatus values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION        (0x0020)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE          (0x0021)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE          (0x0022)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA          (0x0023)
+#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS           (0x0024)
+#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT           (0x0025)
+
+/****************************************************************************
+* SCSI IO Reply
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR         (0x0040)
+#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE       (0x0042)
+#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE        (0x0043)
+#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN            (0x0044)
+#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN           (0x0045)
+#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR           (0x0046)
+#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR          (0x0047)
+#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED         (0x0048)
+#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH       (0x0049)
+#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED        (0x004A)
+#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED          (0x004B)
+#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED          (0x004C)
+
+/****************************************************************************
+* For use by SCSI Initiator and SCSI Target end-to-end data protection
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR             (0x004D)
+#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR           (0x004E)
+#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR           (0x004F)
+
+/****************************************************************************
+* SCSI Target values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX      (0x0062)
+#define MPI2_IOCSTATUS_TARGET_ABORTED               (0x0063)
+#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE     (0x0064)
+#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION         (0x0065)
+#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH   (0x006A)
+#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR     (0x006D)
+#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA   (0x006E)
+#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT          (0x006F)
+#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT       (0x0070)
+#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED          (0x0071)
+
+/****************************************************************************
+* Serial Attached SCSI values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED       (0x0090)
+#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN         (0x0091)
+
+/****************************************************************************
+* Diagnostic Buffer Post / Diagnostic Release values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED          (0x00A0)
+
+/****************************************************************************
+* RAID Accelerator values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR             (0x00B0)
+
+/****************************************************************************
+* IOCStatus flag to indicate that log info is available
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE      (0x8000)
+
+/****************************************************************************
+* IOCLogInfo Types
+****************************************************************************/
+
+#define MPI2_IOCLOGINFO_TYPE_MASK               (0xF0000000)
+#define MPI2_IOCLOGINFO_TYPE_SHIFT              (28)
+#define MPI2_IOCLOGINFO_TYPE_NONE               (0x0)
+#define MPI2_IOCLOGINFO_TYPE_SCSI               (0x1)
+#define MPI2_IOCLOGINFO_TYPE_FC                 (0x2)
+#define MPI2_IOCLOGINFO_TYPE_SAS                (0x3)
+#define MPI2_IOCLOGINFO_TYPE_ISCSI              (0x4)
+#define MPI2_IOCLOGINFO_LOG_DATA_MASK           (0x0FFFFFFF)
+
+/*****************************************************************************
+*
+*       Standard Message Structures
+*
+*****************************************************************************/
+
+/****************************************************************************
+*Request Message Header for all request messages
+****************************************************************************/
+
+typedef struct _MPI2_REQUEST_HEADER {
+       U16 FunctionDependent1; /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 FunctionDependent2; /*0x04 */
+       U8 FunctionDependent3;  /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+} MPI2_REQUEST_HEADER, *PTR_MPI2_REQUEST_HEADER,
+       MPI2RequestHeader_t, *pMPI2RequestHeader_t;
+
+/****************************************************************************
+* Default Reply
+****************************************************************************/
+
+typedef struct _MPI2_DEFAULT_REPLY {
+       U16 FunctionDependent1; /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 FunctionDependent2; /*0x04 */
+       U8 FunctionDependent3;  /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+       U16 FunctionDependent5; /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_DEFAULT_REPLY, *PTR_MPI2_DEFAULT_REPLY,
+       MPI2DefaultReply_t, *pMPI2DefaultReply_t;
+
+/*common version structure/union used in messages and configuration pages */
+
+typedef struct _MPI2_VERSION_STRUCT {
+       U8 Dev;                 /*0x00 */
+       U8 Unit;                /*0x01 */
+       U8 Minor;               /*0x02 */
+       U8 Major;               /*0x03 */
+} MPI2_VERSION_STRUCT;
+
+typedef union _MPI2_VERSION_UNION {
+       MPI2_VERSION_STRUCT Struct;
+       U32 Word;
+} MPI2_VERSION_UNION;
+
+/*LUN field defines, common to many structures */
+#define MPI2_LUN_FIRST_LEVEL_ADDRESSING             (0x0000FFFF)
+#define MPI2_LUN_SECOND_LEVEL_ADDRESSING            (0xFFFF0000)
+#define MPI2_LUN_THIRD_LEVEL_ADDRESSING             (0x0000FFFF)
+#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING            (0xFFFF0000)
+#define MPI2_LUN_LEVEL_1_WORD                       (0xFF00)
+#define MPI2_LUN_LEVEL_1_DWORD                      (0x0000FF00)
+
+/*****************************************************************************
+*
+*       Fusion-MPT MPI Scatter Gather Elements
+*
+*****************************************************************************/
+
+/****************************************************************************
+* MPI Simple Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_SIMPLE32 {
+       U32 FlagsLength;
+       U32 Address;
+} MPI2_SGE_SIMPLE32, *PTR_MPI2_SGE_SIMPLE32,
+       Mpi2SGESimple32_t, *pMpi2SGESimple32_t;
+
+typedef struct _MPI2_SGE_SIMPLE64 {
+       U32 FlagsLength;
+       U64 Address;
+} MPI2_SGE_SIMPLE64, *PTR_MPI2_SGE_SIMPLE64,
+       Mpi2SGESimple64_t, *pMpi2SGESimple64_t;
+
+typedef struct _MPI2_SGE_SIMPLE_UNION {
+       U32 FlagsLength;
+       union {
+               U32 Address32;
+               U64 Address64;
+       } u;
+} MPI2_SGE_SIMPLE_UNION,
+       *PTR_MPI2_SGE_SIMPLE_UNION,
+       Mpi2SGESimpleUnion_t,
+       *pMpi2SGESimpleUnion_t;
+
+/****************************************************************************
+* MPI Chain Element structures - for MPI v2.0 products only
+****************************************************************************/
+
+typedef struct _MPI2_SGE_CHAIN32 {
+       U16 Length;
+       U8 NextChainOffset;
+       U8 Flags;
+       U32 Address;
+} MPI2_SGE_CHAIN32, *PTR_MPI2_SGE_CHAIN32,
+       Mpi2SGEChain32_t, *pMpi2SGEChain32_t;
+
+typedef struct _MPI2_SGE_CHAIN64 {
+       U16 Length;
+       U8 NextChainOffset;
+       U8 Flags;
+       U64 Address;
+} MPI2_SGE_CHAIN64, *PTR_MPI2_SGE_CHAIN64,
+       Mpi2SGEChain64_t, *pMpi2SGEChain64_t;
+
+typedef struct _MPI2_SGE_CHAIN_UNION {
+       U16 Length;
+       U8 NextChainOffset;
+       U8 Flags;
+       union {
+               U32 Address32;
+               U64 Address64;
+       } u;
+} MPI2_SGE_CHAIN_UNION,
+       *PTR_MPI2_SGE_CHAIN_UNION,
+       Mpi2SGEChainUnion_t,
+       *pMpi2SGEChainUnion_t;
+
+/****************************************************************************
+* MPI Transaction Context Element structures - for MPI v2.0 products only
+****************************************************************************/
+
+typedef struct _MPI2_SGE_TRANSACTION32 {
+       U8 Reserved;
+       U8 ContextSize;
+       U8 DetailsLength;
+       U8 Flags;
+       U32 TransactionContext[1];
+       U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION32,
+       *PTR_MPI2_SGE_TRANSACTION32,
+       Mpi2SGETransaction32_t,
+       *pMpi2SGETransaction32_t;
+
+typedef struct _MPI2_SGE_TRANSACTION64 {
+       U8 Reserved;
+       U8 ContextSize;
+       U8 DetailsLength;
+       U8 Flags;
+       U32 TransactionContext[2];
+       U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION64,
+       *PTR_MPI2_SGE_TRANSACTION64,
+       Mpi2SGETransaction64_t,
+       *pMpi2SGETransaction64_t;
+
+typedef struct _MPI2_SGE_TRANSACTION96 {
+       U8 Reserved;
+       U8 ContextSize;
+       U8 DetailsLength;
+       U8 Flags;
+       U32 TransactionContext[3];
+       U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION96, *PTR_MPI2_SGE_TRANSACTION96,
+       Mpi2SGETransaction96_t, *pMpi2SGETransaction96_t;
+
+typedef struct _MPI2_SGE_TRANSACTION128 {
+       U8 Reserved;
+       U8 ContextSize;
+       U8 DetailsLength;
+       U8 Flags;
+       U32 TransactionContext[4];
+       U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION128, *PTR_MPI2_SGE_TRANSACTION128,
+       Mpi2SGETransaction_t128, *pMpi2SGETransaction_t128;
+
+typedef struct _MPI2_SGE_TRANSACTION_UNION {
+       U8 Reserved;
+       U8 ContextSize;
+       U8 DetailsLength;
+       U8 Flags;
+       union {
+               U32 TransactionContext32[1];
+               U32 TransactionContext64[2];
+               U32 TransactionContext96[3];
+               U32 TransactionContext128[4];
+       } u;
+       U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION_UNION,
+       *PTR_MPI2_SGE_TRANSACTION_UNION,
+       Mpi2SGETransactionUnion_t,
+       *pMpi2SGETransactionUnion_t;
+
+/****************************************************************************
+* MPI SGE union for IO SGL's - for MPI v2.0 products only
+****************************************************************************/
+
+typedef struct _MPI2_MPI_SGE_IO_UNION {
+       union {
+               MPI2_SGE_SIMPLE_UNION Simple;
+               MPI2_SGE_CHAIN_UNION Chain;
+       } u;
+} MPI2_MPI_SGE_IO_UNION, *PTR_MPI2_MPI_SGE_IO_UNION,
+       Mpi2MpiSGEIOUnion_t, *pMpi2MpiSGEIOUnion_t;
+
+/****************************************************************************
+* MPI SGE union for SGL's with Simple and Transaction elements - for MPI v2.0 products only
+****************************************************************************/
+
+typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION {
+       union {
+               MPI2_SGE_SIMPLE_UNION Simple;
+               MPI2_SGE_TRANSACTION_UNION Transaction;
+       } u;
+} MPI2_SGE_TRANS_SIMPLE_UNION,
+       *PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
+       Mpi2SGETransSimpleUnion_t,
+       *pMpi2SGETransSimpleUnion_t;
+
+/****************************************************************************
+* All MPI SGE types union
+****************************************************************************/
+
+typedef struct _MPI2_MPI_SGE_UNION {
+       union {
+               MPI2_SGE_SIMPLE_UNION Simple;
+               MPI2_SGE_CHAIN_UNION Chain;
+               MPI2_SGE_TRANSACTION_UNION Transaction;
+       } u;
+} MPI2_MPI_SGE_UNION, *PTR_MPI2_MPI_SGE_UNION,
+       Mpi2MpiSgeUnion_t, *pMpi2MpiSgeUnion_t;
+
+/****************************************************************************
+* MPI SGE field definition and masks
+****************************************************************************/
+
+/*Flags field bit definitions */
+
+#define MPI2_SGE_FLAGS_LAST_ELEMENT             (0x80)
+#define MPI2_SGE_FLAGS_END_OF_BUFFER            (0x40)
+#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK        (0x30)
+#define MPI2_SGE_FLAGS_LOCAL_ADDRESS            (0x08)
+#define MPI2_SGE_FLAGS_DIRECTION                (0x04)
+#define MPI2_SGE_FLAGS_ADDRESS_SIZE             (0x02)
+#define MPI2_SGE_FLAGS_END_OF_LIST              (0x01)
+
+#define MPI2_SGE_FLAGS_SHIFT                    (24)
+
+#define MPI2_SGE_LENGTH_MASK                    (0x00FFFFFF)
+#define MPI2_SGE_CHAIN_LENGTH_MASK              (0x0000FFFF)
+
+/*Element Type */
+
+#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT      (0x00)
+#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT           (0x10)
+#define MPI2_SGE_FLAGS_CHAIN_ELEMENT            (0x30)
+#define MPI2_SGE_FLAGS_ELEMENT_MASK             (0x30)
+
+/*Address location */
+
+#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS           (0x00)
+
+/*Direction */
+
+#define MPI2_SGE_FLAGS_IOC_TO_HOST              (0x00)
+#define MPI2_SGE_FLAGS_HOST_TO_IOC              (0x04)
+
+#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST)
+#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC)
+
+/*Address Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING        (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
+
+/*Context Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_CONTEXT           (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_CONTEXT           (0x02)
+#define MPI2_SGE_FLAGS_96_BIT_CONTEXT           (0x04)
+#define MPI2_SGE_FLAGS_128_BIT_CONTEXT          (0x06)
+
+#define MPI2_SGE_CHAIN_OFFSET_MASK              (0x00FF0000)
+#define MPI2_SGE_CHAIN_OFFSET_SHIFT             (16)
+
+/****************************************************************************
+* MPI SGE operation Macros
+****************************************************************************/
+
+/*SIMPLE FlagsLength manipulations... */
+#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
+#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> \
+                                       MPI2_SGE_FLAGS_SHIFT)
+#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK)
+#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
+
+#define MPI2_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_SGE_SET_FLAGS(f) | \
+                                       MPI2_SGE_LENGTH(l))
+
+#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
+#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength)
+#define MPI2_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \
+                                       MPI2_SGE_SET_FLAGS_LENGTH(f, l))
+
+/*CAUTION - The following are READ-MODIFY-WRITE! */
+#define MPI2_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \
+                                       MPI2_SGE_SET_FLAGS(f))
+#define MPI2_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \
+                                       MPI2_SGE_LENGTH(l))
+
+#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> \
+                                       MPI2_SGE_CHAIN_OFFSET_SHIFT)
+
+/*****************************************************************************
+*
+*       Fusion-MPT IEEE Scatter Gather Elements
+*
+*****************************************************************************/
+
+/****************************************************************************
+* IEEE Simple Element structures
+****************************************************************************/
+
+/*MPI2_IEEE_SGE_SIMPLE32 is for MPI v2.0 products only */
+typedef struct _MPI2_IEEE_SGE_SIMPLE32 {
+       U32 Address;
+       U32 FlagsLength;
+} MPI2_IEEE_SGE_SIMPLE32, *PTR_MPI2_IEEE_SGE_SIMPLE32,
+       Mpi2IeeeSgeSimple32_t, *pMpi2IeeeSgeSimple32_t;
+
+typedef struct _MPI2_IEEE_SGE_SIMPLE64 {
+       U64 Address;
+       U32 Length;
+       U16 Reserved1;
+       U8 Reserved2;
+       U8 Flags;
+} MPI2_IEEE_SGE_SIMPLE64, *PTR_MPI2_IEEE_SGE_SIMPLE64,
+       Mpi2IeeeSgeSimple64_t, *pMpi2IeeeSgeSimple64_t;
+
+typedef union _MPI2_IEEE_SGE_SIMPLE_UNION {
+       MPI2_IEEE_SGE_SIMPLE32 Simple32;
+       MPI2_IEEE_SGE_SIMPLE64 Simple64;
+} MPI2_IEEE_SGE_SIMPLE_UNION,
+       *PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
+       Mpi2IeeeSgeSimpleUnion_t,
+       *pMpi2IeeeSgeSimpleUnion_t;
+
+/****************************************************************************
+* IEEE Chain Element structures
+****************************************************************************/
+
+/*MPI2_IEEE_SGE_CHAIN32 is for MPI v2.0 products only */
+typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
+
+/*MPI2_IEEE_SGE_CHAIN64 is for MPI v2.0 products only */
+typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
+
+typedef union _MPI2_IEEE_SGE_CHAIN_UNION {
+       MPI2_IEEE_SGE_CHAIN32 Chain32;
+       MPI2_IEEE_SGE_CHAIN64 Chain64;
+} MPI2_IEEE_SGE_CHAIN_UNION,
+       *PTR_MPI2_IEEE_SGE_CHAIN_UNION,
+       Mpi2IeeeSgeChainUnion_t,
+       *pMpi2IeeeSgeChainUnion_t;
+
+/*MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */
+typedef struct _MPI25_IEEE_SGE_CHAIN64 {
+       U64 Address;
+       U32 Length;
+       U16 Reserved1;
+       U8 NextChainOffset;
+       U8 Flags;
+} MPI25_IEEE_SGE_CHAIN64,
+       *PTR_MPI25_IEEE_SGE_CHAIN64,
+       Mpi25IeeeSgeChain64_t,
+       *pMpi25IeeeSgeChain64_t;
+
+/****************************************************************************
+* All IEEE SGE types union
+****************************************************************************/
+
+/*MPI2_IEEE_SGE_UNION is for MPI v2.0 products only */
+typedef struct _MPI2_IEEE_SGE_UNION {
+       union {
+               MPI2_IEEE_SGE_SIMPLE_UNION Simple;
+               MPI2_IEEE_SGE_CHAIN_UNION Chain;
+       } u;
+} MPI2_IEEE_SGE_UNION, *PTR_MPI2_IEEE_SGE_UNION,
+       Mpi2IeeeSgeUnion_t, *pMpi2IeeeSgeUnion_t;
+
+/****************************************************************************
+* IEEE SGE union for IO SGL's
+****************************************************************************/
+
+typedef union _MPI25_SGE_IO_UNION {
+       MPI2_IEEE_SGE_SIMPLE64 IeeeSimple;
+       MPI25_IEEE_SGE_CHAIN64 IeeeChain;
+} MPI25_SGE_IO_UNION, *PTR_MPI25_SGE_IO_UNION,
+       Mpi25SGEIOUnion_t, *pMpi25SGEIOUnion_t;
+
+/****************************************************************************
+* IEEE SGE field definitions and masks
+****************************************************************************/
+
+/*Flags field bit definitions */
+
+#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK   (0x80)
+#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST        (0x40)
+
+#define MPI2_IEEE32_SGE_FLAGS_SHIFT             (24)
+
+#define MPI2_IEEE32_SGE_LENGTH_MASK             (0x00FFFFFF)
+
+/*Element Type */
+
+#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT      (0x00)
+#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT       (0x80)
+
+/*Data Location Address Space */
+
+#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK           (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR         (0x00)
+#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR   (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \
+        (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR)
+
+/****************************************************************************
+* IEEE SGE operation Macros
+****************************************************************************/
+
+/*SIMPLE FlagsLength manipulations... */
+#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
+#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) \
+                                >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
+#define MPI2_IEEE32_SGE_LENGTH(f)    ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
+
+#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) |\
+                                                MPI2_IEEE32_SGE_LENGTH(l))
+
+#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) \
+                       MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
+#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) \
+                       MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
+#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \
+                                       MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l))
+
+/*CAUTION - The following are READ-MODIFY-WRITE! */
+#define MPI2_IEEE32_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \
+                                       MPI2_IEEE32_SGE_SET_FLAGS(f))
+#define MPI2_IEEE32_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \
+                                       MPI2_IEEE32_SGE_LENGTH(l))
+
+/*****************************************************************************
+*
+*       Fusion-MPT MPI/IEEE Scatter Gather Unions
+*
+*****************************************************************************/
+
+typedef union _MPI2_SIMPLE_SGE_UNION {
+       MPI2_SGE_SIMPLE_UNION MpiSimple;
+       MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+} MPI2_SIMPLE_SGE_UNION, *PTR_MPI2_SIMPLE_SGE_UNION,
+       Mpi2SimpleSgeUntion_t, *pMpi2SimpleSgeUntion_t;
+
+typedef union _MPI2_SGE_IO_UNION {
+       MPI2_SGE_SIMPLE_UNION MpiSimple;
+       MPI2_SGE_CHAIN_UNION MpiChain;
+       MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+       MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
+} MPI2_SGE_IO_UNION, *PTR_MPI2_SGE_IO_UNION,
+       Mpi2SGEIOUnion_t, *pMpi2SGEIOUnion_t;
+
+/****************************************************************************
+*
+* Values for SGLFlags field, used in many request messages with an SGL
+*
+****************************************************************************/
+
+/*values for MPI SGL Data Location Address Space subfield */
+#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK            (0x0C)
+#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE          (0x00)
+#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE          (0x04)
+#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE          (0x08)
+#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE       (0x0C)
+/*values for SGL Type subfield */
+#define MPI2_SGLFLAGS_SGL_TYPE_MASK                 (0x03)
+#define MPI2_SGLFLAGS_SGL_TYPE_MPI                  (0x00)
+#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32               (0x01)
+#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64               (0x02)
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
new file mode 100644 (file)
index 0000000..d8b2c3e
--- /dev/null
@@ -0,0 +1,3323 @@
+/*
+ * Copyright (c) 2000-2011 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2_cnfg.h
+ *         Title:  MPI Configuration messages and pages
+ * Creation Date:  November 10, 2006
+ *
+ *   mpi2_cnfg.h Version:  02.00.22
+ *
+ * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
+ *       prefix are for use only on MPI v2.5 products, and must not be used
+ *       with MPI v2.0 products. Unless otherwise noted, names beginning with
+ *       MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-04-07  02.00.01  Added defines for SAS IO Unit Page 2 PhyFlags.
+ *                     Added Manufacturing Page 11.
+ *                     Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
+ *                     define.
+ * 06-26-07  02.00.02  Adding generic structure for product-specific
+ *                     Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
+ *                     Rework of BIOS Page 2 configuration page.
+ *                     Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
+ *                     forms.
+ *                     Added configuration pages IOC Page 8 and Driver
+ *                     Persistent Mapping Page 0.
+ * 08-31-07  02.00.03  Modified configuration pages dealing with Integrated
+ *                     RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
+ *                     RAID Physical Disk Pages 0 and 1, RAID Configuration
+ *                     Page 0).
+ *                     Added new value for AccessStatus field of SAS Device
+ *                     Page 0 (_SATA_NEEDS_INITIALIZATION).
+ * 10-31-07  02.00.04  Added missing SEPDevHandle field to
+ *                     MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
+ * 12-18-07  02.00.05  Modified IO Unit Page 0 to use 32-bit version fields for
+ *                     NVDATA.
+ *                     Modified IOC Page 7 to use masks and added field for
+ *                     SASBroadcastPrimitiveMasks.
+ *                     Added MPI2_CONFIG_PAGE_BIOS_4.
+ *                     Added MPI2_CONFIG_PAGE_LOG_0.
+ * 02-29-08  02.00.06  Modified various names to make them 32-character unique.
+ *                     Added SAS Device IDs.
+ *                     Updated Integrated RAID configuration pages including
+ *                     Manufacturing Page 4, IOC Page 6, and RAID Configuration
+ *                     Page 0.
+ * 05-21-08  02.00.07  Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
+ *                     Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
+ *                     Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
+ *                     Added missing MaxNumRoutedSasAddresses field to
+ *                     MPI2_CONFIG_PAGE_EXPANDER_0.
+ *                     Added SAS Port Page 0.
+ *                     Modified structure layout for
+ *                     MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
+ * 06-27-08  02.00.08  Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
+ *                     MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
+ * 10-02-08  02.00.09  Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
+ *                     to 0x000000FF.
+ *                     Added two new values for the Physical Disk Coercion Size
+ *                     bits in the Flags field of Manufacturing Page 4.
+ *                     Added product-specific Manufacturing pages 16 to 31.
+ *                     Modified Flags bits for controlling write cache on SATA
+ *                     drives in IO Unit Page 1.
+ *                     Added new bit to AdditionalControlFlags of SAS IO Unit
+ *                     Page 1 to control Invalid Topology Correction.
+ *                     Added additional defines for RAID Volume Page 0
+ *                     VolumeStatusFlags field.
+ *                     Modified meaning of RAID Volume Page 0 VolumeSettings
+ *                     define for auto-configure of hot-swap drives.
+ *                     Added SupportedPhysDisks field to RAID Volume Page 1 and
+ *                     added related defines.
+ *                     Added PhysDiskAttributes field (and related defines) to
+ *                     RAID Physical Disk Page 0.
+ *                     Added MPI2_SAS_PHYINFO_PHY_VACANT define.
+ *                     Added three new DiscoveryStatus bits for SAS IO Unit
+ *                     Page 0 and SAS Expander Page 0.
+ *                     Removed multiplexing information from SAS IO Unit pages.
+ *                     Added BootDeviceWaitTime field to SAS IO Unit Page 4.
+ *                     Removed Zone Address Resolved bit from PhyInfo and from
+ *                     Expander Page 0 Flags field.
+ *                     Added two new AccessStatus values to SAS Device Page 0
+ *                     for indicating routing problems. Added 3 reserved words
+ *                     to this page.
+ * 01-19-09  02.00.10  Fixed defines for GPIOVal field of IO Unit Page 3.
+ *                     Inserted missing reserved field into structure for IOC
+ *                     Page 6.
+ *                     Added more pending task bits to RAID Volume Page 0
+ *                     VolumeStatusFlags defines.
+ *                     Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
+ *                     Added a new DiscoveryStatus bit for SAS IO Unit Page 0
+ *                     and SAS Expander Page 0 to flag a downstream initiator
+ *                     when in simplified routing mode.
+ *                     Removed SATA Init Failure defines for DiscoveryStatus
+ *                     fields of SAS IO Unit Page 0 and SAS Expander Page 0.
+ *                     Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
+ *                     Added PortGroups, DmaGroup, and ControlGroup fields to
+ *                     SAS Device Page 0.
+ * 05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
+ *                     Unit Page 6.
+ *                     Added expander reduced functionality data to SAS
+ *                     Expander Page 0.
+ *                     Added SAS PHY Page 2 and SAS PHY Page 3.
+ * 07-30-09  02.00.12  Added IO Unit Page 7.
+ *                     Added new device ids.
+ *                     Added SAS IO Unit Page 5.
+ *                     Added partial and slumber power management capable flags
+ *                     to SAS Device Page 0 Flags field.
+ *                     Added PhyInfo defines for power condition.
+ *                     Added Ethernet configuration pages.
+ * 10-28-09  02.00.13  Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
+ *                     Added SAS PHY Page 4 structure and defines.
+ * 02-10-10  02.00.14  Modified the comments for the configuration page
+ *                     structures that contain an array of data. The host
+ *                     should use the "count" field in the page data (e.g. the
+ *                     NumPhys field) to determine the number of valid elements
+ *                     in the array.
+ *                     Added/modified some MPI2_MFGPAGE_DEVID_SAS defines.
+ *                     Added PowerManagementCapabilities to IO Unit Page 7.
+ *                     Added PortWidthModGroup field to
+ *                     MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS.
+ *                     Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
+ *                     Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
+ *                     Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
+ * 05-12-10  02.00.15  Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
+ *                     define.
+ *                     Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
+ *                     Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
+ * 08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
+ *                     defines.
+ * 11-10-10  02.00.17  Added ReceptacleID field (replacing Reserved1) to
+ *                     MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ *                     the Pinout field.
+ *                     Added BoardTemperature and BoardTemperatureUnits fields
+ *                     to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ *                     Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ *                     and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
+ * 02-23-11  02.00.18  Added ProxyVF_ID field to MPI2_CONFIG_REQUEST.
+ *                     Added IO Unit Page 8, IO Unit Page 9,
+ *                     and IO Unit Page 10.
+ *                     Added SASNotifyPrimitiveMasks field to
+ *                     MPI2_CONFIG_PAGE_IOC_7.
+ * 03-09-11  02.00.19  Fixed IO Unit Page 10 (to match the spec).
+ * 05-25-11  02.00.20  Cleaned up a few comments.
+ * 08-24-11  02.00.21  Marked the IO Unit Page 7 PowerManagementCapabilities
+ *                     for PCIe link as obsolete.
+ *                     Added SpinupFlags field containing a Disable Spin-up bit
+ *                     to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of SAS IO
+ *                     Unit Page 4.
+ * 11-18-11  02.00.22  Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT.
+ *                     Added UEFIVersion field to BIOS Page 1 and defined new
+ *                     BiosOptions bits.
+ *                     Incorporating additions for MPI v2.5.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_CNFG_H
+#define MPI2_CNFG_H
+
+/*****************************************************************************
+*  Configuration Page Header and defines
+*****************************************************************************/
+
+/*Config Page Header */
+typedef struct _MPI2_CONFIG_PAGE_HEADER {
+       U8                 PageVersion;                /*0x00 */
+       U8                 PageLength;                 /*0x01 */
+       U8                 PageNumber;                 /*0x02 */
+       U8                 PageType;                   /*0x03 */
+} MPI2_CONFIG_PAGE_HEADER, *PTR_MPI2_CONFIG_PAGE_HEADER,
+       Mpi2ConfigPageHeader_t, *pMpi2ConfigPageHeader_t;
+
+typedef union _MPI2_CONFIG_PAGE_HEADER_UNION {
+       MPI2_CONFIG_PAGE_HEADER  Struct;
+       U8                       Bytes[4];
+       U16                      Word16[2];
+       U32                      Word32;
+} MPI2_CONFIG_PAGE_HEADER_UNION, *PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
+       Mpi2ConfigPageHeaderUnion, *pMpi2ConfigPageHeaderUnion;
+
+/*Extended Config Page Header */
+typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER {
+       U8                  PageVersion;                /*0x00 */
+       U8                  Reserved1;                  /*0x01 */
+       U8                  PageNumber;                 /*0x02 */
+       U8                  PageType;                   /*0x03 */
+       U16                 ExtPageLength;              /*0x04 */
+       U8                  ExtPageType;                /*0x06 */
+       U8                  Reserved2;                  /*0x07 */
+} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
+       *PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
+       Mpi2ConfigExtendedPageHeader_t,
+       *pMpi2ConfigExtendedPageHeader_t;
+
+typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION {
+       MPI2_CONFIG_PAGE_HEADER          Struct;
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
+       U8                               Bytes[8];
+       U16                              Word16[4];
+       U32                              Word32[2];
+} MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
+       *PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
+       Mpi2ConfigPageExtendedHeaderUnion,
+       *pMpi2ConfigPageExtendedHeaderUnion;
+
+
+/*PageType field values */
+#define MPI2_CONFIG_PAGEATTR_READ_ONLY              (0x00)
+#define MPI2_CONFIG_PAGEATTR_CHANGEABLE             (0x10)
+#define MPI2_CONFIG_PAGEATTR_PERSISTENT             (0x20)
+#define MPI2_CONFIG_PAGEATTR_MASK                   (0xF0)
+
+#define MPI2_CONFIG_PAGETYPE_IO_UNIT                (0x00)
+#define MPI2_CONFIG_PAGETYPE_IOC                    (0x01)
+#define MPI2_CONFIG_PAGETYPE_BIOS                   (0x02)
+#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME            (0x08)
+#define MPI2_CONFIG_PAGETYPE_MANUFACTURING          (0x09)
+#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK          (0x0A)
+#define MPI2_CONFIG_PAGETYPE_EXTENDED               (0x0F)
+#define MPI2_CONFIG_PAGETYPE_MASK                   (0x0F)
+
+#define MPI2_CONFIG_TYPENUM_MASK                    (0x0FFF)
+
+
+/*ExtPageType field values */
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT         (0x10)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER        (0x11)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE          (0x12)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY             (0x13)
+#define MPI2_CONFIG_EXTPAGETYPE_LOG                 (0x14)
+#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE           (0x15)
+#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG         (0x16)
+#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING      (0x17)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT            (0x18)
+#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET            (0x19)
+#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING   (0x1A)
+
+
+/*****************************************************************************
+*  PageAddress defines
+*****************************************************************************/
+
+/*RAID Volume PageAddress format */
+#define MPI2_RAID_VOLUME_PGAD_FORM_MASK             (0xF0000000)
+#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE  (0x00000000)
+#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE           (0x10000000)
+
+#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK           (0x0000FFFF)
+
+
+/*RAID Physical Disk PageAddress format */
+#define MPI2_PHYSDISK_PGAD_FORM_MASK                    (0xF0000000)
+#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM    (0x00000000)
+#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM             (0x10000000)
+#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE               (0x20000000)
+
+#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK             (0x000000FF)
+#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK               (0x0000FFFF)
+
+
+/*SAS Expander PageAddress format */
+#define MPI2_SAS_EXPAND_PGAD_FORM_MASK              (0xF0000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL     (0x00000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM      (0x10000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL              (0x20000000)
+
+#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK            (0x0000FFFF)
+#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK            (0x00FF0000)
+#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT           (16)
+
+
+/*SAS Device PageAddress format */
+#define MPI2_SAS_DEVICE_PGAD_FORM_MASK              (0xF0000000)
+#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE   (0x00000000)
+#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE            (0x20000000)
+
+#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK            (0x0000FFFF)
+
+
+/*SAS PHY PageAddress format */
+#define MPI2_SAS_PHY_PGAD_FORM_MASK                 (0xF0000000)
+#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER           (0x00000000)
+#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX        (0x10000000)
+
+#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK           (0x000000FF)
+#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK        (0x0000FFFF)
+
+
+/*SAS Port PageAddress format */
+#define MPI2_SASPORT_PGAD_FORM_MASK                 (0xF0000000)
+#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT        (0x00000000)
+#define MPI2_SASPORT_PGAD_FORM_PORT_NUM             (0x10000000)
+
+#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK           (0x00000FFF)
+
+
+/*SAS Enclosure PageAddress format */
+#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK              (0xF0000000)
+#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE   (0x00000000)
+#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE            (0x10000000)
+
+#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK            (0x0000FFFF)
+
+
+/*RAID Configuration PageAddress format */
+#define MPI2_RAID_PGAD_FORM_MASK                    (0xF0000000)
+#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM      (0x00000000)
+#define MPI2_RAID_PGAD_FORM_CONFIGNUM               (0x10000000)
+#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG           (0x20000000)
+
+#define MPI2_RAID_PGAD_CONFIGNUM_MASK               (0x000000FF)
+
+
+/*Driver Persistent Mapping PageAddress format */
+#define MPI2_DPM_PGAD_FORM_MASK                     (0xF0000000)
+#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE              (0x00000000)
+
+#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK              (0x0FFF0000)
+#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT             (16)
+#define MPI2_DPM_PGAD_START_ENTRY_MASK              (0x0000FFFF)
+
+
+/*Ethernet PageAddress format */
+#define MPI2_ETHERNET_PGAD_FORM_MASK                (0xF0000000)
+#define MPI2_ETHERNET_PGAD_FORM_IF_NUM              (0x00000000)
+
+#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK           (0x000000FF)
+
+
+
+/****************************************************************************
+*  Configuration messages
+****************************************************************************/
+
+/*Configuration Request Message */
+typedef struct _MPI2_CONFIG_REQUEST {
+       U8                      Action;                     /*0x00 */
+       U8                      SGLFlags;                   /*0x01 */
+       U8                      ChainOffset;                /*0x02 */
+       U8                      Function;                   /*0x03 */
+       U16                     ExtPageLength;              /*0x04 */
+       U8                      ExtPageType;                /*0x06 */
+       U8                      MsgFlags;                   /*0x07 */
+       U8                      VP_ID;                      /*0x08 */
+       U8                      VF_ID;                      /*0x09 */
+       U16                     Reserved1;                  /*0x0A */
+       U8                      Reserved2;                  /*0x0C */
+       U8                      ProxyVF_ID;                 /*0x0D */
+       U16                     Reserved4;                  /*0x0E */
+       U32                     Reserved3;                  /*0x10 */
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x14 */
+       U32                     PageAddress;                /*0x18 */
+       MPI2_SGE_IO_UNION       PageBufferSGE;              /*0x1C */
+} MPI2_CONFIG_REQUEST, *PTR_MPI2_CONFIG_REQUEST,
+       Mpi2ConfigRequest_t, *pMpi2ConfigRequest_t;
+
+/*values for the Action field */
+#define MPI2_CONFIG_ACTION_PAGE_HEADER              (0x00)
+#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT        (0x01)
+#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT       (0x02)
+#define MPI2_CONFIG_ACTION_PAGE_DEFAULT             (0x03)
+#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM         (0x04)
+#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT        (0x05)
+#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM          (0x06)
+#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE      (0x07)
+
+/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+/*Config Reply Message */
+typedef struct _MPI2_CONFIG_REPLY {
+       U8                      Action;                     /*0x00 */
+       U8                      SGLFlags;                   /*0x01 */
+       U8                      MsgLength;                  /*0x02 */
+       U8                      Function;                   /*0x03 */
+       U16                     ExtPageLength;              /*0x04 */
+       U8                      ExtPageType;                /*0x06 */
+       U8                      MsgFlags;                   /*0x07 */
+       U8                      VP_ID;                      /*0x08 */
+       U8                      VF_ID;                      /*0x09 */
+       U16                     Reserved1;                  /*0x0A */
+       U16                     Reserved2;                  /*0x0C */
+       U16                     IOCStatus;                  /*0x0E */
+       U32                     IOCLogInfo;                 /*0x10 */
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x14 */
+} MPI2_CONFIG_REPLY, *PTR_MPI2_CONFIG_REPLY,
+       Mpi2ConfigReply_t, *pMpi2ConfigReply_t;
+
+
+
+/*****************************************************************************
+*
+*              C o n f i g u r a t i o n    P a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************
+*  Manufacturing Config pages
+****************************************************************************/
+
+#define MPI2_MFGPAGE_VENDORID_LSI                   (0x1000)
+
+/*MPI v2.0 SAS products */
+#define MPI2_MFGPAGE_DEVID_SAS2004                  (0x0070)
+#define MPI2_MFGPAGE_DEVID_SAS2008                  (0x0072)
+#define MPI2_MFGPAGE_DEVID_SAS2108_1                (0x0074)
+#define MPI2_MFGPAGE_DEVID_SAS2108_2                (0x0076)
+#define MPI2_MFGPAGE_DEVID_SAS2108_3                (0x0077)
+#define MPI2_MFGPAGE_DEVID_SAS2116_1                (0x0064)
+#define MPI2_MFGPAGE_DEVID_SAS2116_2                (0x0065)
+
+#define MPI2_MFGPAGE_DEVID_SSS6200                  (0x007E)
+
+#define MPI2_MFGPAGE_DEVID_SAS2208_1                (0x0080)
+#define MPI2_MFGPAGE_DEVID_SAS2208_2                (0x0081)
+#define MPI2_MFGPAGE_DEVID_SAS2208_3                (0x0082)
+#define MPI2_MFGPAGE_DEVID_SAS2208_4                (0x0083)
+#define MPI2_MFGPAGE_DEVID_SAS2208_5                (0x0084)
+#define MPI2_MFGPAGE_DEVID_SAS2208_6                (0x0085)
+#define MPI2_MFGPAGE_DEVID_SAS2308_1                (0x0086)
+#define MPI2_MFGPAGE_DEVID_SAS2308_2                (0x0087)
+#define MPI2_MFGPAGE_DEVID_SAS2308_3                (0x006E)
+
+/*MPI v2.5 SAS products */
+#define MPI25_MFGPAGE_DEVID_SAS3004                 (0x0096)
+#define MPI25_MFGPAGE_DEVID_SAS3008                 (0x0097)
+#define MPI25_MFGPAGE_DEVID_SAS3108_1               (0x0090)
+#define MPI25_MFGPAGE_DEVID_SAS3108_2               (0x0091)
+#define MPI25_MFGPAGE_DEVID_SAS3108_5               (0x0094)
+#define MPI25_MFGPAGE_DEVID_SAS3108_6               (0x0095)
+
+
+
+
+/*Manufacturing Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_0 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U8                      ChipName[16];               /*0x04 */
+       U8                      ChipRevision[8];            /*0x14 */
+       U8                      BoardName[16];              /*0x1C */
+       U8                      BoardAssembly[16];          /*0x2C */
+       U8                      BoardTracerNumber[16];      /*0x3C */
+} MPI2_CONFIG_PAGE_MAN_0,
+       *PTR_MPI2_CONFIG_PAGE_MAN_0,
+       Mpi2ManufacturingPage0_t,
+       *pMpi2ManufacturingPage0_t;
+
+#define MPI2_MANUFACTURING0_PAGEVERSION                (0x00)
+
+
+/*Manufacturing Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_1 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U8                      VPD[256];                   /*0x04 */
+} MPI2_CONFIG_PAGE_MAN_1,
+       *PTR_MPI2_CONFIG_PAGE_MAN_1,
+       Mpi2ManufacturingPage1_t,
+       *pMpi2ManufacturingPage1_t;
+
+#define MPI2_MANUFACTURING1_PAGEVERSION                (0x00)
+
+
+typedef struct _MPI2_CHIP_REVISION_ID {
+       U16 DeviceID;                                       /*0x00 */
+       U8  PCIRevisionID;                                  /*0x02 */
+       U8  Reserved;                                       /*0x03 */
+} MPI2_CHIP_REVISION_ID, *PTR_MPI2_CHIP_REVISION_ID,
+       Mpi2ChipRevisionId_t, *pMpi2ChipRevisionId_t;
+
+
+/*Manufacturing Page 2 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
+#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS   (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_2 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       MPI2_CHIP_REVISION_ID   ChipId;                     /*0x04 */
+       U32
+               HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/*0x08 */
+} MPI2_CONFIG_PAGE_MAN_2,
+       *PTR_MPI2_CONFIG_PAGE_MAN_2,
+       Mpi2ManufacturingPage2_t,
+       *pMpi2ManufacturingPage2_t;
+
+#define MPI2_MANUFACTURING2_PAGEVERSION                 (0x00)
+
+
+/*Manufacturing Page 3 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
+#define MPI2_MAN_PAGE_3_INFO_WORDS          (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_3 {
+       MPI2_CONFIG_PAGE_HEADER             Header;         /*0x00 */
+       MPI2_CHIP_REVISION_ID               ChipId;         /*0x04 */
+       U32
+               Info[MPI2_MAN_PAGE_3_INFO_WORDS];/*0x08 */
+} MPI2_CONFIG_PAGE_MAN_3,
+       *PTR_MPI2_CONFIG_PAGE_MAN_3,
+       Mpi2ManufacturingPage3_t,
+       *pMpi2ManufacturingPage3_t;
+
+#define MPI2_MANUFACTURING3_PAGEVERSION                 (0x00)
+
+
+/*Manufacturing Page 4 */
+
+typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS {
+       U8                          PowerSaveFlags;                 /*0x00 */
+       U8                          InternalOperationsSleepTime;    /*0x01 */
+       U8                          InternalOperationsRunTime;      /*0x02 */
+       U8                          HostIdleTime;                   /*0x03 */
+} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
+       *PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
+       Mpi2ManPage4PwrSaveSettings_t,
+       *pMpi2ManPage4PwrSaveSettings_t;
+
+/*defines for the PowerSaveFlags field */
+#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE               (0x03)
+#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED           (0x00)
+#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE             (0x01)
+#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE               (0x02)
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_4 {
+       MPI2_CONFIG_PAGE_HEADER             Header;                 /*0x00 */
+       U32                                 Reserved1;              /*0x04 */
+       U32                                 Flags;                  /*0x08 */
+       U8                                  InquirySize;            /*0x0C */
+       U8                                  Reserved2;              /*0x0D */
+       U16                                 Reserved3;              /*0x0E */
+       U8                                  InquiryData[56];        /*0x10 */
+       U32                                 RAID0VolumeSettings;    /*0x48 */
+       U32                                 RAID1EVolumeSettings;   /*0x4C */
+       U32                                 RAID1VolumeSettings;    /*0x50 */
+       U32                                 RAID10VolumeSettings;   /*0x54 */
+       U32                                 Reserved4;              /*0x58 */
+       U32                                 Reserved5;              /*0x5C */
+       MPI2_MANPAGE4_PWR_SAVE_SETTINGS     PowerSaveSettings;      /*0x60 */
+       U8                                  MaxOCEDisks;            /*0x64 */
+       U8                                  ResyncRate;             /*0x65 */
+       U16                                 DataScrubDuration;      /*0x66 */
+       U8                                  MaxHotSpares;           /*0x68 */
+       U8                                  MaxPhysDisksPerVol;     /*0x69 */
+       U8                                  MaxPhysDisks;           /*0x6A */
+       U8                                  MaxVolumes;             /*0x6B */
+} MPI2_CONFIG_PAGE_MAN_4,
+       *PTR_MPI2_CONFIG_PAGE_MAN_4,
+       Mpi2ManufacturingPage4_t,
+       *pMpi2ManufacturingPage4_t;
+
+#define MPI2_MANUFACTURING4_PAGEVERSION                 (0x0A)
+
+/*Manufacturing Page 4 Flags field */
+#define MPI2_MANPAGE4_METADATA_SIZE_MASK                (0x00030000)
+#define MPI2_MANPAGE4_METADATA_512MB                    (0x00000000)
+
+#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA                  (0x00008000)
+#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD               (0x00004000)
+#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR              (0x00002000)
+
+#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION            (0x00001C00)
+#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB             (0x00000000)
+#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION           (0x00000400)
+#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION        (0x00000800)
+#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION            (0x00000C00)
+
+#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING            (0x00000300)
+#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING         (0x00000000)
+#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING           (0x00000100)
+#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING      (0x00000200)
+
+#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER            (0x00000080)
+#define MPI2_MANPAGE4_RAID10_DISABLE                    (0x00000040)
+#define MPI2_MANPAGE4_RAID1E_DISABLE                    (0x00000020)
+#define MPI2_MANPAGE4_RAID1_DISABLE                     (0x00000010)
+#define MPI2_MANPAGE4_RAID0_DISABLE                     (0x00000008)
+#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE              (0x00000004)
+#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE            (0x00000002)
+#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA                (0x00000001)
+
+
+/*Manufacturing Page 5 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
+#define MPI2_MAN_PAGE_5_PHY_ENTRIES         (1)
+#endif
+
+typedef struct _MPI2_MANUFACTURING5_ENTRY {
+       U64                                 WWID;           /*0x00 */
+       U64                                 DeviceName;     /*0x08 */
+} MPI2_MANUFACTURING5_ENTRY,
+       *PTR_MPI2_MANUFACTURING5_ENTRY,
+       Mpi2Manufacturing5Entry_t,
+       *pMpi2Manufacturing5Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_5 {
+       MPI2_CONFIG_PAGE_HEADER             Header;         /*0x00 */
+       U8                                  NumPhys;        /*0x04 */
+       U8                                  Reserved1;      /*0x05 */
+       U16                                 Reserved2;      /*0x06 */
+       U32                                 Reserved3;      /*0x08 */
+       U32                                 Reserved4;      /*0x0C */
+       MPI2_MANUFACTURING5_ENTRY
+               Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/*0x08 */
+} MPI2_CONFIG_PAGE_MAN_5,
+       *PTR_MPI2_CONFIG_PAGE_MAN_5,
+       Mpi2ManufacturingPage5_t,
+       *pMpi2ManufacturingPage5_t;
+
+#define MPI2_MANUFACTURING5_PAGEVERSION                 (0x03)
+
+
+/*Manufacturing Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_6 {
+       MPI2_CONFIG_PAGE_HEADER         Header;             /*0x00 */
+       U32                             ProductSpecificInfo;/*0x04 */
+} MPI2_CONFIG_PAGE_MAN_6,
+       *PTR_MPI2_CONFIG_PAGE_MAN_6,
+       Mpi2ManufacturingPage6_t,
+       *pMpi2ManufacturingPage6_t;
+
+#define MPI2_MANUFACTURING6_PAGEVERSION                 (0x00)
+
+
+/*Manufacturing Page 7 */
+
+typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
+       U32                         Pinout;                 /*0x00 */
+       U8                          Connector[16];          /*0x04 */
+       U8                          Location;               /*0x14 */
+       U8                          ReceptacleID;           /*0x15 */
+       U16                         Slot;                   /*0x16 */
+       U32                         Reserved2;              /*0x18 */
+} MPI2_MANPAGE7_CONNECTOR_INFO,
+       *PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
+       Mpi2ManPage7ConnectorInfo_t,
+       *pMpi2ManPage7ConnectorInfo_t;
+
+/*defines for the Pinout field */
+#define MPI2_MANPAGE7_PINOUT_LANE_MASK                  (0x0000FF00)
+#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT                 (8)
+
+#define MPI2_MANPAGE7_PINOUT_TYPE_MASK                  (0x000000FF)
+#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN               (0x00)
+#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE                (0x01)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482                   (0x02)
+#define MPI2_MANPAGE7_PINOUT_SFF_8486                   (0x03)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484                   (0x04)
+#define MPI2_MANPAGE7_PINOUT_SFF_8087                   (0x05)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I                (0x06)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I                (0x07)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470                   (0x08)
+#define MPI2_MANPAGE7_PINOUT_SFF_8088                   (0x09)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X                (0x0A)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X                (0x0B)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X               (0x0C)
+#define MPI2_MANPAGE7_PINOUT_SFF_8436                   (0x0D)
+
+/*defines for the Location field */
+#define MPI2_MANPAGE7_LOCATION_UNKNOWN                  (0x01)
+#define MPI2_MANPAGE7_LOCATION_INTERNAL                 (0x02)
+#define MPI2_MANPAGE7_LOCATION_EXTERNAL                 (0x04)
+#define MPI2_MANPAGE7_LOCATION_SWITCHABLE               (0x08)
+#define MPI2_MANPAGE7_LOCATION_AUTO                     (0x10)
+#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT              (0x20)
+#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED            (0x80)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
+#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX  (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
+       MPI2_CONFIG_PAGE_HEADER         Header;             /*0x00 */
+       U32                             Reserved1;          /*0x04 */
+       U32                             Reserved2;          /*0x08 */
+       U32                             Flags;              /*0x0C */
+       U8                              EnclosureName[16];  /*0x10 */
+       U8                              NumPhys;            /*0x20 */
+       U8                              Reserved3;          /*0x21 */
+       U16                             Reserved4;          /*0x22 */
+       MPI2_MANPAGE7_CONNECTOR_INFO
+       ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /*0x24 */
+} MPI2_CONFIG_PAGE_MAN_7,
+       *PTR_MPI2_CONFIG_PAGE_MAN_7,
+       Mpi2ManufacturingPage7_t,
+       *pMpi2ManufacturingPage7_t;
+
+#define MPI2_MANUFACTURING7_PAGEVERSION                 (0x01)
+
+/*defines for the Flags field */
+#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO                (0x00000001)
+
+
+/*
+ *Generic structure to use for product-specific manufacturing pages
+ *(currently Manufacturing Page 8 through Manufacturing Page 31).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_PS {
+       MPI2_CONFIG_PAGE_HEADER         Header;             /*0x00 */
+       U32                             ProductSpecificInfo;/*0x04 */
+} MPI2_CONFIG_PAGE_MAN_PS,
+       *PTR_MPI2_CONFIG_PAGE_MAN_PS,
+       Mpi2ManufacturingPagePS_t,
+       *pMpi2ManufacturingPagePS_t;
+
+#define MPI2_MANUFACTURING8_PAGEVERSION                 (0x00)
+#define MPI2_MANUFACTURING9_PAGEVERSION                 (0x00)
+#define MPI2_MANUFACTURING10_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING11_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING12_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING13_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING14_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING15_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING16_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING17_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING18_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING19_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING20_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING21_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING22_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING23_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING24_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING25_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING26_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING27_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING28_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING29_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING30_PAGEVERSION                (0x00)
+#define MPI2_MANUFACTURING31_PAGEVERSION                (0x00)
+
+
+/****************************************************************************
+*  IO Unit Config Pages
+****************************************************************************/
+
+/*IO Unit Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U64                     UniqueValue;                /*0x04 */
+       MPI2_VERSION_UNION      NvdataVersionDefault;       /*0x08 */
+       MPI2_VERSION_UNION      NvdataVersionPersistent;    /*0x0A */
+} MPI2_CONFIG_PAGE_IO_UNIT_0,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
+       Mpi2IOUnitPage0_t, *pMpi2IOUnitPage0_t;
+
+#define MPI2_IOUNITPAGE0_PAGEVERSION                    (0x02)
+
+
+/*IO Unit Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U32                     Flags;                      /*0x04 */
+} MPI2_CONFIG_PAGE_IO_UNIT_1,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
+       Mpi2IOUnitPage1_t, *pMpi2IOUnitPage1_t;
+
+#define MPI2_IOUNITPAGE1_PAGEVERSION                    (0x04)
+
+/*IO Unit Page 1 Flags defines */
+#define MPI25_IOUNITPAGE1_NEW_DEVICE_FAST_PATH_DISABLE  (0x00002000)
+#define MPI25_IOUNITPAGE1_DISABLE_FAST_PATH             (0x00001000)
+#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY    (0x00000800)
+#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE          (0x00000600)
+#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT         (9)
+#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE        (0x00000000)
+#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE       (0x00000200)
+#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE     (0x00000400)
+#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE       (0x00000100)
+#define MPI2_IOUNITPAGE1_DISABLE_IR                     (0x00000040)
+#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
+#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID        (0x00000004)
+
+
+/*IO Unit Page 3 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for GPIOCount at runtime.
+ */
+#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
+#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
+       MPI2_CONFIG_PAGE_HEADER Header;                  /*0x00 */
+       U8                      GPIOCount;               /*0x04 */
+       U8                      Reserved1;               /*0x05 */
+       U16                     Reserved2;               /*0x06 */
+       U16
+               GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/*0x08 */
+} MPI2_CONFIG_PAGE_IO_UNIT_3,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
+       Mpi2IOUnitPage3_t, *pMpi2IOUnitPage3_t;
+
+#define MPI2_IOUNITPAGE3_PAGEVERSION                    (0x01)
+
+/*defines for IO Unit Page 3 GPIOVal field */
+#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK             (0xFFFC)
+#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT            (2)
+#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF               (0x0000)
+#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON                (0x0001)
+
+
+/*IO Unit Page 5 */
+
+/*
+ *Upper layer code (drivers, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumDmaEngines at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
+#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U64
+               RaidAcceleratorBufferBaseAddress;           /*0x04 */
+       U64
+               RaidAcceleratorBufferSize;                  /*0x0C */
+       U64
+               RaidAcceleratorControlBaseAddress;          /*0x14 */
+       U8                      RAControlSize;              /*0x1C */
+       U8                      NumDmaEngines;              /*0x1D */
+       U8                      RAMinControlSize;           /*0x1E */
+       U8                      RAMaxControlSize;           /*0x1F */
+       U32                     Reserved1;                  /*0x20 */
+       U32                     Reserved2;                  /*0x24 */
+       U32                     Reserved3;                  /*0x28 */
+       U32
+       DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /*0x2C */
+} MPI2_CONFIG_PAGE_IO_UNIT_5,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
+       Mpi2IOUnitPage5_t, *pMpi2IOUnitPage5_t;
+
+#define MPI2_IOUNITPAGE5_PAGEVERSION                    (0x00)
+
+/*defines for IO Unit Page 5 DmaEngineCapabilities field */
+#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS      (0xFF00)
+#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS     (16)
+
+#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP                   (0x0008)
+#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION      (0x0004)
+#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING                (0x0002)
+#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION             (0x0001)
+
+
+/*IO Unit Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 {
+       MPI2_CONFIG_PAGE_HEADER Header;                 /*0x00 */
+       U16                     Flags;                  /*0x04 */
+       U8                      RAHostControlSize;      /*0x06 */
+       U8                      Reserved0;              /*0x07 */
+       U64
+               RaidAcceleratorHostControlBaseAddress;  /*0x08 */
+       U32                     Reserved1;              /*0x10 */
+       U32                     Reserved2;              /*0x14 */
+       U32                     Reserved3;              /*0x18 */
+} MPI2_CONFIG_PAGE_IO_UNIT_6,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_6,
+       Mpi2IOUnitPage6_t, *pMpi2IOUnitPage6_t;
+
+#define MPI2_IOUNITPAGE6_PAGEVERSION                    (0x00)
+
+/*defines for IO Unit Page 6 Flags field */
+#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR  (0x0001)
+
+
+/*IO Unit Page 7 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
+       MPI2_CONFIG_PAGE_HEADER Header;                 /*0x00 */
+       U8                      CurrentPowerMode;       /*0x04 */
+       U8                      PreviousPowerMode;      /*0x05 */
+       U8                      PCIeWidth;              /*0x06 */
+       U8                      PCIeSpeed;              /*0x07 */
+       U32                     ProcessorState;         /*0x08 */
+       U32
+               PowerManagementCapabilities;            /*0x0C */
+       U16                     IOCTemperature;         /*0x10 */
+       U8
+               IOCTemperatureUnits;                    /*0x12 */
+       U8                      IOCSpeed;               /*0x13 */
+       U16                     BoardTemperature;       /*0x14 */
+       U8
+               BoardTemperatureUnits;                  /*0x16 */
+       U8                      Reserved3;              /*0x17 */
+} MPI2_CONFIG_PAGE_IO_UNIT_7,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
+       Mpi2IOUnitPage7_t, *pMpi2IOUnitPage7_t;
+
+#define MPI2_IOUNITPAGE7_PAGEVERSION                    (0x02)
+
+/*defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */
+#define MPI25_IOUNITPAGE7_PM_INIT_MASK              (0xC0)
+#define MPI25_IOUNITPAGE7_PM_INIT_UNAVAILABLE       (0x00)
+#define MPI25_IOUNITPAGE7_PM_INIT_HOST              (0x40)
+#define MPI25_IOUNITPAGE7_PM_INIT_IO_UNIT           (0x80)
+#define MPI25_IOUNITPAGE7_PM_INIT_PCIE_DPA          (0xC0)
+
+#define MPI25_IOUNITPAGE7_PM_MODE_MASK              (0x07)
+#define MPI25_IOUNITPAGE7_PM_MODE_UNAVAILABLE       (0x00)
+#define MPI25_IOUNITPAGE7_PM_MODE_UNKNOWN           (0x01)
+#define MPI25_IOUNITPAGE7_PM_MODE_FULL_POWER        (0x04)
+#define MPI25_IOUNITPAGE7_PM_MODE_REDUCED_POWER     (0x05)
+#define MPI25_IOUNITPAGE7_PM_MODE_STANDBY           (0x06)
+
+
+/*defines for IO Unit Page 7 PCIeWidth field */
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1              (0x01)
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2              (0x02)
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4              (0x04)
+#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8              (0x08)
+
+/*defines for IO Unit Page 7 PCIeSpeed field */
+#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS        (0x00)
+#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS        (0x01)
+#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS        (0x02)
+
+/*defines for IO Unit Page 7 ProcessorState field */
+#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND         (0x0000000F)
+#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND        (0)
+
+#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT         (0x00)
+#define MPI2_IOUNITPAGE7_PSTATE_DISABLED            (0x01)
+#define MPI2_IOUNITPAGE7_PSTATE_ENABLED             (0x02)
+
+/*defines for IO Unit Page 7 PowerManagementCapabilities field */
+#define MPI25_IOUNITPAGE7_PMCAP_DPA_FULL_PWR_MODE       (0x00400000)
+#define MPI25_IOUNITPAGE7_PMCAP_DPA_REDUCED_PWR_MODE    (0x00200000)
+#define MPI25_IOUNITPAGE7_PMCAP_DPA_STANDBY_MODE        (0x00100000)
+#define MPI25_IOUNITPAGE7_PMCAP_HOST_FULL_PWR_MODE      (0x00040000)
+#define MPI25_IOUNITPAGE7_PMCAP_HOST_REDUCED_PWR_MODE   (0x00020000)
+#define MPI25_IOUNITPAGE7_PMCAP_HOST_STANDBY_MODE       (0x00010000)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_FULL_PWR_MODE        (0x00004000)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_REDUCED_PWR_MODE     (0x00002000)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_STANDBY_MODE         (0x00001000)
+#define MPI2_IOUNITPAGE7_PMCAP_HOST_12_5_PCT_IOCSPEED   (0x00000400)
+#define MPI2_IOUNITPAGE7_PMCAP_HOST_25_0_PCT_IOCSPEED   (0x00000200)
+#define MPI2_IOUNITPAGE7_PMCAP_HOST_50_0_PCT_IOCSPEED   (0x00000100)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_12_5_PCT_IOCSPEED    (0x00000040)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_25_0_PCT_IOCSPEED    (0x00000020)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_50_0_PCT_IOCSPEED    (0x00000010)
+#define MPI2_IOUNITPAGE7_PMCAP_HOST_WIDTH_CHANGE_PCIE   (0x00000008)
+#define MPI2_IOUNITPAGE7_PMCAP_HOST_SPEED_CHANGE_PCIE   (0x00000004)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_WIDTH_CHANGE_PCIE    (0x00000002)
+#define MPI25_IOUNITPAGE7_PMCAP_IO_SPEED_CHANGE_PCIE    (0x00000001)
+
+/*obsolete names for the PowerManagementCapabilities bits (above) */
+#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED    (0x00000400)
+#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED    (0x00000200)
+#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED    (0x00000100)
+#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE    (0x00000008) /*obsolete */
+#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE    (0x00000004) /*obsolete */
+
+
+/*defines for IO Unit Page 7 IOCTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT       (0x00)
+#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT        (0x01)
+#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS           (0x02)
+
+/*defines for IO Unit Page 7 IOCSpeed field */
+#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL             (0x01)
+#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF             (0x02)
+#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER          (0x04)
+#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH           (0x08)
+
+/*defines for IO Unit Page 7 BoardTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT     (0x00)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT      (0x01)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS         (0x02)
+
+
+/*IO Unit Page 8 */
+
+#define MPI2_IOUNIT8_NUM_THRESHOLDS     (4)
+
+typedef struct _MPI2_IOUNIT8_SENSOR {
+       U16                     Flags;                  /*0x00 */
+       U16                     Reserved1;              /*0x02 */
+       U16
+               Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /*0x04 */
+       U32                     Reserved2;              /*0x0C */
+       U32                     Reserved3;              /*0x10 */
+       U32                     Reserved4;              /*0x14 */
+} MPI2_IOUNIT8_SENSOR, *PTR_MPI2_IOUNIT8_SENSOR,
+       Mpi2IOUnit8Sensor_t, *pMpi2IOUnit8Sensor_t;
+
+/*defines for IO Unit Page 8 Sensor Flags field */
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE         (0x0008)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE         (0x0004)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE         (0x0002)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE         (0x0001)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumSensors at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
+#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES     (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
+       MPI2_CONFIG_PAGE_HEADER Header;                 /*0x00 */
+       U32                     Reserved1;              /*0x04 */
+       U32                     Reserved2;              /*0x08 */
+       U8                      NumSensors;             /*0x0C */
+       U8                      PollingInterval;        /*0x0D */
+       U16                     Reserved3;              /*0x0E */
+       MPI2_IOUNIT8_SENSOR
+               Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/*0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_8,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
+       Mpi2IOUnitPage8_t, *pMpi2IOUnitPage8_t;
+
+#define MPI2_IOUNITPAGE8_PAGEVERSION                    (0x00)
+
+
+/*IO Unit Page 9 */
+
+typedef struct _MPI2_IOUNIT9_SENSOR {
+       U16                     CurrentTemperature;     /*0x00 */
+       U16                     Reserved1;              /*0x02 */
+       U8                      Flags;                  /*0x04 */
+       U8                      Reserved2;              /*0x05 */
+       U16                     Reserved3;              /*0x06 */
+       U32                     Reserved4;              /*0x08 */
+       U32                     Reserved5;              /*0x0C */
+} MPI2_IOUNIT9_SENSOR, *PTR_MPI2_IOUNIT9_SENSOR,
+       Mpi2IOUnit9Sensor_t, *pMpi2IOUnit9Sensor_t;
+
+/*defines for IO Unit Page 9 Sensor Flags field */
+#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID        (0x01)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumSensors at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
+#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES     (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
+       MPI2_CONFIG_PAGE_HEADER Header;                 /*0x00 */
+       U32                     Reserved1;              /*0x04 */
+       U32                     Reserved2;              /*0x08 */
+       U8                      NumSensors;             /*0x0C */
+       U8                      Reserved4;              /*0x0D */
+       U16                     Reserved3;              /*0x0E */
+       MPI2_IOUNIT9_SENSOR
+               Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/*0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_9,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
+       Mpi2IOUnitPage9_t, *pMpi2IOUnitPage9_t;
+
+#define MPI2_IOUNITPAGE9_PAGEVERSION                    (0x00)
+
+
+/*IO Unit Page 10 */
+
+typedef struct _MPI2_IOUNIT10_FUNCTION {
+       U8                      CreditPercent;      /*0x00 */
+       U8                      Reserved1;          /*0x01 */
+       U16                     Reserved2;          /*0x02 */
+} MPI2_IOUNIT10_FUNCTION,
+       *PTR_MPI2_IOUNIT10_FUNCTION,
+       Mpi2IOUnit10Function_t,
+       *pMpi2IOUnit10Function_t;
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumFunctions at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
+#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
+       MPI2_CONFIG_PAGE_HEADER Header;                      /*0x00 */
+       U8                      NumFunctions;                /*0x04 */
+       U8                      Reserved1;                   /*0x05 */
+       U16                     Reserved2;                   /*0x06 */
+       U32                     Reserved3;                   /*0x08 */
+       U32                     Reserved4;                   /*0x0C */
+       MPI2_IOUNIT10_FUNCTION
+               Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/*0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_10,
+       *PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
+       Mpi2IOUnitPage10_t, *pMpi2IOUnitPage10_t;
+
+#define MPI2_IOUNITPAGE10_PAGEVERSION                   (0x01)
+
+
+
+/****************************************************************************
+*  IOC Config Pages
+****************************************************************************/
+
+/*IOC Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_0 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U32                     Reserved1;                  /*0x04 */
+       U32                     Reserved2;                  /*0x08 */
+       U16                     VendorID;                   /*0x0C */
+       U16                     DeviceID;                   /*0x0E */
+       U8                      RevisionID;                 /*0x10 */
+       U8                      Reserved3;                  /*0x11 */
+       U16                     Reserved4;                  /*0x12 */
+       U32                     ClassCode;                  /*0x14 */
+       U16                     SubsystemVendorID;          /*0x18 */
+       U16                     SubsystemID;                /*0x1A */
+} MPI2_CONFIG_PAGE_IOC_0,
+       *PTR_MPI2_CONFIG_PAGE_IOC_0,
+       Mpi2IOCPage0_t, *pMpi2IOCPage0_t;
+
+#define MPI2_IOCPAGE0_PAGEVERSION                       (0x02)
+
+
+/*IOC Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_1 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U32                     Flags;                      /*0x04 */
+       U32                     CoalescingTimeout;          /*0x08 */
+       U8                      CoalescingDepth;            /*0x0C */
+       U8                      PCISlotNum;                 /*0x0D */
+       U8                      PCIBusNum;                  /*0x0E */
+       U8                      PCIDomainSegment;           /*0x0F */
+       U32                     Reserved1;                  /*0x10 */
+       U32                     Reserved2;                  /*0x14 */
+} MPI2_CONFIG_PAGE_IOC_1,
+       *PTR_MPI2_CONFIG_PAGE_IOC_1,
+       Mpi2IOCPage1_t, *pMpi2IOCPage1_t;
+
+#define MPI2_IOCPAGE1_PAGEVERSION                       (0x05)
+
+/*defines for IOC Page 1 Flags field */
+#define MPI2_IOCPAGE1_REPLY_COALESCING                  (0x00000001)
+
+#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN                (0xFF)
+#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN                 (0xFF)
+#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN                 (0xFF)
+
+/*IOC Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_6 {
+       MPI2_CONFIG_PAGE_HEADER Header;         /*0x00 */
+       U32
+               CapabilitiesFlags;              /*0x04 */
+       U8                      MaxDrivesRAID0; /*0x08 */
+       U8                      MaxDrivesRAID1; /*0x09 */
+       U8
+                MaxDrivesRAID1E;                /*0x0A */
+       U8
+                MaxDrivesRAID10;               /*0x0B */
+       U8                      MinDrivesRAID0; /*0x0C */
+       U8                      MinDrivesRAID1; /*0x0D */
+       U8
+                MinDrivesRAID1E;                /*0x0E */
+       U8
+                MinDrivesRAID10;                /*0x0F */
+       U32                     Reserved1;      /*0x10 */
+       U8
+                MaxGlobalHotSpares;             /*0x14 */
+       U8                      MaxPhysDisks;   /*0x15 */
+       U8                      MaxVolumes;     /*0x16 */
+       U8                      MaxConfigs;     /*0x17 */
+       U8                      MaxOCEDisks;    /*0x18 */
+       U8                      Reserved2;      /*0x19 */
+       U16                     Reserved3;      /*0x1A */
+       U32
+               SupportedStripeSizeMapRAID0;    /*0x1C */
+       U32
+               SupportedStripeSizeMapRAID1E;   /*0x20 */
+       U32
+               SupportedStripeSizeMapRAID10;   /*0x24 */
+       U32                     Reserved4;      /*0x28 */
+       U32                     Reserved5;      /*0x2C */
+       U16
+               DefaultMetadataSize;            /*0x30 */
+       U16                     Reserved6;      /*0x32 */
+       U16
+               MaxBadBlockTableEntries;        /*0x34 */
+       U16                     Reserved7;      /*0x36 */
+       U32
+               IRNvsramVersion;                /*0x38 */
+} MPI2_CONFIG_PAGE_IOC_6,
+       *PTR_MPI2_CONFIG_PAGE_IOC_6,
+       Mpi2IOCPage6_t, *pMpi2IOCPage6_t;
+
+#define MPI2_IOCPAGE6_PAGEVERSION                       (0x05)
+
+/*defines for IOC Page 6 CapabilitiesFlags */
+#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT      (0x00000020)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT          (0x00000010)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT           (0x00000008)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT          (0x00000004)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT           (0x00000002)
+#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE        (0x00000001)
+
+
+/*IOC Page 7 */
+
+#define MPI2_IOCPAGE7_EVENTMASK_WORDS       (4)
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_7 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U32                     Reserved1;                  /*0x04 */
+       U32
+               EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/*0x08 */
+       U16                     SASBroadcastPrimitiveMasks; /*0x18 */
+       U16                     SASNotifyPrimitiveMasks;    /*0x1A */
+       U32                     Reserved3;                  /*0x1C */
+} MPI2_CONFIG_PAGE_IOC_7,
+       *PTR_MPI2_CONFIG_PAGE_IOC_7,
+       Mpi2IOCPage7_t, *pMpi2IOCPage7_t;
+
+#define MPI2_IOCPAGE7_PAGEVERSION                       (0x02)
+
+
+/*IOC Page 8 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_8 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U8                      NumDevsPerEnclosure;        /*0x04 */
+       U8                      Reserved1;                  /*0x05 */
+       U16                     Reserved2;                  /*0x06 */
+       U16                     MaxPersistentEntries;       /*0x08 */
+       U16                     MaxNumPhysicalMappedIDs;    /*0x0A */
+       U16                     Flags;                      /*0x0C */
+       U16                     Reserved3;                  /*0x0E */
+       U16                     IRVolumeMappingFlags;       /*0x10 */
+       U16                     Reserved4;                  /*0x12 */
+       U32                     Reserved5;                  /*0x14 */
+} MPI2_CONFIG_PAGE_IOC_8,
+       *PTR_MPI2_CONFIG_PAGE_IOC_8,
+       Mpi2IOCPage8_t, *pMpi2IOCPage8_t;
+
+#define MPI2_IOCPAGE8_PAGEVERSION                       (0x00)
+
+/*defines for IOC Page 8 Flags field */
+#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1             (0x00000020)
+#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0         (0x00000010)
+
+#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE           (0x0000000E)
+#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING  (0x00000000)
+#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING      (0x00000002)
+
+#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING  (0x00000001)
+#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING   (0x00000000)
+
+/*defines for IOC Page 8 IRVolumeMappingFlags */
+#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE  (0x00000003)
+#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING        (0x00000000)
+#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING       (0x00000001)
+
+
+/****************************************************************************
+*  BIOS Config Pages
+****************************************************************************/
+
+/*BIOS Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_1 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U32                     BiosOptions;                /*0x04 */
+       U32                     IOCSettings;                /*0x08 */
+       U32                     Reserved1;                  /*0x0C */
+       U32                     DeviceSettings;             /*0x10 */
+       U16                     NumberOfDevices;            /*0x14 */
+       U16                     UEFIVersion;                /*0x16 */
+       U16                     IOTimeoutBlockDevicesNonRM; /*0x18 */
+       U16                     IOTimeoutSequential;        /*0x1A */
+       U16                     IOTimeoutOther;             /*0x1C */
+       U16                     IOTimeoutBlockDevicesRM;    /*0x1E */
+} MPI2_CONFIG_PAGE_BIOS_1,
+       *PTR_MPI2_CONFIG_PAGE_BIOS_1,
+       Mpi2BiosPage1_t, *pMpi2BiosPage1_t;
+
+#define MPI2_BIOSPAGE1_PAGEVERSION                      (0x05)
+
+/*values for BIOS Page 1 BiosOptions field */
+#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION   (0x00000006)
+#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII              (0x00000000)
+#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII             (0x00000002)
+#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII       (0x00000004)
+
+#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS                 (0x00000001)
+
+/*values for BIOS Page 1 IOCSettings field */
+#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE      (0x00030000)
+#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT       (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT          (0x00010000)
+
+#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING           (0x000000C0)
+#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING           (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING           (0x00000040)
+#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING          (0x00000080)
+
+#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT      (0x00000030)
+#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT                (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT              (0x00000010)
+#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT                (0x00000020)
+#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT               (0x00000030)
+
+#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS             (0x00000008)
+
+/*values for BIOS Page 1 DeviceSettings field */
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING     (0x00000010)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN           (0x00000008)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN            (0x00000004)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN        (0x00000002)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN         (0x00000001)
+
+/*defines for BIOS Page 1 UEFIVersion field */
+#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK              (0xFF00)
+#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT             (8)
+#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK              (0x00FF)
+#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT             (0)
+
+
+
+/*BIOS Page 2 */
+
+typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER {
+       U32         Reserved1;                              /*0x00 */
+       U32         Reserved2;                              /*0x04 */
+       U32         Reserved3;                              /*0x08 */
+       U32         Reserved4;                              /*0x0C */
+       U32         Reserved5;                              /*0x10 */
+       U32         Reserved6;                              /*0x14 */
+} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
+       *PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
+       Mpi2BootDeviceAdapterOrder_t,
+       *pMpi2BootDeviceAdapterOrder_t;
+
+typedef struct _MPI2_BOOT_DEVICE_SAS_WWID {
+       U64         SASAddress;                             /*0x00 */
+       U8          LUN[8];                                 /*0x08 */
+       U32         Reserved1;                              /*0x10 */
+       U32         Reserved2;                              /*0x14 */
+} MPI2_BOOT_DEVICE_SAS_WWID,
+       *PTR_MPI2_BOOT_DEVICE_SAS_WWID,
+       Mpi2BootDeviceSasWwid_t,
+       *pMpi2BootDeviceSasWwid_t;
+
+typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT {
+       U64         EnclosureLogicalID;                     /*0x00 */
+       U32         Reserved1;                              /*0x08 */
+       U32         Reserved2;                              /*0x0C */
+       U16         SlotNumber;                             /*0x10 */
+       U16         Reserved3;                              /*0x12 */
+       U32         Reserved4;                              /*0x14 */
+} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
+       *PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
+       Mpi2BootDeviceEnclosureSlot_t,
+       *pMpi2BootDeviceEnclosureSlot_t;
+
+typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME {
+       U64         DeviceName;                             /*0x00 */
+       U8          LUN[8];                                 /*0x08 */
+       U32         Reserved1;                              /*0x10 */
+       U32         Reserved2;                              /*0x14 */
+} MPI2_BOOT_DEVICE_DEVICE_NAME,
+       *PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
+       Mpi2BootDeviceDeviceName_t,
+       *pMpi2BootDeviceDeviceName_t;
+
+typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE {
+       MPI2_BOOT_DEVICE_ADAPTER_ORDER  AdapterOrder;
+       MPI2_BOOT_DEVICE_SAS_WWID       SasWwid;
+       MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
+       MPI2_BOOT_DEVICE_DEVICE_NAME    DeviceName;
+} MPI2_BIOSPAGE2_BOOT_DEVICE,
+       *PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
+       Mpi2BiosPage2BootDevice_t,
+       *pMpi2BiosPage2BootDevice_t;
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_2 {
+       MPI2_CONFIG_PAGE_HEADER     Header;                 /*0x00 */
+       U32                         Reserved1;              /*0x04 */
+       U32                         Reserved2;              /*0x08 */
+       U32                         Reserved3;              /*0x0C */
+       U32                         Reserved4;              /*0x10 */
+       U32                         Reserved5;              /*0x14 */
+       U32                         Reserved6;              /*0x18 */
+       U8                          ReqBootDeviceForm;      /*0x1C */
+       U8                          Reserved7;              /*0x1D */
+       U16                         Reserved8;              /*0x1E */
+       MPI2_BIOSPAGE2_BOOT_DEVICE  RequestedBootDevice;    /*0x20 */
+       U8                          ReqAltBootDeviceForm;   /*0x38 */
+       U8                          Reserved9;              /*0x39 */
+       U16                         Reserved10;             /*0x3A */
+       MPI2_BIOSPAGE2_BOOT_DEVICE  RequestedAltBootDevice; /*0x3C */
+       U8                          CurrentBootDeviceForm;  /*0x58 */
+       U8                          Reserved11;             /*0x59 */
+       U16                         Reserved12;             /*0x5A */
+       MPI2_BIOSPAGE2_BOOT_DEVICE  CurrentBootDevice;      /*0x58 */
+} MPI2_CONFIG_PAGE_BIOS_2, *PTR_MPI2_CONFIG_PAGE_BIOS_2,
+       Mpi2BiosPage2_t, *pMpi2BiosPage2_t;
+
+#define MPI2_BIOSPAGE2_PAGEVERSION                      (0x04)
+
+/*values for BIOS Page 2 BootDeviceForm fields */
+#define MPI2_BIOSPAGE2_FORM_MASK                        (0x0F)
+#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED         (0x00)
+#define MPI2_BIOSPAGE2_FORM_SAS_WWID                    (0x05)
+#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT              (0x06)
+#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME                 (0x07)
+
+
+/*BIOS Page 3 */
+
+typedef struct _MPI2_ADAPTER_INFO {
+       U8      PciBusNumber;                        /*0x00 */
+       U8      PciDeviceAndFunctionNumber;          /*0x01 */
+       U16     AdapterFlags;                        /*0x02 */
+} MPI2_ADAPTER_INFO, *PTR_MPI2_ADAPTER_INFO,
+       Mpi2AdapterInfo_t, *pMpi2AdapterInfo_t;
+
+#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED                (0x0001)
+#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS             (0x0002)
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_3 {
+       MPI2_CONFIG_PAGE_HEADER Header;              /*0x00 */
+       U32                     GlobalFlags;         /*0x04 */
+       U32                     BiosVersion;         /*0x08 */
+       MPI2_ADAPTER_INFO       AdapterOrder[4];     /*0x0C */
+       U32                     Reserved1;           /*0x1C */
+} MPI2_CONFIG_PAGE_BIOS_3,
+       *PTR_MPI2_CONFIG_PAGE_BIOS_3,
+       Mpi2BiosPage3_t, *pMpi2BiosPage3_t;
+
+#define MPI2_BIOSPAGE3_PAGEVERSION                      (0x00)
+
+/*values for BIOS Page 3 GlobalFlags */
+#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR             (0x00000002)
+#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE             (0x00000004)
+#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE        (0x00000010)
+
+#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK      (0x000000E0)
+#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY      (0x00000000)
+#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY            (0x00000020)
+#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY        (0x00000040)
+
+
+/*BIOS Page 4 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
+#define MPI2_BIOS_PAGE_4_PHY_ENTRIES        (1)
+#endif
+
+typedef struct _MPI2_BIOS4_ENTRY {
+       U64                     ReassignmentWWID;       /*0x00 */
+       U64                     ReassignmentDeviceName; /*0x08 */
+} MPI2_BIOS4_ENTRY, *PTR_MPI2_BIOS4_ENTRY,
+       Mpi2MBios4Entry_t, *pMpi2Bios4Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_4 {
+       MPI2_CONFIG_PAGE_HEADER Header;             /*0x00 */
+       U8                      NumPhys;            /*0x04 */
+       U8                      Reserved1;          /*0x05 */
+       U16                     Reserved2;          /*0x06 */
+       MPI2_BIOS4_ENTRY
+               Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES];  /*0x08 */
+} MPI2_CONFIG_PAGE_BIOS_4, *PTR_MPI2_CONFIG_PAGE_BIOS_4,
+       Mpi2BiosPage4_t, *pMpi2BiosPage4_t;
+
+#define MPI2_BIOSPAGE4_PAGEVERSION                      (0x01)
+
+
+/****************************************************************************
+*  RAID Volume Config Pages
+****************************************************************************/
+
+/*RAID Volume Page 0 */
+
+typedef struct _MPI2_RAIDVOL0_PHYS_DISK {
+       U8                      RAIDSetNum;        /*0x00 */
+       U8                      PhysDiskMap;       /*0x01 */
+       U8                      PhysDiskNum;       /*0x02 */
+       U8                      Reserved;          /*0x03 */
+} MPI2_RAIDVOL0_PHYS_DISK, *PTR_MPI2_RAIDVOL0_PHYS_DISK,
+       Mpi2RaidVol0PhysDisk_t, *pMpi2RaidVol0PhysDisk_t;
+
+/*defines for the PhysDiskMap field */
+#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY                  (0x01)
+#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY                (0x02)
+
+typedef struct _MPI2_RAIDVOL0_SETTINGS {
+       U16                     Settings;          /*0x00 */
+       U8                      HotSparePool;      /*0x01 */
+       U8                      Reserved;          /*0x02 */
+} MPI2_RAIDVOL0_SETTINGS, *PTR_MPI2_RAIDVOL0_SETTINGS,
+       Mpi2RaidVol0Settings_t,
+       *pMpi2RaidVol0Settings_t;
+
+/*RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
+#define MPI2_RAID_HOT_SPARE_POOL_0                      (0x01)
+#define MPI2_RAID_HOT_SPARE_POOL_1                      (0x02)
+#define MPI2_RAID_HOT_SPARE_POOL_2                      (0x04)
+#define MPI2_RAID_HOT_SPARE_POOL_3                      (0x08)
+#define MPI2_RAID_HOT_SPARE_POOL_4                      (0x10)
+#define MPI2_RAID_HOT_SPARE_POOL_5                      (0x20)
+#define MPI2_RAID_HOT_SPARE_POOL_6                      (0x40)
+#define MPI2_RAID_HOT_SPARE_POOL_7                      (0x80)
+
+/*RAID Volume Page 0 VolumeSettings defines */
+#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX     (0x0008)
+#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
+
+#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING        (0x0003)
+#define MPI2_RAIDVOL0_SETTING_UNCHANGED                 (0x0000)
+#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING     (0x0001)
+#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING      (0x0002)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhysDisks at runtime.
+ */
+#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
+#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX       (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 {
+       MPI2_CONFIG_PAGE_HEADER Header;            /*0x00 */
+       U16                     DevHandle;         /*0x04 */
+       U8                      VolumeState;       /*0x06 */
+       U8                      VolumeType;        /*0x07 */
+       U32                     VolumeStatusFlags; /*0x08 */
+       MPI2_RAIDVOL0_SETTINGS  VolumeSettings;    /*0x0C */
+       U64                     MaxLBA;            /*0x10 */
+       U32                     StripeSize;        /*0x18 */
+       U16                     BlockSize;         /*0x1C */
+       U16                     Reserved1;         /*0x1E */
+       U8                      SupportedPhysDisks;/*0x20 */
+       U8                      ResyncRate;        /*0x21 */
+       U16                     DataScrubDuration; /*0x22 */
+       U8                      NumPhysDisks;      /*0x24 */
+       U8                      Reserved2;         /*0x25 */
+       U8                      Reserved3;         /*0x26 */
+       U8                      InactiveStatus;    /*0x27 */
+       MPI2_RAIDVOL0_PHYS_DISK
+       PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /*0x28 */
+} MPI2_CONFIG_PAGE_RAID_VOL_0,
+       *PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
+       Mpi2RaidVolPage0_t, *pMpi2RaidVolPage0_t;
+
+#define MPI2_RAIDVOLPAGE0_PAGEVERSION           (0x0A)
+
+/*values for RAID VolumeState */
+#define MPI2_RAID_VOL_STATE_MISSING                         (0x00)
+#define MPI2_RAID_VOL_STATE_FAILED                          (0x01)
+#define MPI2_RAID_VOL_STATE_INITIALIZING                    (0x02)
+#define MPI2_RAID_VOL_STATE_ONLINE                          (0x03)
+#define MPI2_RAID_VOL_STATE_DEGRADED                        (0x04)
+#define MPI2_RAID_VOL_STATE_OPTIMAL                         (0x05)
+
+/*values for RAID VolumeType */
+#define MPI2_RAID_VOL_TYPE_RAID0                            (0x00)
+#define MPI2_RAID_VOL_TYPE_RAID1E                           (0x01)
+#define MPI2_RAID_VOL_TYPE_RAID1                            (0x02)
+#define MPI2_RAID_VOL_TYPE_RAID10                           (0x05)
+#define MPI2_RAID_VOL_TYPE_UNKNOWN                          (0xFF)
+
+/*values for RAID Volume Page 0 VolumeStatusFlags field */
+#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC            (0x02000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING        (0x01000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING               (0x00800000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING      (0x00400000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT      (0x00200000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB                (0x00100000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK         (0x00080000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION        (0x00040000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT           (0x00020000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS        (0x00010000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT        (0x00000080)
+#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED               (0x00000040)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE              (0x00000020)
+#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR          (0x00000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR        (0x00000010)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL      (0x00000008)
+#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE           (0x00000004)
+#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED                  (0x00000002)
+#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED                   (0x00000001)
+
+/*values for RAID Volume Page 0 SupportedPhysDisks field */
+#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS             (0x08)
+#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS                    (0x04)
+#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL                  (0x02)
+#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL                 (0x01)
+
+/*values for RAID Volume Page 0 InactiveStatus field */
+#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE                  (0x00)
+#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE           (0x01)
+#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE           (0x02)
+#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE    (0x03)
+#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE             (0x04)
+#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE    (0x05)
+#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED                (0x06)
+
+
+/*RAID Volume Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 {
+       MPI2_CONFIG_PAGE_HEADER Header;                     /*0x00 */
+       U16                     DevHandle;                  /*0x04 */
+       U16                     Reserved0;                  /*0x06 */
+       U8                      GUID[24];                   /*0x08 */
+       U8                      Name[16];                   /*0x20 */
+       U64                     WWID;                       /*0x30 */
+       U32                     Reserved1;                  /*0x38 */
+       U32                     Reserved2;                  /*0x3C */
+} MPI2_CONFIG_PAGE_RAID_VOL_1,
+       *PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
+       Mpi2RaidVolPage1_t, *pMpi2RaidVolPage1_t;
+
+#define MPI2_RAIDVOLPAGE1_PAGEVERSION           (0x03)
+
+
+/****************************************************************************
+*  RAID Physical Disk Config Pages
+****************************************************************************/
+
+/*RAID Physical Disk Page 0 */
+
+typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS {
+       U16                     Reserved1;                  /*0x00 */
+       U8                      HotSparePool;               /*0x02 */
+       U8                      Reserved2;                  /*0x03 */
+} MPI2_RAIDPHYSDISK0_SETTINGS,
+       *PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
+       Mpi2RaidPhysDisk0Settings_t,
+       *pMpi2RaidPhysDisk0Settings_t;
+
+/*use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
+
+typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA {
+       U8                      VendorID[8];                /*0x00 */
+       U8                      ProductID[16];              /*0x08 */
+       U8                      ProductRevLevel[4];         /*0x18 */
+       U8                      SerialNum[32];              /*0x1C */
+} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
+       *PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
+       Mpi2RaidPhysDisk0InquiryData_t,
+       *pMpi2RaidPhysDisk0InquiryData_t;
+
+typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 {
+       MPI2_CONFIG_PAGE_HEADER         Header;             /*0x00 */
+       U16                             DevHandle;          /*0x04 */
+       U8                              Reserved1;          /*0x06 */
+       U8                              PhysDiskNum;        /*0x07 */
+       MPI2_RAIDPHYSDISK0_SETTINGS     PhysDiskSettings;   /*0x08 */
+       U32                             Reserved2;          /*0x0C */
+       MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData;        /*0x10 */
+       U32                             Reserved3;          /*0x4C */
+       U8                              PhysDiskState;      /*0x50 */
+       U8                              OfflineReason;      /*0x51 */
+       U8                              IncompatibleReason; /*0x52 */
+       U8                              PhysDiskAttributes; /*0x53 */
+       U32                             PhysDiskStatusFlags;/*0x54 */
+       U64                             DeviceMaxLBA;       /*0x58 */
+       U64                             HostMaxLBA;         /*0x60 */
+       U64                             CoercedMaxLBA;      /*0x68 */
+       U16                             BlockSize;          /*0x70 */
+       U16                             Reserved5;          /*0x72 */
+       U32                             Reserved6;          /*0x74 */
+} MPI2_CONFIG_PAGE_RD_PDISK_0,
+       *PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
+       Mpi2RaidPhysDiskPage0_t,
+       *pMpi2RaidPhysDiskPage0_t;
+
+#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION          (0x05)
+
+/*PhysDiskState defines */
+#define MPI2_RAID_PD_STATE_NOT_CONFIGURED               (0x00)
+#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE               (0x01)
+#define MPI2_RAID_PD_STATE_OFFLINE                      (0x02)
+#define MPI2_RAID_PD_STATE_ONLINE                       (0x03)
+#define MPI2_RAID_PD_STATE_HOT_SPARE                    (0x04)
+#define MPI2_RAID_PD_STATE_DEGRADED                     (0x05)
+#define MPI2_RAID_PD_STATE_REBUILDING                   (0x06)
+#define MPI2_RAID_PD_STATE_OPTIMAL                      (0x07)
+
+/*OfflineReason defines */
+#define MPI2_PHYSDISK0_ONLINE                           (0x00)
+#define MPI2_PHYSDISK0_OFFLINE_MISSING                  (0x01)
+#define MPI2_PHYSDISK0_OFFLINE_FAILED                   (0x03)
+#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING             (0x04)
+#define MPI2_PHYSDISK0_OFFLINE_REQUESTED                (0x05)
+#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED         (0x06)
+#define MPI2_PHYSDISK0_OFFLINE_OTHER                    (0xFF)
+
+/*IncompatibleReason defines */
+#define MPI2_PHYSDISK0_COMPATIBLE                       (0x00)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL            (0x01)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE           (0x02)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA             (0x03)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD   (0x04)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA    (0x05)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE          (0x06)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN             (0xFF)
+
+/*PhysDiskAttributes defines */
+#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK                (0x0C)
+#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE         (0x08)
+#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE           (0x04)
+
+#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK             (0x03)
+#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL              (0x02)
+#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL             (0x01)
+
+/*PhysDiskStatusFlags defines */
+#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED        (0x00000040)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET           (0x00000020)
+#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED  (0x00000010)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS     (0x00000000)
+#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
+#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME      (0x00000004)
+#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED             (0x00000002)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC          (0x00000001)
+
+
+/*RAID Physical Disk Page 1 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhysDiskPaths at runtime.
+ */
+#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
+#define MPI2_RAID_PHYS_DISK1_PATH_MAX   (1)
+#endif
+
+typedef struct _MPI2_RAIDPHYSDISK1_PATH {
+       U16             DevHandle;          /*0x00 */
+       U16             Reserved1;          /*0x02 */
+       U64             WWID;               /*0x04 */
+       U64             OwnerWWID;          /*0x0C */
+       U8              OwnerIdentifier;    /*0x14 */
+       U8              Reserved2;          /*0x15 */
+       U16             Flags;              /*0x16 */
+} MPI2_RAIDPHYSDISK1_PATH, *PTR_MPI2_RAIDPHYSDISK1_PATH,
+       Mpi2RaidPhysDisk1Path_t,
+       *pMpi2RaidPhysDisk1Path_t;
+
+/*RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
+#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY        (0x0004)
+#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN         (0x0002)
+#define MPI2_RAID_PHYSDISK1_FLAG_INVALID        (0x0001)
+
+typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
+       MPI2_CONFIG_PAGE_HEADER         Header;             /*0x00 */
+       U8                              NumPhysDiskPaths;   /*0x04 */
+       U8                              PhysDiskNum;        /*0x05 */
+       U16                             Reserved1;          /*0x06 */
+       U32                             Reserved2;          /*0x08 */
+       MPI2_RAIDPHYSDISK1_PATH
+               PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/*0x0C */
+} MPI2_CONFIG_PAGE_RD_PDISK_1,
+       *PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
+       Mpi2RaidPhysDiskPage1_t,
+       *pMpi2RaidPhysDiskPage1_t;
+
+#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION          (0x02)
+
+
+/****************************************************************************
+*  values for fields used by several types of SAS Config Pages
+****************************************************************************/
+
+/*values for NegotiatedLinkRates fields */
+#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL             (0xF0)
+#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL            (4)
+#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL            (0x0F)
+/*link rates used for Negotiated Physical and Logical Link Rate */
+#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE        (0x00)
+#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED             (0x01)
+#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED       (0x02)
+#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE        (0x03)
+#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR            (0x04)
+#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS    (0x05)
+#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY          (0x06)
+#define MPI2_SAS_NEG_LINK_RATE_1_5                      (0x08)
+#define MPI2_SAS_NEG_LINK_RATE_3_0                      (0x09)
+#define MPI2_SAS_NEG_LINK_RATE_6_0                      (0x0A)
+#define MPI25_SAS_NEG_LINK_RATE_12_0                    (0x0B)
+
+
+/*values for AttachedPhyInfo fields */
+#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT       (0x00000040)
+#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS        (0x00000020)
+#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE           (0x00000010)
+
+#define MPI2_SAS_APHYINFO_REASON_MASK                   (0x0000000F)
+#define MPI2_SAS_APHYINFO_REASON_UNKNOWN                (0x00000000)
+#define MPI2_SAS_APHYINFO_REASON_POWER_ON               (0x00000001)
+#define MPI2_SAS_APHYINFO_REASON_HARD_RESET             (0x00000002)
+#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL        (0x00000003)
+#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC           (0x00000004)
+#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ       (0x00000005)
+#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER    (0x00000006)
+#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT          (0x00000007)
+#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED       (0x00000008)
+
+
+/*values for PhyInfo fields */
+#define MPI2_SAS_PHYINFO_PHY_VACANT                     (0x80000000)
+
+#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK       (0x18000000)
+#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION      (27)
+#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE               (0x00000000)
+#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL              (0x08000000)
+#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER              (0x10000000)
+
+#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS       (0x04000000)
+#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT        (0x02000000)
+#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS               (0x01000000)
+#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT          (0x00400000)
+#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS                   (0x00200000)
+#define MPI2_SAS_PHYINFO_ZONING_ENABLED                 (0x00100000)
+
+#define MPI2_SAS_PHYINFO_REASON_MASK                    (0x000F0000)
+#define MPI2_SAS_PHYINFO_REASON_UNKNOWN                 (0x00000000)
+#define MPI2_SAS_PHYINFO_REASON_POWER_ON                (0x00010000)
+#define MPI2_SAS_PHYINFO_REASON_HARD_RESET              (0x00020000)
+#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL         (0x00030000)
+#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC            (0x00040000)
+#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ        (0x00050000)
+#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER     (0x00060000)
+#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT           (0x00070000)
+#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED        (0x00080000)
+
+#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED         (0x00008000)
+#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE               (0x00004000)
+#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT     (0x00002000)
+#define MPI2_SAS_PHYINFO_VIRTUAL_PHY                    (0x00001000)
+
+#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME      (0x00000F00)
+#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME     (8)
+
+#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE         (0x000000F0)
+#define MPI2_SAS_PHYINFO_DIRECT_ROUTING                 (0x00000000)
+#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING            (0x00000010)
+#define MPI2_SAS_PHYINFO_TABLE_ROUTING                  (0x00000020)
+
+
+/*values for SAS ProgrammedLinkRate fields */
+#define MPI2_SAS_PRATE_MAX_RATE_MASK                    (0xF0)
+#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE        (0x00)
+#define MPI2_SAS_PRATE_MAX_RATE_1_5                     (0x80)
+#define MPI2_SAS_PRATE_MAX_RATE_3_0                     (0x90)
+#define MPI2_SAS_PRATE_MAX_RATE_6_0                     (0xA0)
+#define MPI2_SAS_PRATE_MIN_RATE_MASK                    (0x0F)
+#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE        (0x00)
+#define MPI2_SAS_PRATE_MIN_RATE_1_5                     (0x08)
+#define MPI2_SAS_PRATE_MIN_RATE_3_0                     (0x09)
+#define MPI2_SAS_PRATE_MIN_RATE_6_0                     (0x0A)
+#define MPI25_SAS_PRATE_MIN_RATE_12_0                   (0x0B)
+
+
+/*values for SAS HwLinkRate fields */
+#define MPI2_SAS_HWRATE_MAX_RATE_MASK                   (0xF0)
+#define MPI2_SAS_HWRATE_MAX_RATE_1_5                    (0x80)
+#define MPI2_SAS_HWRATE_MAX_RATE_3_0                    (0x90)
+#define MPI2_SAS_HWRATE_MAX_RATE_6_0                    (0xA0)
+#define MPI2_SAS_HWRATE_MIN_RATE_MASK                   (0x0F)
+#define MPI2_SAS_HWRATE_MIN_RATE_1_5                    (0x08)
+#define MPI2_SAS_HWRATE_MIN_RATE_3_0                    (0x09)
+#define MPI2_SAS_HWRATE_MIN_RATE_6_0                    (0x0A)
+#define MPI25_SAS_HWRATE_MIN_RATE_12_0                  (0x0B)
+
+
+
+/****************************************************************************
+*  SAS IO Unit Config Pages
+****************************************************************************/
+
+/*SAS IO Unit Page 0 */
+
+typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA {
+       U8          Port;                   /*0x00 */
+       U8          PortFlags;              /*0x01 */
+       U8          PhyFlags;               /*0x02 */
+       U8          NegotiatedLinkRate;     /*0x03 */
+       U32         ControllerPhyDeviceInfo;/*0x04 */
+       U16         AttachedDevHandle;      /*0x08 */
+       U16         ControllerDevHandle;    /*0x0A */
+       U32         DiscoveryStatus;        /*0x0C */
+       U32         Reserved;               /*0x10 */
+} MPI2_SAS_IO_UNIT0_PHY_DATA,
+       *PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
+       Mpi2SasIOUnit0PhyData_t,
+       *pMpi2SasIOUnit0PhyData_t;
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
+#define MPI2_SAS_IOUNIT0_PHY_MAX        (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;   /*0x00 */
+       U32                                 Reserved1;/*0x08 */
+       U8                                  NumPhys;  /*0x0C */
+       U8                                  Reserved2;/*0x0D */
+       U16                                 Reserved3;/*0x0E */
+       MPI2_SAS_IO_UNIT0_PHY_DATA
+               PhyData[MPI2_SAS_IOUNIT0_PHY_MAX];    /*0x10 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_0,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
+       Mpi2SasIOUnitPage0_t, *pMpi2SasIOUnitPage0_t;
+
+#define MPI2_SASIOUNITPAGE0_PAGEVERSION                     (0x05)
+
+/*values for SAS IO Unit Page 0 PortFlags */
+#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS     (0x08)
+#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG          (0x01)
+
+/*values for SAS IO Unit Page 0 PhyFlags */
+#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED             (0x10)
+#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED               (0x08)
+
+/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/*see mpi2_sas.h for values for
+ *SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
+
+/*values for SAS IO Unit Page 0 DiscoveryStatus */
+#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED            (0x80000000)
+#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED             (0x40000000)
+#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED               (0x20000000)
+#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED             (0x10000000)
+#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR             (0x08000000)
+#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE    (0x00008000)
+#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE            (0x00004000)
+#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN                (0x00002000)
+#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK        (0x00001000)
+#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
+#define MPI2_SASIOUNIT0_DS_TABLE_LINK                       (0x00000400)
+#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK                 (0x00000200)
+#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR                    (0x00000100)
+#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED              (0x00000080)
+#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST                  (0x00000040)
+#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES                (0x00000020)
+#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT                      (0x00000010)
+#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS                   (0x00000004)
+#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE             (0x00000002)
+#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED                    (0x00000001)
+
+
+/*SAS IO Unit Page 1 */
+
+typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA {
+       U8          Port;                       /*0x00 */
+       U8          PortFlags;                  /*0x01 */
+       U8          PhyFlags;                   /*0x02 */
+       U8          MaxMinLinkRate;             /*0x03 */
+       U32         ControllerPhyDeviceInfo;    /*0x04 */
+       U16         MaxTargetPortConnectTime;   /*0x08 */
+       U16         Reserved1;                  /*0x0A */
+} MPI2_SAS_IO_UNIT1_PHY_DATA,
+       *PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
+       Mpi2SasIOUnit1PhyData_t,
+       *pMpi2SasIOUnit1PhyData_t;
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
+#define MPI2_SAS_IOUNIT1_PHY_MAX        (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header; /*0x00 */
+       U16
+               ControlFlags;                       /*0x08 */
+       U16
+               SASNarrowMaxQueueDepth;             /*0x0A */
+       U16
+               AdditionalControlFlags;             /*0x0C */
+       U16
+               SASWideMaxQueueDepth;               /*0x0E */
+       U8
+               NumPhys;                            /*0x10 */
+       U8
+               SATAMaxQDepth;                      /*0x11 */
+       U8
+               ReportDeviceMissingDelay;           /*0x12 */
+       U8
+               IODeviceMissingDelay;               /*0x13 */
+       MPI2_SAS_IO_UNIT1_PHY_DATA
+               PhyData[MPI2_SAS_IOUNIT1_PHY_MAX];  /*0x14 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_1,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
+       Mpi2SasIOUnitPage1_t, *pMpi2SasIOUnitPage1_t;
+
+#define MPI2_SASIOUNITPAGE1_PAGEVERSION     (0x09)
+
+/*values for SAS IO Unit Page 1 ControlFlags */
+#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST                    (0x8000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX                        (0x4000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX                        (0x2000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE                    (0x1000)
+
+#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT                    (0x0600)
+#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT                   (9)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH                    (0x0)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT                     (0x1)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT                    (0x2)
+
+#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED             (0x0080)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED                 (0x0040)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED                   (0x0020)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED                   (0x0010)
+#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL           (0x0008)
+#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL                 (0x0004)
+#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY                 (0x0002)
+#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION                   (0x0001)
+
+/*values for SAS IO Unit Page 1 AdditionalControlFlags */
+#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL          (0x0080)
+#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
+#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION        (0x0020)
+#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
+#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET  (0x0008)
+#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET   (0x0004)
+#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET     (0x0002)
+#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE               (0x0001)
+
+/*defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
+#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK                 (0x7F)
+#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16                      (0x80)
+
+/*values for SAS IO Unit Page 1 PortFlags */
+#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG                 (0x01)
+
+/*values for SAS IO Unit Page 1 PhyFlags */
+#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE                      (0x10)
+#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE                        (0x08)
+
+/*values for SAS IO Unit Page 1 MaxMinLinkRate */
+#define MPI2_SASIOUNIT1_MAX_RATE_MASK                               (0xF0)
+#define MPI2_SASIOUNIT1_MAX_RATE_1_5                                (0x80)
+#define MPI2_SASIOUNIT1_MAX_RATE_3_0                                (0x90)
+#define MPI2_SASIOUNIT1_MAX_RATE_6_0                                (0xA0)
+#define MPI25_SASIOUNIT1_MAX_RATE_12_0                              (0xB0)
+#define MPI2_SASIOUNIT1_MIN_RATE_MASK                               (0x0F)
+#define MPI2_SASIOUNIT1_MIN_RATE_1_5                                (0x08)
+#define MPI2_SASIOUNIT1_MIN_RATE_3_0                                (0x09)
+#define MPI2_SASIOUNIT1_MIN_RATE_6_0                                (0x0A)
+#define MPI25_SASIOUNIT1_MIN_RATE_12_0                              (0x0B)
+
+/*see mpi2_sas.h for values for
+ *SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
+
+
+/*SAS IO Unit Page 4 */
+
+typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP {
+       U8          MaxTargetSpinup;            /*0x00 */
+       U8          SpinupDelay;                /*0x01 */
+       U8          SpinupFlags;                /*0x02 */
+       U8          Reserved1;                  /*0x03 */
+} MPI2_SAS_IOUNIT4_SPINUP_GROUP,
+       *PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
+       Mpi2SasIOUnit4SpinupGroup_t,
+       *pMpi2SasIOUnit4SpinupGroup_t;
+/*defines for SAS IO Unit Page 4 SpinupFlags */
+#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG         (0x01)
+
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
+#define MPI2_SAS_IOUNIT4_PHY_MAX        (4)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;/*0x00 */
+       MPI2_SAS_IOUNIT4_SPINUP_GROUP
+               SpinupGroupParameters[4];       /*0x08 */
+       U32
+               Reserved1;                      /*0x18 */
+       U32
+               Reserved2;                      /*0x1C */
+       U32
+               Reserved3;                      /*0x20 */
+       U8
+               BootDeviceWaitTime;             /*0x24 */
+       U8
+               Reserved4;                      /*0x25 */
+       U16
+               Reserved5;                      /*0x26 */
+       U8
+               NumPhys;                        /*0x28 */
+       U8
+               PEInitialSpinupDelay;           /*0x29 */
+       U8
+               PEReplyDelay;                   /*0x2A */
+       U8
+               Flags;                          /*0x2B */
+       U8
+               PHY[MPI2_SAS_IOUNIT4_PHY_MAX];  /*0x2C */
+} MPI2_CONFIG_PAGE_SASIOUNIT_4,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
+       Mpi2SasIOUnitPage4_t, *pMpi2SasIOUnitPage4_t;
+
+#define MPI2_SASIOUNITPAGE4_PAGEVERSION     (0x02)
+
+/*defines for Flags field */
+#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE               (0x01)
+
+/*defines for PHY field */
+#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK               (0x03)
+
+
+/*SAS IO Unit Page 5 */
+
+typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS {
+       U8          ControlFlags;               /*0x00 */
+       U8          PortWidthModGroup;          /*0x01 */
+       U16         InactivityTimerExponent;    /*0x02 */
+       U8          SATAPartialTimeout;         /*0x04 */
+       U8          Reserved2;                  /*0x05 */
+       U8          SATASlumberTimeout;         /*0x06 */
+       U8          Reserved3;                  /*0x07 */
+       U8          SASPartialTimeout;          /*0x08 */
+       U8          Reserved4;                  /*0x09 */
+       U8          SASSlumberTimeout;          /*0x0A */
+       U8          Reserved5;                  /*0x0B */
+} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
+       *PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
+       Mpi2SasIOUnit5PhyPmSettings_t,
+       *pMpi2SasIOUnit5PhyPmSettings_t;
+
+/*defines for ControlFlags field */
+#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE      (0x08)
+#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE      (0x04)
+#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE     (0x02)
+#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE     (0x01)
+
+/*defines for PortWidthModeGroup field */
+#define MPI2_SASIOUNIT5_PWMG_DISABLE                    (0xFF)
+
+/*defines for InactivityTimerExponent field */
+#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER            (0x7000)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER           (12)
+#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL            (0x0700)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL           (8)
+#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER           (0x0070)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER          (4)
+#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL           (0x0007)
+#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL          (0)
+
+#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS                 (7)
+#define MPI2_SASIOUNIT5_ITE_ONE_SECOND                  (6)
+#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS        (5)
+#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS            (4)
+#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND             (3)
+#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS        (2)
+#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS            (1)
+#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND             (0)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
+#define MPI2_SAS_IOUNIT5_PHY_MAX        (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;   /*0x00 */
+       U8                                  NumPhys;  /*0x08 */
+       U8                                  Reserved1;/*0x09 */
+       U16                                 Reserved2;/*0x0A */
+       U32                                 Reserved3;/*0x0C */
+       MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS
+       SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];/*0x10 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_5,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
+       Mpi2SasIOUnitPage5_t, *pMpi2SasIOUnitPage5_t;
+
+#define MPI2_SASIOUNITPAGE5_PAGEVERSION     (0x01)
+
+
+/*SAS IO Unit Page 6 */
+
+typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS {
+       U8          CurrentStatus;              /*0x00 */
+       U8          CurrentModulation;          /*0x01 */
+       U8          CurrentUtilization;         /*0x02 */
+       U8          Reserved1;                  /*0x03 */
+       U32         Reserved2;                  /*0x04 */
+} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
+       *PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
+       Mpi2SasIOUnit6PortWidthModGroupStatus_t,
+       *pMpi2SasIOUnit6PortWidthModGroupStatus_t;
+
+/*defines for CurrentStatus field */
+#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE                      (0x00)
+#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED                     (0x01)
+#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG                   (0x02)
+#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN                        (0x03)
+#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY                 (0x04)
+#define MPI2_SASIOUNIT6_STATUS_INACTIVE                         (0x05)
+#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT                    (0x06)
+#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST                      (0x07)
+
+/*defines for CurrentModulation field */
+#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT                   (0x00)
+#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT                   (0x01)
+#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT                   (0x02)
+#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT                  (0x03)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumGroups at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
+#define MPI2_SAS_IOUNIT6_GROUP_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /*0x00 */
+       U32                                 Reserved1;              /*0x08 */
+       U32                                 Reserved2;              /*0x0C */
+       U8                                  NumGroups;              /*0x10 */
+       U8                                  Reserved3;              /*0x11 */
+       U16                                 Reserved4;              /*0x12 */
+       MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
+       PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /*0x14 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_6,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
+       Mpi2SasIOUnitPage6_t, *pMpi2SasIOUnitPage6_t;
+
+#define MPI2_SASIOUNITPAGE6_PAGEVERSION     (0x00)
+
+
+/*SAS IO Unit Page 7 */
+
+typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS {
+       U8          Flags;                      /*0x00 */
+       U8          Reserved1;                  /*0x01 */
+       U16         Reserved2;                  /*0x02 */
+       U8          Threshold75Pct;             /*0x04 */
+       U8          Threshold50Pct;             /*0x05 */
+       U8          Threshold25Pct;             /*0x06 */
+       U8          Reserved3;                  /*0x07 */
+} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
+       *PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
+       Mpi2SasIOUnit7PortWidthModGroupSettings_t,
+       *pMpi2SasIOUnit7PortWidthModGroupSettings_t;
+
+/*defines for Flags field */
+#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION  (0x01)
+
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumGroups at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
+#define MPI2_SAS_IOUNIT7_GROUP_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER Header;             /*0x00 */
+       U8                               SamplingInterval;   /*0x08 */
+       U8                               WindowLength;       /*0x09 */
+       U16                              Reserved1;          /*0x0A */
+       U32                              Reserved2;          /*0x0C */
+       U32                              Reserved3;          /*0x10 */
+       U8                               NumGroups;          /*0x14 */
+       U8                               Reserved4;          /*0x15 */
+       U16                              Reserved5;          /*0x16 */
+       MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
+       PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX];/*0x18 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_7,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
+       Mpi2SasIOUnitPage7_t, *pMpi2SasIOUnitPage7_t;
+
+#define MPI2_SASIOUNITPAGE7_PAGEVERSION     (0x00)
+
+
+/*SAS IO Unit Page 8 */
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                         /*0x00 */
+       U32
+               Reserved1;                      /*0x08 */
+       U32
+               PowerManagementCapabilities;    /*0x0C */
+       U8
+               TxRxSleepStatus;                /*0x10 */
+       U8
+               Reserved2;                      /*0x11 */
+       U16
+               Reserved3;                      /*0x12 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_8,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8,
+       Mpi2SasIOUnitPage8_t, *pMpi2SasIOUnitPage8_t;
+
+#define MPI2_SASIOUNITPAGE8_PAGEVERSION     (0x00)
+
+/*defines for PowerManagementCapabilities field */
+#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD          (0x00001000)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE        (0x00000800)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE        (0x00000400)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE       (0x00000200)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE       (0x00000100)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD        (0x00000010)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE      (0x00000008)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE      (0x00000004)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE     (0x00000002)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE     (0x00000001)
+
+/*defines for TxRxSleepStatus field */
+#define MPI25_SASIOUNIT8_TXRXSLEEP_UNSUPPORTED          (0x00)
+#define MPI25_SASIOUNIT8_TXRXSLEEP_DISENGAGED           (0x01)
+#define MPI25_SASIOUNIT8_TXRXSLEEP_ACTIVE               (0x02)
+#define MPI25_SASIOUNIT8_TXRXSLEEP_SHUTDOWN             (0x03)
+
+
+
+/*SAS IO Unit Page 16 */
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                             /*0x00 */
+       U64
+               TimeStamp;                          /*0x08 */
+       U32
+               Reserved1;                          /*0x10 */
+       U32
+               Reserved2;                          /*0x14 */
+       U32
+               FastPathPendedRequests;             /*0x18 */
+       U32
+               FastPathUnPendedRequests;           /*0x1C */
+       U32
+               FastPathHostRequestStarts;          /*0x20 */
+       U32
+               FastPathFirmwareRequestStarts;      /*0x24 */
+       U32
+               FastPathHostCompletions;            /*0x28 */
+       U32
+               FastPathFirmwareCompletions;        /*0x2C */
+       U32
+               NonFastPathRequestStarts;           /*0x30 */
+       U32
+               NonFastPathHostCompletions;         /*0x30 */
+} MPI2_CONFIG_PAGE_SASIOUNIT16,
+       *PTR_MPI2_CONFIG_PAGE_SASIOUNIT16,
+       Mpi2SasIOUnitPage16_t, *pMpi2SasIOUnitPage16_t;
+
+#define MPI2_SASIOUNITPAGE16_PAGEVERSION    (0x00)
+
+
+/****************************************************************************
+*  SAS Expander Config Pages
+****************************************************************************/
+
+/*SAS Expander Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U8
+               PhysicalPort;               /*0x08 */
+       U8
+               ReportGenLength;            /*0x09 */
+       U16
+               EnclosureHandle;            /*0x0A */
+       U64
+               SASAddress;                 /*0x0C */
+       U32
+               DiscoveryStatus;            /*0x14 */
+       U16
+               DevHandle;                  /*0x18 */
+       U16
+               ParentDevHandle;            /*0x1A */
+       U16
+               ExpanderChangeCount;        /*0x1C */
+       U16
+               ExpanderRouteIndexes;       /*0x1E */
+       U8
+               NumPhys;                    /*0x20 */
+       U8
+               SASLevel;                   /*0x21 */
+       U16
+               Flags;                      /*0x22 */
+       U16
+               STPBusInactivityTimeLimit;  /*0x24 */
+       U16
+               STPMaxConnectTimeLimit;     /*0x26 */
+       U16
+               STP_SMP_NexusLossTime;      /*0x28 */
+       U16
+               MaxNumRoutedSasAddresses;   /*0x2A */
+       U64
+               ActiveZoneManagerSASAddress;/*0x2C */
+       U16
+               ZoneLockInactivityLimit;    /*0x34 */
+       U16
+               Reserved1;                  /*0x36 */
+       U8
+               TimeToReducedFunc;          /*0x38 */
+       U8
+               InitialTimeToReducedFunc;   /*0x39 */
+       U8
+               MaxReducedFuncTime;         /*0x3A */
+       U8
+               Reserved2;                  /*0x3B */
+} MPI2_CONFIG_PAGE_EXPANDER_0,
+       *PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
+       Mpi2ExpanderPage0_t, *pMpi2ExpanderPage0_t;
+
+#define MPI2_SASEXPANDER0_PAGEVERSION       (0x06)
+
+/*values for SAS Expander Page 0 DiscoveryStatus field */
+#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED         (0x80000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED          (0x40000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED            (0x20000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED          (0x10000000)
+#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR          (0x08000000)
+#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
+#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE         (0x00004000)
+#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN             (0x00002000)
+#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK     (0x00001000)
+#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE            (0x00000800)
+#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK                    (0x00000400)
+#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK              (0x00000200)
+#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR                 (0x00000100)
+#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED           (0x00000080)
+#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST               (0x00000040)
+#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES             (0x00000020)
+#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT                   (0x00000010)
+#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS                (0x00000004)
+#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE          (0x00000002)
+#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED                 (0x00000001)
+
+/*values for SAS Expander Page 0 Flags field */
+#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY      (0x2000)
+#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED                (0x1000)
+#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES    (0x0800)
+#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES     (0x0400)
+#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT             (0x0200)
+#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING             (0x0100)
+#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT     (0x0080)
+#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE       (0x0010)
+#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG              (0x0004)
+#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS         (0x0002)
+#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG         (0x0001)
+
+
+/*SAS Expander Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U8
+               PhysicalPort;               /*0x08 */
+       U8
+               Reserved1;                  /*0x09 */
+       U16
+               Reserved2;                  /*0x0A */
+       U8
+               NumPhys;                    /*0x0C */
+       U8
+               Phy;                        /*0x0D */
+       U16
+               NumTableEntriesProgrammed;  /*0x0E */
+       U8
+               ProgrammedLinkRate;         /*0x10 */
+       U8
+               HwLinkRate;                 /*0x11 */
+       U16
+               AttachedDevHandle;          /*0x12 */
+       U32
+               PhyInfo;                    /*0x14 */
+       U32
+               AttachedDeviceInfo;         /*0x18 */
+       U16
+               ExpanderDevHandle;          /*0x1C */
+       U8
+               ChangeCount;                /*0x1E */
+       U8
+               NegotiatedLinkRate;         /*0x1F */
+       U8
+               PhyIdentifier;              /*0x20 */
+       U8
+               AttachedPhyIdentifier;      /*0x21 */
+       U8
+               Reserved3;                  /*0x22 */
+       U8
+               DiscoveryInfo;              /*0x23 */
+       U32
+               AttachedPhyInfo;            /*0x24 */
+       U8
+               ZoneGroup;                  /*0x28 */
+       U8
+               SelfConfigStatus;           /*0x29 */
+       U16
+               Reserved4;                  /*0x2A */
+} MPI2_CONFIG_PAGE_EXPANDER_1,
+       *PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
+       Mpi2ExpanderPage1_t, *pMpi2ExpanderPage1_t;
+
+#define MPI2_SASEXPANDER1_PAGEVERSION       (0x02)
+
+/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
+
+/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
+
+/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */
+
+/*see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines
+ *used for the AttachedDeviceInfo field */
+
+/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/*values for SAS Expander Page 1 DiscoveryInfo field */
+#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED    (0x04)
+#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE  (0x02)
+#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES  (0x01)
+
+/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
+
+
+/****************************************************************************
+*  SAS Device Config Pages
+****************************************************************************/
+
+/*SAS Device Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                 /*0x00 */
+       U16
+               Slot;                   /*0x08 */
+       U16
+               EnclosureHandle;        /*0x0A */
+       U64
+               SASAddress;             /*0x0C */
+       U16
+               ParentDevHandle;        /*0x14 */
+       U8
+               PhyNum;                 /*0x16 */
+       U8
+               AccessStatus;           /*0x17 */
+       U16
+               DevHandle;              /*0x18 */
+       U8
+               AttachedPhyIdentifier;  /*0x1A */
+       U8
+               ZoneGroup;              /*0x1B */
+       U32
+               DeviceInfo;             /*0x1C */
+       U16
+               Flags;                  /*0x20 */
+       U8
+               PhysicalPort;           /*0x22 */
+       U8
+               MaxPortConnections;     /*0x23 */
+       U64
+               DeviceName;             /*0x24 */
+       U8
+               PortGroups;             /*0x2C */
+       U8
+               DmaGroup;               /*0x2D */
+       U8
+               ControlGroup;           /*0x2E */
+       U8
+               Reserved1;              /*0x2F */
+       U32
+               Reserved2;              /*0x30 */
+       U32
+               Reserved3;              /*0x34 */
+} MPI2_CONFIG_PAGE_SAS_DEV_0,
+       *PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
+       Mpi2SasDevicePage0_t,
+       *pMpi2SasDevicePage0_t;
+
+#define MPI2_SASDEVICE0_PAGEVERSION         (0x08)
+
+/*values for SAS Device Page 0 AccessStatus field */
+#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS                  (0x00)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED           (0x01)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED     (0x02)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT  (0x03)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION  (0x04)
+#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE      (0x05)
+#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE  (0x06)
+#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED             (0x07)
+/*specific values for SATA Init failures */
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN                (0x10)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT   (0x11)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG                   (0x12)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION         (0x13)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER            (0x14)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN                 (0x15)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN                (0x16)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN                (0x17)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION       (0x18)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE        (0x19)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX                    (0x1F)
+
+/*see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
+
+/*values for SAS Device Page 0 Flags field */
+#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE          (0x8000)
+#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH           (0x4000)
+#define MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE           (0x2000)
+#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE           (0x1000)
+#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE           (0x0800)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY     (0x0400)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE             (0x0200)
+#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE           (0x0100)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED     (0x0080)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED         (0x0040)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED           (0x0020)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED           (0x0010)
+#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH         (0x0008)
+#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT               (0x0001)
+
+
+/*SAS Device Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                 /*0x00 */
+       U32
+               Reserved1;              /*0x08 */
+       U64
+               SASAddress;             /*0x0C */
+       U32
+               Reserved2;              /*0x14 */
+       U16
+               DevHandle;              /*0x18 */
+       U16
+               Reserved3;              /*0x1A */
+       U8
+               InitialRegDeviceFIS[20];/*0x1C */
+} MPI2_CONFIG_PAGE_SAS_DEV_1,
+       *PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
+       Mpi2SasDevicePage1_t,
+       *pMpi2SasDevicePage1_t;
+
+#define MPI2_SASDEVICE1_PAGEVERSION         (0x01)
+
+
+/****************************************************************************
+*  SAS PHY Config Pages
+****************************************************************************/
+
+/*SAS PHY Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                 /*0x00 */
+       U16
+               OwnerDevHandle;         /*0x08 */
+       U16
+               Reserved1;              /*0x0A */
+       U16
+               AttachedDevHandle;      /*0x0C */
+       U8
+               AttachedPhyIdentifier;  /*0x0E */
+       U8
+               Reserved2;              /*0x0F */
+       U32
+               AttachedPhyInfo;        /*0x10 */
+       U8
+               ProgrammedLinkRate;     /*0x14 */
+       U8
+               HwLinkRate;             /*0x15 */
+       U8
+               ChangeCount;            /*0x16 */
+       U8
+               Flags;                  /*0x17 */
+       U32
+               PhyInfo;                /*0x18 */
+       U8
+               NegotiatedLinkRate;     /*0x1C */
+       U8
+               Reserved3;              /*0x1D */
+       U16
+               Reserved4;              /*0x1E */
+} MPI2_CONFIG_PAGE_SAS_PHY_0,
+       *PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
+       Mpi2SasPhyPage0_t, *pMpi2SasPhyPage0_t;
+
+#define MPI2_SASPHY0_PAGEVERSION            (0x03)
+
+/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
+
+/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
+
+/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
+
+/*values for SAS PHY Page 0 Flags field */
+#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC             (0x01)
+
+/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */
+
+/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+
+/*SAS PHY Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U32
+               Reserved1;                  /*0x08 */
+       U32
+               InvalidDwordCount;          /*0x0C */
+       U32
+               RunningDisparityErrorCount; /*0x10 */
+       U32
+               LossDwordSynchCount;        /*0x14 */
+       U32
+               PhyResetProblemCount;       /*0x18 */
+} MPI2_CONFIG_PAGE_SAS_PHY_1,
+       *PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
+       Mpi2SasPhyPage1_t, *pMpi2SasPhyPage1_t;
+
+#define MPI2_SASPHY1_PAGEVERSION            (0x01)
+
+
+/*SAS PHY Page 2 */
+
+typedef struct _MPI2_SASPHY2_PHY_EVENT {
+       U8          PhyEventCode;       /*0x00 */
+       U8          Reserved1;          /*0x01 */
+       U16         Reserved2;          /*0x02 */
+       U32         PhyEventInfo;       /*0x04 */
+} MPI2_SASPHY2_PHY_EVENT, *PTR_MPI2_SASPHY2_PHY_EVENT,
+       Mpi2SasPhy2PhyEvent_t, *pMpi2SasPhy2PhyEvent_t;
+
+/*use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */
+
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhyEvents at runtime.
+ */
+#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
+#define MPI2_SASPHY2_PHY_EVENT_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U32
+               Reserved1;                  /*0x08 */
+       U8
+               NumPhyEvents;               /*0x0C */
+       U8
+               Reserved2;                  /*0x0D */
+       U16
+               Reserved3;                  /*0x0E */
+       MPI2_SASPHY2_PHY_EVENT
+               PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /*0x10 */
+} MPI2_CONFIG_PAGE_SAS_PHY_2,
+       *PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
+       Mpi2SasPhyPage2_t,
+       *pMpi2SasPhyPage2_t;
+
+#define MPI2_SASPHY2_PAGEVERSION            (0x00)
+
+
+/*SAS PHY Page 3 */
+
+typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
+       U8          PhyEventCode;       /*0x00 */
+       U8          Reserved1;          /*0x01 */
+       U16         Reserved2;          /*0x02 */
+       U8          CounterType;        /*0x04 */
+       U8          ThresholdWindow;    /*0x05 */
+       U8          TimeUnits;          /*0x06 */
+       U8          Reserved3;          /*0x07 */
+       U32         EventThreshold;     /*0x08 */
+       U16         ThresholdFlags;     /*0x0C */
+       U16         Reserved4;          /*0x0E */
+} MPI2_SASPHY3_PHY_EVENT_CONFIG,
+       *PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG,
+       Mpi2SasPhy3PhyEventConfig_t,
+       *pMpi2SasPhy3PhyEventConfig_t;
+
+/*values for PhyEventCode field */
+#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT                    (0x00)
+#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD               (0x01)
+#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR     (0x02)
+#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC             (0x03)
+#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM           (0x04)
+#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW     (0x05)
+#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR                    (0x06)
+#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR         (0x20)
+#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT           (0x21)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT           (0x22)
+#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT           (0x23)
+#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT           (0x24)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON   (0x25)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON   (0x26)
+#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK                    (0x27)
+#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK                    (0x28)
+#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT               (0x29)
+#define MPI2_SASPHY3_EVENT_CODE_CONNECTION                  (0x2A)
+#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED      (0x2B)
+#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME        (0x2C)
+#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME          (0x2D)
+#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME           (0x2E)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES               (0x40)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES               (0x41)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES         (0x42)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES         (0x43)
+#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED           (0x44)
+#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED           (0x45)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES              (0x50)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES              (0x51)
+#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW               (0x52)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES               (0x60)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES               (0x61)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES         (0x63)
+#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT             (0xD0)
+#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE    (0xD1)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP                      (0xD2)
+
+/*values for the CounterType field */
+#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING                  (0x00)
+#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING                (0x01)
+#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE                (0x02)
+
+/*values for the TimeUnits field */
+#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS             (0x00)
+#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS            (0x01)
+#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND               (0x02)
+#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS             (0x03)
+
+/*values for the ThresholdFlags field */
+#define MPI2_SASPHY3_TFLAGS_PHY_RESET                       (0x0002)
+#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY                    (0x0001)
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumPhyEvents at runtime.
+ */
+#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
+#define MPI2_SASPHY3_PHY_EVENT_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U32
+               Reserved1;                  /*0x08 */
+       U8
+               NumPhyEvents;               /*0x0C */
+       U8
+               Reserved2;                  /*0x0D */
+       U16
+               Reserved3;                  /*0x0E */
+       MPI2_SASPHY3_PHY_EVENT_CONFIG
+               PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /*0x10 */
+} MPI2_CONFIG_PAGE_SAS_PHY_3,
+       *PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
+       Mpi2SasPhyPage3_t, *pMpi2SasPhyPage3_t;
+
+#define MPI2_SASPHY3_PAGEVERSION            (0x00)
+
+
+/*SAS PHY Page 4 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U16
+               Reserved1;                  /*0x08 */
+       U8
+               Reserved2;                  /*0x0A */
+       U8
+               Flags;                      /*0x0B */
+       U8
+               InitialFrame[28];           /*0x0C */
+} MPI2_CONFIG_PAGE_SAS_PHY_4,
+       *PTR_MPI2_CONFIG_PAGE_SAS_PHY_4,
+       Mpi2SasPhyPage4_t, *pMpi2SasPhyPage4_t;
+
+#define MPI2_SASPHY4_PAGEVERSION            (0x00)
+
+/*values for the Flags field */
+#define MPI2_SASPHY4_FLAGS_FRAME_VALID        (0x02)
+#define MPI2_SASPHY4_FLAGS_SATA_FRAME         (0x01)
+
+
+
+
+/****************************************************************************
+*  SAS Port Config Pages
+****************************************************************************/
+
+/*SAS Port Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U8
+               PortNumber;                 /*0x08 */
+       U8
+               PhysicalPort;               /*0x09 */
+       U8
+               PortWidth;                  /*0x0A */
+       U8
+               PhysicalPortWidth;          /*0x0B */
+       U8
+               ZoneGroup;                  /*0x0C */
+       U8
+               Reserved1;                  /*0x0D */
+       U16
+               Reserved2;                  /*0x0E */
+       U64
+               SASAddress;                 /*0x10 */
+       U32
+               DeviceInfo;                 /*0x18 */
+       U32
+               Reserved3;                  /*0x1C */
+       U32
+               Reserved4;                  /*0x20 */
+} MPI2_CONFIG_PAGE_SAS_PORT_0,
+       *PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
+       Mpi2SasPortPage0_t, *pMpi2SasPortPage0_t;
+
+#define MPI2_SASPORT0_PAGEVERSION           (0x00)
+
+/*see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
+
+
+/****************************************************************************
+*  SAS Enclosure Config Pages
+****************************************************************************/
+
+/*SAS Enclosure Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                     /*0x00 */
+       U32
+               Reserved1;                  /*0x08 */
+       U64
+               EnclosureLogicalID;         /*0x0C */
+       U16
+               Flags;                      /*0x14 */
+       U16
+               EnclosureHandle;            /*0x16 */
+       U16
+               NumSlots;                   /*0x18 */
+       U16
+               StartSlot;                  /*0x1A */
+       U16
+               Reserved2;                  /*0x1C */
+       U16
+               SEPDevHandle;               /*0x1E */
+       U32
+               Reserved3;                  /*0x20 */
+       U32
+               Reserved4;                  /*0x24 */
+} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
+       *PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
+       Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t;
+
+#define MPI2_SASENCLOSURE0_PAGEVERSION      (0x03)
+
+/*values for SAS Enclosure Page 0 Flags field */
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK              (0x000F)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN           (0x0000)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES           (0x0001)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO         (0x0002)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO         (0x0003)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE     (0x0004)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO          (0x0005)
+
+
+/****************************************************************************
+*  Log Config Page
+****************************************************************************/
+
+/*Log Page 0 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumLogEntries at runtime.
+ */
+#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
+#define MPI2_LOG_0_NUM_LOG_ENTRIES          (1)
+#endif
+
+#define MPI2_LOG_0_LOG_DATA_LENGTH          (0x1C)
+
+typedef struct _MPI2_LOG_0_ENTRY {
+       U64         TimeStamp;                      /*0x00 */
+       U32         Reserved1;                      /*0x08 */
+       U16         LogSequence;                    /*0x0C */
+       U16         LogEntryQualifier;              /*0x0E */
+       U8          VP_ID;                          /*0x10 */
+       U8          VF_ID;                          /*0x11 */
+       U16         Reserved2;                      /*0x12 */
+       U8
+               LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/*0x14 */
+} MPI2_LOG_0_ENTRY, *PTR_MPI2_LOG_0_ENTRY,
+       Mpi2Log0Entry_t, *pMpi2Log0Entry_t;
+
+/*values for Log Page 0 LogEntry LogEntryQualifier field */
+#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED          (0x0000)
+#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET        (0x0001)
+#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE      (0x0002)
+#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC    (0x8000)
+#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC    (0xFFFF)
+
+typedef struct _MPI2_CONFIG_PAGE_LOG_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;       /*0x00 */
+       U32                                 Reserved1;    /*0x08 */
+       U32                                 Reserved2;    /*0x0C */
+       U16                                 NumLogEntries;/*0x10 */
+       U16                                 Reserved3;    /*0x12 */
+       MPI2_LOG_0_ENTRY
+               LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /*0x14 */
+} MPI2_CONFIG_PAGE_LOG_0, *PTR_MPI2_CONFIG_PAGE_LOG_0,
+       Mpi2LogPage0_t, *pMpi2LogPage0_t;
+
+#define MPI2_LOG_0_PAGEVERSION              (0x02)
+
+
+/****************************************************************************
+*  RAID Config Page
+****************************************************************************/
+
+/*RAID Page 0 */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check the value returned for NumElements at runtime.
+ */
+#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
+#define MPI2_RAIDCONFIG0_MAX_ELEMENTS       (1)
+#endif
+
+typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT {
+       U16                     ElementFlags;             /*0x00 */
+       U16                     VolDevHandle;             /*0x02 */
+       U8                      HotSparePool;             /*0x04 */
+       U8                      PhysDiskNum;              /*0x05 */
+       U16                     PhysDiskDevHandle;        /*0x06 */
+} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
+       *PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
+       Mpi2RaidConfig0ConfigElement_t,
+       *pMpi2RaidConfig0ConfigElement_t;
+
+/*values for the ElementFlags field */
+#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE       (0x000F)
+#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT          (0x0000)
+#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT   (0x0001)
+#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT       (0x0002)
+#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT             (0x0003)
+
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;         /*0x00 */
+       U8                                  NumHotSpares;   /*0x08 */
+       U8                                  NumPhysDisks;   /*0x09 */
+       U8                                  NumVolumes;     /*0x0A */
+       U8                                  ConfigNum;      /*0x0B */
+       U32                                 Flags;          /*0x0C */
+       U8                                  ConfigGUID[24]; /*0x10 */
+       U32                                 Reserved1;      /*0x28 */
+       U8                                  NumElements;    /*0x2C */
+       U8                                  Reserved2;      /*0x2D */
+       U16                                 Reserved3;      /*0x2E */
+       MPI2_RAIDCONFIG0_CONFIG_ELEMENT
+               ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /*0x30 */
+} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
+       *PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
+       Mpi2RaidConfigurationPage0_t,
+       *pMpi2RaidConfigurationPage0_t;
+
+#define MPI2_RAIDCONFIG0_PAGEVERSION            (0x00)
+
+/*values for RAID Configuration Page 0 Flags field */
+#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG        (0x00000001)
+
+
+/****************************************************************************
+*  Driver Persistent Mapping Config Pages
+****************************************************************************/
+
+/*Driver Persistent Mapping Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY {
+       U64     PhysicalIdentifier;         /*0x00 */
+       U16     MappingInformation;         /*0x08 */
+       U16     DeviceIndex;                /*0x0A */
+       U32     PhysicalBitsMapping;        /*0x0C */
+       U32     Reserved1;                  /*0x10 */
+} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
+       *PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
+       Mpi2DriverMap0Entry_t, *pMpi2DriverMap0Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header; /*0x00 */
+       MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY  Entry;  /*0x08 */
+} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
+       *PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
+       Mpi2DriverMappingPage0_t, *pMpi2DriverMappingPage0_t;
+
+#define MPI2_DRIVERMAPPING0_PAGEVERSION         (0x00)
+
+/*values for Driver Persistent Mapping Page 0 MappingInformation field */
+#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK              (0x07F0)
+#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT             (4)
+#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK           (0x000F)
+
+
+/****************************************************************************
+*  Ethernet Config Pages
+****************************************************************************/
+
+/*Ethernet Page 0 */
+
+/*IP address (union of IPv4 and IPv6) */
+typedef union _MPI2_ETHERNET_IP_ADDR {
+       U32     IPv4Addr;
+       U32     IPv6Addr[4];
+} MPI2_ETHERNET_IP_ADDR, *PTR_MPI2_ETHERNET_IP_ADDR,
+       Mpi2EthernetIpAddr_t, *pMpi2EthernetIpAddr_t;
+
+#define MPI2_ETHERNET_HOST_NAME_LENGTH          (32)
+
+typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;          /*0x00 */
+       U8                                  NumInterfaces;   /*0x08 */
+       U8                                  Reserved0;       /*0x09 */
+       U16                                 Reserved1;       /*0x0A */
+       U32                                 Status;          /*0x0C */
+       U8                                  MediaState;      /*0x10 */
+       U8                                  Reserved2;       /*0x11 */
+       U16                                 Reserved3;       /*0x12 */
+       U8                                  MacAddress[6];   /*0x14 */
+       U8                                  Reserved4;       /*0x1A */
+       U8                                  Reserved5;       /*0x1B */
+       MPI2_ETHERNET_IP_ADDR               IpAddress;       /*0x1C */
+       MPI2_ETHERNET_IP_ADDR               SubnetMask;      /*0x2C */
+       MPI2_ETHERNET_IP_ADDR               GatewayIpAddress;/*0x3C */
+       MPI2_ETHERNET_IP_ADDR               DNS1IpAddress;   /*0x4C */
+       MPI2_ETHERNET_IP_ADDR               DNS2IpAddress;   /*0x5C */
+       MPI2_ETHERNET_IP_ADDR               DhcpIpAddress;   /*0x6C */
+       U8
+               HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */
+} MPI2_CONFIG_PAGE_ETHERNET_0,
+       *PTR_MPI2_CONFIG_PAGE_ETHERNET_0,
+       Mpi2EthernetPage0_t, *pMpi2EthernetPage0_t;
+
+#define MPI2_ETHERNETPAGE0_PAGEVERSION   (0x00)
+
+/*values for Ethernet Page 0 Status field */
+#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE             (0x80000000)
+#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE             (0x40000000)
+#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED        (0x20000000)
+#define MPI2_ETHPG0_STATUS_DEFAULT_IF               (0x00000100)
+#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED         (0x00000080)
+#define MPI2_ETHPG0_STATUS_TELNET_ENABLED           (0x00000040)
+#define MPI2_ETHPG0_STATUS_SSH2_ENABLED             (0x00000020)
+#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED      (0x00000010)
+#define MPI2_ETHPG0_STATUS_IPV6_ENABLED             (0x00000008)
+#define MPI2_ETHPG0_STATUS_IPV4_ENABLED             (0x00000004)
+#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES           (0x00000002)
+#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED           (0x00000001)
+
+/*values for Ethernet Page 0 MediaState field */
+#define MPI2_ETHPG0_MS_DUPLEX_MASK                  (0x80)
+#define MPI2_ETHPG0_MS_HALF_DUPLEX                  (0x00)
+#define MPI2_ETHPG0_MS_FULL_DUPLEX                  (0x80)
+
+#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK           (0x07)
+#define MPI2_ETHPG0_MS_NOT_CONNECTED                (0x00)
+#define MPI2_ETHPG0_MS_10MBIT                       (0x01)
+#define MPI2_ETHPG0_MS_100MBIT                      (0x02)
+#define MPI2_ETHPG0_MS_1GBIT                        (0x03)
+
+
+/*Ethernet Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                 /*0x00 */
+       U32
+               Reserved0;              /*0x08 */
+       U32
+               Flags;                  /*0x0C */
+       U8
+               MediaState;             /*0x10 */
+       U8
+               Reserved1;              /*0x11 */
+       U16
+               Reserved2;              /*0x12 */
+       U8
+               MacAddress[6];          /*0x14 */
+       U8
+               Reserved3;              /*0x1A */
+       U8
+               Reserved4;              /*0x1B */
+       MPI2_ETHERNET_IP_ADDR
+               StaticIpAddress;        /*0x1C */
+       MPI2_ETHERNET_IP_ADDR
+               StaticSubnetMask;       /*0x2C */
+       MPI2_ETHERNET_IP_ADDR
+               StaticGatewayIpAddress; /*0x3C */
+       MPI2_ETHERNET_IP_ADDR
+               StaticDNS1IpAddress;    /*0x4C */
+       MPI2_ETHERNET_IP_ADDR
+               StaticDNS2IpAddress;    /*0x5C */
+       U32
+               Reserved5;              /*0x6C */
+       U32
+               Reserved6;              /*0x70 */
+       U32
+               Reserved7;              /*0x74 */
+       U32
+               Reserved8;              /*0x78 */
+       U8
+               HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */
+} MPI2_CONFIG_PAGE_ETHERNET_1,
+       *PTR_MPI2_CONFIG_PAGE_ETHERNET_1,
+       Mpi2EthernetPage1_t, *pMpi2EthernetPage1_t;
+
+#define MPI2_ETHERNETPAGE1_PAGEVERSION   (0x00)
+
+/*values for Ethernet Page 1 Flags field */
+#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF             (0x00000100)
+#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD         (0x00000080)
+#define MPI2_ETHPG1_FLAG_ENABLE_TELNET              (0x00000040)
+#define MPI2_ETHPG1_FLAG_ENABLE_SSH2                (0x00000020)
+#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT         (0x00000010)
+#define MPI2_ETHPG1_FLAG_ENABLE_IPV6                (0x00000008)
+#define MPI2_ETHPG1_FLAG_ENABLE_IPV4                (0x00000004)
+#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES         (0x00000002)
+#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF              (0x00000001)
+
+/*values for Ethernet Page 1 MediaState field */
+#define MPI2_ETHPG1_MS_DUPLEX_MASK                  (0x80)
+#define MPI2_ETHPG1_MS_HALF_DUPLEX                  (0x00)
+#define MPI2_ETHPG1_MS_FULL_DUPLEX                  (0x80)
+
+#define MPI2_ETHPG1_MS_DATA_RATE_MASK               (0x07)
+#define MPI2_ETHPG1_MS_DATA_RATE_AUTO               (0x00)
+#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT             (0x01)
+#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT            (0x02)
+#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT              (0x03)
+
+
+/****************************************************************************
+*  Extended Manufacturing Config Pages
+****************************************************************************/
+
+/*
+ *Generic structure to use for product-specific extended manufacturing pages
+ *(currently Extended Manufacturing Page 40 through Extended Manufacturing
+ *Page 60).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
+       MPI2_CONFIG_EXTENDED_PAGE_HEADER
+               Header;                 /*0x00 */
+       U32
+               ProductSpecificInfo;    /*0x08 */
+} MPI2_CONFIG_PAGE_EXT_MAN_PS,
+       *PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
+       Mpi2ExtManufacturingPagePS_t,
+       *pMpi2ExtManufacturingPagePS_t;
+
+/*PageVersion should be provided by product-specific code */
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_init.h b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
new file mode 100644 (file)
index 0000000..a079e52
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2000-2012 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2_init.h
+ *         Title:  MPI SCSI initiator mode messages and structures
+ * Creation Date:  June 23, 2006
+ *
+ * mpi2_init.h Version:  02.00.14
+ *
+ * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
+ *       prefix are for use only on MPI v2.5 products, and must not be used
+ *       with MPI v2.0 products. Unless otherwise noted, names beginning with
+ *       MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 10-31-07  02.00.01  Fixed name for pMpi2SCSITaskManagementRequest_t.
+ * 12-18-07  02.00.02  Modified Task Management Target Reset Method defines.
+ * 02-29-08  02.00.03  Added Query Task Set and Query Unit Attention.
+ * 03-03-08  02.00.04  Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
+ * 05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
+ * 10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
+ *                     Control field Task Attribute flags.
+ *                     Moved LUN field defines to mpi2.h becasue they are
+ *                     common to many structures.
+ * 05-06-09  02.00.07  Changed task management type of Query Unit Attention to
+ *                     Query Asynchronous Event.
+ *                     Defined two new bits in the SlotStatus field of the SCSI
+ *                     Enclosure Processor Request and Reply.
+ * 10-28-09  02.00.08  Added defines for decoding the ResponseInfo bytes for
+ *                     both SCSI IO Error Reply and SCSI Task Management Reply.
+ *                     Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
+ *                     Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
+ * 02-10-10  02.00.09  Removed unused structure that had "#if 0" around it.
+ * 05-12-10  02.00.10  Added optional vendor-unique region to SCSI IO Request.
+ * 11-10-10  02.00.11  Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
+ * 11-18-11  02.00.12  Incorporating additions for MPI v2.5.
+ * 02-06-12  02.00.13  Added alternate defines for Task Priority / Command
+ *                     Priority to match SAM-4.
+ *                     Added EEDPErrorOffset to MPI2_SCSI_IO_REPLY.
+ * 07-10-12  02.00.14  Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_INIT_H
+#define MPI2_INIT_H
+
+/*****************************************************************************
+*
+*              SCSI Initiator Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* SCSI IO messages and associated structures
+****************************************************************************/
+
+typedef struct _MPI2_SCSI_IO_CDB_EEDP32 {
+       U8 CDB[20];             /*0x00 */
+       U32 PrimaryReferenceTag;        /*0x14 */
+       U16 PrimaryApplicationTag;      /*0x18 */
+       U16 PrimaryApplicationTagMask;  /*0x1A */
+       U32 TransferLength;     /*0x1C */
+} MPI2_SCSI_IO_CDB_EEDP32, *PTR_MPI2_SCSI_IO_CDB_EEDP32,
+       Mpi2ScsiIoCdbEedp32_t, *pMpi2ScsiIoCdbEedp32_t;
+
+/*MPI v2.0 CDB field */
+typedef union _MPI2_SCSI_IO_CDB_UNION {
+       U8 CDB32[32];
+       MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+       MPI2_SGE_SIMPLE_UNION SGE;
+} MPI2_SCSI_IO_CDB_UNION, *PTR_MPI2_SCSI_IO_CDB_UNION,
+       Mpi2ScsiIoCdb_t, *pMpi2ScsiIoCdb_t;
+
+/*MPI v2.0 SCSI IO Request Message */
+typedef struct _MPI2_SCSI_IO_REQUEST {
+       U16 DevHandle;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved1;          /*0x04 */
+       U8 Reserved2;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U32 SenseBufferLowAddress;      /*0x0C */
+       U16 SGLFlags;           /*0x10 */
+       U8 SenseBufferLength;   /*0x12 */
+       U8 Reserved4;           /*0x13 */
+       U8 SGLOffset0;          /*0x14 */
+       U8 SGLOffset1;          /*0x15 */
+       U8 SGLOffset2;          /*0x16 */
+       U8 SGLOffset3;          /*0x17 */
+       U32 SkipCount;          /*0x18 */
+       U32 DataLength;         /*0x1C */
+       U32 BidirectionalDataLength;    /*0x20 */
+       U16 IoFlags;            /*0x24 */
+       U16 EEDPFlags;          /*0x26 */
+       U32 EEDPBlockSize;      /*0x28 */
+       U32 SecondaryReferenceTag;      /*0x2C */
+       U16 SecondaryApplicationTag;    /*0x30 */
+       U16 ApplicationTagTranslationMask;      /*0x32 */
+       U8 LUN[8];              /*0x34 */
+       U32 Control;            /*0x3C */
+       MPI2_SCSI_IO_CDB_UNION CDB;     /*0x40 */
+
+#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */
+       MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
+#endif
+
+       MPI2_SGE_IO_UNION SGL;  /*0x60 */
+
+} MPI2_SCSI_IO_REQUEST, *PTR_MPI2_SCSI_IO_REQUEST,
+       Mpi2SCSIIORequest_t, *pMpi2SCSIIORequest_t;
+
+/*SCSI IO MsgFlags bits */
+
+/*MsgFlags for SenseBufferAddressSpace */
+#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR        (0x0C)
+#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR      (0x00)
+#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR      (0x04)
+#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR      (0x08)
+#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR   (0x0C)
+
+/*SCSI IO SGLFlags bits */
+
+/*base values for Data Location Address Space */
+#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK              (0x0C)
+#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR            (0x00)
+#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR            (0x04)
+#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR            (0x08)
+#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR         (0x0C)
+
+/*base values for Type */
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK              (0x03)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI               (0x00)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32            (0x01)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64            (0x02)
+
+/*shift values for each sub-field */
+#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT             (12)
+#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT             (8)
+#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT             (4)
+#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT             (0)
+
+/*number of SGLOffset fields */
+#define MPI2_SCSIIO_NUM_SGLOFFSETS                  (4)
+
+/*SCSI IO IoFlags bits */
+
+/*Large CDB Address Space */
+#define MPI2_SCSIIO_CDB_ADDR_MASK                   (0x6000)
+#define MPI2_SCSIIO_CDB_ADDR_SYSTEM                 (0x0000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCDDR                 (0x2000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCPLB                 (0x4000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA              (0x6000)
+
+#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB               (0x1000)
+#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL           (0x0800)
+#define MPI2_SCSIIO_IOFLAGS_MULTICAST               (0x0400)
+#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
+#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK          (0x01FF)
+
+/*SCSI IO EEDPFlags bits */
+
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG        (0x8000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG        (0x4000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG        (0x2000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG        (0x1000)
+
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG          (0x0400)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG          (0x0200)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD           (0x0100)
+
+#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG       (0x0008)
+
+#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP               (0x0007)
+#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP               (0x0000)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP              (0x0001)
+#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP              (0x0002)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP       (0x0003)
+#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP             (0x0004)
+#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP            (0x0006)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP        (0x0007)
+
+/*SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
+
+/*SCSI IO Control bits */
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK      (0xFC000000)
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT     (26)
+
+#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK  (0x03000000)
+#define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24)
+#define MPI2_SCSIIO_CONTROL_NODATATRANSFER      (0x00000000)
+#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
+#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL       (0x03000000)
+
+#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK        (0x00007800)
+#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT       (11)
+/*alternate name for the previous field; called Command Priority in SAM-4 */
+#define MPI2_SCSIIO_CONTROL_CMDPRI_MASK         (0x00007800)
+#define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT        (11)
+
+#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK  (0x00000700)
+#define MPI2_SCSIIO_CONTROL_SIMPLEQ             (0x00000000)
+#define MPI2_SCSIIO_CONTROL_HEADOFQ             (0x00000100)
+#define MPI2_SCSIIO_CONTROL_ORDEREDQ            (0x00000200)
+#define MPI2_SCSIIO_CONTROL_ACAQ                (0x00000400)
+
+#define MPI2_SCSIIO_CONTROL_TLR_MASK            (0x000000C0)
+#define MPI2_SCSIIO_CONTROL_NO_TLR              (0x00000000)
+#define MPI2_SCSIIO_CONTROL_TLR_ON              (0x00000040)
+#define MPI2_SCSIIO_CONTROL_TLR_OFF             (0x00000080)
+
+/*MPI v2.5 CDB field */
+typedef union _MPI25_SCSI_IO_CDB_UNION {
+       U8 CDB32[32];
+       MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+       MPI2_IEEE_SGE_SIMPLE64 SGE;
+} MPI25_SCSI_IO_CDB_UNION, *PTR_MPI25_SCSI_IO_CDB_UNION,
+       Mpi25ScsiIoCdb_t, *pMpi25ScsiIoCdb_t;
+
+/*MPI v2.5 SCSI IO Request Message */
+typedef struct _MPI25_SCSI_IO_REQUEST {
+       U16 DevHandle;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved1;          /*0x04 */
+       U8 Reserved2;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U32 SenseBufferLowAddress;      /*0x0C */
+       U8 DMAFlags;            /*0x10 */
+       U8 Reserved5;           /*0x11 */
+       U8 SenseBufferLength;   /*0x12 */
+       U8 Reserved4;           /*0x13 */
+       U8 SGLOffset0;          /*0x14 */
+       U8 SGLOffset1;          /*0x15 */
+       U8 SGLOffset2;          /*0x16 */
+       U8 SGLOffset3;          /*0x17 */
+       U32 SkipCount;          /*0x18 */
+       U32 DataLength;         /*0x1C */
+       U32 BidirectionalDataLength;    /*0x20 */
+       U16 IoFlags;            /*0x24 */
+       U16 EEDPFlags;          /*0x26 */
+       U16 EEDPBlockSize;      /*0x28 */
+       U16 Reserved6;          /*0x2A */
+       U32 SecondaryReferenceTag;      /*0x2C */
+       U16 SecondaryApplicationTag;    /*0x30 */
+       U16 ApplicationTagTranslationMask;      /*0x32 */
+       U8 LUN[8];              /*0x34 */
+       U32 Control;            /*0x3C */
+       MPI25_SCSI_IO_CDB_UNION CDB;    /*0x40 */
+
+#ifdef MPI25_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */
+       MPI25_SCSI_IO_VENDOR_UNIQUE VendorRegion;
+#endif
+
+       MPI25_SGE_IO_UNION SGL; /*0x60 */
+
+} MPI25_SCSI_IO_REQUEST, *PTR_MPI25_SCSI_IO_REQUEST,
+       Mpi25SCSIIORequest_t, *pMpi25SCSIIORequest_t;
+
+/*use MPI2_SCSIIO_MSGFLAGS_ defines for the MsgFlags field */
+
+/*Defines for the DMAFlags field
+ * Each setting affects 4 SGLS, from SGL0 to SGL3.
+ *     D = Data
+ *     C = Cache DIF
+ *     I = Interleaved
+ *     H = Host DIF
+ */
+#define MPI25_SCSIIO_DMAFLAGS_OP_MASK               (0x0F)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_D            (0x00)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_C            (0x01)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_I            (0x02)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_C            (0x03)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_I            (0x04)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_I_I            (0x05)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_C            (0x06)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_I            (0x07)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_I_I            (0x08)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_I_I_I            (0x09)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_D            (0x0A)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_C            (0x0B)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_I            (0x0C)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_C            (0x0D)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_I            (0x0E)
+#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_I_I            (0x0F)
+
+/*number of SGLOffset fields */
+#define MPI25_SCSIIO_NUM_SGLOFFSETS                 (4)
+
+/*defines for the IoFlags field */
+#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK           (0xC000)
+#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH            (0x0000)
+#define MPI25_SCSIIO_IOFLAGS_FAST_PATH              (0x4000)
+
+#define MPI25_SCSIIO_IOFLAGS_LARGE_CDB                  (0x1000)
+#define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL              (0x0800)
+#define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK             (0x01FF)
+
+/*MPI v2.5 defines for the EEDPFlags bits */
+/*use MPI2_SCSIIO_EEDPFLAGS_ defines for the other EEDPFlags bits */
+#define MPI25_SCSIIO_EEDPFLAGS_ESCAPE_MODE_MASK             (0x00C0)
+#define MPI25_SCSIIO_EEDPFLAGS_COMPATIBLE_MODE              (0x0000)
+#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE          (0x0040)
+#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE          (0x0080)
+#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_REFTAG_DISABLE_MODE   (0x00C0)
+
+#define MPI25_SCSIIO_EEDPFLAGS_HOST_GUARD_METHOD_MASK       (0x0030)
+#define MPI25_SCSIIO_EEDPFLAGS_T10_CRC_HOST_GUARD           (0x0000)
+#define MPI25_SCSIIO_EEDPFLAGS_IP_CHKSUM_HOST_GUARD         (0x0010)
+
+/*use MPI2_LUN_ defines from mpi2.h for the LUN field */
+
+/*use MPI2_SCSIIO_CONTROL_ defines for the Control field */
+
+/*NOTE: The SCSI IO Reply is nearly the same for MPI 2.0 and MPI 2.5, so
+ *      MPI2_SCSI_IO_REPLY is used for both.
+ */
+
+/*SCSI IO Error Reply Message */
+typedef struct _MPI2_SCSI_IO_REPLY {
+       U16 DevHandle;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved1;          /*0x04 */
+       U8 Reserved2;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U8 SCSIStatus;          /*0x0C */
+       U8 SCSIState;           /*0x0D */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 TransferCount;      /*0x14 */
+       U32 SenseCount;         /*0x18 */
+       U32 ResponseInfo;       /*0x1C */
+       U16 TaskTag;            /*0x20 */
+       U16 Reserved4;          /*0x22 */
+       U32 BidirectionalTransferCount; /*0x24 */
+       U32 EEDPErrorOffset;    /*0x28 *//*MPI 2.5 only; Reserved in MPI 2.0*/
+       U32 Reserved6;          /*0x2C */
+} MPI2_SCSI_IO_REPLY, *PTR_MPI2_SCSI_IO_REPLY,
+       Mpi2SCSIIOReply_t, *pMpi2SCSIIOReply_t;
+
+/*SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
+
+#define MPI2_SCSI_STATUS_GOOD                   (0x00)
+#define MPI2_SCSI_STATUS_CHECK_CONDITION        (0x02)
+#define MPI2_SCSI_STATUS_CONDITION_MET          (0x04)
+#define MPI2_SCSI_STATUS_BUSY                   (0x08)
+#define MPI2_SCSI_STATUS_INTERMEDIATE           (0x10)
+#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET   (0x14)
+#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT   (0x18)
+#define MPI2_SCSI_STATUS_COMMAND_TERMINATED     (0x22) /*obsolete */
+#define MPI2_SCSI_STATUS_TASK_SET_FULL          (0x28)
+#define MPI2_SCSI_STATUS_ACA_ACTIVE             (0x30)
+#define MPI2_SCSI_STATUS_TASK_ABORTED           (0x40)
+
+/*SCSI IO Reply SCSIState flags */
+
+#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID     (0x10)
+#define MPI2_SCSI_STATE_TERMINATED              (0x08)
+#define MPI2_SCSI_STATE_NO_SCSI_STATUS          (0x04)
+#define MPI2_SCSI_STATE_AUTOSENSE_FAILED        (0x02)
+#define MPI2_SCSI_STATE_AUTOSENSE_VALID         (0x01)
+
+/*masks and shifts for the ResponseInfo field */
+
+#define MPI2_SCSI_RI_MASK_REASONCODE            (0x000000FF)
+#define MPI2_SCSI_RI_SHIFT_REASONCODE           (0)
+
+#define MPI2_SCSI_TASKTAG_UNKNOWN               (0xFFFF)
+
+/****************************************************************************
+* SCSI Task Management messages
+****************************************************************************/
+
+/*SCSI Task Management Request Message */
+typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST {
+       U16 DevHandle;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U8 Reserved1;           /*0x04 */
+       U8 TaskType;            /*0x05 */
+       U8 Reserved2;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U8 LUN[8];              /*0x0C */
+       U32 Reserved4[7];       /*0x14 */
+       U16 TaskMID;            /*0x30 */
+       U16 Reserved5;          /*0x32 */
+} MPI2_SCSI_TASK_MANAGE_REQUEST,
+       *PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
+       Mpi2SCSITaskManagementRequest_t,
+       *pMpi2SCSITaskManagementRequest_t;
+
+/*TaskType values */
+
+#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK           (0x01)
+#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET        (0x02)
+#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET         (0x03)
+#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET   (0x05)
+#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET       (0x06)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK           (0x07)
+#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA              (0x08)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET         (0x09)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT      (0x0A)
+
+/*obsolete TaskType name */
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \
+               (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
+
+/*MsgFlags bits */
+
+#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET    (0x18)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET           (0x00)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST     (0x08)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET  (0x10)
+
+#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU  (0x01)
+
+/*SCSI Task Management Reply Message */
+typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY {
+       U16 DevHandle;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U8 ResponseCode;        /*0x04 */
+       U8 TaskType;            /*0x05 */
+       U8 Reserved1;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U16 Reserved3;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 TerminationCount;   /*0x14 */
+       U32 ResponseInfo;       /*0x18 */
+} MPI2_SCSI_TASK_MANAGE_REPLY,
+       *PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
+       Mpi2SCSITaskManagementReply_t, *pMpi2SCSIManagementReply_t;
+
+/*ResponseCode values */
+
+#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE               (0x00)
+#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME             (0x02)
+#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED          (0x04)
+#define MPI2_SCSITASKMGMT_RSP_TM_FAILED                 (0x05)
+#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED              (0x08)
+#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN            (0x09)
+#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG         (0x0A)
+#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC          (0x80)
+
+/*masks and shifts for the ResponseInfo field */
+
+#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE            (0x000000FF)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE           (0)
+#define MPI2_SCSITASKMGMT_RI_MASK_ARI2                  (0x0000FF00)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2                 (8)
+#define MPI2_SCSITASKMGMT_RI_MASK_ARI1                  (0x00FF0000)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1                 (16)
+#define MPI2_SCSITASKMGMT_RI_MASK_ARI0                  (0xFF000000)
+#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0                 (24)
+
+/****************************************************************************
+* SCSI Enclosure Processor messages
+****************************************************************************/
+
+/*SCSI Enclosure Processor Request Message */
+typedef struct _MPI2_SEP_REQUEST {
+       U16 DevHandle;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U8 Action;              /*0x04 */
+       U8 Flags;               /*0x05 */
+       U8 Reserved1;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U32 SlotStatus;         /*0x0C */
+       U32 Reserved3;          /*0x10 */
+       U32 Reserved4;          /*0x14 */
+       U32 Reserved5;          /*0x18 */
+       U16 Slot;               /*0x1C */
+       U16 EnclosureHandle;    /*0x1E */
+} MPI2_SEP_REQUEST, *PTR_MPI2_SEP_REQUEST,
+       Mpi2SepRequest_t, *pMpi2SepRequest_t;
+
+/*Action defines */
+#define MPI2_SEP_REQ_ACTION_WRITE_STATUS                (0x00)
+#define MPI2_SEP_REQ_ACTION_READ_STATUS                 (0x01)
+
+/*Flags defines */
+#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS            (0x00)
+#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS       (0x01)
+
+/*SlotStatus defines */
+#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE          (0x00040000)
+#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST        (0x00020000)
+#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED         (0x00000200)
+#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE               (0x00000100)
+#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED            (0x00000080)
+#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT         (0x00000040)
+#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY       (0x00000010)
+#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY         (0x00000008)
+#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING          (0x00000004)
+#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY              (0x00000002)
+#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR                (0x00000001)
+
+/*SCSI Enclosure Processor Reply Message */
+typedef struct _MPI2_SEP_REPLY {
+       U16 DevHandle;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U8 Action;              /*0x04 */
+       U8 Flags;               /*0x05 */
+       U8 Reserved1;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U16 Reserved3;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 SlotStatus;         /*0x14 */
+       U32 Reserved4;          /*0x18 */
+       U16 Slot;               /*0x1C */
+       U16 EnclosureHandle;    /*0x1E */
+} MPI2_SEP_REPLY, *PTR_MPI2_SEP_REPLY,
+       Mpi2SepReply_t, *pMpi2SepReply_t;
+
+/*SlotStatus defines */
+#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY          (0x00040000)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST      (0x00020000)
+#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED       (0x00000200)
+#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE             (0x00000100)
+#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED          (0x00000080)
+#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT       (0x00000040)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY     (0x00000010)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY       (0x00000008)
+#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING        (0x00000004)
+#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY            (0x00000002)
+#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR              (0x00000001)
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
new file mode 100644 (file)
index 0000000..0de425d
--- /dev/null
@@ -0,0 +1,1665 @@
+/*
+ * Copyright (c) 2000-2012 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2_ioc.h
+ *         Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
+ * Creation Date:  October 11, 2006
+ *
+ * mpi2_ioc.h Version:  02.00.21
+ *
+ * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
+ *       prefix are for use only on MPI v2.5 products, and must not be used
+ *       with MPI v2.0 products. Unless otherwise noted, names beginning with
+ *       MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-04-07  02.00.01  In IOCFacts Reply structure, renamed MaxDevices to
+ *                     MaxTargets.
+ *                     Added TotalImageSize field to FWDownload Request.
+ *                     Added reserved words to FWUpload Request.
+ * 06-26-07  02.00.02  Added IR Configuration Change List Event.
+ * 08-31-07  02.00.03  Removed SystemReplyQueueDepth field from the IOCInit
+ *                     request and replaced it with
+ *                     ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
+ *                     Replaced the MinReplyQueueDepth field of the IOCFacts
+ *                     reply with MaxReplyDescriptorPostQueueDepth.
+ *                     Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
+ *                     depth for the Reply Descriptor Post Queue.
+ *                     Added SASAddress field to Initiator Device Table
+ *                     Overflow Event data.
+ * 10-31-07  02.00.04  Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
+ *                     for SAS Initiator Device Status Change Event data.
+ *                     Modified Reason Code defines for SAS Topology Change
+ *                     List Event data, including adding a bit for PHY Vacant
+ *                     status, and adding a mask for the Reason Code.
+ *                     Added define for
+ *                     MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
+ *                     Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
+ * 12-18-07  02.00.05  Added Boot Status defines for the IOCExceptions field of
+ *                     the IOCFacts Reply.
+ *                     Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                     Moved MPI2_VERSION_UNION to mpi2.h.
+ *                     Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
+ *                     instead of enables, and added SASBroadcastPrimitiveMasks
+ *                     field.
+ *                     Added Log Entry Added Event and related structure.
+ * 02-29-08  02.00.06  Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
+ *                     Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
+ *                     Added MaxVolumes and MaxPersistentEntries fields to
+ *                     IOCFacts reply.
+ *                     Added ProtocalFlags and IOCCapabilities fields to
+ *                     MPI2_FW_IMAGE_HEADER.
+ *                     Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
+ * 03-03-08  02.00.07  Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
+ *                     a U16 (from a U32).
+ *                     Removed extra 's' from EventMasks name.
+ * 06-27-08  02.00.08  Fixed an offset in a comment.
+ * 10-02-08  02.00.09  Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
+ *                     Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
+ *                     renamed MinReplyFrameSize to ReplyFrameSize.
+ *                     Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
+ *                     Added two new RAIDOperation values for Integrated RAID
+ *                     Operations Status Event data.
+ *                     Added four new IR Configuration Change List Event data
+ *                     ReasonCode values.
+ *                     Added two new ReasonCode defines for SAS Device Status
+ *                     Change Event data.
+ *                     Added three new DiscoveryStatus bits for the SAS
+ *                     Discovery event data.
+ *                     Added Multiplexing Status Change bit to the PhyStatus
+ *                     field of the SAS Topology Change List event data.
+ *                     Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
+ *                     BootFlags are now product-specific.
+ *                     Added defines for the indivdual signature bytes
+ *                     for MPI2_INIT_IMAGE_FOOTER.
+ * 01-19-09  02.00.10  Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
+ *                     Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
+ *                     define.
+ *                     Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
+ *                     define.
+ *                     Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
+ * 05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
+ *                     Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
+ *                     Added two new reason codes for SAS Device Status Change
+ *                     Event.
+ *                     Added new event: SAS PHY Counter.
+ * 07-30-09  02.00.12  Added GPIO Interrupt event define and structure.
+ *                     Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                     Added new product id family for 2208.
+ * 10-28-09  02.00.13  Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
+ *                     Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
+ *                     Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
+ *                     Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
+ *                     Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
+ *                     Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
+ *                     Added Host Based Discovery Phy Event data.
+ *                     Added defines for ProductID Product field
+ *                     (MPI2_FW_HEADER_PID_).
+ *                     Modified values for SAS ProductID Family
+ *                     (MPI2_FW_HEADER_PID_FAMILY_).
+ * 02-10-10  02.00.14  Added SAS Quiesce Event structure and defines.
+ *                     Added PowerManagementControl Request structures and
+ *                     defines.
+ * 05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
+ *                     Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ * 11-10-10  02.00.16  Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
+ * 02-23-11  02.00.17  Added SAS NOTIFY Primitive event, and added
+ *                     SASNotifyPrimitiveMasks field to
+ *                     MPI2_EVENT_NOTIFICATION_REQUEST.
+ *                     Added Temperature Threshold Event.
+ *                     Added Host Message Event.
+ *                     Added Send Host Message request and reply.
+ * 05-25-11  02.00.18  For Extended Image Header, added
+ *                     MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and
+ *                     MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines.
+ *                     Deprecated MPI2_EXT_IMAGE_TYPE_MAX define.
+ * 08-24-11  02.00.19  Added PhysicalPort field to
+ *                     MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure.
+ *                     Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete.
+ * 11-18-11  02.00.20  Incorporating additions for MPI v2.5.
+ * 03-29-12  02.00.21  Added a product specific range to event values.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_IOC_H
+#define MPI2_IOC_H
+
+/*****************************************************************************
+*
+*              IOC Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* IOCInit message
+****************************************************************************/
+
+/*IOCInit Request message */
+typedef struct _MPI2_IOC_INIT_REQUEST {
+       U8 WhoInit;             /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 MsgVersion;         /*0x0C */
+       U16 HeaderVersion;      /*0x0E */
+       U32 Reserved5;          /*0x10 */
+       U16 Reserved6;          /*0x14 */
+       U8 Reserved7;           /*0x16 */
+       U8 HostMSIxVectors;     /*0x17 */
+       U16 Reserved8;          /*0x18 */
+       U16 SystemRequestFrameSize;     /*0x1A */
+       U16 ReplyDescriptorPostQueueDepth;      /*0x1C */
+       U16 ReplyFreeQueueDepth;        /*0x1E */
+       U32 SenseBufferAddressHigh;     /*0x20 */
+       U32 SystemReplyAddressHigh;     /*0x24 */
+       U64 SystemRequestFrameBaseAddress;      /*0x28 */
+       U64 ReplyDescriptorPostQueueAddress;    /*0x30 */
+       U64 ReplyFreeQueueAddress;      /*0x38 */
+       U64 TimeStamp;          /*0x40 */
+} MPI2_IOC_INIT_REQUEST, *PTR_MPI2_IOC_INIT_REQUEST,
+       Mpi2IOCInitRequest_t, *pMpi2IOCInitRequest_t;
+
+/*WhoInit values */
+#define MPI2_WHOINIT_NOT_INITIALIZED            (0x00)
+#define MPI2_WHOINIT_SYSTEM_BIOS                (0x01)
+#define MPI2_WHOINIT_ROM_BIOS                   (0x02)
+#define MPI2_WHOINIT_PCI_PEER                   (0x03)
+#define MPI2_WHOINIT_HOST_DRIVER                (0x04)
+#define MPI2_WHOINIT_MANUFACTURER               (0x05)
+
+/*MsgVersion */
+#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK      (0xFF00)
+#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT     (8)
+#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK      (0x00FF)
+#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT     (0)
+
+/*HeaderVersion */
+#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK       (0xFF00)
+#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT      (8)
+#define MPI2_IOCINIT_HDRVERSION_DEV_MASK        (0x00FF)
+#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT       (0)
+
+/*minimum depth for the Reply Descriptor Post Queue */
+#define MPI2_RDPQ_DEPTH_MIN                     (16)
+
+/*IOCInit Reply message */
+typedef struct _MPI2_IOC_INIT_REPLY {
+       U8 WhoInit;             /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_IOC_INIT_REPLY, *PTR_MPI2_IOC_INIT_REPLY,
+       Mpi2IOCInitReply_t, *pMpi2IOCInitReply_t;
+
+/****************************************************************************
+* IOCFacts message
+****************************************************************************/
+
+/*IOCFacts Request message */
+typedef struct _MPI2_IOC_FACTS_REQUEST {
+       U16 Reserved1;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+} MPI2_IOC_FACTS_REQUEST, *PTR_MPI2_IOC_FACTS_REQUEST,
+       Mpi2IOCFactsRequest_t, *pMpi2IOCFactsRequest_t;
+
+/*IOCFacts Reply message */
+typedef struct _MPI2_IOC_FACTS_REPLY {
+       U16 MsgVersion;         /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 HeaderVersion;      /*0x04 */
+       U8 IOCNumber;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+       U16 IOCExceptions;      /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U8 MaxChainDepth;       /*0x14 */
+       U8 WhoInit;             /*0x15 */
+       U8 NumberOfPorts;       /*0x16 */
+       U8 MaxMSIxVectors;      /*0x17 */
+       U16 RequestCredit;      /*0x18 */
+       U16 ProductID;          /*0x1A */
+       U32 IOCCapabilities;    /*0x1C */
+       MPI2_VERSION_UNION FWVersion;   /*0x20 */
+       U16 IOCRequestFrameSize;        /*0x24 */
+       U16 IOCMaxChainSegmentSize;     /*0x26 */
+       U16 MaxInitiators;      /*0x28 */
+       U16 MaxTargets;         /*0x2A */
+       U16 MaxSasExpanders;    /*0x2C */
+       U16 MaxEnclosures;      /*0x2E */
+       U16 ProtocolFlags;      /*0x30 */
+       U16 HighPriorityCredit; /*0x32 */
+       U16 MaxReplyDescriptorPostQueueDepth;   /*0x34 */
+       U8 ReplyFrameSize;      /*0x36 */
+       U8 MaxVolumes;          /*0x37 */
+       U16 MaxDevHandle;       /*0x38 */
+       U16 MaxPersistentEntries;       /*0x3A */
+       U16 MinDevHandle;       /*0x3C */
+       U16 Reserved4;          /*0x3E */
+} MPI2_IOC_FACTS_REPLY, *PTR_MPI2_IOC_FACTS_REPLY,
+       Mpi2IOCFactsReply_t, *pMpi2IOCFactsReply_t;
+
+/*MsgVersion */
+#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT            (8)
+#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK             (0x00FF)
+#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT            (0)
+
+/*HeaderVersion */
+#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK              (0xFF00)
+#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT             (8)
+#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK               (0x00FF)
+#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT              (0)
+
+/*IOCExceptions */
+#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX      (0x0100)
+
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK              (0x00E0)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD              (0x0000)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP            (0x0020)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED          (0x0040)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP    (0x0060)
+
+#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED       (0x0010)
+#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL     (0x0008)
+#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL           (0x0004)
+#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID        (0x0002)
+#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL       (0x0001)
+
+/*defines for WhoInit field are after the IOCInit Request */
+
+/*ProductID field uses MPI2_FW_HEADER_PID_ */
+
+/*IOCCapabilities */
+#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE     (0x00020000)
+#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY   (0x00010000)
+#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX            (0x00008000)
+#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR       (0x00004000)
+#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY           (0x00002000)
+#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID        (0x00001000)
+#define MPI2_IOCFACTS_CAPABILITY_TLR                    (0x00000800)
+#define MPI2_IOCFACTS_CAPABILITY_MULTICAST              (0x00000100)
+#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET   (0x00000080)
+#define MPI2_IOCFACTS_CAPABILITY_EEDP                   (0x00000040)
+#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER        (0x00000020)
+#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER        (0x00000010)
+#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER      (0x00000008)
+#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
+
+/*ProtocolFlags */
+#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET              (0x0001)
+#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR           (0x0002)
+
+/****************************************************************************
+* PortFacts message
+****************************************************************************/
+
+/*PortFacts Request message */
+typedef struct _MPI2_PORT_FACTS_REQUEST {
+       U16 Reserved1;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 PortNumber;          /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+} MPI2_PORT_FACTS_REQUEST, *PTR_MPI2_PORT_FACTS_REQUEST,
+       Mpi2PortFactsRequest_t, *pMpi2PortFactsRequest_t;
+
+/*PortFacts Reply message */
+typedef struct _MPI2_PORT_FACTS_REPLY {
+       U16 Reserved1;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 PortNumber;          /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U16 Reserved4;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U8 Reserved5;           /*0x14 */
+       U8 PortType;            /*0x15 */
+       U16 Reserved6;          /*0x16 */
+       U16 MaxPostedCmdBuffers;        /*0x18 */
+       U16 Reserved7;          /*0x1A */
+} MPI2_PORT_FACTS_REPLY, *PTR_MPI2_PORT_FACTS_REPLY,
+       Mpi2PortFactsReply_t, *pMpi2PortFactsReply_t;
+
+/*PortType values */
+#define MPI2_PORTFACTS_PORTTYPE_INACTIVE            (0x00)
+#define MPI2_PORTFACTS_PORTTYPE_FC                  (0x10)
+#define MPI2_PORTFACTS_PORTTYPE_ISCSI               (0x20)
+#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL        (0x30)
+#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL         (0x31)
+
+/****************************************************************************
+* PortEnable message
+****************************************************************************/
+
+/*PortEnable Request message */
+typedef struct _MPI2_PORT_ENABLE_REQUEST {
+       U16 Reserved1;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U8 Reserved2;           /*0x04 */
+       U8 PortFlags;           /*0x05 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+} MPI2_PORT_ENABLE_REQUEST, *PTR_MPI2_PORT_ENABLE_REQUEST,
+       Mpi2PortEnableRequest_t, *pMpi2PortEnableRequest_t;
+
+/*PortEnable Reply message */
+typedef struct _MPI2_PORT_ENABLE_REPLY {
+       U16 Reserved1;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U8 Reserved2;           /*0x04 */
+       U8 PortFlags;           /*0x05 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_PORT_ENABLE_REPLY, *PTR_MPI2_PORT_ENABLE_REPLY,
+       Mpi2PortEnableReply_t, *pMpi2PortEnableReply_t;
+
+/****************************************************************************
+* EventNotification message
+****************************************************************************/
+
+/*EventNotification Request message */
+#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS           (4)
+
+typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST {
+       U16 Reserved1;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 Reserved5;          /*0x0C */
+       U32 Reserved6;          /*0x10 */
+       U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];      /*0x14 */
+       U16 SASBroadcastPrimitiveMasks; /*0x24 */
+       U16 SASNotifyPrimitiveMasks;    /*0x26 */
+       U32 Reserved8;          /*0x28 */
+} MPI2_EVENT_NOTIFICATION_REQUEST,
+       *PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
+       Mpi2EventNotificationRequest_t,
+       *pMpi2EventNotificationRequest_t;
+
+/*EventNotification Reply message */
+typedef struct _MPI2_EVENT_NOTIFICATION_REPLY {
+       U16 EventDataLength;    /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved1;          /*0x04 */
+       U8 AckRequired;         /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U16 Reserved3;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U16 Event;              /*0x14 */
+       U16 Reserved4;          /*0x16 */
+       U32 EventContext;       /*0x18 */
+       U32 EventData[1];       /*0x1C */
+} MPI2_EVENT_NOTIFICATION_REPLY, *PTR_MPI2_EVENT_NOTIFICATION_REPLY,
+       Mpi2EventNotificationReply_t,
+       *pMpi2EventNotificationReply_t;
+
+/*AckRequired */
+#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED    (0x00)
+#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED        (0x01)
+
+/*Event */
+#define MPI2_EVENT_LOG_DATA                         (0x0001)
+#define MPI2_EVENT_STATE_CHANGE                     (0x0002)
+#define MPI2_EVENT_HARD_RESET_RECEIVED              (0x0005)
+#define MPI2_EVENT_EVENT_CHANGE                     (0x000A)
+#define MPI2_EVENT_TASK_SET_FULL                    (0x000E)   /*obsolete */
+#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE         (0x000F)
+#define MPI2_EVENT_IR_OPERATION_STATUS              (0x0014)
+#define MPI2_EVENT_SAS_DISCOVERY                    (0x0016)
+#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE          (0x0017)
+#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE    (0x0018)
+#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW          (0x0019)
+#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST         (0x001C)
+#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE    (0x001D)
+#define MPI2_EVENT_IR_VOLUME                        (0x001E)
+#define MPI2_EVENT_IR_PHYSICAL_DISK                 (0x001F)
+#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST     (0x0020)
+#define MPI2_EVENT_LOG_ENTRY_ADDED                  (0x0021)
+#define MPI2_EVENT_SAS_PHY_COUNTER                  (0x0022)
+#define MPI2_EVENT_GPIO_INTERRUPT                   (0x0023)
+#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY         (0x0024)
+#define MPI2_EVENT_SAS_QUIESCE                      (0x0025)
+#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE             (0x0026)
+#define MPI2_EVENT_TEMP_THRESHOLD                   (0x0027)
+#define MPI2_EVENT_HOST_MESSAGE                     (0x0028)
+#define MPI2_EVENT_POWER_PERFORMANCE_CHANGE         (0x0029)
+#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC             (0x006E)
+#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC             (0x007F)
+
+/*Log Entry Added Event data */
+
+/*the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
+#define MPI2_EVENT_DATA_LOG_DATA_LENGTH             (0x1C)
+
+typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED {
+       U64 TimeStamp;          /*0x00 */
+       U32 Reserved1;          /*0x08 */
+       U16 LogSequence;        /*0x0C */
+       U16 LogEntryQualifier;  /*0x0E */
+       U8 VP_ID;               /*0x10 */
+       U8 VF_ID;               /*0x11 */
+       U16 Reserved2;          /*0x12 */
+       U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];    /*0x14 */
+} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
+       *PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
+       Mpi2EventDataLogEntryAdded_t,
+       *pMpi2EventDataLogEntryAdded_t;
+
+/*GPIO Interrupt Event data */
+
+typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT {
+       U8 GPIONum;             /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+} MPI2_EVENT_DATA_GPIO_INTERRUPT,
+       *PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
+       Mpi2EventDataGpioInterrupt_t,
+       *pMpi2EventDataGpioInterrupt_t;
+
+/*Temperature Threshold Event data */
+
+typedef struct _MPI2_EVENT_DATA_TEMPERATURE {
+       U16 Status;             /*0x00 */
+       U8 SensorNum;           /*0x02 */
+       U8 Reserved1;           /*0x03 */
+       U16 CurrentTemperature; /*0x04 */
+       U16 Reserved2;          /*0x06 */
+       U32 Reserved3;          /*0x08 */
+       U32 Reserved4;          /*0x0C */
+} MPI2_EVENT_DATA_TEMPERATURE,
+       *PTR_MPI2_EVENT_DATA_TEMPERATURE,
+       Mpi2EventDataTemperature_t, *pMpi2EventDataTemperature_t;
+
+/*Temperature Threshold Event data Status bits */
+#define MPI2_EVENT_TEMPERATURE3_EXCEEDED            (0x0008)
+#define MPI2_EVENT_TEMPERATURE2_EXCEEDED            (0x0004)
+#define MPI2_EVENT_TEMPERATURE1_EXCEEDED            (0x0002)
+#define MPI2_EVENT_TEMPERATURE0_EXCEEDED            (0x0001)
+
+/*Host Message Event data */
+
+typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE {
+       U8 SourceVF_ID;         /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+       U32 Reserved3;          /*0x04 */
+       U32 HostData[1];        /*0x08 */
+} MPI2_EVENT_DATA_HOST_MESSAGE, *PTR_MPI2_EVENT_DATA_HOST_MESSAGE,
+       Mpi2EventDataHostMessage_t, *pMpi2EventDataHostMessage_t;
+
+/*Power Performance Change Event */
+
+typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE {
+       U8 CurrentPowerMode;    /*0x00 */
+       U8 PreviousPowerMode;   /*0x01 */
+       U16 Reserved1;          /*0x02 */
+} MPI2_EVENT_DATA_POWER_PERF_CHANGE,
+       *PTR_MPI2_EVENT_DATA_POWER_PERF_CHANGE,
+       Mpi2EventDataPowerPerfChange_t,
+       *pMpi2EventDataPowerPerfChange_t;
+
+/*defines for CurrentPowerMode and PreviousPowerMode fields */
+#define MPI2_EVENT_PM_INIT_MASK              (0xC0)
+#define MPI2_EVENT_PM_INIT_UNAVAILABLE       (0x00)
+#define MPI2_EVENT_PM_INIT_HOST              (0x40)
+#define MPI2_EVENT_PM_INIT_IO_UNIT           (0x80)
+#define MPI2_EVENT_PM_INIT_PCIE_DPA          (0xC0)
+
+#define MPI2_EVENT_PM_MODE_MASK              (0x07)
+#define MPI2_EVENT_PM_MODE_UNAVAILABLE       (0x00)
+#define MPI2_EVENT_PM_MODE_UNKNOWN           (0x01)
+#define MPI2_EVENT_PM_MODE_FULL_POWER        (0x04)
+#define MPI2_EVENT_PM_MODE_REDUCED_POWER     (0x05)
+#define MPI2_EVENT_PM_MODE_STANDBY           (0x06)
+
+/*Hard Reset Received Event data */
+
+typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED {
+       U8 Reserved1;           /*0x00 */
+       U8 Port;                /*0x01 */
+       U16 Reserved2;          /*0x02 */
+} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
+       *PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
+       Mpi2EventDataHardResetReceived_t,
+       *pMpi2EventDataHardResetReceived_t;
+
+/*Task Set Full Event data */
+/*  this event is obsolete */
+
+typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL {
+       U16 DevHandle;          /*0x00 */
+       U16 CurrentDepth;       /*0x02 */
+} MPI2_EVENT_DATA_TASK_SET_FULL, *PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
+       Mpi2EventDataTaskSetFull_t, *pMpi2EventDataTaskSetFull_t;
+
+/*SAS Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE {
+       U16 TaskTag;            /*0x00 */
+       U8 ReasonCode;          /*0x02 */
+       U8 PhysicalPort;        /*0x03 */
+       U8 ASC;                 /*0x04 */
+       U8 ASCQ;                /*0x05 */
+       U16 DevHandle;          /*0x06 */
+       U32 Reserved2;          /*0x08 */
+       U64 SASAddress;         /*0x0C */
+       U8 LUN[8];              /*0x14 */
+} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+       *PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+       Mpi2EventDataSasDeviceStatusChange_t,
+       *pMpi2EventDataSasDeviceStatusChange_t;
+
+/*SAS Device Status Change Event data ReasonCode values */
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA                           (0x05)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED                          (0x07)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET                (0x08)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL                  (0x09)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL              (0x0A)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL              (0x0B)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL                  (0x0C)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION                   (0x0D)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET               (0x0E)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL              (0x0F)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE                    (0x10)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY       (0x11)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY   (0x12)
+
+/*Integrated RAID Operation Status Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS {
+       U16 VolDevHandle;       /*0x00 */
+       U16 Reserved1;          /*0x02 */
+       U8 RAIDOperation;       /*0x04 */
+       U8 PercentComplete;     /*0x05 */
+       U16 Reserved2;          /*0x06 */
+       U32 Resereved3;         /*0x08 */
+} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
+       *PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
+       Mpi2EventDataIrOperationStatus_t,
+       *pMpi2EventDataIrOperationStatus_t;
+
+/*Integrated RAID Operation Status Event data RAIDOperation values */
+#define MPI2_EVENT_IR_RAIDOP_RESYNC                     (0x00)
+#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION       (0x01)
+#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK          (0x02)
+#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT            (0x03)
+#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT       (0x04)
+
+/*Integrated RAID Volume Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_VOLUME {
+       U16 VolDevHandle;       /*0x00 */
+       U8 ReasonCode;          /*0x02 */
+       U8 Reserved1;           /*0x03 */
+       U32 NewValue;           /*0x04 */
+       U32 PreviousValue;      /*0x08 */
+} MPI2_EVENT_DATA_IR_VOLUME, *PTR_MPI2_EVENT_DATA_IR_VOLUME,
+       Mpi2EventDataIrVolume_t, *pMpi2EventDataIrVolume_t;
+
+/*Integrated RAID Volume Event data ReasonCode values */
+#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED        (0x01)
+#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED    (0x02)
+#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED           (0x03)
+
+/*Integrated RAID Physical Disk Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK {
+       U16 Reserved1;          /*0x00 */
+       U8 ReasonCode;          /*0x02 */
+       U8 PhysDiskNum;         /*0x03 */
+       U16 PhysDiskDevHandle;  /*0x04 */
+       U16 Reserved2;          /*0x06 */
+       U16 Slot;               /*0x08 */
+       U16 EnclosureHandle;    /*0x0A */
+       U32 NewValue;           /*0x0C */
+       U32 PreviousValue;      /*0x10 */
+} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
+       *PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
+       Mpi2EventDataIrPhysicalDisk_t,
+       *pMpi2EventDataIrPhysicalDisk_t;
+
+/*Integrated RAID Physical Disk Event data ReasonCode values */
+#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED      (0x01)
+#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED  (0x02)
+#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED         (0x03)
+
+/*Integrated RAID Configuration Change List Event data */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check NumElements at runtime.
+ */
+#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
+#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT          (1)
+#endif
+
+typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT {
+       U16 ElementFlags;       /*0x00 */
+       U16 VolDevHandle;       /*0x02 */
+       U8 ReasonCode;          /*0x04 */
+       U8 PhysDiskNum;         /*0x05 */
+       U16 PhysDiskDevHandle;  /*0x06 */
+} MPI2_EVENT_IR_CONFIG_ELEMENT, *PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
+       Mpi2EventIrConfigElement_t, *pMpi2EventIrConfigElement_t;
+
+/*IR Configuration Change List Event data ElementFlags values */
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK   (0x000F)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT      (0x0000)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT    (0x0002)
+
+/*IR Configuration Change List Event data ReasonCode values */
+#define MPI2_EVENT_IR_CHANGE_RC_ADDED                   (0x01)
+#define MPI2_EVENT_IR_CHANGE_RC_REMOVED                 (0x02)
+#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE               (0x03)
+#define MPI2_EVENT_IR_CHANGE_RC_HIDE                    (0x04)
+#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE                  (0x05)
+#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED          (0x06)
+#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED          (0x07)
+#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED              (0x08)
+#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED              (0x09)
+
+typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST {
+       U8 NumElements;         /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 Reserved2;           /*0x02 */
+       U8 ConfigNum;           /*0x03 */
+       U32 Flags;              /*0x04 */
+       MPI2_EVENT_IR_CONFIG_ELEMENT
+               ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];/*0x08 */
+} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
+       *PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
+       Mpi2EventDataIrConfigChangeList_t,
+       *pMpi2EventDataIrConfigChangeList_t;
+
+/*IR Configuration Change List Event data Flags values */
+#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG   (0x00000001)
+
+/*SAS Discovery Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY {
+       U8 Flags;               /*0x00 */
+       U8 ReasonCode;          /*0x01 */
+       U8 PhysicalPort;        /*0x02 */
+       U8 Reserved1;           /*0x03 */
+       U32 DiscoveryStatus;    /*0x04 */
+} MPI2_EVENT_DATA_SAS_DISCOVERY,
+       *PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
+       Mpi2EventDataSasDiscovery_t, *pMpi2EventDataSasDiscovery_t;
+
+/*SAS Discovery Event data Flags values */
+#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE                   (0x02)
+#define MPI2_EVENT_SAS_DISC_IN_PROGRESS                     (0x01)
+
+/*SAS Discovery Event data ReasonCode values */
+#define MPI2_EVENT_SAS_DISC_RC_STARTED                      (0x01)
+#define MPI2_EVENT_SAS_DISC_RC_COMPLETED                    (0x02)
+
+/*SAS Discovery Event data DiscoveryStatus values */
+#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED            (0x80000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED             (0x40000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED               (0x20000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED             (0x10000000)
+#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR             (0x08000000)
+#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE    (0x00008000)
+#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE            (0x00004000)
+#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN                (0x00002000)
+#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK        (0x00001000)
+#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE               (0x00000800)
+#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK                       (0x00000400)
+#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK                 (0x00000200)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR                    (0x00000100)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED              (0x00000080)
+#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST                  (0x00000040)
+#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES                (0x00000020)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT                      (0x00000010)
+#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS                   (0x00000004)
+#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE             (0x00000002)
+#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED                    (0x00000001)
+
+/*SAS Broadcast Primitive Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE {
+       U8 PhyNum;              /*0x00 */
+       U8 Port;                /*0x01 */
+       U8 PortWidth;           /*0x02 */
+       U8 Primitive;           /*0x03 */
+} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+       *PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+       Mpi2EventDataSasBroadcastPrimitive_t,
+       *pMpi2EventDataSasBroadcastPrimitive_t;
+
+/*defines for the Primitive field */
+#define MPI2_EVENT_PRIMITIVE_CHANGE                         (0x01)
+#define MPI2_EVENT_PRIMITIVE_SES                            (0x02)
+#define MPI2_EVENT_PRIMITIVE_EXPANDER                       (0x03)
+#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT             (0x04)
+#define MPI2_EVENT_PRIMITIVE_RESERVED3                      (0x05)
+#define MPI2_EVENT_PRIMITIVE_RESERVED4                      (0x06)
+#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED               (0x07)
+#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED               (0x08)
+
+/*SAS Notify Primitive Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE {
+       U8 PhyNum;              /*0x00 */
+       U8 Port;                /*0x01 */
+       U8 Reserved1;           /*0x02 */
+       U8 Primitive;           /*0x03 */
+} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
+       *PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
+       Mpi2EventDataSasNotifyPrimitive_t,
+       *pMpi2EventDataSasNotifyPrimitive_t;
+
+/*defines for the Primitive field */
+#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP                     (0x01)
+#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED               (0x02)
+#define MPI2_EVENT_NOTIFY_RESERVED1                         (0x03)
+#define MPI2_EVENT_NOTIFY_RESERVED2                         (0x04)
+
+/*SAS Initiator Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE {
+       U8 ReasonCode;          /*0x00 */
+       U8 PhysicalPort;        /*0x01 */
+       U16 DevHandle;          /*0x02 */
+       U64 SASAddress;         /*0x04 */
+} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+       *PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+       Mpi2EventDataSasInitDevStatusChange_t,
+       *pMpi2EventDataSasInitDevStatusChange_t;
+
+/*SAS Initiator Device Status Change event ReasonCode values */
+#define MPI2_EVENT_SAS_INIT_RC_ADDED                (0x01)
+#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING       (0x02)
+
+/*SAS Initiator Device Table Overflow Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW {
+       U16 MaxInit;            /*0x00 */
+       U16 CurrentInit;        /*0x02 */
+       U64 SASAddress;         /*0x04 */
+} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+       *PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+       Mpi2EventDataSasInitTableOverflow_t,
+       *pMpi2EventDataSasInitTableOverflow_t;
+
+/*SAS Topology Change List Event data */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check NumEntries at runtime.
+ */
+#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
+#define MPI2_EVENT_SAS_TOPO_PHY_COUNT           (1)
+#endif
+
+typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY {
+       U16 AttachedDevHandle;  /*0x00 */
+       U8 LinkRate;            /*0x02 */
+       U8 PhyStatus;           /*0x03 */
+} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, *PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
+       Mpi2EventSasTopoPhyEntry_t, *pMpi2EventSasTopoPhyEntry_t;
+
+typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST {
+       U16 EnclosureHandle;    /*0x00 */
+       U16 ExpanderDevHandle;  /*0x02 */
+       U8 NumPhys;             /*0x04 */
+       U8 Reserved1;           /*0x05 */
+       U16 Reserved2;          /*0x06 */
+       U8 NumEntries;          /*0x08 */
+       U8 StartPhyNum;         /*0x09 */
+       U8 ExpStatus;           /*0x0A */
+       U8 PhysicalPort;        /*0x0B */
+       MPI2_EVENT_SAS_TOPO_PHY_ENTRY
+       PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT];     /*0x0C */
+} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
+       *PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
+       Mpi2EventDataSasTopologyChangeList_t,
+       *pMpi2EventDataSasTopologyChangeList_t;
+
+/*values for the ExpStatus field */
+#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER                  (0x00)
+#define MPI2_EVENT_SAS_TOPO_ES_ADDED                        (0x01)
+#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING               (0x02)
+#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING                   (0x03)
+#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING         (0x04)
+
+/*defines for the LinkRate field */
+#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK                 (0xF0)
+#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT                (4)
+#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK                    (0x0F)
+#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT                   (0)
+
+#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE            (0x00)
+#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED                 (0x01)
+#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED           (0x02)
+#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE            (0x03)
+#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR                (0x04)
+#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS        (0x05)
+#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY              (0x06)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5                     (0x08)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0                     (0x09)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0                     (0x0A)
+#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0                   (0x0B)
+
+/*values for the PhyStatus field */
+#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT                (0x80)
+#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE             (0x10)
+/*values for the PhyStatus ReasonCode sub-field */
+#define MPI2_EVENT_SAS_TOPO_RC_MASK                         (0x0F)
+#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED                   (0x01)
+#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING          (0x02)
+#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED                  (0x03)
+#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE                    (0x04)
+#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING         (0x05)
+
+/*SAS Enclosure Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE {
+       U16 EnclosureHandle;    /*0x00 */
+       U8 ReasonCode;          /*0x02 */
+       U8 PhysicalPort;        /*0x03 */
+       U64 EnclosureLogicalID; /*0x04 */
+       U16 NumSlots;           /*0x0C */
+       U16 StartSlot;          /*0x0E */
+       U32 PhyBits;            /*0x10 */
+} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
+       *PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
+       Mpi2EventDataSasEnclDevStatusChange_t,
+       *pMpi2EventDataSasEnclDevStatusChange_t;
+
+/*SAS Enclosure Device Status Change event ReasonCode values */
+#define MPI2_EVENT_SAS_ENCL_RC_ADDED                (0x01)
+#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING       (0x02)
+
+/*SAS PHY Counter Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER {
+       U64 TimeStamp;          /*0x00 */
+       U32 Reserved1;          /*0x08 */
+       U8 PhyEventCode;        /*0x0C */
+       U8 PhyNum;              /*0x0D */
+       U16 Reserved2;          /*0x0E */
+       U32 PhyEventInfo;       /*0x10 */
+       U8 CounterType;         /*0x14 */
+       U8 ThresholdWindow;     /*0x15 */
+       U8 TimeUnits;           /*0x16 */
+       U8 Reserved3;           /*0x17 */
+       U32 EventThreshold;     /*0x18 */
+       U16 ThresholdFlags;     /*0x1C */
+       U16 Reserved4;          /*0x1E */
+} MPI2_EVENT_DATA_SAS_PHY_COUNTER,
+       *PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER,
+       Mpi2EventDataSasPhyCounter_t,
+       *pMpi2EventDataSasPhyCounter_t;
+
+/*use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h
+ *for the PhyEventCode field */
+
+/*use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h
+ *for the CounterType field */
+
+/*use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h
+ *for the TimeUnits field */
+
+/*use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h
+ *for the ThresholdFlags field */
+
+/*SAS Quiesce Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE {
+       U8 ReasonCode;          /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+       U32 Reserved3;          /*0x04 */
+} MPI2_EVENT_DATA_SAS_QUIESCE,
+       *PTR_MPI2_EVENT_DATA_SAS_QUIESCE,
+       Mpi2EventDataSasQuiesce_t, *pMpi2EventDataSasQuiesce_t;
+
+/*SAS Quiesce Event data ReasonCode values */
+#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED                   (0x01)
+#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED                 (0x02)
+
+/*Host Based Discovery Phy Event data */
+
+typedef struct _MPI2_EVENT_HBD_PHY_SAS {
+       U8 Flags;               /*0x00 */
+       U8 NegotiatedLinkRate;  /*0x01 */
+       U8 PhyNum;              /*0x02 */
+       U8 PhysicalPort;        /*0x03 */
+       U32 Reserved1;          /*0x04 */
+       U8 InitialFrame[28];    /*0x08 */
+} MPI2_EVENT_HBD_PHY_SAS, *PTR_MPI2_EVENT_HBD_PHY_SAS,
+       Mpi2EventHbdPhySas_t, *pMpi2EventHbdPhySas_t;
+
+/*values for the Flags field */
+#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID        (0x02)
+#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME         (0x01)
+
+/*use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h
+ *for the NegotiatedLinkRate field */
+
+typedef union _MPI2_EVENT_HBD_DESCRIPTOR {
+       MPI2_EVENT_HBD_PHY_SAS Sas;
+} MPI2_EVENT_HBD_DESCRIPTOR, *PTR_MPI2_EVENT_HBD_DESCRIPTOR,
+       Mpi2EventHbdDescriptor_t, *pMpi2EventHbdDescriptor_t;
+
+typedef struct _MPI2_EVENT_DATA_HBD_PHY {
+       U8 DescriptorType;      /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+       U32 Reserved3;          /*0x04 */
+       MPI2_EVENT_HBD_DESCRIPTOR Descriptor;   /*0x08 */
+} MPI2_EVENT_DATA_HBD_PHY, *PTR_MPI2_EVENT_DATA_HBD_PHY,
+       Mpi2EventDataHbdPhy_t,
+       *pMpi2EventDataMpi2EventDataHbdPhy_t;
+
+/*values for the DescriptorType field */
+#define MPI2_EVENT_HBD_DT_SAS               (0x01)
+
+/****************************************************************************
+* EventAck message
+****************************************************************************/
+
+/*EventAck Request message */
+typedef struct _MPI2_EVENT_ACK_REQUEST {
+       U16 Reserved1;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Event;              /*0x0C */
+       U16 Reserved5;          /*0x0E */
+       U32 EventContext;       /*0x10 */
+} MPI2_EVENT_ACK_REQUEST, *PTR_MPI2_EVENT_ACK_REQUEST,
+       Mpi2EventAckRequest_t, *pMpi2EventAckRequest_t;
+
+/*EventAck Reply message */
+typedef struct _MPI2_EVENT_ACK_REPLY {
+       U16 Reserved1;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_EVENT_ACK_REPLY, *PTR_MPI2_EVENT_ACK_REPLY,
+       Mpi2EventAckReply_t, *pMpi2EventAckReply_t;
+
+/****************************************************************************
+* SendHostMessage message
+****************************************************************************/
+
+/*SendHostMessage Request message */
+typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST {
+       U16 HostDataLength;     /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved1;          /*0x04 */
+       U8 Reserved2;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U8 Reserved4;           /*0x0C */
+       U8 DestVF_ID;           /*0x0D */
+       U16 Reserved5;          /*0x0E */
+       U32 Reserved6;          /*0x10 */
+       U32 Reserved7;          /*0x14 */
+       U32 Reserved8;          /*0x18 */
+       U32 Reserved9;          /*0x1C */
+       U32 Reserved10;         /*0x20 */
+       U32 HostData[1];        /*0x24 */
+} MPI2_SEND_HOST_MESSAGE_REQUEST,
+       *PTR_MPI2_SEND_HOST_MESSAGE_REQUEST,
+       Mpi2SendHostMessageRequest_t,
+       *pMpi2SendHostMessageRequest_t;
+
+/*SendHostMessage Reply message */
+typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY {
+       U16 HostDataLength;     /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved1;          /*0x04 */
+       U8 Reserved2;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U16 Reserved4;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_SEND_HOST_MESSAGE_REPLY, *PTR_MPI2_SEND_HOST_MESSAGE_REPLY,
+       Mpi2SendHostMessageReply_t, *pMpi2SendHostMessageReply_t;
+
+/****************************************************************************
+* FWDownload message
+****************************************************************************/
+
+/*MPI v2.0 FWDownload Request message */
+typedef struct _MPI2_FW_DOWNLOAD_REQUEST {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 TotalImageSize;     /*0x0C */
+       U32 Reserved5;          /*0x10 */
+       MPI2_MPI_SGE_UNION SGL; /*0x14 */
+} MPI2_FW_DOWNLOAD_REQUEST, *PTR_MPI2_FW_DOWNLOAD_REQUEST,
+       Mpi2FWDownloadRequest, *pMpi2FWDownloadRequest;
+
+#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT   (0x01)
+
+#define MPI2_FW_DOWNLOAD_ITYPE_FW                   (0x01)
+#define MPI2_FW_DOWNLOAD_ITYPE_BIOS                 (0x02)
+#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING        (0x06)
+#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1             (0x07)
+#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2             (0x08)
+#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID             (0x09)
+#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE             (0x0A)
+#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK    (0x0B)
+#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
+
+/*MPI v2.0 FWDownload TransactionContext Element */
+typedef struct _MPI2_FW_DOWNLOAD_TCSGE {
+       U8 Reserved1;           /*0x00 */
+       U8 ContextSize;         /*0x01 */
+       U8 DetailsLength;       /*0x02 */
+       U8 Flags;               /*0x03 */
+       U32 Reserved2;          /*0x04 */
+       U32 ImageOffset;        /*0x08 */
+       U32 ImageSize;          /*0x0C */
+} MPI2_FW_DOWNLOAD_TCSGE, *PTR_MPI2_FW_DOWNLOAD_TCSGE,
+       Mpi2FWDownloadTCSGE_t, *pMpi2FWDownloadTCSGE_t;
+
+/*MPI v2.5 FWDownload Request message */
+typedef struct _MPI25_FW_DOWNLOAD_REQUEST {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 TotalImageSize;     /*0x0C */
+       U32 Reserved5;          /*0x10 */
+       U32 Reserved6;          /*0x14 */
+       U32 ImageOffset;        /*0x18 */
+       U32 ImageSize;          /*0x1C */
+       MPI25_SGE_IO_UNION SGL; /*0x20 */
+} MPI25_FW_DOWNLOAD_REQUEST, *PTR_MPI25_FW_DOWNLOAD_REQUEST,
+       Mpi25FWDownloadRequest, *pMpi25FWDownloadRequest;
+
+/*FWDownload Reply message */
+typedef struct _MPI2_FW_DOWNLOAD_REPLY {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_FW_DOWNLOAD_REPLY, *PTR_MPI2_FW_DOWNLOAD_REPLY,
+       Mpi2FWDownloadReply_t, *pMpi2FWDownloadReply_t;
+
+/****************************************************************************
+* FWUpload message
+****************************************************************************/
+
+/*MPI v2.0 FWUpload Request message */
+typedef struct _MPI2_FW_UPLOAD_REQUEST {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 Reserved5;          /*0x0C */
+       U32 Reserved6;          /*0x10 */
+       MPI2_MPI_SGE_UNION SGL; /*0x14 */
+} MPI2_FW_UPLOAD_REQUEST, *PTR_MPI2_FW_UPLOAD_REQUEST,
+       Mpi2FWUploadRequest_t, *pMpi2FWUploadRequest_t;
+
+#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT         (0x00)
+#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH           (0x01)
+#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH         (0x02)
+#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP          (0x05)
+#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING      (0x06)
+#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1           (0x07)
+#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2           (0x08)
+#define MPI2_FW_UPLOAD_ITYPE_MEGARAID           (0x09)
+#define MPI2_FW_UPLOAD_ITYPE_COMPLETE           (0x0A)
+#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK  (0x0B)
+
+/*MPI v2.0 FWUpload TransactionContext Element */
+typedef struct _MPI2_FW_UPLOAD_TCSGE {
+       U8 Reserved1;           /*0x00 */
+       U8 ContextSize;         /*0x01 */
+       U8 DetailsLength;       /*0x02 */
+       U8 Flags;               /*0x03 */
+       U32 Reserved2;          /*0x04 */
+       U32 ImageOffset;        /*0x08 */
+       U32 ImageSize;          /*0x0C */
+} MPI2_FW_UPLOAD_TCSGE, *PTR_MPI2_FW_UPLOAD_TCSGE,
+       Mpi2FWUploadTCSGE_t, *pMpi2FWUploadTCSGE_t;
+
+/*MPI v2.5 FWUpload Request message */
+typedef struct _MPI25_FW_UPLOAD_REQUEST {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 Reserved5;          /*0x0C */
+       U32 Reserved6;          /*0x10 */
+       U32 Reserved7;          /*0x14 */
+       U32 ImageOffset;        /*0x18 */
+       U32 ImageSize;          /*0x1C */
+       MPI25_SGE_IO_UNION SGL; /*0x20 */
+} MPI25_FW_UPLOAD_REQUEST, *PTR_MPI25_FW_UPLOAD_REQUEST,
+       Mpi25FWUploadRequest_t, *pMpi25FWUploadRequest_t;
+
+/*FWUpload Reply message */
+typedef struct _MPI2_FW_UPLOAD_REPLY {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 ActualImageSize;    /*0x14 */
+} MPI2_FW_UPLOAD_REPLY, *PTR_MPI2_FW_UPLOAD_REPLY,
+       Mpi2FWUploadReply_t, *pMPi2FWUploadReply_t;
+
+/*FW Image Header */
+typedef struct _MPI2_FW_IMAGE_HEADER {
+       U32 Signature;          /*0x00 */
+       U32 Signature0;         /*0x04 */
+       U32 Signature1;         /*0x08 */
+       U32 Signature2;         /*0x0C */
+       MPI2_VERSION_UNION MPIVersion;  /*0x10 */
+       MPI2_VERSION_UNION FWVersion;   /*0x14 */
+       MPI2_VERSION_UNION NVDATAVersion;       /*0x18 */
+       MPI2_VERSION_UNION PackageVersion;      /*0x1C */
+       U16 VendorID;           /*0x20 */
+       U16 ProductID;          /*0x22 */
+       U16 ProtocolFlags;      /*0x24 */
+       U16 Reserved26;         /*0x26 */
+       U32 IOCCapabilities;    /*0x28 */
+       U32 ImageSize;          /*0x2C */
+       U32 NextImageHeaderOffset;      /*0x30 */
+       U32 Checksum;           /*0x34 */
+       U32 Reserved38;         /*0x38 */
+       U32 Reserved3C;         /*0x3C */
+       U32 Reserved40;         /*0x40 */
+       U32 Reserved44;         /*0x44 */
+       U32 Reserved48;         /*0x48 */
+       U32 Reserved4C;         /*0x4C */
+       U32 Reserved50;         /*0x50 */
+       U32 Reserved54;         /*0x54 */
+       U32 Reserved58;         /*0x58 */
+       U32 Reserved5C;         /*0x5C */
+       U32 Reserved60;         /*0x60 */
+       U32 FirmwareVersionNameWhat;    /*0x64 */
+       U8 FirmwareVersionName[32];     /*0x68 */
+       U32 VendorNameWhat;     /*0x88 */
+       U8 VendorName[32];      /*0x8C */
+       U32 PackageNameWhat;    /*0x88 */
+       U8 PackageName[32];     /*0x8C */
+       U32 ReservedD0;         /*0xD0 */
+       U32 ReservedD4;         /*0xD4 */
+       U32 ReservedD8;         /*0xD8 */
+       U32 ReservedDC;         /*0xDC */
+       U32 ReservedE0;         /*0xE0 */
+       U32 ReservedE4;         /*0xE4 */
+       U32 ReservedE8;         /*0xE8 */
+       U32 ReservedEC;         /*0xEC */
+       U32 ReservedF0;         /*0xF0 */
+       U32 ReservedF4;         /*0xF4 */
+       U32 ReservedF8;         /*0xF8 */
+       U32 ReservedFC;         /*0xFC */
+} MPI2_FW_IMAGE_HEADER, *PTR_MPI2_FW_IMAGE_HEADER,
+       Mpi2FWImageHeader_t, *pMpi2FWImageHeader_t;
+
+/*Signature field */
+#define MPI2_FW_HEADER_SIGNATURE_OFFSET         (0x00)
+#define MPI2_FW_HEADER_SIGNATURE_MASK           (0xFF000000)
+#define MPI2_FW_HEADER_SIGNATURE                (0xEA000000)
+
+/*Signature0 field */
+#define MPI2_FW_HEADER_SIGNATURE0_OFFSET        (0x04)
+#define MPI2_FW_HEADER_SIGNATURE0               (0x5AFAA55A)
+
+/*Signature1 field */
+#define MPI2_FW_HEADER_SIGNATURE1_OFFSET        (0x08)
+#define MPI2_FW_HEADER_SIGNATURE1               (0xA55AFAA5)
+
+/*Signature2 field */
+#define MPI2_FW_HEADER_SIGNATURE2_OFFSET        (0x0C)
+#define MPI2_FW_HEADER_SIGNATURE2               (0x5AA55AFA)
+
+/*defines for using the ProductID field */
+#define MPI2_FW_HEADER_PID_TYPE_MASK            (0xF000)
+#define MPI2_FW_HEADER_PID_TYPE_SAS             (0x2000)
+
+#define MPI2_FW_HEADER_PID_PROD_MASK                    (0x0F00)
+#define MPI2_FW_HEADER_PID_PROD_A                       (0x0000)
+#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI   (0x0200)
+#define MPI2_FW_HEADER_PID_PROD_IR_SCSI                 (0x0700)
+
+#define MPI2_FW_HEADER_PID_FAMILY_MASK          (0x00FF)
+/*SAS ProductID Family bits */
+#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS      (0x0013)
+#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS      (0x0014)
+#define MPI25_FW_HEADER_PID_FAMILY_3108_SAS     (0x0021)
+
+/*use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
+
+/*use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
+
+#define MPI2_FW_HEADER_IMAGESIZE_OFFSET         (0x2C)
+#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET         (0x30)
+#define MPI2_FW_HEADER_VERNMHWAT_OFFSET         (0x64)
+
+#define MPI2_FW_HEADER_WHAT_SIGNATURE           (0x29232840)
+
+#define MPI2_FW_HEADER_SIZE                     (0x100)
+
+/*Extended Image Header */
+typedef struct _MPI2_EXT_IMAGE_HEADER {
+       U8 ImageType;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+       U32 Checksum;           /*0x04 */
+       U32 ImageSize;          /*0x08 */
+       U32 NextImageHeaderOffset;      /*0x0C */
+       U32 PackageVersion;     /*0x10 */
+       U32 Reserved3;          /*0x14 */
+       U32 Reserved4;          /*0x18 */
+       U32 Reserved5;          /*0x1C */
+       U8 IdentifyString[32];  /*0x20 */
+} MPI2_EXT_IMAGE_HEADER, *PTR_MPI2_EXT_IMAGE_HEADER,
+       Mpi2ExtImageHeader_t, *pMpi2ExtImageHeader_t;
+
+/*useful offsets */
+#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET         (0x00)
+#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET         (0x08)
+#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET         (0x0C)
+
+#define MPI2_EXT_IMAGE_HEADER_SIZE              (0x40)
+
+/*defines for the ImageType field */
+#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED             (0x00)
+#define MPI2_EXT_IMAGE_TYPE_FW                      (0x01)
+#define MPI2_EXT_IMAGE_TYPE_NVDATA                  (0x03)
+#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER              (0x04)
+#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION          (0x05)
+#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT            (0x06)
+#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES       (0x07)
+#define MPI2_EXT_IMAGE_TYPE_MEGARAID                (0x08)
+#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC    (0x80)
+#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC    (0xFF)
+
+#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC)
+
+/*FLASH Layout Extended Image Data */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check RegionsPerLayout at runtime.
+ */
+#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
+#define MPI2_FLASH_NUMBER_OF_REGIONS        (1)
+#endif
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check NumberOfLayouts at runtime.
+ */
+#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
+#define MPI2_FLASH_NUMBER_OF_LAYOUTS        (1)
+#endif
+
+typedef struct _MPI2_FLASH_REGION {
+       U8 RegionType;          /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+       U32 RegionOffset;       /*0x04 */
+       U32 RegionSize;         /*0x08 */
+       U32 Reserved3;          /*0x0C */
+} MPI2_FLASH_REGION, *PTR_MPI2_FLASH_REGION,
+       Mpi2FlashRegion_t, *pMpi2FlashRegion_t;
+
+typedef struct _MPI2_FLASH_LAYOUT {
+       U32 FlashSize;          /*0x00 */
+       U32 Reserved1;          /*0x04 */
+       U32 Reserved2;          /*0x08 */
+       U32 Reserved3;          /*0x0C */
+       MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS]; /*0x10 */
+} MPI2_FLASH_LAYOUT, *PTR_MPI2_FLASH_LAYOUT,
+       Mpi2FlashLayout_t, *pMpi2FlashLayout_t;
+
+typedef struct _MPI2_FLASH_LAYOUT_DATA {
+       U8 ImageRevision;       /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 SizeOfRegion;        /*0x02 */
+       U8 Reserved2;           /*0x03 */
+       U16 NumberOfLayouts;    /*0x04 */
+       U16 RegionsPerLayout;   /*0x06 */
+       U16 MinimumSectorAlignment;     /*0x08 */
+       U16 Reserved3;          /*0x0A */
+       U32 Reserved4;          /*0x0C */
+       MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS]; /*0x10 */
+} MPI2_FLASH_LAYOUT_DATA, *PTR_MPI2_FLASH_LAYOUT_DATA,
+       Mpi2FlashLayoutData_t, *pMpi2FlashLayoutData_t;
+
+/*defines for the RegionType field */
+#define MPI2_FLASH_REGION_UNUSED                (0x00)
+#define MPI2_FLASH_REGION_FIRMWARE              (0x01)
+#define MPI2_FLASH_REGION_BIOS                  (0x02)
+#define MPI2_FLASH_REGION_NVDATA                (0x03)
+#define MPI2_FLASH_REGION_FIRMWARE_BACKUP       (0x05)
+#define MPI2_FLASH_REGION_MFG_INFORMATION       (0x06)
+#define MPI2_FLASH_REGION_CONFIG_1              (0x07)
+#define MPI2_FLASH_REGION_CONFIG_2              (0x08)
+#define MPI2_FLASH_REGION_MEGARAID              (0x09)
+#define MPI2_FLASH_REGION_INIT                  (0x0A)
+
+/*ImageRevision */
+#define MPI2_FLASH_LAYOUT_IMAGE_REVISION        (0x00)
+
+/*Supported Devices Extended Image Data */
+
+/*
+ *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ *one and check NumberOfDevices at runtime.
+ */
+#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
+#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES    (1)
+#endif
+
+typedef struct _MPI2_SUPPORTED_DEVICE {
+       U16 DeviceID;           /*0x00 */
+       U16 VendorID;           /*0x02 */
+       U16 DeviceIDMask;       /*0x04 */
+       U16 Reserved1;          /*0x06 */
+       U8 LowPCIRev;           /*0x08 */
+       U8 HighPCIRev;          /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U32 Reserved3;          /*0x0C */
+} MPI2_SUPPORTED_DEVICE, *PTR_MPI2_SUPPORTED_DEVICE,
+       Mpi2SupportedDevice_t, *pMpi2SupportedDevice_t;
+
+typedef struct _MPI2_SUPPORTED_DEVICES_DATA {
+       U8 ImageRevision;       /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 NumberOfDevices;     /*0x02 */
+       U8 Reserved2;           /*0x03 */
+       U32 Reserved3;          /*0x04 */
+       MPI2_SUPPORTED_DEVICE
+       SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES];/*0x08 */
+} MPI2_SUPPORTED_DEVICES_DATA, *PTR_MPI2_SUPPORTED_DEVICES_DATA,
+       Mpi2SupportedDevicesData_t, *pMpi2SupportedDevicesData_t;
+
+/*ImageRevision */
+#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION   (0x00)
+
+/*Init Extended Image Data */
+
+typedef struct _MPI2_INIT_IMAGE_FOOTER {
+       U32 BootFlags;          /*0x00 */
+       U32 ImageSize;          /*0x04 */
+       U32 Signature0;         /*0x08 */
+       U32 Signature1;         /*0x0C */
+       U32 Signature2;         /*0x10 */
+       U32 ResetVector;        /*0x14 */
+} MPI2_INIT_IMAGE_FOOTER, *PTR_MPI2_INIT_IMAGE_FOOTER,
+       Mpi2InitImageFooter_t, *pMpi2InitImageFooter_t;
+
+/*defines for the BootFlags field */
+#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET        (0x00)
+
+/*defines for the ImageSize field */
+#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET        (0x04)
+
+/*defines for the Signature0 field */
+#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET       (0x08)
+#define MPI2_INIT_IMAGE_SIGNATURE0              (0x5AA55AEA)
+
+/*defines for the Signature1 field */
+#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET       (0x0C)
+#define MPI2_INIT_IMAGE_SIGNATURE1              (0xA55AEAA5)
+
+/*defines for the Signature2 field */
+#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET       (0x10)
+#define MPI2_INIT_IMAGE_SIGNATURE2              (0x5AEAA55A)
+
+/*Signature fields as individual bytes */
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0        (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1        (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2        (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3        (0x5A)
+
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4        (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5        (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6        (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7        (0xA5)
+
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8        (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9        (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A        (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B        (0x5A)
+
+/*defines for the ResetVector field */
+#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET      (0x14)
+
+/****************************************************************************
+* PowerManagementControl message
+****************************************************************************/
+
+/*PowerManagementControl Request message */
+typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST {
+       U8 Feature;             /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U8 Parameter1;          /*0x0C */
+       U8 Parameter2;          /*0x0D */
+       U8 Parameter3;          /*0x0E */
+       U8 Parameter4;          /*0x0F */
+       U32 Reserved5;          /*0x10 */
+       U32 Reserved6;          /*0x14 */
+} MPI2_PWR_MGMT_CONTROL_REQUEST, *PTR_MPI2_PWR_MGMT_CONTROL_REQUEST,
+       Mpi2PwrMgmtControlRequest_t, *pMpi2PwrMgmtControlRequest_t;
+
+/*defines for the Feature field */
+#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND       (0x01)
+#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION   (0x02)
+#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK               (0x03) /*obsolete */
+#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED               (0x04)
+#define MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE    (0x05)
+#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC    (0x80)
+#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC    (0xFF)
+
+/*parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */
+/*Parameter1 contains a PHY number */
+/*Parameter2 indicates power condition action using these defines */
+#define MPI2_PM_CONTROL_PARAM2_PARTIAL                  (0x01)
+#define MPI2_PM_CONTROL_PARAM2_SLUMBER                  (0x02)
+#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT            (0x03)
+/*Parameter3 and Parameter4 are reserved */
+
+/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION
+ * Feature */
+/*Parameter1 contains SAS port width modulation group number */
+/*Parameter2 indicates IOC action using these defines */
+#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP        (0x01)
+#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION        (0x02)
+#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP     (0x03)
+/*Parameter3 indicates desired modulation level using these defines */
+#define MPI2_PM_CONTROL_PARAM3_25_PERCENT               (0x00)
+#define MPI2_PM_CONTROL_PARAM3_50_PERCENT               (0x01)
+#define MPI2_PM_CONTROL_PARAM3_75_PERCENT               (0x02)
+#define MPI2_PM_CONTROL_PARAM3_100_PERCENT              (0x03)
+/*Parameter4 is reserved */
+
+/*this next set (_PCIE_LINK) is obsolete */
+/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */
+/*Parameter1 indicates desired PCIe link speed using these defines */
+#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS            (0x00) /*obsolete */
+#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS            (0x01) /*obsolete */
+#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS            (0x02) /*obsolete */
+/*Parameter2 indicates desired PCIe link width using these defines */
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1                 (0x01) /*obsolete */
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2                 (0x02) /*obsolete */
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4                 (0x04) /*obsolete */
+#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8                 (0x08) /*obsolete */
+/*Parameter3 and Parameter4 are reserved */
+
+/*parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */
+/*Parameter1 indicates desired IOC hardware clock speed using these defines */
+#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED           (0x01)
+#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED           (0x02)
+#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED        (0x04)
+#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED         (0x08)
+/*Parameter2, Parameter3, and Parameter4 are reserved */
+
+/*parameter usage for the MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE Feature*/
+/*Parameter1 indicates host action regarding global power management mode */
+#define MPI2_PM_CONTROL_PARAM1_TAKE_CONTROL             (0x01)
+#define MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE       (0x02)
+#define MPI2_PM_CONTROL_PARAM1_RELEASE_CONTROL          (0x03)
+/*Parameter2 indicates the requested global power management mode */
+#define MPI2_PM_CONTROL_PARAM2_FULL_PWR_PERF            (0x01)
+#define MPI2_PM_CONTROL_PARAM2_REDUCED_PWR_PERF         (0x08)
+#define MPI2_PM_CONTROL_PARAM2_STANDBY                  (0x40)
+/*Parameter3 and Parameter4 are reserved */
+
+/*PowerManagementControl Reply message */
+typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY {
+       U8 Feature;             /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_PWR_MGMT_CONTROL_REPLY, *PTR_MPI2_PWR_MGMT_CONTROL_REPLY,
+       Mpi2PwrMgmtControlReply_t, *pMpi2PwrMgmtControlReply_t;
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_raid.h b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h
new file mode 100644 (file)
index 0000000..d1d9866
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2000-2012 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2_raid.h
+ *         Title:  MPI Integrated RAID messages and structures
+ * Creation Date:  April 26, 2007
+ *
+ *   mpi2_raid.h Version:  02.00.08
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 08-31-07  02.00.01  Modifications to RAID Action request and reply,
+ *                     including the Actions and ActionData.
+ * 02-29-08  02.00.02  Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
+ * 05-21-08  02.00.03  Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
+ *                     the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
+ *                     can be sized by the build environment.
+ * 07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
+ *                     VolumeCreationFlags and marked the old one as obsolete.
+ * 05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
+ * 08-24-10  02.00.06  Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with
+ *                     related structures and defines.
+ *                     Added product-specific range to RAID Action values.
+ * 11-18-11  02.00.07  Incorporating additions for MPI v2.5.
+ * 02-06-12  02.00.08  Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_RAID_H
+#define MPI2_RAID_H
+
+/*****************************************************************************
+*
+*              Integrated RAID Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* RAID Action messages
+****************************************************************************/
+
+/*ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
+#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0            (0x00000000)
+#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0            (0x00000001)
+
+/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for
+ *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
+
+/*ActionDataWord defines for use with
+ *MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
+#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD  (0x00000001)
+
+/*ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
+typedef struct _MPI2_RAID_ACTION_RATE_DATA {
+       U8 RateToChange;        /*0x00 */
+       U8 RateOrMode;          /*0x01 */
+       U16 DataScrubDuration;  /*0x02 */
+} MPI2_RAID_ACTION_RATE_DATA, *PTR_MPI2_RAID_ACTION_RATE_DATA,
+       Mpi2RaidActionRateData_t, *pMpi2RaidActionRateData_t;
+
+#define MPI2_RAID_ACTION_SET_RATE_RESYNC            (0x00)
+#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB        (0x01)
+#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE    (0x02)
+
+/*ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
+typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION {
+       U8 RAIDFunction;        /*0x00 */
+       U8 Flags;               /*0x01 */
+       U16 Reserved1;          /*0x02 */
+} MPI2_RAID_ACTION_START_RAID_FUNCTION,
+       *PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
+       Mpi2RaidActionStartRaidFunction_t,
+       *pMpi2RaidActionStartRaidFunction_t;
+
+/*defines for the RAIDFunction field */
+#define MPI2_RAID_ACTION_START_BACKGROUND_INIT      (0x00)
+#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
+#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK    (0x02)
+
+/*defines for the Flags field */
+#define MPI2_RAID_ACTION_START_NEW                  (0x00)
+#define MPI2_RAID_ACTION_START_RESUME               (0x01)
+
+/*ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
+typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION {
+       U8 RAIDFunction;        /*0x00 */
+       U8 Flags;               /*0x01 */
+       U16 Reserved1;          /*0x02 */
+} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
+       *PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
+       Mpi2RaidActionStopRaidFunction_t,
+       *pMpi2RaidActionStopRaidFunction_t;
+
+/*defines for the RAIDFunction field */
+#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT       (0x00)
+#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION  (0x01)
+#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK     (0x02)
+
+/*defines for the Flags field */
+#define MPI2_RAID_ACTION_STOP_ABORT                 (0x00)
+#define MPI2_RAID_ACTION_STOP_PAUSE                 (0x01)
+
+/*ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
+typedef struct _MPI2_RAID_ACTION_HOT_SPARE {
+       U8 HotSparePool;        /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 DevHandle;          /*0x02 */
+} MPI2_RAID_ACTION_HOT_SPARE, *PTR_MPI2_RAID_ACTION_HOT_SPARE,
+       Mpi2RaidActionHotSpare_t, *pMpi2RaidActionHotSpare_t;
+
+/*ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
+typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE {
+       U8 Flags;               /*0x00 */
+       U8 DeviceFirmwareUpdateModeTimeout;     /*0x01 */
+       U16 Reserved1;          /*0x02 */
+} MPI2_RAID_ACTION_FW_UPDATE_MODE,
+       *PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
+       Mpi2RaidActionFwUpdateMode_t,
+       *pMpi2RaidActionFwUpdateMode_t;
+
+/*ActionDataWord defines for use with
+ *MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
+#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE        (0x00)
+#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE         (0x01)
+
+typedef union _MPI2_RAID_ACTION_DATA {
+       U32 Word;
+       MPI2_RAID_ACTION_RATE_DATA Rates;
+       MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
+       MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
+       MPI2_RAID_ACTION_HOT_SPARE HotSpare;
+       MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
+} MPI2_RAID_ACTION_DATA, *PTR_MPI2_RAID_ACTION_DATA,
+       Mpi2RaidActionData_t, *pMpi2RaidActionData_t;
+
+/*RAID Action Request Message */
+typedef struct _MPI2_RAID_ACTION_REQUEST {
+       U8 Action;              /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 VolDevHandle;       /*0x04 */
+       U8 PhysDiskNum;         /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U32 Reserved3;          /*0x0C */
+       MPI2_RAID_ACTION_DATA ActionDataWord;   /*0x10 */
+       MPI2_SGE_SIMPLE_UNION ActionDataSGE;    /*0x14 */
+} MPI2_RAID_ACTION_REQUEST, *PTR_MPI2_RAID_ACTION_REQUEST,
+       Mpi2RaidActionRequest_t, *pMpi2RaidActionRequest_t;
+
+/*RAID Action request Action values */
+
+#define MPI2_RAID_ACTION_INDICATOR_STRUCT           (0x01)
+#define MPI2_RAID_ACTION_CREATE_VOLUME              (0x02)
+#define MPI2_RAID_ACTION_DELETE_VOLUME              (0x03)
+#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES        (0x04)
+#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES         (0x05)
+#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE           (0x0A)
+#define MPI2_RAID_ACTION_PHYSDISK_ONLINE            (0x0B)
+#define MPI2_RAID_ACTION_FAIL_PHYSDISK              (0x0F)
+#define MPI2_RAID_ACTION_ACTIVATE_VOLUME            (0x11)
+#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE      (0x15)
+#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE     (0x17)
+#define MPI2_RAID_ACTION_SET_VOLUME_NAME            (0x18)
+#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE     (0x19)
+#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME       (0x1C)
+#define MPI2_RAID_ACTION_CREATE_HOT_SPARE           (0x1D)
+#define MPI2_RAID_ACTION_DELETE_HOT_SPARE           (0x1E)
+#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED  (0x20)
+#define MPI2_RAID_ACTION_START_RAID_FUNCTION        (0x21)
+#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION         (0x22)
+#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK        (0x23)
+#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN            (0x24)
+#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC       (0x80)
+#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC       (0xFF)
+
+/*RAID Volume Creation Structure */
+
+/*
+ *The following define can be customized for the targeted product.
+ */
+#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
+#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS        (1)
+#endif
+
+typedef struct _MPI2_RAID_VOLUME_PHYSDISK {
+       U8 RAIDSetNum;          /*0x00 */
+       U8 PhysDiskMap;         /*0x01 */
+       U16 PhysDiskDevHandle;  /*0x02 */
+} MPI2_RAID_VOLUME_PHYSDISK, *PTR_MPI2_RAID_VOLUME_PHYSDISK,
+       Mpi2RaidVolumePhysDisk_t, *pMpi2RaidVolumePhysDisk_t;
+
+/*defines for the PhysDiskMap field */
+#define MPI2_RAIDACTION_PHYSDISK_PRIMARY            (0x01)
+#define MPI2_RAIDACTION_PHYSDISK_SECONDARY          (0x02)
+
+typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT {
+       U8 NumPhysDisks;        /*0x00 */
+       U8 VolumeType;          /*0x01 */
+       U16 Reserved1;          /*0x02 */
+       U32 VolumeCreationFlags;        /*0x04 */
+       U32 VolumeSettings;     /*0x08 */
+       U8 Reserved2;           /*0x0C */
+       U8 ResyncRate;          /*0x0D */
+       U16 DataScrubDuration;  /*0x0E */
+       U64 VolumeMaxLBA;       /*0x10 */
+       U32 StripeSize;         /*0x18 */
+       U8 Name[16];            /*0x1C */
+       MPI2_RAID_VOLUME_PHYSDISK
+               PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS]; /*0x2C */
+} MPI2_RAID_VOLUME_CREATION_STRUCT,
+       *PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
+       Mpi2RaidVolumeCreationStruct_t,
+       *pMpi2RaidVolumeCreationStruct_t;
+
+/*use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
+
+/*defines for the VolumeCreationFlags field */
+#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS     (0x80000000)
+#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT      (0x00000004)
+#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT       (0x00000002)
+#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA         (0x00000001)
+/*The following is an obsolete define.
+ *It must be shifted left 24 bits in order to set the proper bit.
+ */
+#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
+
+/*RAID Online Capacity Expansion Structure */
+
+typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION {
+       U32 Flags;              /*0x00 */
+       U16 DevHandle0;         /*0x04 */
+       U16 Reserved1;          /*0x06 */
+       U16 DevHandle1;         /*0x08 */
+       U16 Reserved2;          /*0x0A */
+} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
+       *PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
+       Mpi2RaidOnlineCapacityExpansion_t,
+       *pMpi2RaidOnlineCapacityExpansion_t;
+
+/*RAID Compatibility Input Structure */
+
+typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT {
+       U16 SourceDevHandle;    /*0x00 */
+       U16 CandidateDevHandle; /*0x02 */
+       U32 Flags;              /*0x04 */
+       U32 Reserved1;          /*0x08 */
+       U32 Reserved2;          /*0x0C */
+} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
+       *PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
+       Mpi2RaidCompatibilityInputStruct_t,
+       *pMpi2RaidCompatibilityInputStruct_t;
+
+/*defines for RAID Compatibility Structure Flags field */
+#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG      (0x00000002)
+#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG    (0x00000001)
+
+/*RAID Volume Indicator Structure */
+
+typedef struct _MPI2_RAID_VOL_INDICATOR {
+       U64 TotalBlocks;        /*0x00 */
+       U64 BlocksRemaining;    /*0x08 */
+       U32 Flags;              /*0x10 */
+} MPI2_RAID_VOL_INDICATOR, *PTR_MPI2_RAID_VOL_INDICATOR,
+       Mpi2RaidVolIndicator_t, *pMpi2RaidVolIndicator_t;
+
+/*defines for RAID Volume Indicator Flags field */
+#define MPI2_RAID_VOL_FLAGS_OP_MASK                 (0x0000000F)
+#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT      (0x00000000)
+#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
+#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK    (0x00000002)
+#define MPI2_RAID_VOL_FLAGS_OP_RESYNC               (0x00000003)
+#define MPI2_RAID_VOL_FLAGS_OP_MDC                  (0x00000004)
+
+/*RAID Compatibility Result Structure */
+
+typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT {
+       U8 State;               /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U16 Reserved2;          /*0x02 */
+       U32 GenericAttributes;  /*0x04 */
+       U32 OEMSpecificAttributes;      /*0x08 */
+       U32 Reserved3;          /*0x0C */
+       U32 Reserved4;          /*0x10 */
+} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
+       *PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
+       Mpi2RaidCompatibilityResultStruct_t,
+       *pMpi2RaidCompatibilityResultStruct_t;
+
+/*defines for RAID Compatibility Result Structure State field */
+#define MPI2_RAID_COMPAT_STATE_COMPATIBLE           (0x00)
+#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE       (0x01)
+
+/*defines for RAID Compatibility Result Structure GenericAttributes field */
+#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR            (0x00000010)
+
+#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK           (0x0000000C)
+#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE    (0x00000008)
+#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE      (0x00000004)
+
+#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK        (0x00000003)
+#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL         (0x00000002)
+#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL        (0x00000001)
+
+/*RAID Action Reply ActionData union */
+typedef union _MPI2_RAID_ACTION_REPLY_DATA {
+       U32 Word[5];
+       MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
+       U16 VolDevHandle;
+       U8 VolumeState;
+       U8 PhysDiskNum;
+       MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult;
+} MPI2_RAID_ACTION_REPLY_DATA, *PTR_MPI2_RAID_ACTION_REPLY_DATA,
+       Mpi2RaidActionReplyData_t, *pMpi2RaidActionReplyData_t;
+
+/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for
+ *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
+
+/*RAID Action Reply Message */
+typedef struct _MPI2_RAID_ACTION_REPLY {
+       U8 Action;              /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 VolDevHandle;       /*0x04 */
+       U8 PhysDiskNum;         /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved2;          /*0x0A */
+       U16 Reserved3;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       MPI2_RAID_ACTION_REPLY_DATA ActionData; /*0x14 */
+} MPI2_RAID_ACTION_REPLY, *PTR_MPI2_RAID_ACTION_REPLY,
+       Mpi2RaidActionReply_t, *pMpi2RaidActionReply_t;
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_sas.h b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h
new file mode 100644 (file)
index 0000000..b4e7084
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2000-2012 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2_sas.h
+ *         Title:  MPI Serial Attached SCSI structures and definitions
+ * Creation Date:  February 9, 2007
+ *
+ * mpi2_sas.h Version:  02.00.07
+ *
+ * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
+ *       prefix are for use only on MPI v2.5 products, and must not be used
+ *       with MPI v2.0 products. Unless otherwise noted, names beginning with
+ *       MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-26-07  02.00.01  Added Clear All Persistent Operation to SAS IO Unit
+ *                     Control Request.
+ * 10-02-08  02.00.02  Added Set IOC Parameter Operation to SAS IO Unit Control
+ *                     Request.
+ * 10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
+ *                     to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ * 05-12-10  02.00.04  Modified some comments.
+ * 08-11-10  02.00.05  Added NCQ operations to SAS IO Unit Control.
+ * 11-18-11  02.00.06  Incorporating additions for MPI v2.5.
+ * 07-10-12  02.00.07  Added MPI2_SATA_PT_SGE_UNION for use in the SATA
+ *                     Passthrough Request message.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_SAS_H
+#define MPI2_SAS_H
+
+/*
+ *Values for SASStatus.
+ */
+#define MPI2_SASSTATUS_SUCCESS                          (0x00)
+#define MPI2_SASSTATUS_UNKNOWN_ERROR                    (0x01)
+#define MPI2_SASSTATUS_INVALID_FRAME                    (0x02)
+#define MPI2_SASSTATUS_UTC_BAD_DEST                     (0x03)
+#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED               (0x04)
+#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED   (0x05)
+#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST           (0x06)
+#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED       (0x07)
+#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY           (0x08)
+#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION            (0x09)
+#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT           (0x0A)
+#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT            (0x0B)
+#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA    (0x0C)
+#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR    (0x0D)
+#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED            (0x0E)
+#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH       (0x0F)
+#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA          (0x10)
+#define MPI2_SASSTATUS_DATA_OFFSET_ERROR                (0x11)
+#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED                (0x12)
+#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED           (0x13)
+#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT       (0x14)
+
+/*
+ *Values for the SAS DeviceInfo field used in SAS Device Status Change Event
+ *data and SAS Configuration pages.
+ */
+#define MPI2_SAS_DEVICE_INFO_SEP                (0x00004000)
+#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE       (0x00002000)
+#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE         (0x00001000)
+#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH      (0x00000800)
+#define MPI2_SAS_DEVICE_INFO_SSP_TARGET         (0x00000400)
+#define MPI2_SAS_DEVICE_INFO_STP_TARGET         (0x00000200)
+#define MPI2_SAS_DEVICE_INFO_SMP_TARGET         (0x00000100)
+#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE        (0x00000080)
+#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR      (0x00000040)
+#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR      (0x00000020)
+#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR      (0x00000010)
+#define MPI2_SAS_DEVICE_INFO_SATA_HOST          (0x00000008)
+
+#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE   (0x00000007)
+#define MPI2_SAS_DEVICE_INFO_NO_DEVICE          (0x00000000)
+#define MPI2_SAS_DEVICE_INFO_END_DEVICE         (0x00000001)
+#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER      (0x00000002)
+#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER    (0x00000003)
+
+/*****************************************************************************
+*
+*       SAS Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* SMP Passthrough messages
+****************************************************************************/
+
+/*SMP Passthrough Request Message */
+typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST {
+       U8 PassthroughFlags;    /*0x00 */
+       U8 PhysicalPort;        /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 RequestDataLength;  /*0x04 */
+       U8 SGLFlags;            /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+       U32 Reserved2;          /*0x0C */
+       U64 SASAddress;         /*0x10 */
+       U32 Reserved3;          /*0x18 */
+       U32 Reserved4;          /*0x1C */
+       MPI2_SIMPLE_SGE_UNION SGL;/*0x20 */
+} MPI2_SMP_PASSTHROUGH_REQUEST, *PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
+       Mpi2SmpPassthroughRequest_t, *pMpi2SmpPassthroughRequest_t;
+
+/*values for PassthroughFlags field */
+#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE      (0x80)
+
+/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+/*SMP Passthrough Reply Message */
+typedef struct _MPI2_SMP_PASSTHROUGH_REPLY {
+       U8 PassthroughFlags;    /*0x00 */
+       U8 PhysicalPort;        /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 ResponseDataLength; /*0x04 */
+       U8 SGLFlags;            /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+       U8 Reserved2;           /*0x0C */
+       U8 SASStatus;           /*0x0D */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 Reserved3;          /*0x14 */
+       U8 ResponseData[4];     /*0x18 */
+} MPI2_SMP_PASSTHROUGH_REPLY, *PTR_MPI2_SMP_PASSTHROUGH_REPLY,
+       Mpi2SmpPassthroughReply_t, *pMpi2SmpPassthroughReply_t;
+
+/*values for PassthroughFlags field */
+#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE    (0x80)
+
+/*values for SASStatus field are at the top of this file */
+
+/****************************************************************************
+* SATA Passthrough messages
+****************************************************************************/
+
+typedef union _MPI2_SATA_PT_SGE_UNION {
+       MPI2_SGE_SIMPLE_UNION MpiSimple;        /*MPI v2.0 only */
+       MPI2_SGE_CHAIN_UNION MpiChain;  /*MPI v2.0 only */
+       MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+       MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;    /*MPI v2.0 only */
+       MPI25_IEEE_SGE_CHAIN64 IeeeChain64;     /*MPI v2.5 only */
+} MPI2_SATA_PT_SGE_UNION, *PTR_MPI2_SATA_PT_SGE_UNION,
+       Mpi2SataPTSGEUnion_t, *pMpi2SataPTSGEUnion_t;
+
+/*SATA Passthrough Request Message */
+typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST {
+       U16 DevHandle;          /*0x00 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 PassthroughFlags;   /*0x04 */
+       U8 SGLFlags;            /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+       U32 Reserved2;          /*0x0C */
+       U32 Reserved3;          /*0x10 */
+       U32 Reserved4;          /*0x14 */
+       U32 DataLength;         /*0x18 */
+       U8 CommandFIS[20];      /*0x1C */
+       MPI2_SATA_PT_SGE_UNION SGL;/*0x30*//*MPI v2.5: IEEE 64 elements only*/
+} MPI2_SATA_PASSTHROUGH_REQUEST, *PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
+       Mpi2SataPassthroughRequest_t,
+       *pMpi2SataPassthroughRequest_t;
+
+/*values for PassthroughFlags field */
+#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG      (0x0100)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA               (0x0020)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO               (0x0010)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU    (0x0004)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE             (0x0002)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_READ              (0x0001)
+
+/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+/*SATA Passthrough Reply Message */
+typedef struct _MPI2_SATA_PASSTHROUGH_REPLY {
+       U16 DevHandle;          /*0x00 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 PassthroughFlags;   /*0x04 */
+       U8 SGLFlags;            /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved1;          /*0x0A */
+       U8 Reserved2;           /*0x0C */
+       U8 SASStatus;           /*0x0D */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U8 StatusFIS[20];       /*0x14 */
+       U32 StatusControlRegisters;     /*0x28 */
+       U32 TransferCount;      /*0x2C */
+} MPI2_SATA_PASSTHROUGH_REPLY, *PTR_MPI2_SATA_PASSTHROUGH_REPLY,
+       Mpi2SataPassthroughReply_t, *pMpi2SataPassthroughReply_t;
+
+/*values for SASStatus field are at the top of this file */
+
+/****************************************************************************
+* SAS IO Unit Control messages
+****************************************************************************/
+
+/*SAS IO Unit Control Request Message */
+typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST {
+       U8 Operation;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 DevHandle;          /*0x04 */
+       U8 IOCParameter;        /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U16 Reserved4;          /*0x0C */
+       U8 PhyNum;              /*0x0E */
+       U8 PrimFlags;           /*0x0F */
+       U32 Primitive;          /*0x10 */
+       U8 LookupMethod;        /*0x14 */
+       U8 Reserved5;           /*0x15 */
+       U16 SlotNumber;         /*0x16 */
+       U64 LookupAddress;      /*0x18 */
+       U32 IOCParameterValue;  /*0x20 */
+       U32 Reserved7;          /*0x24 */
+       U32 Reserved8;          /*0x28 */
+} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
+       *PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
+       Mpi2SasIoUnitControlRequest_t,
+       *pMpi2SasIoUnitControlRequest_t;
+
+/*values for the Operation field */
+#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT        (0x02)
+#define MPI2_SAS_OP_PHY_LINK_RESET              (0x06)
+#define MPI2_SAS_OP_PHY_HARD_RESET              (0x07)
+#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG         (0x08)
+#define MPI2_SAS_OP_SEND_PRIMITIVE              (0x0A)
+#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY        (0x0B)
+#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
+#define MPI2_SAS_OP_REMOVE_DEVICE               (0x0D)
+#define MPI2_SAS_OP_LOOKUP_MAPPING              (0x0E)
+#define MPI2_SAS_OP_SET_IOC_PARAMETER           (0x0F)
+#define MPI25_SAS_OP_ENABLE_FP_DEVICE           (0x10)
+#define MPI25_SAS_OP_DISABLE_FP_DEVICE          (0x11)
+#define MPI25_SAS_OP_ENABLE_FP_ALL              (0x12)
+#define MPI25_SAS_OP_DISABLE_FP_ALL             (0x13)
+#define MPI2_SAS_OP_DEV_ENABLE_NCQ              (0x14)
+#define MPI2_SAS_OP_DEV_DISABLE_NCQ             (0x15)
+#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN        (0x80)
+
+/*values for the PrimFlags field */
+#define MPI2_SAS_PRIMFLAGS_SINGLE               (0x08)
+#define MPI2_SAS_PRIMFLAGS_TRIPLE               (0x02)
+#define MPI2_SAS_PRIMFLAGS_REDUNDANT            (0x01)
+
+/*values for the LookupMethod field */
+#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS          (0x01)
+#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT   (0x02)
+#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME      (0x03)
+
+/*SAS IO Unit Control Reply Message */
+typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY {
+       U8 Operation;           /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 DevHandle;          /*0x04 */
+       U8 IOCParameter;        /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved3;          /*0x0A */
+       U16 Reserved4;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_SAS_IOUNIT_CONTROL_REPLY,
+       *PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
+       Mpi2SasIoUnitControlReply_t, *pMpi2SasIoUnitControlReply_t;
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
new file mode 100644 (file)
index 0000000..71453d1
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2000-2012 LSI Corporation.
+ *
+ *
+ *          Name:  mpi2_tool.h
+ *         Title:  MPI diagnostic tool structures and definitions
+ * Creation Date:  March 26, 2007
+ *
+ *   mpi2_tool.h Version:  02.00.09
+ *
+ * Version History
+ * ---------------
+ *
+ * Date      Version   Description
+ * --------  --------  ------------------------------------------------------
+ * 04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
+ *                     structures and defines.
+ * 02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ * 05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
+ * 07-30-09  02.00.04  Added ExtendedType field to DiagnosticBufferPost request
+ *                     and reply messages.
+ *                     Added MPI2_DIAG_BUF_TYPE_EXTENDED.
+ *                     Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ * 05-12-10  02.00.05  Added Diagnostic Data Upload tool.
+ * 08-11-10  02.00.06  Added defines that were missing for Diagnostic Buffer
+ *                     Post Request.
+ * 05-25-11  02.00.07  Added Flags field and related defines to
+ *                     MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST.
+ * 11-18-11  02.00.08  Incorporating additions for MPI v2.5.
+ * 07-10-12  02.00.09  Add MPI v2.5 Toolbox Diagnostic CLI Tool Request
+ *                     message.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TOOL_H
+#define MPI2_TOOL_H
+
+/*****************************************************************************
+*
+*              Toolbox Messages
+*
+*****************************************************************************/
+
+/*defines for the Tools */
+#define MPI2_TOOLBOX_CLEAN_TOOL                     (0x00)
+#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL               (0x01)
+#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL          (0x02)
+#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL          (0x03)
+#define MPI2_TOOLBOX_BEACON_TOOL                    (0x05)
+#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL            (0x06)
+
+/****************************************************************************
+* Toolbox reply
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_REPLY {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_TOOLBOX_REPLY, *PTR_MPI2_TOOLBOX_REPLY,
+       Mpi2ToolboxReply_t, *pMpi2ToolboxReply_t;
+
+/****************************************************************************
+* Toolbox Clean Tool request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 Flags;              /*0x0C */
+} MPI2_TOOLBOX_CLEAN_REQUEST, *PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
+       Mpi2ToolboxCleanRequest_t, *pMpi2ToolboxCleanRequest_t;
+
+/*values for the Flags field */
+#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES            (0x80000000)
+#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES   (0x40000000)
+#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES      (0x20000000)
+#define MPI2_TOOLBOX_CLEAN_FW_CURRENT               (0x10000000)
+#define MPI2_TOOLBOX_CLEAN_FW_BACKUP                (0x08000000)
+#define MPI2_TOOLBOX_CLEAN_MEGARAID                 (0x02000000)
+#define MPI2_TOOLBOX_CLEAN_INITIALIZATION           (0x01000000)
+#define MPI2_TOOLBOX_CLEAN_FLASH                    (0x00000004)
+#define MPI2_TOOLBOX_CLEAN_SEEPROM                  (0x00000002)
+#define MPI2_TOOLBOX_CLEAN_NVSRAM                   (0x00000001)
+
+/****************************************************************************
+* Toolbox Memory Move request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       MPI2_SGE_SIMPLE_UNION SGL;      /*0x0C */
+} MPI2_TOOLBOX_MEM_MOVE_REQUEST, *PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
+       Mpi2ToolboxMemMoveRequest_t, *pMpi2ToolboxMemMoveRequest_t;
+
+/****************************************************************************
+* Toolbox Diagnostic Data Upload request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U8 SGLFlags;            /*0x0C */
+       U8 Reserved5;           /*0x0D */
+       U16 Reserved6;          /*0x0E */
+       U32 Flags;              /*0x10 */
+       U32 DataLength;         /*0x14 */
+       MPI2_SGE_SIMPLE_UNION SGL;      /*0x18 */
+} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+       *PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+       Mpi2ToolboxDiagDataUploadRequest_t,
+       *pMpi2ToolboxDiagDataUploadRequest_t;
+
+/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER {
+       U32 DiagDataLength;     /*00h */
+       U8 FormatCode;          /*04h */
+       U8 Reserved1;           /*05h */
+       U16 Reserved2;          /*06h */
+} MPI2_DIAG_DATA_UPLOAD_HEADER, *PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
+       Mpi2DiagDataUploadHeader_t, *pMpi2DiagDataUploadHeader_t;
+
+/****************************************************************************
+* Toolbox ISTWI Read Write Tool
+****************************************************************************/
+
+/*Toolbox ISTWI Read Write Tool request message */
+typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 Reserved5;          /*0x0C */
+       U32 Reserved6;          /*0x10 */
+       U8 DevIndex;            /*0x14 */
+       U8 Action;              /*0x15 */
+       U8 SGLFlags;            /*0x16 */
+       U8 Flags;               /*0x17 */
+       U16 TxDataLength;       /*0x18 */
+       U16 RxDataLength;       /*0x1A */
+       U32 Reserved8;          /*0x1C */
+       U32 Reserved9;          /*0x20 */
+       U32 Reserved10;         /*0x24 */
+       U32 Reserved11;         /*0x28 */
+       U32 Reserved12;         /*0x2C */
+       MPI2_SGE_SIMPLE_UNION SGL;      /*0x30 */
+} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+       *PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+       Mpi2ToolboxIstwiReadWriteRequest_t,
+       *pMpi2ToolboxIstwiReadWriteRequest_t;
+
+/*values for the Action field */
+#define MPI2_TOOL_ISTWI_ACTION_READ_DATA            (0x01)
+#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA           (0x02)
+#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE             (0x03)
+#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS          (0x10)
+#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS          (0x11)
+#define MPI2_TOOL_ISTWI_ACTION_RESET                (0x12)
+
+/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+/*values for the Flags field */
+#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE   (0x80)
+#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK         (0x07)
+
+/*Toolbox ISTWI Read Write Tool reply message */
+typedef struct _MPI2_TOOLBOX_ISTWI_REPLY {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U8 DevIndex;            /*0x14 */
+       U8 Action;              /*0x15 */
+       U8 IstwiStatus;         /*0x16 */
+       U8 Reserved6;           /*0x17 */
+       U16 TxDataCount;        /*0x18 */
+       U16 RxDataCount;        /*0x1A */
+} MPI2_TOOLBOX_ISTWI_REPLY, *PTR_MPI2_TOOLBOX_ISTWI_REPLY,
+       Mpi2ToolboxIstwiReply_t, *pMpi2ToolboxIstwiReply_t;
+
+/****************************************************************************
+* Toolbox Beacon Tool request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_BEACON_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U8 Reserved5;           /*0x0C */
+       U8 PhysicalPort;        /*0x0D */
+       U8 Reserved6;           /*0x0E */
+       U8 Flags;               /*0x0F */
+} MPI2_TOOLBOX_BEACON_REQUEST, *PTR_MPI2_TOOLBOX_BEACON_REQUEST,
+       Mpi2ToolboxBeaconRequest_t, *pMpi2ToolboxBeaconRequest_t;
+
+/*values for the Flags field */
+#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF       (0x00)
+#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON        (0x01)
+
+/****************************************************************************
+* Toolbox Diagnostic CLI Tool
+****************************************************************************/
+
+#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH    (0x5C)
+
+/*MPI v2.0 Toolbox Diagnostic CLI Tool request message */
+typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U8 SGLFlags;            /*0x0C */
+       U8 Reserved5;           /*0x0D */
+       U16 Reserved6;          /*0x0E */
+       U32 DataLength;         /*0x10 */
+       U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */
+       MPI2_SGE_SIMPLE_UNION SGL;      /*0x70 */
+} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+       *PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+       Mpi2ToolboxDiagnosticCliRequest_t,
+       *pMpi2ToolboxDiagnosticCliRequest_t;
+
+/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+/*MPI v2.5 Toolbox Diagnostic CLI Tool request message */
+typedef struct _MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U32 Reserved5;          /*0x0C */
+       U32 DataLength;         /*0x10 */
+       U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */
+       MPI25_SGE_IO_UNION SGL; /*0x70 */
+} MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+       *PTR_MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+       Mpi25ToolboxDiagnosticCliRequest_t,
+       *pMpi25ToolboxDiagnosticCliRequest_t;
+
+/*Toolbox Diagnostic CLI Tool reply message */
+typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY {
+       U8 Tool;                /*0x00 */
+       U8 Reserved1;           /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 ReturnedDataLength; /*0x14 */
+} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY,
+       *PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY,
+       Mpi2ToolboxDiagnosticCliReply_t,
+       *pMpi2ToolboxDiagnosticCliReply_t;
+
+/*****************************************************************************
+*
+*      Diagnostic Buffer Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* Diagnostic Buffer Post request
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST {
+       U8 ExtendedType;        /*0x00 */
+       U8 BufferType;          /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U64 BufferAddress;      /*0x0C */
+       U32 BufferLength;       /*0x14 */
+       U32 Reserved5;          /*0x18 */
+       U32 Reserved6;          /*0x1C */
+       U32 Flags;              /*0x20 */
+       U32 ProductSpecific[23];        /*0x24 */
+} MPI2_DIAG_BUFFER_POST_REQUEST, *PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
+       Mpi2DiagBufferPostRequest_t, *pMpi2DiagBufferPostRequest_t;
+
+/*values for the ExtendedType field */
+#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION         (0x02)
+
+/*values for the BufferType field */
+#define MPI2_DIAG_BUF_TYPE_TRACE                    (0x00)
+#define MPI2_DIAG_BUF_TYPE_SNAPSHOT                 (0x01)
+#define MPI2_DIAG_BUF_TYPE_EXTENDED                 (0x02)
+/*count of the number of buffer types */
+#define MPI2_DIAG_BUF_TYPE_COUNT                    (0x03)
+
+/*values for the Flags field */
+#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL          (0x00000002)
+#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE        (0x00000001)
+
+/****************************************************************************
+* Diagnostic Buffer Post reply
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_BUFFER_POST_REPLY {
+       U8 ExtendedType;        /*0x00 */
+       U8 BufferType;          /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+       U32 TransferLength;     /*0x14 */
+} MPI2_DIAG_BUFFER_POST_REPLY, *PTR_MPI2_DIAG_BUFFER_POST_REPLY,
+       Mpi2DiagBufferPostReply_t, *pMpi2DiagBufferPostReply_t;
+
+/****************************************************************************
+* Diagnostic Release request
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_RELEASE_REQUEST {
+       U8 Reserved1;           /*0x00 */
+       U8 BufferType;          /*0x01 */
+       U8 ChainOffset;         /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+} MPI2_DIAG_RELEASE_REQUEST, *PTR_MPI2_DIAG_RELEASE_REQUEST,
+       Mpi2DiagReleaseRequest_t, *pMpi2DiagReleaseRequest_t;
+
+/****************************************************************************
+* Diagnostic Buffer Post reply
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_RELEASE_REPLY {
+       U8 Reserved1;           /*0x00 */
+       U8 BufferType;          /*0x01 */
+       U8 MsgLength;           /*0x02 */
+       U8 Function;            /*0x03 */
+       U16 Reserved2;          /*0x04 */
+       U8 Reserved3;           /*0x06 */
+       U8 MsgFlags;            /*0x07 */
+       U8 VP_ID;               /*0x08 */
+       U8 VF_ID;               /*0x09 */
+       U16 Reserved4;          /*0x0A */
+       U16 Reserved5;          /*0x0C */
+       U16 IOCStatus;          /*0x0E */
+       U32 IOCLogInfo;         /*0x10 */
+} MPI2_DIAG_RELEASE_REPLY, *PTR_MPI2_DIAG_RELEASE_REPLY,
+       Mpi2DiagReleaseReply_t, *pMpi2DiagReleaseReply_t;
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_type.h b/drivers/scsi/mpt3sas/mpi/mpi2_type.h
new file mode 100644 (file)
index 0000000..516f959
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2000-2007 LSI Corporation.
+ *
+ *
+ *           Name:  mpi2_type.h
+ *          Title:  MPI basic type definitions
+ *  Creation Date:  August 16, 2006
+ *
+ *    mpi2_type.h Version:  02.00.00
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TYPE_H
+#define MPI2_TYPE_H
+
+/*******************************************************************************
+ * Define * if it hasn't already been defined. By default
+ * * is defined to be a near pointer. MPI2_POINTER can be defined as
+ * a far pointer by defining * as "far *" before this header file is
+ * included.
+ */
+
+/* the basic types may have already been included by mpi_type.h */
+#ifndef MPI_TYPE_H
+/*****************************************************************************
+*
+*               Basic Types
+*
+*****************************************************************************/
+
+typedef u8 U8;
+typedef __le16 U16;
+typedef __le32 U32;
+typedef __le64 U64 __attribute__ ((aligned(4)));
+
+/*****************************************************************************
+*
+*               Pointer Types
+*
+*****************************************************************************/
+
+typedef U8 *PU8;
+typedef U16 *PU16;
+typedef U32 *PU32;
+typedef U64 *PU64;
+
+#endif
+
+#endif
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
new file mode 100644 (file)
index 0000000..04f8010
--- /dev/null
@@ -0,0 +1,4840 @@
+/*
+ * This is the Fusion MPT base driver providing common API layer interface
+ * for access to MPT (Message Passing Technology) firmware.
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/time.h>
+#include <linux/kthread.h>
+#include <linux/aer.h>
+
+
+#include "mpt3sas_base.h"
+
+static MPT_CALLBACK    mpt_callbacks[MPT_MAX_CALLBACKS];
+
+
+#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
+
+ /* maximum controller queue depth */
+#define MAX_HBA_QUEUE_DEPTH    30000
+#define MAX_CHAIN_DEPTH                100000
+static int max_queue_depth = -1;
+module_param(max_queue_depth, int, 0);
+MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
+
+static int max_sgl_entries = -1;
+module_param(max_sgl_entries, int, 0);
+MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
+
+static int msix_disable = -1;
+module_param(msix_disable, int, 0);
+MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
+
+
+static int mpt3sas_fwfault_debug;
+MODULE_PARM_DESC(mpt3sas_fwfault_debug,
+       " enable detection of firmware fault and halt firmware - (default=0)");
+
+
+/**
+ * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
+ *
+ */
+static int
+_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+       struct MPT3SAS_ADAPTER *ioc;
+
+       if (ret)
+               return ret;
+
+       pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug);
+       list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
+               ioc->fwfault_debug = mpt3sas_fwfault_debug;
+       return 0;
+}
+module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug,
+       param_get_int, &mpt3sas_fwfault_debug, 0644);
+
+/**
+ *  mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc
+ * @arg: input argument, used to derive ioc
+ *
+ * Return 0 if controller is removed from pci subsystem.
+ * Return -1 for other case.
+ */
+static int mpt3sas_remove_dead_ioc_func(void *arg)
+{
+       struct MPT3SAS_ADAPTER *ioc = (struct MPT3SAS_ADAPTER *)arg;
+       struct pci_dev *pdev;
+
+       if ((ioc == NULL))
+               return -1;
+
+       pdev = ioc->pdev;
+       if ((pdev == NULL))
+               return -1;
+       pci_stop_and_remove_bus_device(pdev);
+       return 0;
+}
+
+/**
+ * _base_fault_reset_work - workq handling ioc fault conditions
+ * @work: input argument, used to derive ioc
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+static void
+_base_fault_reset_work(struct work_struct *work)
+{
+       struct MPT3SAS_ADAPTER *ioc =
+           container_of(work, struct MPT3SAS_ADAPTER, fault_reset_work.work);
+       unsigned long    flags;
+       u32 doorbell;
+       int rc;
+       struct task_struct *p;
+
+
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->shost_recovery)
+               goto rearm_timer;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+       doorbell = mpt3sas_base_get_iocstate(ioc, 0);
+       if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) {
+               pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n",
+                   ioc->name);
+
+               /*
+                * Call _scsih_flush_pending_cmds callback so that we flush all
+                * pending commands back to OS. This call is required to aovid
+                * deadlock at block layer. Dead IOC will fail to do diag reset,
+                * and this call is safe since dead ioc will never return any
+                * command back from HW.
+                */
+               ioc->schedule_dead_ioc_flush_running_cmds(ioc);
+               /*
+                * Set remove_host flag early since kernel thread will
+                * take some time to execute.
+                */
+               ioc->remove_host = 1;
+               /*Remove the Dead Host */
+               p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc,
+                   "mpt3sas_dead_ioc_%d", ioc->id);
+               if (IS_ERR(p))
+                       pr_err(MPT3SAS_FMT
+                       "%s: Running mpt3sas_dead_ioc thread failed !!!!\n",
+                       ioc->name, __func__);
+               else
+                       pr_err(MPT3SAS_FMT
+                       "%s: Running mpt3sas_dead_ioc thread success !!!!\n",
+                       ioc->name, __func__);
+               return; /* don't rearm timer */
+       }
+
+       if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) {
+               rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+               pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name,
+                   __func__, (rc == 0) ? "success" : "failed");
+               doorbell = mpt3sas_base_get_iocstate(ioc, 0);
+               if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
+                       mpt3sas_base_fault_info(ioc, doorbell &
+                           MPI2_DOORBELL_DATA_MASK);
+               if (rc && (doorbell & MPI2_IOC_STATE_MASK) !=
+                   MPI2_IOC_STATE_OPERATIONAL)
+                       return; /* don't rearm timer */
+       }
+
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ rearm_timer:
+       if (ioc->fault_reset_work_q)
+               queue_delayed_work(ioc->fault_reset_work_q,
+                   &ioc->fault_reset_work,
+                   msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+}
+
+/**
+ * mpt3sas_base_start_watchdog - start the fault_reset_work_q
+ * @ioc: per adapter object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc)
+{
+       unsigned long    flags;
+
+       if (ioc->fault_reset_work_q)
+               return;
+
+       /* initialize fault polling */
+
+       INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
+       snprintf(ioc->fault_reset_work_q_name,
+           sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+       ioc->fault_reset_work_q =
+               create_singlethread_workqueue(ioc->fault_reset_work_q_name);
+       if (!ioc->fault_reset_work_q) {
+               pr_err(MPT3SAS_FMT "%s: failed (line=%d)\n",
+                   ioc->name, __func__, __LINE__);
+                       return;
+       }
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->fault_reset_work_q)
+               queue_delayed_work(ioc->fault_reset_work_q,
+                   &ioc->fault_reset_work,
+                   msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+}
+
+/**
+ * mpt3sas_base_stop_watchdog - stop the fault_reset_work_q
+ * @ioc: per adapter object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc)
+{
+       unsigned long flags;
+       struct workqueue_struct *wq;
+
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       wq = ioc->fault_reset_work_q;
+       ioc->fault_reset_work_q = NULL;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (wq) {
+               if (!cancel_delayed_work(&ioc->fault_reset_work))
+                       flush_workqueue(wq);
+               destroy_workqueue(wq);
+       }
+}
+
+/**
+ * mpt3sas_base_fault_info - verbose translation of firmware FAULT code
+ * @ioc: per adapter object
+ * @fault_code: fault code
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code)
+{
+       pr_err(MPT3SAS_FMT "fault_state(0x%04x)!\n",
+           ioc->name, fault_code);
+}
+
+/**
+ * mpt3sas_halt_firmware - halt's mpt controller firmware
+ * @ioc: per adapter object
+ *
+ * For debugging timeout related issues.  Writing 0xCOFFEE00
+ * to the doorbell register will halt controller firmware. With
+ * the purpose to stop both driver and firmware, the enduser can
+ * obtain a ring buffer from controller UART.
+ */
+void
+mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc)
+{
+       u32 doorbell;
+
+       if (!ioc->fwfault_debug)
+               return;
+
+       dump_stack();
+
+       doorbell = readl(&ioc->chip->Doorbell);
+       if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
+               mpt3sas_base_fault_info(ioc , doorbell);
+       else {
+               writel(0xC0FFEE00, &ioc->chip->Doorbell);
+               pr_err(MPT3SAS_FMT "Firmware is halted due to command timeout\n",
+                       ioc->name);
+       }
+
+       if (ioc->fwfault_debug == 2)
+               for (;;)
+                       ;
+       else
+               panic("panic in %s\n", __func__);
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _base_sas_ioc_info - verbose translation of the ioc status
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @request_hdr: request mf
+ *
+ * Return nothing.
+ */
+static void
+_base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
+       MPI2RequestHeader_t *request_hdr)
+{
+       u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       char *desc = NULL;
+       u16 frame_sz;
+       char *func_str = NULL;
+
+       /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
+       if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+           request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
+           request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
+               return;
+
+       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+               return;
+
+       switch (ioc_status) {
+
+/****************************************************************************
+*  Common IOCStatus values for all replies
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_INVALID_FUNCTION:
+               desc = "invalid function";
+               break;
+       case MPI2_IOCSTATUS_BUSY:
+               desc = "busy";
+               break;
+       case MPI2_IOCSTATUS_INVALID_SGL:
+               desc = "invalid sgl";
+               break;
+       case MPI2_IOCSTATUS_INTERNAL_ERROR:
+               desc = "internal error";
+               break;
+       case MPI2_IOCSTATUS_INVALID_VPID:
+               desc = "invalid vpid";
+               break;
+       case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
+               desc = "insufficient resources";
+               break;
+       case MPI2_IOCSTATUS_INVALID_FIELD:
+               desc = "invalid field";
+               break;
+       case MPI2_IOCSTATUS_INVALID_STATE:
+               desc = "invalid state";
+               break;
+       case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
+               desc = "op state not supported";
+               break;
+
+/****************************************************************************
+*  Config IOCStatus values
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
+               desc = "config invalid action";
+               break;
+       case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
+               desc = "config invalid type";
+               break;
+       case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
+               desc = "config invalid page";
+               break;
+       case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
+               desc = "config invalid data";
+               break;
+       case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
+               desc = "config no defaults";
+               break;
+       case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
+               desc = "config cant commit";
+               break;
+
+/****************************************************************************
+*  SCSI IO Reply
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+       case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+       case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+       case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+       case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+       case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+       case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+       case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+       case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+       case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+       case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+       case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+               break;
+
+/****************************************************************************
+*  For use by SCSI Initiator and SCSI Target end-to-end data protection
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
+               desc = "eedp guard error";
+               break;
+       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
+               desc = "eedp ref tag error";
+               break;
+       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
+               desc = "eedp app tag error";
+               break;
+
+/****************************************************************************
+*  SCSI Target values
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
+               desc = "target invalid io index";
+               break;
+       case MPI2_IOCSTATUS_TARGET_ABORTED:
+               desc = "target aborted";
+               break;
+       case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
+               desc = "target no conn retryable";
+               break;
+       case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
+               desc = "target no connection";
+               break;
+       case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
+               desc = "target xfer count mismatch";
+               break;
+       case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
+               desc = "target data offset error";
+               break;
+       case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
+               desc = "target too much write data";
+               break;
+       case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
+               desc = "target iu too short";
+               break;
+       case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
+               desc = "target ack nak timeout";
+               break;
+       case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
+               desc = "target nak received";
+               break;
+
+/****************************************************************************
+*  Serial Attached SCSI values
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
+               desc = "smp request failed";
+               break;
+       case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
+               desc = "smp data overrun";
+               break;
+
+/****************************************************************************
+*  Diagnostic Buffer Post / Diagnostic Release values
+****************************************************************************/
+
+       case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
+               desc = "diagnostic released";
+               break;
+       default:
+               break;
+       }
+
+       if (!desc)
+               return;
+
+       switch (request_hdr->Function) {
+       case MPI2_FUNCTION_CONFIG:
+               frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
+               func_str = "config_page";
+               break;
+       case MPI2_FUNCTION_SCSI_TASK_MGMT:
+               frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
+               func_str = "task_mgmt";
+               break;
+       case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
+               frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
+               func_str = "sas_iounit_ctl";
+               break;
+       case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
+               frame_sz = sizeof(Mpi2SepRequest_t);
+               func_str = "enclosure";
+               break;
+       case MPI2_FUNCTION_IOC_INIT:
+               frame_sz = sizeof(Mpi2IOCInitRequest_t);
+               func_str = "ioc_init";
+               break;
+       case MPI2_FUNCTION_PORT_ENABLE:
+               frame_sz = sizeof(Mpi2PortEnableRequest_t);
+               func_str = "port_enable";
+               break;
+       case MPI2_FUNCTION_SMP_PASSTHROUGH:
+               frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
+               func_str = "smp_passthru";
+               break;
+       default:
+               frame_sz = 32;
+               func_str = "unknown";
+               break;
+       }
+
+       pr_warn(MPT3SAS_FMT "ioc_status: %s(0x%04x), request(0x%p),(%s)\n",
+               ioc->name, desc, ioc_status, request_hdr, func_str);
+
+       _debug_dump_mf(request_hdr, frame_sz/4);
+}
+
+/**
+ * _base_display_event_data - verbose translation of firmware asyn events
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ *
+ * Return nothing.
+ */
+static void
+_base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventNotificationReply_t *mpi_reply)
+{
+       char *desc = NULL;
+       u16 event;
+
+       if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
+               return;
+
+       event = le16_to_cpu(mpi_reply->Event);
+
+       switch (event) {
+       case MPI2_EVENT_LOG_DATA:
+               desc = "Log Data";
+               break;
+       case MPI2_EVENT_STATE_CHANGE:
+               desc = "Status Change";
+               break;
+       case MPI2_EVENT_HARD_RESET_RECEIVED:
+               desc = "Hard Reset Received";
+               break;
+       case MPI2_EVENT_EVENT_CHANGE:
+               desc = "Event Change";
+               break;
+       case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+               desc = "Device Status Change";
+               break;
+       case MPI2_EVENT_IR_OPERATION_STATUS:
+               desc = "IR Operation Status";
+               break;
+       case MPI2_EVENT_SAS_DISCOVERY:
+       {
+               Mpi2EventDataSasDiscovery_t *event_data =
+                   (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData;
+               pr_info(MPT3SAS_FMT "Discovery: (%s)", ioc->name,
+                   (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
+                   "start" : "stop");
+               if (event_data->DiscoveryStatus)
+                       pr_info("discovery_status(0x%08x)",
+                           le32_to_cpu(event_data->DiscoveryStatus));
+                       pr_info("\n");
+               return;
+       }
+       case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+               desc = "SAS Broadcast Primitive";
+               break;
+       case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+               desc = "SAS Init Device Status Change";
+               break;
+       case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
+               desc = "SAS Init Table Overflow";
+               break;
+       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+               desc = "SAS Topology Change List";
+               break;
+       case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+               desc = "SAS Enclosure Device Status Change";
+               break;
+       case MPI2_EVENT_IR_VOLUME:
+               desc = "IR Volume";
+               break;
+       case MPI2_EVENT_IR_PHYSICAL_DISK:
+               desc = "IR Physical Disk";
+               break;
+       case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+               desc = "IR Configuration Change List";
+               break;
+       case MPI2_EVENT_LOG_ENTRY_ADDED:
+               desc = "Log Entry Added";
+               break;
+       }
+
+       if (!desc)
+               return;
+
+       pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc);
+}
+#endif
+
+/**
+ * _base_sas_log_info - verbose translation of firmware log info
+ * @ioc: per adapter object
+ * @log_info: log info
+ *
+ * Return nothing.
+ */
+static void
+_base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info)
+{
+       union loginfo_type {
+               u32     loginfo;
+               struct {
+                       u32     subcode:16;
+                       u32     code:8;
+                       u32     originator:4;
+                       u32     bus_type:4;
+               } dw;
+       };
+       union loginfo_type sas_loginfo;
+       char *originator_str = NULL;
+
+       sas_loginfo.loginfo = log_info;
+       if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
+               return;
+
+       /* each nexus loss loginfo */
+       if (log_info == 0x31170000)
+               return;
+
+       /* eat the loginfos associated with task aborts */
+       if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info ==
+           0x31140000 || log_info == 0x31130000))
+               return;
+
+       switch (sas_loginfo.dw.originator) {
+       case 0:
+               originator_str = "IOP";
+               break;
+       case 1:
+               originator_str = "PL";
+               break;
+       case 2:
+               originator_str = "IR";
+               break;
+       }
+
+       pr_warn(MPT3SAS_FMT
+               "log_info(0x%08x): originator(%s), code(0x%02x), sub_code(0x%04x)\n",
+               ioc->name, log_info,
+            originator_str, sas_loginfo.dw.code,
+            sas_loginfo.dw.subcode);
+}
+
+/**
+ * _base_display_reply_info -
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return nothing.
+ */
+static void
+_base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+       u16 ioc_status;
+       u32 loginfo = 0;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (unlikely(!mpi_reply)) {
+               pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
+           (ioc->logging_level & MPT_DEBUG_REPLY)) {
+               _base_sas_ioc_info(ioc , mpi_reply,
+                  mpt3sas_base_get_msg_frame(ioc, smid));
+       }
+#endif
+       if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+               loginfo = le32_to_cpu(mpi_reply->IOCLogInfo);
+               _base_sas_log_info(ioc, loginfo);
+       }
+
+       if (ioc_status || loginfo) {
+               ioc_status &= MPI2_IOCSTATUS_MASK;
+               mpt3sas_trigger_mpi(ioc, ioc_status, loginfo);
+       }
+}
+
+/**
+ * mpt3sas_base_done - base internal command completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
+               return 1;
+
+       if (ioc->base_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+
+       ioc->base_cmds.status |= MPT3_CMD_COMPLETE;
+       if (mpi_reply) {
+               ioc->base_cmds.status |= MPT3_CMD_REPLY_VALID;
+               memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+       }
+       ioc->base_cmds.status &= ~MPT3_CMD_PENDING;
+
+       complete(&ioc->base_cmds.done);
+       return 1;
+}
+
+/**
+ * _base_async_event - main callback handler for firmware asyn events
+ * @ioc: per adapter object
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
+{
+       Mpi2EventNotificationReply_t *mpi_reply;
+       Mpi2EventAckRequest_t *ack_request;
+       u16 smid;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (!mpi_reply)
+               return 1;
+       if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
+               return 1;
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       _base_display_event_data(ioc, mpi_reply);
+#endif
+       if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
+               goto out;
+       smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               goto out;
+       }
+
+       ack_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
+       ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
+       ack_request->Event = mpi_reply->Event;
+       ack_request->EventContext = mpi_reply->EventContext;
+       ack_request->VF_ID = 0;  /* TODO */
+       ack_request->VP_ID = 0;
+       mpt3sas_base_put_smid_default(ioc, smid);
+
+ out:
+
+       /* scsih callback handler */
+       mpt3sas_scsih_event_callback(ioc, msix_index, reply);
+
+       /* ctl callback handler */
+       mpt3sas_ctl_event_callback(ioc, msix_index, reply);
+
+       return 1;
+}
+
+/**
+ * _base_get_cb_idx - obtain the callback index
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Return callback index.
+ */
+static u8
+_base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       int i;
+       u8 cb_idx;
+
+       if (smid < ioc->hi_priority_smid) {
+               i = smid - 1;
+               cb_idx = ioc->scsi_lookup[i].cb_idx;
+       } else if (smid < ioc->internal_smid) {
+               i = smid - ioc->hi_priority_smid;
+               cb_idx = ioc->hpr_lookup[i].cb_idx;
+       } else if (smid <= ioc->hba_queue_depth) {
+               i = smid - ioc->internal_smid;
+               cb_idx = ioc->internal_lookup[i].cb_idx;
+       } else
+               cb_idx = 0xFF;
+       return cb_idx;
+}
+
+/**
+ * _base_mask_interrupts - disable interrupts
+ * @ioc: per adapter object
+ *
+ * Disabling ResetIRQ, Reply and Doorbell Interrupts
+ *
+ * Return nothing.
+ */
+static void
+_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc)
+{
+       u32 him_register;
+
+       ioc->mask_interrupts = 1;
+       him_register = readl(&ioc->chip->HostInterruptMask);
+       him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
+       writel(him_register, &ioc->chip->HostInterruptMask);
+       readl(&ioc->chip->HostInterruptMask);
+}
+
+/**
+ * _base_unmask_interrupts - enable interrupts
+ * @ioc: per adapter object
+ *
+ * Enabling only Reply Interrupts
+ *
+ * Return nothing.
+ */
+static void
+_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc)
+{
+       u32 him_register;
+
+       him_register = readl(&ioc->chip->HostInterruptMask);
+       him_register &= ~MPI2_HIM_RIM;
+       writel(him_register, &ioc->chip->HostInterruptMask);
+       ioc->mask_interrupts = 0;
+}
+
+union reply_descriptor {
+       u64 word;
+       struct {
+               u32 low;
+               u32 high;
+       } u;
+};
+
+/**
+ * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
+ * @irq: irq number (not used)
+ * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
+ * @r: pt_regs pointer (not used)
+ *
+ * Return IRQ_HANDLE if processed, else IRQ_NONE.
+ */
+static irqreturn_t
+_base_interrupt(int irq, void *bus_id)
+{
+       struct adapter_reply_queue *reply_q = bus_id;
+       union reply_descriptor rd;
+       u32 completed_cmds;
+       u8 request_desript_type;
+       u16 smid;
+       u8 cb_idx;
+       u32 reply;
+       u8 msix_index = reply_q->msix_index;
+       struct MPT3SAS_ADAPTER *ioc = reply_q->ioc;
+       Mpi2ReplyDescriptorsUnion_t *rpf;
+       u8 rc;
+
+       if (ioc->mask_interrupts)
+               return IRQ_NONE;
+
+       if (!atomic_add_unless(&reply_q->busy, 1, 1))
+               return IRQ_NONE;
+
+       rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index];
+       request_desript_type = rpf->Default.ReplyFlags
+            & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+       if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
+               atomic_dec(&reply_q->busy);
+               return IRQ_NONE;
+       }
+
+       completed_cmds = 0;
+       cb_idx = 0xFF;
+       do {
+               rd.word = le64_to_cpu(rpf->Words);
+               if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
+                       goto out;
+               reply = 0;
+               smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
+               if (request_desript_type ==
+                   MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS ||
+                   request_desript_type ==
+                   MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
+                       cb_idx = _base_get_cb_idx(ioc, smid);
+                       if ((likely(cb_idx < MPT_MAX_CALLBACKS)) &&
+                           (likely(mpt_callbacks[cb_idx] != NULL))) {
+                               rc = mpt_callbacks[cb_idx](ioc, smid,
+                                   msix_index, 0);
+                               if (rc)
+                                       mpt3sas_base_free_smid(ioc, smid);
+                       }
+               } else if (request_desript_type ==
+                   MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
+                       reply = le32_to_cpu(
+                           rpf->AddressReply.ReplyFrameAddress);
+                       if (reply > ioc->reply_dma_max_address ||
+                           reply < ioc->reply_dma_min_address)
+                               reply = 0;
+                       if (smid) {
+                               cb_idx = _base_get_cb_idx(ioc, smid);
+                               if ((likely(cb_idx < MPT_MAX_CALLBACKS)) &&
+                                   (likely(mpt_callbacks[cb_idx] != NULL))) {
+                                       rc = mpt_callbacks[cb_idx](ioc, smid,
+                                           msix_index, reply);
+                                       if (reply)
+                                               _base_display_reply_info(ioc,
+                                                   smid, msix_index, reply);
+                                       if (rc)
+                                               mpt3sas_base_free_smid(ioc,
+                                                   smid);
+                               }
+                       } else {
+                               _base_async_event(ioc, msix_index, reply);
+                       }
+
+                       /* reply free queue handling */
+                       if (reply) {
+                               ioc->reply_free_host_index =
+                                   (ioc->reply_free_host_index ==
+                                   (ioc->reply_free_queue_depth - 1)) ?
+                                   0 : ioc->reply_free_host_index + 1;
+                               ioc->reply_free[ioc->reply_free_host_index] =
+                                   cpu_to_le32(reply);
+                               wmb();
+                               writel(ioc->reply_free_host_index,
+                                   &ioc->chip->ReplyFreeHostIndex);
+                       }
+               }
+
+               rpf->Words = cpu_to_le64(ULLONG_MAX);
+               reply_q->reply_post_host_index =
+                   (reply_q->reply_post_host_index ==
+                   (ioc->reply_post_queue_depth - 1)) ? 0 :
+                   reply_q->reply_post_host_index + 1;
+               request_desript_type =
+                   reply_q->reply_post_free[reply_q->reply_post_host_index].
+                   Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+               completed_cmds++;
+               if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+                       goto out;
+               if (!reply_q->reply_post_host_index)
+                       rpf = reply_q->reply_post_free;
+               else
+                       rpf++;
+       } while (1);
+
+ out:
+
+       if (!completed_cmds) {
+               atomic_dec(&reply_q->busy);
+               return IRQ_NONE;
+       }
+
+       wmb();
+       writel(reply_q->reply_post_host_index | (msix_index <<
+           MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex);
+       atomic_dec(&reply_q->busy);
+       return IRQ_HANDLED;
+}
+
+/**
+ * _base_is_controller_msix_enabled - is controller support muli-reply queues
+ * @ioc: per adapter object
+ *
+ */
+static inline int
+_base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc)
+{
+       return (ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable;
+}
+
+/**
+ * mpt3sas_base_flush_reply_queues - flushing the MSIX reply queues
+ * @ioc: per adapter object
+ * Context: ISR conext
+ *
+ * Called when a Task Management request has completed. We want
+ * to flush the other reply queues so all the outstanding IO has been
+ * completed back to OS before we process the TM completetion.
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct adapter_reply_queue *reply_q;
+
+       /* If MSIX capability is turned off
+        * then multi-queues are not enabled
+        */
+       if (!_base_is_controller_msix_enabled(ioc))
+               return;
+
+       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+               if (ioc->shost_recovery)
+                       return;
+               /* TMs are on msix_index == 0 */
+               if (reply_q->msix_index == 0)
+                       continue;
+               _base_interrupt(reply_q->vector, (void *)reply_q);
+       }
+}
+
+/**
+ * mpt3sas_base_release_callback_handler - clear interrupt callback handler
+ * @cb_idx: callback index
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_release_callback_handler(u8 cb_idx)
+{
+       mpt_callbacks[cb_idx] = NULL;
+}
+
+/**
+ * mpt3sas_base_register_callback_handler - obtain index for the interrupt callback handler
+ * @cb_func: callback function
+ *
+ * Returns cb_func.
+ */
+u8
+mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func)
+{
+       u8 cb_idx;
+
+       for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
+               if (mpt_callbacks[cb_idx] == NULL)
+                       break;
+
+       mpt_callbacks[cb_idx] = cb_func;
+       return cb_idx;
+}
+
+/**
+ * mpt3sas_base_initialize_callback_handler - initialize the interrupt callback handler
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_initialize_callback_handler(void)
+{
+       u8 cb_idx;
+
+       for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
+               mpt3sas_base_release_callback_handler(cb_idx);
+}
+
+
+/**
+ * _base_build_zero_len_sge - build zero length sg entry
+ * @ioc: per adapter object
+ * @paddr: virtual address for SGE
+ *
+ * Create a zero length scatter gather entry to insure the IOCs hardware has
+ * something to use if the target device goes brain dead and tries
+ * to send data even when none is asked for.
+ *
+ * Return nothing.
+ */
+static void
+_base_build_zero_len_sge(struct MPT3SAS_ADAPTER *ioc, void *paddr)
+{
+       u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
+           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
+           MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
+           MPI2_SGE_FLAGS_SHIFT);
+       ioc->base_add_sg_single(paddr, flags_length, -1);
+}
+
+/**
+ * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
+ * @paddr: virtual address for SGE
+ * @flags_length: SGE flags and data transfer length
+ * @dma_addr: Physical address
+ *
+ * Return nothing.
+ */
+static void
+_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
+{
+       Mpi2SGESimple32_t *sgel = paddr;
+
+       flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
+           MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
+       sgel->FlagsLength = cpu_to_le32(flags_length);
+       sgel->Address = cpu_to_le32(dma_addr);
+}
+
+
+/**
+ * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
+ * @paddr: virtual address for SGE
+ * @flags_length: SGE flags and data transfer length
+ * @dma_addr: Physical address
+ *
+ * Return nothing.
+ */
+static void
+_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
+{
+       Mpi2SGESimple64_t *sgel = paddr;
+
+       flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
+           MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
+       sgel->FlagsLength = cpu_to_le32(flags_length);
+       sgel->Address = cpu_to_le64(dma_addr);
+}
+
+/**
+ * _base_get_chain_buffer_tracker - obtain chain tracker
+ * @ioc: per adapter object
+ * @smid: smid associated to an IO request
+ *
+ * Returns chain tracker(from ioc->free_chain_list)
+ */
+static struct chain_tracker *
+_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       struct chain_tracker *chain_req;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (list_empty(&ioc->free_chain_list)) {
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                       "chain buffers not available\n", ioc->name));
+               return NULL;
+       }
+       chain_req = list_entry(ioc->free_chain_list.next,
+           struct chain_tracker, tracker_list);
+       list_del_init(&chain_req->tracker_list);
+       list_add_tail(&chain_req->tracker_list,
+           &ioc->scsi_lookup[smid - 1].chain_list);
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return chain_req;
+}
+
+
+/**
+ * _base_build_sg - build generic sg
+ * @ioc: per adapter object
+ * @psge: virtual address for SGE
+ * @data_out_dma: physical address for WRITES
+ * @data_out_sz: data xfer size for WRITES
+ * @data_in_dma: physical address for READS
+ * @data_in_sz: data xfer size for READS
+ *
+ * Return nothing.
+ */
+static void
+_base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge,
+       dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma,
+       size_t data_in_sz)
+{
+       u32 sgl_flags;
+
+       if (!data_out_sz && !data_in_sz) {
+               _base_build_zero_len_sge(ioc, psge);
+               return;
+       }
+
+       if (data_out_sz && data_in_sz) {
+               /* WRITE sgel first */
+               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
+               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+               ioc->base_add_sg_single(psge, sgl_flags |
+                   data_out_sz, data_out_dma);
+
+               /* incr sgel */
+               psge += ioc->sge_size;
+
+               /* READ sgel last */
+               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+                   MPI2_SGE_FLAGS_END_OF_LIST);
+               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+               ioc->base_add_sg_single(psge, sgl_flags |
+                   data_in_sz, data_in_dma);
+       } else if (data_out_sz) /* WRITE */ {
+               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+                   MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
+               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+               ioc->base_add_sg_single(psge, sgl_flags |
+                   data_out_sz, data_out_dma);
+       } else if (data_in_sz) /* READ */ {
+               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+                   MPI2_SGE_FLAGS_END_OF_LIST);
+               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+               ioc->base_add_sg_single(psge, sgl_flags |
+                   data_in_sz, data_in_dma);
+       }
+}
+
+/* IEEE format sgls */
+
+/**
+ * _base_add_sg_single_ieee - add sg element for IEEE format
+ * @paddr: virtual address for SGE
+ * @flags: SGE flags
+ * @chain_offset: number of 128 byte elements from start of segment
+ * @length: data transfer length
+ * @dma_addr: Physical address
+ *
+ * Return nothing.
+ */
+static void
+_base_add_sg_single_ieee(void *paddr, u8 flags, u8 chain_offset, u32 length,
+       dma_addr_t dma_addr)
+{
+       Mpi25IeeeSgeChain64_t *sgel = paddr;
+
+       sgel->Flags = flags;
+       sgel->NextChainOffset = chain_offset;
+       sgel->Length = cpu_to_le32(length);
+       sgel->Address = cpu_to_le64(dma_addr);
+}
+
+/**
+ * _base_build_zero_len_sge_ieee - build zero length sg entry for IEEE format
+ * @ioc: per adapter object
+ * @paddr: virtual address for SGE
+ *
+ * Create a zero length scatter gather entry to insure the IOCs hardware has
+ * something to use if the target device goes brain dead and tries
+ * to send data even when none is asked for.
+ *
+ * Return nothing.
+ */
+static void
+_base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
+{
+       u8 sgl_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
+               MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
+               MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
+       _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1);
+}
+
+/**
+ * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format
+ * @ioc: per adapter object
+ * @scmd: scsi command
+ * @smid: system request message index
+ * Context: none.
+ *
+ * The main routine that builds scatter gather table from a given
+ * scsi request sent via the .queuecommand main handler.
+ *
+ * Returns 0 success, anything else error
+ */
+static int
+_base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
+       struct scsi_cmnd *scmd, u16 smid)
+{
+       Mpi2SCSIIORequest_t *mpi_request;
+       dma_addr_t chain_dma;
+       struct scatterlist *sg_scmd;
+       void *sg_local, *chain;
+       u32 chain_offset;
+       u32 chain_length;
+       u32 chain_flags;
+       int sges_left;
+       u32 sges_in_segment;
+       u8 simple_sgl_flags;
+       u8 simple_sgl_flags_last;
+       u8 chain_sgl_flags;
+       struct chain_tracker *chain_req;
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+
+       /* init scatter gather flags */
+       simple_sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
+           MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
+       simple_sgl_flags_last = simple_sgl_flags |
+           MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
+       chain_sgl_flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+           MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
+
+       sg_scmd = scsi_sglist(scmd);
+       sges_left = scsi_dma_map(scmd);
+       if (!sges_left) {
+               sdev_printk(KERN_ERR, scmd->device,
+                       "pci_map_sg failed: request for %d bytes!\n",
+                       scsi_bufflen(scmd));
+               return -ENOMEM;
+       }
+
+       sg_local = &mpi_request->SGL;
+       sges_in_segment = (ioc->request_sz -
+           offsetof(Mpi2SCSIIORequest_t, SGL))/ioc->sge_size_ieee;
+       if (sges_left <= sges_in_segment)
+               goto fill_in_last_segment;
+
+       mpi_request->ChainOffset = (sges_in_segment - 1 /* chain element */) +
+           (offsetof(Mpi2SCSIIORequest_t, SGL)/ioc->sge_size_ieee);
+
+       /* fill in main message segment when there is a chain following */
+       while (sges_in_segment > 1) {
+               _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0,
+                   sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+               sg_scmd = sg_next(sg_scmd);
+               sg_local += ioc->sge_size_ieee;
+               sges_left--;
+               sges_in_segment--;
+       }
+
+       /* initializing the chain flags and pointers */
+       chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
+       chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+       if (!chain_req)
+               return -1;
+       chain = chain_req->chain_buffer;
+       chain_dma = chain_req->chain_buffer_dma;
+       do {
+               sges_in_segment = (sges_left <=
+                   ioc->max_sges_in_chain_message) ? sges_left :
+                   ioc->max_sges_in_chain_message;
+               chain_offset = (sges_left == sges_in_segment) ?
+                   0 : sges_in_segment;
+               chain_length = sges_in_segment * ioc->sge_size_ieee;
+               if (chain_offset)
+                       chain_length += ioc->sge_size_ieee;
+               _base_add_sg_single_ieee(sg_local, chain_sgl_flags,
+                   chain_offset, chain_length, chain_dma);
+
+               sg_local = chain;
+               if (!chain_offset)
+                       goto fill_in_last_segment;
+
+               /* fill in chain segments */
+               while (sges_in_segment) {
+                       _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0,
+                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+                       sg_scmd = sg_next(sg_scmd);
+                       sg_local += ioc->sge_size_ieee;
+                       sges_left--;
+                       sges_in_segment--;
+               }
+
+               chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+               if (!chain_req)
+                       return -1;
+               chain = chain_req->chain_buffer;
+               chain_dma = chain_req->chain_buffer_dma;
+       } while (1);
+
+
+ fill_in_last_segment:
+
+       /* fill the last segment */
+       while (sges_left) {
+               if (sges_left == 1)
+                       _base_add_sg_single_ieee(sg_local,
+                           simple_sgl_flags_last, 0, sg_dma_len(sg_scmd),
+                           sg_dma_address(sg_scmd));
+               else
+                       _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0,
+                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+               sg_scmd = sg_next(sg_scmd);
+               sg_local += ioc->sge_size_ieee;
+               sges_left--;
+       }
+
+       return 0;
+}
+
+/**
+ * _base_build_sg_ieee - build generic sg for IEEE format
+ * @ioc: per adapter object
+ * @psge: virtual address for SGE
+ * @data_out_dma: physical address for WRITES
+ * @data_out_sz: data xfer size for WRITES
+ * @data_in_dma: physical address for READS
+ * @data_in_sz: data xfer size for READS
+ *
+ * Return nothing.
+ */
+static void
+_base_build_sg_ieee(struct MPT3SAS_ADAPTER *ioc, void *psge,
+       dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma,
+       size_t data_in_sz)
+{
+       u8 sgl_flags;
+
+       if (!data_out_sz && !data_in_sz) {
+               _base_build_zero_len_sge_ieee(ioc, psge);
+               return;
+       }
+
+       if (data_out_sz && data_in_sz) {
+               /* WRITE sgel first */
+               sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
+               _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz,
+                   data_out_dma);
+
+               /* incr sgel */
+               psge += ioc->sge_size_ieee;
+
+               /* READ sgel last */
+               sgl_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
+               _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz,
+                   data_in_dma);
+       } else if (data_out_sz) /* WRITE */ {
+               sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI25_IEEE_SGE_FLAGS_END_OF_LIST |
+                   MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
+               _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz,
+                   data_out_dma);
+       } else if (data_in_sz) /* READ */ {
+               sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
+                   MPI25_IEEE_SGE_FLAGS_END_OF_LIST |
+                   MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
+               _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz,
+                   data_in_dma);
+       }
+}
+
+#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
+
+/**
+ * _base_config_dma_addressing - set dma addressing
+ * @ioc: per adapter object
+ * @pdev: PCI device struct
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
+{
+       struct sysinfo s;
+       char *desc = NULL;
+
+       if (sizeof(dma_addr_t) > 4) {
+               const uint64_t required_mask =
+                   dma_get_required_mask(&pdev->dev);
+               if ((required_mask > DMA_BIT_MASK(32)) &&
+                   !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
+                   !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+                       ioc->base_add_sg_single = &_base_add_sg_single_64;
+                       ioc->sge_size = sizeof(Mpi2SGESimple64_t);
+                       desc = "64";
+                       goto out;
+               }
+       }
+
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+           && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               ioc->base_add_sg_single = &_base_add_sg_single_32;
+               ioc->sge_size = sizeof(Mpi2SGESimple32_t);
+               desc = "32";
+       } else
+               return -ENODEV;
+
+ out:
+       si_meminfo(&s);
+       pr_info(MPT3SAS_FMT
+               "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n",
+               ioc->name, desc, convert_to_kb(s.totalram));
+
+       return 0;
+}
+
+/**
+ * _base_check_enable_msix - checks MSIX capabable.
+ * @ioc: per adapter object
+ *
+ * Check to see if card is capable of MSIX, and set number
+ * of available msix vectors
+ */
+static int
+_base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc)
+{
+       int base;
+       u16 message_control;
+
+       base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
+       if (!base) {
+               dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n",
+                       ioc->name));
+               return -EINVAL;
+       }
+
+       /* get msix vector count */
+
+       pci_read_config_word(ioc->pdev, base + 2, &message_control);
+       ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+       if (ioc->msix_vector_count > 8)
+               ioc->msix_vector_count = 8;
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "msix is supported, vector_count(%d)\n",
+               ioc->name, ioc->msix_vector_count));
+       return 0;
+}
+
+/**
+ * _base_free_irq - free irq
+ * @ioc: per adapter object
+ *
+ * Freeing respective reply_queue from the list.
+ */
+static void
+_base_free_irq(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct adapter_reply_queue *reply_q, *next;
+
+       if (list_empty(&ioc->reply_queue_list))
+               return;
+
+       list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
+               list_del(&reply_q->list);
+               synchronize_irq(reply_q->vector);
+               free_irq(reply_q->vector, reply_q);
+               kfree(reply_q);
+       }
+}
+
+/**
+ * _base_request_irq - request irq
+ * @ioc: per adapter object
+ * @index: msix index into vector table
+ * @vector: irq vector
+ *
+ * Inserting respective reply_queue into the list.
+ */
+static int
+_base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
+{
+       struct adapter_reply_queue *reply_q;
+       int r;
+
+       reply_q =  kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
+       if (!reply_q) {
+               pr_err(MPT3SAS_FMT "unable to allocate memory %d!\n",
+                   ioc->name, (int)sizeof(struct adapter_reply_queue));
+               return -ENOMEM;
+       }
+       reply_q->ioc = ioc;
+       reply_q->msix_index = index;
+       reply_q->vector = vector;
+       atomic_set(&reply_q->busy, 0);
+       if (ioc->msix_enable)
+               snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
+                   MPT3SAS_DRIVER_NAME, ioc->id, index);
+       else
+               snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
+                   MPT3SAS_DRIVER_NAME, ioc->id);
+       r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
+           reply_q);
+       if (r) {
+               pr_err(MPT3SAS_FMT "unable to allocate interrupt %d!\n",
+                   reply_q->name, vector);
+               kfree(reply_q);
+               return -EBUSY;
+       }
+
+       INIT_LIST_HEAD(&reply_q->list);
+       list_add_tail(&reply_q->list, &ioc->reply_queue_list);
+       return 0;
+}
+
+/**
+ * _base_assign_reply_queues - assigning msix index for each cpu
+ * @ioc: per adapter object
+ *
+ * The enduser would need to set the affinity via /proc/irq/#/smp_affinity
+ *
+ * It would nice if we could call irq_set_affinity, however it is not
+ * an exported symbol
+ */
+static void
+_base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct adapter_reply_queue *reply_q;
+       int cpu_id;
+       int cpu_grouping, loop, grouping, grouping_mod;
+       int reply_queue;
+
+       if (!_base_is_controller_msix_enabled(ioc))
+               return;
+
+       memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
+
+       /* NUMA Hardware bug workaround - drop to less reply queues */
+       if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) {
+               ioc->reply_queue_count = ioc->facts.MaxMSIxVectors;
+               reply_queue = 0;
+               list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+                       reply_q->msix_index = reply_queue;
+                       if (++reply_queue == ioc->reply_queue_count)
+                               reply_queue = 0;
+               }
+       }
+
+       /* when there are more cpus than available msix vectors,
+        * then group cpus togeather on same irq
+        */
+       if (ioc->cpu_count > ioc->msix_vector_count) {
+               grouping = ioc->cpu_count / ioc->msix_vector_count;
+               grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
+               if (grouping < 2 || (grouping == 2 && !grouping_mod))
+                       cpu_grouping = 2;
+               else if (grouping < 4 || (grouping == 4 && !grouping_mod))
+                       cpu_grouping = 4;
+               else if (grouping < 8 || (grouping == 8 && !grouping_mod))
+                       cpu_grouping = 8;
+               else
+                       cpu_grouping = 16;
+       } else
+               cpu_grouping = 0;
+
+       loop = 0;
+       reply_q = list_entry(ioc->reply_queue_list.next,
+            struct adapter_reply_queue, list);
+       for_each_online_cpu(cpu_id) {
+               if (!cpu_grouping) {
+                       ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
+                       reply_q = list_entry(reply_q->list.next,
+                           struct adapter_reply_queue, list);
+               } else {
+                       if (loop < cpu_grouping) {
+                               ioc->cpu_msix_table[cpu_id] =
+                                   reply_q->msix_index;
+                               loop++;
+                       } else {
+                               reply_q = list_entry(reply_q->list.next,
+                                   struct adapter_reply_queue, list);
+                               ioc->cpu_msix_table[cpu_id] =
+                                   reply_q->msix_index;
+                               loop = 1;
+                       }
+               }
+       }
+}
+
+/**
+ * _base_disable_msix - disables msix
+ * @ioc: per adapter object
+ *
+ */
+static void
+_base_disable_msix(struct MPT3SAS_ADAPTER *ioc)
+{
+       if (!ioc->msix_enable)
+               return;
+       pci_disable_msix(ioc->pdev);
+       ioc->msix_enable = 0;
+}
+
+/**
+ * _base_enable_msix - enables msix, failback to io_apic
+ * @ioc: per adapter object
+ *
+ */
+static int
+_base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct msix_entry *entries, *a;
+       int r;
+       int i;
+       u8 try_msix = 0;
+
+       INIT_LIST_HEAD(&ioc->reply_queue_list);
+
+       if (msix_disable == -1 || msix_disable == 0)
+               try_msix = 1;
+
+       if (!try_msix)
+               goto try_ioapic;
+
+       if (_base_check_enable_msix(ioc) != 0)
+               goto try_ioapic;
+
+       ioc->reply_queue_count = min_t(int, ioc->cpu_count,
+           ioc->msix_vector_count);
+
+       entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
+           GFP_KERNEL);
+       if (!entries) {
+               dfailprintk(ioc, pr_info(MPT3SAS_FMT
+                       "kcalloc failed @ at %s:%d/%s() !!!\n",
+                       ioc->name, __FILE__, __LINE__, __func__));
+               goto try_ioapic;
+       }
+
+       for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++)
+               a->entry = i;
+
+       r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count);
+       if (r) {
+               dfailprintk(ioc, pr_info(MPT3SAS_FMT
+                       "pci_enable_msix failed (r=%d) !!!\n",
+                       ioc->name, r));
+               kfree(entries);
+               goto try_ioapic;
+       }
+
+       ioc->msix_enable = 1;
+       for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) {
+               r = _base_request_irq(ioc, i, a->vector);
+               if (r) {
+                       _base_free_irq(ioc);
+                       _base_disable_msix(ioc);
+                       kfree(entries);
+                       goto try_ioapic;
+               }
+       }
+
+       kfree(entries);
+       return 0;
+
+/* failback to io_apic interrupt routing */
+ try_ioapic:
+
+       r = _base_request_irq(ioc, 0, ioc->pdev->irq);
+
+       return r;
+}
+
+/**
+ * mpt3sas_base_map_resources - map in controller resources (io/irq/memap)
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct pci_dev *pdev = ioc->pdev;
+       u32 memap_sz;
+       u32 pio_sz;
+       int i, r = 0;
+       u64 pio_chip = 0;
+       u64 chip_phys = 0;
+       struct adapter_reply_queue *reply_q;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n",
+           ioc->name, __func__));
+
+       ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       if (pci_enable_device_mem(pdev)) {
+               pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n",
+                       ioc->name);
+               return -ENODEV;
+       }
+
+
+       if (pci_request_selected_regions(pdev, ioc->bars,
+           MPT3SAS_DRIVER_NAME)) {
+               pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n",
+                       ioc->name);
+               r = -ENODEV;
+               goto out_fail;
+       }
+
+/* AER (Advanced Error Reporting) hooks */
+       pci_enable_pcie_error_reporting(pdev);
+
+       pci_set_master(pdev);
+
+
+       if (_base_config_dma_addressing(ioc, pdev) != 0) {
+               pr_warn(MPT3SAS_FMT "no suitable DMA mask for %s\n",
+                   ioc->name, pci_name(pdev));
+               r = -ENODEV;
+               goto out_fail;
+       }
+
+       for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
+               if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+                       if (pio_sz)
+                               continue;
+                       pio_chip = (u64)pci_resource_start(pdev, i);
+                       pio_sz = pci_resource_len(pdev, i);
+               } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
+                       if (memap_sz)
+                               continue;
+                       ioc->chip_phys = pci_resource_start(pdev, i);
+                       chip_phys = (u64)ioc->chip_phys;
+                       memap_sz = pci_resource_len(pdev, i);
+                       ioc->chip = ioremap(ioc->chip_phys, memap_sz);
+                       if (ioc->chip == NULL) {
+                               pr_err(MPT3SAS_FMT "unable to map adapter memory!\n",
+                                       ioc->name);
+                               r = -EINVAL;
+                               goto out_fail;
+                       }
+               }
+       }
+
+       _base_mask_interrupts(ioc);
+       r = _base_enable_msix(ioc);
+       if (r)
+               goto out_fail;
+
+       list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
+               pr_info(MPT3SAS_FMT "%s: IRQ %d\n",
+                   reply_q->name,  ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
+                   "IO-APIC enabled"), reply_q->vector);
+
+       pr_info(MPT3SAS_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
+           ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
+       pr_info(MPT3SAS_FMT "ioport(0x%016llx), size(%d)\n",
+           ioc->name, (unsigned long long)pio_chip, pio_sz);
+
+       /* Save PCI configuration state for recovery from PCI AER/EEH errors */
+       pci_save_state(pdev);
+       return 0;
+
+ out_fail:
+       if (ioc->chip_phys)
+               iounmap(ioc->chip);
+       ioc->chip_phys = 0;
+       pci_release_selected_regions(ioc->pdev, ioc->bars);
+       pci_disable_pcie_error_reporting(pdev);
+       pci_disable_device(pdev);
+       return r;
+}
+
+/**
+ * mpt3sas_base_get_msg_frame - obtain request mf pointer
+ * @ioc: per adapter object
+ * @smid: system request message index(smid zero is invalid)
+ *
+ * Returns virt pointer to message frame.
+ */
+void *
+mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       return (void *)(ioc->request + (smid * ioc->request_sz));
+}
+
+/**
+ * mpt3sas_base_get_sense_buffer - obtain a sense buffer virt addr
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns virt pointer to sense buffer.
+ */
+void *
+mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
+}
+
+/**
+ * mpt3sas_base_get_sense_buffer_dma - obtain a sense buffer dma addr
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns phys pointer to the low 32bit address of the sense buffer.
+ */
+__le32
+mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       return cpu_to_le32(ioc->sense_dma + ((smid - 1) *
+           SCSI_SENSE_BUFFERSIZE));
+}
+
+/**
+ * mpt3sas_base_get_reply_virt_addr - obtain reply frames virt address
+ * @ioc: per adapter object
+ * @phys_addr: lower 32 physical addr of the reply
+ *
+ * Converts 32bit lower physical addr into a virt address.
+ */
+void *
+mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr)
+{
+       if (!phys_addr)
+               return NULL;
+       return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
+}
+
+/**
+ * mpt3sas_base_get_smid - obtain a free smid from internal queue
+ * @ioc: per adapter object
+ * @cb_idx: callback index
+ *
+ * Returns smid (zero is invalid)
+ */
+u16
+mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx)
+{
+       unsigned long flags;
+       struct request_tracker *request;
+       u16 smid;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (list_empty(&ioc->internal_free_list)) {
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               pr_err(MPT3SAS_FMT "%s: smid not available\n",
+                   ioc->name, __func__);
+               return 0;
+       }
+
+       request = list_entry(ioc->internal_free_list.next,
+           struct request_tracker, tracker_list);
+       request->cb_idx = cb_idx;
+       smid = request->smid;
+       list_del(&request->tracker_list);
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return smid;
+}
+
+/**
+ * mpt3sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
+ * @ioc: per adapter object
+ * @cb_idx: callback index
+ * @scmd: pointer to scsi command object
+ *
+ * Returns smid (zero is invalid)
+ */
+u16
+mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
+       struct scsi_cmnd *scmd)
+{
+       unsigned long flags;
+       struct scsiio_tracker *request;
+       u16 smid;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (list_empty(&ioc->free_list)) {
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               pr_err(MPT3SAS_FMT "%s: smid not available\n",
+                   ioc->name, __func__);
+               return 0;
+       }
+
+       request = list_entry(ioc->free_list.next,
+           struct scsiio_tracker, tracker_list);
+       request->scmd = scmd;
+       request->cb_idx = cb_idx;
+       smid = request->smid;
+       list_del(&request->tracker_list);
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return smid;
+}
+
+/**
+ * mpt3sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
+ * @ioc: per adapter object
+ * @cb_idx: callback index
+ *
+ * Returns smid (zero is invalid)
+ */
+u16
+mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx)
+{
+       unsigned long flags;
+       struct request_tracker *request;
+       u16 smid;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (list_empty(&ioc->hpr_free_list)) {
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               return 0;
+       }
+
+       request = list_entry(ioc->hpr_free_list.next,
+           struct request_tracker, tracker_list);
+       request->cb_idx = cb_idx;
+       smid = request->smid;
+       list_del(&request->tracker_list);
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return smid;
+}
+
+/**
+ * mpt3sas_base_free_smid - put smid back on free_list
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       unsigned long flags;
+       int i;
+       struct chain_tracker *chain_req, *next;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (smid < ioc->hi_priority_smid) {
+               /* scsiio queue */
+               i = smid - 1;
+               if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
+                       list_for_each_entry_safe(chain_req, next,
+                           &ioc->scsi_lookup[i].chain_list, tracker_list) {
+                               list_del_init(&chain_req->tracker_list);
+                               list_add(&chain_req->tracker_list,
+                                   &ioc->free_chain_list);
+                       }
+               }
+               ioc->scsi_lookup[i].cb_idx = 0xFF;
+               ioc->scsi_lookup[i].scmd = NULL;
+               list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list);
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+               /*
+                * See _wait_for_commands_to_complete() call with regards
+                * to this code.
+                */
+               if (ioc->shost_recovery && ioc->pending_io_count) {
+                       if (ioc->pending_io_count == 1)
+                               wake_up(&ioc->reset_wq);
+                       ioc->pending_io_count--;
+               }
+               return;
+       } else if (smid < ioc->internal_smid) {
+               /* hi-priority */
+               i = smid - ioc->hi_priority_smid;
+               ioc->hpr_lookup[i].cb_idx = 0xFF;
+               list_add(&ioc->hpr_lookup[i].tracker_list, &ioc->hpr_free_list);
+       } else if (smid <= ioc->hba_queue_depth) {
+               /* internal queue */
+               i = smid - ioc->internal_smid;
+               ioc->internal_lookup[i].cb_idx = 0xFF;
+               list_add(&ioc->internal_lookup[i].tracker_list,
+                   &ioc->internal_free_list);
+       }
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+}
+
+/**
+ * _base_writeq - 64 bit write to MMIO
+ * @ioc: per adapter object
+ * @b: data payload
+ * @addr: address in MMIO space
+ * @writeq_lock: spin lock
+ *
+ * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
+ * care of 32 bit environment where its not quarenteed to send the entire word
+ * in one transfer.
+ */
+#if defined(writeq) && defined(CONFIG_64BIT)
+static inline void
+_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
+{
+       writeq(cpu_to_le64(b), addr);
+}
+#else
+static inline void
+_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
+{
+       unsigned long flags;
+       __u64 data_out = cpu_to_le64(b);
+
+       spin_lock_irqsave(writeq_lock, flags);
+       writel((u32)(data_out), addr);
+       writel((u32)(data_out >> 32), (addr + 4));
+       spin_unlock_irqrestore(writeq_lock, flags);
+}
+#endif
+
+static inline u8
+_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
+{
+       return ioc->cpu_msix_table[raw_smp_processor_id()];
+}
+
+/**
+ * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle)
+{
+       Mpi2RequestDescriptorUnion_t descriptor;
+       u64 *request = (u64 *)&descriptor;
+
+
+       descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
+       descriptor.SCSIIO.MSIxIndex =  _base_get_msix_index(ioc);
+       descriptor.SCSIIO.SMID = cpu_to_le16(smid);
+       descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
+       descriptor.SCSIIO.LMID = 0;
+       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+           &ioc->scsi_lookup_lock);
+}
+
+/**
+ * mpt3sas_base_put_smid_fast_path - send fast path request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       u16 handle)
+{
+       Mpi2RequestDescriptorUnion_t descriptor;
+       u64 *request = (u64 *)&descriptor;
+
+       descriptor.SCSIIO.RequestFlags =
+           MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
+       descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
+       descriptor.SCSIIO.SMID = cpu_to_le16(smid);
+       descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
+       descriptor.SCSIIO.LMID = 0;
+       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+           &ioc->scsi_lookup_lock);
+}
+
+/**
+ * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       Mpi2RequestDescriptorUnion_t descriptor;
+       u64 *request = (u64 *)&descriptor;
+
+       descriptor.HighPriority.RequestFlags =
+           MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+       descriptor.HighPriority.MSIxIndex =  0;
+       descriptor.HighPriority.SMID = cpu_to_le16(smid);
+       descriptor.HighPriority.LMID = 0;
+       descriptor.HighPriority.Reserved1 = 0;
+       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+           &ioc->scsi_lookup_lock);
+}
+
+/**
+ * mpt3sas_base_put_smid_default - Default, primarily used for config pages
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       Mpi2RequestDescriptorUnion_t descriptor;
+       u64 *request = (u64 *)&descriptor;
+
+       descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+       descriptor.Default.MSIxIndex =  _base_get_msix_index(ioc);
+       descriptor.Default.SMID = cpu_to_le16(smid);
+       descriptor.Default.LMID = 0;
+       descriptor.Default.DescriptorTypeDependent = 0;
+       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+           &ioc->scsi_lookup_lock);
+}
+
+
+
+/**
+ * _base_display_ioc_capabilities - Disply IOC's capabilities.
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
+{
+       int i = 0;
+       char desc[16];
+       u32 iounit_pg1_flags;
+       u32 bios_version;
+
+       bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
+       strncpy(desc, ioc->manu_pg0.ChipName, 16);
+       pr_info(MPT3SAS_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "\
+          "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
+           ioc->name, desc,
+          (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
+          (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
+          (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
+          ioc->facts.FWVersion.Word & 0x000000FF,
+          ioc->pdev->revision,
+          (bios_version & 0xFF000000) >> 24,
+          (bios_version & 0x00FF0000) >> 16,
+          (bios_version & 0x0000FF00) >> 8,
+           bios_version & 0x000000FF);
+
+       pr_info(MPT3SAS_FMT "Protocol=(", ioc->name);
+
+       if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
+               pr_info("Initiator");
+               i++;
+       }
+
+       if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
+               pr_info("%sTarget", i ? "," : "");
+               i++;
+       }
+
+       i = 0;
+       pr_info("), ");
+       pr_info("Capabilities=(");
+
+       if (ioc->facts.IOCCapabilities &
+                   MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
+                       pr_info("Raid");
+                       i++;
+       }
+
+       if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
+               pr_info("%sTLR", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
+               pr_info("%sMulticast", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
+               pr_info("%sBIDI Target", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
+               pr_info("%sEEDP", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
+               pr_info("%sSnapshot Buffer", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
+               pr_info("%sDiag Trace Buffer", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
+               pr_info("%sDiag Extended Buffer", i ? "," : "");
+               i++;
+       }
+
+       if (ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
+               pr_info("%sTask Set Full", i ? "," : "");
+               i++;
+       }
+
+       iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
+       if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
+               pr_info("%sNCQ", i ? "," : "");
+               i++;
+       }
+
+       pr_info(")\n");
+}
+
+/**
+ * mpt3sas_base_update_missing_delay - change the missing delay timers
+ * @ioc: per adapter object
+ * @device_missing_delay: amount of time till device is reported missing
+ * @io_missing_delay: interval IO is returned when there is a missing device
+ *
+ * Return nothing.
+ *
+ * Passed on the command line, this function will modify the device missing
+ * delay, as well as the io missing delay. This should be called at driver
+ * load time.
+ */
+void
+mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
+       u16 device_missing_delay, u8 io_missing_delay)
+{
+       u16 dmd, dmd_new, dmd_orignal;
+       u8 io_missing_delay_original;
+       u16 sz;
+       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+       Mpi2ConfigReply_t mpi_reply;
+       u8 num_phys = 0;
+       u16 ioc_status;
+
+       mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
+       if (!num_phys)
+               return;
+
+       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
+           sizeof(Mpi2SasIOUnit1PhyData_t));
+       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg1) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+           sas_iounit_pg1, sz))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+
+       /* device missing delay */
+       dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
+       if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+               dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+       else
+               dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+       dmd_orignal = dmd;
+       if (device_missing_delay > 0x7F) {
+               dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
+                   device_missing_delay;
+               dmd = dmd / 16;
+               dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
+       } else
+               dmd = device_missing_delay;
+       sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
+
+       /* io missing delay */
+       io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
+       sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
+
+       if (!mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
+           sz)) {
+               if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+                       dmd_new = (dmd &
+                           MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+               else
+                       dmd_new =
+                   dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+               pr_info(MPT3SAS_FMT "device_missing_delay: old(%d), new(%d)\n",
+                       ioc->name, dmd_orignal, dmd_new);
+               pr_info(MPT3SAS_FMT "ioc_missing_delay: old(%d), new(%d)\n",
+                       ioc->name, io_missing_delay_original,
+                   io_missing_delay);
+               ioc->device_missing_delay = dmd_new;
+               ioc->io_missing_delay = io_missing_delay;
+       }
+
+out:
+       kfree(sas_iounit_pg1);
+}
+/**
+ * _base_static_config_pages - static start of day config pages
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2ConfigReply_t mpi_reply;
+       u32 iounit_pg1_flags;
+
+       mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
+       if (ioc->ir_firmware)
+               mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
+                   &ioc->manu_pg10);
+
+       /*
+        * Ensure correct T10 PI operation if vendor left EEDPTagMode
+        * flag unset in NVDATA.
+        */
+       mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11);
+       if (ioc->manu_pg11.EEDPTagMode == 0) {
+               pr_err("%s: overriding NVDATA EEDPTagMode setting\n",
+                   ioc->name);
+               ioc->manu_pg11.EEDPTagMode &= ~0x3;
+               ioc->manu_pg11.EEDPTagMode |= 0x1;
+               mpt3sas_config_set_manufacturing_pg11(ioc, &mpi_reply,
+                   &ioc->manu_pg11);
+       }
+
+       mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
+       mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
+       mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
+       mpt3sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
+       mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
+       _base_display_ioc_capabilities(ioc);
+
+       /*
+        * Enable task_set_full handling in iounit_pg1 when the
+        * facts capabilities indicate that its supported.
+        */
+       iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
+       if ((ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
+               iounit_pg1_flags &=
+                   ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
+       else
+               iounit_pg1_flags |=
+                   MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
+       ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
+       mpt3sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
+}
+
+/**
+ * _base_release_memory_pools - release memory
+ * @ioc: per adapter object
+ *
+ * Free memory allocated from _base_allocate_memory_pools.
+ *
+ * Return nothing.
+ */
+static void
+_base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
+{
+       int i;
+
+       dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       if (ioc->request) {
+               pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
+                   ioc->request,  ioc->request_dma);
+               dexitprintk(ioc, pr_info(MPT3SAS_FMT
+                       "request_pool(0x%p): free\n",
+                       ioc->name, ioc->request));
+               ioc->request = NULL;
+       }
+
+       if (ioc->sense) {
+               pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
+               if (ioc->sense_dma_pool)
+                       pci_pool_destroy(ioc->sense_dma_pool);
+               dexitprintk(ioc, pr_info(MPT3SAS_FMT
+                       "sense_pool(0x%p): free\n",
+                       ioc->name, ioc->sense));
+               ioc->sense = NULL;
+       }
+
+       if (ioc->reply) {
+               pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
+               if (ioc->reply_dma_pool)
+                       pci_pool_destroy(ioc->reply_dma_pool);
+               dexitprintk(ioc, pr_info(MPT3SAS_FMT
+                       "reply_pool(0x%p): free\n",
+                       ioc->name, ioc->reply));
+               ioc->reply = NULL;
+       }
+
+       if (ioc->reply_free) {
+               pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
+                   ioc->reply_free_dma);
+               if (ioc->reply_free_dma_pool)
+                       pci_pool_destroy(ioc->reply_free_dma_pool);
+               dexitprintk(ioc, pr_info(MPT3SAS_FMT
+                       "reply_free_pool(0x%p): free\n",
+                       ioc->name, ioc->reply_free));
+               ioc->reply_free = NULL;
+       }
+
+       if (ioc->reply_post_free) {
+               pci_pool_free(ioc->reply_post_free_dma_pool,
+                   ioc->reply_post_free, ioc->reply_post_free_dma);
+               if (ioc->reply_post_free_dma_pool)
+                       pci_pool_destroy(ioc->reply_post_free_dma_pool);
+               dexitprintk(ioc, pr_info(MPT3SAS_FMT
+                   "reply_post_free_pool(0x%p): free\n", ioc->name,
+                   ioc->reply_post_free));
+               ioc->reply_post_free = NULL;
+       }
+
+       if (ioc->config_page) {
+               dexitprintk(ioc, pr_info(MPT3SAS_FMT
+                   "config_page(0x%p): free\n", ioc->name,
+                   ioc->config_page));
+               pci_free_consistent(ioc->pdev, ioc->config_page_sz,
+                   ioc->config_page, ioc->config_page_dma);
+       }
+
+       if (ioc->scsi_lookup) {
+               free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages);
+               ioc->scsi_lookup = NULL;
+       }
+       kfree(ioc->hpr_lookup);
+       kfree(ioc->internal_lookup);
+       if (ioc->chain_lookup) {
+               for (i = 0; i < ioc->chain_depth; i++) {
+                       if (ioc->chain_lookup[i].chain_buffer)
+                               pci_pool_free(ioc->chain_dma_pool,
+                                   ioc->chain_lookup[i].chain_buffer,
+                                   ioc->chain_lookup[i].chain_buffer_dma);
+               }
+               if (ioc->chain_dma_pool)
+                       pci_pool_destroy(ioc->chain_dma_pool);
+               free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
+               ioc->chain_lookup = NULL;
+       }
+}
+
+/**
+ * _base_allocate_memory_pools - allocate start of day memory pools
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 success, anything else error
+ */
+static int
+_base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc,  int sleep_flag)
+{
+       struct mpt3sas_facts *facts;
+       u16 max_sge_elements;
+       u16 chains_needed_per_io;
+       u32 sz, total_sz, reply_post_free_sz;
+       u32 retry_sz;
+       u16 max_request_credit;
+       unsigned short sg_tablesize;
+       u16 sge_size;
+       int i;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+
+       retry_sz = 0;
+       facts = &ioc->facts;
+
+       /* command line tunables for max sgl entries */
+       if (max_sgl_entries != -1)
+               sg_tablesize = max_sgl_entries;
+       else
+               sg_tablesize = MPT3SAS_SG_DEPTH;
+
+       if (sg_tablesize < MPT3SAS_MIN_PHYS_SEGMENTS)
+               sg_tablesize = MPT3SAS_MIN_PHYS_SEGMENTS;
+       else if (sg_tablesize > MPT3SAS_MAX_PHYS_SEGMENTS)
+               sg_tablesize = MPT3SAS_MAX_PHYS_SEGMENTS;
+       ioc->shost->sg_tablesize = sg_tablesize;
+
+       ioc->hi_priority_depth = facts->HighPriorityCredit;
+       ioc->internal_depth = ioc->hi_priority_depth + (5);
+       /* command line tunables  for max controller queue depth */
+       if (max_queue_depth != -1 && max_queue_depth != 0) {
+               max_request_credit = min_t(u16, max_queue_depth +
+                   ioc->hi_priority_depth + ioc->internal_depth,
+                   facts->RequestCredit);
+               if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
+                       max_request_credit =  MAX_HBA_QUEUE_DEPTH;
+       } else
+               max_request_credit = min_t(u16, facts->RequestCredit,
+                   MAX_HBA_QUEUE_DEPTH);
+
+       ioc->hba_queue_depth = max_request_credit;
+
+       /* request frame size */
+       ioc->request_sz = facts->IOCRequestFrameSize * 4;
+
+       /* reply frame size */
+       ioc->reply_sz = facts->ReplyFrameSize * 4;
+
+       /* calculate the max scatter element size */
+       sge_size = max_t(u16, ioc->sge_size, ioc->sge_size_ieee);
+
+ retry_allocation:
+       total_sz = 0;
+       /* calculate number of sg elements left over in the 1st frame */
+       max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
+           sizeof(Mpi2SGEIOUnion_t)) + sge_size);
+       ioc->max_sges_in_main_message = max_sge_elements/sge_size;
+
+       /* now do the same for a chain buffer */
+       max_sge_elements = ioc->request_sz - sge_size;
+       ioc->max_sges_in_chain_message = max_sge_elements/sge_size;
+
+       /*
+        *  MPT3SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
+        */
+       chains_needed_per_io = ((ioc->shost->sg_tablesize -
+          ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
+           + 1;
+       if (chains_needed_per_io > facts->MaxChainDepth) {
+               chains_needed_per_io = facts->MaxChainDepth;
+               ioc->shost->sg_tablesize = min_t(u16,
+               ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
+               * chains_needed_per_io), ioc->shost->sg_tablesize);
+       }
+       ioc->chains_needed_per_io = chains_needed_per_io;
+
+       /* reply free queue sizing - taking into account for 64 FW events */
+       ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
+
+       /* calculate reply descriptor post queue depth */
+       ioc->reply_post_queue_depth = ioc->hba_queue_depth +
+                               ioc->reply_free_queue_depth +  1 ;
+       /* align the reply post queue on the next 16 count boundary */
+       if (ioc->reply_post_queue_depth % 16)
+               ioc->reply_post_queue_depth += 16 -
+               (ioc->reply_post_queue_depth % 16);
+
+
+       if (ioc->reply_post_queue_depth >
+           facts->MaxReplyDescriptorPostQueueDepth) {
+               ioc->reply_post_queue_depth =
+                               facts->MaxReplyDescriptorPostQueueDepth -
+                   (facts->MaxReplyDescriptorPostQueueDepth % 16);
+               ioc->hba_queue_depth =
+                               ((ioc->reply_post_queue_depth - 64) / 2) - 1;
+               ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
+       }
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "scatter gather: " \
+           "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
+           "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
+           ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
+           ioc->chains_needed_per_io));
+
+       ioc->scsiio_depth = ioc->hba_queue_depth -
+           ioc->hi_priority_depth - ioc->internal_depth;
+
+       /* set the scsi host can_queue depth
+        * with some internal commands that could be outstanding
+        */
+       ioc->shost->can_queue = ioc->scsiio_depth;
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "scsi host: can_queue depth (%d)\n",
+               ioc->name, ioc->shost->can_queue));
+
+
+       /* contiguous pool for request and chains, 16 byte align, one extra "
+        * "frame for smid=0
+        */
+       ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
+       sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
+
+       /* hi-priority queue */
+       sz += (ioc->hi_priority_depth * ioc->request_sz);
+
+       /* internal queue */
+       sz += (ioc->internal_depth * ioc->request_sz);
+
+       ioc->request_dma_sz = sz;
+       ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
+       if (!ioc->request) {
+               pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \
+                   "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
+                   "total(%d kB)\n", ioc->name, ioc->hba_queue_depth,
+                   ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
+               if (ioc->scsiio_depth < MPT3SAS_SAS_QUEUE_DEPTH)
+                       goto out;
+               retry_sz += 64;
+               ioc->hba_queue_depth = max_request_credit - retry_sz;
+               goto retry_allocation;
+       }
+
+       if (retry_sz)
+               pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \
+                   "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
+                   "total(%d kb)\n", ioc->name, ioc->hba_queue_depth,
+                   ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
+
+       /* hi-priority queue */
+       ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) *
+           ioc->request_sz);
+       ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) *
+           ioc->request_sz);
+
+       /* internal queue */
+       ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth *
+           ioc->request_sz);
+       ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
+           ioc->request_sz);
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "request pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n",
+               ioc->name, ioc->request, ioc->hba_queue_depth, ioc->request_sz,
+           (ioc->hba_queue_depth * ioc->request_sz)/1024));
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "request pool: dma(0x%llx)\n",
+           ioc->name, (unsigned long long) ioc->request_dma));
+       total_sz += sz;
+
+       sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
+       ioc->scsi_lookup_pages = get_order(sz);
+       ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
+           GFP_KERNEL, ioc->scsi_lookup_pages);
+       if (!ioc->scsi_lookup) {
+               pr_err(MPT3SAS_FMT "scsi_lookup: get_free_pages failed, sz(%d)\n",
+                       ioc->name, (int)sz);
+               goto out;
+       }
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "scsiio(0x%p): depth(%d)\n",
+               ioc->name, ioc->request, ioc->scsiio_depth));
+
+       ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
+       sz = ioc->chain_depth * sizeof(struct chain_tracker);
+       ioc->chain_pages = get_order(sz);
+       ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
+           GFP_KERNEL, ioc->chain_pages);
+       if (!ioc->chain_lookup) {
+               pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages failed\n",
+                       ioc->name);
+               goto out;
+       }
+       ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
+           ioc->request_sz, 16, 0);
+       if (!ioc->chain_dma_pool) {
+               pr_err(MPT3SAS_FMT "chain_dma_pool: pci_pool_create failed\n",
+                       ioc->name);
+               goto out;
+       }
+       for (i = 0; i < ioc->chain_depth; i++) {
+               ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
+                   ioc->chain_dma_pool , GFP_KERNEL,
+                   &ioc->chain_lookup[i].chain_buffer_dma);
+               if (!ioc->chain_lookup[i].chain_buffer) {
+                       ioc->chain_depth = i;
+                       goto chain_done;
+               }
+               total_sz += ioc->request_sz;
+       }
+ chain_done:
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n",
+               ioc->name, ioc->chain_depth, ioc->request_sz,
+               ((ioc->chain_depth *  ioc->request_sz))/1024));
+
+       /* initialize hi-priority queue smid's */
+       ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
+           sizeof(struct request_tracker), GFP_KERNEL);
+       if (!ioc->hpr_lookup) {
+               pr_err(MPT3SAS_FMT "hpr_lookup: kcalloc failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->hi_priority_smid = ioc->scsiio_depth + 1;
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "hi_priority(0x%p): depth(%d), start smid(%d)\n",
+               ioc->name, ioc->hi_priority,
+           ioc->hi_priority_depth, ioc->hi_priority_smid));
+
+       /* initialize internal queue smid's */
+       ioc->internal_lookup = kcalloc(ioc->internal_depth,
+           sizeof(struct request_tracker), GFP_KERNEL);
+       if (!ioc->internal_lookup) {
+               pr_err(MPT3SAS_FMT "internal_lookup: kcalloc failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth;
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "internal(0x%p): depth(%d), start smid(%d)\n",
+               ioc->name, ioc->internal,
+           ioc->internal_depth, ioc->internal_smid));
+
+       /* sense buffers, 4 byte align */
+       sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
+       ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
+           0);
+       if (!ioc->sense_dma_pool) {
+               pr_err(MPT3SAS_FMT "sense pool: pci_pool_create failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
+           &ioc->sense_dma);
+       if (!ioc->sense) {
+               pr_err(MPT3SAS_FMT "sense pool: pci_pool_alloc failed\n",
+                   ioc->name);
+               goto out;
+       }
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+           "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
+           "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
+           SCSI_SENSE_BUFFERSIZE, sz/1024));
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "sense_dma(0x%llx)\n",
+           ioc->name, (unsigned long long)ioc->sense_dma));
+       total_sz += sz;
+
+       /* reply pool, 4 byte align */
+       sz = ioc->reply_free_queue_depth * ioc->reply_sz;
+       ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
+           0);
+       if (!ioc->reply_dma_pool) {
+               pr_err(MPT3SAS_FMT "reply pool: pci_pool_create failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
+           &ioc->reply_dma);
+       if (!ioc->reply) {
+               pr_err(MPT3SAS_FMT "reply pool: pci_pool_alloc failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
+       ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "reply pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n",
+               ioc->name, ioc->reply,
+           ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_dma(0x%llx)\n",
+           ioc->name, (unsigned long long)ioc->reply_dma));
+       total_sz += sz;
+
+       /* reply free queue, 16 byte align */
+       sz = ioc->reply_free_queue_depth * 4;
+       ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
+           ioc->pdev, sz, 16, 0);
+       if (!ioc->reply_free_dma_pool) {
+               pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_create failed\n",
+                       ioc->name);
+               goto out;
+       }
+       ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
+           &ioc->reply_free_dma);
+       if (!ioc->reply_free) {
+               pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_alloc failed\n",
+                       ioc->name);
+               goto out;
+       }
+       memset(ioc->reply_free, 0, sz);
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_free pool(0x%p): " \
+           "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
+           ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "reply_free_dma (0x%llx)\n",
+               ioc->name, (unsigned long long)ioc->reply_free_dma));
+       total_sz += sz;
+
+       /* reply post queue, 16 byte align */
+       reply_post_free_sz = ioc->reply_post_queue_depth *
+           sizeof(Mpi2DefaultReplyDescriptor_t);
+       if (_base_is_controller_msix_enabled(ioc))
+               sz = reply_post_free_sz * ioc->reply_queue_count;
+       else
+               sz = reply_post_free_sz;
+       ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
+           ioc->pdev, sz, 16, 0);
+       if (!ioc->reply_post_free_dma_pool) {
+               pr_err(MPT3SAS_FMT
+                       "reply_post_free pool: pci_pool_create failed\n",
+                       ioc->name);
+               goto out;
+       }
+       ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
+           GFP_KERNEL, &ioc->reply_post_free_dma);
+       if (!ioc->reply_post_free) {
+               pr_err(MPT3SAS_FMT
+                       "reply_post_free pool: pci_pool_alloc failed\n",
+                       ioc->name);
+               goto out;
+       }
+       memset(ioc->reply_post_free, 0, sz);
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply post free pool" \
+           "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
+           ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
+           sz/1024));
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "reply_post_free_dma = (0x%llx)\n",
+               ioc->name, (unsigned long long)
+           ioc->reply_post_free_dma));
+       total_sz += sz;
+
+       ioc->config_page_sz = 512;
+       ioc->config_page = pci_alloc_consistent(ioc->pdev,
+           ioc->config_page_sz, &ioc->config_page_dma);
+       if (!ioc->config_page) {
+               pr_err(MPT3SAS_FMT
+                       "config page: pci_pool_alloc failed\n",
+                       ioc->name);
+               goto out;
+       }
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "config page(0x%p): size(%d)\n",
+               ioc->name, ioc->config_page, ioc->config_page_sz));
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "config_page_dma(0x%llx)\n",
+               ioc->name, (unsigned long long)ioc->config_page_dma));
+       total_sz += ioc->config_page_sz;
+
+       pr_info(MPT3SAS_FMT "Allocated physical memory: size(%d kB)\n",
+           ioc->name, total_sz/1024);
+       pr_info(MPT3SAS_FMT
+               "Current Controller Queue Depth(%d),Max Controller Queue Depth(%d)\n",
+           ioc->name, ioc->shost->can_queue, facts->RequestCredit);
+       pr_info(MPT3SAS_FMT "Scatter Gather Elements per IO(%d)\n",
+           ioc->name, ioc->shost->sg_tablesize);
+       return 0;
+
+ out:
+       return -ENOMEM;
+}
+
+/**
+ * mpt3sas_base_get_iocstate - Get the current state of a MPT adapter.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @cooked: Request raw or cooked IOC state
+ *
+ * Returns all IOC Doorbell register bits if cooked==0, else just the
+ * Doorbell bits in MPI_IOC_STATE_MASK.
+ */
+u32
+mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked)
+{
+       u32 s, sc;
+
+       s = readl(&ioc->chip->Doorbell);
+       sc = s & MPI2_IOC_STATE_MASK;
+       return cooked ? sc : s;
+}
+
+/**
+ * _base_wait_on_iocstate - waiting on a particular ioc state
+ * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
+       int sleep_flag)
+{
+       u32 count, cntdn;
+       u32 current_state;
+
+       count = 0;
+       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+       do {
+               current_state = mpt3sas_base_get_iocstate(ioc, 1);
+               if (current_state == ioc_state)
+                       return 0;
+               if (count && current_state == MPI2_IOC_STATE_FAULT)
+                       break;
+               if (sleep_flag == CAN_SLEEP)
+                       usleep_range(1000, 1500);
+               else
+                       udelay(500);
+               count++;
+       } while (--cntdn);
+
+       return current_state;
+}
+
+/**
+ * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
+ * a write to the doorbell)
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
+ */
+static int
+_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout,
+       int sleep_flag)
+{
+       u32 cntdn, count;
+       u32 int_status;
+
+       count = 0;
+       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+       do {
+               int_status = readl(&ioc->chip->HostInterruptStatus);
+               if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+                       dhsprintk(ioc, pr_info(MPT3SAS_FMT
+                               "%s: successful count(%d), timeout(%d)\n",
+                               ioc->name, __func__, count, timeout));
+                       return 0;
+               }
+               if (sleep_flag == CAN_SLEEP)
+                       usleep_range(1000, 1500);
+               else
+                       udelay(500);
+               count++;
+       } while (--cntdn);
+
+       pr_err(MPT3SAS_FMT
+               "%s: failed due to timeout count(%d), int_status(%x)!\n",
+               ioc->name, __func__, count, int_status);
+       return -EFAULT;
+}
+
+/**
+ * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
+ * doorbell.
+ */
+static int
+_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout,
+       int sleep_flag)
+{
+       u32 cntdn, count;
+       u32 int_status;
+       u32 doorbell;
+
+       count = 0;
+       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+       do {
+               int_status = readl(&ioc->chip->HostInterruptStatus);
+               if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
+                       dhsprintk(ioc, pr_info(MPT3SAS_FMT
+                               "%s: successful count(%d), timeout(%d)\n",
+                               ioc->name, __func__, count, timeout));
+                       return 0;
+               } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+                       doorbell = readl(&ioc->chip->Doorbell);
+                       if ((doorbell & MPI2_IOC_STATE_MASK) ==
+                           MPI2_IOC_STATE_FAULT) {
+                               mpt3sas_base_fault_info(ioc , doorbell);
+                               return -EFAULT;
+                       }
+               } else if (int_status == 0xFFFFFFFF)
+                       goto out;
+
+               if (sleep_flag == CAN_SLEEP)
+                       usleep_range(1000, 1500);
+               else
+                       udelay(500);
+               count++;
+       } while (--cntdn);
+
+ out:
+       pr_err(MPT3SAS_FMT
+        "%s: failed due to timeout count(%d), int_status(%x)!\n",
+        ioc->name, __func__, count, int_status);
+       return -EFAULT;
+}
+
+/**
+ * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout,
+       int sleep_flag)
+{
+       u32 cntdn, count;
+       u32 doorbell_reg;
+
+       count = 0;
+       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+       do {
+               doorbell_reg = readl(&ioc->chip->Doorbell);
+               if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
+                       dhsprintk(ioc, pr_info(MPT3SAS_FMT
+                               "%s: successful count(%d), timeout(%d)\n",
+                               ioc->name, __func__, count, timeout));
+                       return 0;
+               }
+               if (sleep_flag == CAN_SLEEP)
+                       usleep_range(1000, 1500);
+               else
+                       udelay(500);
+               count++;
+       } while (--cntdn);
+
+       pr_err(MPT3SAS_FMT
+               "%s: failed due to timeout count(%d), doorbell_reg(%x)!\n",
+               ioc->name, __func__, count, doorbell_reg);
+       return -EFAULT;
+}
+
+/**
+ * _base_send_ioc_reset - send doorbell reset
+ * @ioc: per adapter object
+ * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout,
+       int sleep_flag)
+{
+       u32 ioc_state;
+       int r = 0;
+
+       if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
+               pr_err(MPT3SAS_FMT "%s: unknown reset_type\n",
+                   ioc->name, __func__);
+               return -EFAULT;
+       }
+
+       if (!(ioc->facts.IOCCapabilities &
+          MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
+               return -EFAULT;
+
+       pr_info(MPT3SAS_FMT "sending message unit reset !!\n", ioc->name);
+
+       writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
+           &ioc->chip->Doorbell);
+       if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
+               r = -EFAULT;
+               goto out;
+       }
+       ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
+           timeout, sleep_flag);
+       if (ioc_state) {
+               pr_err(MPT3SAS_FMT
+                       "%s: failed going to ready state (ioc_state=0x%x)\n",
+                       ioc->name, __func__, ioc_state);
+               r = -EFAULT;
+               goto out;
+       }
+ out:
+       pr_info(MPT3SAS_FMT "message unit reset: %s\n",
+           ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
+       return r;
+}
+
+/**
+ * _base_handshake_req_reply_wait - send request thru doorbell interface
+ * @ioc: per adapter object
+ * @request_bytes: request length
+ * @request: pointer having request payload
+ * @reply_bytes: reply length
+ * @reply: pointer to reply payload
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
+       u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
+{
+       MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
+       int i;
+       u8 failed;
+       u16 dummy;
+       __le32 *mfp;
+
+       /* make sure doorbell is not in use */
+       if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
+               pr_err(MPT3SAS_FMT
+                       "doorbell is in use (line=%d)\n",
+                       ioc->name, __LINE__);
+               return -EFAULT;
+       }
+
+       /* clear pending doorbell interrupts from previous state changes */
+       if (readl(&ioc->chip->HostInterruptStatus) &
+           MPI2_HIS_IOC2SYS_DB_STATUS)
+               writel(0, &ioc->chip->HostInterruptStatus);
+
+       /* send message to ioc */
+       writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
+           ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
+           &ioc->chip->Doorbell);
+
+       if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
+               pr_err(MPT3SAS_FMT
+                       "doorbell handshake int failed (line=%d)\n",
+                       ioc->name, __LINE__);
+               return -EFAULT;
+       }
+       writel(0, &ioc->chip->HostInterruptStatus);
+
+       if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
+               pr_err(MPT3SAS_FMT
+                       "doorbell handshake ack failed (line=%d)\n",
+                       ioc->name, __LINE__);
+               return -EFAULT;
+       }
+
+       /* send message 32-bits at a time */
+       for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
+               writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
+               if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
+                       failed = 1;
+       }
+
+       if (failed) {
+               pr_err(MPT3SAS_FMT
+                       "doorbell handshake sending request failed (line=%d)\n",
+                       ioc->name, __LINE__);
+               return -EFAULT;
+       }
+
+       /* now wait for the reply */
+       if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
+               pr_err(MPT3SAS_FMT
+                       "doorbell handshake int failed (line=%d)\n",
+                       ioc->name, __LINE__);
+               return -EFAULT;
+       }
+
+       /* read the first two 16-bits, it gives the total length of the reply */
+       reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+           & MPI2_DOORBELL_DATA_MASK);
+       writel(0, &ioc->chip->HostInterruptStatus);
+       if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+               pr_err(MPT3SAS_FMT
+                       "doorbell handshake int failed (line=%d)\n",
+                       ioc->name, __LINE__);
+               return -EFAULT;
+       }
+       reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+           & MPI2_DOORBELL_DATA_MASK);
+       writel(0, &ioc->chip->HostInterruptStatus);
+
+       for (i = 2; i < default_reply->MsgLength * 2; i++)  {
+               if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+                       pr_err(MPT3SAS_FMT
+                               "doorbell handshake int failed (line=%d)\n",
+                               ioc->name, __LINE__);
+                       return -EFAULT;
+               }
+               if (i >=  reply_bytes/2) /* overflow case */
+                       dummy = readl(&ioc->chip->Doorbell);
+               else
+                       reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+                           & MPI2_DOORBELL_DATA_MASK);
+               writel(0, &ioc->chip->HostInterruptStatus);
+       }
+
+       _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
+       if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
+               dhsprintk(ioc, pr_info(MPT3SAS_FMT
+                       "doorbell is in use (line=%d)\n", ioc->name, __LINE__));
+       }
+       writel(0, &ioc->chip->HostInterruptStatus);
+
+       if (ioc->logging_level & MPT_DEBUG_INIT) {
+               mfp = (__le32 *)reply;
+               pr_info("\toffset:data\n");
+               for (i = 0; i < reply_bytes/4; i++)
+                       pr_info("\t[0x%02x]:%08x\n", i*4,
+                           le32_to_cpu(mfp[i]));
+       }
+       return 0;
+}
+
+/**
+ * mpt3sas_base_sas_iounit_control - send sas iounit control to FW
+ * @ioc: per adapter object
+ * @mpi_reply: the reply payload from FW
+ * @mpi_request: the request payload sent to FW
+ *
+ * The SAS IO Unit Control Request message allows the host to perform low-level
+ * operations, such as resets on the PHYs of the IO Unit, also allows the host
+ * to obtain the IOC assigned device handles for a device if it has other
+ * identifying information about the device, in addition allows the host to
+ * remove IOC resources associated with the device.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2SasIoUnitControlReply_t *mpi_reply,
+       Mpi2SasIoUnitControlRequest_t *mpi_request)
+{
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       u8 issue_reset;
+       int rc;
+       void *request;
+       u16 wait_state_count;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       mutex_lock(&ioc->base_cmds.mutex);
+
+       if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: base_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       rc = -EFAULT;
+                       goto out;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name, __func__, wait_state_count);
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       rc = 0;
+       ioc->base_cmds.status = MPT3_CMD_PENDING;
+       request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->base_cmds.smid = smid;
+       memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
+       if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
+           mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
+               ioc->ioc_link_reset_in_progress = 1;
+       init_completion(&ioc->base_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+           msecs_to_jiffies(10000));
+       if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
+           mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
+           ioc->ioc_link_reset_in_progress)
+               ioc->ioc_link_reset_in_progress = 0;
+       if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SasIoUnitControlRequest_t)/4);
+               if (!(ioc->base_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+       if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID)
+               memcpy(mpi_reply, ioc->base_cmds.reply,
+                   sizeof(Mpi2SasIoUnitControlReply_t));
+       else
+               memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+       goto out;
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+       rc = -EFAULT;
+ out:
+       mutex_unlock(&ioc->base_cmds.mutex);
+       return rc;
+}
+
+/**
+ * mpt3sas_base_scsi_enclosure_processor - sending request to sep device
+ * @ioc: per adapter object
+ * @mpi_reply: the reply payload from FW
+ * @mpi_request: the request payload sent to FW
+ *
+ * The SCSI Enclosure Processor request message causes the IOC to
+ * communicate with SES devices to control LED status signals.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
+{
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       u8 issue_reset;
+       int rc;
+       void *request;
+       u16 wait_state_count;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       mutex_lock(&ioc->base_cmds.mutex);
+
+       if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: base_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       rc = -EFAULT;
+                       goto out;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name,
+                   __func__, wait_state_count);
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       rc = 0;
+       ioc->base_cmds.status = MPT3_CMD_PENDING;
+       request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->base_cmds.smid = smid;
+       memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
+       init_completion(&ioc->base_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+           msecs_to_jiffies(10000));
+       if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SepRequest_t)/4);
+               if (!(ioc->base_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+       if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID)
+               memcpy(mpi_reply, ioc->base_cmds.reply,
+                   sizeof(Mpi2SepReply_t));
+       else
+               memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+       goto out;
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+       rc = -EFAULT;
+ out:
+       mutex_unlock(&ioc->base_cmds.mutex);
+       return rc;
+}
+
+/**
+ * _base_get_port_facts - obtain port facts reply and save in ioc
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag)
+{
+       Mpi2PortFactsRequest_t mpi_request;
+       Mpi2PortFactsReply_t mpi_reply;
+       struct mpt3sas_port_facts *pfacts;
+       int mpi_reply_sz, mpi_request_sz, r;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
+       mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
+       memset(&mpi_request, 0, mpi_request_sz);
+       mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
+       mpi_request.PortNumber = port;
+       r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
+           (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
+
+       if (r != 0) {
+               pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
+                   ioc->name, __func__, r);
+               return r;
+       }
+
+       pfacts = &ioc->pfacts[port];
+       memset(pfacts, 0, sizeof(struct mpt3sas_port_facts));
+       pfacts->PortNumber = mpi_reply.PortNumber;
+       pfacts->VP_ID = mpi_reply.VP_ID;
+       pfacts->VF_ID = mpi_reply.VF_ID;
+       pfacts->MaxPostedCmdBuffers =
+           le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
+
+       return 0;
+}
+
+/**
+ * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       Mpi2IOCFactsRequest_t mpi_request;
+       Mpi2IOCFactsReply_t mpi_reply;
+       struct mpt3sas_facts *facts;
+       int mpi_reply_sz, mpi_request_sz, r;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
+       mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
+       memset(&mpi_request, 0, mpi_request_sz);
+       mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
+       r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
+           (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
+
+       if (r != 0) {
+               pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
+                   ioc->name, __func__, r);
+               return r;
+       }
+
+       facts = &ioc->facts;
+       memset(facts, 0, sizeof(struct mpt3sas_facts));
+       facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
+       facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
+       facts->VP_ID = mpi_reply.VP_ID;
+       facts->VF_ID = mpi_reply.VF_ID;
+       facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
+       facts->MaxChainDepth = mpi_reply.MaxChainDepth;
+       facts->WhoInit = mpi_reply.WhoInit;
+       facts->NumberOfPorts = mpi_reply.NumberOfPorts;
+       facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
+       facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
+       facts->MaxReplyDescriptorPostQueueDepth =
+           le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
+       facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
+       facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
+       if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
+               ioc->ir_firmware = 1;
+       facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
+       facts->IOCRequestFrameSize =
+           le16_to_cpu(mpi_reply.IOCRequestFrameSize);
+       facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
+       facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
+       ioc->shost->max_id = -1;
+       facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
+       facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
+       facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
+       facts->HighPriorityCredit =
+           le16_to_cpu(mpi_reply.HighPriorityCredit);
+       facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
+       facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "hba queue depth(%d), max chains per io(%d)\n",
+               ioc->name, facts->RequestCredit,
+           facts->MaxChainDepth));
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+               "request frame size(%d), reply frame size(%d)\n", ioc->name,
+           facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
+       return 0;
+}
+
+/**
+ * _base_send_ioc_init - send ioc_init to firmware
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       Mpi2IOCInitRequest_t mpi_request;
+       Mpi2IOCInitReply_t mpi_reply;
+       int r;
+       struct timeval current_time;
+       u16 ioc_status;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
+       mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
+       mpi_request.VF_ID = 0; /* TODO */
+       mpi_request.VP_ID = 0;
+       mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
+       mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
+
+       if (_base_is_controller_msix_enabled(ioc))
+               mpi_request.HostMSIxVectors = ioc->reply_queue_count;
+       mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
+       mpi_request.ReplyDescriptorPostQueueDepth =
+           cpu_to_le16(ioc->reply_post_queue_depth);
+       mpi_request.ReplyFreeQueueDepth =
+           cpu_to_le16(ioc->reply_free_queue_depth);
+
+       mpi_request.SenseBufferAddressHigh =
+           cpu_to_le32((u64)ioc->sense_dma >> 32);
+       mpi_request.SystemReplyAddressHigh =
+           cpu_to_le32((u64)ioc->reply_dma >> 32);
+       mpi_request.SystemRequestFrameBaseAddress =
+           cpu_to_le64((u64)ioc->request_dma);
+       mpi_request.ReplyFreeQueueAddress =
+           cpu_to_le64((u64)ioc->reply_free_dma);
+       mpi_request.ReplyDescriptorPostQueueAddress =
+           cpu_to_le64((u64)ioc->reply_post_free_dma);
+
+
+       /* This time stamp specifies number of milliseconds
+        * since epoch ~ midnight January 1, 1970.
+        */
+       do_gettimeofday(&current_time);
+       mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 +
+           (current_time.tv_usec / 1000));
+
+       if (ioc->logging_level & MPT_DEBUG_INIT) {
+               __le32 *mfp;
+               int i;
+
+               mfp = (__le32 *)&mpi_request;
+               pr_info("\toffset:data\n");
+               for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
+                       pr_info("\t[0x%02x]:%08x\n", i*4,
+                           le32_to_cpu(mfp[i]));
+       }
+
+       r = _base_handshake_req_reply_wait(ioc,
+           sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
+           sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
+           sleep_flag);
+
+       if (r != 0) {
+               pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
+                   ioc->name, __func__, r);
+               return r;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
+           mpi_reply.IOCLogInfo) {
+               pr_err(MPT3SAS_FMT "%s: failed\n", ioc->name, __func__);
+               r = -EIO;
+       }
+
+       return 0;
+}
+
+/**
+ * mpt3sas_port_enable_done - command completion routine for port enable
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+       u16 ioc_status;
+
+       if (ioc->port_enable_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (!mpi_reply)
+               return 1;
+
+       if (mpi_reply->Function != MPI2_FUNCTION_PORT_ENABLE)
+               return 1;
+
+       ioc->port_enable_cmds.status &= ~MPT3_CMD_PENDING;
+       ioc->port_enable_cmds.status |= MPT3_CMD_COMPLETE;
+       ioc->port_enable_cmds.status |= MPT3_CMD_REPLY_VALID;
+       memcpy(ioc->port_enable_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+               ioc->port_enable_failed = 1;
+
+       if (ioc->is_driver_loading) {
+               if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+                       mpt3sas_port_enable_complete(ioc);
+                       return 1;
+               } else {
+                       ioc->start_scan_failed = ioc_status;
+                       ioc->start_scan = 0;
+                       return 1;
+               }
+       }
+       complete(&ioc->port_enable_cmds.done);
+       return 1;
+}
+
+/**
+ * _base_send_port_enable - send port_enable(discovery stuff) to firmware
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       Mpi2PortEnableRequest_t *mpi_request;
+       Mpi2PortEnableReply_t *mpi_reply;
+       unsigned long timeleft;
+       int r = 0;
+       u16 smid;
+       u16 ioc_status;
+
+       pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name);
+
+       if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) {
+               pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       ioc->port_enable_cmds.status = MPT3_CMD_PENDING;
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->port_enable_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
+
+       init_completion(&ioc->port_enable_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
+           300*HZ);
+       if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2PortEnableRequest_t)/4);
+               if (ioc->port_enable_cmds.status & MPT3_CMD_RESET)
+                       r = -EFAULT;
+               else
+                       r = -ETIME;
+               goto out;
+       }
+
+       mpi_reply = ioc->port_enable_cmds.reply;
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "%s: failed with (ioc_status=0x%08x)\n",
+                   ioc->name, __func__, ioc_status);
+               r = -EFAULT;
+               goto out;
+       }
+
+ out:
+       ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED;
+       pr_info(MPT3SAS_FMT "port enable: %s\n", ioc->name, ((r == 0) ?
+           "SUCCESS" : "FAILED"));
+       return r;
+}
+
+/**
+ * mpt3sas_port_enable - initiate firmware discovery (don't wait for reply)
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2PortEnableRequest_t *mpi_request;
+       u16 smid;
+
+       pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name);
+
+       if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) {
+               pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       ioc->port_enable_cmds.status = MPT3_CMD_PENDING;
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->port_enable_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
+
+       mpt3sas_base_put_smid_default(ioc, smid);
+       return 0;
+}
+
+/**
+ * _base_determine_wait_on_discovery - desposition
+ * @ioc: per adapter object
+ *
+ * Decide whether to wait on discovery to complete. Used to either
+ * locate boot device, or report volumes ahead of physical devices.
+ *
+ * Returns 1 for wait, 0 for don't wait
+ */
+static int
+_base_determine_wait_on_discovery(struct MPT3SAS_ADAPTER *ioc)
+{
+       /* We wait for discovery to complete if IR firmware is loaded.
+        * The sas topology events arrive before PD events, so we need time to
+        * turn on the bit in ioc->pd_handles to indicate PD
+        * Also, it maybe required to report Volumes ahead of physical
+        * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set.
+        */
+       if (ioc->ir_firmware)
+               return 1;
+
+       /* if no Bios, then we don't need to wait */
+       if (!ioc->bios_pg3.BiosVersion)
+               return 0;
+
+       /* Bios is present, then we drop down here.
+        *
+        * If there any entries in the Bios Page 2, then we wait
+        * for discovery to complete.
+        */
+
+       /* Current Boot Device */
+       if ((ioc->bios_pg2.CurrentBootDeviceForm &
+           MPI2_BIOSPAGE2_FORM_MASK) ==
+           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
+       /* Request Boot Device */
+          (ioc->bios_pg2.ReqBootDeviceForm &
+           MPI2_BIOSPAGE2_FORM_MASK) ==
+           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
+       /* Alternate Request Boot Device */
+          (ioc->bios_pg2.ReqAltBootDeviceForm &
+           MPI2_BIOSPAGE2_FORM_MASK) ==
+           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED)
+               return 0;
+
+       return 1;
+}
+
+/**
+ * _base_unmask_events - turn on notification for this event
+ * @ioc: per adapter object
+ * @event: firmware event
+ *
+ * The mask is stored in ioc->event_masks.
+ */
+static void
+_base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event)
+{
+       u32 desired_event;
+
+       if (event >= 128)
+               return;
+
+       desired_event = (1 << (event % 32));
+
+       if (event < 32)
+               ioc->event_masks[0] &= ~desired_event;
+       else if (event < 64)
+               ioc->event_masks[1] &= ~desired_event;
+       else if (event < 96)
+               ioc->event_masks[2] &= ~desired_event;
+       else if (event < 128)
+               ioc->event_masks[3] &= ~desired_event;
+}
+
+/**
+ * _base_event_notification - send event notification
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       Mpi2EventNotificationRequest_t *mpi_request;
+       unsigned long timeleft;
+       u16 smid;
+       int r = 0;
+       int i;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       if (ioc->base_cmds.status & MPT3_CMD_PENDING) {
+               pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+       ioc->base_cmds.status = MPT3_CMD_PENDING;
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->base_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+       for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+               mpi_request->EventMasks[i] =
+                   cpu_to_le32(ioc->event_masks[i]);
+       init_completion(&ioc->base_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
+       if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2EventNotificationRequest_t)/4);
+               if (ioc->base_cmds.status & MPT3_CMD_RESET)
+                       r = -EFAULT;
+               else
+                       r = -ETIME;
+       } else
+               dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s: complete\n",
+                   ioc->name, __func__));
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+       return r;
+}
+
+/**
+ * mpt3sas_base_validate_event_type - validating event types
+ * @ioc: per adapter object
+ * @event: firmware event
+ *
+ * This will turn on firmware event notification when application
+ * ask for that event. We don't mask events that are already enabled.
+ */
+void
+mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type)
+{
+       int i, j;
+       u32 event_mask, desired_event;
+       u8 send_update_to_fw;
+
+       for (i = 0, send_update_to_fw = 0; i <
+           MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
+               event_mask = ~event_type[i];
+               desired_event = 1;
+               for (j = 0; j < 32; j++) {
+                       if (!(event_mask & desired_event) &&
+                           (ioc->event_masks[i] & desired_event)) {
+                               ioc->event_masks[i] &= ~desired_event;
+                               send_update_to_fw = 1;
+                       }
+                       desired_event = (desired_event << 1);
+               }
+       }
+
+       if (!send_update_to_fw)
+               return;
+
+       mutex_lock(&ioc->base_cmds.mutex);
+       _base_event_notification(ioc, CAN_SLEEP);
+       mutex_unlock(&ioc->base_cmds.mutex);
+}
+
+/**
+ * _base_diag_reset - the "big hammer" start of day reset
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       u32 host_diagnostic;
+       u32 ioc_state;
+       u32 count;
+       u32 hcb_size;
+
+       pr_info(MPT3SAS_FMT "sending diag reset !!\n", ioc->name);
+
+       drsprintk(ioc, pr_info(MPT3SAS_FMT "clear interrupts\n",
+           ioc->name));
+
+       count = 0;
+       do {
+               /* Write magic sequence to WriteSequence register
+                * Loop until in diagnostic mode
+                */
+               drsprintk(ioc, pr_info(MPT3SAS_FMT
+                       "write magic sequence\n", ioc->name));
+               writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
+               writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
+               writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
+               writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
+               writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
+               writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
+               writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
+
+               /* wait 100 msec */
+               if (sleep_flag == CAN_SLEEP)
+                       msleep(100);
+               else
+                       mdelay(100);
+
+               if (count++ > 20)
+                       goto out;
+
+               host_diagnostic = readl(&ioc->chip->HostDiagnostic);
+               drsprintk(ioc, pr_info(MPT3SAS_FMT
+                       "wrote magic sequence: count(%d), host_diagnostic(0x%08x)\n",
+                   ioc->name, count, host_diagnostic));
+
+       } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
+
+       hcb_size = readl(&ioc->chip->HCBSize);
+
+       drsprintk(ioc, pr_info(MPT3SAS_FMT "diag reset: issued\n",
+           ioc->name));
+       writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
+            &ioc->chip->HostDiagnostic);
+
+       /* don't access any registers for 50 milliseconds */
+       msleep(50);
+
+       /* 300 second max wait */
+       for (count = 0; count < 3000000 ; count++) {
+
+               host_diagnostic = readl(&ioc->chip->HostDiagnostic);
+
+               if (host_diagnostic == 0xFFFFFFFF)
+                       goto out;
+               if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
+                       break;
+
+               /* wait 1 msec */
+               if (sleep_flag == CAN_SLEEP)
+                       usleep_range(1000, 1500);
+               else
+                       mdelay(1);
+       }
+
+       if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
+
+               drsprintk(ioc, pr_info(MPT3SAS_FMT
+               "restart the adapter assuming the HCB Address points to good F/W\n",
+                   ioc->name));
+               host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
+               host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
+               writel(host_diagnostic, &ioc->chip->HostDiagnostic);
+
+               drsprintk(ioc, pr_info(MPT3SAS_FMT
+                   "re-enable the HCDW\n", ioc->name));
+               writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
+                   &ioc->chip->HCBSize);
+       }
+
+       drsprintk(ioc, pr_info(MPT3SAS_FMT "restart the adapter\n",
+           ioc->name));
+       writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
+           &ioc->chip->HostDiagnostic);
+
+       drsprintk(ioc, pr_info(MPT3SAS_FMT
+               "disable writes to the diagnostic register\n", ioc->name));
+       writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
+
+       drsprintk(ioc, pr_info(MPT3SAS_FMT
+               "Wait for FW to go to the READY state\n", ioc->name));
+       ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
+           sleep_flag);
+       if (ioc_state) {
+               pr_err(MPT3SAS_FMT
+                       "%s: failed going to ready state (ioc_state=0x%x)\n",
+                       ioc->name, __func__, ioc_state);
+               goto out;
+       }
+
+       pr_info(MPT3SAS_FMT "diag reset: SUCCESS\n", ioc->name);
+       return 0;
+
+ out:
+       pr_err(MPT3SAS_FMT "diag reset: FAILED\n", ioc->name);
+       return -EFAULT;
+}
+
+/**
+ * _base_make_ioc_ready - put controller in READY state
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ * @type: FORCE_BIG_HAMMER or SOFT_RESET
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
+       enum reset_type type)
+{
+       u32 ioc_state;
+       int rc;
+       int count;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       if (ioc->pci_error_recovery)
+               return 0;
+
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+       dhsprintk(ioc, pr_info(MPT3SAS_FMT "%s: ioc_state(0x%08x)\n",
+           ioc->name, __func__, ioc_state));
+
+       /* if in RESET state, it should move to READY state shortly */
+       count = 0;
+       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
+               while ((ioc_state & MPI2_IOC_STATE_MASK) !=
+                   MPI2_IOC_STATE_READY) {
+                       if (count++ == 10) {
+                               pr_err(MPT3SAS_FMT
+                                       "%s: failed going to ready state (ioc_state=0x%x)\n",
+                                   ioc->name, __func__, ioc_state);
+                               return -EFAULT;
+                       }
+                       if (sleep_flag == CAN_SLEEP)
+                               ssleep(1);
+                       else
+                               mdelay(1000);
+                       ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+               }
+       }
+
+       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
+               return 0;
+
+       if (ioc_state & MPI2_DOORBELL_USED) {
+               dhsprintk(ioc, pr_info(MPT3SAS_FMT
+                       "unexpected doorbell active!\n",
+                       ioc->name));
+               goto issue_diag_reset;
+       }
+
+       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+               mpt3sas_base_fault_info(ioc, ioc_state &
+                   MPI2_DOORBELL_DATA_MASK);
+               goto issue_diag_reset;
+       }
+
+       if (type == FORCE_BIG_HAMMER)
+               goto issue_diag_reset;
+
+       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
+               if (!(_base_send_ioc_reset(ioc,
+                   MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
+                       return 0;
+       }
+
+ issue_diag_reset:
+       rc = _base_diag_reset(ioc, CAN_SLEEP);
+       return rc;
+}
+
+/**
+ * _base_make_ioc_operational - put controller in OPERATIONAL state
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       int r, i;
+       unsigned long   flags;
+       u32 reply_address;
+       u16 smid;
+       struct _tr_list *delayed_tr, *delayed_tr_next;
+       struct adapter_reply_queue *reply_q;
+       long reply_post_free;
+       u32 reply_post_free_sz;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       /* clean the delayed target reset list */
+       list_for_each_entry_safe(delayed_tr, delayed_tr_next,
+           &ioc->delayed_tr_list, list) {
+               list_del(&delayed_tr->list);
+               kfree(delayed_tr);
+       }
+
+
+       list_for_each_entry_safe(delayed_tr, delayed_tr_next,
+           &ioc->delayed_tr_volume_list, list) {
+               list_del(&delayed_tr->list);
+               kfree(delayed_tr);
+       }
+
+       /* initialize the scsi lookup free list */
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       INIT_LIST_HEAD(&ioc->free_list);
+       smid = 1;
+       for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
+               INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
+               ioc->scsi_lookup[i].cb_idx = 0xFF;
+               ioc->scsi_lookup[i].smid = smid;
+               ioc->scsi_lookup[i].scmd = NULL;
+               list_add_tail(&ioc->scsi_lookup[i].tracker_list,
+                   &ioc->free_list);
+       }
+
+       /* hi-priority queue */
+       INIT_LIST_HEAD(&ioc->hpr_free_list);
+       smid = ioc->hi_priority_smid;
+       for (i = 0; i < ioc->hi_priority_depth; i++, smid++) {
+               ioc->hpr_lookup[i].cb_idx = 0xFF;
+               ioc->hpr_lookup[i].smid = smid;
+               list_add_tail(&ioc->hpr_lookup[i].tracker_list,
+                   &ioc->hpr_free_list);
+       }
+
+       /* internal queue */
+       INIT_LIST_HEAD(&ioc->internal_free_list);
+       smid = ioc->internal_smid;
+       for (i = 0; i < ioc->internal_depth; i++, smid++) {
+               ioc->internal_lookup[i].cb_idx = 0xFF;
+               ioc->internal_lookup[i].smid = smid;
+               list_add_tail(&ioc->internal_lookup[i].tracker_list,
+                   &ioc->internal_free_list);
+       }
+
+       /* chain pool */
+       INIT_LIST_HEAD(&ioc->free_chain_list);
+       for (i = 0; i < ioc->chain_depth; i++)
+               list_add_tail(&ioc->chain_lookup[i].tracker_list,
+                   &ioc->free_chain_list);
+
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+       /* initialize Reply Free Queue */
+       for (i = 0, reply_address = (u32)ioc->reply_dma ;
+           i < ioc->reply_free_queue_depth ; i++, reply_address +=
+           ioc->reply_sz)
+               ioc->reply_free[i] = cpu_to_le32(reply_address);
+
+       /* initialize reply queues */
+       if (ioc->is_driver_loading)
+               _base_assign_reply_queues(ioc);
+
+       /* initialize Reply Post Free Queue */
+       reply_post_free = (long)ioc->reply_post_free;
+       reply_post_free_sz = ioc->reply_post_queue_depth *
+           sizeof(Mpi2DefaultReplyDescriptor_t);
+       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+               reply_q->reply_post_host_index = 0;
+               reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
+                   reply_post_free;
+               for (i = 0; i < ioc->reply_post_queue_depth; i++)
+                       reply_q->reply_post_free[i].Words =
+                           cpu_to_le64(ULLONG_MAX);
+               if (!_base_is_controller_msix_enabled(ioc))
+                       goto skip_init_reply_post_free_queue;
+               reply_post_free += reply_post_free_sz;
+       }
+ skip_init_reply_post_free_queue:
+
+       r = _base_send_ioc_init(ioc, sleep_flag);
+       if (r)
+               return r;
+
+       /* initialize reply free host index */
+       ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
+       writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
+
+       /* initialize reply post host index */
+       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+               writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT,
+                   &ioc->chip->ReplyPostHostIndex);
+               if (!_base_is_controller_msix_enabled(ioc))
+                       goto skip_init_reply_post_host_index;
+       }
+
+ skip_init_reply_post_host_index:
+
+       _base_unmask_interrupts(ioc);
+       r = _base_event_notification(ioc, sleep_flag);
+       if (r)
+               return r;
+
+       if (sleep_flag == CAN_SLEEP)
+               _base_static_config_pages(ioc);
+
+
+       if (ioc->is_driver_loading) {
+               ioc->wait_for_discovery_to_complete =
+                   _base_determine_wait_on_discovery(ioc);
+
+               return r; /* scan_start and scan_finished support */
+       }
+
+       r = _base_send_port_enable(ioc, sleep_flag);
+       if (r)
+               return r;
+
+       return r;
+}
+
+/**
+ * mpt3sas_base_free_resources - free resources controller resources
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct pci_dev *pdev = ioc->pdev;
+
+       dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       _base_mask_interrupts(ioc);
+       ioc->shost_recovery = 1;
+       _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
+       ioc->shost_recovery = 0;
+       _base_free_irq(ioc);
+       _base_disable_msix(ioc);
+       if (ioc->chip_phys)
+               iounmap(ioc->chip);
+       ioc->chip_phys = 0;
+       pci_release_selected_regions(ioc->pdev, ioc->bars);
+       pci_disable_pcie_error_reporting(pdev);
+       pci_disable_device(pdev);
+       return;
+}
+
+/**
+ * mpt3sas_base_attach - attach controller instance
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
+{
+       int r, i;
+       int cpu_id, last_cpu_id = 0;
+
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       /* setup cpu_msix_table */
+       ioc->cpu_count = num_online_cpus();
+       for_each_online_cpu(cpu_id)
+               last_cpu_id = cpu_id;
+       ioc->cpu_msix_table_sz = last_cpu_id + 1;
+       ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
+       ioc->reply_queue_count = 1;
+       if (!ioc->cpu_msix_table) {
+               dfailprintk(ioc, pr_info(MPT3SAS_FMT
+                       "allocation for cpu_msix_table failed!!!\n",
+                       ioc->name));
+               r = -ENOMEM;
+               goto out_free_resources;
+       }
+
+       r = mpt3sas_base_map_resources(ioc);
+       if (r)
+               goto out_free_resources;
+
+
+       pci_set_drvdata(ioc->pdev, ioc->shost);
+       r = _base_get_ioc_facts(ioc, CAN_SLEEP);
+       if (r)
+               goto out_free_resources;
+
+       /*
+        * In SAS3.0,
+        * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and
+        * Target Status - all require the IEEE formated scatter gather
+        * elements.
+        */
+
+       ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
+       ioc->build_sg = &_base_build_sg_ieee;
+       ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
+       ioc->mpi25 = 1;
+       ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
+
+       /*
+        * These function pointers for other requests that don't
+        * the require IEEE scatter gather elements.
+        *
+        * For example Configuration Pages and SAS IOUNIT Control don't.
+        */
+       ioc->build_sg_mpi = &_base_build_sg;
+       ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge;
+
+       r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
+       if (r)
+               goto out_free_resources;
+
+       ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
+           sizeof(struct mpt3sas_port_facts), GFP_KERNEL);
+       if (!ioc->pfacts) {
+               r = -ENOMEM;
+               goto out_free_resources;
+       }
+
+       for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
+               r = _base_get_port_facts(ioc, i, CAN_SLEEP);
+               if (r)
+                       goto out_free_resources;
+       }
+
+       r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
+       if (r)
+               goto out_free_resources;
+
+       init_waitqueue_head(&ioc->reset_wq);
+
+       /* allocate memory pd handle bitmask list */
+       ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
+       if (ioc->facts.MaxDevHandle % 8)
+               ioc->pd_handles_sz++;
+       ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
+           GFP_KERNEL);
+       if (!ioc->pd_handles) {
+               r = -ENOMEM;
+               goto out_free_resources;
+       }
+       ioc->blocking_handles = kzalloc(ioc->pd_handles_sz,
+           GFP_KERNEL);
+       if (!ioc->blocking_handles) {
+               r = -ENOMEM;
+               goto out_free_resources;
+       }
+
+       ioc->fwfault_debug = mpt3sas_fwfault_debug;
+
+       /* base internal command bits */
+       mutex_init(&ioc->base_cmds.mutex);
+       ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+
+       /* port_enable command bits */
+       ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED;
+
+       /* transport internal command bits */
+       ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_init(&ioc->transport_cmds.mutex);
+
+       /* scsih internal command bits */
+       ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_init(&ioc->scsih_cmds.mutex);
+
+       /* task management internal command bits */
+       ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_init(&ioc->tm_cmds.mutex);
+
+       /* config page internal command bits */
+       ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->config_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_init(&ioc->config_cmds.mutex);
+
+       /* ctl module internal command bits */
+       ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+       ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_init(&ioc->ctl_cmds.mutex);
+
+       if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
+           !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
+           !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
+           !ioc->ctl_cmds.sense) {
+               r = -ENOMEM;
+               goto out_free_resources;
+       }
+
+       for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+               ioc->event_masks[i] = -1;
+
+       /* here we enable the events we care about */
+       _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
+       _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
+       _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
+       _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
+       _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
+       _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
+       _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
+       _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
+       _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
+       _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
+
+       r = _base_make_ioc_operational(ioc, CAN_SLEEP);
+       if (r)
+               goto out_free_resources;
+
+       return 0;
+
+ out_free_resources:
+
+       ioc->remove_host = 1;
+
+       mpt3sas_base_free_resources(ioc);
+       _base_release_memory_pools(ioc);
+       pci_set_drvdata(ioc->pdev, NULL);
+       kfree(ioc->cpu_msix_table);
+       kfree(ioc->pd_handles);
+       kfree(ioc->blocking_handles);
+       kfree(ioc->tm_cmds.reply);
+       kfree(ioc->transport_cmds.reply);
+       kfree(ioc->scsih_cmds.reply);
+       kfree(ioc->config_cmds.reply);
+       kfree(ioc->base_cmds.reply);
+       kfree(ioc->port_enable_cmds.reply);
+       kfree(ioc->ctl_cmds.reply);
+       kfree(ioc->ctl_cmds.sense);
+       kfree(ioc->pfacts);
+       ioc->ctl_cmds.reply = NULL;
+       ioc->base_cmds.reply = NULL;
+       ioc->tm_cmds.reply = NULL;
+       ioc->scsih_cmds.reply = NULL;
+       ioc->transport_cmds.reply = NULL;
+       ioc->config_cmds.reply = NULL;
+       ioc->pfacts = NULL;
+       return r;
+}
+
+
+/**
+ * mpt3sas_base_detach - remove controller instance
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
+{
+       dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       mpt3sas_base_stop_watchdog(ioc);
+       mpt3sas_base_free_resources(ioc);
+       _base_release_memory_pools(ioc);
+       pci_set_drvdata(ioc->pdev, NULL);
+       kfree(ioc->cpu_msix_table);
+       kfree(ioc->pd_handles);
+       kfree(ioc->blocking_handles);
+       kfree(ioc->pfacts);
+       kfree(ioc->ctl_cmds.reply);
+       kfree(ioc->ctl_cmds.sense);
+       kfree(ioc->base_cmds.reply);
+       kfree(ioc->port_enable_cmds.reply);
+       kfree(ioc->tm_cmds.reply);
+       kfree(ioc->transport_cmds.reply);
+       kfree(ioc->scsih_cmds.reply);
+       kfree(ioc->config_cmds.reply);
+}
+
+/**
+ * _base_reset_handler - reset callback handler (for base)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
+ * MPT3_IOC_DONE_RESET
+ *
+ * Return nothing.
+ */
+static void
+_base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
+{
+       mpt3sas_scsih_reset_handler(ioc, reset_phase);
+       mpt3sas_ctl_reset_handler(ioc, reset_phase);
+       switch (reset_phase) {
+       case MPT3_IOC_PRE_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
+               break;
+       case MPT3_IOC_AFTER_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
+               if (ioc->transport_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->transport_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->transport_cmds.smid);
+                       complete(&ioc->transport_cmds.done);
+               }
+               if (ioc->base_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->base_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->base_cmds.smid);
+                       complete(&ioc->base_cmds.done);
+               }
+               if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->port_enable_failed = 1;
+                       ioc->port_enable_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->port_enable_cmds.smid);
+                       if (ioc->is_driver_loading) {
+                               ioc->start_scan_failed =
+                                   MPI2_IOCSTATUS_INTERNAL_ERROR;
+                               ioc->start_scan = 0;
+                               ioc->port_enable_cmds.status =
+                                   MPT3_CMD_NOT_USED;
+                       } else
+                               complete(&ioc->port_enable_cmds.done);
+               }
+               if (ioc->config_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->config_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->config_cmds.smid);
+                       ioc->config_cmds.smid = USHRT_MAX;
+                       complete(&ioc->config_cmds.done);
+               }
+               break;
+       case MPT3_IOC_DONE_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
+               break;
+       }
+}
+
+/**
+ * _wait_for_commands_to_complete - reset controller
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * This function waiting(3s) for all pending commands to complete
+ * prior to putting controller in reset.
+ */
+static void
+_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+{
+       u32 ioc_state;
+       unsigned long flags;
+       u16 i;
+
+       ioc->pending_io_count = 0;
+       if (sleep_flag != CAN_SLEEP)
+               return;
+
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+       if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
+               return;
+
+       /* pending command count */
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       for (i = 0; i < ioc->scsiio_depth; i++)
+               if (ioc->scsi_lookup[i].cb_idx != 0xFF)
+                       ioc->pending_io_count++;
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+       if (!ioc->pending_io_count)
+               return;
+
+       /* wait for pending commands to complete */
+       wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
+}
+
+/**
+ * mpt3sas_base_hard_reset_handler - reset controller
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ * @type: FORCE_BIG_HAMMER or SOFT_RESET
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
+       enum reset_type type)
+{
+       int r;
+       unsigned long flags;
+       u32 ioc_state;
+       u8 is_fault = 0, is_trigger = 0;
+
+       dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
+           __func__));
+
+       if (ioc->pci_error_recovery) {
+               pr_err(MPT3SAS_FMT "%s: pci error recovery reset\n",
+                   ioc->name, __func__);
+               r = 0;
+               goto out_unlocked;
+       }
+
+       if (mpt3sas_fwfault_debug)
+               mpt3sas_halt_firmware(ioc);
+
+       /* TODO - What we really should be doing is pulling
+        * out all the code associated with NO_SLEEP; its never used.
+        * That is legacy code from mpt fusion driver, ported over.
+        * I will leave this BUG_ON here for now till its been resolved.
+        */
+       BUG_ON(sleep_flag == NO_SLEEP);
+
+       /* wait for an active reset in progress to complete */
+       if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
+               do {
+                       ssleep(1);
+               } while (ioc->shost_recovery == 1);
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+                   __func__));
+               return ioc->ioc_reset_in_progress_status;
+       }
+
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       ioc->shost_recovery = 1;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) &&
+           (!(ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED))) {
+               is_trigger = 1;
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+               if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
+                       is_fault = 1;
+       }
+       _base_reset_handler(ioc, MPT3_IOC_PRE_RESET);
+       _wait_for_commands_to_complete(ioc, sleep_flag);
+       _base_mask_interrupts(ioc);
+       r = _base_make_ioc_ready(ioc, sleep_flag, type);
+       if (r)
+               goto out;
+       _base_reset_handler(ioc, MPT3_IOC_AFTER_RESET);
+
+       /* If this hard reset is called while port enable is active, then
+        * there is no reason to call make_ioc_operational
+        */
+       if (ioc->is_driver_loading && ioc->port_enable_failed) {
+               ioc->remove_host = 1;
+               r = -EFAULT;
+               goto out;
+       }
+       r = _base_get_ioc_facts(ioc, CAN_SLEEP);
+       if (r)
+               goto out;
+       r = _base_make_ioc_operational(ioc, sleep_flag);
+       if (!r)
+               _base_reset_handler(ioc, MPT3_IOC_DONE_RESET);
+
+ out:
+       dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: %s\n",
+           ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
+
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       ioc->ioc_reset_in_progress_status = r;
+       ioc->shost_recovery = 0;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       ioc->ioc_reset_count++;
+       mutex_unlock(&ioc->reset_in_progress_mutex);
+
+ out_unlocked:
+       if ((r == 0) && is_trigger) {
+               if (is_fault)
+                       mpt3sas_trigger_master(ioc, MASTER_TRIGGER_FW_FAULT);
+               else
+                       mpt3sas_trigger_master(ioc,
+                           MASTER_TRIGGER_ADAPTER_RESET);
+       }
+       dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+       return r;
+}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
new file mode 100644 (file)
index 0000000..994656c
--- /dev/null
@@ -0,0 +1,1139 @@
+/*
+ * This is the Fusion MPT base driver providing common API layer interface
+ * for access to MPT (Message Passing Technology) firmware.
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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 MPT3SAS_BASE_H_INCLUDED
+#define MPT3SAS_BASE_H_INCLUDED
+
+#include "mpi/mpi2_type.h"
+#include "mpi/mpi2.h"
+#include "mpi/mpi2_ioc.h"
+#include "mpi/mpi2_cnfg.h"
+#include "mpi/mpi2_init.h"
+#include "mpi/mpi2_raid.h"
+#include "mpi/mpi2_tool.h"
+#include "mpi/mpi2_sas.h"
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_sas.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+
+#include "mpt3sas_debug.h"
+#include "mpt3sas_trigger_diag.h"
+
+/* driver versioning info */
+#define MPT3SAS_DRIVER_NAME            "mpt3sas"
+#define MPT3SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
+#define MPT3SAS_DESCRIPTION    "LSI MPT Fusion SAS 3.0 Device Driver"
+#define MPT3SAS_DRIVER_VERSION         "01.100.01.00"
+#define MPT3SAS_MAJOR_VERSION          1
+#define MPT3SAS_MINOR_VERSION          100
+#define MPT3SAS_BUILD_VERSION          1
+#define MPT3SAS_RELEASE_VERSION        00
+
+/*
+ * Set MPT3SAS_SG_DEPTH value based on user input.
+ */
+#define MPT3SAS_MAX_PHYS_SEGMENTS      SCSI_MAX_SG_SEGMENTS
+#define MPT3SAS_MIN_PHYS_SEGMENTS      16
+#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE
+#define MPT3SAS_SG_DEPTH               CONFIG_SCSI_MPT3SAS_MAX_SGE
+#else
+#define MPT3SAS_SG_DEPTH               MPT3SAS_MAX_PHYS_SEGMENTS
+#endif
+
+
+/*
+ * Generic Defines
+ */
+#define MPT3SAS_SATA_QUEUE_DEPTH       32
+#define MPT3SAS_SAS_QUEUE_DEPTH                254
+#define MPT3SAS_RAID_QUEUE_DEPTH       128
+
+#define MPT_NAME_LENGTH                        32      /* generic length of strings */
+#define MPT_STRING_LENGTH              64
+
+#define MPT_MAX_CALLBACKS              32
+
+
+#define         CAN_SLEEP                      1
+#define  NO_SLEEP                      0
+
+#define INTERNAL_CMDS_COUNT            10      /* reserved cmds */
+
+#define MPI3_HIM_MASK                  0xFFFFFFFF /* mask every bit*/
+
+#define MPT3SAS_INVALID_DEVICE_HANDLE  0xFFFF
+
+/*
+ * reset phases
+ */
+#define MPT3_IOC_PRE_RESET             1 /* prior to host reset */
+#define MPT3_IOC_AFTER_RESET           2 /* just after host reset */
+#define MPT3_IOC_DONE_RESET            3 /* links re-initialized */
+
+/*
+ * logging format
+ */
+#define MPT3SAS_FMT                    "%s: "
+
+/*
+ * per target private data
+ */
+#define MPT_TARGET_FLAGS_RAID_COMPONENT        0x01
+#define MPT_TARGET_FLAGS_VOLUME                0x02
+#define MPT_TARGET_FLAGS_DELETED       0x04
+#define MPT_TARGET_FASTPATH_IO         0x08
+
+
+
+/*
+ * status bits for ioc->diag_buffer_status
+ */
+#define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01)
+#define MPT3_DIAG_BUFFER_IS_RELEASED   (0x02)
+#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04)
+
+
+/* OEM Identifiers */
+#define MFG10_OEM_ID_INVALID                   (0x00000000)
+#define MFG10_OEM_ID_DELL                      (0x00000001)
+#define MFG10_OEM_ID_FSC                       (0x00000002)
+#define MFG10_OEM_ID_SUN                       (0x00000003)
+#define MFG10_OEM_ID_IBM                       (0x00000004)
+
+/* GENERIC Flags 0*/
+#define MFG10_GF0_OCE_DISABLED                 (0x00000001)
+#define MFG10_GF0_R1E_DRIVE_COUNT              (0x00000002)
+#define MFG10_GF0_R10_DISPLAY                  (0x00000004)
+#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE       (0x00000008)
+#define MFG10_GF0_SINGLE_DRIVE_R0              (0x00000010)
+
+/* OEM Specific Flags will come from OEM specific header files */
+struct Mpi2ManufacturingPage10_t {
+       MPI2_CONFIG_PAGE_HEADER Header;         /* 00h */
+       U8      OEMIdentifier;                  /* 04h */
+       U8      Reserved1;                      /* 05h */
+       U16     Reserved2;                      /* 08h */
+       U32     Reserved3;                      /* 0Ch */
+       U32     GenericFlags0;                  /* 10h */
+       U32     GenericFlags1;                  /* 14h */
+       U32     Reserved4;                      /* 18h */
+       U32     OEMSpecificFlags0;              /* 1Ch */
+       U32     OEMSpecificFlags1;              /* 20h */
+       U32     Reserved5[18];                  /* 24h - 60h*/
+};
+
+
+/* Miscellaneous options */
+struct Mpi2ManufacturingPage11_t {
+       MPI2_CONFIG_PAGE_HEADER Header;         /* 00h */
+       __le32  Reserved1;                      /* 04h */
+       u8      Reserved2;                      /* 08h */
+       u8      EEDPTagMode;                    /* 09h */
+       u8      Reserved3;                      /* 0Ah */
+       u8      Reserved4;                      /* 0Bh */
+       __le32  Reserved5[23];                  /* 0Ch-60h*/
+};
+
+/**
+ * struct MPT3SAS_TARGET - starget private hostdata
+ * @starget: starget object
+ * @sas_address: target sas address
+ * @handle: device handle
+ * @num_luns: number luns
+ * @flags: MPT_TARGET_FLAGS_XXX flags
+ * @deleted: target flaged for deletion
+ * @tm_busy: target is busy with TM request.
+ */
+struct MPT3SAS_TARGET {
+       struct scsi_target *starget;
+       u64     sas_address;
+       u16     handle;
+       int     num_luns;
+       u32     flags;
+       u8      deleted;
+       u8      tm_busy;
+};
+
+
+/*
+ * per device private data
+ */
+#define MPT_DEVICE_FLAGS_INIT          0x01
+#define MPT_DEVICE_TLR_ON              0x02
+
+/**
+ * struct MPT3SAS_DEVICE - sdev private hostdata
+ * @sas_target: starget private hostdata
+ * @lun: lun number
+ * @flags: MPT_DEVICE_XXX flags
+ * @configured_lun: lun is configured
+ * @block: device is in SDEV_BLOCK state
+ * @tlr_snoop_check: flag used in determining whether to disable TLR
+ * @eedp_enable: eedp support enable bit
+ * @eedp_type: 0(type_1), 1(type_2), 2(type_3)
+ * @eedp_block_length: block size
+ */
+struct MPT3SAS_DEVICE {
+       struct MPT3SAS_TARGET *sas_target;
+       unsigned int    lun;
+       u32     flags;
+       u8      configured_lun;
+       u8      block;
+       u8      tlr_snoop_check;
+};
+
+#define MPT3_CMD_NOT_USED      0x8000  /* free */
+#define MPT3_CMD_COMPLETE      0x0001  /* completed */
+#define MPT3_CMD_PENDING       0x0002  /* pending */
+#define MPT3_CMD_REPLY_VALID   0x0004  /* reply is valid */
+#define MPT3_CMD_RESET         0x0008  /* host reset dropped the command */
+
+/**
+ * struct _internal_cmd - internal commands struct
+ * @mutex: mutex
+ * @done: completion
+ * @reply: reply message pointer
+ * @sense: sense data
+ * @status: MPT3_CMD_XXX status
+ * @smid: system message id
+ */
+struct _internal_cmd {
+       struct mutex mutex;
+       struct completion done;
+       void    *reply;
+       void    *sense;
+       u16     status;
+       u16     smid;
+};
+
+
+
+/**
+ * struct _sas_device - attached device information
+ * @list: sas device list
+ * @starget: starget object
+ * @sas_address: device sas address
+ * @device_name: retrieved from the SAS IDENTIFY frame.
+ * @handle: device handle
+ * @sas_address_parent: sas address of parent expander or sas host
+ * @enclosure_handle: enclosure handle
+ * @enclosure_logical_id: enclosure logical identifier
+ * @volume_handle: volume handle (valid when hidden raid member)
+ * @volume_wwid: volume unique identifier
+ * @device_info: bitfield provides detailed info about the device
+ * @id: target id
+ * @channel: target channel
+ * @slot: number number
+ * @phy: phy identifier provided in sas device page 0
+ * @fast_path: fast path feature enable bit
+ * @responding: used in _scsih_sas_device_mark_responding
+ */
+struct _sas_device {
+       struct list_head list;
+       struct scsi_target *starget;
+       u64     sas_address;
+       u64     device_name;
+       u16     handle;
+       u64     sas_address_parent;
+       u16     enclosure_handle;
+       u64     enclosure_logical_id;
+       u16     volume_handle;
+       u64     volume_wwid;
+       u32     device_info;
+       int     id;
+       int     channel;
+       u16     slot;
+       u8      phy;
+       u8      responding;
+       u8      fast_path;
+};
+
+/**
+ * struct _raid_device - raid volume link list
+ * @list: sas device list
+ * @starget: starget object
+ * @sdev: scsi device struct (volumes are single lun)
+ * @wwid: unique identifier for the volume
+ * @handle: device handle
+ * @id: target id
+ * @channel: target channel
+ * @volume_type: the raid level
+ * @device_info: bitfield provides detailed info about the hidden components
+ * @num_pds: number of hidden raid components
+ * @responding: used in _scsih_raid_device_mark_responding
+ * @percent_complete: resync percent complete
+ */
+#define MPT_MAX_WARPDRIVE_PDS          8
+struct _raid_device {
+       struct list_head list;
+       struct scsi_target *starget;
+       struct scsi_device *sdev;
+       u64     wwid;
+       u16     handle;
+       int     id;
+       int     channel;
+       u8      volume_type;
+       u8      num_pds;
+       u8      responding;
+       u8      percent_complete;
+       u32     device_info;
+};
+
+/**
+ * struct _boot_device - boot device info
+ * @is_raid: flag to indicate whether this is volume
+ * @device: holds pointer for either struct _sas_device or
+ *     struct _raid_device
+ */
+struct _boot_device {
+       u8 is_raid;
+       void *device;
+};
+
+/**
+ * struct _sas_port - wide/narrow sas port information
+ * @port_list: list of ports belonging to expander
+ * @num_phys: number of phys belonging to this port
+ * @remote_identify: attached device identification
+ * @rphy: sas transport rphy object
+ * @port: sas transport wide/narrow port object
+ * @phy_list: _sas_phy list objects belonging to this port
+ */
+struct _sas_port {
+       struct list_head port_list;
+       u8      num_phys;
+       struct sas_identify remote_identify;
+       struct sas_rphy *rphy;
+       struct sas_port *port;
+       struct list_head phy_list;
+};
+
+/**
+ * struct _sas_phy - phy information
+ * @port_siblings: list of phys belonging to a port
+ * @identify: phy identification
+ * @remote_identify: attached device identification
+ * @phy: sas transport phy object
+ * @phy_id: unique phy id
+ * @handle: device handle for this phy
+ * @attached_handle: device handle for attached device
+ * @phy_belongs_to_port: port has been created for this phy
+ */
+struct _sas_phy {
+       struct list_head port_siblings;
+       struct sas_identify identify;
+       struct sas_identify remote_identify;
+       struct sas_phy *phy;
+       u8      phy_id;
+       u16     handle;
+       u16     attached_handle;
+       u8      phy_belongs_to_port;
+};
+
+/**
+ * struct _sas_node - sas_host/expander information
+ * @list: list of expanders
+ * @parent_dev: parent device class
+ * @num_phys: number phys belonging to this sas_host/expander
+ * @sas_address: sas address of this sas_host/expander
+ * @handle: handle for this sas_host/expander
+ * @sas_address_parent: sas address of parent expander or sas host
+ * @enclosure_handle: handle for this a member of an enclosure
+ * @device_info: bitwise defining capabilities of this sas_host/expander
+ * @responding: used in _scsih_expander_device_mark_responding
+ * @phy: a list of phys that make up this sas_host/expander
+ * @sas_port_list: list of ports attached to this sas_host/expander
+ */
+struct _sas_node {
+       struct list_head list;
+       struct device *parent_dev;
+       u8      num_phys;
+       u64     sas_address;
+       u16     handle;
+       u64     sas_address_parent;
+       u16     enclosure_handle;
+       u64     enclosure_logical_id;
+       u8      responding;
+       struct  _sas_phy *phy;
+       struct list_head sas_port_list;
+};
+
+/**
+ * enum reset_type - reset state
+ * @FORCE_BIG_HAMMER: issue diagnostic reset
+ * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
+ */
+enum reset_type {
+       FORCE_BIG_HAMMER,
+       SOFT_RESET,
+};
+
+/**
+ * struct chain_tracker - firmware chain tracker
+ * @chain_buffer: chain buffer
+ * @chain_buffer_dma: physical address
+ * @tracker_list: list of free request (ioc->free_chain_list)
+ */
+struct chain_tracker {
+       void *chain_buffer;
+       dma_addr_t chain_buffer_dma;
+       struct list_head tracker_list;
+};
+
+/**
+ * struct scsiio_tracker - scsi mf request tracker
+ * @smid: system message id
+ * @scmd: scsi request pointer
+ * @cb_idx: callback index
+ * @tracker_list: list of free request (ioc->free_list)
+ */
+struct scsiio_tracker {
+       u16     smid;
+       struct scsi_cmnd *scmd;
+       u8      cb_idx;
+       struct list_head chain_list;
+       struct list_head tracker_list;
+};
+
+/**
+ * struct request_tracker - firmware request tracker
+ * @smid: system message id
+ * @cb_idx: callback index
+ * @tracker_list: list of free request (ioc->free_list)
+ */
+struct request_tracker {
+       u16     smid;
+       u8      cb_idx;
+       struct list_head tracker_list;
+};
+
+/**
+ * struct _tr_list - target reset list
+ * @handle: device handle
+ * @state: state machine
+ */
+struct _tr_list {
+       struct list_head list;
+       u16     handle;
+       u16     state;
+};
+
+
+/**
+ * struct adapter_reply_queue - the reply queue struct
+ * @ioc: per adapter object
+ * @msix_index: msix index into vector table
+ * @vector: irq vector
+ * @reply_post_host_index: head index in the pool where FW completes IO
+ * @reply_post_free: reply post base virt address
+ * @name: the name registered to request_irq()
+ * @busy: isr is actively processing replies on another cpu
+ * @list: this list
+*/
+struct adapter_reply_queue {
+       struct MPT3SAS_ADAPTER  *ioc;
+       u8                      msix_index;
+       unsigned int            vector;
+       u32                     reply_post_host_index;
+       Mpi2ReplyDescriptorsUnion_t *reply_post_free;
+       char                    name[MPT_NAME_LENGTH];
+       atomic_t                busy;
+       struct list_head        list;
+};
+
+typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
+
+/* SAS3.0 support */
+typedef int (*MPT_BUILD_SG_SCMD)(struct MPT3SAS_ADAPTER *ioc,
+               struct scsi_cmnd *scmd, u16 smid);
+typedef void (*MPT_BUILD_SG)(struct MPT3SAS_ADAPTER *ioc, void *psge,
+               dma_addr_t data_out_dma, size_t data_out_sz,
+               dma_addr_t data_in_dma, size_t data_in_sz);
+typedef void (*MPT_BUILD_ZERO_LEN_SGE)(struct MPT3SAS_ADAPTER *ioc,
+               void *paddr);
+
+
+
+/* IOC Facts and Port Facts converted from little endian to cpu */
+union mpi3_version_union {
+       MPI2_VERSION_STRUCT             Struct;
+       u32                             Word;
+};
+
+struct mpt3sas_facts {
+       u16                     MsgVersion;
+       u16                     HeaderVersion;
+       u8                      IOCNumber;
+       u8                      VP_ID;
+       u8                      VF_ID;
+       u16                     IOCExceptions;
+       u16                     IOCStatus;
+       u32                     IOCLogInfo;
+       u8                      MaxChainDepth;
+       u8                      WhoInit;
+       u8                      NumberOfPorts;
+       u8                      MaxMSIxVectors;
+       u16                     RequestCredit;
+       u16                     ProductID;
+       u32                     IOCCapabilities;
+       union mpi3_version_union        FWVersion;
+       u16                     IOCRequestFrameSize;
+       u16                     Reserved3;
+       u16                     MaxInitiators;
+       u16                     MaxTargets;
+       u16                     MaxSasExpanders;
+       u16                     MaxEnclosures;
+       u16                     ProtocolFlags;
+       u16                     HighPriorityCredit;
+       u16                     MaxReplyDescriptorPostQueueDepth;
+       u8                      ReplyFrameSize;
+       u8                      MaxVolumes;
+       u16                     MaxDevHandle;
+       u16                     MaxPersistentEntries;
+       u16                     MinDevHandle;
+};
+
+struct mpt3sas_port_facts {
+       u8                      PortNumber;
+       u8                      VP_ID;
+       u8                      VF_ID;
+       u8                      PortType;
+       u16                     MaxPostedCmdBuffers;
+};
+
+/**
+ * enum mutex_type - task management mutex type
+ * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
+ * @TM_MUTEX_ON: mutex is required
+ */
+enum mutex_type {
+       TM_MUTEX_OFF = 0,
+       TM_MUTEX_ON = 1,
+};
+
+typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
+/**
+ * struct MPT3SAS_ADAPTER - per adapter struct
+ * @list: ioc_list
+ * @shost: shost object
+ * @id: unique adapter id
+ * @cpu_count: number online cpus
+ * @name: generic ioc string
+ * @tmp_string: tmp string used for logging
+ * @pdev: pci pdev object
+ * @pio_chip: physical io register space
+ * @chip: memory mapped register space
+ * @chip_phys: physical addrss prior to mapping
+ * @logging_level: see mpt3sas_debug.h
+ * @fwfault_debug: debuging FW timeouts
+ * @ir_firmware: IR firmware present
+ * @bars: bitmask of BAR's that must be configured
+ * @mask_interrupts: ignore interrupt
+ * @fault_reset_work_q_name: fw fault work queue
+ * @fault_reset_work_q: ""
+ * @fault_reset_work: ""
+ * @firmware_event_name: fw event work queue
+ * @firmware_event_thread: ""
+ * @fw_event_lock:
+ * @fw_event_list: list of fw events
+ * @aen_event_read_flag: event log was read
+ * @broadcast_aen_busy: broadcast aen waiting to be serviced
+ * @shost_recovery: host reset in progress
+ * @ioc_reset_in_progress_lock:
+ * @ioc_link_reset_in_progress: phy/hard reset in progress
+ * @ignore_loginfos: ignore loginfos during task management
+ * @remove_host: flag for when driver unloads, to avoid sending dev resets
+ * @pci_error_recovery: flag to prevent ioc access until slot reset completes
+ * @wait_for_discovery_to_complete: flag set at driver load time when
+ *                                               waiting on reporting devices
+ * @is_driver_loading: flag set at driver load time
+ * @port_enable_failed: flag set when port enable has failed
+ * @start_scan: flag set from scan_start callback, cleared from _mpt3sas_fw_work
+ * @start_scan_failed: means port enable failed, return's the ioc_status
+ * @msix_enable: flag indicating msix is enabled
+ * @msix_vector_count: number msix vectors
+ * @cpu_msix_table: table for mapping cpus to msix index
+ * @cpu_msix_table_sz: table size
+ * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
+ * @scsi_io_cb_idx: shost generated commands
+ * @tm_cb_idx: task management commands
+ * @scsih_cb_idx: scsih internal commands
+ * @transport_cb_idx: transport internal commands
+ * @ctl_cb_idx: clt internal commands
+ * @base_cb_idx: base internal commands
+ * @config_cb_idx: base internal commands
+ * @tm_tr_cb_idx : device removal target reset handshake
+ * @tm_tr_volume_cb_idx : volume removal target reset
+ * @base_cmds:
+ * @transport_cmds:
+ * @scsih_cmds:
+ * @tm_cmds:
+ * @ctl_cmds:
+ * @config_cmds:
+ * @base_add_sg_single: handler for either 32/64 bit sgl's
+ * @event_type: bits indicating which events to log
+ * @event_context: unique id for each logged event
+ * @event_log: event log pointer
+ * @event_masks: events that are masked
+ * @facts: static facts data
+ * @pfacts: static port facts data
+ * @manu_pg0: static manufacturing page 0
+ * @manu_pg10: static manufacturing page 10
+ * @manu_pg11: static manufacturing page 11
+ * @bios_pg2: static bios page 2
+ * @bios_pg3: static bios page 3
+ * @ioc_pg8: static ioc page 8
+ * @iounit_pg0: static iounit page 0
+ * @iounit_pg1: static iounit page 1
+ * @sas_hba: sas host object
+ * @sas_expander_list: expander object list
+ * @sas_node_lock:
+ * @sas_device_list: sas device object list
+ * @sas_device_init_list: sas device object list (used only at init time)
+ * @sas_device_lock:
+ * @io_missing_delay: time for IO completed by fw when PDR enabled
+ * @device_missing_delay: time for device missing by fw when PDR enabled
+ * @sas_id : used for setting volume target IDs
+ * @blocking_handles: bitmask used to identify which devices need blocking
+ * @pd_handles : bitmask for PD handles
+ * @pd_handles_sz : size of pd_handle bitmask
+ * @config_page_sz: config page size
+ * @config_page: reserve memory for config page payload
+ * @config_page_dma:
+ * @hba_queue_depth: hba request queue depth
+ * @sge_size: sg element size for either 32/64 bit
+ * @scsiio_depth: SCSI_IO queue depth
+ * @request_sz: per request frame size
+ * @request: pool of request frames
+ * @request_dma:
+ * @request_dma_sz:
+ * @scsi_lookup: firmware request tracker list
+ * @scsi_lookup_lock:
+ * @free_list: free list of request
+ * @pending_io_count:
+ * @reset_wq:
+ * @chain: pool of chains
+ * @chain_dma:
+ * @max_sges_in_main_message: number sg elements in main message
+ * @max_sges_in_chain_message: number sg elements per chain
+ * @chains_needed_per_io: max chains per io
+ * @chain_depth: total chains allocated
+ * @hi_priority_smid:
+ * @hi_priority:
+ * @hi_priority_dma:
+ * @hi_priority_depth:
+ * @hpr_lookup:
+ * @hpr_free_list:
+ * @internal_smid:
+ * @internal:
+ * @internal_dma:
+ * @internal_depth:
+ * @internal_lookup:
+ * @internal_free_list:
+ * @sense: pool of sense
+ * @sense_dma:
+ * @sense_dma_pool:
+ * @reply_depth: hba reply queue depth:
+ * @reply_sz: per reply frame size:
+ * @reply: pool of replys:
+ * @reply_dma:
+ * @reply_dma_pool:
+ * @reply_free_queue_depth: reply free depth
+ * @reply_free: pool for reply free queue (32 bit addr)
+ * @reply_free_dma:
+ * @reply_free_dma_pool:
+ * @reply_free_host_index: tail index in pool to insert free replys
+ * @reply_post_queue_depth: reply post queue depth
+ * @reply_post_free: pool for reply post (64bit descriptor)
+ * @reply_post_free_dma:
+ * @reply_queue_count: number of reply queue's
+ * @reply_queue_list: link list contaning the reply queue info
+ * @reply_post_host_index: head index in the pool where FW completes IO
+ * @delayed_tr_list: target reset link list
+ * @delayed_tr_volume_list: volume target reset link list
+ */
+struct MPT3SAS_ADAPTER {
+       struct list_head list;
+       struct Scsi_Host *shost;
+       u8              id;
+       int             cpu_count;
+       char            name[MPT_NAME_LENGTH];
+       char            tmp_string[MPT_STRING_LENGTH];
+       struct pci_dev  *pdev;
+       Mpi2SystemInterfaceRegs_t __iomem *chip;
+       resource_size_t chip_phys;
+       int             logging_level;
+       int             fwfault_debug;
+       u8              ir_firmware;
+       int             bars;
+       u8              mask_interrupts;
+
+       /* fw fault handler */
+       char            fault_reset_work_q_name[20];
+       struct workqueue_struct *fault_reset_work_q;
+       struct delayed_work fault_reset_work;
+
+       /* fw event handler */
+       char            firmware_event_name[20];
+       struct workqueue_struct *firmware_event_thread;
+       spinlock_t      fw_event_lock;
+       struct list_head fw_event_list;
+
+        /* misc flags */
+       int             aen_event_read_flag;
+       u8              broadcast_aen_busy;
+       u16             broadcast_aen_pending;
+       u8              shost_recovery;
+
+       struct mutex    reset_in_progress_mutex;
+       spinlock_t      ioc_reset_in_progress_lock;
+       u8              ioc_link_reset_in_progress;
+       u8              ioc_reset_in_progress_status;
+
+       u8              ignore_loginfos;
+       u8              remove_host;
+       u8              pci_error_recovery;
+       u8              wait_for_discovery_to_complete;
+       u8              is_driver_loading;
+       u8              port_enable_failed;
+       u8              start_scan;
+       u16             start_scan_failed;
+
+       u8              msix_enable;
+       u16             msix_vector_count;
+       u8              *cpu_msix_table;
+       u16             cpu_msix_table_sz;
+       u32             ioc_reset_count;
+       MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
+
+       /* internal commands, callback index */
+       u8              scsi_io_cb_idx;
+       u8              tm_cb_idx;
+       u8              transport_cb_idx;
+       u8              scsih_cb_idx;
+       u8              ctl_cb_idx;
+       u8              base_cb_idx;
+       u8              port_enable_cb_idx;
+       u8              config_cb_idx;
+       u8              tm_tr_cb_idx;
+       u8              tm_tr_volume_cb_idx;
+       u8              tm_sas_control_cb_idx;
+       struct _internal_cmd base_cmds;
+       struct _internal_cmd port_enable_cmds;
+       struct _internal_cmd transport_cmds;
+       struct _internal_cmd scsih_cmds;
+       struct _internal_cmd tm_cmds;
+       struct _internal_cmd ctl_cmds;
+       struct _internal_cmd config_cmds;
+
+       MPT_ADD_SGE     base_add_sg_single;
+
+       /* function ptr for either IEEE or MPI sg elements */
+       MPT_BUILD_SG_SCMD build_sg_scmd;
+       MPT_BUILD_SG    build_sg;
+       MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge;
+       u8              mpi25;
+       u16             sge_size_ieee;
+
+       /* function ptr for MPI sg elements only */
+       MPT_BUILD_SG    build_sg_mpi;
+       MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge_mpi;
+
+       /* event log */
+       u32             event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+       u32             event_context;
+       void            *event_log;
+       u32             event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+
+       /* static config pages */
+       struct mpt3sas_facts facts;
+       struct mpt3sas_port_facts *pfacts;
+       Mpi2ManufacturingPage0_t manu_pg0;
+       struct Mpi2ManufacturingPage10_t manu_pg10;
+       struct Mpi2ManufacturingPage11_t manu_pg11;
+       Mpi2BiosPage2_t bios_pg2;
+       Mpi2BiosPage3_t bios_pg3;
+       Mpi2IOCPage8_t ioc_pg8;
+       Mpi2IOUnitPage0_t iounit_pg0;
+       Mpi2IOUnitPage1_t iounit_pg1;
+
+       struct _boot_device req_boot_device;
+       struct _boot_device req_alt_boot_device;
+       struct _boot_device current_boot_device;
+
+       /* sas hba, expander, and device list */
+       struct _sas_node sas_hba;
+       struct list_head sas_expander_list;
+       spinlock_t      sas_node_lock;
+       struct list_head sas_device_list;
+       struct list_head sas_device_init_list;
+       spinlock_t      sas_device_lock;
+       struct list_head raid_device_list;
+       spinlock_t      raid_device_lock;
+       u8              io_missing_delay;
+       u16             device_missing_delay;
+       int             sas_id;
+
+       void            *blocking_handles;
+       void            *pd_handles;
+       u16             pd_handles_sz;
+
+       /* config page */
+       u16             config_page_sz;
+       void            *config_page;
+       dma_addr_t      config_page_dma;
+
+       /* scsiio request */
+       u16             hba_queue_depth;
+       u16             sge_size;
+       u16             scsiio_depth;
+       u16             request_sz;
+       u8              *request;
+       dma_addr_t      request_dma;
+       u32             request_dma_sz;
+       struct scsiio_tracker *scsi_lookup;
+       ulong           scsi_lookup_pages;
+       spinlock_t      scsi_lookup_lock;
+       struct list_head free_list;
+       int             pending_io_count;
+       wait_queue_head_t reset_wq;
+
+       /* chain */
+       struct chain_tracker *chain_lookup;
+       struct list_head free_chain_list;
+       struct dma_pool *chain_dma_pool;
+       ulong           chain_pages;
+       u16             max_sges_in_main_message;
+       u16             max_sges_in_chain_message;
+       u16             chains_needed_per_io;
+       u32             chain_depth;
+
+       /* hi-priority queue */
+       u16             hi_priority_smid;
+       u8              *hi_priority;
+       dma_addr_t      hi_priority_dma;
+       u16             hi_priority_depth;
+       struct request_tracker *hpr_lookup;
+       struct list_head hpr_free_list;
+
+       /* internal queue */
+       u16             internal_smid;
+       u8              *internal;
+       dma_addr_t      internal_dma;
+       u16             internal_depth;
+       struct request_tracker *internal_lookup;
+       struct list_head internal_free_list;
+
+       /* sense */
+       u8              *sense;
+       dma_addr_t      sense_dma;
+       struct dma_pool *sense_dma_pool;
+
+       /* reply */
+       u16             reply_sz;
+       u8              *reply;
+       dma_addr_t      reply_dma;
+       u32             reply_dma_max_address;
+       u32             reply_dma_min_address;
+       struct dma_pool *reply_dma_pool;
+
+       /* reply free queue */
+       u16             reply_free_queue_depth;
+       __le32          *reply_free;
+       dma_addr_t      reply_free_dma;
+       struct dma_pool *reply_free_dma_pool;
+       u32             reply_free_host_index;
+
+       /* reply post queue */
+       u16             reply_post_queue_depth;
+       Mpi2ReplyDescriptorsUnion_t *reply_post_free;
+       dma_addr_t      reply_post_free_dma;
+       struct dma_pool *reply_post_free_dma_pool;
+       u8              reply_queue_count;
+       struct list_head reply_queue_list;
+
+       struct list_head delayed_tr_list;
+       struct list_head delayed_tr_volume_list;
+
+       /* diag buffer support */
+       u8              *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
+       u32             diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
+       dma_addr_t      diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
+       u8              diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
+       u32             unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
+       u32             product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
+       u32             diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
+       u32             ring_buffer_offset;
+       u32             ring_buffer_sz;
+       spinlock_t      diag_trigger_lock;
+       u8              diag_trigger_active;
+       struct SL_WH_MASTER_TRIGGER_T diag_trigger_master;
+       struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
+       struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
+       struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi;
+};
+
+typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply);
+
+
+/* base shared API */
+extern struct list_head mpt3sas_ioc_list;
+void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc);
+
+int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc);
+int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc);
+int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
+       enum reset_type type);
+
+void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void *mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+__le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc,
+       u16 smid);
+void mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc);
+
+/* hi-priority queue */
+u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
+u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
+       struct scsi_cmnd *scmd);
+
+u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
+void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       u16 handle);
+void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       u16 handle);
+void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void mpt3sas_base_initialize_callback_handler(void);
+u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func);
+void mpt3sas_base_release_callback_handler(u8 cb_idx);
+
+u8 mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply);
+u8 mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       u8 msix_index, u32 reply);
+void *mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc,
+       u32 phys_addr);
+
+u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked);
+
+void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code);
+int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2SasIoUnitControlReply_t *mpi_reply,
+       Mpi2SasIoUnitControlRequest_t *mpi_request);
+int mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
+
+void mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc,
+       u32 *event_type);
+
+void mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc);
+
+void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
+       u16 device_missing_delay, u8 io_missing_delay);
+
+int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
+
+
+/* scsih shared API */
+u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
+       u32 reply);
+void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
+
+int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       uint channel, uint id, uint lun, u8 type, u16 smid_task,
+       ulong timeout, unsigned long serial_number,  enum mutex_type m_type);
+void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
+void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
+void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address);
+
+struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
+       struct MPT3SAS_ADAPTER *ioc, u16 handle);
+struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address(
+       struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address(
+       struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+
+void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
+
+/* config shared API */
+u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply);
+int mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc,
+       u8 *num_phys);
+int mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
+int mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
+       u16 sz);
+int mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply,
+       struct Mpi2ManufacturingPage10_t *config_page);
+
+int mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply,
+       struct Mpi2ManufacturingPage11_t  *config_page);
+int mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply,
+       struct Mpi2ManufacturingPage11_t *config_page);
+
+int mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2BiosPage2_t *config_page);
+int mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2BiosPage3_t *config_page);
+int mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2IOUnitPage0_t *config_page);
+int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
+       u32 form, u32 handle);
+int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
+       u32 form, u32 handle);
+int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
+       u16 sz);
+int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2IOUnitPage1_t *config_page);
+int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2IOUnitPage1_t *config_page);
+int mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
+       u16 sz);
+int mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
+       u16 sz);
+int mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2IOCPage8_t *config_page);
+int mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage0_t *config_page,
+       u32 form, u32 handle);
+int mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage1_t *config_page,
+       u32 phy_number, u16 handle);
+int mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasEnclosurePage0_t *config_page,
+       u32 form, u32 handle);
+int mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number);
+int mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number);
+int mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
+       u32 handle);
+int mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       u8 *num_pds);
+int mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
+       u32 handle, u16 sz);
+int mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page,
+       u32 form, u32 form_specific);
+int mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
+       u16 *volume_handle);
+int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc,
+       u16 volume_handle, u64 *wwid);
+
+/* ctl shared API */
+extern struct device_attribute *mpt3sas_host_attrs[];
+extern struct device_attribute *mpt3sas_dev_attrs[];
+void mpt3sas_ctl_init(void);
+void mpt3sas_ctl_exit(void);
+u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply);
+void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
+u8 mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc,
+       u8 msix_index, u32 reply);
+void mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventNotificationReply_t *mpi_reply);
+
+void mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc,
+       u8 bits_to_regsiter);
+int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
+       u8 *issue_reset);
+
+/* transport shared API */
+u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply);
+struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc,
+       u16 handle, u64 sas_address);
+void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+       u64 sas_address_parent);
+int mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
+       *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
+int mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_phy *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
+       struct device *parent_dev);
+void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
+extern struct sas_function_template mpt3sas_transport_functions;
+extern struct scsi_transport_template *mpt3sas_transport_template;
+extern int scsi_internal_device_block(struct scsi_device *sdev);
+extern int scsi_internal_device_unblock(struct scsi_device *sdev,
+                               enum scsi_device_state new_state);
+/* trigger data externs */
+void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
+       struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
+void mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
+       struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
+void mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc,
+       u32 tigger_bitmask);
+void mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
+       u16 log_entry_qualifier);
+void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key,
+       u8 asc, u8 ascq);
+void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status,
+       u32 loginfo);
+#endif /* MPT3SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
new file mode 100644 (file)
index 0000000..ce7e59b
--- /dev/null
@@ -0,0 +1,1650 @@
+/*
+ * This module provides common API for accessing firmware configuration pages
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include "mpt3sas_base.h"
+
+/* local definitions */
+
+/* Timeout for config page request (in seconds) */
+#define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
+
+/* Common sgl flags for READING a config page. */
+#define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
+       MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
+       | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
+
+/* Common sgl flags for WRITING a config page. */
+#define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
+       MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
+       | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
+       << MPI2_SGE_FLAGS_SHIFT)
+
+/**
+ * struct config_request - obtain dma memory via routine
+ * @sz: size
+ * @page: virt pointer
+ * @page_dma: phys pointer
+ *
+ */
+struct config_request {
+       u16                     sz;
+       void                    *page;
+       dma_addr_t              page_dma;
+};
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _config_display_some_debug - debug routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @calling_function_name: string pass from calling function
+ * @mpi_reply: reply message frame
+ * Context: none.
+ *
+ * Function for displaying debug info helpful when debugging issues
+ * in this module.
+ */
+static void
+_config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
+{
+       Mpi2ConfigRequest_t *mpi_request;
+       char *desc = NULL;
+
+       if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+               return;
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
+       case MPI2_CONFIG_PAGETYPE_IO_UNIT:
+               desc = "io_unit";
+               break;
+       case MPI2_CONFIG_PAGETYPE_IOC:
+               desc = "ioc";
+               break;
+       case MPI2_CONFIG_PAGETYPE_BIOS:
+               desc = "bios";
+               break;
+       case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
+               desc = "raid_volume";
+               break;
+       case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
+               desc = "manufaucturing";
+               break;
+       case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
+               desc = "physdisk";
+               break;
+       case MPI2_CONFIG_PAGETYPE_EXTENDED:
+               switch (mpi_request->ExtPageType) {
+               case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
+                       desc = "sas_io_unit";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
+                       desc = "sas_expander";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
+                       desc = "sas_device";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
+                       desc = "sas_phy";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_LOG:
+                       desc = "log";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
+                       desc = "enclosure";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
+                       desc = "raid_config";
+                       break;
+               case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
+                       desc = "driver_mappping";
+                       break;
+               }
+               break;
+       }
+
+       if (!desc)
+               return;
+
+       pr_info(MPT3SAS_FMT
+               "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
+               ioc->name, calling_function_name, desc,
+           mpi_request->Header.PageNumber, mpi_request->Action,
+           le32_to_cpu(mpi_request->PageAddress), smid);
+
+       if (!mpi_reply)
+               return;
+
+       if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
+               pr_info(MPT3SAS_FMT
+                   "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+                   le32_to_cpu(mpi_reply->IOCLogInfo));
+}
+#endif
+
+/**
+ * _config_alloc_config_dma_memory - obtain physical memory
+ * @ioc: per adapter object
+ * @mem: struct config_request
+ *
+ * A wrapper for obtaining dma-able memory for config page request.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
+       struct config_request *mem)
+{
+       int r = 0;
+
+       if (mem->sz > ioc->config_page_sz) {
+               mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
+                   &mem->page_dma, GFP_KERNEL);
+               if (!mem->page) {
+                       pr_err(MPT3SAS_FMT
+                               "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
+                           ioc->name, __func__, mem->sz);
+                       r = -ENOMEM;
+               }
+       } else { /* use tmp buffer if less than 512 bytes */
+               mem->page = ioc->config_page;
+               mem->page_dma = ioc->config_page_dma;
+       }
+       return r;
+}
+
+/**
+ * _config_free_config_dma_memory - wrapper to free the memory
+ * @ioc: per adapter object
+ * @mem: struct config_request
+ *
+ * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static void
+_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
+       struct config_request *mem)
+{
+       if (mem->sz > ioc->config_page_sz)
+               dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
+                   mem->page_dma);
+}
+
+/**
+ * mpt3sas_config_done - config page completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: none.
+ *
+ * The callback handler when using _config_request.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+
+       if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+       if (ioc->config_cmds.smid != smid)
+               return 1;
+       ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
+       mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (mpi_reply) {
+               ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
+               memcpy(ioc->config_cmds.reply, mpi_reply,
+                   mpi_reply->MsgLength*4);
+       }
+       ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
+#endif
+       ioc->config_cmds.smid = USHRT_MAX;
+       complete(&ioc->config_cmds.done);
+       return 1;
+}
+
+/**
+ * _config_request - main routine for sending config page requests
+ * @ioc: per adapter object
+ * @mpi_request: request message frame
+ * @mpi_reply: reply mf payload returned from firmware
+ * @timeout: timeout in seconds
+ * @config_page: contents of the config page
+ * @config_page_sz: size of config page
+ * Context: sleep
+ *
+ * A generic API for config page requests to firmware.
+ *
+ * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
+ * this API.
+ *
+ * The callback index is set inside `ioc->config_cb_idx.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
+       *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
+       void *config_page, u16 config_page_sz)
+{
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       Mpi2ConfigRequest_t *config_request;
+       int r;
+       u8 retry_count, issue_host_reset = 0;
+       u16 wait_state_count;
+       struct config_request mem;
+       u32 ioc_status = UINT_MAX;
+
+       mutex_lock(&ioc->config_cmds.mutex);
+       if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
+                   ioc->name, __func__);
+               mutex_unlock(&ioc->config_cmds.mutex);
+               return -EAGAIN;
+       }
+
+       retry_count = 0;
+       memset(&mem, 0, sizeof(struct config_request));
+
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+
+       if (config_page) {
+               mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
+               mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
+               mpi_request->Header.PageType = mpi_reply->Header.PageType;
+               mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
+               mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
+               mpi_request->ExtPageType = mpi_reply->ExtPageType;
+               if (mpi_request->Header.PageLength)
+                       mem.sz = mpi_request->Header.PageLength * 4;
+               else
+                       mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+               r = _config_alloc_config_dma_memory(ioc, &mem);
+               if (r != 0)
+                       goto out;
+               if (mpi_request->Action ==
+                   MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
+                   mpi_request->Action ==
+                   MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
+                       ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
+                           MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
+                           mem.page_dma);
+                       memcpy(mem.page, config_page, min_t(u16, mem.sz,
+                           config_page_sz));
+               } else {
+                       memset(config_page, 0, config_page_sz);
+                       ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
+                           MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
+                       memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
+               }
+       }
+
+ retry_config:
+       if (retry_count) {
+               if (retry_count > 2) { /* attempt only 2 retries */
+                       r = -EFAULT;
+                       goto free_mem;
+               }
+               pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
+                   ioc->name, __func__, retry_count);
+       }
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       ioc->config_cmds.status = MPT3_CMD_NOT_USED;
+                       r = -EFAULT;
+                       goto free_mem;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name, __func__, wait_state_count);
+       }
+       if (wait_state_count)
+               pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+                   ioc->name, __func__);
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               ioc->config_cmds.status = MPT3_CMD_NOT_USED;
+               r = -EAGAIN;
+               goto free_mem;
+       }
+
+       r = 0;
+       memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
+       ioc->config_cmds.status = MPT3_CMD_PENDING;
+       config_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->config_cmds.smid = smid;
+       memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       _config_display_some_debug(ioc, smid, "config_request", NULL);
+#endif
+       init_completion(&ioc->config_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
+           timeout*HZ);
+       if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2ConfigRequest_t)/4);
+               retry_count++;
+               if (ioc->config_cmds.smid == smid)
+                       mpt3sas_base_free_smid(ioc, smid);
+               if ((ioc->shost_recovery) || (ioc->config_cmds.status &
+                   MPT3_CMD_RESET) || ioc->pci_error_recovery)
+                       goto retry_config;
+               issue_host_reset = 1;
+               r = -EFAULT;
+               goto free_mem;
+       }
+
+       if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
+               memcpy(mpi_reply, ioc->config_cmds.reply,
+                   sizeof(Mpi2ConfigReply_t));
+
+               /* Reply Frame Sanity Checks to workaround FW issues */
+               if ((mpi_request->Header.PageType & 0xF) !=
+                   (mpi_reply->Header.PageType & 0xF)) {
+                       _debug_dump_mf(mpi_request, ioc->request_sz/4);
+                       _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+                       panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
+                           " mpi_reply mismatch: Requested PageType(0x%02x)" \
+                           " Reply PageType(0x%02x)\n", \
+                           ioc->name, __func__,
+                           (mpi_request->Header.PageType & 0xF),
+                           (mpi_reply->Header.PageType & 0xF));
+               }
+
+               if (((mpi_request->Header.PageType & 0xF) ==
+                   MPI2_CONFIG_PAGETYPE_EXTENDED) &&
+                   mpi_request->ExtPageType != mpi_reply->ExtPageType) {
+                       _debug_dump_mf(mpi_request, ioc->request_sz/4);
+                       _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+                       panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
+                           " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
+                           " Reply ExtPageType(0x%02x)\n",
+                           ioc->name, __func__, mpi_request->ExtPageType,
+                           mpi_reply->ExtPageType);
+               }
+               ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
+                   & MPI2_IOCSTATUS_MASK;
+       }
+
+       if (retry_count)
+               pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
+                   ioc->name, __func__, retry_count);
+
+       if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
+           config_page && mpi_request->Action ==
+           MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
+               u8 *p = (u8 *)mem.page;
+
+               /* Config Page Sanity Checks to workaround FW issues */
+               if (p) {
+                       if ((mpi_request->Header.PageType & 0xF) !=
+                           (p[3] & 0xF)) {
+                               _debug_dump_mf(mpi_request, ioc->request_sz/4);
+                               _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+                               _debug_dump_config(p, min_t(u16, mem.sz,
+                                   config_page_sz)/4);
+                               panic(KERN_WARNING MPT3SAS_FMT
+                                       "%s: Firmware BUG:" \
+                                   " config page mismatch:"
+                                   " Requested PageType(0x%02x)"
+                                   " Reply PageType(0x%02x)\n",
+                                   ioc->name, __func__,
+                                   (mpi_request->Header.PageType & 0xF),
+                                   (p[3] & 0xF));
+                       }
+
+                       if (((mpi_request->Header.PageType & 0xF) ==
+                           MPI2_CONFIG_PAGETYPE_EXTENDED) &&
+                           (mpi_request->ExtPageType != p[6])) {
+                               _debug_dump_mf(mpi_request, ioc->request_sz/4);
+                               _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+                               _debug_dump_config(p, min_t(u16, mem.sz,
+                                   config_page_sz)/4);
+                               panic(KERN_WARNING MPT3SAS_FMT
+                                       "%s: Firmware BUG:" \
+                                   " config page mismatch:"
+                                   " Requested ExtPageType(0x%02x)"
+                                   " Reply ExtPageType(0x%02x)\n",
+                                   ioc->name, __func__,
+                                   mpi_request->ExtPageType, p[6]);
+                       }
+               }
+               memcpy(config_page, mem.page, min_t(u16, mem.sz,
+                   config_page_sz));
+       }
+
+ free_mem:
+       if (config_page)
+               _config_free_config_dma_memory(ioc, &mem);
+ out:
+       ioc->config_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_unlock(&ioc->config_cmds.mutex);
+
+       if (issue_host_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
+       u16 sz)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+       mpi_request.Header.PageNumber = 7;
+       mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sz);
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply,
+       struct Mpi2ManufacturingPage10_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+       mpi_request.Header.PageNumber = 10;
+       mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply,
+       struct Mpi2ManufacturingPage11_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+       mpi_request.Header.PageNumber = 11;
+       mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply,
+       struct Mpi2ManufacturingPage11_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+       mpi_request.Header.PageNumber = 11;
+       mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_bios_pg2 - obtain bios page 2
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
+       mpi_request.Header.PageNumber = 2;
+       mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_bios_pg3 - obtain bios page 3
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2BiosPage3_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
+       mpi_request.Header.PageNumber = 3;
+       mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_set_iounit_pg1 - set iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
+       mpi_request.Header.PageNumber = 8;
+       mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: device handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
+       u32 form, u32 handle)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+       mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
+       mpi_request.Header.PageNumber = 0;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: device handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
+       u32 form, u32 handle)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+       mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
+       mpi_request.Header.PageNumber = 1;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
+ * @ioc: per adapter object
+ * @num_phys: pointer returned with the number of phys
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+       u16 ioc_status;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasIOUnitPage0_t config_page;
+
+       *num_phys = 0;
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, &mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, &mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
+           sizeof(Mpi2SasIOUnitPage0_t));
+       if (!r) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
+                       *num_phys = config_page.NumPhys;
+       }
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Calling function should call config_get_number_hba_phys prior to
+ * this function, so enough memory is allocated for config_page.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
+       u16 sz)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Calling function should call config_get_number_hba_phys prior to
+ * this function, so enough memory is allocated for config_page.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
+       u16 sz)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Calling function should call config_get_number_hba_phys prior to
+ * this function, so enough memory is allocated for config_page.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
+       u16 sz)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+       _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_expander_pg0 - obtain expander page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: expander handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_expander_pg1 - obtain expander page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @phy_number: phy number
+ * @handle: expander handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
+       u16 handle)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress =
+           cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
+           (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: expander handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_phy_pg0 - obtain phy page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @phy_number: phy number
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress =
+           cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_phy_pg1 - obtain phy page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @phy_number: phy number
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress =
+           cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: volume handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
+       u32 handle)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+       mpi_request.Header.PageNumber = 1;
+       mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
+ * @ioc: per adapter object
+ * @handle: volume handle
+ * @num_pds: returns pds count
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       u8 *num_pds)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       Mpi2RaidVolPage0_t config_page;
+       Mpi2ConfigReply_t mpi_reply;
+       int r;
+       u16 ioc_status;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       *num_pds = 0;
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, &mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress =
+           cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, &mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
+           sizeof(Mpi2RaidVolPage0_t));
+       if (!r) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
+                       *num_pds = config_page.NumPhysDisks;
+       }
+
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: volume handle
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
+       u32 handle, u16 sz)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | handle);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
+ * @form_specific: specific to the form
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+       *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
+       u32 form_specific)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
+       mpi_request.Header.PageNumber = 0;
+       mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.PageAddress = cpu_to_le32(form | form_specific);
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+           sizeof(*config_page));
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
+ * raid components
+ * @ioc: per adapter object
+ * @pd_handle: phys disk handle
+ * @volume_handle: volume handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
+       u16 *volume_handle)
+{
+       Mpi2RaidConfigurationPage0_t *config_page = NULL;
+       Mpi2ConfigRequest_t mpi_request;
+       Mpi2ConfigReply_t mpi_reply;
+       int r, i, config_page_sz;
+       u16 ioc_status;
+       int config_num;
+       u16 element_type;
+       u16 phys_disk_dev_handle;
+
+       *volume_handle = 0;
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
+       mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
+       mpi_request.Header.PageNumber = 0;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, &mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
+       config_page = kmalloc(config_page_sz, GFP_KERNEL);
+       if (!config_page) {
+               r = -1;
+               goto out;
+       }
+
+       config_num = 0xff;
+       while (1) {
+               mpi_request.PageAddress = cpu_to_le32(config_num +
+                   MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
+               r = _config_request(ioc, &mpi_request, &mpi_reply,
+                   MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+                   config_page_sz);
+               if (r)
+                       goto out;
+               r = -1;
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+                       goto out;
+               for (i = 0; i < config_page->NumElements; i++) {
+                       element_type = le16_to_cpu(config_page->
+                           ConfigElement[i].ElementFlags) &
+                           MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
+                       if (element_type ==
+                           MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
+                           element_type ==
+                           MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
+                               phys_disk_dev_handle =
+                                   le16_to_cpu(config_page->ConfigElement[i].
+                                   PhysDiskDevHandle);
+                               if (phys_disk_dev_handle == pd_handle) {
+                                       *volume_handle =
+                                           le16_to_cpu(config_page->
+                                           ConfigElement[i].VolDevHandle);
+                                       r = 0;
+                                       goto out;
+                               }
+                       } else if (element_type ==
+                           MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
+                               *volume_handle = 0;
+                               r = 0;
+                               goto out;
+                       }
+               }
+               config_num = config_page->ConfigNum;
+       }
+ out:
+       kfree(config_page);
+       return r;
+}
+
+/**
+ * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
+ * @ioc: per adapter object
+ * @volume_handle: volume handle
+ * @wwid: volume wwid
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
+       u64 *wwid)
+{
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2RaidVolPage1_t raid_vol_pg1;
+
+       *wwid = 0;
+       if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+           &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
+           volume_handle))) {
+               *wwid = le64_to_cpu(raid_vol_pg1.WWID);
+               return 0;
+       } else
+               return -1;
+}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
new file mode 100644 (file)
index 0000000..8af944d
--- /dev/null
@@ -0,0 +1,3297 @@
+/*
+ * Management Module Support for MPT (Message Passing Technology) based
+ * controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/compat.h>
+#include <linux/poll.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include "mpt3sas_base.h"
+#include "mpt3sas_ctl.h"
+
+
+static struct fasync_struct *async_queue;
+static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
+
+
+/**
+ * enum block_state - blocking state
+ * @NON_BLOCKING: non blocking
+ * @BLOCKING: blocking
+ *
+ * These states are for ioctls that need to wait for a response
+ * from firmware, so they probably require sleep.
+ */
+enum block_state {
+       NON_BLOCKING,
+       BLOCKING,
+};
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _ctl_sas_device_find_by_handle - sas device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for sas_device based on sas_address, then return sas_device
+ * object.
+ */
+static struct _sas_device *
+_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _sas_device *sas_device, *r;
+
+       r = NULL;
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+               if (sas_device->handle != handle)
+                       continue;
+               r = sas_device;
+               goto out;
+       }
+
+ out:
+       return r;
+}
+
+/**
+ * _ctl_display_some_debug - debug routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @calling_function_name: string pass from calling function
+ * @mpi_reply: reply message frame
+ * Context: none.
+ *
+ * Function for displaying debug info helpful when debugging issues
+ * in this module.
+ */
+static void
+_ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
+{
+       Mpi2ConfigRequest_t *mpi_request;
+       char *desc = NULL;
+
+       if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
+               return;
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       switch (mpi_request->Function) {
+       case MPI2_FUNCTION_SCSI_IO_REQUEST:
+       {
+               Mpi2SCSIIORequest_t *scsi_request =
+                   (Mpi2SCSIIORequest_t *)mpi_request;
+
+               snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
+                   "scsi_io, cmd(0x%02x), cdb_len(%d)",
+                   scsi_request->CDB.CDB32[0],
+                   le16_to_cpu(scsi_request->IoFlags) & 0xF);
+               desc = ioc->tmp_string;
+               break;
+       }
+       case MPI2_FUNCTION_SCSI_TASK_MGMT:
+               desc = "task_mgmt";
+               break;
+       case MPI2_FUNCTION_IOC_INIT:
+               desc = "ioc_init";
+               break;
+       case MPI2_FUNCTION_IOC_FACTS:
+               desc = "ioc_facts";
+               break;
+       case MPI2_FUNCTION_CONFIG:
+       {
+               Mpi2ConfigRequest_t *config_request =
+                   (Mpi2ConfigRequest_t *)mpi_request;
+
+               snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
+                   "config, type(0x%02x), ext_type(0x%02x), number(%d)",
+                   (config_request->Header.PageType &
+                    MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
+                   config_request->Header.PageNumber);
+               desc = ioc->tmp_string;
+               break;
+       }
+       case MPI2_FUNCTION_PORT_FACTS:
+               desc = "port_facts";
+               break;
+       case MPI2_FUNCTION_PORT_ENABLE:
+               desc = "port_enable";
+               break;
+       case MPI2_FUNCTION_EVENT_NOTIFICATION:
+               desc = "event_notification";
+               break;
+       case MPI2_FUNCTION_FW_DOWNLOAD:
+               desc = "fw_download";
+               break;
+       case MPI2_FUNCTION_FW_UPLOAD:
+               desc = "fw_upload";
+               break;
+       case MPI2_FUNCTION_RAID_ACTION:
+               desc = "raid_action";
+               break;
+       case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
+       {
+               Mpi2SCSIIORequest_t *scsi_request =
+                   (Mpi2SCSIIORequest_t *)mpi_request;
+
+               snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
+                   "raid_pass, cmd(0x%02x), cdb_len(%d)",
+                   scsi_request->CDB.CDB32[0],
+                   le16_to_cpu(scsi_request->IoFlags) & 0xF);
+               desc = ioc->tmp_string;
+               break;
+       }
+       case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
+               desc = "sas_iounit_cntl";
+               break;
+       case MPI2_FUNCTION_SATA_PASSTHROUGH:
+               desc = "sata_pass";
+               break;
+       case MPI2_FUNCTION_DIAG_BUFFER_POST:
+               desc = "diag_buffer_post";
+               break;
+       case MPI2_FUNCTION_DIAG_RELEASE:
+               desc = "diag_release";
+               break;
+       case MPI2_FUNCTION_SMP_PASSTHROUGH:
+               desc = "smp_passthrough";
+               break;
+       }
+
+       if (!desc)
+               return;
+
+       pr_info(MPT3SAS_FMT "%s: %s, smid(%d)\n",
+           ioc->name, calling_function_name, desc, smid);
+
+       if (!mpi_reply)
+               return;
+
+       if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
+               pr_info(MPT3SAS_FMT
+                   "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+                   le32_to_cpu(mpi_reply->IOCLogInfo));
+
+       if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+           mpi_request->Function ==
+           MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+               Mpi2SCSIIOReply_t *scsi_reply =
+                   (Mpi2SCSIIOReply_t *)mpi_reply;
+               struct _sas_device *sas_device = NULL;
+               unsigned long flags;
+
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = _ctl_sas_device_find_by_handle(ioc,
+                   le16_to_cpu(scsi_reply->DevHandle));
+               if (sas_device) {
+                       pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), phy(%d)\n",
+                               ioc->name, (unsigned long long)
+                           sas_device->sas_address, sas_device->phy);
+                       pr_warn(MPT3SAS_FMT
+                           "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
+                           ioc->name, (unsigned long long)
+                           sas_device->enclosure_logical_id, sas_device->slot);
+               }
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
+                       pr_info(MPT3SAS_FMT
+                           "\tscsi_state(0x%02x), scsi_status"
+                           "(0x%02x)\n", ioc->name,
+                           scsi_reply->SCSIState,
+                           scsi_reply->SCSIStatus);
+       }
+}
+
+#endif
+
+/**
+ * mpt3sas_ctl_done - ctl module completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: none.
+ *
+ * The callback handler when using ioc->ctl_cb_idx.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+       Mpi2SCSIIOReply_t *scsiio_reply;
+       const void *sense_data;
+       u32 sz;
+
+       if (ioc->ctl_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+       if (ioc->ctl_cmds.smid != smid)
+               return 1;
+       ioc->ctl_cmds.status |= MPT3_CMD_COMPLETE;
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (mpi_reply) {
+               memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+               ioc->ctl_cmds.status |= MPT3_CMD_REPLY_VALID;
+               /* get sense data */
+               if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+                   mpi_reply->Function ==
+                   MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+                       scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply;
+                       if (scsiio_reply->SCSIState &
+                           MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+                               sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
+                                   le32_to_cpu(scsiio_reply->SenseCount));
+                               sense_data = mpt3sas_base_get_sense_buffer(ioc,
+                                   smid);
+                               memcpy(ioc->ctl_cmds.sense, sense_data, sz);
+                       }
+               }
+       }
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
+#endif
+       ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING;
+       complete(&ioc->ctl_cmds.done);
+       return 1;
+}
+
+/**
+ * _ctl_check_event_type - determines when an event needs logging
+ * @ioc: per adapter object
+ * @event: firmware event
+ *
+ * The bitmask in ioc->event_type[] indicates which events should be
+ * be saved in the driver event_log.  This bitmask is set by application.
+ *
+ * Returns 1 when event should be captured, or zero means no match.
+ */
+static int
+_ctl_check_event_type(struct MPT3SAS_ADAPTER *ioc, u16 event)
+{
+       u16 i;
+       u32 desired_event;
+
+       if (event >= 128 || !event || !ioc->event_log)
+               return 0;
+
+       desired_event = (1 << (event % 32));
+       if (!desired_event)
+               desired_event = 1;
+       i = event / 32;
+       return desired_event & ioc->event_type[i];
+}
+
+/**
+ * mpt3sas_ctl_add_to_event_log - add event
+ * @ioc: per adapter object
+ * @mpi_reply: reply message frame
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventNotificationReply_t *mpi_reply)
+{
+       struct MPT3_IOCTL_EVENTS *event_log;
+       u16 event;
+       int i;
+       u32 sz, event_data_sz;
+       u8 send_aen = 0;
+
+       if (!ioc->event_log)
+               return;
+
+       event = le16_to_cpu(mpi_reply->Event);
+
+       if (_ctl_check_event_type(ioc, event)) {
+
+               /* insert entry into circular event_log */
+               i = ioc->event_context % MPT3SAS_CTL_EVENT_LOG_SIZE;
+               event_log = ioc->event_log;
+               event_log[i].event = event;
+               event_log[i].context = ioc->event_context++;
+
+               event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
+               sz = min_t(u32, event_data_sz, MPT3_EVENT_DATA_SIZE);
+               memset(event_log[i].data, 0, MPT3_EVENT_DATA_SIZE);
+               memcpy(event_log[i].data, mpi_reply->EventData, sz);
+               send_aen = 1;
+       }
+
+       /* This aen_event_read_flag flag is set until the
+        * application has read the event log.
+        * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
+        */
+       if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
+           (send_aen && !ioc->aen_event_read_flag)) {
+               ioc->aen_event_read_flag = 1;
+               wake_up_interruptible(&ctl_poll_wait);
+               if (async_queue)
+                       kill_fasync(&async_queue, SIGIO, POLL_IN);
+       }
+}
+
+/**
+ * mpt3sas_ctl_event_callback - firmware event handler (called at ISR time)
+ * @ioc: per adapter object
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt.
+ *
+ * This function merely adds a new work task into ioc->firmware_event_thread.
+ * The tasks are worked from _firmware_event_work in user context.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
+       u32 reply)
+{
+       Mpi2EventNotificationReply_t *mpi_reply;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
+       return 1;
+}
+
+/**
+ * _ctl_verify_adapter - validates ioc_number passed from application
+ * @ioc: per adapter object
+ * @iocpp: The ioc pointer is returned in this.
+ *
+ * Return (-1) means error, else ioc_number.
+ */
+static int
+_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp)
+{
+       struct MPT3SAS_ADAPTER *ioc;
+
+       list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
+               if (ioc->id != ioc_number)
+                       continue;
+               *iocpp = ioc;
+               return ioc_number;
+       }
+       *iocpp = NULL;
+       return -1;
+}
+
+/**
+ * mpt3sas_ctl_reset_handler - reset callback handler (for ctl)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
+ * MPT3_IOC_DONE_RESET
+ */
+void
+mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
+{
+       int i;
+       u8 issue_reset;
+
+       switch (reset_phase) {
+       case MPT3_IOC_PRE_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
+               for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+                       if (!(ioc->diag_buffer_status[i] &
+                           MPT3_DIAG_BUFFER_IS_REGISTERED))
+                               continue;
+                       if ((ioc->diag_buffer_status[i] &
+                           MPT3_DIAG_BUFFER_IS_RELEASED))
+                               continue;
+                       mpt3sas_send_diag_release(ioc, i, &issue_reset);
+               }
+               break;
+       case MPT3_IOC_AFTER_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
+               if (ioc->ctl_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->ctl_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
+                       complete(&ioc->ctl_cmds.done);
+               }
+               break;
+       case MPT3_IOC_DONE_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
+
+               for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+                       if (!(ioc->diag_buffer_status[i] &
+                           MPT3_DIAG_BUFFER_IS_REGISTERED))
+                               continue;
+                       if ((ioc->diag_buffer_status[i] &
+                           MPT3_DIAG_BUFFER_IS_RELEASED))
+                               continue;
+                       ioc->diag_buffer_status[i] |=
+                           MPT3_DIAG_BUFFER_IS_DIAG_RESET;
+               }
+               break;
+       }
+}
+
+/**
+ * _ctl_fasync -
+ * @fd -
+ * @filep -
+ * @mode -
+ *
+ * Called when application request fasyn callback handler.
+ */
+static int
+_ctl_fasync(int fd, struct file *filep, int mode)
+{
+       return fasync_helper(fd, filep, mode, &async_queue);
+}
+
+/**
+ * _ctl_release -
+ * @inode -
+ * @filep -
+ *
+ * Called when application releases the fasyn callback handler.
+ */
+static int
+_ctl_release(struct inode *inode, struct file *filep)
+{
+       return fasync_helper(-1, filep, 0, &async_queue);
+}
+
+/**
+ * _ctl_poll -
+ * @file -
+ * @wait -
+ *
+ */
+static unsigned int
+_ctl_poll(struct file *filep, poll_table *wait)
+{
+       struct MPT3SAS_ADAPTER *ioc;
+
+       poll_wait(filep, &ctl_poll_wait, wait);
+
+       list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
+               if (ioc->aen_event_read_flag)
+                       return POLLIN | POLLRDNORM;
+       }
+       return 0;
+}
+
+/**
+ * _ctl_set_task_mid - assign an active smid to tm request
+ * @ioc: per adapter object
+ * @karg - (struct mpt3_ioctl_command)
+ * @tm_request - pointer to mf from user space
+ *
+ * Returns 0 when an smid if found, else fail.
+ * during failure, the reply frame is filled.
+ */
+static int
+_ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg,
+       Mpi2SCSITaskManagementRequest_t *tm_request)
+{
+       u8 found = 0;
+       u16 i;
+       u16 handle;
+       struct scsi_cmnd *scmd;
+       struct MPT3SAS_DEVICE *priv_data;
+       unsigned long flags;
+       Mpi2SCSITaskManagementReply_t *tm_reply;
+       u32 sz;
+       u32 lun;
+       char *desc = NULL;
+
+       if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+               desc = "abort_task";
+       else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
+               desc = "query_task";
+       else
+               return 0;
+
+       lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
+
+       handle = le16_to_cpu(tm_request->DevHandle);
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       for (i = ioc->scsiio_depth; i && !found; i--) {
+               scmd = ioc->scsi_lookup[i - 1].scmd;
+               if (scmd == NULL || scmd->device == NULL ||
+                   scmd->device->hostdata == NULL)
+                       continue;
+               if (lun != scmd->device->lun)
+                       continue;
+               priv_data = scmd->device->hostdata;
+               if (priv_data->sas_target == NULL)
+                       continue;
+               if (priv_data->sas_target->handle != handle)
+                       continue;
+               tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
+               found = 1;
+       }
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+       if (!found) {
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: handle(0x%04x), lun(%d), no active mid!!\n",
+                       ioc->name,
+                   desc, le16_to_cpu(tm_request->DevHandle), lun));
+               tm_reply = ioc->ctl_cmds.reply;
+               tm_reply->DevHandle = tm_request->DevHandle;
+               tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+               tm_reply->TaskType = tm_request->TaskType;
+               tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
+               tm_reply->VP_ID = tm_request->VP_ID;
+               tm_reply->VF_ID = tm_request->VF_ID;
+               sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
+               if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
+                   sz))
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+               return 1;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name,
+           desc, le16_to_cpu(tm_request->DevHandle), lun,
+            le16_to_cpu(tm_request->TaskMID)));
+       return 0;
+}
+
+/**
+ * _ctl_do_mpt_command - main handler for MPT3COMMAND opcode
+ * @ioc: per adapter object
+ * @karg - (struct mpt3_ioctl_command)
+ * @mf - pointer to mf in user space
+ */
+static long
+_ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
+       void __user *mf)
+{
+       MPI2RequestHeader_t *mpi_request = NULL, *request;
+       MPI2DefaultReply_t *mpi_reply;
+       u32 ioc_state;
+       u16 ioc_status;
+       u16 smid;
+       unsigned long timeout, timeleft;
+       u8 issue_reset;
+       u32 sz;
+       void *psge;
+       void *data_out = NULL;
+       dma_addr_t data_out_dma = 0;
+       size_t data_out_sz = 0;
+       void *data_in = NULL;
+       dma_addr_t data_in_dma = 0;
+       size_t data_in_sz = 0;
+       long ret;
+       u16 wait_state_count;
+
+       issue_reset = 0;
+
+       if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
+                   ioc->name, __func__);
+               ret = -EAGAIN;
+               goto out;
+       }
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       ret = -EFAULT;
+                       goto out;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name,
+                   __func__, wait_state_count);
+       }
+       if (wait_state_count)
+               pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+                   ioc->name, __func__);
+
+       mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL);
+       if (!mpi_request) {
+               pr_err(MPT3SAS_FMT
+                       "%s: failed obtaining a memory for mpi_request\n",
+                       ioc->name, __func__);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* Check for overflow and wraparound */
+       if (karg.data_sge_offset * 4 > ioc->request_sz ||
+           karg.data_sge_offset > (UINT_MAX / 4)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* copy in request message frame from user */
+       if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
+               pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+                   __func__);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
+               smid = mpt3sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx);
+               if (!smid) {
+                       pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                           ioc->name, __func__);
+                       ret = -EAGAIN;
+                       goto out;
+               }
+       } else {
+
+               smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
+               if (!smid) {
+                       pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                           ioc->name, __func__);
+                       ret = -EAGAIN;
+                       goto out;
+               }
+       }
+
+       ret = 0;
+       ioc->ctl_cmds.status = MPT3_CMD_PENDING;
+       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+       request = mpt3sas_base_get_msg_frame(ioc, smid);
+       memcpy(request, mpi_request, karg.data_sge_offset*4);
+       ioc->ctl_cmds.smid = smid;
+       data_out_sz = karg.data_out_size;
+       data_in_sz = karg.data_in_size;
+
+       if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+           mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+               if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
+                   le16_to_cpu(mpi_request->FunctionDependent1) >
+                   ioc->facts.MaxDevHandle) {
+                       ret = -EINVAL;
+                       mpt3sas_base_free_smid(ioc, smid);
+                       goto out;
+               }
+       }
+
+       /* obtain dma-able memory for data transfer */
+       if (data_out_sz) /* WRITE */ {
+               data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
+                   &data_out_dma);
+               if (!data_out) {
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+                       ret = -ENOMEM;
+                       mpt3sas_base_free_smid(ioc, smid);
+                       goto out;
+               }
+               if (copy_from_user(data_out, karg.data_out_buf_ptr,
+                       data_out_sz)) {
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+                       ret =  -EFAULT;
+                       mpt3sas_base_free_smid(ioc, smid);
+                       goto out;
+               }
+       }
+
+       if (data_in_sz) /* READ */ {
+               data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
+                   &data_in_dma);
+               if (!data_in) {
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+                       ret = -ENOMEM;
+                       mpt3sas_base_free_smid(ioc, smid);
+                       goto out;
+               }
+       }
+
+       psge = (void *)request + (karg.data_sge_offset*4);
+
+       /* send command to firmware */
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
+#endif
+
+       init_completion(&ioc->ctl_cmds.done);
+       switch (mpi_request->Function) {
+       case MPI2_FUNCTION_SCSI_IO_REQUEST:
+       case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
+       {
+               Mpi2SCSIIORequest_t *scsiio_request =
+                   (Mpi2SCSIIORequest_t *)request;
+               scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
+               scsiio_request->SenseBufferLowAddress =
+                   mpt3sas_base_get_sense_buffer_dma(ioc, smid);
+               memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
+               ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
+                   data_in_dma, data_in_sz);
+
+               if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
+                       mpt3sas_base_put_smid_scsi_io(ioc, smid,
+                           le16_to_cpu(mpi_request->FunctionDependent1));
+               else
+                       mpt3sas_base_put_smid_default(ioc, smid);
+               break;
+       }
+       case MPI2_FUNCTION_SCSI_TASK_MGMT:
+       {
+               Mpi2SCSITaskManagementRequest_t *tm_request =
+                   (Mpi2SCSITaskManagementRequest_t *)request;
+
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n",
+                       ioc->name,
+                   le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
+
+               if (tm_request->TaskType ==
+                   MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
+                   tm_request->TaskType ==
+                   MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
+                       if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
+                               mpt3sas_base_free_smid(ioc, smid);
+                               goto out;
+                       }
+               }
+
+               mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu(
+                   tm_request->DevHandle));
+               ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
+                   data_in_dma, data_in_sz);
+               mpt3sas_base_put_smid_hi_priority(ioc, smid);
+               break;
+       }
+       case MPI2_FUNCTION_SMP_PASSTHROUGH:
+       {
+               Mpi2SmpPassthroughRequest_t *smp_request =
+                   (Mpi2SmpPassthroughRequest_t *)mpi_request;
+               u8 *data;
+
+               /* ioc determines which port to use */
+               smp_request->PhysicalPort = 0xFF;
+               if (smp_request->PassthroughFlags &
+                   MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
+                       data = (u8 *)&smp_request->SGL;
+               else {
+                       if (unlikely(data_out == NULL)) {
+                               pr_err("failure at %s:%d/%s()!\n",
+                                   __FILE__, __LINE__, __func__);
+                               mpt3sas_base_free_smid(ioc, smid);
+                               ret = -EINVAL;
+                               goto out;
+                       }
+                       data = data_out;
+               }
+
+               if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
+                       ioc->ioc_link_reset_in_progress = 1;
+                       ioc->ignore_loginfos = 1;
+               }
+               ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
+                   data_in_sz);
+               mpt3sas_base_put_smid_default(ioc, smid);
+               break;
+       }
+       case MPI2_FUNCTION_SATA_PASSTHROUGH:
+       case MPI2_FUNCTION_FW_DOWNLOAD:
+       case MPI2_FUNCTION_FW_UPLOAD:
+       {
+               ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
+                   data_in_sz);
+               mpt3sas_base_put_smid_default(ioc, smid);
+               break;
+       }
+       case MPI2_FUNCTION_TOOLBOX:
+       {
+               Mpi2ToolboxCleanRequest_t *toolbox_request =
+                       (Mpi2ToolboxCleanRequest_t *)mpi_request;
+
+               if (toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) {
+                       ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
+                               data_in_dma, data_in_sz);
+               } else {
+                       ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
+                               data_in_dma, data_in_sz);
+               }
+               mpt3sas_base_put_smid_default(ioc, smid);
+               break;
+       }
+       case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
+       {
+               Mpi2SasIoUnitControlRequest_t *sasiounit_request =
+                   (Mpi2SasIoUnitControlRequest_t *)mpi_request;
+
+               if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
+                   || sasiounit_request->Operation ==
+                   MPI2_SAS_OP_PHY_LINK_RESET) {
+                       ioc->ioc_link_reset_in_progress = 1;
+                       ioc->ignore_loginfos = 1;
+               }
+               /* drop to default case for posting the request */
+       }
+       default:
+               ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
+                   data_in_dma, data_in_sz);
+               mpt3sas_base_put_smid_default(ioc, smid);
+               break;
+       }
+
+       if (karg.timeout < MPT3_IOCTL_DEFAULT_TIMEOUT)
+               timeout = MPT3_IOCTL_DEFAULT_TIMEOUT;
+       else
+               timeout = karg.timeout;
+       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+           timeout*HZ);
+       if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
+               Mpi2SCSITaskManagementRequest_t *tm_request =
+                   (Mpi2SCSITaskManagementRequest_t *)mpi_request;
+               mpt3sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
+                   tm_request->DevHandle));
+               mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
+       } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
+           mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
+               ioc->ioc_link_reset_in_progress) {
+               ioc->ioc_link_reset_in_progress = 0;
+               ioc->ignore_loginfos = 0;
+       }
+       if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
+                   __func__);
+               _debug_dump_mf(mpi_request, karg.data_sge_offset);
+               if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       mpi_reply = ioc->ctl_cmds.reply;
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
+           (ioc->logging_level & MPT_DEBUG_TM)) {
+               Mpi2SCSITaskManagementReply_t *tm_reply =
+                   (Mpi2SCSITaskManagementReply_t *)mpi_reply;
+
+               pr_info(MPT3SAS_FMT "TASK_MGMT: " \
+                   "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
+                   "TerminationCount(0x%08x)\n", ioc->name,
+                   le16_to_cpu(tm_reply->IOCStatus),
+                   le32_to_cpu(tm_reply->IOCLogInfo),
+                   le32_to_cpu(tm_reply->TerminationCount));
+       }
+#endif
+       /* copy out xdata to user */
+       if (data_in_sz) {
+               if (copy_to_user(karg.data_in_buf_ptr, data_in,
+                   data_in_sz)) {
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+                       ret = -ENODATA;
+                       goto out;
+               }
+       }
+
+       /* copy out reply message frame to user */
+       if (karg.max_reply_bytes) {
+               sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
+               if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
+                   sz)) {
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+                       ret = -ENODATA;
+                       goto out;
+               }
+       }
+
+       /* copy out sense to user */
+       if (karg.max_sense_bytes && (mpi_request->Function ==
+           MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
+           MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+               sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
+               if (copy_to_user(karg.sense_data_ptr, ioc->ctl_cmds.sense,
+                   sz)) {
+                       pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                           __LINE__, __func__);
+                       ret = -ENODATA;
+                       goto out;
+               }
+       }
+
+ issue_host_reset:
+       if (issue_reset) {
+               ret = -ENODATA;
+               if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+                   mpi_request->Function ==
+                   MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
+                   mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) {
+                       pr_info(MPT3SAS_FMT "issue target reset: handle = (0x%04x)\n",
+                               ioc->name,
+                               le16_to_cpu(mpi_request->FunctionDependent1));
+                       mpt3sas_halt_firmware(ioc);
+                       mpt3sas_scsih_issue_tm(ioc,
+                           le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
+                           0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30,
+                           0, TM_MUTEX_ON);
+               } else
+                       mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                           FORCE_BIG_HAMMER);
+       }
+
+ out:
+
+       /* free memory associated with sg buffers */
+       if (data_in)
+               pci_free_consistent(ioc->pdev, data_in_sz, data_in,
+                   data_in_dma);
+
+       if (data_out)
+               pci_free_consistent(ioc->pdev, data_out_sz, data_out,
+                   data_out_dma);
+
+       kfree(mpi_request);
+       ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
+       return ret;
+}
+
+/**
+ * _ctl_getiocinfo - main handler for MPT3IOCINFO opcode
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_ioctl_iocinfo karg;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
+           __func__));
+
+       memset(&karg, 0 , sizeof(karg));
+       karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
+       if (ioc->pfacts)
+               karg.port_number = ioc->pfacts[0].PortNumber;
+       karg.hw_rev = ioc->pdev->revision;
+       karg.pci_id = ioc->pdev->device;
+       karg.subsystem_device = ioc->pdev->subsystem_device;
+       karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
+       karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
+       karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
+       karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
+       karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
+       karg.firmware_version = ioc->facts.FWVersion.Word;
+       strcpy(karg.driver_version, MPT3SAS_DRIVER_NAME);
+       strcat(karg.driver_version, "-");
+       strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
+       karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
+
+       if (copy_to_user(arg, &karg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+/**
+ * _ctl_eventquery - main handler for MPT3EVENTQUERY opcode
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_eventquery(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_ioctl_eventquery karg;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
+           __func__));
+
+       karg.event_entries = MPT3SAS_CTL_EVENT_LOG_SIZE;
+       memcpy(karg.event_types, ioc->event_type,
+           MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
+
+       if (copy_to_user(arg, &karg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+/**
+ * _ctl_eventenable - main handler for MPT3EVENTENABLE opcode
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_eventenable(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_ioctl_eventenable karg;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
+           __func__));
+
+       memcpy(ioc->event_type, karg.event_types,
+           MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
+       mpt3sas_base_validate_event_type(ioc, ioc->event_type);
+
+       if (ioc->event_log)
+               return 0;
+       /* initialize event_log */
+       ioc->event_context = 0;
+       ioc->aen_event_read_flag = 0;
+       ioc->event_log = kcalloc(MPT3SAS_CTL_EVENT_LOG_SIZE,
+           sizeof(struct MPT3_IOCTL_EVENTS), GFP_KERNEL);
+       if (!ioc->event_log) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/**
+ * _ctl_eventreport - main handler for MPT3EVENTREPORT opcode
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_eventreport(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_ioctl_eventreport karg;
+       u32 number_bytes, max_events, max;
+       struct mpt3_ioctl_eventreport __user *uarg = arg;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
+           __func__));
+
+       number_bytes = karg.hdr.max_data_size -
+           sizeof(struct mpt3_ioctl_header);
+       max_events = number_bytes/sizeof(struct MPT3_IOCTL_EVENTS);
+       max = min_t(u32, MPT3SAS_CTL_EVENT_LOG_SIZE, max_events);
+
+       /* If fewer than 1 event is requested, there must have
+        * been some type of error.
+        */
+       if (!max || !ioc->event_log)
+               return -ENODATA;
+
+       number_bytes = max * sizeof(struct MPT3_IOCTL_EVENTS);
+       if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       /* reset flag so SIGIO can restart */
+       ioc->aen_event_read_flag = 0;
+       return 0;
+}
+
+/**
+ * _ctl_do_reset - main handler for MPT3HARDRESET opcode
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_ioctl_diag_reset karg;
+       int retval;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery ||
+           ioc->is_driver_loading)
+               return -EAGAIN;
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
+           __func__));
+
+       retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+           FORCE_BIG_HAMMER);
+       pr_info(MPT3SAS_FMT "host reset: %s\n",
+           ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
+       return 0;
+}
+
+/**
+ * _ctl_btdh_search_sas_device - searching for sas device
+ * @ioc: per adapter object
+ * @btdh: btdh ioctl payload
+ */
+static int
+_ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc,
+       struct mpt3_ioctl_btdh_mapping *btdh)
+{
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       int rc = 0;
+
+       if (list_empty(&ioc->sas_device_list))
+               return rc;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+               if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
+                   btdh->handle == sas_device->handle) {
+                       btdh->bus = sas_device->channel;
+                       btdh->id = sas_device->id;
+                       rc = 1;
+                       goto out;
+               } else if (btdh->bus == sas_device->channel && btdh->id ==
+                   sas_device->id && btdh->handle == 0xFFFF) {
+                       btdh->handle = sas_device->handle;
+                       rc = 1;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       return rc;
+}
+
+/**
+ * _ctl_btdh_search_raid_device - searching for raid device
+ * @ioc: per adapter object
+ * @btdh: btdh ioctl payload
+ */
+static int
+_ctl_btdh_search_raid_device(struct MPT3SAS_ADAPTER *ioc,
+       struct mpt3_ioctl_btdh_mapping *btdh)
+{
+       struct _raid_device *raid_device;
+       unsigned long flags;
+       int rc = 0;
+
+       if (list_empty(&ioc->raid_device_list))
+               return rc;
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+               if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
+                   btdh->handle == raid_device->handle) {
+                       btdh->bus = raid_device->channel;
+                       btdh->id = raid_device->id;
+                       rc = 1;
+                       goto out;
+               } else if (btdh->bus == raid_device->channel && btdh->id ==
+                   raid_device->id && btdh->handle == 0xFFFF) {
+                       btdh->handle = raid_device->handle;
+                       rc = 1;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+       return rc;
+}
+
+/**
+ * _ctl_btdh_mapping - main handler for MPT3BTDHMAPPING opcode
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_btdh_mapping(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_ioctl_btdh_mapping karg;
+       int rc;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       rc = _ctl_btdh_search_sas_device(ioc, &karg);
+       if (!rc)
+               _ctl_btdh_search_raid_device(ioc, &karg);
+
+       if (copy_to_user(arg, &karg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+/**
+ * _ctl_diag_capability - return diag buffer capability
+ * @ioc: per adapter object
+ * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
+ *
+ * returns 1 when diag buffer support is enabled in firmware
+ */
+static u8
+_ctl_diag_capability(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type)
+{
+       u8 rc = 0;
+
+       switch (buffer_type) {
+       case MPI2_DIAG_BUF_TYPE_TRACE:
+               if (ioc->facts.IOCCapabilities &
+                   MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
+                       rc = 1;
+               break;
+       case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
+               if (ioc->facts.IOCCapabilities &
+                   MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
+                       rc = 1;
+               break;
+       case MPI2_DIAG_BUF_TYPE_EXTENDED:
+               if (ioc->facts.IOCCapabilities &
+                   MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
+                       rc = 1;
+       }
+
+       return rc;
+}
+
+
+/**
+ * _ctl_diag_register_2 - wrapper for registering diag buffer support
+ * @ioc: per adapter object
+ * @diag_register: the diag_register struct passed in from user space
+ *
+ */
+static long
+_ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
+       struct mpt3_diag_register *diag_register)
+{
+       int rc, i;
+       void *request_data = NULL;
+       dma_addr_t request_data_dma;
+       u32 request_data_sz = 0;
+       Mpi2DiagBufferPostRequest_t *mpi_request;
+       Mpi2DiagBufferPostReply_t *mpi_reply;
+       u8 buffer_type;
+       unsigned long timeleft;
+       u16 smid;
+       u16 ioc_status;
+       u32 ioc_state;
+       u8 issue_reset = 0;
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               pr_err(MPT3SAS_FMT
+                   "%s: failed due to ioc not operational\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       buffer_type = diag_register->buffer_type;
+       if (!_ctl_diag_capability(ioc, buffer_type)) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have capability for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -EPERM;
+       }
+
+       if (ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) {
+               pr_err(MPT3SAS_FMT
+                       "%s: already has a registered buffer for buffer_type(0x%02x)\n",
+                       ioc->name, __func__,
+                   buffer_type);
+               return -EINVAL;
+       }
+
+       if (diag_register->requested_buffer_size % 4)  {
+               pr_err(MPT3SAS_FMT
+                       "%s: the requested_buffer_size is not 4 byte aligned\n",
+                       ioc->name, __func__);
+               return -EINVAL;
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       rc = 0;
+       ioc->ctl_cmds.status = MPT3_CMD_PENDING;
+       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->ctl_cmds.smid = smid;
+
+       request_data = ioc->diag_buffer[buffer_type];
+       request_data_sz = diag_register->requested_buffer_size;
+       ioc->unique_id[buffer_type] = diag_register->unique_id;
+       ioc->diag_buffer_status[buffer_type] = 0;
+       memcpy(ioc->product_specific[buffer_type],
+           diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS);
+       ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
+
+       if (request_data) {
+               request_data_dma = ioc->diag_buffer_dma[buffer_type];
+               if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
+                       pci_free_consistent(ioc->pdev,
+                           ioc->diag_buffer_sz[buffer_type],
+                           request_data, request_data_dma);
+                       request_data = NULL;
+               }
+       }
+
+       if (request_data == NULL) {
+               ioc->diag_buffer_sz[buffer_type] = 0;
+               ioc->diag_buffer_dma[buffer_type] = 0;
+               request_data = pci_alloc_consistent(
+                       ioc->pdev, request_data_sz, &request_data_dma);
+               if (request_data == NULL) {
+                       pr_err(MPT3SAS_FMT "%s: failed allocating memory" \
+                           " for diag buffers, requested size(%d)\n",
+                           ioc->name, __func__, request_data_sz);
+                       mpt3sas_base_free_smid(ioc, smid);
+                       return -ENOMEM;
+               }
+               ioc->diag_buffer[buffer_type] = request_data;
+               ioc->diag_buffer_sz[buffer_type] = request_data_sz;
+               ioc->diag_buffer_dma[buffer_type] = request_data_dma;
+       }
+
+       mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
+       mpi_request->BufferType = diag_register->buffer_type;
+       mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
+       mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
+       mpi_request->BufferLength = cpu_to_le32(request_data_sz);
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: diag_buffer(0x%p), dma(0x%llx), sz(%d)\n",
+               ioc->name, __func__, request_data,
+           (unsigned long long)request_data_dma,
+           le32_to_cpu(mpi_request->BufferLength)));
+
+       for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
+               mpi_request->ProductSpecific[i] =
+                       cpu_to_le32(ioc->product_specific[buffer_type][i]);
+
+       init_completion(&ioc->ctl_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+           MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
+
+       if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
+                   __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2DiagBufferPostRequest_t)/4);
+               if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       /* process the completed Reply Message Frame */
+       if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
+               pr_err(MPT3SAS_FMT "%s: no reply message\n",
+                   ioc->name, __func__);
+               rc = -EFAULT;
+               goto out;
+       }
+
+       mpi_reply = ioc->ctl_cmds.reply;
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+               ioc->diag_buffer_status[buffer_type] |=
+                       MPT3_DIAG_BUFFER_IS_REGISTERED;
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n",
+                   ioc->name, __func__));
+       } else {
+               pr_info(MPT3SAS_FMT
+                       "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
+                       ioc->name, __func__,
+                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
+               rc = -EFAULT;
+       }
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+
+ out:
+
+       if (rc && request_data)
+               pci_free_consistent(ioc->pdev, request_data_sz,
+                   request_data, request_data_dma);
+
+       ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
+       return rc;
+}
+
+/**
+ * mpt3sas_enable_diag_buffer - enabling diag_buffers support driver load time
+ * @ioc: per adapter object
+ * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
+ *
+ * This is called when command line option diag_buffer_enable is enabled
+ * at driver load time.
+ */
+void
+mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
+{
+       struct mpt3_diag_register diag_register;
+
+       memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
+
+       if (bits_to_register & 1) {
+               pr_info(MPT3SAS_FMT "registering trace buffer support\n",
+                   ioc->name);
+               ioc->diag_trigger_master.MasterData =
+                   (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
+               /* register for 2MB buffers  */
+               diag_register.requested_buffer_size = 2 * (1024 * 1024);
+               diag_register.unique_id = 0x7075900;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       }
+
+       if (bits_to_register & 2) {
+               pr_info(MPT3SAS_FMT "registering snapshot buffer support\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
+               /* register for 2MB buffers  */
+               diag_register.requested_buffer_size = 2 * (1024 * 1024);
+               diag_register.unique_id = 0x7075901;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       }
+
+       if (bits_to_register & 4) {
+               pr_info(MPT3SAS_FMT "registering extended buffer support\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
+               /* register for 2MB buffers  */
+               diag_register.requested_buffer_size = 2 * (1024 * 1024);
+               diag_register.unique_id = 0x7075901;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       }
+}
+
+/**
+ * _ctl_diag_register - application register with driver
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ *
+ * This will allow the driver to setup any required buffers that will be
+ * needed by firmware to communicate with the driver.
+ */
+static long
+_ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_diag_register karg;
+       long rc;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       rc = _ctl_diag_register_2(ioc, &karg);
+       return rc;
+}
+
+/**
+ * _ctl_diag_unregister - application unregister with driver
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ *
+ * This will allow the driver to cleanup any memory allocated for diag
+ * messages and to free up any resources.
+ */
+static long
+_ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_diag_unregister karg;
+       void *request_data;
+       dma_addr_t request_data_dma;
+       u32 request_data_sz;
+       u8 buffer_type;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       buffer_type = karg.unique_id & 0x000000ff;
+       if (!_ctl_diag_capability(ioc, buffer_type)) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have capability for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -EPERM;
+       }
+
+       if ((ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               pr_err(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) is not registered\n",
+                       ioc->name, __func__, buffer_type);
+               return -EINVAL;
+       }
+       if ((ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
+               pr_err(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) has not been released\n",
+                       ioc->name, __func__, buffer_type);
+               return -EINVAL;
+       }
+
+       if (karg.unique_id != ioc->unique_id[buffer_type]) {
+               pr_err(MPT3SAS_FMT
+                       "%s: unique_id(0x%08x) is not registered\n",
+                       ioc->name, __func__, karg.unique_id);
+               return -EINVAL;
+       }
+
+       request_data = ioc->diag_buffer[buffer_type];
+       if (!request_data) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -ENOMEM;
+       }
+
+       request_data_sz = ioc->diag_buffer_sz[buffer_type];
+       request_data_dma = ioc->diag_buffer_dma[buffer_type];
+       pci_free_consistent(ioc->pdev, request_data_sz,
+           request_data, request_data_dma);
+       ioc->diag_buffer[buffer_type] = NULL;
+       ioc->diag_buffer_status[buffer_type] = 0;
+       return 0;
+}
+
+/**
+ * _ctl_diag_query - query relevant info associated with diag buffers
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ *
+ * The application will send only buffer_type and unique_id.  Driver will
+ * inspect unique_id first, if valid, fill in all the info.  If unique_id is
+ * 0x00, the driver will return info specified by Buffer Type.
+ */
+static long
+_ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_diag_query karg;
+       void *request_data;
+       int i;
+       u8 buffer_type;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       karg.application_flags = 0;
+       buffer_type = karg.buffer_type;
+
+       if (!_ctl_diag_capability(ioc, buffer_type)) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have capability for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -EPERM;
+       }
+
+       if ((ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               pr_err(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) is not registered\n",
+                       ioc->name, __func__, buffer_type);
+               return -EINVAL;
+       }
+
+       if (karg.unique_id & 0xffffff00) {
+               if (karg.unique_id != ioc->unique_id[buffer_type]) {
+                       pr_err(MPT3SAS_FMT
+                               "%s: unique_id(0x%08x) is not registered\n",
+                               ioc->name, __func__, karg.unique_id);
+                       return -EINVAL;
+               }
+       }
+
+       request_data = ioc->diag_buffer[buffer_type];
+       if (!request_data) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have buffer for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -ENOMEM;
+       }
+
+       if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED)
+               karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
+                   MPT3_APP_FLAGS_BUFFER_VALID);
+       else
+               karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
+                   MPT3_APP_FLAGS_BUFFER_VALID |
+                   MPT3_APP_FLAGS_FW_BUFFER_ACCESS);
+
+       for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
+               karg.product_specific[i] =
+                   ioc->product_specific[buffer_type][i];
+
+       karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
+       karg.driver_added_buffer_size = 0;
+       karg.unique_id = ioc->unique_id[buffer_type];
+       karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
+
+       if (copy_to_user(arg, &karg, sizeof(struct mpt3_diag_query))) {
+               pr_err(MPT3SAS_FMT
+                       "%s: unable to write mpt3_diag_query data @ %p\n",
+                       ioc->name, __func__, arg);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+/**
+ * mpt3sas_send_diag_release - Diag Release Message
+ * @ioc: per adapter object
+ * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
+ * @issue_reset - specifies whether host reset is required.
+ *
+ */
+int
+mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
+       u8 *issue_reset)
+{
+       Mpi2DiagReleaseRequest_t *mpi_request;
+       Mpi2DiagReleaseReply_t *mpi_reply;
+       u16 smid;
+       u16 ioc_status;
+       u32 ioc_state;
+       int rc;
+       unsigned long timeleft;
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       rc = 0;
+       *issue_reset = 0;
+
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (ioc->diag_buffer_status[buffer_type] &
+                   MPT3_DIAG_BUFFER_IS_REGISTERED)
+                       ioc->diag_buffer_status[buffer_type] |=
+                           MPT3_DIAG_BUFFER_IS_RELEASED;
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: skipping due to FAULT state\n", ioc->name,
+                   __func__));
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       ioc->ctl_cmds.status = MPT3_CMD_PENDING;
+       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->ctl_cmds.smid = smid;
+
+       mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
+       mpi_request->BufferType = buffer_type;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+
+       init_completion(&ioc->ctl_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+           MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
+
+       if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
+                   __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2DiagReleaseRequest_t)/4);
+               if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
+                       *issue_reset = 1;
+               rc = -EFAULT;
+               goto out;
+       }
+
+       /* process the completed Reply Message Frame */
+       if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
+               pr_err(MPT3SAS_FMT "%s: no reply message\n",
+                   ioc->name, __func__);
+               rc = -EFAULT;
+               goto out;
+       }
+
+       mpi_reply = ioc->ctl_cmds.reply;
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+               ioc->diag_buffer_status[buffer_type] |=
+                   MPT3_DIAG_BUFFER_IS_RELEASED;
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n",
+                   ioc->name, __func__));
+       } else {
+               pr_info(MPT3SAS_FMT
+                       "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
+                       ioc->name, __func__,
+                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
+               rc = -EFAULT;
+       }
+
+ out:
+       ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
+       return rc;
+}
+
+/**
+ * _ctl_diag_release - request to send Diag Release Message to firmware
+ * @arg - user space buffer containing ioctl content
+ *
+ * This allows ownership of the specified buffer to returned to the driver,
+ * allowing an application to read the buffer without fear that firmware is
+ * overwritting information in the buffer.
+ */
+static long
+_ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_diag_release karg;
+       void *request_data;
+       int rc;
+       u8 buffer_type;
+       u8 issue_reset = 0;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       buffer_type = karg.unique_id & 0x000000ff;
+       if (!_ctl_diag_capability(ioc, buffer_type)) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have capability for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -EPERM;
+       }
+
+       if ((ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               pr_err(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) is not registered\n",
+                       ioc->name, __func__, buffer_type);
+               return -EINVAL;
+       }
+
+       if (karg.unique_id != ioc->unique_id[buffer_type]) {
+               pr_err(MPT3SAS_FMT
+                       "%s: unique_id(0x%08x) is not registered\n",
+                       ioc->name, __func__, karg.unique_id);
+               return -EINVAL;
+       }
+
+       if (ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) {
+               pr_err(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) is already released\n",
+                       ioc->name, __func__,
+                   buffer_type);
+               return 0;
+       }
+
+       request_data = ioc->diag_buffer[buffer_type];
+
+       if (!request_data) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -ENOMEM;
+       }
+
+       /* buffers were released by due to host reset */
+       if ((ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_DIAG_RESET)) {
+               ioc->diag_buffer_status[buffer_type] |=
+                   MPT3_DIAG_BUFFER_IS_RELEASED;
+               ioc->diag_buffer_status[buffer_type] &=
+                   ~MPT3_DIAG_BUFFER_IS_DIAG_RESET;
+               pr_err(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) was released due to host reset\n",
+                       ioc->name, __func__, buffer_type);
+               return 0;
+       }
+
+       rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset);
+
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+
+       return rc;
+}
+
+/**
+ * _ctl_diag_read_buffer - request for copy of the diag buffer
+ * @ioc: per adapter object
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
+{
+       struct mpt3_diag_read_buffer karg;
+       struct mpt3_diag_read_buffer __user *uarg = arg;
+       void *request_data, *diag_data;
+       Mpi2DiagBufferPostRequest_t *mpi_request;
+       Mpi2DiagBufferPostReply_t *mpi_reply;
+       int rc, i;
+       u8 buffer_type;
+       unsigned long timeleft, request_size, copy_size;
+       u16 smid;
+       u16 ioc_status;
+       u8 issue_reset = 0;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+
+       buffer_type = karg.unique_id & 0x000000ff;
+       if (!_ctl_diag_capability(ioc, buffer_type)) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have capability for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -EPERM;
+       }
+
+       if (karg.unique_id != ioc->unique_id[buffer_type]) {
+               pr_err(MPT3SAS_FMT
+                       "%s: unique_id(0x%08x) is not registered\n",
+                       ioc->name, __func__, karg.unique_id);
+               return -EINVAL;
+       }
+
+       request_data = ioc->diag_buffer[buffer_type];
+       if (!request_data) {
+               pr_err(MPT3SAS_FMT
+                       "%s: doesn't have buffer for buffer_type(0x%02x)\n",
+                       ioc->name, __func__, buffer_type);
+               return -ENOMEM;
+       }
+
+       request_size = ioc->diag_buffer_sz[buffer_type];
+
+       if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
+               pr_err(MPT3SAS_FMT "%s: either the starting_offset " \
+                   "or bytes_to_read are not 4 byte aligned\n", ioc->name,
+                   __func__);
+               return -EINVAL;
+       }
+
+       if (karg.starting_offset > request_size)
+               return -EINVAL;
+
+       diag_data = (void *)(request_data + karg.starting_offset);
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: diag_buffer(%p), offset(%d), sz(%d)\n",
+               ioc->name, __func__,
+           diag_data, karg.starting_offset, karg.bytes_to_read));
+
+       /* Truncate data on requests that are too large */
+       if ((diag_data + karg.bytes_to_read < diag_data) ||
+           (diag_data + karg.bytes_to_read > request_data + request_size))
+               copy_size = request_size - karg.starting_offset;
+       else
+               copy_size = karg.bytes_to_read;
+
+       if (copy_to_user((void __user *)uarg->diagnostic_data,
+           diag_data, copy_size)) {
+               pr_err(MPT3SAS_FMT
+                       "%s: Unable to write mpt_diag_read_buffer_t data @ %p\n",
+                       ioc->name, __func__, diag_data);
+               return -EFAULT;
+       }
+
+       if ((karg.flags & MPT3_FLAGS_REREGISTER) == 0)
+               return 0;
+
+       dctlprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: Reregister buffer_type(0x%02x)\n",
+               ioc->name, __func__, buffer_type));
+       if ((ioc->diag_buffer_status[buffer_type] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: buffer_type(0x%02x) is still registered\n",
+                       ioc->name, __func__, buffer_type));
+               return 0;
+       }
+       /* Get a free request frame and save the message context.
+       */
+
+       if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       rc = 0;
+       ioc->ctl_cmds.status = MPT3_CMD_PENDING;
+       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->ctl_cmds.smid = smid;
+
+       mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
+       mpi_request->BufferType = buffer_type;
+       mpi_request->BufferLength =
+           cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
+       mpi_request->BufferAddress =
+           cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
+       for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
+               mpi_request->ProductSpecific[i] =
+                       cpu_to_le32(ioc->product_specific[buffer_type][i]);
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+
+       init_completion(&ioc->ctl_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+           MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
+
+       if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
+                   __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2DiagBufferPostRequest_t)/4);
+               if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       /* process the completed Reply Message Frame */
+       if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
+               pr_err(MPT3SAS_FMT "%s: no reply message\n",
+                   ioc->name, __func__);
+               rc = -EFAULT;
+               goto out;
+       }
+
+       mpi_reply = ioc->ctl_cmds.reply;
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+               ioc->diag_buffer_status[buffer_type] |=
+                   MPT3_DIAG_BUFFER_IS_REGISTERED;
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n",
+                   ioc->name, __func__));
+       } else {
+               pr_info(MPT3SAS_FMT
+                       "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
+                       ioc->name, __func__,
+                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
+               rc = -EFAULT;
+       }
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+
+ out:
+
+       ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
+       return rc;
+}
+
+
+
+#ifdef CONFIG_COMPAT
+/**
+ * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
+ * @ioc: per adapter object
+ * @cmd - ioctl opcode
+ * @arg - (struct mpt3_ioctl_command32)
+ *
+ * MPT3COMMAND32 - Handle 32bit applications running on 64bit os.
+ */
+static long
+_ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
+       void __user *arg)
+{
+       struct mpt3_ioctl_command32 karg32;
+       struct mpt3_ioctl_command32 __user *uarg;
+       struct mpt3_ioctl_command karg;
+
+       if (_IOC_SIZE(cmd) != sizeof(struct mpt3_ioctl_command32))
+               return -EINVAL;
+
+       uarg = (struct mpt3_ioctl_command32 __user *) arg;
+
+       if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       memset(&karg, 0, sizeof(struct mpt3_ioctl_command));
+       karg.hdr.ioc_number = karg32.hdr.ioc_number;
+       karg.hdr.port_number = karg32.hdr.port_number;
+       karg.hdr.max_data_size = karg32.hdr.max_data_size;
+       karg.timeout = karg32.timeout;
+       karg.max_reply_bytes = karg32.max_reply_bytes;
+       karg.data_in_size = karg32.data_in_size;
+       karg.data_out_size = karg32.data_out_size;
+       karg.max_sense_bytes = karg32.max_sense_bytes;
+       karg.data_sge_offset = karg32.data_sge_offset;
+       karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
+       karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
+       karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
+       karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
+       return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
+}
+#endif
+
+/**
+ * _ctl_ioctl_main - main ioctl entry point
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg -
+ * compat - handles 32 bit applications in 64bit os
+ */
+static long
+_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
+       u8 compat)
+{
+       struct MPT3SAS_ADAPTER *ioc;
+       struct mpt3_ioctl_header ioctl_header;
+       enum block_state state;
+       long ret = -EINVAL;
+
+       /* get IOCTL header */
+       if (copy_from_user(&ioctl_header, (char __user *)arg,
+           sizeof(struct mpt3_ioctl_header))) {
+               pr_err("failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+
+       if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
+               return -ENODEV;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery ||
+           ioc->is_driver_loading)
+               return -EAGAIN;
+
+       state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
+       if (state == NON_BLOCKING) {
+               if (!mutex_trylock(&ioc->ctl_cmds.mutex))
+                       return -EAGAIN;
+       } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+               return -ERESTARTSYS;
+
+
+       switch (cmd) {
+       case MPT3IOCINFO:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_iocinfo))
+                       ret = _ctl_getiocinfo(ioc, arg);
+               break;
+#ifdef CONFIG_COMPAT
+       case MPT3COMMAND32:
+#endif
+       case MPT3COMMAND:
+       {
+               struct mpt3_ioctl_command __user *uarg;
+               struct mpt3_ioctl_command karg;
+
+#ifdef CONFIG_COMPAT
+               if (compat) {
+                       ret = _ctl_compat_mpt_command(ioc, cmd, arg);
+                       break;
+               }
+#endif
+               if (copy_from_user(&karg, arg, sizeof(karg))) {
+                       pr_err("failure at %s:%d/%s()!\n",
+                           __FILE__, __LINE__, __func__);
+                       ret = -EFAULT;
+                       break;
+               }
+
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) {
+                       uarg = arg;
+                       ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
+               }
+               break;
+       }
+       case MPT3EVENTQUERY:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventquery))
+                       ret = _ctl_eventquery(ioc, arg);
+               break;
+       case MPT3EVENTENABLE:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventenable))
+                       ret = _ctl_eventenable(ioc, arg);
+               break;
+       case MPT3EVENTREPORT:
+               ret = _ctl_eventreport(ioc, arg);
+               break;
+       case MPT3HARDRESET:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_diag_reset))
+                       ret = _ctl_do_reset(ioc, arg);
+               break;
+       case MPT3BTDHMAPPING:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_btdh_mapping))
+                       ret = _ctl_btdh_mapping(ioc, arg);
+               break;
+       case MPT3DIAGREGISTER:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_register))
+                       ret = _ctl_diag_register(ioc, arg);
+               break;
+       case MPT3DIAGUNREGISTER:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_unregister))
+                       ret = _ctl_diag_unregister(ioc, arg);
+               break;
+       case MPT3DIAGQUERY:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_query))
+                       ret = _ctl_diag_query(ioc, arg);
+               break;
+       case MPT3DIAGRELEASE:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_release))
+                       ret = _ctl_diag_release(ioc, arg);
+               break;
+       case MPT3DIAGREADBUFFER:
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
+                       ret = _ctl_diag_read_buffer(ioc, arg);
+               break;
+       default:
+               dctlprintk(ioc, pr_info(MPT3SAS_FMT
+                   "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
+               break;
+       }
+
+       mutex_unlock(&ioc->ctl_cmds.mutex);
+       return ret;
+}
+
+/**
+ * _ctl_ioctl - main ioctl entry point (unlocked)
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg -
+ */
+static long
+_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+
+       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
+       return ret;
+}
+
+#ifdef CONFIG_COMPAT
+/**
+ * _ctl_ioctl_compat - main ioctl entry point (compat)
+ * @file -
+ * @cmd -
+ * @arg -
+ *
+ * This routine handles 32 bit applications in 64bit os.
+ */
+static long
+_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
+{
+       long ret;
+
+       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
+       return ret;
+}
+#endif
+
+/* scsi host attributes */
+/**
+ * _ctl_version_fw_show - firmware version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
+           (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
+           (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
+           (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
+           ioc->facts.FWVersion.Word & 0x000000FF);
+}
+static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
+
+/**
+ * _ctl_version_bios_show - bios version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
+
+       return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
+           (version & 0xFF000000) >> 24,
+           (version & 0x00FF0000) >> 16,
+           (version & 0x0000FF00) >> 8,
+           version & 0x000000FF);
+}
+static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
+
+/**
+ * _ctl_version_mpi_show - MPI (message passing interface) version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
+           ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
+}
+static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
+
+/**
+ * _ctl_version_product_show - product name
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
+}
+static DEVICE_ATTR(version_product, S_IRUGO, _ctl_version_product_show, NULL);
+
+/**
+ * _ctl_version_nvdata_persistent_show - ndvata persistent version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_nvdata_persistent_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%08xh\n",
+           le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
+}
+static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
+       _ctl_version_nvdata_persistent_show, NULL);
+
+/**
+ * _ctl_version_nvdata_default_show - nvdata default version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_nvdata_default_show(struct device *cdev, struct device_attribute
+       *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%08xh\n",
+           le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
+}
+static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
+       _ctl_version_nvdata_default_show, NULL);
+
+/**
+ * _ctl_board_name_show - board name
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
+}
+static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
+
+/**
+ * _ctl_board_assembly_show - board assembly name
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
+}
+static DEVICE_ATTR(board_assembly, S_IRUGO, _ctl_board_assembly_show, NULL);
+
+/**
+ * _ctl_board_tracer_show - board tracer number
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
+}
+static DEVICE_ATTR(board_tracer, S_IRUGO, _ctl_board_tracer_show, NULL);
+
+/**
+ * _ctl_io_delay_show - io missing delay
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is for firmware implemention for deboucing device
+ * removal events.
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
+}
+static DEVICE_ATTR(io_delay, S_IRUGO, _ctl_io_delay_show, NULL);
+
+/**
+ * _ctl_device_delay_show - device missing delay
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is for firmware implemention for deboucing device
+ * removal events.
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
+}
+static DEVICE_ATTR(device_delay, S_IRUGO, _ctl_device_delay_show, NULL);
+
+/**
+ * _ctl_fw_queue_depth_show - global credits
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is firmware queue depth limit
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
+}
+static DEVICE_ATTR(fw_queue_depth, S_IRUGO, _ctl_fw_queue_depth_show, NULL);
+
+/**
+ * _ctl_sas_address_show - sas address
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is the controller sas address
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
+           (unsigned long long)ioc->sas_hba.sas_address);
+}
+static DEVICE_ATTR(host_sas_address, S_IRUGO,
+       _ctl_host_sas_address_show, NULL);
+
+/**
+ * _ctl_logging_level_show - logging level
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
+}
+static ssize_t
+_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       int val = 0;
+
+       if (sscanf(buf, "%x", &val) != 1)
+               return -EINVAL;
+
+       ioc->logging_level = val;
+       pr_info(MPT3SAS_FMT "logging_level=%08xh\n", ioc->name,
+           ioc->logging_level);
+       return strlen(buf);
+}
+static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, _ctl_logging_level_show,
+       _ctl_logging_level_store);
+
+/**
+ * _ctl_fwfault_debug_show - show/store fwfault_debug
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * mpt3sas_fwfault_debug is command line option
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_fwfault_debug_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
+}
+static ssize_t
+_ctl_fwfault_debug_store(struct device *cdev, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       int val = 0;
+
+       if (sscanf(buf, "%d", &val) != 1)
+               return -EINVAL;
+
+       ioc->fwfault_debug = val;
+       pr_info(MPT3SAS_FMT "fwfault_debug=%d\n", ioc->name,
+           ioc->fwfault_debug);
+       return strlen(buf);
+}
+static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
+       _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
+
+/**
+ * _ctl_ioc_reset_count_show - ioc reset count
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is firmware queue depth limit
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", ioc->ioc_reset_count);
+}
+static DEVICE_ATTR(ioc_reset_count, S_IRUGO, _ctl_ioc_reset_count_show, NULL);
+
+/**
+ * _ctl_ioc_reply_queue_count_show - number of reply queues
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is number of reply queues
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_ioc_reply_queue_count_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       u8 reply_queue_count;
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       if ((ioc->facts.IOCCapabilities &
+           MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
+               reply_queue_count = ioc->reply_queue_count;
+       else
+               reply_queue_count = 1;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
+}
+static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show,
+       NULL);
+
+struct DIAG_BUFFER_START {
+       __le32  Size;
+       __le32  DiagVersion;
+       u8      BufferType;
+       u8      Reserved[3];
+       __le32  Reserved1;
+       __le32  Reserved2;
+       __le32  Reserved3;
+};
+
+/**
+ * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_host_trace_buffer_size_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       u32 size = 0;
+       struct DIAG_BUFFER_START *request_data;
+
+       if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
+               pr_err(MPT3SAS_FMT
+                       "%s: host_trace_buffer is not registered\n",
+                       ioc->name, __func__);
+               return 0;
+       }
+
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               pr_err(MPT3SAS_FMT
+                       "%s: host_trace_buffer is not registered\n",
+                       ioc->name, __func__);
+               return 0;
+       }
+
+       request_data = (struct DIAG_BUFFER_START *)
+           ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
+       if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
+           le32_to_cpu(request_data->DiagVersion) == 0x01000000 ||
+           le32_to_cpu(request_data->DiagVersion) == 0x01010000) &&
+           le32_to_cpu(request_data->Reserved3) == 0x4742444c)
+               size = le32_to_cpu(request_data->Size);
+
+       ioc->ring_buffer_sz = size;
+       return snprintf(buf, PAGE_SIZE, "%d\n", size);
+}
+static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
+       _ctl_host_trace_buffer_size_show, NULL);
+
+/**
+ * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ *
+ * You will only be able to read 4k bytes of ring buffer at a time.
+ * In order to read beyond 4k bytes, you will have to write out the
+ * offset to the same attribute, it will move the pointer.
+ */
+static ssize_t
+_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       void *request_data;
+       u32 size;
+
+       if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
+               pr_err(MPT3SAS_FMT
+                       "%s: host_trace_buffer is not registered\n",
+                       ioc->name, __func__);
+               return 0;
+       }
+
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               pr_err(MPT3SAS_FMT
+                       "%s: host_trace_buffer is not registered\n",
+                       ioc->name, __func__);
+               return 0;
+       }
+
+       if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
+               return 0;
+
+       size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
+       size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size;
+       request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
+       memcpy(buf, request_data, size);
+       return size;
+}
+
+static ssize_t
+_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       int val = 0;
+
+       if (sscanf(buf, "%d", &val) != 1)
+               return -EINVAL;
+
+       ioc->ring_buffer_offset = val;
+       return strlen(buf);
+}
+static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
+       _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
+
+
+/*****************************************/
+
+/**
+ * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ *
+ * This is a mechnism to post/release host_trace_buffers
+ */
+static ssize_t
+_ctl_host_trace_buffer_enable_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
+          ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0))
+               return snprintf(buf, PAGE_SIZE, "off\n");
+       else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED))
+               return snprintf(buf, PAGE_SIZE, "release\n");
+       else
+               return snprintf(buf, PAGE_SIZE, "post\n");
+}
+
+static ssize_t
+_ctl_host_trace_buffer_enable_store(struct device *cdev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       char str[10] = "";
+       struct mpt3_diag_register diag_register;
+       u8 issue_reset = 0;
+
+       /* don't allow post/release occurr while recovery is active */
+       if (ioc->shost_recovery || ioc->remove_host ||
+           ioc->pci_error_recovery || ioc->is_driver_loading)
+               return -EBUSY;
+
+       if (sscanf(buf, "%9s", str) != 1)
+               return -EINVAL;
+
+       if (!strcmp(str, "post")) {
+               /* exit out if host buffers are already posted */
+               if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
+                   (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT3_DIAG_BUFFER_IS_REGISTERED) &&
+                   ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT3_DIAG_BUFFER_IS_RELEASED) == 0))
+                       goto out;
+               memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
+               pr_info(MPT3SAS_FMT "posting host trace buffers\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
+               diag_register.requested_buffer_size = (1024 * 1024);
+               diag_register.unique_id = 0x7075900;
+               ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       } else if (!strcmp(str, "release")) {
+               /* exit out if host buffers are already released */
+               if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
+                       goto out;
+               if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT3_DIAG_BUFFER_IS_REGISTERED) == 0)
+                       goto out;
+               if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT3_DIAG_BUFFER_IS_RELEASED))
+                       goto out;
+               pr_info(MPT3SAS_FMT "releasing host trace buffer\n",
+                   ioc->name);
+               mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
+                   &issue_reset);
+       }
+
+ out:
+       return strlen(buf);
+}
+static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
+       _ctl_host_trace_buffer_enable_show,
+       _ctl_host_trace_buffer_enable_store);
+
+/*********** diagnostic trigger suppport *********************************/
+
+/**
+ * _ctl_diag_trigger_master_show - show the diag_trigger_master attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_master_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t rc;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       rc = sizeof(struct SL_WH_MASTER_TRIGGER_T);
+       memcpy(buf, &ioc->diag_trigger_master, rc);
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return rc;
+}
+
+/**
+ * _ctl_diag_trigger_master_store - store the diag_trigger_master attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_master_store(struct device *cdev,
+       struct device_attribute *attr, const char *buf, size_t count)
+
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t rc;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count);
+       memset(&ioc->diag_trigger_master, 0,
+           sizeof(struct SL_WH_MASTER_TRIGGER_T));
+       memcpy(&ioc->diag_trigger_master, buf, rc);
+       ioc->diag_trigger_master.MasterData |=
+           (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return rc;
+}
+static DEVICE_ATTR(diag_trigger_master, S_IRUGO | S_IWUSR,
+       _ctl_diag_trigger_master_show, _ctl_diag_trigger_master_store);
+
+
+/**
+ * _ctl_diag_trigger_event_show - show the diag_trigger_event attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_event_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t rc;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       rc = sizeof(struct SL_WH_EVENT_TRIGGERS_T);
+       memcpy(buf, &ioc->diag_trigger_event, rc);
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return rc;
+}
+
+/**
+ * _ctl_diag_trigger_event_store - store the diag_trigger_event attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_event_store(struct device *cdev,
+       struct device_attribute *attr, const char *buf, size_t count)
+
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t sz;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count);
+       memset(&ioc->diag_trigger_event, 0,
+           sizeof(struct SL_WH_EVENT_TRIGGERS_T));
+       memcpy(&ioc->diag_trigger_event, buf, sz);
+       if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES)
+               ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES;
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return sz;
+}
+static DEVICE_ATTR(diag_trigger_event, S_IRUGO | S_IWUSR,
+       _ctl_diag_trigger_event_show, _ctl_diag_trigger_event_store);
+
+
+/**
+ * _ctl_diag_trigger_scsi_show - show the diag_trigger_scsi attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_scsi_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t rc;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       rc = sizeof(struct SL_WH_SCSI_TRIGGERS_T);
+       memcpy(buf, &ioc->diag_trigger_scsi, rc);
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return rc;
+}
+
+/**
+ * _ctl_diag_trigger_scsi_store - store the diag_trigger_scsi attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_scsi_store(struct device *cdev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t sz;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count);
+       memset(&ioc->diag_trigger_scsi, 0,
+           sizeof(struct SL_WH_EVENT_TRIGGERS_T));
+       memcpy(&ioc->diag_trigger_scsi, buf, sz);
+       if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES)
+               ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES;
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return sz;
+}
+static DEVICE_ATTR(diag_trigger_scsi, S_IRUGO | S_IWUSR,
+       _ctl_diag_trigger_scsi_show, _ctl_diag_trigger_scsi_store);
+
+
+/**
+ * _ctl_diag_trigger_scsi_show - show the diag_trigger_mpi attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_mpi_show(struct device *cdev,
+       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t rc;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       rc = sizeof(struct SL_WH_MPI_TRIGGERS_T);
+       memcpy(buf, &ioc->diag_trigger_mpi, rc);
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return rc;
+}
+
+/**
+ * _ctl_diag_trigger_mpi_store - store the diag_trigger_mpi attribute
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_diag_trigger_mpi_store(struct device *cdev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       unsigned long flags;
+       ssize_t sz;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count);
+       memset(&ioc->diag_trigger_mpi, 0,
+           sizeof(struct SL_WH_EVENT_TRIGGERS_T));
+       memcpy(&ioc->diag_trigger_mpi, buf, sz);
+       if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES)
+               ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES;
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+       return sz;
+}
+
+static DEVICE_ATTR(diag_trigger_mpi, S_IRUGO | S_IWUSR,
+       _ctl_diag_trigger_mpi_show, _ctl_diag_trigger_mpi_store);
+
+/*********** diagnostic trigger suppport *** END ****************************/
+
+
+
+/*****************************************/
+
+struct device_attribute *mpt3sas_host_attrs[] = {
+       &dev_attr_version_fw,
+       &dev_attr_version_bios,
+       &dev_attr_version_mpi,
+       &dev_attr_version_product,
+       &dev_attr_version_nvdata_persistent,
+       &dev_attr_version_nvdata_default,
+       &dev_attr_board_name,
+       &dev_attr_board_assembly,
+       &dev_attr_board_tracer,
+       &dev_attr_io_delay,
+       &dev_attr_device_delay,
+       &dev_attr_logging_level,
+       &dev_attr_fwfault_debug,
+       &dev_attr_fw_queue_depth,
+       &dev_attr_host_sas_address,
+       &dev_attr_ioc_reset_count,
+       &dev_attr_host_trace_buffer_size,
+       &dev_attr_host_trace_buffer,
+       &dev_attr_host_trace_buffer_enable,
+       &dev_attr_reply_queue_count,
+       &dev_attr_diag_trigger_master,
+       &dev_attr_diag_trigger_event,
+       &dev_attr_diag_trigger_scsi,
+       &dev_attr_diag_trigger_mpi,
+       NULL,
+};
+
+/* device attributes */
+
+/**
+ * _ctl_device_sas_address_show - sas address
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is the sas address for the target
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
+       char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
+
+       return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
+           (unsigned long long)sas_device_priv_data->sas_target->sas_address);
+}
+static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
+
+/**
+ * _ctl_device_handle_show - device handle
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is the firmware assigned device handle
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
+       char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
+
+       return snprintf(buf, PAGE_SIZE, "0x%04x\n",
+           sas_device_priv_data->sas_target->handle);
+}
+static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
+
+struct device_attribute *mpt3sas_dev_attrs[] = {
+       &dev_attr_sas_address,
+       &dev_attr_sas_device_handle,
+       NULL,
+};
+
+static const struct file_operations ctl_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = _ctl_ioctl,
+       .release = _ctl_release,
+       .poll = _ctl_poll,
+       .fasync = _ctl_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = _ctl_ioctl_compat,
+#endif
+};
+
+static struct miscdevice ctl_dev = {
+       .minor  = MPT3SAS_MINOR,
+       .name   = MPT3SAS_DEV_NAME,
+       .fops   = &ctl_fops,
+};
+
+/**
+ * mpt3sas_ctl_init - main entry point for ctl.
+ *
+ */
+void
+mpt3sas_ctl_init(void)
+{
+       async_queue = NULL;
+       if (misc_register(&ctl_dev) < 0)
+               pr_err("%s can't register misc device [minor=%d]\n",
+                   MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
+
+       init_waitqueue_head(&ctl_poll_wait);
+}
+
+/**
+ * mpt3sas_ctl_exit - exit point for ctl
+ *
+ */
+void
+mpt3sas_ctl_exit(void)
+{
+       struct MPT3SAS_ADAPTER *ioc;
+       int i;
+
+       list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
+
+               /* free memory associated to diag buffers */
+               for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+                       if (!ioc->diag_buffer[i])
+                               continue;
+                       if (!(ioc->diag_buffer_status[i] &
+                           MPT3_DIAG_BUFFER_IS_REGISTERED))
+                               continue;
+                       if ((ioc->diag_buffer_status[i] &
+                           MPT3_DIAG_BUFFER_IS_RELEASED))
+                               continue;
+                       pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
+                       ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
+                       ioc->diag_buffer[i] = NULL;
+                       ioc->diag_buffer_status[i] = 0;
+               }
+
+               kfree(ioc->event_log);
+       }
+       misc_deregister(&ctl_dev);
+}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
new file mode 100644 (file)
index 0000000..bd89f4f
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * Management Module Support for MPT (Message Passing Technology) based
+ * controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.h
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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 MPT3SAS_CTL_H_INCLUDED
+#define MPT3SAS_CTL_H_INCLUDED
+
+#ifdef __KERNEL__
+#include <linux/miscdevice.h>
+#endif
+
+
+#ifndef MPT3SAS_MINOR
+#define MPT3SAS_MINOR          (MPT_MINOR + 2)
+#endif
+#define MPT3SAS_DEV_NAME       "mpt3ctl"
+#define MPT3_MAGIC_NUMBER      'L'
+#define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
+
+/**
+ * IOCTL opcodes
+ */
+#define MPT3IOCINFO    _IOWR(MPT3_MAGIC_NUMBER, 17, \
+       struct mpt3_ioctl_iocinfo)
+#define MPT3COMMAND    _IOWR(MPT3_MAGIC_NUMBER, 20, \
+       struct mpt3_ioctl_command)
+#ifdef CONFIG_COMPAT
+#define MPT3COMMAND32  _IOWR(MPT3_MAGIC_NUMBER, 20, \
+       struct mpt3_ioctl_command32)
+#endif
+#define MPT3EVENTQUERY _IOWR(MPT3_MAGIC_NUMBER, 21, \
+       struct mpt3_ioctl_eventquery)
+#define MPT3EVENTENABLE        _IOWR(MPT3_MAGIC_NUMBER, 22, \
+       struct mpt3_ioctl_eventenable)
+#define MPT3EVENTREPORT        _IOWR(MPT3_MAGIC_NUMBER, 23, \
+       struct mpt3_ioctl_eventreport)
+#define MPT3HARDRESET  _IOWR(MPT3_MAGIC_NUMBER, 24, \
+       struct mpt3_ioctl_diag_reset)
+#define MPT3BTDHMAPPING        _IOWR(MPT3_MAGIC_NUMBER, 31, \
+       struct mpt3_ioctl_btdh_mapping)
+
+/* diag buffer support */
+#define MPT3DIAGREGISTER _IOWR(MPT3_MAGIC_NUMBER, 26, \
+       struct mpt3_diag_register)
+#define MPT3DIAGRELEASE        _IOWR(MPT3_MAGIC_NUMBER, 27, \
+       struct mpt3_diag_release)
+#define MPT3DIAGUNREGISTER _IOWR(MPT3_MAGIC_NUMBER, 28, \
+       struct mpt3_diag_unregister)
+#define MPT3DIAGQUERY  _IOWR(MPT3_MAGIC_NUMBER, 29, \
+       struct mpt3_diag_query)
+#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
+       struct mpt3_diag_read_buffer)
+
+/**
+ * struct mpt3_ioctl_header - main header structure
+ * @ioc_number -  IOC unit number
+ * @port_number - IOC port number
+ * @max_data_size - maximum number bytes to transfer on read
+ */
+struct mpt3_ioctl_header {
+       uint32_t ioc_number;
+       uint32_t port_number;
+       uint32_t max_data_size;
+};
+
+/**
+ * struct mpt3_ioctl_diag_reset - diagnostic reset
+ * @hdr - generic header
+ */
+struct mpt3_ioctl_diag_reset {
+       struct mpt3_ioctl_header hdr;
+};
+
+
+/**
+ * struct mpt3_ioctl_pci_info - pci device info
+ * @device - pci device id
+ * @function - pci function id
+ * @bus - pci bus id
+ * @segment_id - pci segment id
+ */
+struct mpt3_ioctl_pci_info {
+       union {
+               struct {
+                       uint32_t device:5;
+                       uint32_t function:3;
+                       uint32_t bus:24;
+               } bits;
+               uint32_t  word;
+       } u;
+       uint32_t segment_id;
+};
+
+
+#define MPT2_IOCTL_INTERFACE_SCSI      (0x00)
+#define MPT2_IOCTL_INTERFACE_FC                (0x01)
+#define MPT2_IOCTL_INTERFACE_FC_IP     (0x02)
+#define MPT2_IOCTL_INTERFACE_SAS       (0x03)
+#define MPT2_IOCTL_INTERFACE_SAS2      (0x04)
+#define MPT3_IOCTL_INTERFACE_SAS3      (0x06)
+#define MPT2_IOCTL_VERSION_LENGTH      (32)
+
+/**
+ * struct mpt3_ioctl_iocinfo - generic controller info
+ * @hdr - generic header
+ * @adapter_type - type of adapter (spi, fc, sas)
+ * @port_number - port number
+ * @pci_id - PCI Id
+ * @hw_rev - hardware revision
+ * @sub_system_device - PCI subsystem Device ID
+ * @sub_system_vendor - PCI subsystem Vendor ID
+ * @rsvd0 - reserved
+ * @firmware_version - firmware version
+ * @bios_version - BIOS version
+ * @driver_version - driver version - 32 ASCII characters
+ * @rsvd1 - reserved
+ * @scsi_id - scsi id of adapter 0
+ * @rsvd2 - reserved
+ * @pci_information - pci info (2nd revision)
+ */
+struct mpt3_ioctl_iocinfo {
+       struct mpt3_ioctl_header hdr;
+       uint32_t adapter_type;
+       uint32_t port_number;
+       uint32_t pci_id;
+       uint32_t hw_rev;
+       uint32_t subsystem_device;
+       uint32_t subsystem_vendor;
+       uint32_t rsvd0;
+       uint32_t firmware_version;
+       uint32_t bios_version;
+       uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
+       uint8_t rsvd1;
+       uint8_t scsi_id;
+       uint16_t rsvd2;
+       struct mpt3_ioctl_pci_info pci_information;
+};
+
+
+/* number of event log entries */
+#define MPT3SAS_CTL_EVENT_LOG_SIZE (50)
+
+/**
+ * struct mpt3_ioctl_eventquery - query event count and type
+ * @hdr - generic header
+ * @event_entries - number of events returned by get_event_report
+ * @rsvd - reserved
+ * @event_types - type of events currently being captured
+ */
+struct mpt3_ioctl_eventquery {
+       struct mpt3_ioctl_header hdr;
+       uint16_t event_entries;
+       uint16_t rsvd;
+       uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+};
+
+/**
+ * struct mpt3_ioctl_eventenable - enable/disable event capturing
+ * @hdr - generic header
+ * @event_types - toggle off/on type of events to be captured
+ */
+struct mpt3_ioctl_eventenable {
+       struct mpt3_ioctl_header hdr;
+       uint32_t event_types[4];
+};
+
+#define MPT3_EVENT_DATA_SIZE (192)
+/**
+ * struct MPT3_IOCTL_EVENTS -
+ * @event - the event that was reported
+ * @context - unique value for each event assigned by driver
+ * @data - event data returned in fw reply message
+ */
+struct MPT3_IOCTL_EVENTS {
+       uint32_t event;
+       uint32_t context;
+       uint8_t data[MPT3_EVENT_DATA_SIZE];
+};
+
+/**
+ * struct mpt3_ioctl_eventreport - returing event log
+ * @hdr - generic header
+ * @event_data - (see struct MPT3_IOCTL_EVENTS)
+ */
+struct mpt3_ioctl_eventreport {
+       struct mpt3_ioctl_header hdr;
+       struct MPT3_IOCTL_EVENTS event_data[1];
+};
+
+/**
+ * struct mpt3_ioctl_command - generic mpt firmware passthru ioctl
+ * @hdr - generic header
+ * @timeout - command timeout in seconds. (if zero then use driver default
+ *  value).
+ * @reply_frame_buf_ptr - reply location
+ * @data_in_buf_ptr - destination for read
+ * @data_out_buf_ptr - data source for write
+ * @sense_data_ptr - sense data location
+ * @max_reply_bytes - maximum number of reply bytes to be sent to app.
+ * @data_in_size - number bytes for data transfer in (read)
+ * @data_out_size - number bytes for data transfer out (write)
+ * @max_sense_bytes - maximum number of bytes for auto sense buffers
+ * @data_sge_offset - offset in words from the start of the request message to
+ * the first SGL
+ * @mf[1];
+ */
+struct mpt3_ioctl_command {
+       struct mpt3_ioctl_header hdr;
+       uint32_t timeout;
+       void __user *reply_frame_buf_ptr;
+       void __user *data_in_buf_ptr;
+       void __user *data_out_buf_ptr;
+       void __user *sense_data_ptr;
+       uint32_t max_reply_bytes;
+       uint32_t data_in_size;
+       uint32_t data_out_size;
+       uint32_t max_sense_bytes;
+       uint32_t data_sge_offset;
+       uint8_t mf[1];
+};
+
+#ifdef CONFIG_COMPAT
+struct mpt3_ioctl_command32 {
+       struct mpt3_ioctl_header hdr;
+       uint32_t timeout;
+       uint32_t reply_frame_buf_ptr;
+       uint32_t data_in_buf_ptr;
+       uint32_t data_out_buf_ptr;
+       uint32_t sense_data_ptr;
+       uint32_t max_reply_bytes;
+       uint32_t data_in_size;
+       uint32_t data_out_size;
+       uint32_t max_sense_bytes;
+       uint32_t data_sge_offset;
+       uint8_t mf[1];
+};
+#endif
+
+/**
+ * struct mpt3_ioctl_btdh_mapping - mapping info
+ * @hdr - generic header
+ * @id - target device identification number
+ * @bus - SCSI bus number that the target device exists on
+ * @handle - device handle for the target device
+ * @rsvd - reserved
+ *
+ * To obtain a bus/id the application sets
+ * handle to valid handle, and bus/id to 0xFFFF.
+ *
+ * To obtain the device handle the application sets
+ * bus/id valid value, and the handle to 0xFFFF.
+ */
+struct mpt3_ioctl_btdh_mapping {
+       struct mpt3_ioctl_header hdr;
+       uint32_t id;
+       uint32_t bus;
+       uint16_t handle;
+       uint16_t rsvd;
+};
+
+
+
+/* application flags for mpt3_diag_register, mpt3_diag_query */
+#define MPT3_APP_FLAGS_APP_OWNED       (0x0001)
+#define MPT3_APP_FLAGS_BUFFER_VALID    (0x0002)
+#define MPT3_APP_FLAGS_FW_BUFFER_ACCESS        (0x0004)
+
+/* flags for mpt3_diag_read_buffer */
+#define MPT3_FLAGS_REREGISTER          (0x0001)
+
+#define MPT3_PRODUCT_SPECIFIC_DWORDS           23
+
+/**
+ * struct mpt3_diag_register - application register with driver
+ * @hdr - generic header
+ * @reserved -
+ * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
+ * @application_flags - misc flags
+ * @diagnostic_flags - specifies flags affecting command processing
+ * @product_specific - product specific information
+ * @requested_buffer_size - buffers size in bytes
+ * @unique_id - tag specified by application that is used to signal ownership
+ *  of the buffer.
+ *
+ * This will allow the driver to setup any required buffers that will be
+ * needed by firmware to communicate with the driver.
+ */
+struct mpt3_diag_register {
+       struct mpt3_ioctl_header hdr;
+       uint8_t reserved;
+       uint8_t buffer_type;
+       uint16_t application_flags;
+       uint32_t diagnostic_flags;
+       uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS];
+       uint32_t requested_buffer_size;
+       uint32_t unique_id;
+};
+
+/**
+ * struct mpt3_diag_unregister - application unregister with driver
+ * @hdr - generic header
+ * @unique_id - tag uniquely identifies the buffer to be unregistered
+ *
+ * This will allow the driver to cleanup any memory allocated for diag
+ * messages and to free up any resources.
+ */
+struct mpt3_diag_unregister {
+       struct mpt3_ioctl_header hdr;
+       uint32_t unique_id;
+};
+
+/**
+ * struct mpt3_diag_query - query relevant info associated with diag buffers
+ * @hdr - generic header
+ * @reserved -
+ * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
+ * @application_flags - misc flags
+ * @diagnostic_flags - specifies flags affecting command processing
+ * @product_specific - product specific information
+ * @total_buffer_size - diag buffer size in bytes
+ * @driver_added_buffer_size - size of extra space appended to end of buffer
+ * @unique_id - unique id associated with this buffer.
+ *
+ * The application will send only buffer_type and unique_id.  Driver will
+ * inspect unique_id first, if valid, fill in all the info.  If unique_id is
+ * 0x00, the driver will return info specified by Buffer Type.
+ */
+struct mpt3_diag_query {
+       struct mpt3_ioctl_header hdr;
+       uint8_t reserved;
+       uint8_t buffer_type;
+       uint16_t application_flags;
+       uint32_t diagnostic_flags;
+       uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS];
+       uint32_t total_buffer_size;
+       uint32_t driver_added_buffer_size;
+       uint32_t unique_id;
+};
+
+/**
+ * struct mpt3_diag_release -  request to send Diag Release Message to firmware
+ * @hdr - generic header
+ * @unique_id - tag uniquely identifies the buffer to be released
+ *
+ * This allows ownership of the specified buffer to returned to the driver,
+ * allowing an application to read the buffer without fear that firmware is
+ * overwritting information in the buffer.
+ */
+struct mpt3_diag_release {
+       struct mpt3_ioctl_header hdr;
+       uint32_t unique_id;
+};
+
+/**
+ * struct mpt3_diag_read_buffer - request for copy of the diag buffer
+ * @hdr - generic header
+ * @status -
+ * @reserved -
+ * @flags - misc flags
+ * @starting_offset - starting offset within drivers buffer where to start
+ *  reading data at into the specified application buffer
+ * @bytes_to_read - number of bytes to copy from the drivers buffer into the
+ *  application buffer starting at starting_offset.
+ * @unique_id - unique id associated with this buffer.
+ * @diagnostic_data - data payload
+ */
+struct mpt3_diag_read_buffer {
+       struct mpt3_ioctl_header hdr;
+       uint8_t status;
+       uint8_t reserved;
+       uint16_t flags;
+       uint32_t starting_offset;
+       uint32_t bytes_to_read;
+       uint32_t unique_id;
+       uint32_t diagnostic_data[1];
+};
+
+#endif /* MPT3SAS_CTL_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_debug.h b/drivers/scsi/mpt3sas/mpt3sas_debug.h
new file mode 100644 (file)
index 0000000..35405e7
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Logging Support for MPT (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_debug.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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 MPT3SAS_DEBUG_H_INCLUDED
+#define MPT3SAS_DEBUG_H_INCLUDED
+
+#define MPT_DEBUG                      0x00000001
+#define MPT_DEBUG_MSG_FRAME            0x00000002
+#define MPT_DEBUG_SG                   0x00000004
+#define MPT_DEBUG_EVENTS               0x00000008
+#define MPT_DEBUG_EVENT_WORK_TASK      0x00000010
+#define MPT_DEBUG_INIT                 0x00000020
+#define MPT_DEBUG_EXIT                 0x00000040
+#define MPT_DEBUG_FAIL                 0x00000080
+#define MPT_DEBUG_TM                   0x00000100
+#define MPT_DEBUG_REPLY                0x00000200
+#define MPT_DEBUG_HANDSHAKE            0x00000400
+#define MPT_DEBUG_CONFIG               0x00000800
+#define MPT_DEBUG_DL                   0x00001000
+#define MPT_DEBUG_RESET                0x00002000
+#define MPT_DEBUG_SCSI                 0x00004000
+#define MPT_DEBUG_IOCTL                0x00008000
+#define MPT_DEBUG_SAS                  0x00020000
+#define MPT_DEBUG_TRANSPORT            0x00040000
+#define MPT_DEBUG_TASK_SET_FULL        0x00080000
+
+#define MPT_DEBUG_TRIGGER_DIAG         0x00200000
+
+
+/*
+ * CONFIG_SCSI_MPT3SAS_LOGGING - enabled in Kconfig
+ */
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+#define MPT_CHECK_LOGGING(IOC, CMD, BITS)                      \
+{                                                              \
+       if (IOC->logging_level & BITS)                          \
+               CMD;                                            \
+}
+#else
+#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
+#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
+
+
+/*
+ * debug macros
+ */
+
+#define dprintk(IOC, CMD)                      \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG)
+
+#define dsgprintk(IOC, CMD)                    \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG)
+
+#define devtprintk(IOC, CMD)                   \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS)
+
+#define dewtprintk(IOC, CMD)           \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK)
+
+#define dinitprintk(IOC, CMD)                  \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT)
+
+#define dexitprintk(IOC, CMD)                  \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT)
+
+#define dfailprintk(IOC, CMD)                  \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL)
+
+#define dtmprintk(IOC, CMD)                    \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM)
+
+#define dreplyprintk(IOC, CMD)                 \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY)
+
+#define dhsprintk(IOC, CMD)                    \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE)
+
+#define dcprintk(IOC, CMD)                     \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG)
+
+#define ddlprintk(IOC, CMD)                    \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL)
+
+#define drsprintk(IOC, CMD)                    \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET)
+
+#define dsprintk(IOC, CMD)                     \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI)
+
+#define dctlprintk(IOC, CMD)                   \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
+
+#define dsasprintk(IOC, CMD)                   \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS)
+
+#define dsastransport(IOC, CMD)                \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
+
+#define dmfprintk(IOC, CMD)                    \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME)
+
+#define dtsfprintk(IOC, CMD)                   \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL)
+
+#define dtransportprintk(IOC, CMD)                     \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT)
+
+#define dTriggerDiagPrintk(IOC, CMD)                   \
+       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRIGGER_DIAG)
+
+
+
+/* inline functions for dumping debug data*/
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _debug_dump_mf - print message frame contents
+ * @mpi_request: pointer to message frame
+ * @sz: number of dwords
+ */
+static inline void
+_debug_dump_mf(void *mpi_request, int sz)
+{
+       int i;
+       __le32 *mfp = (__le32 *)mpi_request;
+
+       pr_info("mf:\n\t");
+       for (i = 0; i < sz; i++) {
+               if (i && ((i % 8) == 0))
+                       pr_info("\n\t");
+               pr_info("%08x ", le32_to_cpu(mfp[i]));
+       }
+       pr_info("\n");
+}
+/**
+ * _debug_dump_reply - print message frame contents
+ * @mpi_request: pointer to message frame
+ * @sz: number of dwords
+ */
+static inline void
+_debug_dump_reply(void *mpi_request, int sz)
+{
+       int i;
+       __le32 *mfp = (__le32 *)mpi_request;
+
+       pr_info("reply:\n\t");
+       for (i = 0; i < sz; i++) {
+               if (i && ((i % 8) == 0))
+                       pr_info("\n\t");
+               pr_info("%08x ", le32_to_cpu(mfp[i]));
+       }
+       pr_info("\n");
+}
+/**
+ * _debug_dump_config - print config page contents
+ * @mpi_request: pointer to message frame
+ * @sz: number of dwords
+ */
+static inline void
+_debug_dump_config(void *mpi_request, int sz)
+{
+       int i;
+       __le32 *mfp = (__le32 *)mpi_request;
+
+       pr_info("config:\n\t");
+       for (i = 0; i < sz; i++) {
+               if (i && ((i % 8) == 0))
+                       pr_info("\n\t");
+               pr_info("%08x ", le32_to_cpu(mfp[i]));
+       }
+       pr_info("\n");
+}
+#else
+#define _debug_dump_mf(mpi_request, sz)
+#define _debug_dump_reply(mpi_request, sz)
+#define _debug_dump_config(mpi_request, sz)
+#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
+
+#endif /* MPT3SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
new file mode 100644 (file)
index 0000000..05f8045
--- /dev/null
@@ -0,0 +1,8167 @@
+/*
+ * Scsi Host Layer for MPT (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/aer.h>
+#include <linux/raid_class.h>
+
+#include "mpt3sas_base.h"
+
+MODULE_AUTHOR(MPT3SAS_AUTHOR);
+MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
+
+#define RAID_CHANNEL 1
+/* forward proto's */
+static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_expander);
+static void _firmware_event_work(struct work_struct *work);
+
+static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_device *sas_device);
+static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       u8 retry_count, u8 is_pd);
+
+static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+
+static void _scsih_scan_start(struct Scsi_Host *shost);
+static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
+
+/* global parameters */
+LIST_HEAD(mpt3sas_ioc_list);
+
+/* local parameters */
+static u8 scsi_io_cb_idx = -1;
+static u8 tm_cb_idx = -1;
+static u8 ctl_cb_idx = -1;
+static u8 base_cb_idx = -1;
+static u8 port_enable_cb_idx = -1;
+static u8 transport_cb_idx = -1;
+static u8 scsih_cb_idx = -1;
+static u8 config_cb_idx = -1;
+static int mpt_ids;
+
+static u8 tm_tr_cb_idx = -1 ;
+static u8 tm_tr_volume_cb_idx = -1 ;
+static u8 tm_sas_control_cb_idx = -1;
+
+/* command line options */
+static u32 logging_level;
+MODULE_PARM_DESC(logging_level,
+       " bits for enabling additional logging info (default=0)");
+
+
+static ushort max_sectors = 0xFFFF;
+module_param(max_sectors, ushort, 0);
+MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767  default=32767");
+
+
+static int missing_delay[2] = {-1, -1};
+module_param_array(missing_delay, int, NULL, 0);
+MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
+
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPT3SAS_MAX_LUN (16895)
+static int max_lun = MPT3SAS_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
+
+
+
+/* diag_buffer_enable is bitwise
+ * bit 0 set = TRACE
+ * bit 1 set = SNAPSHOT
+ * bit 2 set = EXTENDED
+ *
+ * Either bit can be set, or both
+ */
+static int diag_buffer_enable = -1;
+module_param(diag_buffer_enable, int, 0);
+MODULE_PARM_DESC(diag_buffer_enable,
+       " post diag buffers (TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
+static int disable_discovery = -1;
+module_param(disable_discovery, int, 0);
+MODULE_PARM_DESC(disable_discovery, " disable discovery ");
+
+
+/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
+static int prot_mask = -1;
+module_param(prot_mask, int, 0);
+MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
+
+
+/* raid transport support */
+
+static struct raid_template *mpt3sas_raid_template;
+
+
+/**
+ * struct sense_info - common structure for obtaining sense keys
+ * @skey: sense key
+ * @asc: additional sense code
+ * @ascq: additional sense code qualifier
+ */
+struct sense_info {
+       u8 skey;
+       u8 asc;
+       u8 ascq;
+};
+
+#define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB)
+#define MPT3SAS_TURN_ON_FAULT_LED (0xFFFC)
+#define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD)
+#define MPT3SAS_ABRT_TASK_SET (0xFFFE)
+#define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
+/**
+ * struct fw_event_work - firmware event struct
+ * @list: link list framework
+ * @work: work object (ioc->fault_reset_work_q)
+ * @cancel_pending_work: flag set during reset handling
+ * @ioc: per adapter object
+ * @device_handle: device handle
+ * @VF_ID: virtual function id
+ * @VP_ID: virtual port id
+ * @ignore: flag meaning this event has been marked to ignore
+ * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
+ * @event_data: reply event data payload follows
+ *
+ * This object stored on ioc->fw_event_list.
+ */
+struct fw_event_work {
+       struct list_head        list;
+       struct work_struct      work;
+       u8                      cancel_pending_work;
+       struct delayed_work     delayed_work;
+
+       struct MPT3SAS_ADAPTER *ioc;
+       u16                     device_handle;
+       u8                      VF_ID;
+       u8                      VP_ID;
+       u8                      ignore;
+       u16                     event;
+       void                    *event_data;
+};
+
+/* raid transport support */
+static struct raid_template *mpt3sas_raid_template;
+
+/**
+ * struct _scsi_io_transfer - scsi io transfer
+ * @handle: sas device handle (assigned by firmware)
+ * @is_raid: flag set for hidden raid components
+ * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
+ * @data_length: data transfer length
+ * @data_dma: dma pointer to data
+ * @sense: sense data
+ * @lun: lun number
+ * @cdb_length: cdb length
+ * @cdb: cdb contents
+ * @timeout: timeout for this command
+ * @VF_ID: virtual function id
+ * @VP_ID: virtual port id
+ * @valid_reply: flag set for reply message
+ * @sense_length: sense length
+ * @ioc_status: ioc status
+ * @scsi_state: scsi state
+ * @scsi_status: scsi staus
+ * @log_info: log information
+ * @transfer_length: data length transfer when there is a reply message
+ *
+ * Used for sending internal scsi commands to devices within this module.
+ * Refer to _scsi_send_scsi_io().
+ */
+struct _scsi_io_transfer {
+       u16     handle;
+       u8      is_raid;
+       enum dma_data_direction dir;
+       u32     data_length;
+       dma_addr_t data_dma;
+       u8      sense[SCSI_SENSE_BUFFERSIZE];
+       u32     lun;
+       u8      cdb_length;
+       u8      cdb[32];
+       u8      timeout;
+       u8      VF_ID;
+       u8      VP_ID;
+       u8      valid_reply;
+  /* the following bits are only valid when 'valid_reply = 1' */
+       u32     sense_length;
+       u16     ioc_status;
+       u8      scsi_state;
+       u8      scsi_status;
+       u32     log_info;
+       u32     transfer_length;
+};
+
+/*
+ * The pci device ids are defined in mpi/mpi2_cnfg.h.
+ */
+static DEFINE_PCI_DEVICE_TABLE(scsih_pci_table) = {
+       /* Fury ~ 3004 and 3008 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Invader ~ 3108 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
+               PCI_ANY_ID, PCI_ANY_ID },
+       {0}     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, scsih_pci_table);
+
+/**
+ * _scsih_set_debug_level - global setting of ioc->logging_level.
+ *
+ * Note: The logging levels are defined in mpt3sas_debug.h.
+ */
+static int
+_scsih_set_debug_level(const char *val, struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+       struct MPT3SAS_ADAPTER *ioc;
+
+       if (ret)
+               return ret;
+
+       pr_info("setting logging_level(0x%08x)\n", logging_level);
+       list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
+               ioc->logging_level = logging_level;
+       return 0;
+}
+module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
+       &logging_level, 0644);
+
+/**
+ * _scsih_srch_boot_sas_address - search based on sas_address
+ * @sas_address: sas address
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static inline int
+_scsih_srch_boot_sas_address(u64 sas_address,
+       Mpi2BootDeviceSasWwid_t *boot_device)
+{
+       return (sas_address == le64_to_cpu(boot_device->SASAddress)) ?  1 : 0;
+}
+
+/**
+ * _scsih_srch_boot_device_name - search based on device name
+ * @device_name: device name specified in INDENTIFY fram
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static inline int
+_scsih_srch_boot_device_name(u64 device_name,
+       Mpi2BootDeviceDeviceName_t *boot_device)
+{
+       return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
+}
+
+/**
+ * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
+ * @enclosure_logical_id: enclosure logical id
+ * @slot_number: slot number
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static inline int
+_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
+       Mpi2BootDeviceEnclosureSlot_t *boot_device)
+{
+       return (enclosure_logical_id == le64_to_cpu(boot_device->
+           EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
+           SlotNumber)) ? 1 : 0;
+}
+
+/**
+ * _scsih_is_boot_device - search for matching boot device.
+ * @sas_address: sas address
+ * @device_name: device name specified in INDENTIFY fram
+ * @enclosure_logical_id: enclosure logical id
+ * @slot_number: slot number
+ * @form: specifies boot device form
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static int
+_scsih_is_boot_device(u64 sas_address, u64 device_name,
+       u64 enclosure_logical_id, u16 slot, u8 form,
+       Mpi2BiosPage2BootDevice_t *boot_device)
+{
+       int rc = 0;
+
+       switch (form) {
+       case MPI2_BIOSPAGE2_FORM_SAS_WWID:
+               if (!sas_address)
+                       break;
+               rc = _scsih_srch_boot_sas_address(
+                   sas_address, &boot_device->SasWwid);
+               break;
+       case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
+               if (!enclosure_logical_id)
+                       break;
+               rc = _scsih_srch_boot_encl_slot(
+                   enclosure_logical_id,
+                   slot, &boot_device->EnclosureSlot);
+               break;
+       case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
+               if (!device_name)
+                       break;
+               rc = _scsih_srch_boot_device_name(
+                   device_name, &boot_device->DeviceName);
+               break;
+       case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
+               break;
+       }
+
+       return rc;
+}
+
+/**
+ * _scsih_get_sas_address - set the sas_address for given device handle
+ * @handle: device handle
+ * @sas_address: sas address
+ *
+ * Returns 0 success, non-zero when failure
+ */
+static int
+_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       u64 *sas_address)
+{
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u32 ioc_status;
+
+       *sas_address = 0;
+
+       if (handle <= ioc->sas_hba.num_phys) {
+               *sas_address = ioc->sas_hba.sas_address;
+               return 0;
+       }
+
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
+               __FILE__, __LINE__, __func__);
+               return -ENXIO;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+               *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+               return 0;
+       }
+
+       /* we hit this becuase the given parent handle doesn't exist */
+       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+               return -ENXIO;
+
+       /* else error case */
+       pr_err(MPT3SAS_FMT
+               "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n",
+               ioc->name, handle, ioc_status,
+            __FILE__, __LINE__, __func__);
+       return -EIO;
+}
+
+/**
+ * _scsih_determine_boot_device - determine boot device.
+ * @ioc: per adapter object
+ * @device: either sas_device or raid_device object
+ * @is_raid: [flag] 1 = raid object, 0 = sas object
+ *
+ * Determines whether this device should be first reported device to
+ * to scsi-ml or sas transport, this purpose is for persistent boot device.
+ * There are primary, alternate, and current entries in bios page 2. The order
+ * priority is primary, alternate, then current.  This routine saves
+ * the corresponding device object and is_raid flag in the ioc object.
+ * The saved data to be used later in _scsih_probe_boot_devices().
+ */
+static void
+_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
+       void *device, u8 is_raid)
+{
+       struct _sas_device *sas_device;
+       struct _raid_device *raid_device;
+       u64 sas_address;
+       u64 device_name;
+       u64 enclosure_logical_id;
+       u16 slot;
+
+        /* only process this function when driver loads */
+       if (!ioc->is_driver_loading)
+               return;
+
+        /* no Bios, return immediately */
+       if (!ioc->bios_pg3.BiosVersion)
+               return;
+
+       if (!is_raid) {
+               sas_device = device;
+               sas_address = sas_device->sas_address;
+               device_name = sas_device->device_name;
+               enclosure_logical_id = sas_device->enclosure_logical_id;
+               slot = sas_device->slot;
+       } else {
+               raid_device = device;
+               sas_address = raid_device->wwid;
+               device_name = 0;
+               enclosure_logical_id = 0;
+               slot = 0;
+       }
+
+       if (!ioc->req_boot_device.device) {
+               if (_scsih_is_boot_device(sas_address, device_name,
+                   enclosure_logical_id, slot,
+                   (ioc->bios_pg2.ReqBootDeviceForm &
+                   MPI2_BIOSPAGE2_FORM_MASK),
+                   &ioc->bios_pg2.RequestedBootDevice)) {
+                       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+                          "%s: req_boot_device(0x%016llx)\n",
+                           ioc->name, __func__,
+                           (unsigned long long)sas_address));
+                       ioc->req_boot_device.device = device;
+                       ioc->req_boot_device.is_raid = is_raid;
+               }
+       }
+
+       if (!ioc->req_alt_boot_device.device) {
+               if (_scsih_is_boot_device(sas_address, device_name,
+                   enclosure_logical_id, slot,
+                   (ioc->bios_pg2.ReqAltBootDeviceForm &
+                   MPI2_BIOSPAGE2_FORM_MASK),
+                   &ioc->bios_pg2.RequestedAltBootDevice)) {
+                       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+                          "%s: req_alt_boot_device(0x%016llx)\n",
+                           ioc->name, __func__,
+                           (unsigned long long)sas_address));
+                       ioc->req_alt_boot_device.device = device;
+                       ioc->req_alt_boot_device.is_raid = is_raid;
+               }
+       }
+
+       if (!ioc->current_boot_device.device) {
+               if (_scsih_is_boot_device(sas_address, device_name,
+                   enclosure_logical_id, slot,
+                   (ioc->bios_pg2.CurrentBootDeviceForm &
+                   MPI2_BIOSPAGE2_FORM_MASK),
+                   &ioc->bios_pg2.CurrentBootDevice)) {
+                       dinitprintk(ioc, pr_info(MPT3SAS_FMT
+                          "%s: current_boot_device(0x%016llx)\n",
+                           ioc->name, __func__,
+                           (unsigned long long)sas_address));
+                       ioc->current_boot_device.device = device;
+                       ioc->current_boot_device.is_raid = is_raid;
+               }
+       }
+}
+
+/**
+ * mpt3sas_scsih_sas_device_find_by_sas_address - sas device search
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for sas_device based on sas_address, then return sas_device
+ * object.
+ */
+struct _sas_device *
+mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address)
+{
+       struct _sas_device *sas_device;
+
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list)
+               if (sas_device->sas_address == sas_address)
+                       return sas_device;
+
+       list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
+               if (sas_device->sas_address == sas_address)
+                       return sas_device;
+
+       return NULL;
+}
+
+/**
+ * _scsih_sas_device_find_by_handle - sas device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for sas_device based on sas_address, then return sas_device
+ * object.
+ */
+static struct _sas_device *
+_scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _sas_device *sas_device;
+
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list)
+               if (sas_device->handle == handle)
+                       return sas_device;
+
+       list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
+               if (sas_device->handle == handle)
+                       return sas_device;
+
+       return NULL;
+}
+
+/**
+ * _scsih_sas_device_remove - remove sas_device from list.
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * Context: This function will acquire ioc->sas_device_lock.
+ *
+ * Removing object and freeing associated memory from the ioc->sas_device_list.
+ */
+static void
+_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_device *sas_device)
+{
+       unsigned long flags;
+
+       if (!sas_device)
+               return;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       list_del(&sas_device->list);
+       kfree(sas_device);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
+/**
+ * _scsih_device_remove_by_handle - removing device object by handle
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _sas_device *sas_device;
+       unsigned long flags;
+
+       if (ioc->shost_recovery)
+               return;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (sas_device)
+               list_del(&sas_device->list);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       if (sas_device)
+               _scsih_remove_device(ioc, sas_device);
+}
+
+/**
+ * mpt3sas_device_remove_by_sas_address - removing device object by sas address
+ * @ioc: per adapter object
+ * @sas_address: device sas_address
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address)
+{
+       struct _sas_device *sas_device;
+       unsigned long flags;
+
+       if (ioc->shost_recovery)
+               return;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+           sas_address);
+       if (sas_device)
+               list_del(&sas_device->list);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       if (sas_device)
+               _scsih_remove_device(ioc, sas_device);
+}
+
+/**
+ * _scsih_sas_device_add - insert sas_device to the list.
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * Context: This function will acquire ioc->sas_device_lock.
+ *
+ * Adding new object to the ioc->sas_device_list.
+ */
+static void
+_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_device *sas_device)
+{
+       unsigned long flags;
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: handle(0x%04x), sas_addr(0x%016llx)\n",
+               ioc->name, __func__, sas_device->handle,
+               (unsigned long long)sas_device->sas_address));
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       list_add_tail(&sas_device->list, &ioc->sas_device_list);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
+            sas_device->sas_address_parent)) {
+               _scsih_sas_device_remove(ioc, sas_device);
+       } else if (!sas_device->starget) {
+               /*
+                * When asyn scanning is enabled, its not possible to remove
+                * devices while scanning is turned on due to an oops in
+                * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
+                */
+               if (!ioc->is_driver_loading)
+                       mpt3sas_transport_port_remove(ioc,
+                           sas_device->sas_address,
+                           sas_device->sas_address_parent);
+               _scsih_sas_device_remove(ioc, sas_device);
+       }
+}
+
+/**
+ * _scsih_sas_device_init_add - insert sas_device to the list.
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * Context: This function will acquire ioc->sas_device_lock.
+ *
+ * Adding new object at driver load time to the ioc->sas_device_init_list.
+ */
+static void
+_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_device *sas_device)
+{
+       unsigned long flags;
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
+               __func__, sas_device->handle,
+               (unsigned long long)sas_device->sas_address));
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
+       _scsih_determine_boot_device(ioc, sas_device, 0);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
+/**
+ * _scsih_raid_device_find_by_id - raid device search
+ * @ioc: per adapter object
+ * @id: sas device target id
+ * @channel: sas device channel
+ * Context: Calling function should acquire ioc->raid_device_lock
+ *
+ * This searches for raid_device based on target id, then return raid_device
+ * object.
+ */
+static struct _raid_device *
+_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
+{
+       struct _raid_device *raid_device, *r;
+
+       r = NULL;
+       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+               if (raid_device->id == id && raid_device->channel == channel) {
+                       r = raid_device;
+                       goto out;
+               }
+       }
+
+ out:
+       return r;
+}
+
+/**
+ * _scsih_raid_device_find_by_handle - raid device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->raid_device_lock
+ *
+ * This searches for raid_device based on handle, then return raid_device
+ * object.
+ */
+static struct _raid_device *
+_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _raid_device *raid_device, *r;
+
+       r = NULL;
+       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+               if (raid_device->handle != handle)
+                       continue;
+               r = raid_device;
+               goto out;
+       }
+
+ out:
+       return r;
+}
+
+/**
+ * _scsih_raid_device_find_by_wwid - raid device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->raid_device_lock
+ *
+ * This searches for raid_device based on wwid, then return raid_device
+ * object.
+ */
+static struct _raid_device *
+_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid)
+{
+       struct _raid_device *raid_device, *r;
+
+       r = NULL;
+       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+               if (raid_device->wwid != wwid)
+                       continue;
+               r = raid_device;
+               goto out;
+       }
+
+ out:
+       return r;
+}
+
+/**
+ * _scsih_raid_device_add - add raid_device object
+ * @ioc: per adapter object
+ * @raid_device: raid_device object
+ *
+ * This is added to the raid_device_list link list.
+ */
+static void
+_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc,
+       struct _raid_device *raid_device)
+{
+       unsigned long flags;
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
+           raid_device->handle, (unsigned long long)raid_device->wwid));
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       list_add_tail(&raid_device->list, &ioc->raid_device_list);
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * _scsih_raid_device_remove - delete raid_device object
+ * @ioc: per adapter object
+ * @raid_device: raid_device object
+ *
+ */
+static void
+_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc,
+       struct _raid_device *raid_device)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       list_del(&raid_device->list);
+       kfree(raid_device);
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * mpt3sas_scsih_expander_find_by_handle - expander device search
+ * @ioc: per adapter object
+ * @handle: expander handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for expander device based on handle, then returns the
+ * sas_node object.
+ */
+struct _sas_node *
+mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _sas_node *sas_expander, *r;
+
+       r = NULL;
+       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+               if (sas_expander->handle != handle)
+                       continue;
+               r = sas_expander;
+               goto out;
+       }
+ out:
+       return r;
+}
+
+/**
+ * mpt3sas_scsih_expander_find_by_sas_address - expander device search
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * Context: Calling function should acquire ioc->sas_node_lock.
+ *
+ * This searches for expander device based on sas_address, then returns the
+ * sas_node object.
+ */
+struct _sas_node *
+mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address)
+{
+       struct _sas_node *sas_expander, *r;
+
+       r = NULL;
+       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+               if (sas_expander->sas_address != sas_address)
+                       continue;
+               r = sas_expander;
+               goto out;
+       }
+ out:
+       return r;
+}
+
+/**
+ * _scsih_expander_node_add - insert expander device to the list.
+ * @ioc: per adapter object
+ * @sas_expander: the sas_device object
+ * Context: This function will acquire ioc->sas_node_lock.
+ *
+ * Adding new object to the ioc->sas_expander_list.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_expander)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+}
+
+/**
+ * _scsih_is_end_device - determines if device is an end device
+ * @device_info: bitfield providing information about the device.
+ * Context: none
+ *
+ * Returns 1 if end device.
+ */
+static int
+_scsih_is_end_device(u32 device_info)
+{
+       if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
+               ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
+               (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
+               (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
+               return 1;
+       else
+               return 0;
+}
+
+/**
+ * _scsih_scsi_lookup_get - returns scmd entry
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns the smid stored scmd pointer.
+ */
+static struct scsi_cmnd *
+_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       return ioc->scsi_lookup[smid - 1].scmd;
+}
+
+/**
+ * _scsih_scsi_lookup_get_clear - returns scmd entry
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns the smid stored scmd pointer.
+ * Then will derefrence the stored scmd pointer.
+ */
+static inline struct scsi_cmnd *
+_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       unsigned long flags;
+       struct scsi_cmnd *scmd;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       scmd = ioc->scsi_lookup[smid - 1].scmd;
+       ioc->scsi_lookup[smid - 1].scmd = NULL;
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+       return scmd;
+}
+
+/**
+ * _scsih_scsi_lookup_find_by_scmd - scmd lookup
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @scmd: pointer to scsi command object
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a scmd pointer in the scsi_lookup array,
+ * returning the revelent smid.  A returned value of zero means invalid.
+ */
+static u16
+_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
+       *scmd)
+{
+       u16 smid;
+       unsigned long   flags;
+       int i;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       smid = 0;
+       for (i = 0; i < ioc->scsiio_depth; i++) {
+               if (ioc->scsi_lookup[i].scmd == scmd) {
+                       smid = ioc->scsi_lookup[i].smid;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return smid;
+}
+
+/**
+ * _scsih_scsi_lookup_find_by_target - search for matching channel:id
+ * @ioc: per adapter object
+ * @id: target id
+ * @channel: channel
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a matching channel:id in the scsi_lookup array,
+ * returning 1 if found.
+ */
+static u8
+_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
+       int channel)
+{
+       u8 found;
+       unsigned long   flags;
+       int i;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       found = 0;
+       for (i = 0 ; i < ioc->scsiio_depth; i++) {
+               if (ioc->scsi_lookup[i].scmd &&
+                   (ioc->scsi_lookup[i].scmd->device->id == id &&
+                   ioc->scsi_lookup[i].scmd->device->channel == channel)) {
+                       found = 1;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return found;
+}
+
+/**
+ * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
+ * @ioc: per adapter object
+ * @id: target id
+ * @lun: lun number
+ * @channel: channel
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a matching channel:id:lun in the scsi_lookup array,
+ * returning 1 if found.
+ */
+static u8
+_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
+       unsigned int lun, int channel)
+{
+       u8 found;
+       unsigned long   flags;
+       int i;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       found = 0;
+       for (i = 0 ; i < ioc->scsiio_depth; i++) {
+               if (ioc->scsi_lookup[i].scmd &&
+                   (ioc->scsi_lookup[i].scmd->device->id == id &&
+                   ioc->scsi_lookup[i].scmd->device->channel == channel &&
+                   ioc->scsi_lookup[i].scmd->device->lun == lun)) {
+                       found = 1;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return found;
+}
+
+
+static void
+_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+       struct Scsi_Host *shost = sdev->host;
+       int max_depth;
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+
+       max_depth = shost->can_queue;
+
+       /* limit max device queue for SATA to 32 */
+       sas_device_priv_data = sdev->hostdata;
+       if (!sas_device_priv_data)
+               goto not_sata;
+       sas_target_priv_data = sas_device_priv_data->sas_target;
+       if (!sas_target_priv_data)
+               goto not_sata;
+       if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
+               goto not_sata;
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+          sas_device_priv_data->sas_target->sas_address);
+       if (sas_device && sas_device->device_info &
+           MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+               max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ not_sata:
+
+       if (!sdev->tagged_supported)
+               max_depth = 1;
+       if (qdepth > max_depth)
+               qdepth = max_depth;
+       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+}
+
+/**
+ * _scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
+ * (see include/scsi/scsi_host.h for definition)
+ *
+ * Returns queue depth.
+ */
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+{
+       if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
+               _scsih_adjust_queue_depth(sdev, qdepth);
+       else if (reason == SCSI_QDEPTH_QFULL)
+               scsi_track_queue_full(sdev, qdepth);
+       else
+               return -EOPNOTSUPP;
+
+       if (sdev->inquiry_len > 7)
+               sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " \
+               "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
+               sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
+               sdev->ordered_tags, sdev->scsi_level,
+               (sdev->inquiry[7] & 2) >> 1);
+
+       return sdev->queue_depth;
+}
+
+/**
+ * _scsih_change_queue_type - changing device queue tag type
+ * @sdev: scsi device struct
+ * @tag_type: requested tag type
+ *
+ * Returns queue tag type.
+ */
+static int
+_scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
+{
+       if (sdev->tagged_supported) {
+               scsi_set_tag_type(sdev, tag_type);
+               if (tag_type)
+                       scsi_activate_tcq(sdev, sdev->queue_depth);
+               else
+                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
+       } else
+               tag_type = 0;
+
+       return tag_type;
+}
+
+
+/**
+ * _scsih_target_alloc - target add routine
+ * @starget: scsi target struct
+ *
+ * Returns 0 if ok. Any other return is assumed to be an error and
+ * the device is ignored.
+ */
+static int
+_scsih_target_alloc(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct _sas_device *sas_device;
+       struct _raid_device *raid_device;
+       unsigned long flags;
+       struct sas_rphy *rphy;
+
+       sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
+       if (!sas_target_priv_data)
+               return -ENOMEM;
+
+       starget->hostdata = sas_target_priv_data;
+       sas_target_priv_data->starget = starget;
+       sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
+
+       /* RAID volumes */
+       if (starget->channel == RAID_CHANNEL) {
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
+                   starget->channel);
+               if (raid_device) {
+                       sas_target_priv_data->handle = raid_device->handle;
+                       sas_target_priv_data->sas_address = raid_device->wwid;
+                       sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
+                       raid_device->starget = starget;
+               }
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+               return 0;
+       }
+
+       /* sas/sata devices */
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       rphy = dev_to_rphy(starget->dev.parent);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+          rphy->identify.sas_address);
+
+       if (sas_device) {
+               sas_target_priv_data->handle = sas_device->handle;
+               sas_target_priv_data->sas_address = sas_device->sas_address;
+               sas_device->starget = starget;
+               sas_device->id = starget->id;
+               sas_device->channel = starget->channel;
+               if (test_bit(sas_device->handle, ioc->pd_handles))
+                       sas_target_priv_data->flags |=
+                           MPT_TARGET_FLAGS_RAID_COMPONENT;
+               if (sas_device->fast_path)
+                       sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO;
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       return 0;
+}
+
+/**
+ * _scsih_target_destroy - target destroy routine
+ * @starget: scsi target struct
+ *
+ * Returns nothing.
+ */
+static void
+_scsih_target_destroy(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct _sas_device *sas_device;
+       struct _raid_device *raid_device;
+       unsigned long flags;
+       struct sas_rphy *rphy;
+
+       sas_target_priv_data = starget->hostdata;
+       if (!sas_target_priv_data)
+               return;
+
+       if (starget->channel == RAID_CHANNEL) {
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
+                   starget->channel);
+               if (raid_device) {
+                       raid_device->starget = NULL;
+                       raid_device->sdev = NULL;
+               }
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+               goto out;
+       }
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       rphy = dev_to_rphy(starget->dev.parent);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+          rphy->identify.sas_address);
+       if (sas_device && (sas_device->starget == starget) &&
+           (sas_device->id == starget->id) &&
+           (sas_device->channel == starget->channel))
+               sas_device->starget = NULL;
+
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ out:
+       kfree(sas_target_priv_data);
+       starget->hostdata = NULL;
+}
+
+/**
+ * _scsih_slave_alloc - device add routine
+ * @sdev: scsi device struct
+ *
+ * Returns 0 if ok. Any other return is assumed to be an error and
+ * the device is ignored.
+ */
+static int
+_scsih_slave_alloc(struct scsi_device *sdev)
+{
+       struct Scsi_Host *shost;
+       struct MPT3SAS_ADAPTER *ioc;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_target *starget;
+       struct _raid_device *raid_device;
+       unsigned long flags;
+
+       sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
+       if (!sas_device_priv_data)
+               return -ENOMEM;
+
+       sas_device_priv_data->lun = sdev->lun;
+       sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
+
+       starget = scsi_target(sdev);
+       sas_target_priv_data = starget->hostdata;
+       sas_target_priv_data->num_luns++;
+       sas_device_priv_data->sas_target = sas_target_priv_data;
+       sdev->hostdata = sas_device_priv_data;
+       if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
+               sdev->no_uld_attach = 1;
+
+       shost = dev_to_shost(&starget->dev);
+       ioc = shost_priv(shost);
+       if (starget->channel == RAID_CHANNEL) {
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = _scsih_raid_device_find_by_id(ioc,
+                   starget->id, starget->channel);
+               if (raid_device)
+                       raid_device->sdev = sdev; /* raid is single lun */
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+       }
+
+       return 0;
+}
+
+/**
+ * _scsih_slave_destroy - device destroy routine
+ * @sdev: scsi device struct
+ *
+ * Returns nothing.
+ */
+static void
+_scsih_slave_destroy(struct scsi_device *sdev)
+{
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct scsi_target *starget;
+       struct Scsi_Host *shost;
+       struct MPT3SAS_ADAPTER *ioc;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+
+       if (!sdev->hostdata)
+               return;
+
+       starget = scsi_target(sdev);
+       sas_target_priv_data = starget->hostdata;
+       sas_target_priv_data->num_luns--;
+
+       shost = dev_to_shost(&starget->dev);
+       ioc = shost_priv(shost);
+
+       if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+                  sas_target_priv_data->sas_address);
+               if (sas_device && !sas_target_priv_data->num_luns)
+                       sas_device->starget = NULL;
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       }
+
+       kfree(sdev->hostdata);
+       sdev->hostdata = NULL;
+}
+
+/**
+ * _scsih_display_sata_capabilities - sata capabilities
+ * @ioc: per adapter object
+ * @handle: device handle
+ * @sdev: scsi device struct
+ */
+static void
+_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
+       u16 handle, struct scsi_device *sdev)
+{
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       u32 ioc_status;
+       u16 flags;
+       u32 device_info;
+
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       flags = le16_to_cpu(sas_device_pg0.Flags);
+       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+
+       sdev_printk(KERN_INFO, sdev,
+           "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
+           "sw_preserve(%s)\n",
+           (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
+           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
+           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
+           "n",
+           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
+           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
+           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
+}
+
+/*
+ * raid transport support -
+ * Enabled for SLES11 and newer, in older kernels the driver will panic when
+ * unloading the driver followed by a load - I beleive that the subroutine
+ * raid_class_release() is not cleaning up properly.
+ */
+
+/**
+ * _scsih_is_raid - return boolean indicating device is raid volume
+ * @dev the device struct object
+ */
+static int
+_scsih_is_raid(struct device *dev)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+
+       return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
+}
+
+/**
+ * _scsih_get_resync - get raid volume resync percent complete
+ * @dev the device struct object
+ */
+static void
+_scsih_get_resync(struct device *dev)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
+       static struct _raid_device *raid_device;
+       unsigned long flags;
+       Mpi2RaidVolPage0_t vol_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u32 volume_status_flags;
+       u8 percent_complete;
+       u16 handle;
+
+       percent_complete = 0;
+       handle = 0;
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
+           sdev->channel);
+       if (raid_device) {
+               handle = raid_device->handle;
+               percent_complete = raid_device->percent_complete;
+       }
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+
+       if (!handle)
+               goto out;
+
+       if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
+            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+            sizeof(Mpi2RaidVolPage0_t))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               percent_complete = 0;
+               goto out;
+       }
+
+       volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
+       if (!(volume_status_flags &
+           MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
+               percent_complete = 0;
+
+ out:
+       raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
+}
+
+/**
+ * _scsih_get_state - get raid volume level
+ * @dev the device struct object
+ */
+static void
+_scsih_get_state(struct device *dev)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
+       static struct _raid_device *raid_device;
+       unsigned long flags;
+       Mpi2RaidVolPage0_t vol_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u32 volstate;
+       enum raid_state state = RAID_STATE_UNKNOWN;
+       u16 handle = 0;
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
+           sdev->channel);
+       if (raid_device)
+               handle = raid_device->handle;
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+
+       if (!raid_device)
+               goto out;
+
+       if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
+            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+            sizeof(Mpi2RaidVolPage0_t))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+
+       volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
+       if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
+               state = RAID_STATE_RESYNCING;
+               goto out;
+       }
+
+       switch (vol_pg0.VolumeState) {
+       case MPI2_RAID_VOL_STATE_OPTIMAL:
+       case MPI2_RAID_VOL_STATE_ONLINE:
+               state = RAID_STATE_ACTIVE;
+               break;
+       case  MPI2_RAID_VOL_STATE_DEGRADED:
+               state = RAID_STATE_DEGRADED;
+               break;
+       case MPI2_RAID_VOL_STATE_FAILED:
+       case MPI2_RAID_VOL_STATE_MISSING:
+               state = RAID_STATE_OFFLINE;
+               break;
+       }
+ out:
+       raid_set_state(mpt3sas_raid_template, dev, state);
+}
+
+/**
+ * _scsih_set_level - set raid level
+ * @sdev: scsi device struct
+ * @volume_type: volume type
+ */
+static void
+_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
+{
+       enum raid_level level = RAID_LEVEL_UNKNOWN;
+
+       switch (volume_type) {
+       case MPI2_RAID_VOL_TYPE_RAID0:
+               level = RAID_LEVEL_0;
+               break;
+       case MPI2_RAID_VOL_TYPE_RAID10:
+               level = RAID_LEVEL_10;
+               break;
+       case MPI2_RAID_VOL_TYPE_RAID1E:
+               level = RAID_LEVEL_1E;
+               break;
+       case MPI2_RAID_VOL_TYPE_RAID1:
+               level = RAID_LEVEL_1;
+               break;
+       }
+
+       raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level);
+}
+
+
+/**
+ * _scsih_get_volume_capabilities - volume capabilities
+ * @ioc: per adapter object
+ * @sas_device: the raid_device object
+ *
+ * Returns 0 for success, else 1
+ */
+static int
+_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
+       struct _raid_device *raid_device)
+{
+       Mpi2RaidVolPage0_t *vol_pg0;
+       Mpi2RaidPhysDiskPage0_t pd_pg0;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 sz;
+       u8 num_pds;
+
+       if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
+           &num_pds)) || !num_pds) {
+               dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               return 1;
+       }
+
+       raid_device->num_pds = num_pds;
+       sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
+           sizeof(Mpi2RaidVol0PhysDisk_t));
+       vol_pg0 = kzalloc(sz, GFP_KERNEL);
+       if (!vol_pg0) {
+               dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               return 1;
+       }
+
+       if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
+            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
+               dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               kfree(vol_pg0);
+               return 1;
+       }
+
+       raid_device->volume_type = vol_pg0->VolumeType;
+
+       /* figure out what the underlying devices are by
+        * obtaining the device_info bits for the 1st device
+        */
+       if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+           &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
+           vol_pg0->PhysDisk[0].PhysDiskNum))) {
+               if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+                   le16_to_cpu(pd_pg0.DevHandle)))) {
+                       raid_device->device_info =
+                           le32_to_cpu(sas_device_pg0.DeviceInfo);
+               }
+       }
+
+       kfree(vol_pg0);
+       return 0;
+}
+
+
+
+/**
+ * _scsih_enable_tlr - setting TLR flags
+ * @ioc: per adapter object
+ * @sdev: scsi device struct
+ *
+ * Enabling Transaction Layer Retries for tape devices when
+ * vpd page 0x90 is present
+ *
+ */
+static void
+_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
+{
+
+       /* only for TAPE */
+       if (sdev->type != TYPE_TAPE)
+               return;
+
+       if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
+               return;
+
+       sas_enable_tlr(sdev);
+       sdev_printk(KERN_INFO, sdev, "TLR %s\n",
+           sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
+       return;
+
+}
+
+/**
+ * _scsih_slave_configure - device configure routine.
+ * @sdev: scsi device struct
+ *
+ * Returns 0 if ok. Any other return is assumed to be an error and
+ * the device is ignored.
+ */
+static int
+_scsih_slave_configure(struct scsi_device *sdev)
+{
+       struct Scsi_Host *shost = sdev->host;
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct _sas_device *sas_device;
+       struct _raid_device *raid_device;
+       unsigned long flags;
+       int qdepth;
+       u8 ssp_target = 0;
+       char *ds = "";
+       char *r_level = "";
+       u16 handle, volume_handle = 0;
+       u64 volume_wwid = 0;
+
+       qdepth = 1;
+       sas_device_priv_data = sdev->hostdata;
+       sas_device_priv_data->configured_lun = 1;
+       sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
+       sas_target_priv_data = sas_device_priv_data->sas_target;
+       handle = sas_target_priv_data->handle;
+
+       /* raid volume handling */
+       if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
+
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+               if (!raid_device) {
+                       dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+                           __LINE__, __func__));
+                       return 1;
+               }
+
+               if (_scsih_get_volume_capabilities(ioc, raid_device)) {
+                       dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+                           __LINE__, __func__));
+                       return 1;
+               }
+
+
+               /* RAID Queue Depth Support
+                * IS volume = underlying qdepth of drive type, either
+                *    MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH
+                * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH)
+                */
+               if (raid_device->device_info &
+                   MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
+                       qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
+                       ds = "SSP";
+               } else {
+                       qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
+                        if (raid_device->device_info &
+                           MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+                               ds = "SATA";
+                       else
+                               ds = "STP";
+               }
+
+               switch (raid_device->volume_type) {
+               case MPI2_RAID_VOL_TYPE_RAID0:
+                       r_level = "RAID0";
+                       break;
+               case MPI2_RAID_VOL_TYPE_RAID1E:
+                       qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
+                       if (ioc->manu_pg10.OEMIdentifier &&
+                           (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
+                           MFG10_GF0_R10_DISPLAY) &&
+                           !(raid_device->num_pds % 2))
+                               r_level = "RAID10";
+                       else
+                               r_level = "RAID1E";
+                       break;
+               case MPI2_RAID_VOL_TYPE_RAID1:
+                       qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
+                       r_level = "RAID1";
+                       break;
+               case MPI2_RAID_VOL_TYPE_RAID10:
+                       qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
+                       r_level = "RAID10";
+                       break;
+               case MPI2_RAID_VOL_TYPE_UNKNOWN:
+               default:
+                       qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
+                       r_level = "RAIDX";
+                       break;
+               }
+
+               sdev_printk(KERN_INFO, sdev,
+                       "%s: handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
+                        r_level, raid_device->handle,
+                        (unsigned long long)raid_device->wwid,
+                        raid_device->num_pds, ds);
+
+
+               _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+
+/* raid transport support */
+               _scsih_set_level(sdev, raid_device->volume_type);
+               return 0;
+       }
+
+       /* non-raid handling */
+       if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+               if (mpt3sas_config_get_volume_handle(ioc, handle,
+                   &volume_handle)) {
+                       dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name,
+                           __FILE__, __LINE__, __func__));
+                       return 1;
+               }
+               if (volume_handle && mpt3sas_config_get_volume_wwid(ioc,
+                   volume_handle, &volume_wwid)) {
+                       dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name,
+                           __FILE__, __LINE__, __func__));
+                       return 1;
+               }
+       }
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+          sas_device_priv_data->sas_target->sas_address);
+       if (!sas_device) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               dfailprintk(ioc, pr_warn(MPT3SAS_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               return 1;
+       }
+
+       sas_device->volume_handle = volume_handle;
+       sas_device->volume_wwid = volume_wwid;
+       if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
+               qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
+               ssp_target = 1;
+               ds = "SSP";
+       } else {
+               qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
+               if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
+                       ds = "STP";
+               else if (sas_device->device_info &
+                   MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+                       ds = "SATA";
+       }
+
+       sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \
+           "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
+           ds, handle, (unsigned long long)sas_device->sas_address,
+           sas_device->phy, (unsigned long long)sas_device->device_name);
+       sdev_printk(KERN_INFO, sdev,
+               "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
+               ds, (unsigned long long)
+           sas_device->enclosure_logical_id, sas_device->slot);
+
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (!ssp_target)
+               _scsih_display_sata_capabilities(ioc, handle, sdev);
+
+
+       _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+
+       if (ssp_target) {
+               sas_read_port_mode_page(sdev);
+               _scsih_enable_tlr(ioc, sdev);
+       }
+
+       return 0;
+}
+
+/**
+ * _scsih_bios_param - fetch head, sector, cylinder info for a disk
+ * @sdev: scsi device struct
+ * @bdev: pointer to block device context
+ * @capacity: device size (in 512 byte sectors)
+ * @params: three element array to place output:
+ *              params[0] number of heads (max 255)
+ *              params[1] number of sectors (max 63)
+ *              params[2] number of cylinders
+ *
+ * Return nothing.
+ */
+static int
+_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+       sector_t capacity, int params[])
+{
+       int             heads;
+       int             sectors;
+       sector_t        cylinders;
+       ulong           dummy;
+
+       heads = 64;
+       sectors = 32;
+
+       dummy = heads * sectors;
+       cylinders = capacity;
+       sector_div(cylinders, dummy);
+
+       /*
+        * Handle extended translation size for logical drives
+        * > 1Gb
+        */
+       if ((ulong)capacity >= 0x200000) {
+               heads = 255;
+               sectors = 63;
+               dummy = heads * sectors;
+               cylinders = capacity;
+               sector_div(cylinders, dummy);
+       }
+
+       /* return result */
+       params[0] = heads;
+       params[1] = sectors;
+       params[2] = cylinders;
+
+       return 0;
+}
+
+/**
+ * _scsih_response_code - translation of device response code
+ * @ioc: per adapter object
+ * @response_code: response code returned by the device
+ *
+ * Return nothing.
+ */
+static void
+_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code)
+{
+       char *desc;
+
+       switch (response_code) {
+       case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
+               desc = "task management request completed";
+               break;
+       case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
+               desc = "invalid frame";
+               break;
+       case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
+               desc = "task management request not supported";
+               break;
+       case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
+               desc = "task management request failed";
+               break;
+       case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
+               desc = "task management request succeeded";
+               break;
+       case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
+               desc = "invalid lun";
+               break;
+       case 0xA:
+               desc = "overlapped tag attempted";
+               break;
+       case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
+               desc = "task queued, however not sent to target";
+               break;
+       default:
+               desc = "unknown";
+               break;
+       }
+       pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n",
+               ioc->name, response_code, desc);
+}
+
+/**
+ * _scsih_tm_done - tm completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: none.
+ *
+ * The callback handler when using scsih_issue_tm.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+
+       if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+       if (ioc->tm_cmds.smid != smid)
+               return 1;
+       mpt3sas_base_flush_reply_queues(ioc);
+       ioc->tm_cmds.status |= MPT3_CMD_COMPLETE;
+       mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (mpi_reply) {
+               memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+               ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID;
+       }
+       ioc->tm_cmds.status &= ~MPT3_CMD_PENDING;
+       complete(&ioc->tm_cmds.done);
+       return 1;
+}
+
+/**
+ * mpt3sas_scsih_set_tm_flag - set per target tm_busy
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During taskmangement request, we need to freeze the device queue.
+ */
+void
+mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+       u8 skip = 0;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               if (skip)
+                       continue;
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (sas_device_priv_data->sas_target->handle == handle) {
+                       sas_device_priv_data->sas_target->tm_busy = 1;
+                       skip = 1;
+                       ioc->ignore_loginfos = 1;
+               }
+       }
+}
+
+/**
+ * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During taskmangement request, we need to freeze the device queue.
+ */
+void
+mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+       u8 skip = 0;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               if (skip)
+                       continue;
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (sas_device_priv_data->sas_target->handle == handle) {
+                       sas_device_priv_data->sas_target->tm_busy = 0;
+                       skip = 1;
+                       ioc->ignore_loginfos = 0;
+               }
+       }
+}
+
+/**
+ * mpt3sas_scsih_issue_tm - main routine for sending tm requests
+ * @ioc: per adapter struct
+ * @device_handle: device handle
+ * @channel: the channel assigned by the OS
+ * @id: the id assigned by the OS
+ * @lun: lun number
+ * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
+ * @smid_task: smid assigned to the task
+ * @timeout: timeout in seconds
+ * @serial_number: the serial_number from scmd
+ * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
+ * Context: user
+ *
+ * A generic API for sending task management requests to firmware.
+ *
+ * The callback index is set inside `ioc->tm_cb_idx`.
+ *
+ * Return SUCCESS or FAILED.
+ */
+int
+mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
+       uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
+       unsigned long serial_number, enum mutex_type m_type)
+{
+       Mpi2SCSITaskManagementRequest_t *mpi_request;
+       Mpi2SCSITaskManagementReply_t *mpi_reply;
+       u16 smid = 0;
+       u32 ioc_state;
+       unsigned long timeleft;
+       struct scsiio_tracker *scsi_lookup = NULL;
+       int rc;
+
+       if (m_type == TM_MUTEX_ON)
+               mutex_lock(&ioc->tm_cmds.mutex);
+       if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n",
+                   __func__, ioc->name);
+               rc = FAILED;
+               goto err_out;
+       }
+
+       if (ioc->shost_recovery || ioc->remove_host ||
+           ioc->pci_error_recovery) {
+               pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               rc = FAILED;
+               goto err_out;
+       }
+
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+       if (ioc_state & MPI2_DOORBELL_USED) {
+               dhsprintk(ioc, pr_info(MPT3SAS_FMT
+                       "unexpected doorbell active!\n", ioc->name));
+               rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+               rc = (!rc) ? SUCCESS : FAILED;
+               goto err_out;
+       }
+
+       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+               mpt3sas_base_fault_info(ioc, ioc_state &
+                   MPI2_DOORBELL_DATA_MASK);
+               rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+               rc = (!rc) ? SUCCESS : FAILED;
+               goto err_out;
+       }
+
+       smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = FAILED;
+               goto err_out;
+       }
+
+       if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+               scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
+
+       dtmprintk(ioc, pr_info(MPT3SAS_FMT
+               "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
+               ioc->name, handle, type, smid_task));
+       ioc->tm_cmds.status = MPT3_CMD_PENDING;
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->tm_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+       memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
+       mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+       mpi_request->DevHandle = cpu_to_le16(handle);
+       mpi_request->TaskType = type;
+       mpi_request->TaskMID = cpu_to_le16(smid_task);
+       int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
+       mpt3sas_scsih_set_tm_flag(ioc, handle);
+       init_completion(&ioc->tm_cmds.done);
+       mpt3sas_base_put_smid_hi_priority(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
+       if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SCSITaskManagementRequest_t)/4);
+               if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) {
+                       rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                           FORCE_BIG_HAMMER);
+                       rc = (!rc) ? SUCCESS : FAILED;
+                       ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
+                       mpt3sas_scsih_clear_tm_flag(ioc, handle);
+                       goto err_out;
+               }
+       }
+
+       if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) {
+               mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
+               mpi_reply = ioc->tm_cmds.reply;
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \
+                   "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+                   le32_to_cpu(mpi_reply->IOCLogInfo),
+                   le32_to_cpu(mpi_reply->TerminationCount)));
+               if (ioc->logging_level & MPT_DEBUG_TM) {
+                       _scsih_response_code(ioc, mpi_reply->ResponseCode);
+                       if (mpi_reply->IOCStatus)
+                               _debug_dump_mf(mpi_request,
+                                   sizeof(Mpi2SCSITaskManagementRequest_t)/4);
+               }
+       }
+
+       switch (type) {
+       case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+               rc = SUCCESS;
+               if (scsi_lookup->scmd == NULL)
+                       break;
+               rc = FAILED;
+               break;
+
+       case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+               if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
+                       rc = FAILED;
+               else
+                       rc = SUCCESS;
+               break;
+       case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
+       case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
+               if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
+                       rc = FAILED;
+               else
+                       rc = SUCCESS;
+               break;
+       case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+               rc = SUCCESS;
+               break;
+       default:
+               rc = FAILED;
+               break;
+       }
+
+       mpt3sas_scsih_clear_tm_flag(ioc, handle);
+       ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
+       if (m_type == TM_MUTEX_ON)
+               mutex_unlock(&ioc->tm_cmds.mutex);
+
+       return rc;
+
+ err_out:
+       if (m_type == TM_MUTEX_ON)
+               mutex_unlock(&ioc->tm_cmds.mutex);
+       return rc;
+}
+
+/**
+ * _scsih_tm_display_info - displays info about the device
+ * @ioc: per adapter struct
+ * @scmd: pointer to scsi command object
+ *
+ * Called by task management callback handlers.
+ */
+static void
+_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
+{
+       struct scsi_target *starget = scmd->device->sdev_target;
+       struct MPT3SAS_TARGET *priv_target = starget->hostdata;
+       struct _sas_device *sas_device = NULL;
+       unsigned long flags;
+       char *device_str = NULL;
+
+       if (!priv_target)
+               return;
+       device_str = "volume";
+
+       scsi_print_command(scmd);
+       if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
+               starget_printk(KERN_INFO, starget,
+                       "%s handle(0x%04x), %s wwid(0x%016llx)\n",
+                       device_str, priv_target->handle,
+                   device_str, (unsigned long long)priv_target->sas_address);
+       } else {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+                   priv_target->sas_address);
+               if (sas_device) {
+                       if (priv_target->flags &
+                           MPT_TARGET_FLAGS_RAID_COMPONENT) {
+                               starget_printk(KERN_INFO, starget,
+                                   "volume handle(0x%04x), "
+                                   "volume wwid(0x%016llx)\n",
+                                   sas_device->volume_handle,
+                                  (unsigned long long)sas_device->volume_wwid);
+                       }
+                       starget_printk(KERN_INFO, starget,
+                           "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
+                           sas_device->handle,
+                           (unsigned long long)sas_device->sas_address,
+                           sas_device->phy);
+                       starget_printk(KERN_INFO, starget,
+                           "enclosure_logical_id(0x%016llx), slot(%d)\n",
+                          (unsigned long long)sas_device->enclosure_logical_id,
+                           sas_device->slot);
+               }
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       }
+}
+
+/**
+ * _scsih_abort - eh threads main abort routine
+ * @scmd: pointer to scsi command object
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+_scsih_abort(struct scsi_cmnd *scmd)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       u16 smid;
+       u16 handle;
+       int r;
+
+       sdev_printk(KERN_INFO, scmd->device,
+               "attempting task abort! scmd(%p)\n", scmd);
+       _scsih_tm_display_info(ioc, scmd);
+
+       sas_device_priv_data = scmd->device->hostdata;
+       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
+               sdev_printk(KERN_INFO, scmd->device,
+                       "device been deleted! scmd(%p)\n", scmd);
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               r = SUCCESS;
+               goto out;
+       }
+
+       /* search for the command */
+       smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
+       if (!smid) {
+               scmd->result = DID_RESET << 16;
+               r = SUCCESS;
+               goto out;
+       }
+
+       /* for hidden raid components and volumes this is not supported */
+       if (sas_device_priv_data->sas_target->flags &
+           MPT_TARGET_FLAGS_RAID_COMPONENT ||
+           sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
+               scmd->result = DID_RESET << 16;
+               r = FAILED;
+               goto out;
+       }
+
+       mpt3sas_halt_firmware(ioc);
+
+       handle = sas_device_priv_data->sas_target->handle;
+       r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
+           scmd->device->id, scmd->device->lun,
+           MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+           scmd->serial_number, TM_MUTEX_ON);
+
+ out:
+       sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
+           ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+       return r;
+}
+
+/**
+ * _scsih_dev_reset - eh threads main device reset routine
+ * @scmd: pointer to scsi command object
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+_scsih_dev_reset(struct scsi_cmnd *scmd)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       u16     handle;
+       int r;
+
+       sdev_printk(KERN_INFO, scmd->device,
+               "attempting device reset! scmd(%p)\n", scmd);
+       _scsih_tm_display_info(ioc, scmd);
+
+       sas_device_priv_data = scmd->device->hostdata;
+       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
+               sdev_printk(KERN_INFO, scmd->device,
+                       "device been deleted! scmd(%p)\n", scmd);
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               r = SUCCESS;
+               goto out;
+       }
+
+       /* for hidden raid components obtain the volume_handle */
+       handle = 0;
+       if (sas_device_priv_data->sas_target->flags &
+           MPT_TARGET_FLAGS_RAID_COMPONENT) {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = _scsih_sas_device_find_by_handle(ioc,
+                  sas_device_priv_data->sas_target->handle);
+               if (sas_device)
+                       handle = sas_device->volume_handle;
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       } else
+               handle = sas_device_priv_data->sas_target->handle;
+
+       if (!handle) {
+               scmd->result = DID_RESET << 16;
+               r = FAILED;
+               goto out;
+       }
+
+       r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
+           scmd->device->id, scmd->device->lun,
+           MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
+           TM_MUTEX_ON);
+
+ out:
+       sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
+           ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+       return r;
+}
+
+/**
+ * _scsih_target_reset - eh threads main target reset routine
+ * @scmd: pointer to scsi command object
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+_scsih_target_reset(struct scsi_cmnd *scmd)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       u16     handle;
+       int r;
+       struct scsi_target *starget = scmd->device->sdev_target;
+
+       starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
+               scmd);
+       _scsih_tm_display_info(ioc, scmd);
+
+       sas_device_priv_data = scmd->device->hostdata;
+       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
+               starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
+                       scmd);
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               r = SUCCESS;
+               goto out;
+       }
+
+       /* for hidden raid components obtain the volume_handle */
+       handle = 0;
+       if (sas_device_priv_data->sas_target->flags &
+           MPT_TARGET_FLAGS_RAID_COMPONENT) {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = _scsih_sas_device_find_by_handle(ioc,
+                  sas_device_priv_data->sas_target->handle);
+               if (sas_device)
+                       handle = sas_device->volume_handle;
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       } else
+               handle = sas_device_priv_data->sas_target->handle;
+
+       if (!handle) {
+               scmd->result = DID_RESET << 16;
+               r = FAILED;
+               goto out;
+       }
+
+       r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
+           scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+           30, 0, TM_MUTEX_ON);
+
+ out:
+       starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
+           ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+       return r;
+}
+
+
+/**
+ * _scsih_host_reset - eh threads main host reset routine
+ * @scmd: pointer to scsi command object
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+_scsih_host_reset(struct scsi_cmnd *scmd)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+       int r, retval;
+
+       pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n",
+           ioc->name, scmd);
+       scsi_print_command(scmd);
+
+       retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+           FORCE_BIG_HAMMER);
+       r = (retval < 0) ? FAILED : SUCCESS;
+       pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n",
+           ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+       return r;
+}
+
+/**
+ * _scsih_fw_event_add - insert and queue up fw_event
+ * @ioc: per adapter object
+ * @fw_event: object describing the event
+ * Context: This function will acquire ioc->fw_event_lock.
+ *
+ * This adds the firmware event object into link list, then queues it up to
+ * be processed from user context.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
+{
+       unsigned long flags;
+
+       if (ioc->firmware_event_thread == NULL)
+               return;
+
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       INIT_LIST_HEAD(&fw_event->list);
+       list_add_tail(&fw_event->list, &ioc->fw_event_list);
+       INIT_WORK(&fw_event->work, _firmware_event_work);
+       queue_work(ioc->firmware_event_thread, &fw_event->work);
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_fw_event_free - delete fw_event
+ * @ioc: per adapter object
+ * @fw_event: object describing the event
+ * Context: This function will acquire ioc->fw_event_lock.
+ *
+ * This removes firmware event object from link list, frees associated memory.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
+       *fw_event)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       list_del(&fw_event->list);
+       kfree(fw_event->event_data);
+       kfree(fw_event);
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+
+ /**
+ * mpt3sas_send_trigger_data_event - send event for processing trigger data
+ * @ioc: per adapter object
+ * @event_data: trigger event data
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
+       struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
+{
+       struct fw_event_work *fw_event;
+
+       if (ioc->is_driver_loading)
+               return;
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event)
+               return;
+       fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC);
+       if (!fw_event->event_data)
+               return;
+       fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
+       fw_event->ioc = ioc;
+       memcpy(fw_event->event_data, event_data, sizeof(*event_data));
+       _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * _scsih_error_recovery_delete_devices - remove devices not responding
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct fw_event_work *fw_event;
+
+       if (ioc->is_driver_loading)
+               return;
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event)
+               return;
+       fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
+       fw_event->ioc = ioc;
+       _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * mpt3sas_port_enable_complete - port enable completed (fake event)
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct fw_event_work *fw_event;
+
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event)
+               return;
+       fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
+       fw_event->ioc = ioc;
+       _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * _scsih_fw_event_cleanup_queue - cleanup event queue
+ * @ioc: per adapter object
+ *
+ * Walk the firmware event queue, either killing timers, or waiting
+ * for outstanding events to complete
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct fw_event_work *fw_event, *next;
+
+       if (list_empty(&ioc->fw_event_list) ||
+            !ioc->firmware_event_thread || in_interrupt())
+               return;
+
+       list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
+               if (cancel_delayed_work(&fw_event->delayed_work)) {
+                       _scsih_fw_event_free(ioc, fw_event);
+                       continue;
+               }
+               fw_event->cancel_pending_work = 1;
+       }
+}
+
+/**
+ * _scsih_ublock_io_all_device - unblock every device
+ * @ioc: per adapter object
+ *
+ * change the device state from block to running
+ */
+static void
+_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (!sas_device_priv_data->block)
+                       continue;
+
+               sas_device_priv_data->block = 0;
+               dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
+                       "device_running, handle(0x%04x)\n",
+                   sas_device_priv_data->sas_target->handle));
+               scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+       }
+}
+
+
+/**
+ * _scsih_ublock_io_device - prepare device to be deleted
+ * @ioc: per adapter object
+ * @sas_addr: sas address
+ *
+ * unblock then put device in offline state
+ */
+static void
+_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (sas_device_priv_data->sas_target->sas_address
+                   != sas_address)
+                       continue;
+               if (sas_device_priv_data->block) {
+                       sas_device_priv_data->block = 0;
+                       scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+               }
+       }
+}
+
+/**
+ * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (sas_device_priv_data->block)
+                       continue;
+               sas_device_priv_data->block = 1;
+               scsi_internal_device_block(sdev);
+               sdev_printk(KERN_INFO, sdev, "device_blocked, handle(0x%04x)\n",
+                   sas_device_priv_data->sas_target->handle);
+       }
+}
+
+/**
+ * _scsih_block_io_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (sas_device_priv_data->sas_target->handle != handle)
+                       continue;
+               if (sas_device_priv_data->block)
+                       continue;
+               sas_device_priv_data->block = 1;
+               scsi_internal_device_block(sdev);
+               sdev_printk(KERN_INFO, sdev,
+                       "device_blocked, handle(0x%04x)\n", handle);
+       }
+}
+
+/**
+ * _scsih_block_io_to_children_attached_to_ex
+ * @ioc: per adapter object
+ * @sas_expander: the sas_device object
+ *
+ * This routine set sdev state to SDEV_BLOCK for all devices
+ * attached to this expander. This function called when expander is
+ * pulled.
+ */
+static void
+_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_expander)
+{
+       struct _sas_port *mpt3sas_port;
+       struct _sas_device *sas_device;
+       struct _sas_node *expander_sibling;
+       unsigned long flags;
+
+       if (!sas_expander)
+               return;
+
+       list_for_each_entry(mpt3sas_port,
+          &sas_expander->sas_port_list, port_list) {
+               if (mpt3sas_port->remote_identify.device_type ==
+                   SAS_END_DEVICE) {
+                       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+                       sas_device =
+                           mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+                          mpt3sas_port->remote_identify.sas_address);
+                       if (sas_device)
+                               set_bit(sas_device->handle,
+                                   ioc->blocking_handles);
+                       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               }
+       }
+
+       list_for_each_entry(mpt3sas_port,
+          &sas_expander->sas_port_list, port_list) {
+
+               if (mpt3sas_port->remote_identify.device_type ==
+                   SAS_EDGE_EXPANDER_DEVICE ||
+                   mpt3sas_port->remote_identify.device_type ==
+                   SAS_FANOUT_EXPANDER_DEVICE) {
+                       expander_sibling =
+                           mpt3sas_scsih_expander_find_by_sas_address(
+                           ioc, mpt3sas_port->remote_identify.sas_address);
+                       _scsih_block_io_to_children_attached_to_ex(ioc,
+                           expander_sibling);
+               }
+       }
+}
+
+/**
+ * _scsih_block_io_to_children_attached_directly
+ * @ioc: per adapter object
+ * @event_data: topology change event data
+ *
+ * This routine set sdev state to SDEV_BLOCK for all devices
+ * direct attached during device pull.
+ */
+static void
+_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+       int i;
+       u16 handle;
+       u16 reason_code;
+       u8 phy_number;
+
+       for (i = 0; i < event_data->NumEntries; i++) {
+               handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+               if (!handle)
+                       continue;
+               phy_number = event_data->StartPhyNum + i;
+               reason_code = event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
+                       _scsih_block_io_device(ioc, handle);
+       }
+}
+
+/**
+ * _scsih_tm_tr_send - send task management request
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt time.
+ *
+ * This code is to initiate the device removal handshake protocol
+ * with controller firmware.  This function will issue target reset
+ * using high priority request queue.  It will send a sas iounit
+ * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
+ *
+ * This is designed to send muliple task management request at the same
+ * time to the fifo. If the fifo is full, we will append the request,
+ * and process it in a future completion.
+ */
+static void
+_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       Mpi2SCSITaskManagementRequest_t *mpi_request;
+       u16 smid;
+       struct _sas_device *sas_device;
+       struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
+       u64 sas_address = 0;
+       unsigned long flags;
+       struct _tr_list *delayed_tr;
+       u32 ioc_state;
+
+       if (ioc->remove_host) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host has been removed: handle(0x%04x)\n",
+                       __func__, ioc->name, handle));
+               return;
+       } else if (ioc->pci_error_recovery) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host in pci error recovery: handle(0x%04x)\n",
+                       __func__, ioc->name,
+                   handle));
+               return;
+       }
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host is not operational: handle(0x%04x)\n",
+                       __func__, ioc->name,
+                  handle));
+               return;
+       }
+
+       /* if PD, then return */
+       if (test_bit(handle, ioc->pd_handles))
+               return;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (sas_device && sas_device->starget &&
+           sas_device->starget->hostdata) {
+               sas_target_priv_data = sas_device->starget->hostdata;
+               sas_target_priv_data->deleted = 1;
+               sas_address = sas_device->sas_address;
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (sas_target_priv_data) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n",
+                       ioc->name, handle,
+                   (unsigned long long)sas_address));
+               _scsih_ublock_io_device(ioc, sas_address);
+               sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
+       }
+
+       smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
+       if (!smid) {
+               delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
+               if (!delayed_tr)
+                       return;
+               INIT_LIST_HEAD(&delayed_tr->list);
+               delayed_tr->handle = handle;
+               list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "DELAYED:tr:handle(0x%04x), (open)\n",
+                   ioc->name, handle));
+               return;
+       }
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
+               ioc->name, handle, smid,
+           ioc->tm_tr_cb_idx));
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+       mpi_request->DevHandle = cpu_to_le16(handle);
+       mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+       mpt3sas_base_put_smid_hi_priority(ioc, smid);
+       mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
+}
+
+/**
+ * _scsih_tm_tr_complete -
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt time.
+ *
+ * This is the target reset completion routine.
+ * This code is part of the code to initiate the device removal
+ * handshake protocol with controller firmware.
+ * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       u16 handle;
+       Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
+       Mpi2SCSITaskManagementReply_t *mpi_reply =
+           mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       Mpi2SasIoUnitControlRequest_t *mpi_request;
+       u16 smid_sas_ctrl;
+       u32 ioc_state;
+
+       if (ioc->remove_host) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host has been removed\n", __func__, ioc->name));
+               return 1;
+       } else if (ioc->pci_error_recovery) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host in pci error recovery\n", __func__,
+                       ioc->name));
+               return 1;
+       }
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host is not operational\n", __func__, ioc->name));
+               return 1;
+       }
+       if (unlikely(!mpi_reply)) {
+               pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return 1;
+       }
+       mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
+       handle = le16_to_cpu(mpi_request_tm->DevHandle);
+       if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
+               dewtprintk(ioc, pr_err(MPT3SAS_FMT
+                       "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
+                       ioc->name, handle,
+                   le16_to_cpu(mpi_reply->DevHandle), smid));
+               return 0;
+       }
+
+       mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+           "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
+           "loginfo(0x%08x), completed(%d)\n", ioc->name,
+           handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
+           le32_to_cpu(mpi_reply->IOCLogInfo),
+           le32_to_cpu(mpi_reply->TerminationCount)));
+
+       smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
+       if (!smid_sas_ctrl) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               return 1;
+       }
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
+               ioc->name, handle, smid_sas_ctrl,
+           ioc->tm_sas_control_cb_idx));
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl);
+       memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+       mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
+       mpi_request->DevHandle = mpi_request_tm->DevHandle;
+       mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl);
+
+       return _scsih_check_for_pending_tm(ioc, smid);
+}
+
+
+/**
+ * _scsih_sas_control_complete - completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt time.
+ *
+ * This is the sas iounit control completion routine.
+ * This code is part of the code to initiate the device removal
+ * handshake protocol with controller firmware.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       u8 msix_index, u32 reply)
+{
+       Mpi2SasIoUnitControlReply_t *mpi_reply =
+           mpt3sas_base_get_reply_virt_addr(ioc, reply);
+
+       if (likely(mpi_reply)) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "sc_complete:handle(0x%04x), (open) "
+               "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
+               ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
+               le16_to_cpu(mpi_reply->IOCStatus),
+               le32_to_cpu(mpi_reply->IOCLogInfo)));
+       } else {
+               pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+       }
+       return 1;
+}
+
+/**
+ * _scsih_tm_tr_volume_send - send target reset request for volumes
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt time.
+ *
+ * This is designed to send muliple task management request at the same
+ * time to the fifo. If the fifo is full, we will append the request,
+ * and process it in a future completion.
+ */
+static void
+_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       Mpi2SCSITaskManagementRequest_t *mpi_request;
+       u16 smid;
+       struct _tr_list *delayed_tr;
+
+       if (ioc->shost_recovery || ioc->remove_host ||
+           ioc->pci_error_recovery) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host reset in progress!\n",
+                       __func__, ioc->name));
+               return;
+       }
+
+       smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
+       if (!smid) {
+               delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
+               if (!delayed_tr)
+                       return;
+               INIT_LIST_HEAD(&delayed_tr->list);
+               delayed_tr->handle = handle;
+               list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "DELAYED:tr:handle(0x%04x), (open)\n",
+                   ioc->name, handle));
+               return;
+       }
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
+               ioc->name, handle, smid,
+           ioc->tm_tr_volume_cb_idx));
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+       mpi_request->DevHandle = cpu_to_le16(handle);
+       mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+       mpt3sas_base_put_smid_hi_priority(ioc, smid);
+}
+
+/**
+ * _scsih_tm_volume_tr_complete - target reset completion
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt time.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+       u8 msix_index, u32 reply)
+{
+       u16 handle;
+       Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
+       Mpi2SCSITaskManagementReply_t *mpi_reply =
+           mpt3sas_base_get_reply_virt_addr(ioc, reply);
+
+       if (ioc->shost_recovery || ioc->remove_host ||
+           ioc->pci_error_recovery) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: host reset in progress!\n",
+                       __func__, ioc->name));
+               return 1;
+       }
+       if (unlikely(!mpi_reply)) {
+               pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return 1;
+       }
+
+       mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
+       handle = le16_to_cpu(mpi_request_tm->DevHandle);
+       if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
+               dewtprintk(ioc, pr_err(MPT3SAS_FMT
+                       "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
+                       ioc->name, handle,
+                   le16_to_cpu(mpi_reply->DevHandle), smid));
+               return 0;
+       }
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+           "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
+           "loginfo(0x%08x), completed(%d)\n", ioc->name,
+           handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
+           le32_to_cpu(mpi_reply->IOCLogInfo),
+           le32_to_cpu(mpi_reply->TerminationCount)));
+
+       return _scsih_check_for_pending_tm(ioc, smid);
+}
+
+
+/**
+ * _scsih_check_for_pending_tm - check for pending task management
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * This will check delayed target reset list, and feed the
+ * next reqeust.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       struct _tr_list *delayed_tr;
+
+       if (!list_empty(&ioc->delayed_tr_volume_list)) {
+               delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
+                   struct _tr_list, list);
+               mpt3sas_base_free_smid(ioc, smid);
+               _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
+               list_del(&delayed_tr->list);
+               kfree(delayed_tr);
+               return 0;
+       }
+
+       if (!list_empty(&ioc->delayed_tr_list)) {
+               delayed_tr = list_entry(ioc->delayed_tr_list.next,
+                   struct _tr_list, list);
+               mpt3sas_base_free_smid(ioc, smid);
+               _scsih_tm_tr_send(ioc, delayed_tr->handle);
+               list_del(&delayed_tr->list);
+               kfree(delayed_tr);
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ * _scsih_check_topo_delete_events - sanity check on topo events
+ * @ioc: per adapter object
+ * @event_data: the event data payload
+ *
+ * This routine added to better handle cable breaker.
+ *
+ * This handles the case where driver receives multiple expander
+ * add and delete events in a single shot.  When there is a delete event
+ * the routine will void any pending add events waiting in the event queue.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+       struct fw_event_work *fw_event;
+       Mpi2EventDataSasTopologyChangeList_t *local_event_data;
+       u16 expander_handle;
+       struct _sas_node *sas_expander;
+       unsigned long flags;
+       int i, reason_code;
+       u16 handle;
+
+       for (i = 0 ; i < event_data->NumEntries; i++) {
+               handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+               if (!handle)
+                       continue;
+               reason_code = event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
+                       _scsih_tm_tr_send(ioc, handle);
+       }
+
+       expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
+       if (expander_handle < ioc->sas_hba.num_phys) {
+               _scsih_block_io_to_children_attached_directly(ioc, event_data);
+               return;
+       }
+       if (event_data->ExpStatus ==
+           MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
+               /* put expander attached devices into blocking state */
+               spin_lock_irqsave(&ioc->sas_node_lock, flags);
+               sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
+                   expander_handle);
+               _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               do {
+                       handle = find_first_bit(ioc->blocking_handles,
+                           ioc->facts.MaxDevHandle);
+                       if (handle < ioc->facts.MaxDevHandle)
+                               _scsih_block_io_device(ioc, handle);
+               } while (test_and_clear_bit(handle, ioc->blocking_handles));
+       } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
+               _scsih_block_io_to_children_attached_directly(ioc, event_data);
+
+       if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
+               return;
+
+       /* mark ignore flag for pending events */
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
+               if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
+                   fw_event->ignore)
+                       continue;
+               local_event_data = fw_event->event_data;
+               if (local_event_data->ExpStatus ==
+                   MPI2_EVENT_SAS_TOPO_ES_ADDED ||
+                   local_event_data->ExpStatus ==
+                   MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
+                       if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
+                           expander_handle) {
+                               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                                   "setting ignoring flag\n", ioc->name));
+                               fw_event->ignore = 1;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_set_volume_delete_flag - setting volume delete flag
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * This returns nothing.
+ */
+static void
+_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _raid_device *raid_device;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+       if (raid_device && raid_device->starget &&
+           raid_device->starget->hostdata) {
+               sas_target_priv_data =
+                   raid_device->starget->hostdata;
+               sas_target_priv_data->deleted = 1;
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "setting delete flag: handle(0x%04x), "
+                   "wwid(0x%016llx)\n", ioc->name, handle,
+                   (unsigned long long) raid_device->wwid));
+       }
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
+ * @handle: input handle
+ * @a: handle for volume a
+ * @b: handle for volume b
+ *
+ * IR firmware only supports two raid volumes.  The purpose of this
+ * routine is to set the volume handle in either a or b. When the given
+ * input handle is non-zero, or when a and b have not been set before.
+ */
+static void
+_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
+{
+       if (!handle || handle == *a || handle == *b)
+               return;
+       if (!*a)
+               *a = handle;
+       else if (!*b)
+               *b = handle;
+}
+
+/**
+ * _scsih_check_ir_config_unhide_events - check for UNHIDE events
+ * @ioc: per adapter object
+ * @event_data: the event data payload
+ * Context: interrupt time.
+ *
+ * This routine will send target reset to volume, followed by target
+ * resets to the PDs. This is called when a PD has been removed, or
+ * volume has been deleted or removed. When the target reset is sent
+ * to volume, the PD target resets need to be queued to start upon
+ * completion of the volume target reset.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataIrConfigChangeList_t *event_data)
+{
+       Mpi2EventIrConfigElement_t *element;
+       int i;
+       u16 handle, volume_handle, a, b;
+       struct _tr_list *delayed_tr;
+
+       a = 0;
+       b = 0;
+
+       /* Volume Resets for Deleted or Removed */
+       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+       for (i = 0; i < event_data->NumElements; i++, element++) {
+               if (le32_to_cpu(event_data->Flags) &
+                   MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
+                       continue;
+               if (element->ReasonCode ==
+                   MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
+                   element->ReasonCode ==
+                   MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
+                       volume_handle = le16_to_cpu(element->VolDevHandle);
+                       _scsih_set_volume_delete_flag(ioc, volume_handle);
+                       _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
+               }
+       }
+
+       /* Volume Resets for UNHIDE events */
+       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+       for (i = 0; i < event_data->NumElements; i++, element++) {
+               if (le32_to_cpu(event_data->Flags) &
+                   MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
+                       continue;
+               if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
+                       volume_handle = le16_to_cpu(element->VolDevHandle);
+                       _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
+               }
+       }
+
+       if (a)
+               _scsih_tm_tr_volume_send(ioc, a);
+       if (b)
+               _scsih_tm_tr_volume_send(ioc, b);
+
+       /* PD target resets */
+       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+       for (i = 0; i < event_data->NumElements; i++, element++) {
+               if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
+                       continue;
+               handle = le16_to_cpu(element->PhysDiskDevHandle);
+               volume_handle = le16_to_cpu(element->VolDevHandle);
+               clear_bit(handle, ioc->pd_handles);
+               if (!volume_handle)
+                       _scsih_tm_tr_send(ioc, handle);
+               else if (volume_handle == a || volume_handle == b) {
+                       delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
+                       BUG_ON(!delayed_tr);
+                       INIT_LIST_HEAD(&delayed_tr->list);
+                       delayed_tr->handle = handle;
+                       list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                           "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
+                           handle));
+               } else
+                       _scsih_tm_tr_send(ioc, handle);
+       }
+}
+
+
+/**
+ * _scsih_check_volume_delete_events - set delete flag for volumes
+ * @ioc: per adapter object
+ * @event_data: the event data payload
+ * Context: interrupt time.
+ *
+ * This will handle the case when the cable connected to entire volume is
+ * pulled. We will take care of setting the deleted flag so normal IO will
+ * not be sent.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataIrVolume_t *event_data)
+{
+       u32 state;
+
+       if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
+               return;
+       state = le32_to_cpu(event_data->NewValue);
+       if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
+           MPI2_RAID_VOL_STATE_FAILED)
+               _scsih_set_volume_delete_flag(ioc,
+                   le16_to_cpu(event_data->VolDevHandle));
+}
+
+/**
+ * _scsih_flush_running_cmds - completing outstanding commands.
+ * @ioc: per adapter object
+ *
+ * The flushing out of all pending scmd commands following host reset,
+ * where all IO is dropped to the floor.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct scsi_cmnd *scmd;
+       u16 smid;
+       u16 count = 0;
+
+       for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+               scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
+               if (!scmd)
+                       continue;
+               count++;
+               mpt3sas_base_free_smid(ioc, smid);
+               scsi_dma_unmap(scmd);
+               if (ioc->pci_error_recovery)
+                       scmd->result = DID_NO_CONNECT << 16;
+               else
+                       scmd->result = DID_RESET << 16;
+               scmd->scsi_done(scmd);
+       }
+       dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n",
+           ioc->name, count));
+}
+
+/**
+ * _scsih_setup_eedp - setup MPI request for EEDP transfer
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ * @mpi_request: pointer to the SCSI_IO reqest message frame
+ *
+ * Supporting protection 1 and 3.
+ *
+ * Returns nothing
+ */
+static void
+_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+       Mpi2SCSIIORequest_t *mpi_request)
+{
+       u16 eedp_flags;
+       unsigned char prot_op = scsi_get_prot_op(scmd);
+       unsigned char prot_type = scsi_get_prot_type(scmd);
+       Mpi25SCSIIORequest_t *mpi_request_3v =
+          (Mpi25SCSIIORequest_t *)mpi_request;
+
+       if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
+               return;
+
+       if (prot_op ==  SCSI_PROT_READ_STRIP)
+               eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
+       else if (prot_op ==  SCSI_PROT_WRITE_INSERT)
+               eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
+       else
+               return;
+
+       switch (prot_type) {
+       case SCSI_PROT_DIF_TYPE1:
+       case SCSI_PROT_DIF_TYPE2:
+
+               /*
+               * enable ref/guard checking
+               * auto increment ref tag
+               */
+               eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+                   MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
+                   MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
+               mpi_request->CDB.EEDP32.PrimaryReferenceTag =
+                   cpu_to_be32(scsi_get_lba(scmd));
+               break;
+
+       case SCSI_PROT_DIF_TYPE3:
+
+               /*
+               * enable guard checking
+               */
+               eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
+
+               break;
+       }
+
+       mpi_request_3v->EEDPBlockSize =
+           cpu_to_le16(scmd->device->sector_size);
+       mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
+}
+
+/**
+ * _scsih_eedp_error_handling - return sense code for EEDP errors
+ * @scmd: pointer to scsi command object
+ * @ioc_status: ioc status
+ *
+ * Returns nothing
+ */
+static void
+_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
+{
+       u8 ascq;
+
+       switch (ioc_status) {
+       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
+               ascq = 0x01;
+               break;
+       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
+               ascq = 0x02;
+               break;
+       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
+               ascq = 0x03;
+               break;
+       default:
+               ascq = 0x00;
+               break;
+       }
+       scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10,
+           ascq);
+       scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
+           SAM_STAT_CHECK_CONDITION;
+}
+
+
+/**
+ * _scsih_qcmd_lck - main scsi request entry point
+ * @scmd: pointer to scsi command object
+ * @done: function pointer to be invoked on completion
+ *
+ * The callback index is set inside `ioc->scsi_io_cb_idx`.
+ *
+ * Returns 0 on success.  If there's a failure, return either:
+ * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
+ * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
+ */
+static int
+_scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       Mpi2SCSIIORequest_t *mpi_request;
+       u32 mpi_control;
+       u16 smid;
+       u16 handle;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_SCSI)
+               scsi_print_command(scmd);
+#endif
+
+       scmd->scsi_done = done;
+       sas_device_priv_data = scmd->device->hostdata;
+       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+       }
+
+       if (ioc->pci_error_recovery || ioc->remove_host) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+       }
+
+       sas_target_priv_data = sas_device_priv_data->sas_target;
+
+       /* invalid device handle */
+       handle = sas_target_priv_data->handle;
+       if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+       }
+
+
+       /* host recovery or link resets sent via IOCTLs */
+       if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
+       /* device has been deleted */
+       else if (sas_target_priv_data->deleted) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+       /* device busy with task managment */
+       } else if (sas_target_priv_data->tm_busy ||
+           sas_device_priv_data->block)
+               return SCSI_MLQUEUE_DEVICE_BUSY;
+
+       if (scmd->sc_data_direction == DMA_FROM_DEVICE)
+               mpi_control = MPI2_SCSIIO_CONTROL_READ;
+       else if (scmd->sc_data_direction == DMA_TO_DEVICE)
+               mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
+       else
+               mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
+
+       /* set tags */
+       if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
+               if (scmd->device->tagged_supported) {
+                       if (scmd->device->ordered_tags)
+                               mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
+                       else
+                               mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+               } else
+                       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+       } else
+               mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+
+       if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
+           scmd->cmd_len != 32)
+               mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
+
+       smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               goto out;
+       }
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
+       _scsih_setup_eedp(ioc, scmd, mpi_request);
+
+       if (scmd->cmd_len == 32)
+               mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
+       mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+       if (sas_device_priv_data->sas_target->flags &
+           MPT_TARGET_FLAGS_RAID_COMPONENT)
+               mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
+       else
+               mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+       mpi_request->DevHandle = cpu_to_le16(handle);
+       mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
+       mpi_request->Control = cpu_to_le32(mpi_control);
+       mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
+       mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
+       mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
+       mpi_request->SenseBufferLowAddress =
+           mpt3sas_base_get_sense_buffer_dma(ioc, smid);
+       mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
+       int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
+           mpi_request->LUN);
+       memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
+
+       if (mpi_request->DataLength) {
+               if (ioc->build_sg_scmd(ioc, scmd, smid)) {
+                       mpt3sas_base_free_smid(ioc, smid);
+                       goto out;
+               }
+       } else
+               ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
+
+       if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
+               if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
+                       mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
+                           MPI25_SCSIIO_IOFLAGS_FAST_PATH);
+                       mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
+               } else
+                       mpt3sas_base_put_smid_scsi_io(ioc, smid, handle);
+       } else
+               mpt3sas_base_put_smid_default(ioc, smid);
+       return 0;
+
+ out:
+       return SCSI_MLQUEUE_HOST_BUSY;
+}
+static DEF_SCSI_QCMD(_scsih_qcmd)
+
+
+/**
+ * _scsih_normalize_sense - normalize descriptor and fixed format sense data
+ * @sense_buffer: sense data returned by target
+ * @data: normalized skey/asc/ascq
+ *
+ * Return nothing.
+ */
+static void
+_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
+{
+       if ((sense_buffer[0] & 0x7F) >= 0x72) {
+               /* descriptor format */
+               data->skey = sense_buffer[1] & 0x0F;
+               data->asc = sense_buffer[2];
+               data->ascq = sense_buffer[3];
+       } else {
+               /* fixed format */
+               data->skey = sense_buffer[2] & 0x0F;
+               data->asc = sense_buffer[12];
+               data->ascq = sense_buffer[13];
+       }
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ * @mpi_reply: reply mf payload returned from firmware
+ *
+ * scsi_status - SCSI Status code returned from target device
+ * scsi_state - state info associated with SCSI_IO determined by ioc
+ * ioc_status - ioc supplied status info
+ *
+ * Return nothing.
+ */
+static void
+_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+       Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
+{
+       u32 response_info;
+       u8 *response_bytes;
+       u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       u8 scsi_state = mpi_reply->SCSIState;
+       u8 scsi_status = mpi_reply->SCSIStatus;
+       char *desc_ioc_state = NULL;
+       char *desc_scsi_status = NULL;
+       char *desc_scsi_state = ioc->tmp_string;
+       u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
+       struct _sas_device *sas_device = NULL;
+       unsigned long flags;
+       struct scsi_target *starget = scmd->device->sdev_target;
+       struct MPT3SAS_TARGET *priv_target = starget->hostdata;
+       char *device_str = NULL;
+
+       if (!priv_target)
+               return;
+       device_str = "volume";
+
+       if (log_info == 0x31170000)
+               return;
+
+       switch (ioc_status) {
+       case MPI2_IOCSTATUS_SUCCESS:
+               desc_ioc_state = "success";
+               break;
+       case MPI2_IOCSTATUS_INVALID_FUNCTION:
+               desc_ioc_state = "invalid function";
+               break;
+       case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+               desc_ioc_state = "scsi recovered error";
+               break;
+       case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+               desc_ioc_state = "scsi invalid dev handle";
+               break;
+       case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+               desc_ioc_state = "scsi device not there";
+               break;
+       case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+               desc_ioc_state = "scsi data overrun";
+               break;
+       case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+               desc_ioc_state = "scsi data underrun";
+               break;
+       case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+               desc_ioc_state = "scsi io data error";
+               break;
+       case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+               desc_ioc_state = "scsi protocol error";
+               break;
+       case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+               desc_ioc_state = "scsi task terminated";
+               break;
+       case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+               desc_ioc_state = "scsi residual mismatch";
+               break;
+       case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+               desc_ioc_state = "scsi task mgmt failed";
+               break;
+       case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+               desc_ioc_state = "scsi ioc terminated";
+               break;
+       case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+               desc_ioc_state = "scsi ext terminated";
+               break;
+       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
+               desc_ioc_state = "eedp guard error";
+               break;
+       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
+               desc_ioc_state = "eedp ref tag error";
+               break;
+       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
+               desc_ioc_state = "eedp app tag error";
+               break;
+       default:
+               desc_ioc_state = "unknown";
+               break;
+       }
+
+       switch (scsi_status) {
+       case MPI2_SCSI_STATUS_GOOD:
+               desc_scsi_status = "good";
+               break;
+       case MPI2_SCSI_STATUS_CHECK_CONDITION:
+               desc_scsi_status = "check condition";
+               break;
+       case MPI2_SCSI_STATUS_CONDITION_MET:
+               desc_scsi_status = "condition met";
+               break;
+       case MPI2_SCSI_STATUS_BUSY:
+               desc_scsi_status = "busy";
+               break;
+       case MPI2_SCSI_STATUS_INTERMEDIATE:
+               desc_scsi_status = "intermediate";
+               break;
+       case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
+               desc_scsi_status = "intermediate condmet";
+               break;
+       case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
+               desc_scsi_status = "reservation conflict";
+               break;
+       case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
+               desc_scsi_status = "command terminated";
+               break;
+       case MPI2_SCSI_STATUS_TASK_SET_FULL:
+               desc_scsi_status = "task set full";
+               break;
+       case MPI2_SCSI_STATUS_ACA_ACTIVE:
+               desc_scsi_status = "aca active";
+               break;
+       case MPI2_SCSI_STATUS_TASK_ABORTED:
+               desc_scsi_status = "task aborted";
+               break;
+       default:
+               desc_scsi_status = "unknown";
+               break;
+       }
+
+       desc_scsi_state[0] = '\0';
+       if (!scsi_state)
+               desc_scsi_state = " ";
+       if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
+               strcat(desc_scsi_state, "response info ");
+       if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+               strcat(desc_scsi_state, "state terminated ");
+       if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
+               strcat(desc_scsi_state, "no status ");
+       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
+               strcat(desc_scsi_state, "autosense failed ");
+       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
+               strcat(desc_scsi_state, "autosense valid ");
+
+       scsi_print_command(scmd);
+
+       if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
+               pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
+                   device_str, (unsigned long long)priv_target->sas_address);
+       } else {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+                   priv_target->sas_address);
+               if (sas_device) {
+                       pr_warn(MPT3SAS_FMT
+                               "\tsas_address(0x%016llx), phy(%d)\n",
+                               ioc->name, (unsigned long long)
+                           sas_device->sas_address, sas_device->phy);
+                       pr_warn(MPT3SAS_FMT
+                           "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
+                           ioc->name, (unsigned long long)
+                           sas_device->enclosure_logical_id, sas_device->slot);
+               }
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       }
+
+       pr_warn(MPT3SAS_FMT
+               "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n",
+               ioc->name, le16_to_cpu(mpi_reply->DevHandle),
+           desc_ioc_state, ioc_status, smid);
+       pr_warn(MPT3SAS_FMT
+               "\trequest_len(%d), underflow(%d), resid(%d)\n",
+               ioc->name, scsi_bufflen(scmd), scmd->underflow,
+           scsi_get_resid(scmd));
+       pr_warn(MPT3SAS_FMT
+               "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n",
+               ioc->name, le16_to_cpu(mpi_reply->TaskTag),
+           le32_to_cpu(mpi_reply->TransferCount), scmd->result);
+       pr_warn(MPT3SAS_FMT
+               "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n",
+               ioc->name, desc_scsi_status,
+           scsi_status, desc_scsi_state, scsi_state);
+
+       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+               struct sense_info data;
+               _scsih_normalize_sense(scmd->sense_buffer, &data);
+               pr_warn(MPT3SAS_FMT
+                       "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
+                       ioc->name, data.skey,
+                   data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
+       }
+
+       if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
+               response_info = le32_to_cpu(mpi_reply->ResponseInfo);
+               response_bytes = (u8 *)&response_info;
+               _scsih_response_code(ioc, response_bytes[0]);
+       }
+}
+#endif
+
+/**
+ * _scsih_turn_on_fault_led - illuminate Fault LED
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: process
+ *
+ * Return nothing.
+ */
+static void
+_scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       Mpi2SepReply_t mpi_reply;
+       Mpi2SepRequest_t mpi_request;
+
+       memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+       mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
+       mpi_request.SlotStatus =
+           cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+       mpi_request.DevHandle = cpu_to_le16(handle);
+       mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
+       if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
+           &mpi_request)) != 0) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
+               __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
+                       ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
+                   le32_to_cpu(mpi_reply.IOCLogInfo)));
+               return;
+       }
+}
+
+/**
+ * _scsih_send_event_to_turn_on_fault_led - fire delayed event
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_send_event_to_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct fw_event_work *fw_event;
+
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event)
+               return;
+       fw_event->event = MPT3SAS_TURN_ON_FAULT_LED;
+       fw_event->device_handle = handle;
+       fw_event->ioc = ioc;
+       _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * _scsih_smart_predicted_fault - process smart errors
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct scsi_target *starget;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       Mpi2EventNotificationReply_t *event_reply;
+       Mpi2EventDataSasDeviceStatusChange_t *event_data;
+       struct _sas_device *sas_device;
+       ssize_t sz;
+       unsigned long flags;
+
+       /* only handle non-raid devices */
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (!sas_device) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+       starget = sas_device->starget;
+       sas_target_priv_data = starget->hostdata;
+
+       if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
+          ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+       starget_printk(KERN_WARNING, starget, "predicted fault\n");
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
+               _scsih_send_event_to_turn_on_fault_led(ioc, handle);
+
+       /* insert into event log */
+       sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
+            sizeof(Mpi2EventDataSasDeviceStatusChange_t);
+       event_reply = kzalloc(sz, GFP_KERNEL);
+       if (!event_reply) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
+       event_reply->Event =
+           cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
+       event_reply->MsgLength = sz/4;
+       event_reply->EventDataLength =
+           cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
+       event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
+           event_reply->EventData;
+       event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
+       event_data->ASC = 0x5D;
+       event_data->DevHandle = cpu_to_le16(handle);
+       event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
+       mpt3sas_ctl_add_to_event_log(ioc, event_reply);
+       kfree(event_reply);
+}
+
+/**
+ * _scsih_io_done - scsi request callback
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Callback handler when using _scsih_qcmd.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
+{
+       Mpi2SCSIIORequest_t *mpi_request;
+       Mpi2SCSIIOReply_t *mpi_reply;
+       struct scsi_cmnd *scmd;
+       u16 ioc_status;
+       u32 xfer_cnt;
+       u8 scsi_state;
+       u8 scsi_status;
+       u32 log_info;
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       u32 response_code = 0;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
+       if (scmd == NULL)
+               return 1;
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+
+       if (mpi_reply == NULL) {
+               scmd->result = DID_OK << 16;
+               goto out;
+       }
+
+       sas_device_priv_data = scmd->device->hostdata;
+       if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
+            sas_device_priv_data->sas_target->deleted) {
+               scmd->result = DID_NO_CONNECT << 16;
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
+
+       /* turning off TLR */
+       scsi_state = mpi_reply->SCSIState;
+       if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
+               response_code =
+                   le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
+       if (!sas_device_priv_data->tlr_snoop_check) {
+               sas_device_priv_data->tlr_snoop_check++;
+               if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
+                   response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
+                       sas_device_priv_data->flags &=
+                           ~MPT_DEVICE_TLR_ON;
+       }
+
+       xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
+       scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
+       if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
+               log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
+       else
+               log_info = 0;
+       ioc_status &= MPI2_IOCSTATUS_MASK;
+       scsi_status = mpi_reply->SCSIStatus;
+
+       if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
+           (scsi_status == MPI2_SCSI_STATUS_BUSY ||
+            scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
+            scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
+               ioc_status = MPI2_IOCSTATUS_SUCCESS;
+       }
+
+       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+               struct sense_info data;
+               const void *sense_data = mpt3sas_base_get_sense_buffer(ioc,
+                   smid);
+               u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
+                   le32_to_cpu(mpi_reply->SenseCount));
+               memcpy(scmd->sense_buffer, sense_data, sz);
+               _scsih_normalize_sense(scmd->sense_buffer, &data);
+               /* failure prediction threshold exceeded */
+               if (data.asc == 0x5D)
+                       _scsih_smart_predicted_fault(ioc,
+                           le16_to_cpu(mpi_reply->DevHandle));
+               mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
+       }
+
+       switch (ioc_status) {
+       case MPI2_IOCSTATUS_BUSY:
+       case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
+               scmd->result = SAM_STAT_BUSY;
+               break;
+
+       case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+               scmd->result = DID_NO_CONNECT << 16;
+               break;
+
+       case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+               if (sas_device_priv_data->block) {
+                       scmd->result = DID_TRANSPORT_DISRUPTED << 16;
+                       goto out;
+               }
+               if (log_info == 0x31110630) {
+                       if (scmd->retries > 2) {
+                               scmd->result = DID_NO_CONNECT << 16;
+                               scsi_device_set_state(scmd->device,
+                                   SDEV_OFFLINE);
+                       } else {
+                               scmd->result = DID_SOFT_ERROR << 16;
+                               scmd->device->expecting_cc_ua = 1;
+                       }
+                       break;
+               }
+               scmd->result = DID_SOFT_ERROR << 16;
+               break;
+       case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+       case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+               scmd->result = DID_RESET << 16;
+               break;
+
+       case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+               if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
+                       scmd->result = DID_SOFT_ERROR << 16;
+               else
+                       scmd->result = (DID_OK << 16) | scsi_status;
+               break;
+
+       case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+               scmd->result = (DID_OK << 16) | scsi_status;
+
+               if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
+                       break;
+
+               if (xfer_cnt < scmd->underflow) {
+                       if (scsi_status == SAM_STAT_BUSY)
+                               scmd->result = SAM_STAT_BUSY;
+                       else
+                               scmd->result = DID_SOFT_ERROR << 16;
+               } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
+                    MPI2_SCSI_STATE_NO_SCSI_STATUS))
+                       scmd->result = DID_SOFT_ERROR << 16;
+               else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+                       scmd->result = DID_RESET << 16;
+               else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
+                       mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
+                       mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
+                       scmd->result = (DRIVER_SENSE << 24) |
+                           SAM_STAT_CHECK_CONDITION;
+                       scmd->sense_buffer[0] = 0x70;
+                       scmd->sense_buffer[2] = ILLEGAL_REQUEST;
+                       scmd->sense_buffer[12] = 0x20;
+                       scmd->sense_buffer[13] = 0;
+               }
+               break;
+
+       case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+               scsi_set_resid(scmd, 0);
+       case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+       case MPI2_IOCSTATUS_SUCCESS:
+               scmd->result = (DID_OK << 16) | scsi_status;
+               if (response_code ==
+                   MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
+                   (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
+                    MPI2_SCSI_STATE_NO_SCSI_STATUS)))
+                       scmd->result = DID_SOFT_ERROR << 16;
+               else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+                       scmd->result = DID_RESET << 16;
+               break;
+
+       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
+       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
+       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
+               _scsih_eedp_error_handling(scmd, ioc_status);
+               break;
+
+       case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+       case MPI2_IOCSTATUS_INVALID_FUNCTION:
+       case MPI2_IOCSTATUS_INVALID_SGL:
+       case MPI2_IOCSTATUS_INTERNAL_ERROR:
+       case MPI2_IOCSTATUS_INVALID_FIELD:
+       case MPI2_IOCSTATUS_INVALID_STATE:
+       case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+       case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+       default:
+               scmd->result = DID_SOFT_ERROR << 16;
+               break;
+
+       }
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
+               _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
+#endif
+
+ out:
+
+       scsi_dma_unmap(scmd);
+
+       scmd->scsi_done(scmd);
+       return 1;
+}
+
+/**
+ * _scsih_sas_host_refresh - refreshing sas host object contents
+ * @ioc: per adapter object
+ * Context: user
+ *
+ * During port enable, fw will send topology events for every device. Its
+ * possible that the handles may change from the previous setting, so this
+ * code keeping handles updating if changed.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
+{
+       u16 sz;
+       u16 ioc_status;
+       int i;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+       u16 attached_handle;
+       u8 link_rate;
+
+       dtmprintk(ioc, pr_info(MPT3SAS_FMT
+           "updating handles for sas_host(0x%016llx)\n",
+           ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
+
+       sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
+           * sizeof(Mpi2SasIOUnit0PhyData_t));
+       sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg0) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+           sas_iounit_pg0, sz)) != 0)
+               goto out;
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+               goto out;
+       for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+               link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
+               if (i == 0)
+                       ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
+                           PhyData[0].ControllerDevHandle);
+               ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
+               attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
+                   AttachedDevHandle);
+               if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
+                       link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
+               mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
+                   attached_handle, i, link_rate);
+       }
+ out:
+       kfree(sas_iounit_pg0);
+}
+
+/**
+ * _scsih_sas_host_add - create sas host object
+ * @ioc: per adapter object
+ *
+ * Creating host side data object, stored in ioc->sas_hba
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
+{
+       int i;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+       Mpi2SasPhyPage0_t phy_pg0;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2SasEnclosurePage0_t enclosure_pg0;
+       u16 ioc_status;
+       u16 sz;
+       u8 device_missing_delay;
+
+       mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
+       if (!ioc->sas_hba.num_phys) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       /* sas_iounit page 0 */
+       sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
+           sizeof(Mpi2SasIOUnit0PhyData_t));
+       sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg0) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+       if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+           sas_iounit_pg0, sz))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+
+       /* sas_iounit page 1 */
+       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
+           sizeof(Mpi2SasIOUnit1PhyData_t));
+       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg1) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+           sas_iounit_pg1, sz))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+
+       ioc->io_missing_delay =
+           sas_iounit_pg1->IODeviceMissingDelay;
+       device_missing_delay =
+           sas_iounit_pg1->ReportDeviceMissingDelay;
+       if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+               ioc->device_missing_delay = (device_missing_delay &
+                   MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+       else
+               ioc->device_missing_delay = device_missing_delay &
+                   MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+
+       ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
+       ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
+           sizeof(struct _sas_phy), GFP_KERNEL);
+       if (!ioc->sas_hba.phy) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+               if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
+                   i))) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       goto out;
+               }
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       goto out;
+               }
+
+               if (i == 0)
+                       ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
+                           PhyData[0].ControllerDevHandle);
+               ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
+               ioc->sas_hba.phy[i].phy_id = i;
+               mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
+                   phy_pg0, ioc->sas_hba.parent_dev);
+       }
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out;
+       }
+       ioc->sas_hba.enclosure_handle =
+           le16_to_cpu(sas_device_pg0.EnclosureHandle);
+       ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+       pr_info(MPT3SAS_FMT
+               "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
+               ioc->name, ioc->sas_hba.handle,
+           (unsigned long long) ioc->sas_hba.sas_address,
+           ioc->sas_hba.num_phys) ;
+
+       if (ioc->sas_hba.enclosure_handle) {
+               if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
+                   &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+                  ioc->sas_hba.enclosure_handle)))
+                       ioc->sas_hba.enclosure_logical_id =
+                           le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+       }
+
+ out:
+       kfree(sas_iounit_pg1);
+       kfree(sas_iounit_pg0);
+}
+
+/**
+ * _scsih_expander_add -  creating expander object
+ * @ioc: per adapter object
+ * @handle: expander handle
+ *
+ * Creating expander object, stored in ioc->sas_expander_list.
+ *
+ * Return 0 for success, else error.
+ */
+static int
+_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _sas_node *sas_expander;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2ExpanderPage0_t expander_pg0;
+       Mpi2ExpanderPage1_t expander_pg1;
+       Mpi2SasEnclosurePage0_t enclosure_pg0;
+       u32 ioc_status;
+       u16 parent_handle;
+       u64 sas_address, sas_address_parent = 0;
+       int i;
+       unsigned long flags;
+       struct _sas_port *mpt3sas_port = NULL;
+
+       int rc = 0;
+
+       if (!handle)
+               return -1;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery)
+               return -1;
+
+       if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+           MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+
+       /* handle out of order topology events */
+       parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
+       if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
+           != 0) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+       if (sas_address_parent != ioc->sas_hba.sas_address) {
+               spin_lock_irqsave(&ioc->sas_node_lock, flags);
+               sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
+                   sas_address_parent);
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               if (!sas_expander) {
+                       rc = _scsih_expander_add(ioc, parent_handle);
+                       if (rc != 0)
+                               return rc;
+               }
+       }
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_address = le64_to_cpu(expander_pg0.SASAddress);
+       sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
+           sas_address);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       if (sas_expander)
+               return 0;
+
+       sas_expander = kzalloc(sizeof(struct _sas_node),
+           GFP_KERNEL);
+       if (!sas_expander) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+
+       sas_expander->handle = handle;
+       sas_expander->num_phys = expander_pg0.NumPhys;
+       sas_expander->sas_address_parent = sas_address_parent;
+       sas_expander->sas_address = sas_address;
+
+       pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \
+           " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
+           handle, parent_handle, (unsigned long long)
+           sas_expander->sas_address, sas_expander->num_phys);
+
+       if (!sas_expander->num_phys)
+               goto out_fail;
+       sas_expander->phy = kcalloc(sas_expander->num_phys,
+           sizeof(struct _sas_phy), GFP_KERNEL);
+       if (!sas_expander->phy) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -1;
+               goto out_fail;
+       }
+
+       INIT_LIST_HEAD(&sas_expander->sas_port_list);
+       mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
+           sas_address_parent);
+       if (!mpt3sas_port) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -1;
+               goto out_fail;
+       }
+       sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
+
+       for (i = 0 ; i < sas_expander->num_phys ; i++) {
+               if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
+                   &expander_pg1, i, handle))) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       rc = -1;
+                       goto out_fail;
+               }
+               sas_expander->phy[i].handle = handle;
+               sas_expander->phy[i].phy_id = i;
+
+               if ((mpt3sas_transport_add_expander_phy(ioc,
+                   &sas_expander->phy[i], expander_pg1,
+                   sas_expander->parent_dev))) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       rc = -1;
+                       goto out_fail;
+               }
+       }
+
+       if (sas_expander->enclosure_handle) {
+               if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
+                   &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+                  sas_expander->enclosure_handle)))
+                       sas_expander->enclosure_logical_id =
+                           le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+       }
+
+       _scsih_expander_node_add(ioc, sas_expander);
+        return 0;
+
+ out_fail:
+
+       if (mpt3sas_port)
+               mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
+                   sas_address_parent);
+       kfree(sas_expander);
+       return rc;
+}
+
+/**
+ * mpt3sas_expander_remove - removing expander object
+ * @ioc: per adapter object
+ * @sas_address: expander sas_address
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
+{
+       struct _sas_node *sas_expander;
+       unsigned long flags;
+
+       if (ioc->shost_recovery)
+               return;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
+           sas_address);
+       if (sas_expander)
+               list_del(&sas_expander->list);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+       if (sas_expander)
+               _scsih_expander_node_remove(ioc, sas_expander);
+}
+
+/**
+ * _scsih_done -  internal SCSI_IO callback handler.
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Callback handler when sending internal generated SCSI_IO.
+ * The callback index passed is `ioc->scsih_cb_idx`
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+
+       mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+       if (ioc->scsih_cmds.smid != smid)
+               return 1;
+       ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE;
+       if (mpi_reply) {
+               memcpy(ioc->scsih_cmds.reply, mpi_reply,
+                   mpi_reply->MsgLength*4);
+               ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID;
+       }
+       ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING;
+       complete(&ioc->scsih_cmds.done);
+       return 1;
+}
+
+
+
+
+#define MPT3_MAX_LUNS (255)
+
+
+/**
+ * _scsih_check_access_status - check access flags
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * @handle: sas device handle
+ * @access_flags: errors returned during discovery of the device
+ *
+ * Return 0 for success, else failure
+ */
+static u8
+_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+       u16 handle, u8 access_status)
+{
+       u8 rc = 1;
+       char *desc = NULL;
+
+       switch (access_status) {
+       case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
+       case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
+               rc = 0;
+               break;
+       case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
+               desc = "sata capability failed";
+               break;
+       case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
+               desc = "sata affiliation conflict";
+               break;
+       case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
+               desc = "route not addressable";
+               break;
+       case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
+               desc = "smp error not addressable";
+               break;
+       case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
+               desc = "device blocked";
+               break;
+       case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
+       case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
+               desc = "sata initialization failed";
+               break;
+       default:
+               desc = "unknown";
+               break;
+       }
+
+       if (!rc)
+               return 0;
+
+       pr_err(MPT3SAS_FMT
+               "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n",
+               ioc->name, desc, (unsigned long long)sas_address, handle);
+       return rc;
+}
+
+/**
+ * _scsih_check_device - checking device responsiveness
+ * @ioc: per adapter object
+ * @parent_sas_address: sas address of parent expander or sas host
+ * @handle: attached device handle
+ * @phy_numberv: phy number
+ * @link_rate: new link rate
+ *
+ * Returns nothing.
+ */
+static void
+_scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
+       u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate)
+{
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       struct _sas_device *sas_device;
+       u32 ioc_status;
+       unsigned long flags;
+       u64 sas_address;
+       struct scsi_target *starget;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       u32 device_info;
+
+
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
+               return;
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+               return;
+
+       /* wide port handling ~ we need only handle device once for the phy that
+        * is matched in sas device page zero
+        */
+       if (phy_number != sas_device_pg0.PhyNum)
+               return;
+
+       /* check if this is end device */
+       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+       if (!(_scsih_is_end_device(device_info)))
+               return;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+           sas_address);
+
+       if (!sas_device) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+
+       if (unlikely(sas_device->handle != handle)) {
+               starget = sas_device->starget;
+               sas_target_priv_data = starget->hostdata;
+               starget_printk(KERN_INFO, starget,
+                       "handle changed from(0x%04x) to (0x%04x)!!!\n",
+                       sas_device->handle, handle);
+               sas_target_priv_data->handle = handle;
+               sas_device->handle = handle;
+       }
+
+       /* check if device is present */
+       if (!(le16_to_cpu(sas_device_pg0.Flags) &
+           MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
+               pr_err(MPT3SAS_FMT
+                       "device is not present handle(0x%04x), flags!!!\n",
+                       ioc->name, handle);
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+
+       /* check if there were any issues with discovery */
+       if (_scsih_check_access_status(ioc, sas_address, handle,
+           sas_device_pg0.AccessStatus)) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       _scsih_ublock_io_device(ioc, sas_address);
+
+}
+
+/**
+ * _scsih_add_device -  creating sas device object
+ * @ioc: per adapter object
+ * @handle: sas device handle
+ * @phy_num: phy number end device attached to
+ * @is_pd: is this hidden raid component
+ *
+ * Creating end device object, stored in ioc->sas_device_list.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
+       u8 is_pd)
+{
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2SasEnclosurePage0_t enclosure_pg0;
+       struct _sas_device *sas_device;
+       u32 ioc_status;
+       u64 sas_address;
+       u32 device_info;
+       unsigned long flags;
+
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+
+       /* check if this is end device */
+       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+       if (!(_scsih_is_end_device(device_info)))
+               return -1;
+       sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+
+       /* check if device is present */
+       if (!(le16_to_cpu(sas_device_pg0.Flags) &
+           MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
+               pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n",
+                       ioc->name, handle);
+               return -1;
+       }
+
+       /* check if there were any issues with discovery */
+       if (_scsih_check_access_status(ioc, sas_address, handle,
+           sas_device_pg0.AccessStatus))
+               return -1;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+           sas_address);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (sas_device)
+               return -1;
+
+       sas_device = kzalloc(sizeof(struct _sas_device),
+           GFP_KERNEL);
+       if (!sas_device) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return 0;
+       }
+
+       sas_device->handle = handle;
+       if (_scsih_get_sas_address(ioc,
+           le16_to_cpu(sas_device_pg0.ParentDevHandle),
+           &sas_device->sas_address_parent) != 0)
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+       sas_device->enclosure_handle =
+           le16_to_cpu(sas_device_pg0.EnclosureHandle);
+       sas_device->slot =
+           le16_to_cpu(sas_device_pg0.Slot);
+       sas_device->device_info = device_info;
+       sas_device->sas_address = sas_address;
+       sas_device->phy = sas_device_pg0.PhyNum;
+       sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
+           MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
+
+       /* get enclosure_logical_id */
+       if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
+          ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+          sas_device->enclosure_handle)))
+               sas_device->enclosure_logical_id =
+                   le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+
+       /* get device name */
+       sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
+
+       if (ioc->wait_for_discovery_to_complete)
+               _scsih_sas_device_init_add(ioc, sas_device);
+       else
+               _scsih_sas_device_add(ioc, sas_device);
+
+       return 0;
+}
+
+/**
+ * _scsih_remove_device -  removing sas device object
+ * @ioc: per adapter object
+ * @sas_device_delete: the sas_device object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_device *sas_device)
+{
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
+               ioc->name, __func__,
+           sas_device->handle, (unsigned long long)
+           sas_device->sas_address));
+
+       if (sas_device->starget && sas_device->starget->hostdata) {
+               sas_target_priv_data = sas_device->starget->hostdata;
+               sas_target_priv_data->deleted = 1;
+               _scsih_ublock_io_device(ioc, sas_device->sas_address);
+               sas_target_priv_data->handle =
+                    MPT3SAS_INVALID_DEVICE_HANDLE;
+       }
+       mpt3sas_transport_port_remove(ioc,
+                   sas_device->sas_address,
+                   sas_device->sas_address_parent);
+
+       pr_info(MPT3SAS_FMT
+               "removing handle(0x%04x), sas_addr(0x%016llx)\n",
+               ioc->name, sas_device->handle,
+           (unsigned long long) sas_device->sas_address);
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
+               ioc->name, __func__,
+           sas_device->handle, (unsigned long long)
+           sas_device->sas_address));
+
+       kfree(sas_device);
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _scsih_sas_topology_change_event_debug - debug for topology event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ */
+static void
+_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+       int i;
+       u16 handle;
+       u16 reason_code;
+       u8 phy_number;
+       char *status_str = NULL;
+       u8 link_rate, prev_link_rate;
+
+       switch (event_data->ExpStatus) {
+       case MPI2_EVENT_SAS_TOPO_ES_ADDED:
+               status_str = "add";
+               break;
+       case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
+               status_str = "remove";
+               break;
+       case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
+       case 0:
+               status_str =  "responding";
+               break;
+       case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
+               status_str = "remove delay";
+               break;
+       default:
+               status_str = "unknown status";
+               break;
+       }
+       pr_info(MPT3SAS_FMT "sas topology change: (%s)\n",
+           ioc->name, status_str);
+       pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \
+           "start_phy(%02d), count(%d)\n",
+           le16_to_cpu(event_data->ExpanderDevHandle),
+           le16_to_cpu(event_data->EnclosureHandle),
+           event_data->StartPhyNum, event_data->NumEntries);
+       for (i = 0; i < event_data->NumEntries; i++) {
+               handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+               if (!handle)
+                       continue;
+               phy_number = event_data->StartPhyNum + i;
+               reason_code = event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               switch (reason_code) {
+               case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
+                       status_str = "target add";
+                       break;
+               case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
+                       status_str = "target remove";
+                       break;
+               case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
+                       status_str = "delay target remove";
+                       break;
+               case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
+                       status_str = "link rate change";
+                       break;
+               case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
+                       status_str = "target responding";
+                       break;
+               default:
+                       status_str = "unknown";
+                       break;
+               }
+               link_rate = event_data->PHY[i].LinkRate >> 4;
+               prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
+               pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \
+                   " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
+                   handle, status_str, link_rate, prev_link_rate);
+
+       }
+}
+#endif
+
+/**
+ * _scsih_sas_topology_change_event - handle topology changes
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ */
+static int
+_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       int i;
+       u16 parent_handle, handle;
+       u16 reason_code;
+       u8 phy_number, max_phys;
+       struct _sas_node *sas_expander;
+       u64 sas_address;
+       unsigned long flags;
+       u8 link_rate, prev_link_rate;
+       Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+               _scsih_sas_topology_change_event_debug(ioc, event_data);
+#endif
+
+       if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
+               return 0;
+
+       if (!ioc->sas_hba.num_phys)
+               _scsih_sas_host_add(ioc);
+       else
+               _scsih_sas_host_refresh(ioc);
+
+       if (fw_event->ignore) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "ignoring expander event\n", ioc->name));
+               return 0;
+       }
+
+       parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
+
+       /* handle expander add */
+       if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
+               if (_scsih_expander_add(ioc, parent_handle) != 0)
+                       return 0;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
+           parent_handle);
+       if (sas_expander) {
+               sas_address = sas_expander->sas_address;
+               max_phys = sas_expander->num_phys;
+       } else if (parent_handle < ioc->sas_hba.num_phys) {
+               sas_address = ioc->sas_hba.sas_address;
+               max_phys = ioc->sas_hba.num_phys;
+       } else {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return 0;
+       }
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       /* handle siblings events */
+       for (i = 0; i < event_data->NumEntries; i++) {
+               if (fw_event->ignore) {
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                               "ignoring expander event\n", ioc->name));
+                       return 0;
+               }
+               if (ioc->remove_host || ioc->pci_error_recovery)
+                       return 0;
+               phy_number = event_data->StartPhyNum + i;
+               if (phy_number >= max_phys)
+                       continue;
+               reason_code = event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               if ((event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
+                   MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
+                               continue;
+               handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+               if (!handle)
+                       continue;
+               link_rate = event_data->PHY[i].LinkRate >> 4;
+               prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
+               switch (reason_code) {
+               case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
+
+                       if (ioc->shost_recovery)
+                               break;
+
+                       if (link_rate == prev_link_rate)
+                               break;
+
+                       mpt3sas_transport_update_links(ioc, sas_address,
+                           handle, phy_number, link_rate);
+
+                       if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
+                               break;
+
+                       _scsih_check_device(ioc, sas_address, handle,
+                           phy_number, link_rate);
+
+
+               case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
+
+                       if (ioc->shost_recovery)
+                               break;
+
+                       mpt3sas_transport_update_links(ioc, sas_address,
+                           handle, phy_number, link_rate);
+
+                       _scsih_add_device(ioc, handle, phy_number, 0);
+
+                       break;
+               case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
+
+                       _scsih_device_remove_by_handle(ioc, handle);
+                       break;
+               }
+       }
+
+       /* handle expander removal */
+       if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
+           sas_expander)
+               mpt3sas_expander_remove(ioc, sas_address);
+
+       return 0;
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _scsih_sas_device_status_change_event_debug - debug for device event
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataSasDeviceStatusChange_t *event_data)
+{
+       char *reason_str = NULL;
+
+       switch (event_data->ReasonCode) {
+       case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+               reason_str = "smart data";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+               reason_str = "unsupported device discovered";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+               reason_str = "internal device reset";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+               reason_str = "internal task abort";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+               reason_str = "internal task abort set";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+               reason_str = "internal clear task set";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
+               reason_str = "internal query task";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
+               reason_str = "sata init failure";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
+               reason_str = "internal device reset complete";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
+               reason_str = "internal task abort complete";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
+               reason_str = "internal async notification";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
+               reason_str = "expander reduced functionality";
+               break;
+       case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
+               reason_str = "expander reduced functionality complete";
+               break;
+       default:
+               reason_str = "unknown reason";
+               break;
+       }
+       pr_info(MPT3SAS_FMT "device status change: (%s)\n"
+           "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
+           ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
+           (unsigned long long)le64_to_cpu(event_data->SASAddress),
+           le16_to_cpu(event_data->TaskTag));
+       if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
+               pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
+                   event_data->ASC, event_data->ASCQ);
+       pr_info("\n");
+}
+#endif
+
+/**
+ * _scsih_sas_device_status_change_event - handle device status change
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       struct MPT3SAS_TARGET *target_priv_data;
+       struct _sas_device *sas_device;
+       u64 sas_address;
+       unsigned long flags;
+       Mpi2EventDataSasDeviceStatusChange_t *event_data =
+           fw_event->event_data;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+               _scsih_sas_device_status_change_event_debug(ioc,
+                    event_data);
+#endif
+
+       /* In MPI Revision K (0xC), the internal device reset complete was
+        * implemented, so avoid setting tm_busy flag for older firmware.
+        */
+       if ((ioc->facts.HeaderVersion >> 8) < 0xC)
+               return;
+
+       if (event_data->ReasonCode !=
+           MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
+          event_data->ReasonCode !=
+           MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
+               return;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_address = le64_to_cpu(event_data->SASAddress);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+           sas_address);
+
+       if (!sas_device || !sas_device->starget) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+
+       target_priv_data = sas_device->starget->hostdata;
+       if (!target_priv_data) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               return;
+       }
+
+       if (event_data->ReasonCode ==
+           MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
+               target_priv_data->tm_busy = 1;
+       else
+               target_priv_data->tm_busy = 0;
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
+ * event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataSasEnclDevStatusChange_t *event_data)
+{
+       char *reason_str = NULL;
+
+       switch (event_data->ReasonCode) {
+       case MPI2_EVENT_SAS_ENCL_RC_ADDED:
+               reason_str = "enclosure add";
+               break;
+       case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
+               reason_str = "enclosure remove";
+               break;
+       default:
+               reason_str = "unknown reason";
+               break;
+       }
+
+       pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n"
+           "\thandle(0x%04x), enclosure logical id(0x%016llx)"
+           " number slots(%d)\n", ioc->name, reason_str,
+           le16_to_cpu(event_data->EnclosureHandle),
+           (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
+           le16_to_cpu(event_data->StartSlot));
+}
+#endif
+
+/**
+ * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+               _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
+                    fw_event->event_data);
+#endif
+}
+
+/**
+ * _scsih_sas_broadcast_primitive_event - handle broadcast events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       struct scsi_cmnd *scmd;
+       struct scsi_device *sdev;
+       u16 smid, handle;
+       u32 lun;
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       u32 termination_count;
+       u32 query_count;
+       Mpi2SCSITaskManagementReply_t *mpi_reply;
+       Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
+       u16 ioc_status;
+       unsigned long flags;
+       int r;
+       u8 max_retries = 0;
+       u8 task_abort_retries;
+
+       mutex_lock(&ioc->tm_cmds.mutex);
+       pr_info(MPT3SAS_FMT
+               "%s: enter: phy number(%d), width(%d)\n",
+               ioc->name, __func__, event_data->PhyNum,
+            event_data->PortWidth);
+
+       _scsih_block_io_all_device(ioc);
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       mpi_reply = ioc->tm_cmds.reply;
+ broadcast_aen_retry:
+
+       /* sanity checks for retrying this loop */
+       if (max_retries++ == 5) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n",
+                   ioc->name, __func__));
+               goto out;
+       } else if (max_retries > 1)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n",
+                   ioc->name, __func__, max_retries - 1));
+
+       termination_count = 0;
+       query_count = 0;
+       for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+               if (ioc->shost_recovery)
+                       goto out;
+               scmd = _scsih_scsi_lookup_get(ioc, smid);
+               if (!scmd)
+                       continue;
+               sdev = scmd->device;
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
+                       continue;
+                /* skip hidden raid components */
+               if (sas_device_priv_data->sas_target->flags &
+                   MPT_TARGET_FLAGS_RAID_COMPONENT)
+                       continue;
+                /* skip volumes */
+               if (sas_device_priv_data->sas_target->flags &
+                   MPT_TARGET_FLAGS_VOLUME)
+                       continue;
+
+               handle = sas_device_priv_data->sas_target->handle;
+               lun = sas_device_priv_data->lun;
+               query_count++;
+
+               if (ioc->shost_recovery)
+                       goto out;
+
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
+                   MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
+                   TM_MUTEX_OFF);
+               if (r == FAILED) {
+                       sdev_printk(KERN_WARNING, sdev,
+                           "mpt3sas_scsih_issue_tm: FAILED when sending "
+                           "QUERY_TASK: scmd(%p)\n", scmd);
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       goto broadcast_aen_retry;
+               }
+               ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
+                   & MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       sdev_printk(KERN_WARNING, sdev,
+                               "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n",
+                               ioc_status, scmd);
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       goto broadcast_aen_retry;
+               }
+
+               /* see if IO is still owned by IOC and target */
+               if (mpi_reply->ResponseCode ==
+                    MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
+                    mpi_reply->ResponseCode ==
+                    MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       continue;
+               }
+               task_abort_retries = 0;
+ tm_retry:
+               if (task_abort_retries++ == 60) {
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                           "%s: ABORT_TASK: giving up\n", ioc->name,
+                           __func__));
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       goto broadcast_aen_retry;
+               }
+
+               if (ioc->shost_recovery)
+                       goto out_no_lock;
+
+               r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
+                   sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+                   scmd->serial_number, TM_MUTEX_OFF);
+               if (r == FAILED) {
+                       sdev_printk(KERN_WARNING, sdev,
+                           "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
+                           "scmd(%p)\n", scmd);
+                       goto tm_retry;
+               }
+
+               if (task_abort_retries > 1)
+                       sdev_printk(KERN_WARNING, sdev,
+                           "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
+                           " scmd(%p)\n",
+                           task_abort_retries - 1, scmd);
+
+               termination_count += le32_to_cpu(mpi_reply->TerminationCount);
+               spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       }
+
+       if (ioc->broadcast_aen_pending) {
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: loop back due to pending AEN\n",
+                       ioc->name, __func__));
+                ioc->broadcast_aen_pending = 0;
+                goto broadcast_aen_retry;
+       }
+
+ out:
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ out_no_lock:
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+           "%s - exit, query_count = %d termination_count = %d\n",
+           ioc->name, __func__, query_count, termination_count));
+
+       ioc->broadcast_aen_busy = 0;
+       if (!ioc->shost_recovery)
+               _scsih_ublock_io_all_device(ioc);
+       mutex_unlock(&ioc->tm_cmds.mutex);
+}
+
+/**
+ * _scsih_sas_discovery_event - handle discovery events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
+               pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
+                   (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
+                   "start" : "stop");
+       if (event_data->DiscoveryStatus)
+               pr_info("discovery_status(0x%08x)",
+                   le32_to_cpu(event_data->DiscoveryStatus));
+       pr_info("\n");
+       }
+#endif
+
+       if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
+           !ioc->sas_hba.num_phys) {
+               if (disable_discovery > 0 && ioc->shost_recovery) {
+                       /* Wait for the reset to complete */
+                       while (ioc->shost_recovery)
+                               ssleep(1);
+               }
+               _scsih_sas_host_add(ioc);
+       }
+}
+
+/**
+ * _scsih_ir_fastpath - turn on fastpath for IR physdisk
+ * @ioc: per adapter object
+ * @handle: device handle for physical disk
+ * @phys_disk_num: physical disk number
+ *
+ * Return 0 for success, else failure.
+ */
+static int
+_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
+{
+       Mpi2RaidActionRequest_t *mpi_request;
+       Mpi2RaidActionReply_t *mpi_reply;
+       u16 smid;
+       u8 issue_reset = 0;
+       int rc = 0;
+       u16 ioc_status;
+       u32 log_info;
+
+
+       mutex_lock(&ioc->scsih_cmds.mutex);
+
+       if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+       ioc->scsih_cmds.status = MPT3_CMD_PENDING;
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->scsih_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
+
+       mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
+       mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
+       mpi_request->PhysDiskNum = phys_disk_num;
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\
+           "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name,
+           handle, phys_disk_num));
+
+       init_completion(&ioc->scsih_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
+
+       if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               rc = -EFAULT;
+               goto out;
+       }
+
+       if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
+
+               mpi_reply = ioc->scsih_cmds.reply;
+               ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
+               if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
+                       log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
+               else
+                       log_info = 0;
+               ioc_status &= MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                           "IR RAID_ACTION: failed: ioc_status(0x%04x), "
+                           "loginfo(0x%08x)!!!\n", ioc->name, ioc_status,
+                           log_info));
+                       rc = -EFAULT;
+               } else
+                       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                           "IR RAID_ACTION: completed successfully\n",
+                           ioc->name));
+       }
+
+ out:
+       ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_unlock(&ioc->scsih_cmds.mutex);
+
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+       return rc;
+}
+
+/**
+ * _scsih_reprobe_lun - reprobing lun
+ * @sdev: scsi device struct
+ * @no_uld_attach: sdev->no_uld_attach flag setting
+ *
+ **/
+static void
+_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
+{
+       int rc;
+       sdev->no_uld_attach = no_uld_attach ? 1 : 0;
+       sdev_printk(KERN_INFO, sdev, "%s raid component\n",
+           sdev->no_uld_attach ? "hidding" : "exposing");
+       rc = scsi_device_reprobe(sdev);
+}
+
+/**
+ * _scsih_sas_volume_add - add new volume
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventIrConfigElement_t *element)
+{
+       struct _raid_device *raid_device;
+       unsigned long flags;
+       u64 wwid;
+       u16 handle = le16_to_cpu(element->VolDevHandle);
+       int rc;
+
+       mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
+       if (!wwid) {
+               pr_err(MPT3SAS_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name,
+                   __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+
+       if (raid_device)
+               return;
+
+       raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
+       if (!raid_device) {
+               pr_err(MPT3SAS_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name,
+                   __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       raid_device->id = ioc->sas_id++;
+       raid_device->channel = RAID_CHANNEL;
+       raid_device->handle = handle;
+       raid_device->wwid = wwid;
+       _scsih_raid_device_add(ioc, raid_device);
+       if (!ioc->wait_for_discovery_to_complete) {
+               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+                   raid_device->id, 0);
+               if (rc)
+                       _scsih_raid_device_remove(ioc, raid_device);
+       } else {
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               _scsih_determine_boot_device(ioc, raid_device, 1);
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+       }
+}
+
+/**
+ * _scsih_sas_volume_delete - delete volume
+ * @ioc: per adapter object
+ * @handle: volume device handle
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _raid_device *raid_device;
+       unsigned long flags;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct scsi_target *starget = NULL;
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+       if (raid_device) {
+               if (raid_device->starget) {
+                       starget = raid_device->starget;
+                       sas_target_priv_data = starget->hostdata;
+                       sas_target_priv_data->deleted = 1;
+               }
+               pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
+                       ioc->name,  raid_device->handle,
+                   (unsigned long long) raid_device->wwid);
+               list_del(&raid_device->list);
+               kfree(raid_device);
+       }
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+       if (starget)
+               scsi_remove_target(&starget->dev);
+}
+
+/**
+ * _scsih_sas_pd_expose - expose pd component to /dev/sdX
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventIrConfigElement_t *element)
+{
+       struct _sas_device *sas_device;
+       struct scsi_target *starget = NULL;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       unsigned long flags;
+       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (sas_device) {
+               sas_device->volume_handle = 0;
+               sas_device->volume_wwid = 0;
+               clear_bit(handle, ioc->pd_handles);
+               if (sas_device->starget && sas_device->starget->hostdata) {
+                       starget = sas_device->starget;
+                       sas_target_priv_data = starget->hostdata;
+                       sas_target_priv_data->flags &=
+                           ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+               }
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       if (!sas_device)
+               return;
+
+       /* exposing raid component */
+       if (starget)
+               starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
+}
+
+/**
+ * _scsih_sas_pd_hide - hide pd component from /dev/sdX
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventIrConfigElement_t *element)
+{
+       struct _sas_device *sas_device;
+       struct scsi_target *starget = NULL;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       unsigned long flags;
+       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+       u16 volume_handle = 0;
+       u64 volume_wwid = 0;
+
+       mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle);
+       if (volume_handle)
+               mpt3sas_config_get_volume_wwid(ioc, volume_handle,
+                   &volume_wwid);
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (sas_device) {
+               set_bit(handle, ioc->pd_handles);
+               if (sas_device->starget && sas_device->starget->hostdata) {
+                       starget = sas_device->starget;
+                       sas_target_priv_data = starget->hostdata;
+                       sas_target_priv_data->flags |=
+                           MPT_TARGET_FLAGS_RAID_COMPONENT;
+                       sas_device->volume_handle = volume_handle;
+                       sas_device->volume_wwid = volume_wwid;
+               }
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       if (!sas_device)
+               return;
+
+       /* hiding raid component */
+       _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+       if (starget)
+               starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
+}
+
+/**
+ * _scsih_sas_pd_delete - delete pd component
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventIrConfigElement_t *element)
+{
+       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+
+       _scsih_device_remove_by_handle(ioc, handle);
+}
+
+/**
+ * _scsih_sas_pd_add - remove pd component
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventIrConfigElement_t *element)
+{
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       u32 ioc_status;
+       u64 sas_address;
+       u16 parent_handle;
+
+       set_bit(handle, ioc->pd_handles);
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       if (sas_device) {
+               _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+               return;
+       }
+
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+       if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
+               mpt3sas_transport_update_links(ioc, sas_address, handle,
+                   sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+       _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+       _scsih_add_device(ioc, handle, 0, 1);
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataIrConfigChangeList_t *event_data)
+{
+       Mpi2EventIrConfigElement_t *element;
+       u8 element_type;
+       int i;
+       char *reason_str = NULL, *element_str = NULL;
+
+       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+
+       pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n",
+           ioc->name, (le32_to_cpu(event_data->Flags) &
+           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
+           "foreign" : "native", event_data->NumElements);
+       for (i = 0; i < event_data->NumElements; i++, element++) {
+               switch (element->ReasonCode) {
+               case MPI2_EVENT_IR_CHANGE_RC_ADDED:
+                       reason_str = "add";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
+                       reason_str = "remove";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
+                       reason_str = "no change";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_HIDE:
+                       reason_str = "hide";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
+                       reason_str = "unhide";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
+                       reason_str = "volume_created";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
+                       reason_str = "volume_deleted";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
+                       reason_str = "pd_created";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
+                       reason_str = "pd_deleted";
+                       break;
+               default:
+                       reason_str = "unknown reason";
+                       break;
+               }
+               element_type = le16_to_cpu(element->ElementFlags) &
+                   MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
+               switch (element_type) {
+               case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
+                       element_str = "volume";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
+                       element_str = "phys disk";
+                       break;
+               case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
+                       element_str = "hot spare";
+                       break;
+               default:
+                       element_str = "unknown element";
+                       break;
+               }
+               pr_info("\t(%s:%s), vol handle(0x%04x), " \
+                   "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
+                   reason_str, le16_to_cpu(element->VolDevHandle),
+                   le16_to_cpu(element->PhysDiskDevHandle),
+                   element->PhysDiskNum);
+       }
+}
+#endif
+
+/**
+ * _scsih_sas_ir_config_change_event - handle ir configuration change events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       Mpi2EventIrConfigElement_t *element;
+       int i;
+       u8 foreign_config;
+       Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+               _scsih_sas_ir_config_change_event_debug(ioc, event_data);
+
+#endif
+
+       foreign_config = (le32_to_cpu(event_data->Flags) &
+           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
+
+       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+       if (ioc->shost_recovery) {
+
+               for (i = 0; i < event_data->NumElements; i++, element++) {
+                       if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
+                               _scsih_ir_fastpath(ioc,
+                                       le16_to_cpu(element->PhysDiskDevHandle),
+                                       element->PhysDiskNum);
+               }
+               return;
+       }
+       for (i = 0; i < event_data->NumElements; i++, element++) {
+
+               switch (element->ReasonCode) {
+               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
+               case MPI2_EVENT_IR_CHANGE_RC_ADDED:
+                       if (!foreign_config)
+                               _scsih_sas_volume_add(ioc, element);
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
+               case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
+                       if (!foreign_config)
+                               _scsih_sas_volume_delete(ioc,
+                                   le16_to_cpu(element->VolDevHandle));
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
+                       _scsih_sas_pd_hide(ioc, element);
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
+                       _scsih_sas_pd_expose(ioc, element);
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_HIDE:
+                       _scsih_sas_pd_add(ioc, element);
+                       break;
+               case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
+                       _scsih_sas_pd_delete(ioc, element);
+                       break;
+               }
+       }
+}
+
+/**
+ * _scsih_sas_ir_volume_event - IR volume event
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       u64 wwid;
+       unsigned long flags;
+       struct _raid_device *raid_device;
+       u16 handle;
+       u32 state;
+       int rc;
+       Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
+
+       if (ioc->shost_recovery)
+               return;
+
+       if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
+               return;
+
+       handle = le16_to_cpu(event_data->VolDevHandle);
+       state = le32_to_cpu(event_data->NewValue);
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
+               ioc->name, __func__,  handle,
+           le32_to_cpu(event_data->PreviousValue), state));
+       switch (state) {
+       case MPI2_RAID_VOL_STATE_MISSING:
+       case MPI2_RAID_VOL_STATE_FAILED:
+               _scsih_sas_volume_delete(ioc, handle);
+               break;
+
+       case MPI2_RAID_VOL_STATE_ONLINE:
+       case MPI2_RAID_VOL_STATE_DEGRADED:
+       case MPI2_RAID_VOL_STATE_OPTIMAL:
+
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+
+               if (raid_device)
+                       break;
+
+               mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
+               if (!wwid) {
+                       pr_err(MPT3SAS_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name,
+                           __FILE__, __LINE__, __func__);
+                       break;
+               }
+
+               raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
+               if (!raid_device) {
+                       pr_err(MPT3SAS_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name,
+                           __FILE__, __LINE__, __func__);
+                       break;
+               }
+
+               raid_device->id = ioc->sas_id++;
+               raid_device->channel = RAID_CHANNEL;
+               raid_device->handle = handle;
+               raid_device->wwid = wwid;
+               _scsih_raid_device_add(ioc, raid_device);
+               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+                   raid_device->id, 0);
+               if (rc)
+                       _scsih_raid_device_remove(ioc, raid_device);
+               break;
+
+       case MPI2_RAID_VOL_STATE_INITIALIZING:
+       default:
+               break;
+       }
+}
+
+/**
+ * _scsih_sas_ir_physical_disk_event - PD event
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       u16 handle, parent_handle;
+       u32 state;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       u32 ioc_status;
+       Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
+       u64 sas_address;
+
+       if (ioc->shost_recovery)
+               return;
+
+       if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
+               return;
+
+       handle = le16_to_cpu(event_data->PhysDiskDevHandle);
+       state = le32_to_cpu(event_data->NewValue);
+
+       dewtprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
+               ioc->name, __func__,  handle,
+                   le32_to_cpu(event_data->PreviousValue), state));
+       switch (state) {
+       case MPI2_RAID_PD_STATE_ONLINE:
+       case MPI2_RAID_PD_STATE_DEGRADED:
+       case MPI2_RAID_PD_STATE_REBUILDING:
+       case MPI2_RAID_PD_STATE_OPTIMAL:
+       case MPI2_RAID_PD_STATE_HOT_SPARE:
+
+               set_bit(handle, ioc->pd_handles);
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+               if (sas_device)
+                       return;
+
+               if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+                   handle))) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       return;
+               }
+
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       return;
+               }
+
+               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+               if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
+                       mpt3sas_transport_update_links(ioc, sas_address, handle,
+                           sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+               _scsih_add_device(ioc, handle, 0, 1);
+
+               break;
+
+       case MPI2_RAID_PD_STATE_OFFLINE:
+       case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
+       case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
+       default:
+               break;
+       }
+}
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+/**
+ * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2EventDataIrOperationStatus_t *event_data)
+{
+       char *reason_str = NULL;
+
+       switch (event_data->RAIDOperation) {
+       case MPI2_EVENT_IR_RAIDOP_RESYNC:
+               reason_str = "resync";
+               break;
+       case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
+               reason_str = "online capacity expansion";
+               break;
+       case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
+               reason_str = "consistency check";
+               break;
+       case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
+               reason_str = "background init";
+               break;
+       case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
+               reason_str = "make data consistent";
+               break;
+       }
+
+       if (!reason_str)
+               return;
+
+       pr_info(MPT3SAS_FMT "raid operational status: (%s)" \
+           "\thandle(0x%04x), percent complete(%d)\n",
+           ioc->name, reason_str,
+           le16_to_cpu(event_data->VolDevHandle),
+           event_data->PercentComplete);
+}
+#endif
+
+/**
+ * _scsih_sas_ir_operation_status_event - handle RAID operation events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
+       struct fw_event_work *fw_event)
+{
+       Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
+       static struct _raid_device *raid_device;
+       unsigned long flags;
+       u16 handle;
+
+#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+               _scsih_sas_ir_operation_status_event_debug(ioc,
+                    event_data);
+#endif
+
+       /* code added for raid transport support */
+       if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
+
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               handle = le16_to_cpu(event_data->VolDevHandle);
+               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+               if (raid_device)
+                       raid_device->percent_complete =
+                           event_data->PercentComplete;
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+       }
+}
+
+/**
+ * _scsih_prep_device_scan - initialize parameters prior to device scan
+ * @ioc: per adapter object
+ *
+ * Set the deleted flag prior to device scan.  If the device is found during
+ * the scan, then we clear the deleted flag.
+ */
+static void
+_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct MPT3SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (sas_device_priv_data && sas_device_priv_data->sas_target)
+                       sas_device_priv_data->sas_target->deleted = 1;
+       }
+}
+
+/**
+ * _scsih_mark_responding_sas_device - mark a sas_devices as responding
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * @slot: enclosure slot id
+ * @handle: device handle
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsih_remove_unresponsive_sas_devices.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+       u16 slot, u16 handle)
+{
+       struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
+       struct scsi_target *starget;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+               if (sas_device->sas_address == sas_address &&
+                   sas_device->slot == slot) {
+                       sas_device->responding = 1;
+                       starget = sas_device->starget;
+                       if (starget && starget->hostdata) {
+                               sas_target_priv_data = starget->hostdata;
+                               sas_target_priv_data->tm_busy = 0;
+                               sas_target_priv_data->deleted = 0;
+                       } else
+                               sas_target_priv_data = NULL;
+                       if (starget)
+                               starget_printk(KERN_INFO, starget,
+                                   "handle(0x%04x), sas_addr(0x%016llx), "
+                                   "enclosure logical id(0x%016llx), "
+                                   "slot(%d)\n", handle,
+                                   (unsigned long long)sas_device->sas_address,
+                                   (unsigned long long)
+                                   sas_device->enclosure_logical_id,
+                                   sas_device->slot);
+                       if (sas_device->handle == handle)
+                               goto out;
+                       pr_info("\thandle changed from(0x%04x)!!!\n",
+                           sas_device->handle);
+                       sas_device->handle = handle;
+                       if (sas_target_priv_data)
+                               sas_target_priv_data->handle = handle;
+                       goto out;
+               }
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
+/**
+ * _scsih_search_responding_sas_devices -
+ * @ioc: per adapter object
+ *
+ * After host reset, find out whether devices are still responding.
+ * If not remove.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 ioc_status;
+       u16 handle;
+       u32 device_info;
+
+       pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);
+
+       if (list_empty(&ioc->sas_device_list))
+               goto out;
+
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+           &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
+           handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               handle = le16_to_cpu(sas_device_pg0.DevHandle);
+               device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+               if (!(_scsih_is_end_device(device_info)))
+                       continue;
+               _scsih_mark_responding_sas_device(ioc,
+                   le64_to_cpu(sas_device_pg0.SASAddress),
+                   le16_to_cpu(sas_device_pg0.Slot), handle);
+       }
+
+ out:
+       pr_info(MPT3SAS_FMT "search for end-devices: complete\n",
+           ioc->name);
+}
+
+/**
+ * _scsih_mark_responding_raid_device - mark a raid_device as responding
+ * @ioc: per adapter object
+ * @wwid: world wide identifier for raid volume
+ * @handle: device handle
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsih_remove_unresponsive_raid_devices.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
+       u16 handle)
+{
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct scsi_target *starget;
+       struct _raid_device *raid_device;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+               if (raid_device->wwid == wwid && raid_device->starget) {
+                       starget = raid_device->starget;
+                       if (starget && starget->hostdata) {
+                               sas_target_priv_data = starget->hostdata;
+                               sas_target_priv_data->deleted = 0;
+                       } else
+                               sas_target_priv_data = NULL;
+                       raid_device->responding = 1;
+                       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+                       starget_printk(KERN_INFO, raid_device->starget,
+                           "handle(0x%04x), wwid(0x%016llx)\n", handle,
+                           (unsigned long long)raid_device->wwid);
+                       spin_lock_irqsave(&ioc->raid_device_lock, flags);
+                       if (raid_device->handle == handle) {
+                               spin_unlock_irqrestore(&ioc->raid_device_lock,
+                                   flags);
+                               return;
+                       }
+                       pr_info("\thandle changed from(0x%04x)!!!\n",
+                           raid_device->handle);
+                       raid_device->handle = handle;
+                       if (sas_target_priv_data)
+                               sas_target_priv_data->handle = handle;
+                       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+                       return;
+               }
+       }
+       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * _scsih_search_responding_raid_devices -
+ * @ioc: per adapter object
+ *
+ * After host reset, find out whether devices are still responding.
+ * If not remove.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2RaidVolPage1_t volume_pg1;
+       Mpi2RaidVolPage0_t volume_pg0;
+       Mpi2RaidPhysDiskPage0_t pd_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 ioc_status;
+       u16 handle;
+       u8 phys_disk_num;
+
+       if (!ioc->ir_firmware)
+               return;
+
+       pr_info(MPT3SAS_FMT "search for raid volumes: start\n",
+           ioc->name);
+
+       if (list_empty(&ioc->raid_device_list))
+               goto out;
+
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+           &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               handle = le16_to_cpu(volume_pg1.DevHandle);
+
+               if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
+                   &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+                    sizeof(Mpi2RaidVolPage0_t)))
+                       continue;
+
+               if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
+                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
+                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
+                       _scsih_mark_responding_raid_device(ioc,
+                           le64_to_cpu(volume_pg1.WWID), handle);
+       }
+
+       /* refresh the pd_handles */
+               phys_disk_num = 0xFF;
+               memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
+               while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+                   &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
+                   phys_disk_num))) {
+                       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                           MPI2_IOCSTATUS_MASK;
+                       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                               break;
+                       phys_disk_num = pd_pg0.PhysDiskNum;
+                       handle = le16_to_cpu(pd_pg0.DevHandle);
+                       set_bit(handle, ioc->pd_handles);
+               }
+ out:
+       pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
+               ioc->name);
+}
+
+/**
+ * _scsih_mark_responding_expander - mark a expander as responding
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * @handle:
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsih_remove_unresponsive_expanders.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+       u16 handle)
+{
+       struct _sas_node *sas_expander;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+               if (sas_expander->sas_address != sas_address)
+                       continue;
+               sas_expander->responding = 1;
+               if (sas_expander->handle == handle)
+                       goto out;
+               pr_info("\texpander(0x%016llx): handle changed" \
+                   " from(0x%04x) to (0x%04x)!!!\n",
+                   (unsigned long long)sas_expander->sas_address,
+                   sas_expander->handle, handle);
+               sas_expander->handle = handle;
+               for (i = 0 ; i < sas_expander->num_phys ; i++)
+                       sas_expander->phy[i].handle = handle;
+               goto out;
+       }
+ out:
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+}
+
+/**
+ * _scsih_search_responding_expanders -
+ * @ioc: per adapter object
+ *
+ * After host reset, find out whether devices are still responding.
+ * If not remove.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2ExpanderPage0_t expander_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 ioc_status;
+       u64 sas_address;
+       u16 handle;
+
+       pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name);
+
+       if (list_empty(&ioc->sas_expander_list))
+               goto out;
+
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+           MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
+
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+
+               handle = le16_to_cpu(expander_pg0.DevHandle);
+               sas_address = le64_to_cpu(expander_pg0.SASAddress);
+               pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
+                       handle,
+                   (unsigned long long)sas_address);
+               _scsih_mark_responding_expander(ioc, sas_address, handle);
+       }
+
+ out:
+       pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name);
+}
+
+/**
+ * _scsih_remove_unresponding_sas_devices - removing unresponding devices
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct _sas_device *sas_device, *sas_device_next;
+       struct _sas_node *sas_expander, *sas_expander_next;
+       struct _raid_device *raid_device, *raid_device_next;
+       struct list_head tmp_list;
+       unsigned long flags;
+
+       pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
+           ioc->name);
+
+       /* removing unresponding end devices */
+       pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
+           ioc->name);
+       list_for_each_entry_safe(sas_device, sas_device_next,
+           &ioc->sas_device_list, list) {
+               if (!sas_device->responding)
+                       mpt3sas_device_remove_by_sas_address(ioc,
+                           sas_device->sas_address);
+               else
+                       sas_device->responding = 0;
+       }
+
+       /* removing unresponding volumes */
+       if (ioc->ir_firmware) {
+               pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n",
+                       ioc->name);
+               list_for_each_entry_safe(raid_device, raid_device_next,
+                   &ioc->raid_device_list, list) {
+                       if (!raid_device->responding)
+                               _scsih_sas_volume_delete(ioc,
+                                   raid_device->handle);
+                       else
+                               raid_device->responding = 0;
+               }
+       }
+
+       /* removing unresponding expanders */
+       pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n",
+           ioc->name);
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       INIT_LIST_HEAD(&tmp_list);
+       list_for_each_entry_safe(sas_expander, sas_expander_next,
+           &ioc->sas_expander_list, list) {
+               if (!sas_expander->responding)
+                       list_move_tail(&sas_expander->list, &tmp_list);
+               else
+                       sas_expander->responding = 0;
+       }
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+       list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
+           list) {
+               list_del(&sas_expander->list);
+               _scsih_expander_node_remove(ioc, sas_expander);
+       }
+
+       pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n",
+           ioc->name);
+
+       /* unblock devices */
+       _scsih_ublock_io_all_device(ioc);
+}
+
+static void
+_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_expander, u16 handle)
+{
+       Mpi2ExpanderPage1_t expander_pg1;
+       Mpi2ConfigReply_t mpi_reply;
+       int i;
+
+       for (i = 0 ; i < sas_expander->num_phys ; i++) {
+               if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
+                   &expander_pg1, i, handle))) {
+                       pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       return;
+               }
+
+               mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
+                   le16_to_cpu(expander_pg1.AttachedDevHandle), i,
+                   expander_pg1.NegotiatedLinkRate >> 4);
+       }
+}
+
+/**
+ * _scsih_scan_for_devices_after_reset - scan for devices after host reset
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2ExpanderPage0_t expander_pg0;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2RaidVolPage1_t volume_pg1;
+       Mpi2RaidVolPage0_t volume_pg0;
+       Mpi2RaidPhysDiskPage0_t pd_pg0;
+       Mpi2EventIrConfigElement_t element;
+       Mpi2ConfigReply_t mpi_reply;
+       u8 phys_disk_num;
+       u16 ioc_status;
+       u16 handle, parent_handle;
+       u64 sas_address;
+       struct _sas_device *sas_device;
+       struct _sas_node *expander_device;
+       static struct _raid_device *raid_device;
+       u8 retry_count;
+       unsigned long flags;
+
+       pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name);
+
+       _scsih_sas_host_refresh(ioc);
+
+       pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name);
+
+       /* expanders */
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+           MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
+                           "ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, ioc_status,
+                           le32_to_cpu(mpi_reply.IOCLogInfo));
+                       break;
+               }
+               handle = le16_to_cpu(expander_pg0.DevHandle);
+               spin_lock_irqsave(&ioc->sas_node_lock, flags);
+               expander_device = mpt3sas_scsih_expander_find_by_sas_address(
+                   ioc, le64_to_cpu(expander_pg0.SASAddress));
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               if (expander_device)
+                       _scsih_refresh_expander_links(ioc, expander_device,
+                           handle);
+               else {
+                       pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \
+                           "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
+                           handle, (unsigned long long)
+                           le64_to_cpu(expander_pg0.SASAddress));
+                       _scsih_expander_add(ioc, handle);
+                       pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \
+                           "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
+                           handle, (unsigned long long)
+                           le64_to_cpu(expander_pg0.SASAddress));
+               }
+       }
+
+       pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n",
+           ioc->name);
+
+       if (!ioc->ir_firmware)
+               goto skip_to_sas;
+
+       pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name);
+
+       /* phys disk */
+       phys_disk_num = 0xFF;
+       while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+           &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
+           phys_disk_num))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
+                           "ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, ioc_status,
+                           le32_to_cpu(mpi_reply.IOCLogInfo));
+                       break;
+               }
+               phys_disk_num = pd_pg0.PhysDiskNum;
+               handle = le16_to_cpu(pd_pg0.DevHandle);
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               if (sas_device)
+                       continue;
+               if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+                   handle) != 0)
+                       continue;
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \
+                           "ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, ioc_status,
+                           le32_to_cpu(mpi_reply.IOCLogInfo));
+                       break;
+               }
+               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+               if (!_scsih_get_sas_address(ioc, parent_handle,
+                   &sas_address)) {
+                       pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \
+                           " handle (0x%04x), sas_addr(0x%016llx)\n",
+                           ioc->name, handle, (unsigned long long)
+                           le64_to_cpu(sas_device_pg0.SASAddress));
+                       mpt3sas_transport_update_links(ioc, sas_address,
+                           handle, sas_device_pg0.PhyNum,
+                           MPI2_SAS_NEG_LINK_RATE_1_5);
+                       set_bit(handle, ioc->pd_handles);
+                       retry_count = 0;
+                       /* This will retry adding the end device.
+                        * _scsih_add_device() will decide on retries and
+                        * return "1" when it should be retried
+                        */
+                       while (_scsih_add_device(ioc, handle, retry_count++,
+                           1)) {
+                               ssleep(1);
+                       }
+                       pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \
+                           " handle (0x%04x), sas_addr(0x%016llx)\n",
+                           ioc->name, handle, (unsigned long long)
+                           le64_to_cpu(sas_device_pg0.SASAddress));
+               }
+       }
+
+       pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n",
+           ioc->name);
+
+       pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name);
+
+       /* volumes */
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+           &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
+                           "ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, ioc_status,
+                           le32_to_cpu(mpi_reply.IOCLogInfo));
+                       break;
+               }
+               handle = le16_to_cpu(volume_pg1.DevHandle);
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = _scsih_raid_device_find_by_wwid(ioc,
+                   le64_to_cpu(volume_pg1.WWID));
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+               if (raid_device)
+                       continue;
+               if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
+                   &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+                    sizeof(Mpi2RaidVolPage0_t)))
+                       continue;
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
+                           "ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, ioc_status,
+                           le32_to_cpu(mpi_reply.IOCLogInfo));
+                       break;
+               }
+               if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
+                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
+                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
+                       memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
+                       element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
+                       element.VolDevHandle = volume_pg1.DevHandle;
+                       pr_info(MPT3SAS_FMT
+                               "\tBEFORE adding volume: handle (0x%04x)\n",
+                               ioc->name, volume_pg1.DevHandle);
+                       _scsih_sas_volume_add(ioc, &element);
+                       pr_info(MPT3SAS_FMT
+                               "\tAFTER adding volume: handle (0x%04x)\n",
+                               ioc->name, volume_pg1.DevHandle);
+               }
+       }
+
+       pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n",
+           ioc->name);
+
+ skip_to_sas:
+
+       pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n",
+           ioc->name);
+
+       /* sas devices */
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+           &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
+           handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
+                           " ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, ioc_status,
+                           le32_to_cpu(mpi_reply.IOCLogInfo));
+                       break;
+               }
+               handle = le16_to_cpu(sas_device_pg0.DevHandle);
+               if (!(_scsih_is_end_device(
+                   le32_to_cpu(sas_device_pg0.DeviceInfo))))
+                       continue;
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+                   le64_to_cpu(sas_device_pg0.SASAddress));
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               if (sas_device)
+                       continue;
+               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+               if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
+                       pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
+                           "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
+                           handle, (unsigned long long)
+                           le64_to_cpu(sas_device_pg0.SASAddress));
+                       mpt3sas_transport_update_links(ioc, sas_address, handle,
+                           sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+                       retry_count = 0;
+                       /* This will retry adding the end device.
+                        * _scsih_add_device() will decide on retries and
+                        * return "1" when it should be retried
+                        */
+                       while (_scsih_add_device(ioc, handle, retry_count++,
+                           0)) {
+                               ssleep(1);
+                       }
+                       pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \
+                           "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
+                           handle, (unsigned long long)
+                           le64_to_cpu(sas_device_pg0.SASAddress));
+               }
+       }
+       pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
+           ioc->name);
+
+       pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
+}
+/**
+ * mpt3sas_scsih_reset_handler - reset callback handler (for scsih)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
+ * MPT3_IOC_DONE_RESET
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
+{
+       switch (reset_phase) {
+       case MPT3_IOC_PRE_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
+               break;
+       case MPT3_IOC_AFTER_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
+               if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->scsih_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
+                       complete(&ioc->scsih_cmds.done);
+               }
+               if (ioc->tm_cmds.status & MPT3_CMD_PENDING) {
+                       ioc->tm_cmds.status |= MPT3_CMD_RESET;
+                       mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid);
+                       complete(&ioc->tm_cmds.done);
+               }
+
+               _scsih_fw_event_cleanup_queue(ioc);
+               _scsih_flush_running_cmds(ioc);
+               break;
+       case MPT3_IOC_DONE_RESET:
+               dtmprintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
+               if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
+                   !ioc->sas_hba.num_phys)) {
+                       _scsih_prep_device_scan(ioc);
+                       _scsih_search_responding_sas_devices(ioc);
+                       _scsih_search_responding_raid_devices(ioc);
+                       _scsih_search_responding_expanders(ioc);
+                       _scsih_error_recovery_delete_devices(ioc);
+               }
+               break;
+       }
+}
+
+/**
+ * _mpt3sas_fw_work - delayed task for processing firmware events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
+{
+       /* the queue is being flushed so ignore this event */
+       if (ioc->remove_host || fw_event->cancel_pending_work ||
+           ioc->pci_error_recovery) {
+               _scsih_fw_event_free(ioc, fw_event);
+               return;
+       }
+
+       switch (fw_event->event) {
+       case MPT3SAS_PROCESS_TRIGGER_DIAG:
+               mpt3sas_process_trigger_data(ioc, fw_event->event_data);
+               break;
+       case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
+               while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
+                       ssleep(1);
+               _scsih_remove_unresponding_sas_devices(ioc);
+               _scsih_scan_for_devices_after_reset(ioc);
+               break;
+       case MPT3SAS_PORT_ENABLE_COMPLETE:
+               ioc->start_scan = 0;
+       if (missing_delay[0] != -1 && missing_delay[1] != -1)
+                       mpt3sas_base_update_missing_delay(ioc, missing_delay[0],
+                           missing_delay[1]);
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                       "port enable: complete from worker thread\n",
+                       ioc->name));
+               break;
+       case MPT3SAS_TURN_ON_FAULT_LED:
+               _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
+               break;
+       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+               _scsih_sas_topology_change_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+               _scsih_sas_device_status_change_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_SAS_DISCOVERY:
+               _scsih_sas_discovery_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+               _scsih_sas_broadcast_primitive_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+               _scsih_sas_enclosure_dev_status_change_event(ioc,
+                   fw_event);
+               break;
+       case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+               _scsih_sas_ir_config_change_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_IR_VOLUME:
+               _scsih_sas_ir_volume_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_IR_PHYSICAL_DISK:
+               _scsih_sas_ir_physical_disk_event(ioc, fw_event);
+               break;
+       case MPI2_EVENT_IR_OPERATION_STATUS:
+               _scsih_sas_ir_operation_status_event(ioc, fw_event);
+               break;
+       }
+       _scsih_fw_event_free(ioc, fw_event);
+}
+
+/**
+ * _firmware_event_work
+ * @ioc: per adapter object
+ * @work: The fw_event_work object
+ * Context: user.
+ *
+ * wrappers for the work thread handling firmware events
+ *
+ * Return nothing.
+ */
+
+static void
+_firmware_event_work(struct work_struct *work)
+{
+       struct fw_event_work *fw_event = container_of(work,
+           struct fw_event_work, work);
+
+       _mpt3sas_fw_work(fw_event->ioc, fw_event);
+}
+
+/**
+ * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
+ * @ioc: per adapter object
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt.
+ *
+ * This function merely adds a new work task into ioc->firmware_event_thread.
+ * The tasks are worked from _firmware_event_work in user context.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
+       u32 reply)
+{
+       struct fw_event_work *fw_event;
+       Mpi2EventNotificationReply_t *mpi_reply;
+       u16 event;
+       u16 sz;
+
+       /* events turned off due to host reset or driver unloading */
+       if (ioc->remove_host || ioc->pci_error_recovery)
+               return 1;
+
+       mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
+
+       if (unlikely(!mpi_reply)) {
+               pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return 1;
+       }
+
+       event = le16_to_cpu(mpi_reply->Event);
+
+       if (event != MPI2_EVENT_LOG_ENTRY_ADDED)
+               mpt3sas_trigger_event(ioc, event, 0);
+
+       switch (event) {
+       /* handle these */
+       case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+       {
+               Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
+                   (Mpi2EventDataSasBroadcastPrimitive_t *)
+                   mpi_reply->EventData;
+
+               if (baen_data->Primitive !=
+                   MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
+                       return 1;
+
+               if (ioc->broadcast_aen_busy) {
+                       ioc->broadcast_aen_pending++;
+                       return 1;
+               } else
+                       ioc->broadcast_aen_busy = 1;
+               break;
+       }
+
+       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+               _scsih_check_topo_delete_events(ioc,
+                   (Mpi2EventDataSasTopologyChangeList_t *)
+                   mpi_reply->EventData);
+               break;
+       case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+               _scsih_check_ir_config_unhide_events(ioc,
+                   (Mpi2EventDataIrConfigChangeList_t *)
+                   mpi_reply->EventData);
+               break;
+       case MPI2_EVENT_IR_VOLUME:
+               _scsih_check_volume_delete_events(ioc,
+                   (Mpi2EventDataIrVolume_t *)
+                   mpi_reply->EventData);
+               break;
+
+       case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+       case MPI2_EVENT_IR_OPERATION_STATUS:
+       case MPI2_EVENT_SAS_DISCOVERY:
+       case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+       case MPI2_EVENT_IR_PHYSICAL_DISK:
+               break;
+
+       default: /* ignore the rest */
+               return 1;
+       }
+
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return 1;
+       }
+       sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
+       fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
+       if (!fw_event->event_data) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               kfree(fw_event);
+               return 1;
+       }
+
+       memcpy(fw_event->event_data, mpi_reply->EventData, sz);
+       fw_event->ioc = ioc;
+       fw_event->VF_ID = mpi_reply->VF_ID;
+       fw_event->VP_ID = mpi_reply->VP_ID;
+       fw_event->event = event;
+       _scsih_fw_event_add(ioc, fw_event);
+       return 1;
+}
+
+/* shost template */
+static struct scsi_host_template scsih_driver_template = {
+       .module                         = THIS_MODULE,
+       .name                           = "Fusion MPT SAS Host",
+       .proc_name                      = MPT3SAS_DRIVER_NAME,
+       .queuecommand                   = _scsih_qcmd,
+       .target_alloc                   = _scsih_target_alloc,
+       .slave_alloc                    = _scsih_slave_alloc,
+       .slave_configure                = _scsih_slave_configure,
+       .target_destroy                 = _scsih_target_destroy,
+       .slave_destroy                  = _scsih_slave_destroy,
+       .scan_finished                  = _scsih_scan_finished,
+       .scan_start                     = _scsih_scan_start,
+       .change_queue_depth             = _scsih_change_queue_depth,
+       .change_queue_type              = _scsih_change_queue_type,
+       .eh_abort_handler               = _scsih_abort,
+       .eh_device_reset_handler        = _scsih_dev_reset,
+       .eh_target_reset_handler        = _scsih_target_reset,
+       .eh_host_reset_handler          = _scsih_host_reset,
+       .bios_param                     = _scsih_bios_param,
+       .can_queue                      = 1,
+       .this_id                        = -1,
+       .sg_tablesize                   = MPT3SAS_SG_DEPTH,
+       .max_sectors                    = 32767,
+       .cmd_per_lun                    = 7,
+       .use_clustering                 = ENABLE_CLUSTERING,
+       .shost_attrs                    = mpt3sas_host_attrs,
+       .sdev_attrs                     = mpt3sas_dev_attrs,
+};
+
+/**
+ * _scsih_expander_node_remove - removing expander device from list.
+ * @ioc: per adapter object
+ * @sas_expander: the sas_device object
+ * Context: Calling function should acquire ioc->sas_node_lock.
+ *
+ * Removing object and freeing associated memory from the
+ * ioc->sas_expander_list.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_expander)
+{
+       struct _sas_port *mpt3sas_port, *next;
+
+       /* remove sibling ports attached to this expander */
+       list_for_each_entry_safe(mpt3sas_port, next,
+          &sas_expander->sas_port_list, port_list) {
+               if (ioc->shost_recovery)
+                       return;
+               if (mpt3sas_port->remote_identify.device_type ==
+                   SAS_END_DEVICE)
+                       mpt3sas_device_remove_by_sas_address(ioc,
+                           mpt3sas_port->remote_identify.sas_address);
+               else if (mpt3sas_port->remote_identify.device_type ==
+                   SAS_EDGE_EXPANDER_DEVICE ||
+                   mpt3sas_port->remote_identify.device_type ==
+                   SAS_FANOUT_EXPANDER_DEVICE)
+                       mpt3sas_expander_remove(ioc,
+                           mpt3sas_port->remote_identify.sas_address);
+       }
+
+       mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
+           sas_expander->sas_address_parent);
+
+       pr_info(MPT3SAS_FMT
+               "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
+               ioc->name,
+           sas_expander->handle, (unsigned long long)
+           sas_expander->sas_address);
+
+       kfree(sas_expander->phy);
+       kfree(sas_expander);
+}
+
+/**
+ * _scsih_ir_shutdown - IR shutdown notification
+ * @ioc: per adapter object
+ *
+ * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
+ * the host system is shutting down.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2RaidActionRequest_t *mpi_request;
+       Mpi2RaidActionReply_t *mpi_reply;
+       u16 smid;
+
+       /* is IR firmware build loaded ? */
+       if (!ioc->ir_firmware)
+               return;
+
+       /* are there any volumes ? */
+       if (list_empty(&ioc->raid_device_list))
+               return;
+
+       mutex_lock(&ioc->scsih_cmds.mutex);
+
+       if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
+                   ioc->name, __func__);
+               goto out;
+       }
+       ioc->scsih_cmds.status = MPT3_CMD_PENDING;
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+               goto out;
+       }
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->scsih_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
+
+       mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
+       mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
+
+       pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
+       init_completion(&ioc->scsih_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
+
+       if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               goto out;
+       }
+
+       if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
+               mpi_reply = ioc->scsih_cmds.reply;
+               pr_info(MPT3SAS_FMT
+                       "IR shutdown (complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+                   le32_to_cpu(mpi_reply->IOCLogInfo));
+       }
+
+ out:
+       ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_unlock(&ioc->scsih_cmds.mutex);
+}
+
+/**
+ * _scsih_remove - detach and remove add host
+ * @pdev: PCI device struct
+ *
+ * Routine called when unloading the driver.
+ * Return nothing.
+ */
+static void __devexit
+_scsih_remove(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       struct _sas_port *mpt3sas_port, *next_port;
+       struct _raid_device *raid_device, *next;
+       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct workqueue_struct *wq;
+       unsigned long flags;
+
+       ioc->remove_host = 1;
+       _scsih_fw_event_cleanup_queue(ioc);
+
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       wq = ioc->firmware_event_thread;
+       ioc->firmware_event_thread = NULL;
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+       if (wq)
+               destroy_workqueue(wq);
+
+       /* release all the volumes */
+       _scsih_ir_shutdown(ioc);
+       list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
+           list) {
+               if (raid_device->starget) {
+                       sas_target_priv_data =
+                           raid_device->starget->hostdata;
+                       sas_target_priv_data->deleted = 1;
+                       scsi_remove_target(&raid_device->starget->dev);
+               }
+               pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
+                       ioc->name,  raid_device->handle,
+                   (unsigned long long) raid_device->wwid);
+               _scsih_raid_device_remove(ioc, raid_device);
+       }
+
+       /* free ports attached to the sas_host */
+       list_for_each_entry_safe(mpt3sas_port, next_port,
+          &ioc->sas_hba.sas_port_list, port_list) {
+               if (mpt3sas_port->remote_identify.device_type ==
+                   SAS_END_DEVICE)
+                       mpt3sas_device_remove_by_sas_address(ioc,
+                           mpt3sas_port->remote_identify.sas_address);
+               else if (mpt3sas_port->remote_identify.device_type ==
+                   SAS_EDGE_EXPANDER_DEVICE ||
+                   mpt3sas_port->remote_identify.device_type ==
+                   SAS_FANOUT_EXPANDER_DEVICE)
+                       mpt3sas_expander_remove(ioc,
+                           mpt3sas_port->remote_identify.sas_address);
+       }
+
+       /* free phys attached to the sas_host */
+       if (ioc->sas_hba.num_phys) {
+               kfree(ioc->sas_hba.phy);
+               ioc->sas_hba.phy = NULL;
+               ioc->sas_hba.num_phys = 0;
+       }
+
+       sas_remove_host(shost);
+       mpt3sas_base_detach(ioc);
+       list_del(&ioc->list);
+       scsi_remove_host(shost);
+       scsi_host_put(shost);
+}
+
+/**
+ * _scsih_shutdown - routine call during system shutdown
+ * @pdev: PCI device struct
+ *
+ * Return nothing.
+ */
+static void
+_scsih_shutdown(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       struct workqueue_struct *wq;
+       unsigned long flags;
+
+       ioc->remove_host = 1;
+       _scsih_fw_event_cleanup_queue(ioc);
+
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       wq = ioc->firmware_event_thread;
+       ioc->firmware_event_thread = NULL;
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+       if (wq)
+               destroy_workqueue(wq);
+
+       _scsih_ir_shutdown(ioc);
+       mpt3sas_base_detach(ioc);
+}
+
+
+/**
+ * _scsih_probe_boot_devices - reports 1st device
+ * @ioc: per adapter object
+ *
+ * If specified in bios page 2, this routine reports the 1st
+ * device scsi-ml or sas transport for persistent boot device
+ * purposes.  Please refer to function _scsih_determine_boot_device()
+ */
+static void
+_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
+{
+       u8 is_raid;
+       void *device;
+       struct _sas_device *sas_device;
+       struct _raid_device *raid_device;
+       u16 handle;
+       u64 sas_address_parent;
+       u64 sas_address;
+       unsigned long flags;
+       int rc;
+
+        /* no Bios, return immediately */
+       if (!ioc->bios_pg3.BiosVersion)
+               return;
+
+       device = NULL;
+       is_raid = 0;
+       if (ioc->req_boot_device.device) {
+               device =  ioc->req_boot_device.device;
+               is_raid = ioc->req_boot_device.is_raid;
+       } else if (ioc->req_alt_boot_device.device) {
+               device =  ioc->req_alt_boot_device.device;
+               is_raid = ioc->req_alt_boot_device.is_raid;
+       } else if (ioc->current_boot_device.device) {
+               device =  ioc->current_boot_device.device;
+               is_raid = ioc->current_boot_device.is_raid;
+       }
+
+       if (!device)
+               return;
+
+       if (is_raid) {
+               raid_device = device;
+               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+                   raid_device->id, 0);
+               if (rc)
+                       _scsih_raid_device_remove(ioc, raid_device);
+       } else {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = device;
+               handle = sas_device->handle;
+               sas_address_parent = sas_device->sas_address_parent;
+               sas_address = sas_device->sas_address;
+               list_move_tail(&sas_device->list, &ioc->sas_device_list);
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+               if (!mpt3sas_transport_port_add(ioc, handle,
+                   sas_address_parent)) {
+                       _scsih_sas_device_remove(ioc, sas_device);
+               } else if (!sas_device->starget) {
+                       if (!ioc->is_driver_loading)
+                               mpt3sas_transport_port_remove(ioc, sas_address,
+                                   sas_address_parent);
+                       _scsih_sas_device_remove(ioc, sas_device);
+               }
+       }
+}
+
+/**
+ * _scsih_probe_raid - reporting raid volumes to scsi-ml
+ * @ioc: per adapter object
+ *
+ * Called during initial loading of the driver.
+ */
+static void
+_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct _raid_device *raid_device, *raid_next;
+       int rc;
+
+       list_for_each_entry_safe(raid_device, raid_next,
+           &ioc->raid_device_list, list) {
+               if (raid_device->starget)
+                       continue;
+               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+                   raid_device->id, 0);
+               if (rc)
+                       _scsih_raid_device_remove(ioc, raid_device);
+       }
+}
+
+/**
+ * _scsih_probe_sas - reporting sas devices to sas transport
+ * @ioc: per adapter object
+ *
+ * Called during initial loading of the driver.
+ */
+static void
+_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct _sas_device *sas_device, *next;
+       unsigned long flags;
+
+       /* SAS Device List */
+       list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
+           list) {
+
+               if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
+                   sas_device->sas_address_parent)) {
+                       list_del(&sas_device->list);
+                       kfree(sas_device);
+                       continue;
+               } else if (!sas_device->starget) {
+                       /*
+                        * When asyn scanning is enabled, its not possible to
+                        * remove devices while scanning is turned on due to an
+                        * oops in scsi_sysfs_add_sdev()->add_device()->
+                        * sysfs_addrm_start()
+                        */
+                       if (!ioc->is_driver_loading)
+                               mpt3sas_transport_port_remove(ioc,
+                                   sas_device->sas_address,
+                                   sas_device->sas_address_parent);
+                       list_del(&sas_device->list);
+                       kfree(sas_device);
+                       continue;
+               }
+
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               list_move_tail(&sas_device->list, &ioc->sas_device_list);
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       }
+}
+
+/**
+ * _scsih_probe_devices - probing for devices
+ * @ioc: per adapter object
+ *
+ * Called during initial loading of the driver.
+ */
+static void
+_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
+{
+       u16 volume_mapping_flags;
+
+       if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
+               return;  /* return when IOC doesn't support initiator mode */
+
+       _scsih_probe_boot_devices(ioc);
+
+       if (ioc->ir_firmware) {
+               volume_mapping_flags =
+                   le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
+                   MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+               if (volume_mapping_flags ==
+                   MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
+                       _scsih_probe_raid(ioc);
+                       _scsih_probe_sas(ioc);
+               } else {
+                       _scsih_probe_sas(ioc);
+                       _scsih_probe_raid(ioc);
+               }
+       } else
+               _scsih_probe_sas(ioc);
+}
+
+/**
+ * _scsih_scan_start - scsi lld callback for .scan_start
+ * @shost: SCSI host pointer
+ *
+ * The shost has the ability to discover targets on its own instead
+ * of scanning the entire bus.  In our implemention, we will kick off
+ * firmware discovery.
+ */
+static void
+_scsih_scan_start(struct Scsi_Host *shost)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       int rc;
+       if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
+               mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
+
+       if (disable_discovery > 0)
+               return;
+
+       ioc->start_scan = 1;
+       rc = mpt3sas_port_enable(ioc);
+
+       if (rc != 0)
+               pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name);
+}
+
+/**
+ * _scsih_scan_finished - scsi lld callback for .scan_finished
+ * @shost: SCSI host pointer
+ * @time: elapsed time of the scan in jiffies
+ *
+ * This function will be called periodicallyn until it returns 1 with the
+ * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
+ * we wait for firmware discovery to complete, then return 1.
+ */
+static int
+_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       if (disable_discovery > 0) {
+               ioc->is_driver_loading = 0;
+               ioc->wait_for_discovery_to_complete = 0;
+               return 1;
+       }
+
+       if (time >= (300 * HZ)) {
+               ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+               pr_info(MPT3SAS_FMT
+                       "port enable: FAILED with timeout (timeout=300s)\n",
+                       ioc->name);
+               ioc->is_driver_loading = 0;
+               return 1;
+       }
+
+       if (ioc->start_scan)
+               return 0;
+
+       if (ioc->start_scan_failed) {
+               pr_info(MPT3SAS_FMT
+                       "port enable: FAILED with (ioc_status=0x%08x)\n",
+                       ioc->name, ioc->start_scan_failed);
+               ioc->is_driver_loading = 0;
+               ioc->wait_for_discovery_to_complete = 0;
+               ioc->remove_host = 1;
+               return 1;
+       }
+
+       pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name);
+       ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+
+       if (ioc->wait_for_discovery_to_complete) {
+               ioc->wait_for_discovery_to_complete = 0;
+               _scsih_probe_devices(ioc);
+       }
+       mpt3sas_base_start_watchdog(ioc);
+       ioc->is_driver_loading = 0;
+       return 1;
+}
+
+/**
+ * _scsih_probe - attach and add scsi host
+ * @pdev: PCI device struct
+ * @id: pci device id
+ *
+ * Returns 0 success, anything else error.
+ */
+static int
+_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct MPT3SAS_ADAPTER *ioc;
+       struct Scsi_Host *shost;
+
+       shost = scsi_host_alloc(&scsih_driver_template,
+           sizeof(struct MPT3SAS_ADAPTER));
+       if (!shost)
+               return -ENODEV;
+
+       /* init local params */
+       ioc = shost_priv(shost);
+       memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+       INIT_LIST_HEAD(&ioc->list);
+       list_add_tail(&ioc->list, &mpt3sas_ioc_list);
+       ioc->shost = shost;
+       ioc->id = mpt_ids++;
+       sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id);
+       ioc->pdev = pdev;
+       ioc->scsi_io_cb_idx = scsi_io_cb_idx;
+       ioc->tm_cb_idx = tm_cb_idx;
+       ioc->ctl_cb_idx = ctl_cb_idx;
+       ioc->base_cb_idx = base_cb_idx;
+       ioc->port_enable_cb_idx = port_enable_cb_idx;
+       ioc->transport_cb_idx = transport_cb_idx;
+       ioc->scsih_cb_idx = scsih_cb_idx;
+       ioc->config_cb_idx = config_cb_idx;
+       ioc->tm_tr_cb_idx = tm_tr_cb_idx;
+       ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
+       ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
+       ioc->logging_level = logging_level;
+       ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
+       /* misc semaphores and spin locks */
+       mutex_init(&ioc->reset_in_progress_mutex);
+       spin_lock_init(&ioc->ioc_reset_in_progress_lock);
+       spin_lock_init(&ioc->scsi_lookup_lock);
+       spin_lock_init(&ioc->sas_device_lock);
+       spin_lock_init(&ioc->sas_node_lock);
+       spin_lock_init(&ioc->fw_event_lock);
+       spin_lock_init(&ioc->raid_device_lock);
+       spin_lock_init(&ioc->diag_trigger_lock);
+
+       INIT_LIST_HEAD(&ioc->sas_device_list);
+       INIT_LIST_HEAD(&ioc->sas_device_init_list);
+       INIT_LIST_HEAD(&ioc->sas_expander_list);
+       INIT_LIST_HEAD(&ioc->fw_event_list);
+       INIT_LIST_HEAD(&ioc->raid_device_list);
+       INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
+       INIT_LIST_HEAD(&ioc->delayed_tr_list);
+       INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
+
+       /* init shost parameters */
+       shost->max_cmd_len = 32;
+       shost->max_lun = max_lun;
+       shost->transportt = mpt3sas_transport_template;
+       shost->unique_id = ioc->id;
+
+       if (max_sectors != 0xFFFF) {
+               if (max_sectors < 64) {
+                       shost->max_sectors = 64;
+                       pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
+                           "for max_sectors, range is 64 to 32767. Assigning "
+                           "value of 64.\n", ioc->name, max_sectors);
+               } else if (max_sectors > 32767) {
+                       shost->max_sectors = 32767;
+                       pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
+                           "for max_sectors, range is 64 to 32767. Assigning "
+                           "default value of 32767.\n", ioc->name,
+                           max_sectors);
+               } else {
+                       shost->max_sectors = max_sectors & 0xFFFE;
+                       pr_info(MPT3SAS_FMT
+                               "The max_sectors value is set to %d\n",
+                               ioc->name, shost->max_sectors);
+               }
+       }
+
+       if ((scsi_add_host(shost, &pdev->dev))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               list_del(&ioc->list);
+               goto out_add_shost_fail;
+       }
+
+       /* register EEDP capabilities with SCSI layer */
+       if (prot_mask > 0)
+               scsi_host_set_prot(shost, prot_mask);
+       else
+               scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
+                                  | SHOST_DIF_TYPE2_PROTECTION
+                                  | SHOST_DIF_TYPE3_PROTECTION);
+
+       scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+
+       /* event thread */
+       snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
+           "fw_event%d", ioc->id);
+       ioc->firmware_event_thread = create_singlethread_workqueue(
+           ioc->firmware_event_name);
+       if (!ioc->firmware_event_thread) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_thread_fail;
+       }
+
+       ioc->is_driver_loading = 1;
+       if ((mpt3sas_base_attach(ioc))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_attach_fail;
+       }
+       scsi_scan_host(shost);
+       return 0;
+
+ out_attach_fail:
+       destroy_workqueue(ioc->firmware_event_thread);
+ out_thread_fail:
+       list_del(&ioc->list);
+       scsi_remove_host(shost);
+ out_add_shost_fail:
+       scsi_host_put(shost);
+       return -ENODEV;
+}
+
+#ifdef CONFIG_PM
+/**
+ * _scsih_suspend - power management suspend main entry point
+ * @pdev: PCI device struct
+ * @state: PM state change to (usually PCI_D3)
+ *
+ * Returns 0 success, anything else error.
+ */
+static int
+_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       pci_power_t device_state;
+
+       mpt3sas_base_stop_watchdog(ioc);
+       flush_scheduled_work();
+       scsi_block_requests(shost);
+       device_state = pci_choose_state(pdev, state);
+       pr_info(MPT3SAS_FMT
+               "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
+               ioc->name, pdev, pci_name(pdev), device_state);
+
+       pci_save_state(pdev);
+       mpt3sas_base_free_resources(ioc);
+       pci_set_power_state(pdev, device_state);
+       return 0;
+}
+
+/**
+ * _scsih_resume - power management resume main entry point
+ * @pdev: PCI device struct
+ *
+ * Returns 0 success, anything else error.
+ */
+static int
+_scsih_resume(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       pci_power_t device_state = pdev->current_state;
+       int r;
+
+       pr_info(MPT3SAS_FMT
+               "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
+               ioc->name, pdev, pci_name(pdev), device_state);
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_enable_wake(pdev, PCI_D0, 0);
+       pci_restore_state(pdev);
+       ioc->pdev = pdev;
+       r = mpt3sas_base_map_resources(ioc);
+       if (r)
+               return r;
+
+       mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
+       scsi_unblock_requests(shost);
+       mpt3sas_base_start_watchdog(ioc);
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+/**
+ * _scsih_pci_error_detected - Called when a PCI error is detected.
+ * @pdev: PCI device struct
+ * @state: PCI channel state
+ *
+ * Description: Called when a PCI error is detected.
+ *
+ * Return value:
+ *      PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
+ */
+static pci_ers_result_t
+_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n",
+           ioc->name, state);
+
+       switch (state) {
+       case pci_channel_io_normal:
+               return PCI_ERS_RESULT_CAN_RECOVER;
+       case pci_channel_io_frozen:
+               /* Fatal error, prepare for slot reset */
+               ioc->pci_error_recovery = 1;
+               scsi_block_requests(ioc->shost);
+               mpt3sas_base_stop_watchdog(ioc);
+               mpt3sas_base_free_resources(ioc);
+               return PCI_ERS_RESULT_NEED_RESET;
+       case pci_channel_io_perm_failure:
+               /* Permanent error, prepare for device removal */
+               ioc->pci_error_recovery = 1;
+               mpt3sas_base_stop_watchdog(ioc);
+               _scsih_flush_running_cmds(ioc);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * _scsih_pci_slot_reset - Called when PCI slot has been reset.
+ * @pdev: PCI device struct
+ *
+ * Description: This routine is called by the pci error recovery
+ * code after the PCI slot has been reset, just before we
+ * should resume normal operations.
+ */
+static pci_ers_result_t
+_scsih_pci_slot_reset(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       int rc;
+
+       pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n",
+            ioc->name);
+
+       ioc->pci_error_recovery = 0;
+       ioc->pdev = pdev;
+       pci_restore_state(pdev);
+       rc = mpt3sas_base_map_resources(ioc);
+       if (rc)
+               return PCI_ERS_RESULT_DISCONNECT;
+
+       rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+           FORCE_BIG_HAMMER);
+
+       pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
+           (rc == 0) ? "success" : "failed");
+
+       if (!rc)
+               return PCI_ERS_RESULT_RECOVERED;
+       else
+               return PCI_ERS_RESULT_DISCONNECT;
+}
+
+/**
+ * _scsih_pci_resume() - resume normal ops after PCI reset
+ * @pdev: pointer to PCI device
+ *
+ * Called when the error recovery driver tells us that its
+ * OK to resume normal operation. Use completion to allow
+ * halted scsi ops to resume.
+ */
+static void
+_scsih_pci_resume(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name);
+
+       pci_cleanup_aer_uncorrect_error_status(pdev);
+       mpt3sas_base_start_watchdog(ioc);
+       scsi_unblock_requests(ioc->shost);
+}
+
+/**
+ * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
+ * @pdev: pointer to PCI device
+ */
+static pci_ers_result_t
+_scsih_pci_mmio_enabled(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n",
+           ioc->name);
+
+       /* TODO - dump whatever for debugging purposes */
+
+       /* Request a slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/* raid transport support */
+static struct raid_function_template mpt3sas_raid_functions = {
+       .cookie         = &scsih_driver_template,
+       .is_raid        = _scsih_is_raid,
+       .get_resync     = _scsih_get_resync,
+       .get_state      = _scsih_get_state,
+};
+
+static struct pci_error_handlers _scsih_err_handler = {
+       .error_detected = _scsih_pci_error_detected,
+       .mmio_enabled = _scsih_pci_mmio_enabled,
+       .slot_reset =   _scsih_pci_slot_reset,
+       .resume =       _scsih_pci_resume,
+};
+
+static struct pci_driver scsih_driver = {
+       .name           = MPT3SAS_DRIVER_NAME,
+       .id_table       = scsih_pci_table,
+       .probe          = _scsih_probe,
+       .remove         = __devexit_p(_scsih_remove),
+       .shutdown       = _scsih_shutdown,
+       .err_handler    = &_scsih_err_handler,
+#ifdef CONFIG_PM
+       .suspend        = _scsih_suspend,
+       .resume         = _scsih_resume,
+#endif
+};
+
+
+/**
+ * _scsih_init - main entry point for this driver.
+ *
+ * Returns 0 success, anything else error.
+ */
+static int __init
+_scsih_init(void)
+{
+       int error;
+
+       mpt_ids = 0;
+
+       pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
+           MPT3SAS_DRIVER_VERSION);
+
+       mpt3sas_transport_template =
+           sas_attach_transport(&mpt3sas_transport_functions);
+       if (!mpt3sas_transport_template)
+               return -ENODEV;
+
+/* raid transport support */
+       mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions);
+       if (!mpt3sas_raid_template) {
+               sas_release_transport(mpt3sas_transport_template);
+               return -ENODEV;
+       }
+
+       mpt3sas_base_initialize_callback_handler();
+
+        /* queuecommand callback hander */
+       scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);
+
+       /* task managment callback handler */
+       tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);
+
+       /* base internal commands callback handler */
+       base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
+       port_enable_cb_idx = mpt3sas_base_register_callback_handler(
+           mpt3sas_port_enable_done);
+
+       /* transport internal commands callback handler */
+       transport_cb_idx = mpt3sas_base_register_callback_handler(
+           mpt3sas_transport_done);
+
+       /* scsih internal commands callback handler */
+       scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);
+
+       /* configuration page API internal commands callback handler */
+       config_cb_idx = mpt3sas_base_register_callback_handler(
+           mpt3sas_config_done);
+
+       /* ctl module callback handler */
+       ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);
+
+       tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
+           _scsih_tm_tr_complete);
+
+       tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
+           _scsih_tm_volume_tr_complete);
+
+       tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
+           _scsih_sas_control_complete);
+
+       mpt3sas_ctl_init();
+
+       error = pci_register_driver(&scsih_driver);
+       if (error) {
+               /* raid transport support */
+               raid_class_release(mpt3sas_raid_template);
+               sas_release_transport(mpt3sas_transport_template);
+       }
+
+       return error;
+}
+
+/**
+ * _scsih_exit - exit point for this driver (when it is a module).
+ *
+ * Returns 0 success, anything else error.
+ */
+static void __exit
+_scsih_exit(void)
+{
+       pr_info("mpt3sas version %s unloading\n",
+           MPT3SAS_DRIVER_VERSION);
+
+       mpt3sas_ctl_exit();
+
+       pci_unregister_driver(&scsih_driver);
+
+
+       mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
+       mpt3sas_base_release_callback_handler(tm_cb_idx);
+       mpt3sas_base_release_callback_handler(base_cb_idx);
+       mpt3sas_base_release_callback_handler(port_enable_cb_idx);
+       mpt3sas_base_release_callback_handler(transport_cb_idx);
+       mpt3sas_base_release_callback_handler(scsih_cb_idx);
+       mpt3sas_base_release_callback_handler(config_cb_idx);
+       mpt3sas_base_release_callback_handler(ctl_cb_idx);
+
+       mpt3sas_base_release_callback_handler(tm_tr_cb_idx);
+       mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx);
+       mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
+
+/* raid transport support */
+       raid_class_release(mpt3sas_raid_template);
+       sas_release_transport(mpt3sas_transport_template);
+}
+
+module_init(_scsih_init);
+module_exit(_scsih_exit);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
new file mode 100644 (file)
index 0000000..87ca2b7
--- /dev/null
@@ -0,0 +1,2128 @@
+/*
+ * SAS Transport Layer for MPT (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_transport.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_sas.h>
+#include <scsi/scsi_dbg.h>
+
+#include "mpt3sas_base.h"
+
+/**
+ * _transport_sas_node_find_by_sas_address - sas node search
+ * @ioc: per adapter object
+ * @sas_address: sas address of expander or sas host
+ * Context: Calling function should acquire ioc->sas_node_lock.
+ *
+ * Search for either hba phys or expander device based on handle, then returns
+ * the sas_node object.
+ */
+static struct _sas_node *
+_transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address)
+{
+       if (ioc->sas_hba.sas_address == sas_address)
+               return &ioc->sas_hba;
+       else
+               return mpt3sas_scsih_expander_find_by_sas_address(ioc,
+                   sas_address);
+}
+
+/**
+ * _transport_convert_phy_link_rate -
+ * @link_rate: link rate returned from mpt firmware
+ *
+ * Convert link_rate from mpi fusion into sas_transport form.
+ */
+static enum sas_linkrate
+_transport_convert_phy_link_rate(u8 link_rate)
+{
+       enum sas_linkrate rc;
+
+       switch (link_rate) {
+       case MPI2_SAS_NEG_LINK_RATE_1_5:
+               rc = SAS_LINK_RATE_1_5_GBPS;
+               break;
+       case MPI2_SAS_NEG_LINK_RATE_3_0:
+               rc = SAS_LINK_RATE_3_0_GBPS;
+               break;
+       case MPI2_SAS_NEG_LINK_RATE_6_0:
+               rc = SAS_LINK_RATE_6_0_GBPS;
+               break;
+       case MPI25_SAS_NEG_LINK_RATE_12_0:
+               rc = SAS_LINK_RATE_12_0_GBPS;
+               break;
+       case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
+               rc = SAS_PHY_DISABLED;
+               break;
+       case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
+               rc = SAS_LINK_RATE_FAILED;
+               break;
+       case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
+               rc = SAS_SATA_PORT_SELECTOR;
+               break;
+       case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
+               rc = SAS_PHY_RESET_IN_PROGRESS;
+               break;
+
+       default:
+       case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
+       case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
+               rc = SAS_LINK_RATE_UNKNOWN;
+               break;
+       }
+       return rc;
+}
+
+/**
+ * _transport_set_identify - set identify for phys and end devices
+ * @ioc: per adapter object
+ * @handle: device handle
+ * @identify: sas identify info
+ *
+ * Populates sas identify info.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_set_identify(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       struct sas_identify *identify)
+{
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u32 device_info;
+       u32 ioc_status;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery) {
+               pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+
+       if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -ENXIO;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT
+                       "handle(0x%04x), ioc_status(0x%04x)\nfailure at %s:%d/%s()!\n",
+                       ioc->name, handle, ioc_status,
+                    __FILE__, __LINE__, __func__);
+               return -EIO;
+       }
+
+       memset(identify, 0, sizeof(struct sas_identify));
+       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+
+       /* sas_address */
+       identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+
+       /* phy number of the parent device this device is linked to */
+       identify->phy_identifier = sas_device_pg0.PhyNum;
+
+       /* device_type */
+       switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+       case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
+               identify->device_type = SAS_PHY_UNUSED;
+               break;
+       case MPI2_SAS_DEVICE_INFO_END_DEVICE:
+               identify->device_type = SAS_END_DEVICE;
+               break;
+       case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
+               identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
+               break;
+       case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+               identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
+               break;
+       }
+
+       /* initiator_port_protocols */
+       if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
+       if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
+       if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
+       if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
+               identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
+
+       /* target_port_protocols */
+       if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
+               identify->target_port_protocols |= SAS_PROTOCOL_SSP;
+       if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
+               identify->target_port_protocols |= SAS_PROTOCOL_STP;
+       if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
+               identify->target_port_protocols |= SAS_PROTOCOL_SMP;
+       if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+               identify->target_port_protocols |= SAS_PROTOCOL_SATA;
+
+       return 0;
+}
+
+/**
+ * mpt3sas_transport_done -  internal transport layer callback handler.
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Callback handler when sending internal generated transport cmds.
+ * The callback index passed is `ioc->transport_cb_idx`
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+
+       mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
+       if (ioc->transport_cmds.status == MPT3_CMD_NOT_USED)
+               return 1;
+       if (ioc->transport_cmds.smid != smid)
+               return 1;
+       ioc->transport_cmds.status |= MPT3_CMD_COMPLETE;
+       if (mpi_reply) {
+               memcpy(ioc->transport_cmds.reply, mpi_reply,
+                   mpi_reply->MsgLength*4);
+               ioc->transport_cmds.status |= MPT3_CMD_REPLY_VALID;
+       }
+       ioc->transport_cmds.status &= ~MPT3_CMD_PENDING;
+       complete(&ioc->transport_cmds.done);
+       return 1;
+}
+
+/* report manufacture request structure */
+struct rep_manu_request {
+       u8 smp_frame_type;
+       u8 function;
+       u8 reserved;
+       u8 request_length;
+};
+
+/* report manufacture reply structure */
+struct rep_manu_reply {
+       u8 smp_frame_type; /* 0x41 */
+       u8 function; /* 0x01 */
+       u8 function_result;
+       u8 response_length;
+       u16 expander_change_count;
+       u8 reserved0[2];
+       u8 sas_format;
+       u8 reserved2[3];
+       u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
+       u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
+       u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
+       u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
+       u16 component_id;
+       u8 component_revision_id;
+       u8 reserved3;
+       u8 vendor_specific[8];
+};
+
+/**
+ * transport_expander_report_manufacture - obtain SMP report_manufacture
+ * @ioc: per adapter object
+ * @sas_address: expander sas address
+ * @edev: the sas_expander_device object
+ *
+ * Fills in the sas_expander_device object when SMP port is created.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address, struct sas_expander_device *edev)
+{
+       Mpi2SmpPassthroughRequest_t *mpi_request;
+       Mpi2SmpPassthroughReply_t *mpi_reply;
+       struct rep_manu_reply *manufacture_reply;
+       struct rep_manu_request *manufacture_request;
+       int rc;
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       void *psge;
+       u8 issue_reset = 0;
+       void *data_out = NULL;
+       dma_addr_t data_out_dma;
+       dma_addr_t data_in_dma;
+       size_t data_in_sz;
+       size_t data_out_sz;
+       u16 wait_state_count;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery) {
+               pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+
+       mutex_lock(&ioc->transport_cmds.mutex);
+
+       if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+       ioc->transport_cmds.status = MPT3_CMD_PENDING;
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       rc = -EFAULT;
+                       goto out;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name, __func__, wait_state_count);
+       }
+       if (wait_state_count)
+               pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+                   ioc->name, __func__);
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       rc = 0;
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->transport_cmds.smid = smid;
+
+       data_out_sz = sizeof(struct rep_manu_request);
+       data_in_sz = sizeof(struct rep_manu_reply);
+       data_out = pci_alloc_consistent(ioc->pdev, data_out_sz + data_in_sz,
+           &data_out_dma);
+
+       if (!data_out) {
+               pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                   __LINE__, __func__);
+               rc = -ENOMEM;
+               mpt3sas_base_free_smid(ioc, smid);
+               goto out;
+       }
+
+       data_in_dma = data_out_dma + sizeof(struct rep_manu_request);
+
+       manufacture_request = data_out;
+       manufacture_request->smp_frame_type = 0x40;
+       manufacture_request->function = 1;
+       manufacture_request->reserved = 0;
+       manufacture_request->request_length = 0;
+
+       memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+       mpi_request->PhysicalPort = 0xFF;
+       mpi_request->SASAddress = cpu_to_le64(sas_address);
+       mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
+       psge = &mpi_request->SGL;
+
+       ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
+           data_in_sz);
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "report_manufacture - send to sas_addr(0x%016llx)\n",
+               ioc->name, (unsigned long long)sas_address));
+       init_completion(&ioc->transport_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
+           10*HZ);
+
+       if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
+               if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "report_manufacture - complete\n", ioc->name));
+
+       if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
+               u8 *tmp;
+
+               mpi_reply = ioc->transport_cmds.reply;
+
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "report_manufacture - reply data transfer size(%d)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
+
+               if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
+                   sizeof(struct rep_manu_reply))
+                       goto out;
+
+               manufacture_reply = data_out + sizeof(struct rep_manu_request);
+               strncpy(edev->vendor_id, manufacture_reply->vendor_id,
+                    SAS_EXPANDER_VENDOR_ID_LEN);
+               strncpy(edev->product_id, manufacture_reply->product_id,
+                    SAS_EXPANDER_PRODUCT_ID_LEN);
+               strncpy(edev->product_rev, manufacture_reply->product_rev,
+                    SAS_EXPANDER_PRODUCT_REV_LEN);
+               edev->level = manufacture_reply->sas_format & 1;
+               if (edev->level) {
+                       strncpy(edev->component_vendor_id,
+                           manufacture_reply->component_vendor_id,
+                            SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+                       tmp = (u8 *)&manufacture_reply->component_id;
+                       edev->component_id = tmp[0] << 8 | tmp[1];
+                       edev->component_revision_id =
+                           manufacture_reply->component_revision_id;
+               }
+       } else
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "report_manufacture - no reply\n", ioc->name));
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+ out:
+       ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
+       if (data_out)
+               pci_free_consistent(ioc->pdev, data_out_sz + data_in_sz,
+                   data_out, data_out_dma);
+
+       mutex_unlock(&ioc->transport_cmds.mutex);
+       return rc;
+}
+
+
+/**
+ * _transport_delete_port - helper function to removing a port
+ * @ioc: per adapter object
+ * @mpt3sas_port: mpt3sas per port object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_port *mpt3sas_port)
+{
+       u64 sas_address = mpt3sas_port->remote_identify.sas_address;
+       enum sas_device_type device_type =
+           mpt3sas_port->remote_identify.device_type;
+
+       dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
+           "remove: sas_addr(0x%016llx)\n",
+           (unsigned long long) sas_address);
+
+       ioc->logging_level |= MPT_DEBUG_TRANSPORT;
+       if (device_type == SAS_END_DEVICE)
+               mpt3sas_device_remove_by_sas_address(ioc, sas_address);
+       else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
+           device_type == SAS_FANOUT_EXPANDER_DEVICE)
+               mpt3sas_expander_remove(ioc, sas_address);
+       ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
+}
+
+/**
+ * _transport_delete_phy - helper function to removing single phy from port
+ * @ioc: per adapter object
+ * @mpt3sas_port: mpt3sas per port object
+ * @mpt3sas_phy: mpt3sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_delete_phy(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy)
+{
+       u64 sas_address = mpt3sas_port->remote_identify.sas_address;
+
+       dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
+           "remove: sas_addr(0x%016llx), phy(%d)\n",
+           (unsigned long long) sas_address, mpt3sas_phy->phy_id);
+
+       list_del(&mpt3sas_phy->port_siblings);
+       mpt3sas_port->num_phys--;
+       sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+       mpt3sas_phy->phy_belongs_to_port = 0;
+}
+
+/**
+ * _transport_add_phy - helper function to adding single phy to port
+ * @ioc: per adapter object
+ * @mpt3sas_port: mpt3sas per port object
+ * @mpt3sas_phy: mpt3sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port,
+       struct _sas_phy *mpt3sas_phy)
+{
+       u64 sas_address = mpt3sas_port->remote_identify.sas_address;
+
+       dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
+           "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
+           sas_address, mpt3sas_phy->phy_id);
+
+       list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list);
+       mpt3sas_port->num_phys++;
+       sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+       mpt3sas_phy->phy_belongs_to_port = 1;
+}
+
+/**
+ * _transport_add_phy_to_an_existing_port - adding new phy to existing port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @mpt3sas_phy: mpt3sas per phy object
+ * @sas_address: sas address of device/expander were phy needs to be added to
+ *
+ * Returns nothing.
+ */
+static void
+_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
+       u64 sas_address)
+{
+       struct _sas_port *mpt3sas_port;
+       struct _sas_phy *phy_srch;
+
+       if (mpt3sas_phy->phy_belongs_to_port == 1)
+               return;
+
+       list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list,
+           port_list) {
+               if (mpt3sas_port->remote_identify.sas_address !=
+                   sas_address)
+                       continue;
+               list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
+                   port_siblings) {
+                       if (phy_srch == mpt3sas_phy)
+                               return;
+               }
+               _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy);
+                       return;
+       }
+
+}
+
+/**
+ * _transport_del_phy_from_an_existing_port - delete phy from existing port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @mpt3sas_phy: mpt3sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy)
+{
+       struct _sas_port *mpt3sas_port, *next;
+       struct _sas_phy *phy_srch;
+
+       if (mpt3sas_phy->phy_belongs_to_port == 0)
+               return;
+
+       list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
+           port_list) {
+               list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
+                   port_siblings) {
+                       if (phy_srch != mpt3sas_phy)
+                               continue;
+
+                       if (mpt3sas_port->num_phys == 1)
+                               _transport_delete_port(ioc, mpt3sas_port);
+                       else
+                               _transport_delete_phy(ioc, mpt3sas_port,
+                                   mpt3sas_phy);
+                       return;
+               }
+       }
+}
+
+/**
+ * _transport_sanity_check - sanity check when adding a new port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @sas_address: sas address of device being added
+ *
+ * See the explanation above from _transport_delete_duplicate_port
+ */
+static void
+_transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
+       u64 sas_address)
+{
+       int i;
+
+       for (i = 0; i < sas_node->num_phys; i++) {
+               if (sas_node->phy[i].remote_identify.sas_address != sas_address)
+                       continue;
+               if (sas_node->phy[i].phy_belongs_to_port == 1)
+                       _transport_del_phy_from_an_existing_port(ioc, sas_node,
+                           &sas_node->phy[i]);
+       }
+}
+
+/**
+ * mpt3sas_transport_port_add - insert port to the list
+ * @ioc: per adapter object
+ * @handle: handle of attached device
+ * @sas_address: sas address of parent expander or sas host
+ * Context: This function will acquire ioc->sas_node_lock.
+ *
+ * Adding new port object to the sas_node->sas_port_list.
+ *
+ * Returns mpt3sas_port.
+ */
+struct _sas_port *
+mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+       u64 sas_address)
+{
+       struct _sas_phy *mpt3sas_phy, *next;
+       struct _sas_port *mpt3sas_port;
+       unsigned long flags;
+       struct _sas_node *sas_node;
+       struct sas_rphy *rphy;
+       int i;
+       struct sas_port *port;
+
+       mpt3sas_port = kzalloc(sizeof(struct _sas_port),
+           GFP_KERNEL);
+       if (!mpt3sas_port) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return NULL;
+       }
+
+       INIT_LIST_HEAD(&mpt3sas_port->port_list);
+       INIT_LIST_HEAD(&mpt3sas_port->phy_list);
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       if (!sas_node) {
+               pr_err(MPT3SAS_FMT
+                       "%s: Could not find parent sas_address(0x%016llx)!\n",
+                       ioc->name, __func__, (unsigned long long)sas_address);
+               goto out_fail;
+       }
+
+       if ((_transport_set_identify(ioc, handle,
+           &mpt3sas_port->remote_identify))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_fail;
+       }
+
+       if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_fail;
+       }
+
+       _transport_sanity_check(ioc, sas_node,
+           mpt3sas_port->remote_identify.sas_address);
+
+       for (i = 0; i < sas_node->num_phys; i++) {
+               if (sas_node->phy[i].remote_identify.sas_address !=
+                   mpt3sas_port->remote_identify.sas_address)
+                       continue;
+               list_add_tail(&sas_node->phy[i].port_siblings,
+                   &mpt3sas_port->phy_list);
+               mpt3sas_port->num_phys++;
+       }
+
+       if (!mpt3sas_port->num_phys) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_fail;
+       }
+
+       port = sas_port_alloc_num(sas_node->parent_dev);
+       if ((sas_port_add(port))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               goto out_fail;
+       }
+
+       list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list,
+           port_siblings) {
+               if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+                       dev_printk(KERN_INFO, &port->dev,
+                               "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n",
+                               handle, (unsigned long long)
+                           mpt3sas_port->remote_identify.sas_address,
+                           mpt3sas_phy->phy_id);
+               sas_port_add_phy(port, mpt3sas_phy->phy);
+               mpt3sas_phy->phy_belongs_to_port = 1;
+       }
+
+       mpt3sas_port->port = port;
+       if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
+               rphy = sas_end_device_alloc(port);
+       else
+               rphy = sas_expander_alloc(port,
+                   mpt3sas_port->remote_identify.device_type);
+
+       rphy->identify = mpt3sas_port->remote_identify;
+       if ((sas_rphy_add(rphy))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+       }
+       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+               dev_printk(KERN_INFO, &rphy->dev,
+                       "add: handle(0x%04x), sas_addr(0x%016llx)\n",
+                       handle, (unsigned long long)
+                   mpt3sas_port->remote_identify.sas_address);
+       mpt3sas_port->rphy = rphy;
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       /* fill in report manufacture */
+       if (mpt3sas_port->remote_identify.device_type ==
+           MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+           mpt3sas_port->remote_identify.device_type ==
+           MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
+               _transport_expander_report_manufacture(ioc,
+                   mpt3sas_port->remote_identify.sas_address,
+                   rphy_to_expander_device(rphy));
+       return mpt3sas_port;
+
+ out_fail:
+       list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
+           port_siblings)
+               list_del(&mpt3sas_phy->port_siblings);
+       kfree(mpt3sas_port);
+       return NULL;
+}
+
+/**
+ * mpt3sas_transport_port_remove - remove port from the list
+ * @ioc: per adapter object
+ * @sas_address: sas address of attached device
+ * @sas_address_parent: sas address of parent expander or sas host
+ * Context: This function will acquire ioc->sas_node_lock.
+ *
+ * Removing object and freeing associated memory from the
+ * ioc->sas_port_list.
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+       u64 sas_address_parent)
+{
+       int i;
+       unsigned long flags;
+       struct _sas_port *mpt3sas_port, *next;
+       struct _sas_node *sas_node;
+       u8 found = 0;
+       struct _sas_phy *mpt3sas_phy, *next_phy;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_node = _transport_sas_node_find_by_sas_address(ioc,
+           sas_address_parent);
+       if (!sas_node) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return;
+       }
+       list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
+           port_list) {
+               if (mpt3sas_port->remote_identify.sas_address != sas_address)
+                       continue;
+               found = 1;
+               list_del(&mpt3sas_port->port_list);
+               goto out;
+       }
+ out:
+       if (!found) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return;
+       }
+
+       for (i = 0; i < sas_node->num_phys; i++) {
+               if (sas_node->phy[i].remote_identify.sas_address == sas_address)
+                       memset(&sas_node->phy[i].remote_identify, 0 ,
+                           sizeof(struct sas_identify));
+       }
+
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       list_for_each_entry_safe(mpt3sas_phy, next_phy,
+           &mpt3sas_port->phy_list, port_siblings) {
+               if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+                       dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
+                           "remove: sas_addr(0x%016llx), phy(%d)\n",
+                           (unsigned long long)
+                           mpt3sas_port->remote_identify.sas_address,
+                           mpt3sas_phy->phy_id);
+               mpt3sas_phy->phy_belongs_to_port = 0;
+               sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+               list_del(&mpt3sas_phy->port_siblings);
+       }
+       sas_port_delete(mpt3sas_port->port);
+       kfree(mpt3sas_port);
+}
+
+/**
+ * mpt3sas_transport_add_host_phy - report sas_host phy to transport
+ * @ioc: per adapter object
+ * @mpt3sas_phy: mpt3sas per phy object
+ * @phy_pg0: sas phy page 0
+ * @parent_dev: parent device class object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
+       *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
+{
+       struct sas_phy *phy;
+       int phy_index = mpt3sas_phy->phy_id;
+
+
+       INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
+       phy = sas_phy_alloc(parent_dev, phy_index);
+       if (!phy) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+       if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
+           &mpt3sas_phy->identify))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               sas_phy_free(phy);
+               return -1;
+       }
+       phy->identify = mpt3sas_phy->identify;
+       mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
+       if (mpt3sas_phy->attached_handle)
+               _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
+                   &mpt3sas_phy->remote_identify);
+       phy->identify.phy_identifier = mpt3sas_phy->phy_id;
+       phy->negotiated_linkrate = _transport_convert_phy_link_rate(
+           phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
+       phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
+           phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
+       phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
+           phy_pg0.HwLinkRate >> 4);
+       phy->minimum_linkrate = _transport_convert_phy_link_rate(
+           phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
+       phy->maximum_linkrate = _transport_convert_phy_link_rate(
+           phy_pg0.ProgrammedLinkRate >> 4);
+
+       if ((sas_phy_add(phy))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               sas_phy_free(phy);
+               return -1;
+       }
+       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+               dev_printk(KERN_INFO, &phy->dev,
+                   "add: handle(0x%04x), sas_addr(0x%016llx)\n"
+                   "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
+                   mpt3sas_phy->handle, (unsigned long long)
+                   mpt3sas_phy->identify.sas_address,
+                   mpt3sas_phy->attached_handle,
+                   (unsigned long long)
+                   mpt3sas_phy->remote_identify.sas_address);
+       mpt3sas_phy->phy = phy;
+       return 0;
+}
+
+
+/**
+ * mpt3sas_transport_add_expander_phy - report expander phy to transport
+ * @ioc: per adapter object
+ * @mpt3sas_phy: mpt3sas per phy object
+ * @expander_pg1: expander page 1
+ * @parent_dev: parent device class object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
+       *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
+       struct device *parent_dev)
+{
+       struct sas_phy *phy;
+       int phy_index = mpt3sas_phy->phy_id;
+
+       INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
+       phy = sas_phy_alloc(parent_dev, phy_index);
+       if (!phy) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -1;
+       }
+       if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
+           &mpt3sas_phy->identify))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               sas_phy_free(phy);
+               return -1;
+       }
+       phy->identify = mpt3sas_phy->identify;
+       mpt3sas_phy->attached_handle =
+           le16_to_cpu(expander_pg1.AttachedDevHandle);
+       if (mpt3sas_phy->attached_handle)
+               _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
+                   &mpt3sas_phy->remote_identify);
+       phy->identify.phy_identifier = mpt3sas_phy->phy_id;
+       phy->negotiated_linkrate = _transport_convert_phy_link_rate(
+           expander_pg1.NegotiatedLinkRate &
+           MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
+       phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
+           expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
+       phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
+           expander_pg1.HwLinkRate >> 4);
+       phy->minimum_linkrate = _transport_convert_phy_link_rate(
+           expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
+       phy->maximum_linkrate = _transport_convert_phy_link_rate(
+           expander_pg1.ProgrammedLinkRate >> 4);
+
+       if ((sas_phy_add(phy))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               sas_phy_free(phy);
+               return -1;
+       }
+       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+               dev_printk(KERN_INFO, &phy->dev,
+                   "add: handle(0x%04x), sas_addr(0x%016llx)\n"
+                   "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
+                   mpt3sas_phy->handle, (unsigned long long)
+                   mpt3sas_phy->identify.sas_address,
+                   mpt3sas_phy->attached_handle,
+                   (unsigned long long)
+                   mpt3sas_phy->remote_identify.sas_address);
+       mpt3sas_phy->phy = phy;
+       return 0;
+}
+
+/**
+ * mpt3sas_transport_update_links - refreshing phy link changes
+ * @ioc: per adapter object
+ * @sas_address: sas address of parent expander or sas host
+ * @handle: attached device handle
+ * @phy_numberv: phy number
+ * @link_rate: new link rate
+ *
+ * Returns nothing.
+ */
+void
+mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
+       u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
+{
+       unsigned long flags;
+       struct _sas_node *sas_node;
+       struct _sas_phy *mpt3sas_phy;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery)
+               return;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
+       if (!sas_node) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return;
+       }
+
+       mpt3sas_phy = &sas_node->phy[phy_number];
+       mpt3sas_phy->attached_handle = handle;
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+       if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
+               _transport_set_identify(ioc, handle,
+                   &mpt3sas_phy->remote_identify);
+               _transport_add_phy_to_an_existing_port(ioc, sas_node,
+                   mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
+       } else
+               memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
+                   sas_identify));
+
+       if (mpt3sas_phy->phy)
+               mpt3sas_phy->phy->negotiated_linkrate =
+                   _transport_convert_phy_link_rate(link_rate);
+
+       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+               dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
+                   "refresh: parent sas_addr(0x%016llx),\n"
+                   "\tlink_rate(0x%02x), phy(%d)\n"
+                   "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
+                   (unsigned long long)sas_address,
+                   link_rate, phy_number, handle, (unsigned long long)
+                   mpt3sas_phy->remote_identify.sas_address);
+}
+
+static inline void *
+phy_to_ioc(struct sas_phy *phy)
+{
+       struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+       return shost_priv(shost);
+}
+
+static inline void *
+rphy_to_ioc(struct sas_rphy *rphy)
+{
+       struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+       return shost_priv(shost);
+}
+
+/* report phy error log structure */
+struct phy_error_log_request {
+       u8 smp_frame_type; /* 0x40 */
+       u8 function; /* 0x11 */
+       u8 allocated_response_length;
+       u8 request_length; /* 02 */
+       u8 reserved_1[5];
+       u8 phy_identifier;
+       u8 reserved_2[2];
+};
+
+/* report phy error log reply structure */
+struct phy_error_log_reply {
+       u8 smp_frame_type; /* 0x41 */
+       u8 function; /* 0x11 */
+       u8 function_result;
+       u8 response_length;
+       __be16 expander_change_count;
+       u8 reserved_1[3];
+       u8 phy_identifier;
+       u8 reserved_2[2];
+       __be32 invalid_dword;
+       __be32 running_disparity_error;
+       __be32 loss_of_dword_sync;
+       __be32 phy_reset_problem;
+};
+
+/**
+ * _transport_get_expander_phy_error_log - return expander counters
+ * @ioc: per adapter object
+ * @phy: The sas phy object
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+_transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
+       struct sas_phy *phy)
+{
+       Mpi2SmpPassthroughRequest_t *mpi_request;
+       Mpi2SmpPassthroughReply_t *mpi_reply;
+       struct phy_error_log_request *phy_error_log_request;
+       struct phy_error_log_reply *phy_error_log_reply;
+       int rc;
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       void *psge;
+       u8 issue_reset = 0;
+       void *data_out = NULL;
+       dma_addr_t data_out_dma;
+       u32 sz;
+       u16 wait_state_count;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery) {
+               pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+
+       mutex_lock(&ioc->transport_cmds.mutex);
+
+       if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+       ioc->transport_cmds.status = MPT3_CMD_PENDING;
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       rc = -EFAULT;
+                       goto out;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name, __func__, wait_state_count);
+       }
+       if (wait_state_count)
+               pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+                   ioc->name, __func__);
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->transport_cmds.smid = smid;
+
+       sz = sizeof(struct phy_error_log_request) +
+           sizeof(struct phy_error_log_reply);
+       data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
+       if (!data_out) {
+               pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                   __LINE__, __func__);
+               rc = -ENOMEM;
+               mpt3sas_base_free_smid(ioc, smid);
+               goto out;
+       }
+
+       rc = -EINVAL;
+       memset(data_out, 0, sz);
+       phy_error_log_request = data_out;
+       phy_error_log_request->smp_frame_type = 0x40;
+       phy_error_log_request->function = 0x11;
+       phy_error_log_request->request_length = 2;
+       phy_error_log_request->allocated_response_length = 0;
+       phy_error_log_request->phy_identifier = phy->number;
+
+       memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+       mpi_request->PhysicalPort = 0xFF;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+       mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
+       mpi_request->RequestDataLength =
+           cpu_to_le16(sizeof(struct phy_error_log_request));
+       psge = &mpi_request->SGL;
+
+       ioc->build_sg(ioc, psge, data_out_dma,
+               sizeof(struct phy_error_log_request),
+           data_out_dma + sizeof(struct phy_error_log_request),
+           sizeof(struct phy_error_log_reply));
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n",
+               ioc->name, (unsigned long long)phy->identify.sas_address,
+               phy->number));
+       init_completion(&ioc->transport_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
+           10*HZ);
+
+       if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
+               if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "phy_error_log - complete\n", ioc->name));
+
+       if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
+
+               mpi_reply = ioc->transport_cmds.reply;
+
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "phy_error_log - reply data transfer size(%d)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
+
+               if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
+                   sizeof(struct phy_error_log_reply))
+                       goto out;
+
+               phy_error_log_reply = data_out +
+                   sizeof(struct phy_error_log_request);
+
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "phy_error_log - function_result(%d)\n",
+                   ioc->name, phy_error_log_reply->function_result));
+
+               phy->invalid_dword_count =
+                   be32_to_cpu(phy_error_log_reply->invalid_dword);
+               phy->running_disparity_error_count =
+                   be32_to_cpu(phy_error_log_reply->running_disparity_error);
+               phy->loss_of_dword_sync_count =
+                   be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
+               phy->phy_reset_problem_count =
+                   be32_to_cpu(phy_error_log_reply->phy_reset_problem);
+               rc = 0;
+       } else
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "phy_error_log - no reply\n", ioc->name));
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+ out:
+       ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
+       if (data_out)
+               pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
+
+       mutex_unlock(&ioc->transport_cmds.mutex);
+       return rc;
+}
+
+/**
+ * _transport_get_linkerrors - return phy counters for both hba and expanders
+ * @phy: The sas phy object
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+_transport_get_linkerrors(struct sas_phy *phy)
+{
+       struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
+       unsigned long flags;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasPhyPage1_t phy_pg1;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       if (_transport_sas_node_find_by_sas_address(ioc,
+           phy->identify.sas_address) == NULL) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       if (phy->identify.sas_address != ioc->sas_hba.sas_address)
+               return _transport_get_expander_phy_error_log(ioc, phy);
+
+       /* get hba phy error logs */
+       if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
+                   phy->number))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -ENXIO;
+       }
+
+       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
+               pr_info(MPT3SAS_FMT
+                       "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n",
+                       ioc->name, phy->number,
+                       le16_to_cpu(mpi_reply.IOCStatus),
+                   le32_to_cpu(mpi_reply.IOCLogInfo));
+
+       phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
+       phy->running_disparity_error_count =
+           le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
+       phy->loss_of_dword_sync_count =
+           le32_to_cpu(phy_pg1.LossDwordSynchCount);
+       phy->phy_reset_problem_count =
+           le32_to_cpu(phy_pg1.PhyResetProblemCount);
+       return 0;
+}
+
+/**
+ * _transport_get_enclosure_identifier -
+ * @phy: The sas phy object
+ *
+ * Obtain the enclosure logical id for an expander.
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
+{
+       struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       int rc;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+           rphy->identify.sas_address);
+       if (sas_device) {
+               *identifier = sas_device->enclosure_logical_id;
+               rc = 0;
+       } else {
+               *identifier = 0;
+               rc = -ENXIO;
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       return rc;
+}
+
+/**
+ * _transport_get_bay_identifier -
+ * @phy: The sas phy object
+ *
+ * Returns the slot id for a device that resides inside an enclosure.
+ */
+static int
+_transport_get_bay_identifier(struct sas_rphy *rphy)
+{
+       struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       int rc;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+           rphy->identify.sas_address);
+       if (sas_device)
+               rc = sas_device->slot;
+       else
+               rc = -ENXIO;
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       return rc;
+}
+
+/* phy control request structure */
+struct phy_control_request {
+       u8 smp_frame_type; /* 0x40 */
+       u8 function; /* 0x91 */
+       u8 allocated_response_length;
+       u8 request_length; /* 0x09 */
+       u16 expander_change_count;
+       u8 reserved_1[3];
+       u8 phy_identifier;
+       u8 phy_operation;
+       u8 reserved_2[13];
+       u64 attached_device_name;
+       u8 programmed_min_physical_link_rate;
+       u8 programmed_max_physical_link_rate;
+       u8 reserved_3[6];
+};
+
+/* phy control reply structure */
+struct phy_control_reply {
+       u8 smp_frame_type; /* 0x41 */
+       u8 function; /* 0x11 */
+       u8 function_result;
+       u8 response_length;
+};
+
+#define SMP_PHY_CONTROL_LINK_RESET     (0x01)
+#define SMP_PHY_CONTROL_HARD_RESET     (0x02)
+#define SMP_PHY_CONTROL_DISABLE                (0x03)
+
+/**
+ * _transport_expander_phy_control - expander phy control
+ * @ioc: per adapter object
+ * @phy: The sas phy object
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+_transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
+       struct sas_phy *phy, u8 phy_operation)
+{
+       Mpi2SmpPassthroughRequest_t *mpi_request;
+       Mpi2SmpPassthroughReply_t *mpi_reply;
+       struct phy_control_request *phy_control_request;
+       struct phy_control_reply *phy_control_reply;
+       int rc;
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       void *psge;
+       u32 sgl_flags;
+       u8 issue_reset = 0;
+       void *data_out = NULL;
+       dma_addr_t data_out_dma;
+       u32 sz;
+       u16 wait_state_count;
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery) {
+               pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+
+       mutex_lock(&ioc->transport_cmds.mutex);
+
+       if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+       ioc->transport_cmds.status = MPT3_CMD_PENDING;
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       rc = -EFAULT;
+                       goto out;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name, __func__, wait_state_count);
+       }
+       if (wait_state_count)
+               pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+                   ioc->name, __func__);
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->transport_cmds.smid = smid;
+
+       sz = sizeof(struct phy_control_request) +
+           sizeof(struct phy_control_reply);
+       data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
+       if (!data_out) {
+               pr_err("failure at %s:%d/%s()!\n", __FILE__,
+                   __LINE__, __func__);
+               rc = -ENOMEM;
+               mpt3sas_base_free_smid(ioc, smid);
+               goto out;
+       }
+
+       rc = -EINVAL;
+       memset(data_out, 0, sz);
+       phy_control_request = data_out;
+       phy_control_request->smp_frame_type = 0x40;
+       phy_control_request->function = 0x91;
+       phy_control_request->request_length = 9;
+       phy_control_request->allocated_response_length = 0;
+       phy_control_request->phy_identifier = phy->number;
+       phy_control_request->phy_operation = phy_operation;
+       phy_control_request->programmed_min_physical_link_rate =
+           phy->minimum_linkrate << 4;
+       phy_control_request->programmed_max_physical_link_rate =
+           phy->maximum_linkrate << 4;
+
+       memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+       mpi_request->PhysicalPort = 0xFF;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+       mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
+       mpi_request->RequestDataLength =
+           cpu_to_le16(sizeof(struct phy_error_log_request));
+       psge = &mpi_request->SGL;
+
+       /* WRITE sgel first */
+       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
+       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+       ioc->base_add_sg_single(psge, sgl_flags |
+           sizeof(struct phy_control_request), data_out_dma);
+
+       /* incr sgel */
+       psge += ioc->sge_size;
+
+       /* READ sgel last */
+       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+           MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+           MPI2_SGE_FLAGS_END_OF_LIST);
+       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+       ioc->base_add_sg_single(psge, sgl_flags |
+           sizeof(struct phy_control_reply), data_out_dma +
+           sizeof(struct phy_control_request));
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
+               ioc->name, (unsigned long long)phy->identify.sas_address,
+               phy->number, phy_operation));
+       init_completion(&ioc->transport_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
+           10*HZ);
+
+       if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s: timeout\n",
+                   ioc->name, __func__);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
+               if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "phy_control - complete\n", ioc->name));
+
+       if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
+
+               mpi_reply = ioc->transport_cmds.reply;
+
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "phy_control - reply data transfer size(%d)\n",
+                   ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
+
+               if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
+                   sizeof(struct phy_control_reply))
+                       goto out;
+
+               phy_control_reply = data_out +
+                   sizeof(struct phy_control_request);
+
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "phy_control - function_result(%d)\n",
+                   ioc->name, phy_control_reply->function_result));
+
+               rc = 0;
+       } else
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "phy_control - no reply\n", ioc->name));
+
+ issue_host_reset:
+       if (issue_reset)
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+ out:
+       ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
+       if (data_out)
+               pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
+
+       mutex_unlock(&ioc->transport_cmds.mutex);
+       return rc;
+}
+
+/**
+ * _transport_phy_reset -
+ * @phy: The sas phy object
+ * @hard_reset:
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_phy_reset(struct sas_phy *phy, int hard_reset)
+{
+       struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
+       Mpi2SasIoUnitControlReply_t mpi_reply;
+       Mpi2SasIoUnitControlRequest_t mpi_request;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       if (_transport_sas_node_find_by_sas_address(ioc,
+           phy->identify.sas_address) == NULL) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       /* handle expander phys */
+       if (phy->identify.sas_address != ioc->sas_hba.sas_address)
+               return _transport_expander_phy_control(ioc, phy,
+                   (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
+                   SMP_PHY_CONTROL_LINK_RESET);
+
+       /* handle hba phys */
+       memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
+       mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+       mpi_request.Operation = hard_reset ?
+           MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
+       mpi_request.PhyNum = phy->number;
+
+       if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return -ENXIO;
+       }
+
+       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
+               pr_info(MPT3SAS_FMT
+               "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
+               ioc->name, phy->number, le16_to_cpu(mpi_reply.IOCStatus),
+                   le32_to_cpu(mpi_reply.IOCLogInfo));
+
+       return 0;
+}
+
+/**
+ * _transport_phy_enable - enable/disable phys
+ * @phy: The sas phy object
+ * @enable: enable phy when true
+ *
+ * Only support sas_host direct attached phys.
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_phy_enable(struct sas_phy *phy, int enable)
+{
+       struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
+       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+       Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 ioc_status;
+       u16 sz;
+       int rc = 0;
+       unsigned long flags;
+       int i, discovery_active;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       if (_transport_sas_node_find_by_sas_address(ioc,
+           phy->identify.sas_address) == NULL) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       /* handle expander phys */
+       if (phy->identify.sas_address != ioc->sas_hba.sas_address)
+               return _transport_expander_phy_control(ioc, phy,
+                   (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
+                   SMP_PHY_CONTROL_DISABLE);
+
+       /* handle hba phys */
+
+       /* read sas_iounit page 0 */
+       sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
+           sizeof(Mpi2SasIOUnit0PhyData_t));
+       sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg0) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENOMEM;
+               goto out;
+       }
+       if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+           sas_iounit_pg0, sz))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENXIO;
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -EIO;
+               goto out;
+       }
+
+       /* unable to enable/disable phys when when discovery is active */
+       for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
+               if (sas_iounit_pg0->PhyData[i].PortFlags &
+                   MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
+                       pr_err(MPT3SAS_FMT "discovery is active on " \
+                           "port = %d, phy = %d: unable to enable/disable "
+                           "phys, try again later!\n", ioc->name,
+                           sas_iounit_pg0->PhyData[i].Port, i);
+                       discovery_active = 1;
+               }
+       }
+
+       if (discovery_active) {
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       /* read sas_iounit page 1 */
+       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
+           sizeof(Mpi2SasIOUnit1PhyData_t));
+       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg1) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENOMEM;
+               goto out;
+       }
+       if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+           sas_iounit_pg1, sz))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENXIO;
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -EIO;
+               goto out;
+       }
+
+       /* copy Port/PortFlags/PhyFlags from page 0 */
+       for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+               sas_iounit_pg1->PhyData[i].Port =
+                   sas_iounit_pg0->PhyData[i].Port;
+               sas_iounit_pg1->PhyData[i].PortFlags =
+                   (sas_iounit_pg0->PhyData[i].PortFlags &
+                   MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
+               sas_iounit_pg1->PhyData[i].PhyFlags =
+                   (sas_iounit_pg0->PhyData[i].PhyFlags &
+                   (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
+                   MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
+       }
+
+       if (enable)
+               sas_iounit_pg1->PhyData[phy->number].PhyFlags
+                   &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
+       else
+               sas_iounit_pg1->PhyData[phy->number].PhyFlags
+                   |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
+
+       mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
+
+       /* link reset */
+       if (enable)
+               _transport_phy_reset(phy, 0);
+
+ out:
+       kfree(sas_iounit_pg1);
+       kfree(sas_iounit_pg0);
+       return rc;
+}
+
+/**
+ * _transport_phy_speed - set phy min/max link rates
+ * @phy: The sas phy object
+ * @rates: rates defined in sas_phy_linkrates
+ *
+ * Only support sas_host direct attached phys.
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
+{
+       struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
+       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+       Mpi2SasPhyPage0_t phy_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 ioc_status;
+       u16 sz;
+       int i;
+       int rc = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       if (_transport_sas_node_find_by_sas_address(ioc,
+           phy->identify.sas_address) == NULL) {
+               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+       if (!rates->minimum_linkrate)
+               rates->minimum_linkrate = phy->minimum_linkrate;
+       else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
+               rates->minimum_linkrate = phy->minimum_linkrate_hw;
+
+       if (!rates->maximum_linkrate)
+               rates->maximum_linkrate = phy->maximum_linkrate;
+       else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
+               rates->maximum_linkrate = phy->maximum_linkrate_hw;
+
+       /* handle expander phys */
+       if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
+               phy->minimum_linkrate = rates->minimum_linkrate;
+               phy->maximum_linkrate = rates->maximum_linkrate;
+               return _transport_expander_phy_control(ioc, phy,
+                   SMP_PHY_CONTROL_LINK_RESET);
+       }
+
+       /* handle hba phys */
+
+       /* sas_iounit page 1 */
+       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
+           sizeof(Mpi2SasIOUnit1PhyData_t));
+       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+       if (!sas_iounit_pg1) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENOMEM;
+               goto out;
+       }
+       if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+           sas_iounit_pg1, sz))) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENXIO;
+               goto out;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -EIO;
+               goto out;
+       }
+
+       for (i = 0; i < ioc->sas_hba.num_phys; i++) {
+               if (phy->number != i) {
+                       sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
+                           (ioc->sas_hba.phy[i].phy->minimum_linkrate +
+                           (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
+               } else {
+                       sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
+                           (rates->minimum_linkrate +
+                           (rates->maximum_linkrate << 4));
+               }
+       }
+
+       if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
+           sz)) {
+               pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               rc = -ENXIO;
+               goto out;
+       }
+
+       /* link reset */
+       _transport_phy_reset(phy, 0);
+
+       /* read phy page 0, then update the rates in the sas transport phy */
+       if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
+           phy->number)) {
+               phy->minimum_linkrate = _transport_convert_phy_link_rate(
+                   phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
+               phy->maximum_linkrate = _transport_convert_phy_link_rate(
+                   phy_pg0.ProgrammedLinkRate >> 4);
+               phy->negotiated_linkrate = _transport_convert_phy_link_rate(
+                   phy_pg0.NegotiatedLinkRate &
+                   MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
+       }
+
+ out:
+       kfree(sas_iounit_pg1);
+       return rc;
+}
+
+/**
+ * _transport_smp_handler - transport portal for smp passthru
+ * @shost: shost object
+ * @rphy: sas transport rphy object
+ * @req:
+ *
+ * This used primarily for smp_utils.
+ * Example:
+ *           smp_rep_general /sys/class/bsg/expander-5:0
+ */
+static int
+_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
+       struct request *req)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       Mpi2SmpPassthroughRequest_t *mpi_request;
+       Mpi2SmpPassthroughReply_t *mpi_reply;
+       int rc, i;
+       u16 smid;
+       u32 ioc_state;
+       unsigned long timeleft;
+       void *psge;
+       u8 issue_reset = 0;
+       dma_addr_t dma_addr_in = 0;
+       dma_addr_t dma_addr_out = 0;
+       dma_addr_t pci_dma_in = 0;
+       dma_addr_t pci_dma_out = 0;
+       void *pci_addr_in = NULL;
+       void *pci_addr_out = NULL;
+       u16 wait_state_count;
+       struct request *rsp = req->next_rq;
+       struct bio_vec *bvec = NULL;
+
+       if (!rsp) {
+               pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n",
+                       ioc->name, __func__);
+               return -EINVAL;
+       }
+
+       if (ioc->shost_recovery || ioc->pci_error_recovery) {
+               pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+
+       rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
+       if (rc)
+               return rc;
+
+       if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
+               pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name,
+                   __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+       ioc->transport_cmds.status = MPT3_CMD_PENDING;
+
+       /* Check if the request is split across multiple segments */
+       if (req->bio->bi_vcnt > 1) {
+               u32 offset = 0;
+
+               /* Allocate memory and copy the request */
+               pci_addr_out = pci_alloc_consistent(ioc->pdev,
+                   blk_rq_bytes(req), &pci_dma_out);
+               if (!pci_addr_out) {
+                       pr_info(MPT3SAS_FMT "%s(): PCI Addr out = NULL\n",
+                           ioc->name, __func__);
+                       rc = -ENOMEM;
+                       goto out;
+               }
+
+               bio_for_each_segment(bvec, req->bio, i) {
+                       memcpy(pci_addr_out + offset,
+                           page_address(bvec->bv_page) + bvec->bv_offset,
+                           bvec->bv_len);
+                       offset += bvec->bv_len;
+               }
+       } else {
+               dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
+                   blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
+               if (!dma_addr_out) {
+                       pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n",
+                           ioc->name, __func__);
+                       rc = -ENOMEM;
+                       goto free_pci;
+               }
+       }
+
+       /* Check if the response needs to be populated across
+        * multiple segments */
+       if (rsp->bio->bi_vcnt > 1) {
+               pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
+                   &pci_dma_in);
+               if (!pci_addr_in) {
+                       pr_info(MPT3SAS_FMT "%s(): PCI Addr in = NULL\n",
+                           ioc->name, __func__);
+                       rc = -ENOMEM;
+                       goto unmap;
+               }
+       } else {
+               dma_addr_in =  pci_map_single(ioc->pdev, bio_data(rsp->bio),
+                   blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
+               if (!dma_addr_in) {
+                       pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n",
+                           ioc->name, __func__);
+                       rc = -ENOMEM;
+                       goto unmap;
+               }
+       }
+
+       wait_state_count = 0;
+       ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               if (wait_state_count++ == 10) {
+                       pr_err(MPT3SAS_FMT
+                           "%s: failed due to ioc not operational\n",
+                           ioc->name, __func__);
+                       rc = -EFAULT;
+                       goto unmap;
+               }
+               ssleep(1);
+               ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+               pr_info(MPT3SAS_FMT
+                       "%s: waiting for operational state(count=%d)\n",
+                       ioc->name, __func__, wait_state_count);
+       }
+       if (wait_state_count)
+               pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+                   ioc->name, __func__);
+
+       smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
+       if (!smid) {
+               pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto unmap;
+       }
+
+       rc = 0;
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+       ioc->transport_cmds.smid = smid;
+
+       memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+       mpi_request->PhysicalPort = 0xFF;
+       mpi_request->SASAddress = (rphy) ?
+           cpu_to_le64(rphy->identify.sas_address) :
+           cpu_to_le64(ioc->sas_hba.sas_address);
+       mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
+       psge = &mpi_request->SGL;
+
+       if (req->bio->bi_vcnt > 1)
+               ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4),
+                   pci_dma_in, (blk_rq_bytes(rsp) + 4));
+       else
+               ioc->build_sg(ioc, psge, dma_addr_out, (blk_rq_bytes(req) - 4),
+                   dma_addr_in, (blk_rq_bytes(rsp) + 4));
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s - sending smp request\n", ioc->name, __func__));
+
+       init_completion(&ioc->transport_cmds.done);
+       mpt3sas_base_put_smid_default(ioc, smid);
+       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
+           10*HZ);
+
+       if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
+               pr_err(MPT3SAS_FMT "%s : timeout\n",
+                   __func__, ioc->name);
+               _debug_dump_mf(mpi_request,
+                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
+               if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
+                       issue_reset = 1;
+               goto issue_host_reset;
+       }
+
+       dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+               "%s - complete\n", ioc->name, __func__));
+
+       if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
+
+               mpi_reply = ioc->transport_cmds.reply;
+
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s - reply data transfer size(%d)\n",
+                   ioc->name, __func__,
+                   le16_to_cpu(mpi_reply->ResponseDataLength)));
+
+               memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
+               req->sense_len = sizeof(*mpi_reply);
+               req->resid_len = 0;
+               rsp->resid_len -=
+                   le16_to_cpu(mpi_reply->ResponseDataLength);
+
+               /* check if the resp needs to be copied from the allocated
+                * pci mem */
+               if (rsp->bio->bi_vcnt > 1) {
+                       u32 offset = 0;
+                       u32 bytes_to_copy =
+                           le16_to_cpu(mpi_reply->ResponseDataLength);
+                       bio_for_each_segment(bvec, rsp->bio, i) {
+                               if (bytes_to_copy <= bvec->bv_len) {
+                                       memcpy(page_address(bvec->bv_page) +
+                                           bvec->bv_offset, pci_addr_in +
+                                           offset, bytes_to_copy);
+                                       break;
+                               } else {
+                                       memcpy(page_address(bvec->bv_page) +
+                                           bvec->bv_offset, pci_addr_in +
+                                           offset, bvec->bv_len);
+                                       bytes_to_copy -= bvec->bv_len;
+                               }
+                               offset += bvec->bv_len;
+                       }
+               }
+       } else {
+               dtransportprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s - no reply\n", ioc->name, __func__));
+               rc = -ENXIO;
+       }
+
+ issue_host_reset:
+       if (issue_reset) {
+               mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                   FORCE_BIG_HAMMER);
+               rc = -ETIMEDOUT;
+       }
+
+ unmap:
+       if (dma_addr_out)
+               pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
+                   PCI_DMA_BIDIRECTIONAL);
+       if (dma_addr_in)
+               pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
+                   PCI_DMA_BIDIRECTIONAL);
+
+ free_pci:
+       if (pci_addr_out)
+               pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
+                   pci_dma_out);
+
+       if (pci_addr_in)
+               pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
+                   pci_dma_in);
+
+ out:
+       ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
+       mutex_unlock(&ioc->transport_cmds.mutex);
+       return rc;
+}
+
+struct sas_function_template mpt3sas_transport_functions = {
+       .get_linkerrors         = _transport_get_linkerrors,
+       .get_enclosure_identifier = _transport_get_enclosure_identifier,
+       .get_bay_identifier     = _transport_get_bay_identifier,
+       .phy_reset              = _transport_phy_reset,
+       .phy_enable             = _transport_phy_enable,
+       .set_phy_speed          = _transport_phy_speed,
+       .smp_handler            = _transport_smp_handler,
+};
+
+struct scsi_transport_template *mpt3sas_transport_template;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
new file mode 100644 (file)
index 0000000..da6c5f2
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * This module provides common API to set Diagnostic trigger for MPT
+ * (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/compat.h>
+#include <linux/poll.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include "mpt3sas_base.h"
+
+/**
+ * _mpt3sas_raise_sigio - notifiy app
+ * @ioc: per adapter object
+ * @event_data:
+ */
+static void
+_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc,
+       struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
+{
+       Mpi2EventNotificationReply_t *mpi_reply;
+       u16 sz, event_data_sz;
+       unsigned long flags;
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n",
+           ioc->name, __func__));
+
+       sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
+           sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4;
+       mpi_reply = kzalloc(sz, GFP_KERNEL);
+       if (!mpi_reply)
+               goto out;
+       mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED);
+       event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4;
+       mpi_reply->EventDataLength = cpu_to_le16(event_data_sz);
+       memcpy(&mpi_reply->EventData, event_data,
+           sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: add to driver event log\n",
+               ioc->name, __func__));
+       mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
+       kfree(mpi_reply);
+ out:
+
+       /* clearing the diag_trigger_active flag */
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: clearing diag_trigger_active flag\n",
+               ioc->name, __func__));
+       ioc->diag_trigger_active = 0;
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+}
+
+/**
+ * mpt3sas_process_trigger_data - process the event data for the trigger
+ * @ioc: per adapter object
+ * @event_data:
+ */
+void
+mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
+       struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
+{
+       u8 issue_reset = 0;
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n",
+           ioc->name, __func__));
+
+       /* release the diag buffer trace */
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
+               dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: release trace diag buffer\n", ioc->name, __func__));
+               mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
+                   &issue_reset);
+       }
+
+       _mpt3sas_raise_sigio(ioc, event_data);
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+}
+
+/**
+ * mpt3sas_trigger_master - Master trigger handler
+ * @ioc: per adapter object
+ * @trigger_bitmask:
+ *
+ */
+void
+mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask)
+{
+       struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
+       unsigned long flags;
+       u8 found_match = 0;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+
+       if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
+           trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
+               goto by_pass_checks;
+
+       /* check to see if trace buffers are currently registered */
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       /* check to see if trace buffers are currently released */
+       if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+ by_pass_checks:
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: enter - trigger_bitmask = 0x%08x\n",
+               ioc->name, __func__, trigger_bitmask));
+
+       /* don't send trigger if an trigger is currently active */
+       if (ioc->diag_trigger_active) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               goto out;
+       }
+
+       /* check for the trigger condition */
+       if (ioc->diag_trigger_master.MasterData & trigger_bitmask) {
+               found_match = 1;
+               ioc->diag_trigger_active = 1;
+               dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: setting diag_trigger_active flag\n",
+               ioc->name, __func__));
+       }
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+
+       if (!found_match)
+               goto out;
+
+       memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
+       event_data.trigger_type = MPT3SAS_TRIGGER_MASTER;
+       event_data.u.master.MasterData = trigger_bitmask;
+
+       if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
+           trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
+               _mpt3sas_raise_sigio(ioc, &event_data);
+       else
+               mpt3sas_send_trigger_data_event(ioc, &event_data);
+
+ out:
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+}
+
+/**
+ * mpt3sas_trigger_event - Event trigger handler
+ * @ioc: per adapter object
+ * @event:
+ * @log_entry_qualifier:
+ *
+ */
+void
+mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
+       u16 log_entry_qualifier)
+{
+       struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
+       struct SL_WH_EVENT_TRIGGER_T *event_trigger;
+       int i;
+       unsigned long flags;
+       u8 found_match;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+
+       /* check to see if trace buffers are currently registered */
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       /* check to see if trace buffers are currently released */
+       if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n",
+               ioc->name, __func__, event, log_entry_qualifier));
+
+       /* don't send trigger if an trigger is currently active */
+       if (ioc->diag_trigger_active) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               goto out;
+       }
+
+       /* check for the trigger condition */
+       event_trigger = ioc->diag_trigger_event.EventTriggerEntry;
+       for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries
+           && !found_match; i++, event_trigger++) {
+               if (event_trigger->EventValue != event)
+                       continue;
+               if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
+                       if (event_trigger->LogEntryQualifier ==
+                           log_entry_qualifier)
+                               found_match = 1;
+                       continue;
+               }
+               found_match = 1;
+               ioc->diag_trigger_active = 1;
+               dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+                       "%s: setting diag_trigger_active flag\n",
+                       ioc->name, __func__));
+       }
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+
+       if (!found_match)
+               goto out;
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: setting diag_trigger_active flag\n",
+               ioc->name, __func__));
+       memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
+       event_data.trigger_type = MPT3SAS_TRIGGER_EVENT;
+       event_data.u.event.EventValue = event;
+       event_data.u.event.LogEntryQualifier = log_entry_qualifier;
+       mpt3sas_send_trigger_data_event(ioc, &event_data);
+ out:
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+}
+
+/**
+ * mpt3sas_trigger_scsi - SCSI trigger handler
+ * @ioc: per adapter object
+ * @sense_key:
+ * @asc:
+ * @ascq:
+ *
+ */
+void
+mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc,
+       u8 ascq)
+{
+       struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
+       struct SL_WH_SCSI_TRIGGER_T *scsi_trigger;
+       int i;
+       unsigned long flags;
+       u8 found_match;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+
+       /* check to see if trace buffers are currently registered */
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       /* check to see if trace buffers are currently released */
+       if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n",
+               ioc->name, __func__, sense_key, asc, ascq));
+
+       /* don't send trigger if an trigger is currently active */
+       if (ioc->diag_trigger_active) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               goto out;
+       }
+
+       /* check for the trigger condition */
+       scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry;
+       for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries
+           && !found_match; i++, scsi_trigger++) {
+               if (scsi_trigger->SenseKey != sense_key)
+                       continue;
+               if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc))
+                       continue;
+               if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq))
+                       continue;
+               found_match = 1;
+               ioc->diag_trigger_active = 1;
+       }
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+
+       if (!found_match)
+               goto out;
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: setting diag_trigger_active flag\n",
+               ioc->name, __func__));
+       memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
+       event_data.trigger_type = MPT3SAS_TRIGGER_SCSI;
+       event_data.u.scsi.SenseKey = sense_key;
+       event_data.u.scsi.ASC = asc;
+       event_data.u.scsi.ASCQ = ascq;
+       mpt3sas_send_trigger_data_event(ioc, &event_data);
+ out:
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+}
+
+/**
+ * mpt3sas_trigger_mpi - MPI trigger handler
+ * @ioc: per adapter object
+ * @ioc_status:
+ * @loginfo:
+ *
+ */
+void
+mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo)
+{
+       struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
+       struct SL_WH_MPI_TRIGGER_T *mpi_trigger;
+       int i;
+       unsigned long flags;
+       u8 found_match;
+
+       spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
+
+       /* check to see if trace buffers are currently registered */
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       /* check to see if trace buffers are currently released */
+       if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT3_DIAG_BUFFER_IS_RELEASED) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               return;
+       }
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n",
+               ioc->name, __func__, ioc_status, loginfo));
+
+       /* don't send trigger if an trigger is currently active */
+       if (ioc->diag_trigger_active) {
+               spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+               goto out;
+       }
+
+       /* check for the trigger condition */
+       mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry;
+       for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries
+           && !found_match; i++, mpi_trigger++) {
+               if (mpi_trigger->IOCStatus != ioc_status)
+                       continue;
+               if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF ||
+                   mpi_trigger->IocLogInfo == loginfo))
+                       continue;
+               found_match = 1;
+               ioc->diag_trigger_active = 1;
+       }
+       spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
+
+       if (!found_match)
+               goto out;
+
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
+               "%s: setting diag_trigger_active flag\n",
+               ioc->name, __func__));
+       memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
+       event_data.trigger_type = MPT3SAS_TRIGGER_MPI;
+       event_data.u.mpi.IOCStatus = ioc_status;
+       event_data.u.mpi.IocLogInfo = loginfo;
+       mpt3sas_send_trigger_data_event(ioc, &event_data);
+ out:
+       dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
+           __func__));
+}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
new file mode 100644 (file)
index 0000000..a10c309
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * This is the Fusion MPT base driver providing common API layer interface
+ * to set Diagnostic triggers for MPT (Message Passing Technology) based
+ * controllers
+ *
+ * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
+ * Copyright (C) 2012  LSI Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * 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.
+ */
+  /* Diagnostic Trigger Configuration Data Structures */
+
+#ifndef MPT3SAS_TRIGGER_DIAG_H_INCLUDED
+#define MPT3SAS_TRIGGER_DIAG_H_INCLUDED
+
+/* limitation on number of entries */
+#define NUM_VALID_ENTRIES               (20)
+
+/* trigger types */
+#define MPT3SAS_TRIGGER_MASTER          (1)
+#define MPT3SAS_TRIGGER_EVENT           (2)
+#define MPT3SAS_TRIGGER_SCSI            (3)
+#define MPT3SAS_TRIGGER_MPI             (4)
+
+/* trigger names */
+#define MASTER_TRIGGER_FILE_NAME        "diag_trigger_master"
+#define EVENT_TRIGGERS_FILE_NAME        "diag_trigger_event"
+#define SCSI_TRIGGERS_FILE_NAME         "diag_trigger_scsi"
+#define MPI_TRIGGER_FILE_NAME           "diag_trigger_mpi"
+
+/* master trigger bitmask */
+#define MASTER_TRIGGER_FW_FAULT         (0x00000001)
+#define MASTER_TRIGGER_ADAPTER_RESET    (0x00000002)
+#define MASTER_TRIGGER_TASK_MANAGMENT   (0x00000004)
+#define MASTER_TRIGGER_DEVICE_REMOVAL   (0x00000008)
+
+/* fake firmware event for tigger */
+#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED    (0x6E)
+
+/**
+ * MasterTrigger is a single U32 passed to/from sysfs.
+ *
+ * Bit Flags (enables) include:
+ * 1. FW Faults
+ * 2. Adapter Reset issued by driver
+ * 3. TMs
+ * 4. Device Remove Event sent by FW
+ */
+
+struct SL_WH_MASTER_TRIGGER_T {
+       uint32_t MasterData;
+};
+
+/**
+ * struct SL_WH_EVENT_TRIGGER_T -  Definition of an event trigger element
+ * @EventValue: Event Code to trigger on
+ * @LogEntryQualifier: Type of FW event that logged (Log Entry Added Event only)
+ *
+ * Defines an event that should induce a DIAG_TRIGGER driver event if observed.
+ */
+struct SL_WH_EVENT_TRIGGER_T {
+       uint16_t EventValue;
+       uint16_t LogEntryQualifier;
+};
+
+/**
+ * struct SL_WH_EVENT_TRIGGERS_T -  Structure passed to/from sysfs containing a
+ *    list of Event Triggers to be monitored for.
+ * @ValidEntries: Number of _SL_WH_EVENT_TRIGGER_T structures contained in this
+ *    structure.
+ * @EventTriggerEntry: List of Event trigger elements.
+ *
+ * This binary structure is transferred via sysfs to get/set Event Triggers
+ * in the Linux Driver.
+ */
+
+struct SL_WH_EVENT_TRIGGERS_T {
+       uint32_t ValidEntries;
+       struct SL_WH_EVENT_TRIGGER_T EventTriggerEntry[NUM_VALID_ENTRIES];
+};
+
+/**
+ * struct SL_WH_SCSI_TRIGGER_T -  Definition of a SCSI trigger element
+ * @ASCQ: Additional Sense Code Qualifier.  Can be specific or 0xFF for
+ *     wildcard.
+ * @ASC: Additional Sense Code.  Can be specific or 0xFF for wildcard
+ * @SenseKey: SCSI Sense Key
+ *
+ * Defines a sense key (single or many variants) that should induce a
+ * DIAG_TRIGGER driver event if observed.
+ */
+struct SL_WH_SCSI_TRIGGER_T {
+       U8 ASCQ;
+       U8 ASC;
+       U8 SenseKey;
+       U8 Reserved;
+};
+
+/**
+ * struct SL_WH_SCSI_TRIGGERS_T -  Structure passed to/from sysfs containing a
+ *    list of SCSI sense codes that should trigger a DIAG_SERVICE event when
+ *    observed.
+ * @ValidEntries: Number of _SL_WH_SCSI_TRIGGER_T structures contained in this
+ *    structure.
+ * @SCSITriggerEntry: List of SCSI Sense Code trigger elements.
+ *
+ * This binary structure is transferred via sysfs to get/set SCSI Sense Code
+ * Triggers in the Linux Driver.
+ */
+struct SL_WH_SCSI_TRIGGERS_T {
+       uint32_t ValidEntries;
+       struct SL_WH_SCSI_TRIGGER_T SCSITriggerEntry[NUM_VALID_ENTRIES];
+};
+
+/**
+ * struct SL_WH_MPI_TRIGGER_T -  Definition of an MPI trigger element
+ * @IOCStatus: MPI IOCStatus
+ * @IocLogInfo: MPI IocLogInfo.  Can be specific or 0xFFFFFFFF for wildcard
+ *
+ * Defines a MPI IOCStatus/IocLogInfo pair that should induce a DIAG_TRIGGER
+ * driver event if observed.
+ */
+struct SL_WH_MPI_TRIGGER_T {
+       uint16_t IOCStatus;
+       uint16_t Reserved;
+       uint32_t IocLogInfo;
+};
+
+/**
+ * struct SL_WH_MPI_TRIGGERS_T -  Structure passed to/from sysfs containing a
+ *    list of MPI IOCStatus/IocLogInfo pairs that should trigger a DIAG_SERVICE
+ *    event when observed.
+ * @ValidEntries: Number of _SL_WH_MPI_TRIGGER_T structures contained in this
+ *    structure.
+ * @MPITriggerEntry: List of MPI IOCStatus/IocLogInfo trigger elements.
+ *
+ * This binary structure is transferred via sysfs to get/set MPI Error Triggers
+ * in the Linux Driver.
+ */
+struct SL_WH_MPI_TRIGGERS_T {
+       uint32_t ValidEntries;
+       struct SL_WH_MPI_TRIGGER_T MPITriggerEntry[NUM_VALID_ENTRIES];
+};
+
+/**
+ * struct SL_WH_TRIGGERS_EVENT_DATA_T -  event data for trigger
+ * @trigger_type: trigger type (see MPT3SAS_TRIGGER_XXXX)
+ * @u: trigger condition that caused trigger to be sent
+ */
+struct SL_WH_TRIGGERS_EVENT_DATA_T {
+       uint32_t trigger_type;
+       union {
+               struct SL_WH_MASTER_TRIGGER_T master;
+               struct SL_WH_EVENT_TRIGGER_T event;
+               struct SL_WH_SCSI_TRIGGER_T scsi;
+               struct SL_WH_MPI_TRIGGER_T mpi;
+       } u;
+};
+#endif /* MPT3SAS_TRIGGER_DIAG_H_INCLUDED */
index 8f7eb4f21140d5955416e4c752b0578cb29adcde..487aa6f974122a801aeb86507813a923be8e3012 100644 (file)
@@ -258,21 +258,11 @@ enum sas_sata_phy_regs {
 #define SPI_ADDR_VLD_94XX              (1U << 1)
 #define SPI_CTRL_SpiStart_94XX         (1U << 0)
 
-#define mv_ffc(x)   ffz(x)
-
 static inline int
 mv_ffc64(u64 v)
 {
-       int i;
-       i = mv_ffc((u32)v);
-       if (i >= 0)
-               return i;
-       i = mv_ffc((u32)(v>>32));
-
-       if (i != 0)
-               return 32 + i;
-
-       return -1;
+       u64 x = ~v;
+       return x ? __ffs64(x) : -1;
 }
 
 #define r_reg_set_enable(i) \
index c04a4f5b5972b2ae405eddf6a3aab5ab82dafe2b..da249553858c4d1240348b6d0387b15d69dc64e8 100644 (file)
@@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_cache;
 #define DEV_IS_EXPANDER(type)  \
        ((type == EDGE_DEV) || (type == FANOUT_DEV))
 
-#define bit(n) ((u32)1 << n)
+#define bit(n) ((u64)1 << n)
 
 #define for_each_phy(__lseq_mask, __mc, __lseq)                        \
        for ((__mc) = (__lseq_mask), (__lseq) = 0;              \
index d4ed9eb526572e07814e167eca89f94d22a3f73a..43754176a7b7efdacaaab1953a3a826ec1cdc53d 100644 (file)
@@ -97,9 +97,37 @@ struct osd_dev_handle {
 
 static DEFINE_IDA(osd_minor_ida);
 
+/*
+ * scsi sysfs attribute operations
+ */
+static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
+                                                  class_dev);
+       return sprintf(buf, "%s\n", ould->odi.osdname);
+}
+
+static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
+                                                  class_dev);
+
+       memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
+       return ould->odi.systemid_len;
+}
+
+static struct device_attribute osd_uld_attrs[] = {
+       __ATTR(osdname, S_IRUGO, osdname_show, NULL),
+       __ATTR(systemid, S_IRUGO, systemid_show, NULL),
+       __ATTR_NULL,
+};
+
 static struct class osd_uld_class = {
        .owner          = THIS_MODULE,
        .name           = "scsi_osd",
+       .dev_attrs      = osd_uld_attrs,
 };
 
 /*
index 1c28215f8bede329f4257838008f0625cd849f2f..83d798428c101c0740d5d864c8fb74ef8a3e21d9 100644 (file)
@@ -1615,8 +1615,7 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
         * At this point all fcport's software-states are cleared.  Perform any
         * final cleanup of firmware resources (PCBs and XCBs).
         */
-       if (fcport->loop_id != FC_NO_LOOP_ID &&
-           !test_bit(UNLOADING, &fcport->vha->dpc_flags)) {
+       if (fcport->loop_id != FC_NO_LOOP_ID) {
                if (IS_FWI2_CAPABLE(fcport->vha->hw))
                        fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
                            fcport->loop_id, fcport->d_id.b.domain,
index 2f9bddd3c616d810303b39dc6f7cb5f22af14828..9f34dedcdad75c77aac2b3bc232d1a354953eb9b 100644 (file)
@@ -219,7 +219,8 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
                break;
        }
 exit_fcp_prio_cfg:
-       bsg_job->job_done(bsg_job);
+       if (!ret)
+               bsg_job->job_done(bsg_job);
        return ret;
 }
 
@@ -741,9 +742,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                        if (qla81xx_get_port_config(vha, config)) {
                                ql_log(ql_log_warn, vha, 0x701f,
                                    "Get port config failed.\n");
-                               bsg_job->reply->result = (DID_ERROR << 16);
                                rval = -EPERM;
-                               goto done_free_dma_req;
+                               goto done_free_dma_rsp;
                        }
 
                        ql_dbg(ql_dbg_user, vha, 0x70c0,
@@ -761,9 +761,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                                    new_config, elreq.options);
 
                        if (rval) {
-                               bsg_job->reply->result = (DID_ERROR << 16);
                                rval = -EPERM;
-                               goto done_free_dma_req;
+                               goto done_free_dma_rsp;
                        }
 
                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
@@ -795,9 +794,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                                            "MPI reset failed.\n");
                                }
 
-                               bsg_job->reply->result = (DID_ERROR << 16);
                                rval = -EIO;
-                               goto done_free_dma_req;
+                               goto done_free_dma_rsp;
                        }
                } else {
                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
@@ -812,34 +810,27 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
                ql_log(ql_log_warn, vha, 0x702c,
                    "Vendor request %s failed.\n", type);
 
-               fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
-                   sizeof(struct fc_bsg_reply);
-
-               memcpy(fw_sts_ptr, response, sizeof(response));
-               fw_sts_ptr += sizeof(response);
-               *fw_sts_ptr = command_sent;
                rval = 0;
                bsg_job->reply->result = (DID_ERROR << 16);
+               bsg_job->reply->reply_payload_rcv_len = 0;
        } else {
                ql_dbg(ql_dbg_user, vha, 0x702d,
                    "Vendor request %s completed.\n", type);
-
-               bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
-                       sizeof(response) + sizeof(uint8_t);
-               bsg_job->reply->reply_payload_rcv_len =
-                       bsg_job->reply_payload.payload_len;
-               fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
-                       sizeof(struct fc_bsg_reply);
-               memcpy(fw_sts_ptr, response, sizeof(response));
-               fw_sts_ptr += sizeof(response);
-               *fw_sts_ptr = command_sent;
-               bsg_job->reply->result = DID_OK;
+               bsg_job->reply->result = (DID_OK << 16);
                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
                        bsg_job->reply_payload.sg_cnt, rsp_data,
                        rsp_data_len);
        }
-       bsg_job->job_done(bsg_job);
 
+       bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
+           sizeof(response) + sizeof(uint8_t);
+       fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
+           sizeof(struct fc_bsg_reply);
+       memcpy(fw_sts_ptr, response, sizeof(response));
+       fw_sts_ptr += sizeof(response);
+       *fw_sts_ptr = command_sent;
+
+done_free_dma_rsp:
        dma_free_coherent(&ha->pdev->dev, rsp_data_len,
                rsp_data, rsp_data_dma);
 done_free_dma_req:
@@ -853,6 +844,8 @@ done_unmap_req_sg:
        dma_unmap_sg(&ha->pdev->dev,
            bsg_job->request_payload.sg_list,
            bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+       if (!rval)
+               bsg_job->job_done(bsg_job);
        return rval;
 }
 
@@ -877,16 +870,15 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
        if (rval) {
                ql_log(ql_log_warn, vha, 0x7030,
                    "Vendor request 84xx reset failed.\n");
-               rval = 0;
-               bsg_job->reply->result = (DID_ERROR << 16);
+               rval = (DID_ERROR << 16);
 
        } else {
                ql_dbg(ql_dbg_user, vha, 0x7031,
                    "Vendor request 84xx reset completed.\n");
                bsg_job->reply->result = DID_OK;
+               bsg_job->job_done(bsg_job);
        }
 
-       bsg_job->job_done(bsg_job);
        return rval;
 }
 
@@ -976,8 +968,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
                ql_log(ql_log_warn, vha, 0x7037,
                    "Vendor request 84xx updatefw failed.\n");
 
-               rval = 0;
-               bsg_job->reply->result = (DID_ERROR << 16);
+               rval = (DID_ERROR << 16);
        } else {
                ql_dbg(ql_dbg_user, vha, 0x7038,
                    "Vendor request 84xx updatefw completed.\n");
@@ -986,7 +977,6 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
                bsg_job->reply->result = DID_OK;
        }
 
-       bsg_job->job_done(bsg_job);
        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
 
 done_free_fw_buf:
@@ -996,6 +986,8 @@ done_unmap_sg:
        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 
+       if (!rval)
+               bsg_job->job_done(bsg_job);
        return rval;
 }
 
@@ -1163,8 +1155,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                ql_log(ql_log_warn, vha, 0x7043,
                    "Vendor request 84xx mgmt failed.\n");
 
-               rval = 0;
-               bsg_job->reply->result = (DID_ERROR << 16);
+               rval = (DID_ERROR << 16);
 
        } else {
                ql_dbg(ql_dbg_user, vha, 0x7044,
@@ -1184,8 +1175,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
                }
        }
 
-       bsg_job->job_done(bsg_job);
-
 done_unmap_sg:
        if (mgmt_b)
                dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
@@ -1200,6 +1189,8 @@ done_unmap_sg:
 exit_mgmt:
        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
 
+       if (!rval)
+               bsg_job->job_done(bsg_job);
        return rval;
 }
 
@@ -1276,9 +1267,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
                    fcport->port_name[3], fcport->port_name[4],
                    fcport->port_name[5], fcport->port_name[6],
                    fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]);
-               rval = 0;
-               bsg_job->reply->result = (DID_ERROR << 16);
-
+               rval = (DID_ERROR << 16);
        } else {
                if (!port_param->mode) {
                        bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
@@ -1292,9 +1281,9 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
                }
 
                bsg_job->reply->result = DID_OK;
+               bsg_job->job_done(bsg_job);
        }
 
-       bsg_job->job_done(bsg_job);
        return rval;
 }
 
@@ -1887,8 +1876,6 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
                return qla24xx_process_bidir_cmd(bsg_job);
 
        default:
-               bsg_job->reply->result = (DID_ERROR << 16);
-               bsg_job->job_done(bsg_job);
                return -ENOSYS;
        }
 }
@@ -1919,8 +1906,6 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
                ql_dbg(ql_dbg_user, vha, 0x709f,
                    "BSG: ISP abort active/needed -- cmd=%d.\n",
                    bsg_job->request->msgcode);
-               bsg_job->reply->result = (DID_ERROR << 16);
-               bsg_job->job_done(bsg_job);
                return -EBUSY;
        }
 
@@ -1943,7 +1928,6 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
        case FC_BSG_RPT_CT:
        default:
                ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
-               bsg_job->reply->result = ret;
                break;
        }
        return ret;
index 44efe3cc79e6b5e90523cac89a718fbd3d946761..53f9e492f9dc842167c60c7d3c033cd0a8386df7 100644 (file)
@@ -11,7 +11,7 @@
  * ----------------------------------------------------------------------
  * |             Level            |   Last Value Used  |     Holes     |
  * ----------------------------------------------------------------------
- * | Module Init and Probe        |       0x0124       | 0x4b,0xba,0xfa |
+ * | Module Init and Probe        |       0x0125       | 0x4b,0xba,0xfa |
  * | Mailbox commands             |       0x114f       | 0x111a-0x111b  |
  * |                              |                    | 0x112c-0x112e  |
  * |                              |                    | 0x113a         |
@@ -526,8 +526,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
                ha->max_req_queues : ha->max_rsp_queues;
        mq->count = htonl(que_cnt);
        for (cnt = 0; cnt < que_cnt; cnt++) {
-               reg = (struct device_reg_25xxmq *) ((void *)
-                       ha->mqiobase + cnt * QLA_QUE_PAGE);
+               reg = (struct device_reg_25xxmq __iomem *)
+                       (ha->mqiobase + cnt * QLA_QUE_PAGE);
                que_idx = cnt * 4;
                mq->qregs[que_idx] = htonl(RD_REG_DWORD(&reg->req_q_in));
                mq->qregs[que_idx+1] = htonl(RD_REG_DWORD(&reg->req_q_out));
@@ -2268,7 +2268,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
 
                if (!cnt) {
                        nxt = fw->code_ram;
-                       nxt += sizeof(fw->code_ram),
+                       nxt += sizeof(fw->code_ram);
                        nxt += (ha->fw_memory_size - 0x100000 + 1);
                        goto copy_queue;
                } else
index a9725bf5527bc139e1f0110e7a2c419626f21f56..6e7727f46d43703ec23e95d88ffa54fede978228 100644 (file)
@@ -2486,9 +2486,9 @@ struct bidi_statistics {
 #define QLA_MAX_QUEUES 256
 #define ISP_QUE_REG(ha, id) \
        ((ha->mqenable || IS_QLA83XX(ha)) ? \
-       ((void *)(ha->mqiobase) +\
+       ((device_reg_t __iomem *)(ha->mqiobase) +\
        (QLA_QUE_PAGE * id)) :\
-       ((void *)(ha->iobase)))
+       ((device_reg_t __iomem *)(ha->iobase)))
 #define QLA_REQ_QUE_ID(tag) \
        ((tag < QLA_MAX_QUEUES && tag > 0) ? tag : 0)
 #define QLA_DEFAULT_QUE_QOS 5
index 59524aa0ab324cf538fa1928d43ecdb843c5c28a..be6d61a89edcb812fa57db086fe26e58e6af10ed 100644 (file)
@@ -1092,6 +1092,27 @@ struct device_reg_24xx {
        uint32_t unused_6[2];           /* Gap. */
        uint32_t iobase_sdata;
 };
+/* RISC-RISC semaphore register PCI offet */
+#define RISC_REGISTER_BASE_OFFSET      0x7010
+#define RISC_REGISTER_WINDOW_OFFET     0x6
+
+/* RISC-RISC semaphore/flag register (risc address 0x7016) */
+
+#define RISC_SEMAPHORE         0x1UL
+#define RISC_SEMAPHORE_WE      (RISC_SEMAPHORE << 16)
+#define RISC_SEMAPHORE_CLR     (RISC_SEMAPHORE_WE | 0x0UL)
+#define RISC_SEMAPHORE_SET     (RISC_SEMAPHORE_WE | RISC_SEMAPHORE)
+
+#define RISC_SEMAPHORE_FORCE           0x8000UL
+#define RISC_SEMAPHORE_FORCE_WE                (RISC_SEMAPHORE_FORCE << 16)
+#define RISC_SEMAPHORE_FORCE_CLR       (RISC_SEMAPHORE_FORCE_WE | 0x0UL)
+#define RISC_SEMAPHORE_FORCE_SET       \
+               (RISC_SEMAPHORE_FORCE_WE | RISC_SEMAPHORE_FORCE)
+
+/* RISC semaphore timeouts (ms) */
+#define TIMEOUT_SEMAPHORE              2500
+#define TIMEOUT_SEMAPHORE_FORCE                2000
+#define TIMEOUT_TOTAL_ELAPSED          4500
 
 /* Trace Control *************************************************************/
 
index 6acb39785a46a2992fa0ec6e761dff79c56d0f93..2411d1a12b26d5b86640ca55c7967357bb699807 100644 (file)
@@ -416,7 +416,7 @@ extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *);
 extern void qla2x00_free_irqs(scsi_qla_host_t *);
 
 extern int qla2x00_get_data_rate(scsi_qla_host_t *);
-extern char *qla2x00_get_link_speed_str(struct qla_hw_data *);
+extern const char *qla2x00_get_link_speed_str(struct qla_hw_data *, uint16_t);
 
 /*
  * Global Function Prototypes in qla_sup.c source file.
@@ -598,7 +598,6 @@ extern void qla82xx_init_flags(struct qla_hw_data *);
 
 /* ISP 8021 hardware related */
 extern void qla82xx_set_drv_active(scsi_qla_host_t *);
-extern void qla82xx_crb_win_unlock(struct qla_hw_data *);
 extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32);
 extern int qla82xx_rd_32(struct qla_hw_data *, ulong);
 extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int);
index f4e4bd7c3f4d66b8ea06bb415315e5e737cb45df..01efc0e9cc36262a7371e53b184b1f4b0aa7fad0 100644 (file)
@@ -218,6 +218,9 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
                memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
                    WWN_SIZE);
 
+               fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
+                   FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
+
                if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
                    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
                        fcport->d_id.b.domain = 0xf0;
@@ -1930,6 +1933,9 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
                        case BIT_11:
                                list[i].fp_speed = PORT_SPEED_8GB;
                                break;
+                       case BIT_10:
+                               list[i].fp_speed = PORT_SPEED_16GB;
+                               break;
                        }
 
                        ql_dbg(ql_dbg_disc, vha, 0x205b,
index 48fca47384b745894e0a8a853c8fc937daa196df..563eee3fa9243dc3cc411f65f8895d805565a36a 100644 (file)
@@ -429,7 +429,7 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 /*                QLogic ISP2x00 Hardware Support Functions.                */
 /****************************************************************************/
 
-int
+static int
 qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
 {
        int rval = QLA_SUCCESS;
@@ -997,7 +997,7 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
  *
  * Returns 0 on success.
  */
-int
+static int
 qla81xx_reset_mpi(scsi_qla_host_t *vha)
 {
        uint16_t mb[4] = {0x1010, 0, 1, 0};
@@ -1095,6 +1095,83 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
                ha->isp_ops->enable_intrs(ha);
 }
 
+static void
+qla25xx_read_risc_sema_reg(scsi_qla_host_t *vha, uint32_t *data)
+{
+       struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
+
+       WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
+       *data = RD_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET);
+
+}
+
+static void
+qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data)
+{
+       struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
+
+       WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
+       WRT_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
+}
+
+static void
+qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha)
+{
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t wd32 = 0;
+       uint delta_msec = 100;
+       uint elapsed_msec = 0;
+       uint timeout_msec;
+       ulong n;
+
+       if (!IS_QLA25XX(ha) && !IS_QLA2031(ha))
+               return;
+
+attempt:
+       timeout_msec = TIMEOUT_SEMAPHORE;
+       n = timeout_msec / delta_msec;
+       while (n--) {
+               qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_SET);
+               qla25xx_read_risc_sema_reg(vha, &wd32);
+               if (wd32 & RISC_SEMAPHORE)
+                       break;
+               msleep(delta_msec);
+               elapsed_msec += delta_msec;
+               if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
+                       goto force;
+       }
+
+       if (!(wd32 & RISC_SEMAPHORE))
+               goto force;
+
+       if (!(wd32 & RISC_SEMAPHORE_FORCE))
+               goto acquired;
+
+       qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_CLR);
+       timeout_msec = TIMEOUT_SEMAPHORE_FORCE;
+       n = timeout_msec / delta_msec;
+       while (n--) {
+               qla25xx_read_risc_sema_reg(vha, &wd32);
+               if (!(wd32 & RISC_SEMAPHORE_FORCE))
+                       break;
+               msleep(delta_msec);
+               elapsed_msec += delta_msec;
+               if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
+                       goto force;
+       }
+
+       if (wd32 & RISC_SEMAPHORE_FORCE)
+               qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_CLR);
+
+       goto attempt;
+
+force:
+       qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_SET);
+
+acquired:
+       return;
+}
+
 /**
  * qla24xx_reset_chip() - Reset ISP24xx chip.
  * @ha: HA context
@@ -1113,6 +1190,8 @@ qla24xx_reset_chip(scsi_qla_host_t *vha)
 
        ha->isp_ops->disable_intrs(ha);
 
+       qla25xx_manipulate_risc_semaphore(vha);
+
        /* Perform RISC reset. */
        qla24xx_reset_risc(vha);
 }
@@ -1888,10 +1967,6 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
                qla2x00_init_response_q_entries(rsp);
        }
 
-       spin_lock(&ha->vport_slock);
-
-       spin_unlock(&ha->vport_slock);
-
        ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
        ha->tgt.atio_ring_index = 0;
        /* Initialize ATIO queue entries */
@@ -1971,6 +2046,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
                    "Waiting for LIP to complete.\n");
 
        do {
+               memset(state, -1, sizeof(state));
                rval = qla2x00_get_firmware_state(vha, state);
                if (rval == QLA_SUCCESS) {
                        if (state[0] < FSTATE_LOSS_OF_SYNC) {
@@ -2907,7 +2983,6 @@ cleanup_allocation:
 static void
 qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
 {
-       char *link_speed;
        int rval;
        uint16_t mb[4];
        struct qla_hw_data *ha = vha->hw;
@@ -2934,10 +3009,10 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
                    fcport->port_name[6], fcport->port_name[7], rval,
                    fcport->fp_speed, mb[0], mb[1]);
        } else {
-               link_speed = qla2x00_get_link_speed_str(ha);
                ql_dbg(ql_dbg_disc, vha, 0x2005,
                    "iIDMA adjusted to %s GB/s "
-                   "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed,
+                   "on %02x%02x%02x%02x%02x%02x%02x%02x.\n",
+                   qla2x00_get_link_speed_str(ha, fcport->fp_speed),
                    fcport->port_name[0], fcport->port_name[1],
                    fcport->port_name[2], fcport->port_name[3],
                    fcport->port_name[4], fcport->port_name[5],
@@ -3007,10 +3082,10 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
        fcport->login_retry = 0;
        fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
 
+       qla2x00_set_fcport_state(fcport, FCS_ONLINE);
        qla2x00_iidma_fcport(vha, fcport);
        qla24xx_update_fcport_fcp_prio(vha, fcport);
        qla2x00_reg_remote_port(vha, fcport);
-       qla2x00_set_fcport_state(fcport, FCS_ONLINE);
 }
 
 /*
@@ -3868,7 +3943,7 @@ qla83xx_reset_ownership(scsi_qla_host_t *vha)
        }
 }
 
-int
+static int
 __qla83xx_set_drv_ack(scsi_qla_host_t *vha)
 {
        int rval = QLA_SUCCESS;
@@ -3884,19 +3959,7 @@ __qla83xx_set_drv_ack(scsi_qla_host_t *vha)
        return rval;
 }
 
-int
-qla83xx_set_drv_ack(scsi_qla_host_t *vha)
-{
-       int rval = QLA_SUCCESS;
-
-       qla83xx_idc_lock(vha, 0);
-       rval = __qla83xx_set_drv_ack(vha);
-       qla83xx_idc_unlock(vha, 0);
-
-       return rval;
-}
-
-int
+static int
 __qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
 {
        int rval = QLA_SUCCESS;
@@ -3912,19 +3975,7 @@ __qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
        return rval;
 }
 
-int
-qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
-{
-       int rval = QLA_SUCCESS;
-
-       qla83xx_idc_lock(vha, 0);
-       rval = __qla83xx_clear_drv_ack(vha);
-       qla83xx_idc_unlock(vha, 0);
-
-       return rval;
-}
-
-const char *
+static const char *
 qla83xx_dev_state_to_string(uint32_t dev_state)
 {
        switch (dev_state) {
@@ -3978,7 +4029,7 @@ qla83xx_idc_audit(scsi_qla_host_t *vha, int audit_type)
 }
 
 /* Assumes idc_lock always held on entry */
-int
+static int
 qla83xx_initiating_reset(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
@@ -4025,37 +4076,13 @@ __qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
        return qla83xx_wr_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
 }
 
-int
-qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
-{
-       int rval = QLA_SUCCESS;
-
-       qla83xx_idc_lock(vha, 0);
-       rval = __qla83xx_set_idc_control(vha, idc_control);
-       qla83xx_idc_unlock(vha, 0);
-
-       return rval;
-}
-
 int
 __qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
 {
        return qla83xx_rd_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
 }
 
-int
-qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
-{
-       int rval = QLA_SUCCESS;
-
-       qla83xx_idc_lock(vha, 0);
-       rval = __qla83xx_get_idc_control(vha, idc_control);
-       qla83xx_idc_unlock(vha, 0);
-
-       return rval;
-}
-
-int
+static int
 qla83xx_check_driver_presence(scsi_qla_host_t *vha)
 {
        uint32_t drv_presence = 0;
index 03b75263283995894a023e11c458aa21e228d105..a481684479c125f9ceb8cba9bc576f00db6a3ed6 100644 (file)
@@ -520,7 +520,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
 
        mrk24 = NULL;
        req = ha->req_q_map[0];
-       mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, 0);
+       mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, NULL);
        if (mrk == NULL) {
                ql_log(ql_log_warn, base_vha, 0x3026,
                    "Failed to allocate Marker IOCB.\n");
@@ -2551,7 +2551,7 @@ sufficient_dsds:
                        (unsigned long __iomem *)ha->nxdb_wr_ptr,
                        dbval);
                wmb();
-               while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) {
+               while (RD_REG_DWORD((void __iomem *)ha->nxdb_rd_ptr) != dbval) {
                        WRT_REG_DWORD(
                                (unsigned long __iomem *)ha->nxdb_wr_ptr,
                                dbval);
@@ -2748,7 +2748,6 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
        struct rsp_que *rsp;
        struct req_que *req;
        int rval = EXT_STATUS_OK;
-       device_reg_t __iomem *reg = ISP_QUE_REG(ha, vha->req->id);
 
        rval = QLA_SUCCESS;
 
@@ -2786,15 +2785,7 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
 
        /* Check for room on request queue. */
        if (req->cnt < req_cnt + 2) {
-               if (ha->mqenable)
-                       cnt = RD_REG_DWORD(&reg->isp25mq.req_q_out);
-               else if (IS_QLA82XX(ha))
-                       cnt = RD_REG_DWORD(&reg->isp82.req_q_out);
-               else if (IS_FWI2_CAPABLE(ha))
-                       cnt = RD_REG_DWORD(&reg->isp24.req_q_out);
-               else
-                       cnt = qla2x00_debounce_register(
-                                       ISP_REQ_Q_OUT(ha, &reg->isp));
+               cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
 
                if  (req->ring_index < cnt)
                        req->cnt = cnt - req->ring_index;
index 5733811ce8e79eb0bce599550604fe6290444f5f..873c82014b16067ef6479b3fb306c0e5be5a427f 100644 (file)
@@ -251,7 +251,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
        /* Read all mbox registers? */
        mboxes = (1 << ha->mbx_count) - 1;
        if (!ha->mcp)
-               ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERRROR.\n");
+               ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
        else
                mboxes = ha->mcp->in_mb;
 
@@ -316,28 +316,24 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
 }
 
 #define LS_UNKNOWN     2
-char *
-qla2x00_get_link_speed_str(struct qla_hw_data *ha)
+const char *
+qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed)
 {
-       static char *link_speeds[] = {"1", "2", "?", "4", "8", "16", "10"};
-       char *link_speed;
-       int fw_speed = ha->link_data_rate;
+       static const char * const link_speeds[] = {
+               "1", "2", "?", "4", "8", "16", "10"
+       };
 
        if (IS_QLA2100(ha) || IS_QLA2200(ha))
-               link_speed = link_speeds[0];
-       else if (fw_speed == 0x13)
-               link_speed = link_speeds[6];
-       else {
-               link_speed = link_speeds[LS_UNKNOWN];
-               if (fw_speed < 6)
-                       link_speed =
-                           link_speeds[fw_speed];
-       }
-
-       return link_speed;
+               return link_speeds[0];
+       else if (speed == 0x13)
+               return link_speeds[6];
+       else if (speed < 6)
+               return link_speeds[speed];
+       else
+               return link_speeds[LS_UNKNOWN];
 }
 
-void
+static void
 qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
 {
        struct qla_hw_data *ha = vha->hw;
@@ -671,7 +667,7 @@ skip_rio:
 
                ql_dbg(ql_dbg_async, vha, 0x500a,
                    "LOOP UP detected (%s Gbps).\n",
-                   qla2x00_get_link_speed_str(ha));
+                   qla2x00_get_link_speed_str(ha, ha->link_data_rate));
 
                vha->flags.management_server_logged_in = 0;
                qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
@@ -860,7 +856,7 @@ skip_rio:
                    mb[1], mb[2], mb[3]);
                ql_log(ql_log_warn, vha, 0x505f,
                    "Link is operational (%s Gbps).\n",
-                   qla2x00_get_link_speed_str(ha));
+                   qla2x00_get_link_speed_str(ha, ha->link_data_rate));
 
                /*
                 * Mark all devices as missing so we will login again.
@@ -2318,7 +2314,7 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
        /* Read all mbox registers? */
        mboxes = (1 << ha->mbx_count) - 1;
        if (!ha->mcp)
-               ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERRROR.\n");
+               ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
        else
                mboxes = ha->mcp->in_mb;
 
@@ -2944,7 +2940,9 @@ skip_msi:
                    "Failed to reserve interrupt %d already in use.\n",
                    ha->pdev->irq);
                goto fail;
-       }
+       } else if (!ha->flags.msi_enabled)
+               ql_dbg(ql_dbg_init, vha, 0x0125,
+                   "INTa mode: Enabled.\n");
 
 clear_risc_ints:
 
index 18c509fae555a2c7331a87b817eab581ebc03d2c..68c55eaa318c59f4b1b99bb15cfe956df7e4bebc 100644 (file)
@@ -3122,7 +3122,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                if (vp_idx == 0 && (MSB(stat) != 1))
                        goto reg_needed;
 
-               if (MSB(stat) != 0) {
+               if (MSB(stat) != 0 && MSB(stat) != 2) {
                        ql_dbg(ql_dbg_mbx, vha, 0x10ba,
                            "Could not acquire ID for VP[%d].\n", vp_idx);
                        return;
@@ -3536,7 +3536,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
        if (IS_QLA83XX(ha))
                mcp->mb[15] = 0;
 
-       reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) +
+       reg = (struct device_reg_25xxmq __iomem *)((ha->mqiobase) +
                QLA_QUE_PAGE * req->id);
 
        mcp->mb[4] = req->id;
@@ -3605,7 +3605,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
        if (IS_QLA83XX(ha))
                mcp->mb[15] = 0;
 
-       reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) +
+       reg = (struct device_reg_25xxmq __iomem *)((ha->mqiobase) +
                QLA_QUE_PAGE * rsp->id);
 
        mcp->mb[4] = rsp->id;
index 14cd361742fa668259b1df795bec4616e7bd68d4..3e3f593bada371be774d4d5ae2f6effb8e93a9cc 100644 (file)
@@ -36,7 +36,7 @@
 
 #define MAX_CRB_XFORM 60
 static unsigned long crb_addr_xform[MAX_CRB_XFORM];
-int qla82xx_crb_table_initialized;
+static int qla82xx_crb_table_initialized;
 
 #define qla82xx_crb_addr_transform(name) \
        (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \
@@ -102,7 +102,7 @@ static void qla82xx_crb_addr_transform_setup(void)
        qla82xx_crb_table_initialized = 1;
 }
 
-struct crb_128M_2M_block_map crb_128M_2M_map[64] = {
+static struct crb_128M_2M_block_map crb_128M_2M_map[64] = {
        {{{0, 0,         0,         0} } },
        {{{1, 0x0100000, 0x0102000, 0x120000},
        {1, 0x0110000, 0x0120000, 0x130000},
@@ -262,7 +262,7 @@ struct crb_128M_2M_block_map crb_128M_2M_map[64] = {
 /*
  * top 12 bits of crb internal address (hub, agent)
  */
-unsigned qla82xx_crb_hub_agt[64] = {
+static unsigned qla82xx_crb_hub_agt[64] = {
        0,
        QLA82XX_HW_CRB_HUB_AGT_ADR_PS,
        QLA82XX_HW_CRB_HUB_AGT_ADR_MN,
@@ -330,7 +330,7 @@ unsigned qla82xx_crb_hub_agt[64] = {
 };
 
 /* Device states */
-char *q_dev_state[] = {
+static char *q_dev_state[] = {
         "Unknown",
        "Cold",
        "Initializing",
@@ -359,12 +359,13 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
 
        ha->crb_win = CRB_HI(*off);
        writel(ha->crb_win,
-               (void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+               (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
 
        /* Read back value to make sure write has gone through before trying
         * to use it.
         */
-       win_read = RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+       win_read = RD_REG_DWORD((void __iomem *)
+           (CRB_WINDOW_2M + ha->nx_pcibase));
        if (win_read != ha->crb_win) {
                ql_dbg(ql_dbg_p3p, vha, 0xb000,
                    "%s: Written crbwin (0x%x) "
@@ -567,7 +568,7 @@ qla82xx_pci_mem_bound_check(struct qla_hw_data *ha,
                return 1;
 }
 
-int qla82xx_pci_set_window_warning_count;
+static int qla82xx_pci_set_window_warning_count;
 
 static unsigned long
 qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
@@ -677,10 +678,10 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
        u64 off, void *data, int size)
 {
        unsigned long   flags;
-       void           *addr = NULL;
+       void __iomem *addr = NULL;
        int             ret = 0;
        u64             start;
-       uint8_t         *mem_ptr = NULL;
+       uint8_t __iomem  *mem_ptr = NULL;
        unsigned long   mem_base;
        unsigned long   mem_page;
        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
@@ -712,7 +713,7 @@ static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha,
                mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
        else
                mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
-       if (mem_ptr == 0UL) {
+       if (mem_ptr == NULL) {
                *(u8  *)data = 0;
                return -1;
        }
@@ -749,10 +750,10 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
        u64 off, void *data, int size)
 {
        unsigned long   flags;
-       void           *addr = NULL;
+       void  __iomem *addr = NULL;
        int             ret = 0;
        u64             start;
-       uint8_t         *mem_ptr = NULL;
+       uint8_t __iomem *mem_ptr = NULL;
        unsigned long   mem_base;
        unsigned long   mem_page;
        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
@@ -784,7 +785,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
                mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
        else
                mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
-       if (mem_ptr == 0UL)
+       if (mem_ptr == NULL)
                return -1;
 
        addr = mem_ptr;
@@ -908,24 +909,24 @@ qla82xx_wait_rom_done(struct qla_hw_data *ha)
        return 0;
 }
 
-int
+static int
 qla82xx_md_rw_32(struct qla_hw_data *ha, uint32_t off, u32 data, uint8_t flag)
 {
        uint32_t  off_value, rval = 0;
 
-       WRT_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase),
+       WRT_REG_DWORD((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase),
            (off & 0xFFFF0000));
 
        /* Read back value to make sure write has gone through */
-       RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+       RD_REG_DWORD((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
        off_value  = (off & 0x0000FFFF);
 
        if (flag)
-               WRT_REG_DWORD((void *)
+               WRT_REG_DWORD((void __iomem *)
                    (off_value + CRB_INDIRECT_2M + ha->nx_pcibase),
                    data);
        else
-               rval = RD_REG_DWORD((void *)
+               rval = RD_REG_DWORD((void __iomem *)
                    (off_value + CRB_INDIRECT_2M + ha->nx_pcibase));
 
        return rval;
@@ -955,7 +956,7 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
        }
        if (loops >= 50000) {
                ql_log(ql_log_fatal, vha, 0x00b9,
-                   "Failed to aquire SEM2 lock.\n");
+                   "Failed to acquire SEM2 lock.\n");
                return -1;
        }
        ret = qla82xx_do_rom_fast_read(ha, addr, valp);
@@ -1122,7 +1123,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
                long data;
        };
 
-       /* Halt all the indiviual PEGs and other blocks of the ISP */
+       /* Halt all the individual PEGs and other blocks of the ISP */
        qla82xx_rom_lock(ha);
 
        /* disable all I2Q */
@@ -1654,7 +1655,6 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
        if (!ha->nx_pcibase) {
                ql_log_pci(ql_log_fatal, ha->pdev, 0x000e,
                    "Cannot remap pcibase MMIO, aborting.\n");
-               pci_release_regions(ha->pdev);
                goto iospace_error_exit;
        }
 
@@ -1669,7 +1669,6 @@ qla82xx_iospace_config(struct qla_hw_data *ha)
                if (!ha->nxdb_wr_ptr) {
                        ql_log_pci(ql_log_fatal, ha->pdev, 0x000f,
                            "Cannot remap MMIO, aborting.\n");
-                       pci_release_regions(ha->pdev);
                        goto iospace_error_exit;
                }
 
@@ -1764,14 +1763,6 @@ void qla82xx_config_rings(struct scsi_qla_host *vha)
        WRT_REG_DWORD((unsigned long  __iomem *)&reg->rsp_q_out[0], 0);
 }
 
-void qla82xx_reset_adapter(struct scsi_qla_host *vha)
-{
-       struct qla_hw_data *ha = vha->hw;
-       vha->flags.online = 0;
-       qla2x00_try_to_stop_firmware(vha);
-       ha->isp_ops->disable_intrs(ha);
-}
-
 static int
 qla82xx_fw_load_from_blob(struct qla_hw_data *ha)
 {
@@ -1856,7 +1847,7 @@ qla82xx_set_product_offset(struct qla_hw_data *ha)
        return -1;
 }
 
-int
+static int
 qla82xx_validate_firmware_blob(scsi_qla_host_t *vha, uint8_t fw_type)
 {
        __le32 val;
@@ -1961,20 +1952,6 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
 }
 
 /* ISR related functions */
-uint32_t qla82xx_isr_int_target_mask_enable[8] = {
-       ISR_INT_TARGET_MASK, ISR_INT_TARGET_MASK_F1,
-       ISR_INT_TARGET_MASK_F2, ISR_INT_TARGET_MASK_F3,
-       ISR_INT_TARGET_MASK_F4, ISR_INT_TARGET_MASK_F5,
-       ISR_INT_TARGET_MASK_F7, ISR_INT_TARGET_MASK_F7
-};
-
-uint32_t qla82xx_isr_int_target_status[8] = {
-       ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
-       ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
-       ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
-       ISR_INT_TARGET_STATUS_F7, ISR_INT_TARGET_STATUS_F7
-};
-
 static struct qla82xx_legacy_intr_set legacy_intr[] = \
        QLA82XX_LEGACY_INTR_CONFIG;
 
@@ -2813,7 +2790,7 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha)
        else {
                WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval);
                wmb();
-               while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) {
+               while (RD_REG_DWORD((void __iomem *)ha->nxdb_rd_ptr) != dbval) {
                        WRT_REG_DWORD((unsigned long  __iomem *)ha->nxdb_wr_ptr,
                                dbval);
                        wmb();
@@ -2821,7 +2798,8 @@ qla82xx_start_iocbs(scsi_qla_host_t *vha)
        }
 }
 
-void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
+static void
+qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
 {
        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
@@ -3177,7 +3155,7 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha)
 }
 
 
-int
+static int
 qla82xx_check_fw_alive(scsi_qla_host_t *vha)
 {
        uint32_t fw_heartbeat_counter;
@@ -3817,7 +3795,8 @@ qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha,
        loop_cnt = ocm_hdr->op_count;
 
        for (i = 0; i < loop_cnt; i++) {
-               r_value = RD_REG_DWORD((void *)(r_addr + ha->nx_pcibase));
+               r_value = RD_REG_DWORD((void __iomem *)
+                   (r_addr + ha->nx_pcibase));
                *data_ptr++ = cpu_to_le32(r_value);
                r_addr += r_stride;
        }
@@ -4376,7 +4355,7 @@ qla82xx_md_free(scsi_qla_host_t *vha)
                    ha->md_tmplt_hdr, ha->md_template_size / 1024);
                dma_free_coherent(&ha->pdev->dev, ha->md_template_size,
                    ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
-               ha->md_tmplt_hdr = 0;
+               ha->md_tmplt_hdr = NULL;
        }
 
        /* Release the template data buffer allocated */
@@ -4386,7 +4365,7 @@ qla82xx_md_free(scsi_qla_host_t *vha)
                    ha->md_dump, ha->md_dump_size / 1024);
                vfree(ha->md_dump);
                ha->md_dump_size = 0;
-               ha->md_dump = 0;
+               ha->md_dump = NULL;
        }
 }
 
@@ -4423,7 +4402,7 @@ qla82xx_md_prep(scsi_qla_host_t *vha)
                                dma_free_coherent(&ha->pdev->dev,
                                    ha->md_template_size,
                                    ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
-                               ha->md_tmplt_hdr = 0;
+                               ha->md_tmplt_hdr = NULL;
                        }
 
                }
index d501bf5f806bed4f1c4d3691b6ee17bed6c81bdf..3a1661cf8c1e59bcc94837fc003a68d6963e70ce 100644 (file)
@@ -41,7 +41,7 @@ static struct kmem_cache *ctx_cachep;
  */
 int ql_errlev = ql_log_all;
 
-int ql2xenableclass2;
+static int ql2xenableclass2;
 module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xenableclass2,
                "Specify if Class 2 operations are supported from the very "
@@ -89,6 +89,8 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
                "\t\t0x00200000 - AER/EEH.       0x00100000 - Multi Q.\n"
                "\t\t0x00080000 - P3P Specific.  0x00040000 - Virtual Port.\n"
                "\t\t0x00020000 - Buffer Dump.   0x00010000 - Misc.\n"
+               "\t\t0x00008000 - Verbose.       0x00004000 - Target.\n"
+               "\t\t0x00002000 - Target Mgmt.   0x00001000 - Target TMF.\n"
                "\t\t0x7fffffff - For enabling all logs, can be too many logs.\n"
                "\t\t0x1e400000 - Preferred value for capturing essential "
                "debug information (equivalent to old "
@@ -494,12 +496,20 @@ qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
                    (BIT_4 | BIT_5 | BIT_6 | BIT_7 | BIT_8 | BIT_9)) >> 4;
 
                strcpy(str, "PCIe (");
-               if (lspeed == 1)
+               switch (lspeed) {
+               case 1:
                        strcat(str, "2.5GT/s ");
-               else if (lspeed == 2)
+                       break;
+               case 2:
                        strcat(str, "5.0GT/s ");
-               else
+                       break;
+               case 3:
+                       strcat(str, "8.0GT/s ");
+                       break;
+               default:
                        strcat(str, "<unknown> ");
+                       break;
+               }
                snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
                strcat(str, lwstr);
 
@@ -719,7 +729,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 
        rval = ha->isp_ops->start_scsi(sp);
        if (rval != QLA_SUCCESS) {
-               ql_dbg(ql_dbg_io, vha, 0x3013,
+               ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3013,
                    "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd);
                goto qc24_host_busy_free_sp;
        }
@@ -2357,7 +2367,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        /* Configure PCI I/O space */
        ret = ha->isp_ops->iospace_config(ha);
        if (ret)
-               goto probe_hw_failed;
+               goto iospace_config_failed;
 
        ql_log_pci(ql_log_info, pdev, 0x001d,
            "Found an ISP%04X irq %d iobase 0x%p.\n",
@@ -2668,7 +2678,11 @@ probe_hw_failed:
                qla82xx_idc_lock(ha);
                qla82xx_clear_drv_active(ha);
                qla82xx_idc_unlock(ha);
-               iounmap((device_reg_t __iomem *)ha->nx_pcibase);
+       }
+iospace_config_failed:
+       if (IS_QLA82XX(ha)) {
+               if (!ha->nx_pcibase)
+                       iounmap((device_reg_t __iomem *)ha->nx_pcibase);
                if (!ql2xdbwr)
                        iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr);
        } else {
@@ -2755,6 +2769,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        ha->flags.host_shutting_down = 1;
 
+       set_bit(UNLOADING, &base_vha->dpc_flags);
        mutex_lock(&ha->vport_lock);
        while (ha->cur_vport_count) {
                struct Scsi_Host *scsi_host;
@@ -2784,8 +2799,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
                            "Error while clearing DRV-Presence.\n");
        }
 
-       set_bit(UNLOADING, &base_vha->dpc_flags);
-
        qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
 
        qla2x00_dfs_remove(base_vha);
@@ -3721,10 +3734,9 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
                                                if (fcport->flags &
                                                    FCF_FCP2_DEVICE)
                                                        opts |= BIT_1;
-                                                       status2 =
-                                                           qla2x00_get_port_database(
-                                                               vha, fcport,
-                                                               opts);
+                                               status2 =
+                                                   qla2x00_get_port_database(
+                                                       vha, fcport, opts);
                                                if (status2 != QLA_SUCCESS)
                                                        status = 1;
                                        }
@@ -3836,7 +3848,7 @@ qla83xx_idc_state_handler_work(struct work_struct *work)
        qla83xx_idc_unlock(base_vha, 0);
 }
 
-int
+static int
 qla83xx_check_nic_core_fw_alive(scsi_qla_host_t *base_vha)
 {
        int rval = QLA_SUCCESS;
@@ -3954,7 +3966,7 @@ qla83xx_wait_logic(void)
        }
 }
 
-int
+static int
 qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha)
 {
        int rval;
@@ -4013,7 +4025,7 @@ qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha)
        return rval;
 }
 
-int
+static int
 qla83xx_idc_lock_recovery(scsi_qla_host_t *base_vha)
 {
        int rval = QLA_SUCCESS;
@@ -4212,7 +4224,7 @@ qla83xx_clear_drv_presence(scsi_qla_host_t *vha)
        return rval;
 }
 
-void
+static void
 qla83xx_need_reset_handler(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
@@ -4224,7 +4236,7 @@ qla83xx_need_reset_handler(scsi_qla_host_t *vha)
        while (1) {
                qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
                qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
-               if (drv_ack == drv_presence)
+               if ((drv_ack & drv_presence) == drv_presence)
                        break;
 
                if (time_after_eq(jiffies, ack_timeout)) {
@@ -4251,7 +4263,7 @@ qla83xx_need_reset_handler(scsi_qla_host_t *vha)
        ql_log(ql_log_info, vha, 0xb068, "HW State: COLD/RE-INIT.\n");
 }
 
-int
+static int
 qla83xx_device_bootstrap(scsi_qla_host_t *vha)
 {
        int rval = QLA_SUCCESS;
@@ -4505,9 +4517,9 @@ qla2x00_do_dpc(void *data)
                            "ISP abort end.\n");
                }
 
-               if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) {
+               if (test_and_clear_bit(FCPORT_UPDATE_NEEDED,
+                   &base_vha->dpc_flags)) {
                        qla2x00_update_fcports(base_vha);
-                       clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
                }
 
                if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) {
@@ -4987,7 +4999,8 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
                return PCI_ERS_RESULT_RECOVERED;
 }
 
-uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
+static uint32_t
+qla82xx_error_recovery(scsi_qla_host_t *base_vha)
 {
        uint32_t rval = QLA_FUNCTION_FAILED;
        uint32_t drv_active = 0;
index 62aa5584f64478d286e373414dd8b119315a5204..ad1dc14bacce6137173835a4ed4ef4c8e2c90af8 100644 (file)
@@ -73,7 +73,7 @@ enum fcp_resp_rsp_codes {
 #define FCP_PTA_SIMPLE      0   /* simple task attribute */
 #define FCP_PTA_HEADQ       1   /* head of queue task attribute */
 #define FCP_PTA_ORDERED     2   /* ordered task attribute */
-#define FCP_PTA_ACA         4   /* auto. contigent allegiance */
+#define FCP_PTA_ACA         4   /* auto. contingent allegiance */
 #define FCP_PTA_MASK        7   /* mask for task attribute field */
 #define FCP_PRI_SHIFT       3   /* priority field starts in bit 3 */
 #define FCP_PRI_RESVD_MASK  0x80        /* reserved bits in priority field */
@@ -1029,7 +1029,7 @@ void qlt_stop_phase2(struct qla_tgt *tgt)
 EXPORT_SYMBOL(qlt_stop_phase2);
 
 /* Called from qlt_remove_target() -> qla2x00_remove_one() */
-void qlt_release(struct qla_tgt *tgt)
+static void qlt_release(struct qla_tgt *tgt)
 {
        struct qla_hw_data *ha = tgt->ha;
 
@@ -3980,7 +3980,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
        case MBA_RSP_TRANSFER_ERR:      /* Response Transfer Error */
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03a,
                    "qla_target(%d): System error async event %#x "
-                   "occured", vha->vp_idx, code);
+                   "occurred", vha->vp_idx, code);
                break;
        case MBA_WAKEUP_THRES:          /* Request Queue Wake-up. */
                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -3989,7 +3989,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
        case MBA_LOOP_UP:
        {
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b,
-                   "qla_target(%d): Async LOOP_UP occured "
+                   "qla_target(%d): Async LOOP_UP occurred "
                    "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
                    le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
                    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4006,7 +4006,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
        case MBA_LIP_RESET:
        case MBA_RSCN_UPDATE:
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
-                   "qla_target(%d): Async event %#x occured "
+                   "qla_target(%d): Async event %#x occurred "
                    "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
                    le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
                    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4015,7 +4015,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
        case MBA_PORT_UPDATE:
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d,
                    "qla_target(%d): Port update async event %#x "
-                   "occured: updating the ports database (m[0]=%x, m[1]=%x, "
+                   "occurred: updating the ports database (m[0]=%x, m[1]=%x, "
                    "m[2]=%x, m[3]=%x)", vha->vp_idx, code,
                    le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
                    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4031,7 +4031,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
 
        default:
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf040,
-                   "qla_target(%d): Async event %#x occured: "
+                   "qla_target(%d): Async event %#x occurred: "
                    "ignore (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
                    code, le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
                    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
index cfe934e1af42039187aba1ca50d4c2c096b597aa..49697ca41e78969e7f4eed005218f4d40c5325ad 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.04.00.07-k"
+#define QLA2XXX_VERSION      "8.04.00.08-k"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   4
index 3d74f2f39ae18954ac825f4599b689d770f494cf..4372e32bc95f71bfde3adf95d5c5ebdfbbfc8c9b 100644 (file)
@@ -367,7 +367,7 @@ static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl(
 
        nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL);
        if (!nacl) {
-               pr_err("Unable to alocate struct tcm_qla2xxx_nacl\n");
+               pr_err("Unable to allocate struct tcm_qla2xxx_nacl\n");
                return NULL;
        }
 
index dc0ad85853e20e30f90ae0045f20f789e4585599..8f6b12cbd224801e2828571beb6938808d87b26c 100644 (file)
 
 #include "scsi_priv.h"
 
-static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
+static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *))
 {
-       struct device_driver *drv;
        int err;
 
        err = scsi_device_quiesce(to_scsi_device(dev));
        if (err == 0) {
-               drv = dev->driver;
-               if (drv && drv->suspend) {
-                       err = drv->suspend(dev, msg);
+               if (cb) {
+                       err = cb(dev);
                        if (err)
                                scsi_device_resume(to_scsi_device(dev));
                }
@@ -34,14 +32,12 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
        return err;
 }
 
-static int scsi_dev_type_resume(struct device *dev)
+static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *))
 {
-       struct device_driver *drv;
        int err = 0;
 
-       drv = dev->driver;
-       if (drv && drv->resume)
-               err = drv->resume(dev);
+       if (cb)
+               err = cb(dev);
        scsi_device_resume(to_scsi_device(dev));
        dev_dbg(dev, "scsi resume: %d\n", err);
        return err;
@@ -49,51 +45,39 @@ static int scsi_dev_type_resume(struct device *dev)
 
 #ifdef CONFIG_PM_SLEEP
 
-static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
+static int
+scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *))
 {
        int err = 0;
 
        if (scsi_is_sdev_device(dev)) {
                /*
-                * sd is the only high-level SCSI driver to implement runtime
-                * PM, and sd treats runtime suspend, system suspend, and
-                * system hibernate identically (but not system freeze).
+                * All the high-level SCSI drivers that implement runtime
+                * PM treat runtime suspend, system suspend, and system
+                * hibernate identically.
                 */
-               if (pm_runtime_suspended(dev)) {
-                       if (msg.event == PM_EVENT_SUSPEND ||
-                           msg.event == PM_EVENT_HIBERNATE)
-                               return 0;       /* already suspended */
+               if (pm_runtime_suspended(dev))
+                       return 0;
 
-                       /* wake up device so that FREEZE will succeed */
-                       pm_runtime_resume(dev);
-               }
-               err = scsi_dev_type_suspend(dev, msg);
+               err = scsi_dev_type_suspend(dev, cb);
        }
+
        return err;
 }
 
-static int scsi_bus_resume_common(struct device *dev)
+static int
+scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *))
 {
        int err = 0;
 
-       /*
-        * Parent device may have runtime suspended as soon as
-        * it is woken up during the system resume.
-        *
-        * Resume it on behalf of child.
-        */
-       pm_runtime_get_sync(dev->parent);
-
        if (scsi_is_sdev_device(dev))
-               err = scsi_dev_type_resume(dev);
+               err = scsi_dev_type_resume(dev, cb);
+
        if (err == 0) {
                pm_runtime_disable(dev);
                pm_runtime_set_active(dev);
                pm_runtime_enable(dev);
        }
-
-       pm_runtime_put_sync(dev->parent);
-
        return err;
 }
 
@@ -112,26 +96,49 @@ static int scsi_bus_prepare(struct device *dev)
 
 static int scsi_bus_suspend(struct device *dev)
 {
-       return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL);
+}
+
+static int scsi_bus_resume(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       return scsi_bus_resume_common(dev, pm ? pm->resume : NULL);
 }
 
 static int scsi_bus_freeze(struct device *dev)
 {
-       return scsi_bus_suspend_common(dev, PMSG_FREEZE);
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       return scsi_bus_suspend_common(dev, pm ? pm->freeze : NULL);
+}
+
+static int scsi_bus_thaw(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       return scsi_bus_resume_common(dev, pm ? pm->thaw : NULL);
 }
 
 static int scsi_bus_poweroff(struct device *dev)
 {
-       return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       return scsi_bus_suspend_common(dev, pm ? pm->poweroff : NULL);
+}
+
+static int scsi_bus_restore(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       return scsi_bus_resume_common(dev, pm ? pm->restore : NULL);
 }
 
 #else /* CONFIG_PM_SLEEP */
 
-#define scsi_bus_resume_common         NULL
 #define scsi_bus_prepare               NULL
 #define scsi_bus_suspend               NULL
+#define scsi_bus_resume                        NULL
 #define scsi_bus_freeze                        NULL
+#define scsi_bus_thaw                  NULL
 #define scsi_bus_poweroff              NULL
+#define scsi_bus_restore               NULL
 
 #endif /* CONFIG_PM_SLEEP */
 
@@ -140,10 +147,12 @@ static int scsi_bus_poweroff(struct device *dev)
 static int scsi_runtime_suspend(struct device *dev)
 {
        int err = 0;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        dev_dbg(dev, "scsi_runtime_suspend\n");
        if (scsi_is_sdev_device(dev)) {
-               err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND);
+               err = scsi_dev_type_suspend(dev,
+                               pm ? pm->runtime_suspend : NULL);
                if (err == -EAGAIN)
                        pm_schedule_suspend(dev, jiffies_to_msecs(
                                round_jiffies_up_relative(HZ/10)));
@@ -157,10 +166,11 @@ static int scsi_runtime_suspend(struct device *dev)
 static int scsi_runtime_resume(struct device *dev)
 {
        int err = 0;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        dev_dbg(dev, "scsi_runtime_resume\n");
        if (scsi_is_sdev_device(dev))
-               err = scsi_dev_type_resume(dev);
+               err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL);
 
        /* Insert hooks here for targets, hosts, and transport classes */
 
@@ -239,11 +249,11 @@ void scsi_autopm_put_host(struct Scsi_Host *shost)
 const struct dev_pm_ops scsi_bus_pm_ops = {
        .prepare =              scsi_bus_prepare,
        .suspend =              scsi_bus_suspend,
-       .resume =               scsi_bus_resume_common,
+       .resume =               scsi_bus_resume,
        .freeze =               scsi_bus_freeze,
-       .thaw =                 scsi_bus_resume_common,
+       .thaw =                 scsi_bus_thaw,
        .poweroff =             scsi_bus_poweroff,
-       .restore =              scsi_bus_resume_common,
+       .restore =              scsi_bus_restore,
        .runtime_suspend =      scsi_runtime_suspend,
        .runtime_resume =       scsi_runtime_resume,
        .runtime_idle =         scsi_runtime_idle,
index ce5224c92edae64061dd7c336d588838132a2e57..931a7d9542038138537a5b76a98fa27217a95d63 100644 (file)
@@ -247,11 +247,11 @@ show_shost_active_mode(struct device *dev,
 
 static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
 
-static int check_reset_type(char *str)
+static int check_reset_type(const char *str)
 {
-       if (strncmp(str, "adapter", 10) == 0)
+       if (sysfs_streq(str, "adapter"))
                return SCSI_ADAPTER_RESET;
-       else if (strncmp(str, "firmware", 10) == 0)
+       else if (sysfs_streq(str, "firmware"))
                return SCSI_FIRMWARE_RESET;
        else
                return 0;
@@ -264,12 +264,9 @@ store_host_reset(struct device *dev, struct device_attribute *attr,
        struct Scsi_Host *shost = class_to_shost(dev);
        struct scsi_host_template *sht = shost->hostt;
        int ret = -EINVAL;
-       char str[10];
        int type;
 
-       sscanf(buf, "%s", str);
-       type = check_reset_type(str);
-
+       type = check_reset_type(buf);
        if (!type)
                goto exit_store_host_reset;
 
index f7565fc4f0e344a0862bfaf02148c826fa7e7538..1b681427dde045cdad8f2455c07467fba4f077f1 100644 (file)
@@ -151,6 +151,7 @@ static struct {
        { SAS_LINK_RATE_1_5_GBPS,       "1.5 Gbit" },
        { SAS_LINK_RATE_3_0_GBPS,       "3.0 Gbit" },
        { SAS_LINK_RATE_6_0_GBPS,       "6.0 Gbit" },
+       { SAS_LINK_RATE_12_0_GBPS,      "12.0 Gbit" },
 };
 sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
 sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
index 21a045e0559ff7ad9a209742f55b020b99adcb6b..f379c7f3034cd55392355189e081b45547323008 100644 (file)
@@ -38,7 +38,7 @@ struct srp_host_attrs {
 #define to_srp_host_attrs(host)        ((struct srp_host_attrs *)(host)->shost_data)
 
 #define SRP_HOST_ATTRS 0
-#define SRP_RPORT_ATTRS 2
+#define SRP_RPORT_ATTRS 3
 
 struct srp_internal {
        struct scsi_transport_template t;
@@ -47,7 +47,6 @@ struct srp_internal {
        struct device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
 
        struct device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
-       struct device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
        struct transport_container rport_attr_cont;
 };
 
@@ -72,24 +71,6 @@ static DECLARE_TRANSPORT_CLASS(srp_host_class, "srp_host", srp_host_setup,
 static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
                               NULL, NULL, NULL);
 
-#define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm)     \
-       i->private_##attrb[count] = dev_attr_##field;           \
-       i->private_##attrb[count].attr.mode = perm;                     \
-       if (ro_test) {                                                  \
-               i->private_##attrb[count].attr.mode = ro_perm;          \
-               i->private_##attrb[count].store = NULL;                 \
-       }                                                               \
-       i->attrb[count] = &i->private_##attrb[count];                   \
-       if (test)                                                       \
-               count++
-
-#define SETUP_RPORT_ATTRIBUTE_RD(field)                                        \
-       SETUP_TEMPLATE(rport_attrs, field, S_IRUGO, 1, 0, 0)
-
-#define SETUP_RPORT_ATTRIBUTE_RW(field)                                        \
-       SETUP_TEMPLATE(rport_attrs, field, S_IRUGO | S_IWUSR,           \
-                      1, 1, S_IRUGO)
-
 #define SRP_PID(p) \
        (p)->port_id[0], (p)->port_id[1], (p)->port_id[2], (p)->port_id[3], \
        (p)->port_id[4], (p)->port_id[5], (p)->port_id[6], (p)->port_id[7], \
@@ -135,6 +116,24 @@ show_srp_rport_roles(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
 
+static ssize_t store_srp_rport_delete(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct srp_rport *rport = transport_class_to_srp_rport(dev);
+       struct Scsi_Host *shost = dev_to_shost(dev);
+       struct srp_internal *i = to_srp_internal(shost->transportt);
+
+       if (i->f->rport_delete) {
+               i->f->rport_delete(rport);
+               return count;
+       } else {
+               return -ENOSYS;
+       }
+}
+
+static DEVICE_ATTR(delete, S_IWUSR, NULL, store_srp_rport_delete);
+
 static void srp_rport_release(struct device *dev)
 {
        struct srp_rport *rport = dev_to_rport(dev);
@@ -324,12 +323,16 @@ srp_attach_transport(struct srp_function_template *ft)
        i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
        i->rport_attr_cont.ac.class = &srp_rport_class.class;
        i->rport_attr_cont.ac.match = srp_rport_match;
-       transport_container_register(&i->rport_attr_cont);
 
        count = 0;
-       SETUP_RPORT_ATTRIBUTE_RD(port_id);
-       SETUP_RPORT_ATTRIBUTE_RD(roles);
-       i->rport_attrs[count] = NULL;
+       i->rport_attrs[count++] = &dev_attr_port_id;
+       i->rport_attrs[count++] = &dev_attr_roles;
+       if (ft->rport_delete)
+               i->rport_attrs[count++] = &dev_attr_delete;
+       i->rport_attrs[count++] = NULL;
+       BUG_ON(count > ARRAY_SIZE(i->rport_attrs));
+
+       transport_container_register(&i->rport_attr_cont);
 
        i->f = ft;
 
index 352bc77b7c886fb80c057019c3edc2d5b95b7d7e..7992635d405fbe91cd1029e8cce15af7e60becc0 100644 (file)
@@ -105,7 +105,7 @@ static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
 static int  sd_remove(struct device *);
 static void sd_shutdown(struct device *);
-static int sd_suspend(struct device *, pm_message_t state);
+static int sd_suspend(struct device *);
 static int sd_resume(struct device *);
 static void sd_rescan(struct device *);
 static int sd_done(struct scsi_cmnd *);
@@ -465,15 +465,23 @@ static struct class sd_disk_class = {
        .dev_attrs      = sd_disk_attrs,
 };
 
+static const struct dev_pm_ops sd_pm_ops = {
+       .suspend                = sd_suspend,
+       .resume                 = sd_resume,
+       .poweroff               = sd_suspend,
+       .restore                = sd_resume,
+       .runtime_suspend        = sd_suspend,
+       .runtime_resume         = sd_resume,
+};
+
 static struct scsi_driver sd_template = {
        .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = "sd",
                .probe          = sd_probe,
                .remove         = sd_remove,
-               .suspend        = sd_suspend,
-               .resume         = sd_resume,
                .shutdown       = sd_shutdown,
+               .pm             = &sd_pm_ops,
        },
        .rescan                 = sd_rescan,
        .done                   = sd_done,
@@ -1011,7 +1019,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff;
                SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff;
                SCpnt->cmnd[31] = (unsigned char) this_count & 0xff;
-       } else if (block > 0xffffffff) {
+       } else if (sdp->use_16_for_rw) {
                SCpnt->cmnd[0] += READ_16 - READ_6;
                SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0);
                SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
@@ -2203,6 +2211,8 @@ got_data:
                }
        }
 
+       sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
+
        /* Rescale capacity to 512-byte units */
        if (sector_size == 4096)
                sdkp->capacity <<= 3;
@@ -3052,7 +3062,7 @@ exit:
        scsi_disk_put(sdkp);
 }
 
-static int sd_suspend(struct device *dev, pm_message_t mesg)
+static int sd_suspend(struct device *dev)
 {
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
        int ret = 0;
@@ -3067,7 +3077,7 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
                        goto done;
        }
 
-       if ((mesg.event & PM_EVENT_SLEEP) && sdkp->device->manage_start_stop) {
+       if (sdkp->device->manage_start_stop) {
                sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
                ret = sd_start_stop_device(sdkp, 0);
        }
@@ -3116,10 +3126,6 @@ static int __init init_sd(void)
        if (err)
                goto err_out;
 
-       err = scsi_register_driver(&sd_template.gendrv);
-       if (err)
-               goto err_out_class;
-
        sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE,
                                         0, 0, NULL);
        if (!sd_cdb_cache) {
@@ -3133,8 +3139,15 @@ static int __init init_sd(void)
                goto err_out_cache;
        }
 
+       err = scsi_register_driver(&sd_template.gendrv);
+       if (err)
+               goto err_out_driver;
+
        return 0;
 
+err_out_driver:
+       mempool_destroy(sd_cdb_pool);
+
 err_out_cache:
        kmem_cache_destroy(sd_cdb_cache);
 
@@ -3157,10 +3170,10 @@ static void __exit exit_sd(void)
 
        SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
+       scsi_unregister_driver(&sd_template.gendrv);
        mempool_destroy(sd_cdb_pool);
        kmem_cache_destroy(sd_cdb_cache);
 
-       scsi_unregister_driver(&sd_template.gendrv);
        class_unregister(&sd_disk_class);
 
        for (i = 0; i < SD_MAJORS; i++)
index 595af1ae4421937ba1b157d79b84d081866e8355..dd8dc27fa32c9e8bf39b1c8a9dd3c853aeabf951 100644 (file)
@@ -469,6 +469,8 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
                              sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
                              GFP_ATOMIC) >= 0)
                ret = 0;
+       else
+               mempool_free(cmd, virtscsi_cmd_pool);
 
 out:
        return ret;
index b3dc44146ca072bdacc97ab0ba3f872a664a341a..5aedcdf4ac5cd185a2ffac8ebcca2e3dcffd6c27 100644 (file)
@@ -401,7 +401,6 @@ static int fsidiv_enable(struct clk *clk)
 
 static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 val;
        int idx;
 
        idx = (clk->parent->rate / rate) & 0xffff;
index 1acae359cabea0c3c48b93390220b9909f012e39..2e188e1127ebdbc94853f41ce86e488ced1acb1f 100644 (file)
@@ -123,6 +123,13 @@ config SPI_BUTTERFLY
          inexpensive battery powered microcontroller evaluation board.
          This same cable can be used to flash new firmware.
 
+config SPI_CLPS711X
+       tristate "CLPS711X host SPI controller"
+       depends on ARCH_CLPS711X
+       help
+         This enables dedicated general purpose SPI/Microwire1-compatible
+         master mode interface (SSI1) for CLPS711X-based CPUs.
+
 config SPI_COLDFIRE_QSPI
        tristate "Freescale Coldfire QSPI controller"
        depends on (M520x || M523x || M5249 || M525x || M527x || M528x || M532x)
@@ -341,10 +348,10 @@ config SPI_SC18IS602
 
 config SPI_SH_MSIOF
        tristate "SuperH MSIOF SPI controller"
-       depends on SUPERH && HAVE_CLK
+       depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
        select SPI_BITBANG
        help
-         SPI driver for SuperH MSIOF blocks.
+         SPI driver for SuperH and SH Mobile MSIOF blocks.
 
 config SPI_SH
        tristate "SuperH SPI controller"
@@ -372,12 +379,6 @@ config SPI_SIRF
        help
          SPI driver for CSR SiRFprimaII SoCs
 
-config SPI_STMP3XXX
-       tristate "Freescale STMP37xx/378x SPI/SSP controller"
-       depends on ARCH_STMP3XXX
-       help
-         SPI driver for Freescale STMP37xx/378x SoC SSP interface
-
 config SPI_MXS
        tristate "Freescale MXS SPI controller"
        depends on ARCH_MXS
@@ -385,6 +386,20 @@ config SPI_MXS
        help
          SPI driver for Freescale MXS devices.
 
+config SPI_TEGRA20_SFLASH
+       tristate "Nvidia Tegra20 Serial flash Controller"
+       depends on ARCH_TEGRA
+       help
+         SPI driver for Nvidia Tegra20 Serial flash Controller interface.
+         The main usecase of this controller is to use spi flash as boot
+         device.
+
+config SPI_TEGRA20_SLINK
+       tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
+       depends on ARCH_TEGRA && TEGRA20_APB_DMA
+       help
+         SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
+
 config SPI_TI_SSP
        tristate "TI Sequencer Serial Port - SPI Support"
        depends on MFD_TI_SSP
index c48df47e4b0f03fd7d7f53a142c3a08bb42de54d..64e970ba261cf353079e5d32696c4f7e3eed45c0 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_SPI_BFIN5XX)             += spi-bfin5xx.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
 obj-$(CONFIG_SPI_BITBANG)              += spi-bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi-butterfly.o
+obj-$(CONFIG_SPI_CLPS711X)             += spi-clps711x.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)                += spi-coldfire-qspi.o
 obj-$(CONFIG_SPI_DAVINCI)              += spi-davinci.o
 obj-$(CONFIG_SPI_DESIGNWARE)           += spi-dw.o
@@ -59,11 +60,11 @@ obj-$(CONFIG_SPI_SH_HSPI)           += spi-sh-hspi.o
 obj-$(CONFIG_SPI_SH_MSIOF)             += spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)               += spi-sh-sci.o
 obj-$(CONFIG_SPI_SIRF)         += spi-sirf.o
-obj-$(CONFIG_SPI_STMP3XXX)             += spi-stmp.o
+obj-$(CONFIG_SPI_TEGRA20_SFLASH)       += spi-tegra20-sflash.o
+obj-$(CONFIG_SPI_TEGRA20_SLINK)                += spi-tegra20-slink.o
 obj-$(CONFIG_SPI_TI_SSP)               += spi-ti-ssp.o
 obj-$(CONFIG_SPI_TLE62X0)              += spi-tle62x0.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)         += spi-topcliff-pch.o
 obj-$(CONFIG_SPI_TXX9)                 += spi-txx9.o
 obj-$(CONFIG_SPI_XCOMM)                += spi-xcomm.o
 obj-$(CONFIG_SPI_XILINX)               += spi-xilinx.o
-
index f1fec2a19d101b110ec3da178299400afb2a1e29..5e7314ac51e9748d70c00de49814f4912e0aec44 100644 (file)
@@ -215,7 +215,7 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-static int __devinit altera_spi_probe(struct platform_device *pdev)
+static int altera_spi_probe(struct platform_device *pdev)
 {
        struct altera_spi_platform_data *platp = pdev->dev.platform_data;
        struct altera_spi *hw;
@@ -290,7 +290,7 @@ exit:
        return err;
 }
 
-static int __devexit altera_spi_remove(struct platform_device *dev)
+static int altera_spi_remove(struct platform_device *dev)
 {
        struct altera_spi *hw = platform_get_drvdata(dev);
        struct spi_master *master = hw->bitbang.master;
@@ -311,7 +311,7 @@ MODULE_DEVICE_TABLE(of, altera_spi_match);
 
 static struct platform_driver altera_spi_driver = {
        .probe = altera_spi_probe,
-       .remove = __devexit_p(altera_spi_remove),
+       .remove = altera_spi_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index 249077e5cc484ffbac1a8d320882faa56c08ff8f..9a5d7791c5fb10baa747a6a5fae6c874a0965305 100644 (file)
@@ -192,7 +192,7 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
        return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
 }
 
-static __devinit int ath79_spi_probe(struct platform_device *pdev)
+static int ath79_spi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct ath79_spi *sp;
@@ -251,7 +251,7 @@ err_put_master:
        return ret;
 }
 
-static __devexit int ath79_spi_remove(struct platform_device *pdev)
+static int ath79_spi_remove(struct platform_device *pdev)
 {
        struct ath79_spi *sp = platform_get_drvdata(pdev);
 
@@ -265,7 +265,7 @@ static __devexit int ath79_spi_remove(struct platform_device *pdev)
 
 static struct platform_driver ath79_spi_driver = {
        .probe          = ath79_spi_probe,
-       .remove         = __devexit_p(ath79_spi_remove),
+       .remove         = ath79_spi_remove,
        .driver         = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 61fb0ec26f061d3231928336fc5f66a2b128ef3c..75c0c4f5fdf2a6d02dbbebdf63ad45d3ebd33252 100644 (file)
@@ -907,7 +907,7 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit atmel_spi_probe(struct platform_device *pdev)
+static int atmel_spi_probe(struct platform_device *pdev)
 {
        struct resource         *regs;
        int                     irq;
@@ -1003,7 +1003,7 @@ out_free:
        return ret;
 }
 
-static int __devexit atmel_spi_remove(struct platform_device *pdev)
+static int atmel_spi_remove(struct platform_device *pdev)
 {
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
index a9f4049c6769316c368a716b0b6707d7082abd25..f44ab55085357392d4a57f173b871c13de4960b9 100644 (file)
@@ -36,7 +36,6 @@
 #include <bcm63xx_dev_spi.h>
 
 #define PFX            KBUILD_MODNAME
-#define DRV_VER                "0.1.2"
 
 struct bcm63xx_spi {
        struct completion       done;
@@ -170,13 +169,6 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       ret = bcm63xx_spi_check_transfer(spi, NULL);
-       if (ret < 0) {
-               dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
-                       spi->mode & ~MODEBITS);
-               return ret;
-       }
-
        dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
                __func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
 
@@ -337,7 +329,7 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
 }
 
 
-static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
+static int bcm63xx_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
        struct device *dev = &pdev->dev;
@@ -441,8 +433,8 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
                goto out_clk_disable;
        }
 
-       dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n",
-                r->start, irq, bs->fifo_size, DRV_VER);
+       dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d)\n",
+                r->start, irq, bs->fifo_size);
 
        return 0;
 
@@ -457,7 +449,7 @@ out:
        return ret;
 }
 
-static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)
+static int bcm63xx_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
@@ -485,6 +477,8 @@ static int bcm63xx_spi_suspend(struct device *dev)
                        platform_get_drvdata(to_platform_device(dev));
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
+       spi_master_suspend(master);
+
        clk_disable(bs->clk);
 
        return 0;
@@ -498,6 +492,8 @@ static int bcm63xx_spi_resume(struct device *dev)
 
        clk_enable(bs->clk);
 
+       spi_master_resume(master);
+
        return 0;
 }
 
@@ -518,7 +514,7 @@ static struct platform_driver bcm63xx_spi_driver = {
                .pm     = BCM63XX_SPI_PM_OPS,
        },
        .probe          = bcm63xx_spi_probe,
-       .remove         = __devexit_p(bcm63xx_spi_remove),
+       .remove         = bcm63xx_spi_remove,
 };
 
 module_platform_driver(bcm63xx_spi_driver);
index 6555ecd07302f148059632beb8105bd8add1370c..ac7ffca7ba470592c76885be9e1e84ef86727b74 100644 (file)
@@ -755,8 +755,7 @@ bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data)
        return 0;
 }
 
-static int __devinit
-bfin_sport_spi_probe(struct platform_device *pdev)
+static int bfin_sport_spi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct bfin5xx_spi_master *platform_info;
@@ -863,8 +862,7 @@ bfin_sport_spi_probe(struct platform_device *pdev)
 }
 
 /* stop hardware and remove the driver */
-static int __devexit
-bfin_sport_spi_remove(struct platform_device *pdev)
+static int bfin_sport_spi_remove(struct platform_device *pdev)
 {
        struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
        int status = 0;
@@ -935,7 +933,7 @@ static struct platform_driver bfin_sport_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe   = bfin_sport_spi_probe,
-       .remove  = __devexit_p(bfin_sport_spi_remove),
+       .remove  = bfin_sport_spi_remove,
        .suspend = bfin_sport_spi_suspend,
        .resume  = bfin_sport_spi_resume,
 };
index 9bb4d4af85475f8cfed48dce4530598fd45cc73d..0429d833f75bf0125df06e5c51d44819769b405c 100644 (file)
@@ -1387,7 +1387,7 @@ out_error_get_res:
 }
 
 /* stop hardware and remove the driver */
-static int __devexit bfin_spi_remove(struct platform_device *pdev)
+static int bfin_spi_remove(struct platform_device *pdev)
 {
        struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
        int status = 0;
@@ -1477,7 +1477,7 @@ static struct platform_driver bfin_spi_driver = {
        },
        .suspend        = bfin_spi_suspend,
        .resume         = bfin_spi_resume,
-       .remove         = __devexit_p(bfin_spi_remove),
+       .remove         = bfin_spi_remove,
 };
 
 static int __init bfin_spi_init(void)
index aef59b1a15f7f13881cd82f21864eb5ec59712b3..8b3d8efafd3cce19116d6f95c8cc46d1643d004e 100644 (file)
@@ -260,11 +260,11 @@ static void bitbang_work(struct work_struct *work)
        struct spi_bitbang      *bitbang =
                container_of(work, struct spi_bitbang, work);
        unsigned long           flags;
+       struct spi_message      *m, *_m;
 
        spin_lock_irqsave(&bitbang->lock, flags);
        bitbang->busy = 1;
-       while (!list_empty(&bitbang->queue)) {
-               struct spi_message      *m;
+       list_for_each_entry_safe(m, _m, &bitbang->queue, queue) {
                struct spi_device       *spi;
                unsigned                nsecs;
                struct spi_transfer     *t = NULL;
@@ -273,9 +273,7 @@ static void bitbang_work(struct work_struct *work)
                int                     status;
                int                     do_setup = -1;
 
-               m = container_of(bitbang->queue.next, struct spi_message,
-                               queue);
-               list_del_init(&m->queue);
+               list_del(&m->queue);
                spin_unlock_irqrestore(&bitbang->lock, flags);
 
                /* FIXME this is made-up ... the correct value is known to
@@ -346,17 +344,14 @@ static void bitbang_work(struct work_struct *work)
                        if (t->delay_usecs)
                                udelay(t->delay_usecs);
 
-                       if (!cs_change)
-                               continue;
-                       if (t->transfer_list.next == &m->transfers)
-                               break;
-
-                       /* sometimes a short mid-message deselect of the chip
-                        * may be needed to terminate a mode or command
-                        */
-                       ndelay(nsecs);
-                       bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-                       ndelay(nsecs);
+                       if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
+                               /* sometimes a short mid-message deselect of the chip
+                                * may be needed to terminate a mode or command
+                                */
+                               ndelay(nsecs);
+                               bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+                               ndelay(nsecs);
+                       }
                }
 
                m->status = status;
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
new file mode 100644 (file)
index 0000000..1366c46
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  CLPS711X SPI bus driver
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * 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/io.h>
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_data/spi-clps711x.h>
+
+#include <mach/hardware.h>
+
+#define DRIVER_NAME    "spi-clps711x"
+
+struct spi_clps711x_data {
+       struct completion       done;
+
+       struct clk              *spi_clk;
+       u32                     max_speed_hz;
+
+       u8                      *tx_buf;
+       u8                      *rx_buf;
+       int                     count;
+       int                     len;
+
+       int                     chipselect[0];
+};
+
+static int spi_clps711x_setup(struct spi_device *spi)
+{
+       struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
+
+       if (spi->bits_per_word != 8) {
+               dev_err(&spi->dev, "Unsupported master bus width %i\n",
+                       spi->bits_per_word);
+               return -EINVAL;
+       }
+
+       /* We are expect that SPI-device is not selected */
+       gpio_direction_output(hw->chipselect[spi->chip_select],
+                             !(spi->mode & SPI_CS_HIGH));
+
+       return 0;
+}
+
+static void spi_clps711x_setup_mode(struct spi_device *spi)
+{
+       /* Setup edge for transfer */
+       if (spi->mode & SPI_CPHA)
+               clps_writew(clps_readw(SYSCON3) | SYSCON3_ADCCKNSEN, SYSCON3);
+       else
+               clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCKNSEN, SYSCON3);
+}
+
+static int spi_clps711x_setup_xfer(struct spi_device *spi,
+                                  struct spi_transfer *xfer)
+{
+       u32 speed = xfer->speed_hz ? : spi->max_speed_hz;
+       u8 bpw = xfer->bits_per_word ? : spi->bits_per_word;
+       struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
+
+       if (bpw != 8) {
+               dev_err(&spi->dev, "Unsupported master bus width %i\n", bpw);
+               return -EINVAL;
+       }
+
+       /* Setup SPI frequency divider */
+       if (!speed || (speed >= hw->max_speed_hz))
+               clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
+                           SYSCON1_ADCKSEL(3), SYSCON1);
+       else if (speed >= (hw->max_speed_hz / 2))
+               clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
+                           SYSCON1_ADCKSEL(2), SYSCON1);
+       else if (speed >= (hw->max_speed_hz / 8))
+               clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
+                           SYSCON1_ADCKSEL(1), SYSCON1);
+       else
+               clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) |
+                           SYSCON1_ADCKSEL(0), SYSCON1);
+
+       return 0;
+}
+
+static int spi_clps711x_transfer_one_message(struct spi_master *master,
+                                            struct spi_message *msg)
+{
+       struct spi_clps711x_data *hw = spi_master_get_devdata(master);
+       struct spi_transfer *xfer;
+       int status = 0, cs = hw->chipselect[msg->spi->chip_select];
+       u32 data;
+
+       spi_clps711x_setup_mode(msg->spi);
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (spi_clps711x_setup_xfer(msg->spi, xfer)) {
+                       status = -EINVAL;
+                       goto out_xfr;
+               }
+
+               gpio_set_value(cs, !!(msg->spi->mode & SPI_CS_HIGH));
+
+               INIT_COMPLETION(hw->done);
+
+               hw->count = 0;
+               hw->len = xfer->len;
+               hw->tx_buf = (u8 *)xfer->tx_buf;
+               hw->rx_buf = (u8 *)xfer->rx_buf;
+
+               /* Initiate transfer */
+               data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
+               clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
+
+               wait_for_completion(&hw->done);
+
+               if (xfer->delay_usecs)
+                       udelay(xfer->delay_usecs);
+
+               if (xfer->cs_change ||
+                   list_is_last(&xfer->transfer_list, &msg->transfers))
+                       gpio_set_value(cs, !(msg->spi->mode & SPI_CS_HIGH));
+
+               msg->actual_length += xfer->len;
+       }
+
+out_xfr:
+       msg->status = status;
+       spi_finalize_current_message(master);
+
+       return 0;
+}
+
+static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
+{
+       struct spi_clps711x_data *hw = (struct spi_clps711x_data *)dev_id;
+       u32 data;
+
+       /* Handle RX */
+       data = clps_readb(SYNCIO);
+       if (hw->rx_buf)
+               hw->rx_buf[hw->count] = (u8)data;
+
+       hw->count++;
+
+       /* Handle TX */
+       if (hw->count < hw->len) {
+               data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
+               clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
+       } else
+               complete(&hw->done);
+
+       return IRQ_HANDLED;
+}
+
+static int spi_clps711x_probe(struct platform_device *pdev)
+{
+       int i, ret;
+       struct spi_master *master;
+       struct spi_clps711x_data *hw;
+       struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data supplied\n");
+               return -EINVAL;
+       }
+
+       if (pdata->num_chipselect < 1) {
+               dev_err(&pdev->dev, "At least one CS must be defined\n");
+               return -EINVAL;
+       }
+
+       master = spi_alloc_master(&pdev->dev,
+                                 sizeof(struct spi_clps711x_data) +
+                                 sizeof(int) * pdata->num_chipselect);
+       if (!master) {
+               dev_err(&pdev->dev, "SPI allocating memory error\n");
+               return -ENOMEM;
+       }
+
+       master->bus_num = pdev->id;
+       master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
+       master->num_chipselect = pdata->num_chipselect;
+       master->setup = spi_clps711x_setup;
+       master->transfer_one_message = spi_clps711x_transfer_one_message;
+
+       hw = spi_master_get_devdata(master);
+
+       for (i = 0; i < master->num_chipselect; i++) {
+               hw->chipselect[i] = pdata->chipselect[i];
+               if (!gpio_is_valid(hw->chipselect[i])) {
+                       dev_err(&pdev->dev, "Invalid CS GPIO %i\n", i);
+                       ret = -EINVAL;
+                       goto err_out;
+               }
+               if (gpio_request(hw->chipselect[i], DRIVER_NAME)) {
+                       dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
+                       ret = -EINVAL;
+                       goto err_out;
+               }
+       }
+
+       hw->spi_clk = devm_clk_get(&pdev->dev, "spi");
+       if (IS_ERR(hw->spi_clk)) {
+               dev_err(&pdev->dev, "Can't get clocks\n");
+               ret = PTR_ERR(hw->spi_clk);
+               goto err_out;
+       }
+       hw->max_speed_hz = clk_get_rate(hw->spi_clk);
+
+       init_completion(&hw->done);
+       platform_set_drvdata(pdev, master);
+
+       /* Disable extended mode due hardware problems */
+       clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCON, SYSCON3);
+
+       /* Clear possible pending interrupt */
+       clps_readl(SYNCIO);
+
+       ret = devm_request_irq(&pdev->dev, IRQ_SSEOTI, spi_clps711x_isr, 0,
+                              dev_name(&pdev->dev), hw);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't request IRQ\n");
+               clk_put(hw->spi_clk);
+               goto clk_out;
+       }
+
+       ret = spi_register_master(master);
+       if (!ret) {
+               dev_info(&pdev->dev,
+                        "SPI bus driver initialized. Master clock %u Hz\n",
+                        hw->max_speed_hz);
+               return 0;
+       }
+
+       dev_err(&pdev->dev, "Failed to register master\n");
+       devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
+
+clk_out:
+       devm_clk_put(&pdev->dev, hw->spi_clk);
+
+err_out:
+       while (--i >= 0)
+               if (gpio_is_valid(hw->chipselect[i]))
+                       gpio_free(hw->chipselect[i]);
+
+       platform_set_drvdata(pdev, NULL);
+       spi_master_put(master);
+       kfree(master);
+
+       return ret;
+}
+
+static int spi_clps711x_remove(struct platform_device *pdev)
+{
+       int i;
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_clps711x_data *hw = spi_master_get_devdata(master);
+
+       devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
+
+       for (i = 0; i < master->num_chipselect; i++)
+               if (gpio_is_valid(hw->chipselect[i]))
+                       gpio_free(hw->chipselect[i]);
+
+       devm_clk_put(&pdev->dev, hw->spi_clk);
+       platform_set_drvdata(pdev, NULL);
+       spi_unregister_master(master);
+       kfree(master);
+
+       return 0;
+}
+
+static struct platform_driver clps711x_spi_driver = {
+       .driver = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = spi_clps711x_probe,
+       .remove = spi_clps711x_remove,
+};
+module_platform_driver(clps711x_spi_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("CLPS711X SPI bus driver");
index 764bfee75920f1779aedf9a0bc78d3280fd2045d..58466b810da4be9690f980191f0add1b27263fb9 100644 (file)
@@ -401,7 +401,7 @@ static int mcfqspi_setup(struct spi_device *spi)
        return 0;
 }
 
-static int __devinit mcfqspi_probe(struct platform_device *pdev)
+static int mcfqspi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct mcfqspi *mcfqspi;
@@ -515,7 +515,7 @@ fail0:
        return status;
 }
 
-static int __devexit mcfqspi_remove(struct platform_device *pdev)
+static int mcfqspi_remove(struct platform_device *pdev)
 {
        struct spi_master *master = platform_get_drvdata(pdev);
        struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
@@ -594,7 +594,7 @@ static struct platform_driver mcfqspi_driver = {
        .driver.owner   = THIS_MODULE,
        .driver.pm      = &mcfqspi_pm,
        .probe          = mcfqspi_probe,
-       .remove         = __devexit_p(mcfqspi_remove),
+       .remove         = mcfqspi_remove,
 };
 module_platform_driver(mcfqspi_driver);
 
index 147dfa87a64b6260b52f71b62d7880ec6905fdfb..13661e129d9634bd3f163d83b1b62d105353ca75 100644 (file)
@@ -769,7 +769,7 @@ rx_dma_failed:
  * It will invoke spi_bitbang_start to create work queue so that client driver
  * can register transfer method to work queue.
  */
-static int __devinit davinci_spi_probe(struct platform_device *pdev)
+static int davinci_spi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct davinci_spi *dspi;
@@ -952,7 +952,7 @@ err:
  * It will also call spi_bitbang_stop to destroy the work queue which was
  * created by spi_bitbang_start.
  */
-static int __devexit davinci_spi_remove(struct platform_device *pdev)
+static int davinci_spi_remove(struct platform_device *pdev)
 {
        struct davinci_spi *dspi;
        struct spi_master *master;
@@ -980,7 +980,7 @@ static struct platform_driver davinci_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = davinci_spi_probe,
-       .remove = __devexit_p(davinci_spi_remove),
+       .remove = davinci_spi_remove,
 };
 module_platform_driver(davinci_spi_driver);
 
index db2f1ba06eaba180a5f7a2a833907ec351aadc35..4a6d5c9057a4428f61fb5937a01b40bec9b90ec0 100644 (file)
@@ -26,7 +26,7 @@ struct dw_spi_mmio {
        struct clk     *clk;
 };
 
-static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
+static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
        struct dw_spi_mmio *dwsmmio;
        struct dw_spi *dws;
@@ -106,7 +106,7 @@ err_end:
        return ret;
 }
 
-static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
+static int dw_spi_mmio_remove(struct platform_device *pdev)
 {
        struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
        struct resource *mem;
@@ -129,7 +129,7 @@ static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
 
 static struct platform_driver dw_spi_mmio_driver = {
        .probe          = dw_spi_mmio_probe,
-       .remove         = __devexit_p(dw_spi_mmio_remove),
+       .remove         = dw_spi_mmio_remove,
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
index ff81abbb3066e2fd09ce8c2c551037e737d00e70..6055c8d9fdd7a44622d9c5c1b27f68ffd4dec50c 100644 (file)
@@ -32,7 +32,7 @@ struct dw_spi_pci {
        struct dw_spi   dws;
 };
 
-static int __devinit spi_pci_probe(struct pci_dev *pdev,
+static int spi_pci_probe(struct pci_dev *pdev,
        const struct pci_device_id *ent)
 {
        struct dw_spi_pci *dwpci;
@@ -105,7 +105,7 @@ err_disable:
        return ret;
 }
 
-static void __devexit spi_pci_remove(struct pci_dev *pdev)
+static void spi_pci_remove(struct pci_dev *pdev)
 {
        struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
 
@@ -159,7 +159,7 @@ static struct pci_driver dw_spi_driver = {
        .name =         DRIVER_NAME,
        .id_table =     pci_ids,
        .probe =        spi_pci_probe,
-       .remove =       __devexit_p(spi_pci_remove),
+       .remove =       spi_pci_remove,
        .suspend =      spi_suspend,
        .resume =       spi_resume,
 };
index d1a495f64e2d62317602d3d2a6d1b56a0eff3f90..c1abc06899e72d7e6fce929acacf4b0f85caeb35 100644 (file)
@@ -696,7 +696,7 @@ static void dw_spi_cleanup(struct spi_device *spi)
        kfree(chip);
 }
 
-static int __devinit init_queue(struct dw_spi *dws)
+static int init_queue(struct dw_spi *dws)
 {
        INIT_LIST_HEAD(&dws->queue);
        spin_lock_init(&dws->lock);
@@ -795,7 +795,7 @@ static void spi_hw_init(struct dw_spi *dws)
        }
 }
 
-int __devinit dw_spi_add_host(struct dw_spi *dws)
+int dw_spi_add_host(struct dw_spi *dws)
 {
        struct spi_master *master;
        int ret;
@@ -877,7 +877,7 @@ exit:
 }
 EXPORT_SYMBOL_GPL(dw_spi_add_host);
 
-void __devexit dw_spi_remove_host(struct dw_spi *dws)
+void dw_spi_remove_host(struct dw_spi *dws)
 {
        int status = 0;
 
index 3a219599612a44e067c552a863316cd72bd82532..acb1e1935c5aedf2ebe7ae1e9ad82aa69bab1506 100644 (file)
@@ -1023,7 +1023,7 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
                free_page((unsigned long)espi->zeropage);
 }
 
-static int __devinit ep93xx_spi_probe(struct platform_device *pdev)
+static int ep93xx_spi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct ep93xx_spi_info *info;
@@ -1138,7 +1138,7 @@ fail_release_master:
        return error;
 }
 
-static int __devexit ep93xx_spi_remove(struct platform_device *pdev)
+static int ep93xx_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master = platform_get_drvdata(pdev);
        struct ep93xx_spi *espi = spi_master_get_devdata(master);
@@ -1180,7 +1180,7 @@ static struct platform_driver ep93xx_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ep93xx_spi_probe,
-       .remove         = __devexit_p(ep93xx_spi_remove),
+       .remove         = ep93xx_spi_remove,
 };
 module_platform_driver(ep93xx_spi_driver);
 
index 8f6aa735a24cc66f4c52fd1cd9234ad58a7f365e..6a6f62ec284091d8c1766ca2940d57a773de5c0b 100644 (file)
@@ -403,7 +403,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master,
        return 0;
 }
 
-static int __devinit falcon_sflash_probe(struct platform_device *pdev)
+static int falcon_sflash_probe(struct platform_device *pdev)
 {
        struct falcon_sflash *priv;
        struct spi_master *master;
@@ -438,7 +438,7 @@ static int __devinit falcon_sflash_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit falcon_sflash_remove(struct platform_device *pdev)
+static int falcon_sflash_remove(struct platform_device *pdev)
 {
        struct falcon_sflash *priv = platform_get_drvdata(pdev);
 
@@ -455,7 +455,7 @@ MODULE_DEVICE_TABLE(of, falcon_sflash_match);
 
 static struct platform_driver falcon_sflash_driver = {
        .probe  = falcon_sflash_probe,
-       .remove = __devexit_p(falcon_sflash_remove),
+       .remove = falcon_sflash_remove,
        .driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 27bdc47b525051080dbfaed8afa50ae8b98d33a3..24610ca8955da2544e9a55cce30edf6081804f2b 100644 (file)
@@ -587,7 +587,7 @@ static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
        iounmap(mspi->reg_base);
 }
 
-static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
+static struct spi_master * fsl_espi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
 {
        struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -686,7 +686,7 @@ static int of_fsl_espi_get_chipselects(struct device *dev)
        return 0;
 }
 
-static int __devinit of_fsl_espi_probe(struct platform_device *ofdev)
+static int of_fsl_espi_probe(struct platform_device *ofdev)
 {
        struct device *dev = &ofdev->dev;
        struct device_node *np = ofdev->dev.of_node;
@@ -725,7 +725,7 @@ err:
        return ret;
 }
 
-static int __devexit of_fsl_espi_remove(struct platform_device *dev)
+static int of_fsl_espi_remove(struct platform_device *dev)
 {
        return mpc8xxx_spi_remove(&dev->dev);
 }
@@ -743,7 +743,7 @@ static struct platform_driver fsl_espi_driver = {
                .of_match_table = of_fsl_espi_match,
        },
        .probe          = of_fsl_espi_probe,
-       .remove         = __devexit_p(of_fsl_espi_remove),
+       .remove         = of_fsl_espi_remove,
 };
 module_platform_driver(fsl_espi_driver);
 
index 1503574b215aebaf685bdab5f061d9c1ad139bbc..8ade675a04f143e6553bbb382d8e782b85c68503 100644 (file)
@@ -169,7 +169,7 @@ err:
        return ret;
 }
 
-int __devexit mpc8xxx_spi_remove(struct device *dev)
+int mpc8xxx_spi_remove(struct device *dev)
 {
        struct mpc8xxx_spi *mpc8xxx_spi;
        struct spi_master *master;
@@ -189,7 +189,7 @@ int __devexit mpc8xxx_spi_remove(struct device *dev)
        return 0;
 }
 
-int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
+int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
 {
        struct device *dev = &ofdev->dev;
        struct device_node *np = ofdev->dev.of_node;
index 6a62934ca74c13b36a01a8e06bbd28c7c275807e..1a7f6359d9986f5104cb4f2563ab5529412fe070 100644 (file)
@@ -843,7 +843,7 @@ static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
        fsl_spi_cpm_free(mspi);
 }
 
-static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
+static struct spi_master * fsl_spi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
 {
        struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -1041,7 +1041,7 @@ static int of_fsl_spi_free_chipselects(struct device *dev)
        return 0;
 }
 
-static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
+static int of_fsl_spi_probe(struct platform_device *ofdev)
 {
        struct device *dev = &ofdev->dev;
        struct device_node *np = ofdev->dev.of_node;
@@ -1081,7 +1081,7 @@ err:
        return ret;
 }
 
-static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
+static int of_fsl_spi_remove(struct platform_device *ofdev)
 {
        int ret;
 
@@ -1105,7 +1105,7 @@ static struct platform_driver of_fsl_spi_driver = {
                .of_match_table = of_fsl_spi_match,
        },
        .probe          = of_fsl_spi_probe,
-       .remove         = __devexit_p(of_fsl_spi_remove),
+       .remove         = of_fsl_spi_remove,
 };
 
 #ifdef CONFIG_MPC832x_RDB
@@ -1116,7 +1116,7 @@ static struct platform_driver of_fsl_spi_driver = {
  * tree can work with OpenFirmware driver. But for now we support old trees
  * as well.
  */
-static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
+static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
 {
        struct resource *mem;
        int irq;
@@ -1139,7 +1139,7 @@ static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
+static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
 {
        return mpc8xxx_spi_remove(&pdev->dev);
 }
@@ -1147,7 +1147,7 @@ static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
 MODULE_ALIAS("platform:mpc8xxx_spi");
 static struct platform_driver mpc8xxx_spi_driver = {
        .probe = plat_mpc8xxx_spi_probe,
-       .remove = __devexit_p(plat_mpc8xxx_spi_remove),
+       .remove = plat_mpc8xxx_spi_remove,
        .driver = {
                .name = "mpc8xxx_spi",
                .owner = THIS_MODULE,
index a2b50c516b318b38f13d131bd665c65c7d7f4d25..c7cf0b7a069b7e5f88be75b3d88daa53e251cd53 100644 (file)
@@ -287,7 +287,7 @@ static void spi_gpio_cleanup(struct spi_device *spi)
        spi_bitbang_cleanup(spi);
 }
 
-static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
+static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
 {
        int value;
 
@@ -301,9 +301,8 @@ static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
        return value;
 }
 
-static int __devinit
-spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
-       u16 *res_flags)
+static int spi_gpio_request(struct spi_gpio_platform_data *pdata,
+                           const char *label, u16 *res_flags)
 {
        int value;
 
@@ -392,7 +391,7 @@ static inline int spi_gpio_probe_dt(struct platform_device *pdev)
 }
 #endif
 
-static int __devinit spi_gpio_probe(struct platform_device *pdev)
+static int spi_gpio_probe(struct platform_device *pdev)
 {
        int                             status;
        struct spi_master               *master;
@@ -485,7 +484,7 @@ gpio_free:
        return status;
 }
 
-static int __devexit spi_gpio_remove(struct platform_device *pdev)
+static int spi_gpio_remove(struct platform_device *pdev)
 {
        struct spi_gpio                 *spi_gpio;
        struct spi_gpio_platform_data   *pdata;
@@ -518,7 +517,7 @@ static struct platform_driver spi_gpio_driver = {
                .of_match_table = of_match_ptr(spi_gpio_dt_ids),
        },
        .probe          = spi_gpio_probe,
-       .remove         = __devexit_p(spi_gpio_remove),
+       .remove         = spi_gpio_remove,
 };
 module_platform_driver(spi_gpio_driver);
 
index c9a0d8467de6a5b275c0bcd735e2c0e155fb3b7c..904913290aa51c0ecc0c6cb423ae714544ac95cf 100644 (file)
@@ -750,7 +750,7 @@ static void spi_imx_cleanup(struct spi_device *spi)
 {
 }
 
-static int __devinit spi_imx_probe(struct platform_device *pdev)
+static int spi_imx_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        const struct of_device_id *of_id =
@@ -906,7 +906,7 @@ out_gpio_free:
        return ret;
 }
 
-static int __devexit spi_imx_remove(struct platform_device *pdev)
+static int spi_imx_remove(struct platform_device *pdev)
 {
        struct spi_master *master = platform_get_drvdata(pdev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -942,7 +942,7 @@ static struct platform_driver spi_imx_driver = {
                   },
        .id_table = spi_imx_devtype,
        .probe = spi_imx_probe,
-       .remove = __devexit_p(spi_imx_remove),
+       .remove = spi_imx_remove,
 };
 module_platform_driver(spi_imx_driver);
 
index 0a1e39e94d06a0292f4ebb60eb4f36b1a374ad6d..cb3a3106bd4ffaa7f65040df88d48448abdd631d 100644 (file)
@@ -406,7 +406,7 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
 }
 
 /* bus_num is used only for the case dev->platform_data == NULL */
-static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
+static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                              u32 size, unsigned int irq,
                                              s16 bus_num)
 {
@@ -492,7 +492,7 @@ free_master:
        return ret;
 }
 
-static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
+static int mpc512x_psc_spi_do_remove(struct device *dev)
 {
        struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
@@ -508,7 +508,7 @@ static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
        return 0;
 }
 
-static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
+static int mpc512x_psc_spi_of_probe(struct platform_device *op)
 {
        const u32 *regaddr_p;
        u64 regaddr64, size64;
@@ -539,7 +539,7 @@ static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
                                irq_of_parse_and_map(op->dev.of_node, 0), id);
 }
 
-static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op)
+static int mpc512x_psc_spi_of_remove(struct platform_device *op)
 {
        return mpc512x_psc_spi_do_remove(&op->dev);
 }
@@ -553,7 +553,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
 
 static struct platform_driver mpc512x_psc_spi_of_driver = {
        .probe = mpc512x_psc_spi_of_probe,
-       .remove = __devexit_p(mpc512x_psc_spi_of_remove),
+       .remove = mpc512x_psc_spi_of_remove,
        .driver = {
                .name = "mpc512x-psc-spi",
                .owner = THIS_MODULE,
index bd47d262d53faa252003a6e707104a6459e7c6ce..291120b37dbb07fc90c74eb9f5c7d08af52e5bb9 100644 (file)
@@ -363,7 +363,7 @@ static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
 }
 
 /* bus_num is used only for the case dev->platform_data == NULL */
-static int __devinit mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                u32 size, unsigned int irq, s16 bus_num)
 {
        struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -450,7 +450,7 @@ free_master:
        return ret;
 }
 
-static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
+static int mpc52xx_psc_spi_of_probe(struct platform_device *op)
 {
        const u32 *regaddr_p;
        u64 regaddr64, size64;
@@ -479,7 +479,7 @@ static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
                                irq_of_parse_and_map(op->dev.of_node, 0), id);
 }
 
-static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
+static int mpc52xx_psc_spi_of_remove(struct platform_device *op)
 {
        struct spi_master *master = spi_master_get(dev_get_drvdata(&op->dev));
        struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
@@ -505,7 +505,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
 
 static struct platform_driver mpc52xx_psc_spi_of_driver = {
        .probe = mpc52xx_psc_spi_of_probe,
-       .remove = __devexit_p(mpc52xx_psc_spi_of_remove),
+       .remove = mpc52xx_psc_spi_of_remove,
        .driver = {
                .name = "mpc52xx-psc-spi",
                .owner = THIS_MODULE,
index 045410650212cf95bf431e63fb5d4951447a4209..29f77056eedcba12b6d796f41799008e378bb2ba 100644 (file)
@@ -390,7 +390,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
 /*
  * OF Platform Bus Binding
  */
-static int __devinit mpc52xx_spi_probe(struct platform_device *op)
+static int mpc52xx_spi_probe(struct platform_device *op)
 {
        struct spi_master *master;
        struct mpc52xx_spi *ms;
@@ -527,7 +527,7 @@ static int __devinit mpc52xx_spi_probe(struct platform_device *op)
        return rc;
 }
 
-static int __devexit mpc52xx_spi_remove(struct platform_device *op)
+static int mpc52xx_spi_remove(struct platform_device *op)
 {
        struct spi_master *master = spi_master_get(dev_get_drvdata(&op->dev));
        struct mpc52xx_spi *ms = spi_master_get_devdata(master);
@@ -547,7 +547,7 @@ static int __devexit mpc52xx_spi_remove(struct platform_device *op)
        return 0;
 }
 
-static const struct of_device_id mpc52xx_spi_match[] __devinitconst = {
+static const struct of_device_id mpc52xx_spi_match[] = {
        { .compatible = "fsl,mpc5200-spi", },
        {}
 };
@@ -560,6 +560,6 @@ static struct platform_driver mpc52xx_spi_of_driver = {
                .of_match_table = mpc52xx_spi_match,
        },
        .probe = mpc52xx_spi_probe,
-       .remove = __devexit_p(mpc52xx_spi_remove),
+       .remove = mpc52xx_spi_remove,
 };
 module_platform_driver(mpc52xx_spi_of_driver);
index 86dd04d6bc873dfa30f0bab1148bd863aac818fc..a3ede249d05dfc19010d3b69a244f5093a030cc7 100644 (file)
@@ -509,7 +509,7 @@ static const struct of_device_id mxs_spi_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mxs_spi_dt_ids);
 
-static int __devinit mxs_spi_probe(struct platform_device *pdev)
+static int mxs_spi_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id =
                        of_match_device(mxs_spi_dt_ids, &pdev->dev);
@@ -636,7 +636,7 @@ out_master_free:
        return ret;
 }
 
-static int __devexit mxs_spi_remove(struct platform_device *pdev)
+static int mxs_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct mxs_spi *spi;
@@ -659,7 +659,7 @@ static int __devexit mxs_spi_remove(struct platform_device *pdev)
 
 static struct platform_driver mxs_spi_driver = {
        .probe  = mxs_spi_probe,
-       .remove = __devexit_p(mxs_spi_remove),
+       .remove = mxs_spi_remove,
        .driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
index a6eca6ffdabe7f6db23cc448d45c2b2d8726afaf..b3f9ec83ef7361b98c05d1c42a9ee40949ab585b 100644 (file)
@@ -346,7 +346,7 @@ static void nuc900_init_spi(struct nuc900_spi *hw)
        nuc900_enable_int(hw);
 }
 
-static int __devinit nuc900_spi_probe(struct platform_device *pdev)
+static int nuc900_spi_probe(struct platform_device *pdev)
 {
        struct nuc900_spi *hw;
        struct spi_master *master;
@@ -453,7 +453,7 @@ err_nomem:
        return err;
 }
 
-static int __devexit nuc900_spi_remove(struct platform_device *dev)
+static int nuc900_spi_remove(struct platform_device *dev)
 {
        struct nuc900_spi *hw = platform_get_drvdata(dev);
 
@@ -477,7 +477,7 @@ static int __devexit nuc900_spi_remove(struct platform_device *dev)
 
 static struct platform_driver nuc900_spi_driver = {
        .probe          = nuc900_spi_probe,
-       .remove         = __devexit_p(nuc900_spi_remove),
+       .remove         = nuc900_spi_remove,
        .driver         = {
                .name   = "nuc900-spi",
                .owner  = THIS_MODULE,
index 9d9071b730beeeb6eeea84ee731fb620a5bcca84..432e66ec30888118f72be006957af1e65df61466 100644 (file)
@@ -243,7 +243,7 @@ static irqreturn_t tiny_spi_irq(int irq, void *dev)
 #ifdef CONFIG_OF
 #include <linux/of_gpio.h>
 
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+static int tiny_spi_of_probe(struct platform_device *pdev)
 {
        struct tiny_spi *hw = platform_get_drvdata(pdev);
        struct device_node *np = pdev->dev.of_node;
@@ -277,13 +277,13 @@ static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
        return 0;
 }
 #else /* !CONFIG_OF */
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+static int tiny_spi_of_probe(struct platform_device *pdev)
 {
        return 0;
 }
 #endif /* CONFIG_OF */
 
-static int __devinit tiny_spi_probe(struct platform_device *pdev)
+static int tiny_spi_probe(struct platform_device *pdev)
 {
        struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
        struct tiny_spi *hw;
@@ -373,7 +373,7 @@ exit:
        return err;
 }
 
-static int __devexit tiny_spi_remove(struct platform_device *pdev)
+static int tiny_spi_remove(struct platform_device *pdev)
 {
        struct tiny_spi *hw = platform_get_drvdata(pdev);
        struct spi_master *master = hw->bitbang.master;
@@ -399,7 +399,7 @@ MODULE_DEVICE_TABLE(of, tiny_spi_match);
 
 static struct platform_driver tiny_spi_driver = {
        .probe = tiny_spi_probe,
-       .remove = __devexit_p(tiny_spi_remove),
+       .remove = tiny_spi_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index ea8fb2efb0f894f09889935a99ef10ef7e4d588c..24daf964a4094322a891be0974f291dfbb1a024d 100644 (file)
@@ -266,7 +266,7 @@ static int octeon_spi_nop_transfer_hardware(struct spi_master *master)
        return 0;
 }
 
-static int __devinit octeon_spi_probe(struct platform_device *pdev)
+static int octeon_spi_probe(struct platform_device *pdev)
 {
 
        struct resource *res_mem;
@@ -326,7 +326,7 @@ fail:
        return err;
 }
 
-static int __devexit octeon_spi_remove(struct platform_device *pdev)
+static int octeon_spi_remove(struct platform_device *pdev)
 {
        struct octeon_spi *p = platform_get_drvdata(pdev);
        u64 register_base = p->register_base;
@@ -352,7 +352,7 @@ static struct platform_driver octeon_spi_driver = {
                .of_match_table = octeon_spi_match,
        },
        .probe          = octeon_spi_probe,
-       .remove         = __devexit_p(octeon_spi_remove),
+       .remove         = octeon_spi_remove,
 };
 
 module_platform_driver(octeon_spi_driver);
index dfb4b7f448c585e4a88b78a803e5d61e7d5bbe00..3aef7fa7d5b8cf8ee0cef725ca12d284e17b45a3 100644 (file)
@@ -486,7 +486,7 @@ static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k)
        return 0;
 }
 
-static int __devinit omap1_spi100k_probe(struct platform_device *pdev)
+static int omap1_spi100k_probe(struct platform_device *pdev)
 {
        struct spi_master       *master;
        struct omap1_spi100k    *spi100k;
index 3542fdc664b11abcaecd579b8743b52346453354..b610f522ca4470e341bda1f54f9481a52b37ecb7 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
-#include <linux/err.h>
 
 #include <linux/spi/spi.h>
 
@@ -130,6 +129,7 @@ struct omap2_mcspi {
        struct omap2_mcspi_dma  *dma_channels;
        struct device           *dev;
        struct omap2_mcspi_regs ctx;
+       unsigned int            pin_dir:1;
 };
 
 struct omap2_mcspi_cs {
@@ -323,19 +323,11 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
        struct omap2_mcspi      *mcspi;
        struct omap2_mcspi_dma  *mcspi_dma;
        unsigned int            count;
-       u8                      * rx;
-       const u8                * tx;
-       void __iomem            *chstat_reg;
-       struct omap2_mcspi_cs   *cs = spi->controller_state;
 
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
        count = xfer->len;
 
-       rx = xfer->rx_buf;
-       tx = xfer->tx_buf;
-       chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
-
        if (mcspi_dma->dma_tx) {
                struct dma_async_tx_descriptor *tx;
                struct scatterlist sg;
@@ -359,19 +351,6 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
        dma_async_issue_pending(mcspi_dma->dma_tx);
        omap2_mcspi_set_dma_req(spi, 0, 1);
 
-       wait_for_completion(&mcspi_dma->dma_tx_completion);
-       dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
-                        DMA_TO_DEVICE);
-
-       /* for TX_ONLY mode, be sure all words have shifted out */
-       if (rx == NULL) {
-               if (mcspi_wait_for_reg_bit(chstat_reg,
-                                       OMAP2_MCSPI_CHSTAT_TXS) < 0)
-                       dev_err(&spi->dev, "TXS timed out\n");
-               else if (mcspi_wait_for_reg_bit(chstat_reg,
-                                       OMAP2_MCSPI_CHSTAT_EOT) < 0)
-                       dev_err(&spi->dev, "EOT timed out\n");
-       }
 }
 
 static unsigned
@@ -492,6 +471,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        struct dma_slave_config cfg;
        enum dma_slave_buswidth width;
        unsigned es;
+       void __iomem            *chstat_reg;
 
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -526,8 +506,24 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
                omap2_mcspi_tx_dma(spi, xfer, cfg);
 
        if (rx != NULL)
-               return omap2_mcspi_rx_dma(spi, xfer, cfg, es);
-
+               count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
+
+       if (tx != NULL) {
+               chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+               wait_for_completion(&mcspi_dma->dma_tx_completion);
+               dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
+                                DMA_TO_DEVICE);
+
+               /* for TX_ONLY mode, be sure all words have shifted out */
+               if (rx == NULL) {
+                       if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_TXS) < 0)
+                               dev_err(&spi->dev, "TXS timed out\n");
+                       else if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_EOT) < 0)
+                               dev_err(&spi->dev, "EOT timed out\n");
+               }
+       }
        return count;
 }
 
@@ -765,8 +761,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
        /* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
         * REVISIT: this controller could support SPI_3WIRE mode.
         */
-       l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
-       l |= OMAP2_MCSPI_CHCONF_DPE0;
+       if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) {
+               l &= ~OMAP2_MCSPI_CHCONF_IS;
+               l &= ~OMAP2_MCSPI_CHCONF_DPE1;
+               l |= OMAP2_MCSPI_CHCONF_DPE0;
+       } else {
+               l |= OMAP2_MCSPI_CHCONF_IS;
+               l |= OMAP2_MCSPI_CHCONF_DPE1;
+               l &= ~OMAP2_MCSPI_CHCONF_DPE0;
+       }
 
        /* wordlength */
        l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
@@ -1085,7 +1088,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
        return 0;
 }
 
-static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
+static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
 {
        struct spi_master       *master = mcspi->master;
        struct omap2_mcspi_regs *ctx = &mcspi->ctx;
@@ -1138,7 +1141,7 @@ static const struct of_device_id omap_mcspi_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
 
-static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
+static int omap2_mcspi_probe(struct platform_device *pdev)
 {
        struct spi_master       *master;
        const struct omap2_mcspi_platform_config *pdata;
@@ -1167,6 +1170,11 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
        master->cleanup = omap2_mcspi_cleanup;
        master->dev.of_node = node;
 
+       dev_set_drvdata(&pdev->dev, master);
+
+       mcspi = spi_master_get_devdata(master);
+       mcspi->master = master;
+
        match = of_match_device(omap_mcspi_of_match, &pdev->dev);
        if (match) {
                u32 num_cs = 1; /* default number of chipselect */
@@ -1175,19 +1183,17 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
                of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
                master->num_chipselect = num_cs;
                master->bus_num = bus_num++;
+               if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
+                       mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
        } else {
                pdata = pdev->dev.platform_data;
                master->num_chipselect = pdata->num_cs;
                if (pdev->id != -1)
                        master->bus_num = pdev->id;
+               mcspi->pin_dir = pdata->pin_dir;
        }
        regs_offset = pdata->regs_offset;
 
-       dev_set_drvdata(&pdev->dev, master);
-
-       mcspi = spi_master_get_devdata(master);
-       mcspi->master = master;
-
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (r == NULL) {
                status = -ENODEV;
@@ -1272,7 +1278,7 @@ free_master:
        return status;
 }
 
-static int __devexit omap2_mcspi_remove(struct platform_device *pdev)
+static int omap2_mcspi_remove(struct platform_device *pdev)
 {
        struct spi_master       *master;
        struct omap2_mcspi      *mcspi;
@@ -1341,7 +1347,7 @@ static struct platform_driver omap2_mcspi_driver = {
                .of_match_table = omap_mcspi_of_match,
        },
        .probe =        omap2_mcspi_probe,
-       .remove =       __devexit_p(omap2_mcspi_remove),
+       .remove =       omap2_mcspi_remove,
 };
 
 module_platform_driver(omap2_mcspi_driver);
index b17c09cf0a054c271cbd2f9e4c0841a0364d2706..b7e718254b1dcb79d835cab0f0fa9c0f6705187a 100644 (file)
 #define ORION_SPI_DATA_IN_REG          0x0c
 #define ORION_SPI_INT_CAUSE_REG                0x10
 
+#define ORION_SPI_MODE_CPOL            (1 << 11)
+#define ORION_SPI_MODE_CPHA            (1 << 12)
 #define ORION_SPI_IF_8_16_BIT_MODE     (1 << 5)
 #define ORION_SPI_CLK_PRESCALE_MASK    0x1F
+#define ORION_SPI_MODE_MASK            (ORION_SPI_MODE_CPOL | \
+                                        ORION_SPI_MODE_CPHA)
 
 struct orion_spi {
        struct spi_master       *master;
@@ -123,6 +127,23 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
        return 0;
 }
 
+static void
+orion_spi_mode_set(struct spi_device *spi)
+{
+       u32 reg;
+       struct orion_spi *orion_spi;
+
+       orion_spi = spi_master_get_devdata(spi->master);
+
+       reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
+       reg &= ~ORION_SPI_MODE_MASK;
+       if (spi->mode & SPI_CPOL)
+               reg |= ORION_SPI_MODE_CPOL;
+       if (spi->mode & SPI_CPHA)
+               reg |= ORION_SPI_MODE_CPHA;
+       writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
+}
+
 /*
  * called only when no transfer is active on the bus
  */
@@ -142,6 +163,8 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
        if ((t != NULL) && t->bits_per_word)
                bits_per_word = t->bits_per_word;
 
+       orion_spi_mode_set(spi);
+
        rc = orion_spi_baudrate_set(spi, speed);
        if (rc)
                return rc;
@@ -399,7 +422,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
        }
 
        /* we support only mode 0, and no options */
-       master->mode_bits = 0;
+       master->mode_bits = SPI_CPHA | SPI_CPOL;
 
        master->setup = orion_spi_setup;
        master->transfer_one_message = orion_spi_transfer_one_message;
@@ -478,7 +501,7 @@ static int __exit orion_spi_remove(struct platform_device *pdev)
 
 MODULE_ALIAS("platform:" DRIVER_NAME);
 
-static const struct of_device_id orion_spi_of_match_table[] __devinitdata = {
+static const struct of_device_id orion_spi_of_match_table[] = {
        { .compatible = "marvell,orion-spi", },
        {}
 };
index a1db91a99b89a670cb7979c5fd758c90796aa2a9..b0fe393c882ced538ef9f098daf885a736796469 100644 (file)
@@ -371,6 +371,7 @@ struct pl022 {
        /* Two optional pin states - default & sleep */
        struct pinctrl                  *pinctrl;
        struct pinctrl_state            *pins_default;
+       struct pinctrl_state            *pins_idle;
        struct pinctrl_state            *pins_sleep;
        struct spi_master               *master;
        struct pl022_ssp_controller     *master_info;
@@ -1088,7 +1089,7 @@ err_alloc_rx_sg:
        return -ENOMEM;
 }
 
-static int __devinit pl022_dma_probe(struct pl022 *pl022)
+static int pl022_dma_probe(struct pl022 *pl022)
 {
        dma_cap_mask_t mask;
 
@@ -2057,8 +2058,7 @@ pl022_platform_data_dt_get(struct device *dev)
        return pd;
 }
 
-static int __devinit
-pl022_probe(struct amba_device *adev, const struct amba_id *id)
+static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
        struct device *dev = &adev->dev;
        struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
@@ -2116,6 +2116,11 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        } else
                dev_err(dev, "could not get default pinstate\n");
 
+       pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl,
+                                             PINCTRL_STATE_IDLE);
+       if (IS_ERR(pl022->pins_idle))
+               dev_dbg(dev, "could not get idle pinstate\n");
+
        pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl,
                                               PINCTRL_STATE_SLEEP);
        if (IS_ERR(pl022->pins_sleep))
@@ -2246,10 +2251,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
                pm_runtime_set_autosuspend_delay(dev,
                        platform_info->autosuspend_delay);
                pm_runtime_use_autosuspend(dev);
-               pm_runtime_put_autosuspend(dev);
-       } else {
-               pm_runtime_put(dev);
        }
+       pm_runtime_put(dev);
+
        return 0;
 
  err_spi_register:
@@ -2270,7 +2274,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        return status;
 }
 
-static int __devexit
+static int
 pl022_remove(struct amba_device *adev)
 {
        struct pl022 *pl022 = amba_get_drvdata(adev);
@@ -2303,35 +2307,47 @@ pl022_remove(struct amba_device *adev)
  * the runtime counterparts to handle external resources like
  * clocks, pins and regulators when going to sleep.
  */
-static void pl022_suspend_resources(struct pl022 *pl022)
+static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
 {
        int ret;
+       struct pinctrl_state *pins_state;
 
        clk_disable(pl022->clk);
 
+       pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep;
        /* Optionally let pins go into sleep states */
-       if (!IS_ERR(pl022->pins_sleep)) {
-               ret = pinctrl_select_state(pl022->pinctrl,
-                                          pl022->pins_sleep);
+       if (!IS_ERR(pins_state)) {
+               ret = pinctrl_select_state(pl022->pinctrl, pins_state);
                if (ret)
-                       dev_err(&pl022->adev->dev,
-                               "could not set pins to sleep state\n");
+                       dev_err(&pl022->adev->dev, "could not set %s pins\n",
+                               runtime ? "idle" : "sleep");
        }
 }
 
-static void pl022_resume_resources(struct pl022 *pl022)
+static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
 {
        int ret;
 
        /* Optionaly enable pins to be muxed in and configured */
+       /* First go to the default state */
        if (!IS_ERR(pl022->pins_default)) {
-               ret = pinctrl_select_state(pl022->pinctrl,
-                                          pl022->pins_default);
+               ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default);
                if (ret)
                        dev_err(&pl022->adev->dev,
                                "could not set default pins\n");
        }
 
+       if (!runtime) {
+               /* Then let's idle the pins until the next transfer happens */
+               if (!IS_ERR(pl022->pins_idle)) {
+                       ret = pinctrl_select_state(pl022->pinctrl,
+                                       pl022->pins_idle);
+               if (ret)
+                       dev_err(&pl022->adev->dev,
+                               "could not set idle pins\n");
+               }
+       }
+
        clk_enable(pl022->clk);
 }
 #endif
@@ -2347,7 +2363,9 @@ static int pl022_suspend(struct device *dev)
                dev_warn(dev, "cannot suspend master\n");
                return ret;
        }
-       pl022_suspend_resources(pl022);
+
+       pm_runtime_get_sync(dev);
+       pl022_suspend_resources(pl022, false);
 
        dev_dbg(dev, "suspended\n");
        return 0;
@@ -2358,7 +2376,8 @@ static int pl022_resume(struct device *dev)
        struct pl022 *pl022 = dev_get_drvdata(dev);
        int ret;
 
-       pl022_resume_resources(pl022);
+       pl022_resume_resources(pl022, false);
+       pm_runtime_put(dev);
 
        /* Start the queue running */
        ret = spi_master_resume(pl022->master);
@@ -2376,7 +2395,7 @@ static int pl022_runtime_suspend(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       pl022_suspend_resources(pl022);
+       pl022_suspend_resources(pl022, true);
        return 0;
 }
 
@@ -2384,7 +2403,7 @@ static int pl022_runtime_resume(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       pl022_resume_resources(pl022);
+       pl022_resume_resources(pl022, true);
        return 0;
 }
 #endif
@@ -2464,7 +2483,7 @@ static struct amba_driver pl022_driver = {
        },
        .id_table       = pl022_ids,
        .probe          = pl022_probe,
-       .remove         = __devexit_p(pl022_remove),
+       .remove         = pl022_remove,
 };
 
 static int __init pl022_init(void)
index 9f6ba34b172c2feea78feae9857d94fe0ecdfb42..cf95587eefde4c0aa87b0460b4d4ea6926a00de8 100644 (file)
@@ -51,7 +51,7 @@ void pxa_ssp_free(struct ssp_device *ssp)
 }
 EXPORT_SYMBOL_GPL(pxa_ssp_free);
 
-static int __devinit ce4100_spi_probe(struct pci_dev *dev,
+static int ce4100_spi_probe(struct pci_dev *dev,
                const struct pci_device_id *ent)
 {
        int ret;
@@ -129,7 +129,7 @@ err_nomem:
        return ret;
 }
 
-static void __devexit ce4100_spi_remove(struct pci_dev *dev)
+static void ce4100_spi_remove(struct pci_dev *dev)
 {
        struct ce4100_info *spi_info;
        struct ssp_device *ssp;
@@ -161,7 +161,7 @@ static struct pci_driver ce4100_spi_driver = {
        .name           = "ce4100_spi",
        .id_table       = ce4100_spi_devices,
        .probe          = ce4100_spi_probe,
-       .remove         = __devexit_p(ce4100_spi_remove),
+       .remove         = ce4100_spi_remove,
 };
 
 module_pci_driver(ce4100_spi_driver);
index dc25bee8d33f1d6f93deea0030712a681579b1d0..5c8c4f5883c49f8fefcbbc6f36a6662879dce0b8 100644 (file)
@@ -1438,7 +1438,7 @@ static void cleanup(struct spi_device *spi)
        kfree(chip);
 }
 
-static int __devinit init_queue(struct driver_data *drv_data)
+static int init_queue(struct driver_data *drv_data)
 {
        INIT_LIST_HEAD(&drv_data->queue);
        spin_lock_init(&drv_data->lock);
@@ -1526,7 +1526,7 @@ static int destroy_queue(struct driver_data *drv_data)
        return 0;
 }
 
-static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
+static int pxa2xx_spi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct pxa2xx_spi_master *platform_info;
index 30faf6d4ab9135c84ecd8f359626ddd75e896b60..902f2fb902db8c94ee238b456480a18432c644ee 100644 (file)
@@ -661,7 +661,7 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
        return ret;
 }
 
-static int __devinit rspi_request_dma(struct rspi_data *rspi,
+static int rspi_request_dma(struct rspi_data *rspi,
                                      struct platform_device *pdev)
 {
        struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
@@ -709,7 +709,7 @@ static int __devinit rspi_request_dma(struct rspi_data *rspi,
        return 0;
 }
 
-static void __devexit rspi_release_dma(struct rspi_data *rspi)
+static void rspi_release_dma(struct rspi_data *rspi)
 {
        if (rspi->chan_tx)
                dma_release_channel(rspi->chan_tx);
@@ -717,7 +717,7 @@ static void __devexit rspi_release_dma(struct rspi_data *rspi)
                dma_release_channel(rspi->chan_rx);
 }
 
-static int __devexit rspi_remove(struct platform_device *pdev)
+static int rspi_remove(struct platform_device *pdev)
 {
        struct rspi_data *rspi = dev_get_drvdata(&pdev->dev);
 
@@ -731,7 +731,7 @@ static int __devexit rspi_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit rspi_probe(struct platform_device *pdev)
+static int rspi_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct spi_master *master;
@@ -827,7 +827,7 @@ error1:
 
 static struct platform_driver rspi_driver = {
        .probe =        rspi_probe,
-       .remove =       __devexit_p(rspi_remove),
+       .remove =       rspi_remove,
        .driver         = {
                .name = "rspi",
                .owner  = THIS_MODULE,
index a2a080b7f42b2d9cb515b940301509466a92c7af..02d64603fcc54988f33b1ad74e89a27fdf31a216 100644 (file)
@@ -506,7 +506,7 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
        }
 }
 
-static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
+static int s3c24xx_spi_probe(struct platform_device *pdev)
 {
        struct s3c2410_spi_info *pdata;
        struct s3c24xx_spi *hw;
@@ -663,7 +663,7 @@ static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __devexit s3c24xx_spi_remove(struct platform_device *dev)
+static int s3c24xx_spi_remove(struct platform_device *dev)
 {
        struct s3c24xx_spi *hw = platform_get_drvdata(dev);
 
@@ -722,7 +722,7 @@ static const struct dev_pm_ops s3c24xx_spi_pmops = {
 MODULE_ALIAS("platform:s3c2410-spi");
 static struct platform_driver s3c24xx_spi_driver = {
        .probe          = s3c24xx_spi_probe,
-       .remove         = __devexit_p(s3c24xx_spi_remove),
+       .remove         = s3c24xx_spi_remove,
        .driver         = {
                .name   = "s3c2410-spi",
                .owner  = THIS_MODULE,
index 6e7a805d324d19d6bec848a8bca2f2a74a4303af..4dd7b7ce5c5a99d44f50cb6f7a351aa2bc611c1a 100644 (file)
@@ -516,7 +516,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
        /* Disable Clock */
        if (sdd->port_conf->clk_from_cmu) {
-               clk_disable(sdd->src_clk);
+               clk_disable_unprepare(sdd->src_clk);
        } else {
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
                val &= ~S3C64XX_SPI_ENCLK_ENABLE;
@@ -564,7 +564,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
                /* There is half-multiplier before the SPI */
                clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
                /* Enable Clock */
-               clk_enable(sdd->src_clk);
+               clk_prepare_enable(sdd->src_clk);
        } else {
                /* Configure Clock */
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
@@ -1056,7 +1056,7 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        flush_fifo(sdd);
 }
 
-static int __devinit s3c64xx_spi_get_dmares(
+static int s3c64xx_spi_get_dmares(
                        struct s3c64xx_spi_driver_data *sdd, bool tx)
 {
        struct platform_device *pdev = sdd->pdev;
@@ -1112,7 +1112,7 @@ static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
                        dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio);
                        goto free_gpio;
                }
-
+               sdd->gpios[idx] = gpio;
                ret = gpio_request(gpio, "spi-bus");
                if (ret) {
                        dev_err(dev, "gpio [%d] request failed: %d\n",
@@ -1135,7 +1135,7 @@ static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
                gpio_free(sdd->gpios[idx]);
 }
 
-static struct __devinit s3c64xx_spi_info * s3c64xx_spi_parse_dt(
+static struct s3c64xx_spi_info * s3c64xx_spi_parse_dt(
                                                struct device *dev)
 {
        struct s3c64xx_spi_info *sci;
@@ -1302,7 +1302,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                goto err3;
        }
 
-       if (clk_enable(sdd->clk)) {
+       if (clk_prepare_enable(sdd->clk)) {
                dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
                ret = -EBUSY;
                goto err4;
@@ -1317,7 +1317,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                goto err5;
        }
 
-       if (clk_enable(sdd->src_clk)) {
+       if (clk_prepare_enable(sdd->src_clk)) {
                dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
                ret = -EBUSY;
                goto err6;
@@ -1361,11 +1361,11 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 err8:
        free_irq(irq, sdd);
 err7:
-       clk_disable(sdd->src_clk);
+       clk_disable_unprepare(sdd->src_clk);
 err6:
        clk_put(sdd->src_clk);
 err5:
-       clk_disable(sdd->clk);
+       clk_disable_unprepare(sdd->clk);
 err4:
        clk_put(sdd->clk);
 err3:
@@ -1393,10 +1393,10 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 
        free_irq(platform_get_irq(pdev, 0), sdd);
 
-       clk_disable(sdd->src_clk);
+       clk_disable_unprepare(sdd->src_clk);
        clk_put(sdd->src_clk);
 
-       clk_disable(sdd->clk);
+       clk_disable_unprepare(sdd->clk);
        clk_put(sdd->clk);
 
        if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
@@ -1417,8 +1417,8 @@ static int s3c64xx_spi_suspend(struct device *dev)
        spi_master_suspend(master);
 
        /* Disable the clock */
-       clk_disable(sdd->src_clk);
-       clk_disable(sdd->clk);
+       clk_disable_unprepare(sdd->src_clk);
+       clk_disable_unprepare(sdd->clk);
 
        if (!sdd->cntrlr_info->cfg_gpio && dev->of_node)
                s3c64xx_spi_dt_gpio_free(sdd);
@@ -1440,8 +1440,8 @@ static int s3c64xx_spi_resume(struct device *dev)
                sci->cfg_gpio();
 
        /* Enable the clock */
-       clk_enable(sdd->src_clk);
-       clk_enable(sdd->clk);
+       clk_prepare_enable(sdd->src_clk);
+       clk_prepare_enable(sdd->clk);
 
        s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
@@ -1457,8 +1457,8 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev)
        struct spi_master *master = dev_get_drvdata(dev);
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-       clk_disable(sdd->clk);
-       clk_disable(sdd->src_clk);
+       clk_disable_unprepare(sdd->clk);
+       clk_disable_unprepare(sdd->src_clk);
 
        return 0;
 }
@@ -1468,8 +1468,8 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
        struct spi_master *master = dev_get_drvdata(dev);
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-       clk_enable(sdd->src_clk);
-       clk_enable(sdd->clk);
+       clk_prepare_enable(sdd->src_clk);
+       clk_prepare_enable(sdd->clk);
 
        return 0;
 }
index 796c077ef439dacd3e22fd85415724f72316276d..32f7b55fce093f07130bb7fd2af64f4d85609710 100644 (file)
@@ -68,6 +68,16 @@ static u32 hspi_read(struct hspi_priv *hspi, int reg)
        return ioread32(hspi->addr + reg);
 }
 
+static void hspi_bit_set(struct hspi_priv *hspi, int reg, u32 mask, u32 set)
+{
+       u32 val = hspi_read(hspi, reg);
+
+       val &= ~mask;
+       val |= set & mask;
+
+       hspi_write(hspi, reg, val);
+}
+
 /*
  *             transfer function
  */
@@ -105,6 +115,13 @@ static int hspi_unprepare_transfer(struct spi_master *master)
        return 0;
 }
 
+#define hspi_hw_cs_enable(hspi)                hspi_hw_cs_ctrl(hspi, 0)
+#define hspi_hw_cs_disable(hspi)       hspi_hw_cs_ctrl(hspi, 1)
+static void hspi_hw_cs_ctrl(struct hspi_priv *hspi, int hi)
+{
+       hspi_bit_set(hspi, SPSCR, (1 << 6), (hi) << 6);
+}
+
 static void hspi_hw_setup(struct hspi_priv *hspi,
                          struct spi_message *msg,
                          struct spi_transfer *t)
@@ -155,7 +172,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
 
        hspi_write(hspi, SPCR, spcr);
        hspi_write(hspi, SPSR, 0x0);
-       hspi_write(hspi, SPSCR, 0x1);   /* master mode */
+       hspi_write(hspi, SPSCR, 0x21);  /* master mode / CS control */
 }
 
 static int hspi_transfer_one_message(struct spi_master *master,
@@ -166,12 +183,21 @@ static int hspi_transfer_one_message(struct spi_master *master,
        u32 tx;
        u32 rx;
        int ret, i;
+       unsigned int cs_change;
+       const int nsecs = 50;
 
        dev_dbg(hspi->dev, "%s\n", __func__);
 
+       cs_change = 1;
        ret = 0;
        list_for_each_entry(t, &msg->transfers, transfer_list) {
-               hspi_hw_setup(hspi, msg, t);
+
+               if (cs_change) {
+                       hspi_hw_setup(hspi, msg, t);
+                       hspi_hw_cs_enable(hspi);
+                       ndelay(nsecs);
+               }
+               cs_change = t->cs_change;
 
                for (i = 0; i < t->len; i++) {
 
@@ -198,9 +224,22 @@ static int hspi_transfer_one_message(struct spi_master *master,
                }
 
                msg->actual_length += t->len;
+
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+
+               if (cs_change) {
+                       ndelay(nsecs);
+                       hspi_hw_cs_disable(hspi);
+                       ndelay(nsecs);
+               }
        }
 
        msg->status = ret;
+       if (!cs_change) {
+               ndelay(nsecs);
+               hspi_hw_cs_disable(hspi);
+       }
        spi_finalize_current_message(master);
 
        return ret;
@@ -229,7 +268,7 @@ static void hspi_cleanup(struct spi_device *spi)
        dev_dbg(dev, "%s cleanup\n", spi->modalias);
 }
 
-static int __devinit hspi_probe(struct platform_device *pdev)
+static int hspi_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct spi_master *master;
@@ -300,7 +339,7 @@ static int __devinit hspi_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit hspi_remove(struct platform_device *pdev)
+static int hspi_remove(struct platform_device *pdev)
 {
        struct hspi_priv *hspi = dev_get_drvdata(&pdev->dev);
 
@@ -314,7 +353,7 @@ static int __devexit hspi_remove(struct platform_device *pdev)
 
 static struct platform_driver hspi_driver = {
        .probe = hspi_probe,
-       .remove = __devexit_p(hspi_remove),
+       .remove = hspi_remove,
        .driver = {
                .name = "sh-hspi",
                .owner = THIS_MODULE,
index 1f466bc66d9df21e92dc5b638272214b243b333b..96358d0eabb745cff408e82cda9fd5bc40a51eaa 100644 (file)
@@ -597,7 +597,6 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        struct resource *r;
        struct spi_master *master;
        struct sh_msiof_spi_priv *p;
-       char clk_name[16];
        int i;
        int ret;
 
@@ -614,10 +613,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        p->info = pdev->dev.platform_data;
        init_completion(&p->done);
 
-       snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id);
-       p->clk = clk_get(&pdev->dev, clk_name);
+       p->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(p->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+               dev_err(&pdev->dev, "cannot get clock\n");
                ret = PTR_ERR(p->clk);
                goto err1;
        }
index 79442c31bcd9bc3c33886a9ee635261857526410..3c3600a994bdfce9284b63e637fc10e7515e4548 100644 (file)
@@ -432,7 +432,7 @@ static irqreturn_t spi_sh_irq(int irq, void *_ss)
        return IRQ_HANDLED;
 }
 
-static int __devexit spi_sh_remove(struct platform_device *pdev)
+static int spi_sh_remove(struct platform_device *pdev)
 {
        struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev);
 
@@ -444,7 +444,7 @@ static int __devexit spi_sh_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit spi_sh_probe(struct platform_device *pdev)
+static int spi_sh_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct spi_master *master;
@@ -539,7 +539,7 @@ static int __devinit spi_sh_probe(struct platform_device *pdev)
 
 static struct platform_driver spi_sh_driver = {
        .probe = spi_sh_probe,
-       .remove = __devexit_p(spi_sh_remove),
+       .remove = spi_sh_remove,
        .driver = {
                .name = "sh_spi",
                .owner = THIS_MODULE,
index ecc3d9763d102083618f96e8879b7cb665b4672c..e0f43a512e8484353cacc4ca3a4e93eab8873a25 100644 (file)
@@ -479,7 +479,7 @@ static int spi_sirfsoc_setup(struct spi_device *spi)
        return spi_sirfsoc_setup_transfer(spi, NULL);
 }
 
-static int __devinit spi_sirfsoc_probe(struct platform_device *pdev)
+static int spi_sirfsoc_probe(struct platform_device *pdev)
 {
        struct sirfsoc_spi *sspi;
        struct spi_master *master;
@@ -604,7 +604,7 @@ err_cs:
        return ret;
 }
 
-static int  __devexit spi_sirfsoc_remove(struct platform_device *pdev)
+static int  spi_sirfsoc_remove(struct platform_device *pdev)
 {
        struct spi_master *master;
        struct sirfsoc_spi *sspi;
@@ -673,7 +673,7 @@ static struct platform_driver spi_sirfsoc_driver = {
                .of_match_table = spi_sirfsoc_of_match,
        },
        .probe = spi_sirfsoc_probe,
-       .remove = __devexit_p(spi_sirfsoc_remove),
+       .remove = spi_sirfsoc_remove,
 };
 module_platform_driver(spi_sirfsoc_driver);
 
diff --git a/drivers/spi/spi-stmp.c b/drivers/spi/spi-stmp.c
deleted file mode 100644 (file)
index 911e904..0000000
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * Freescale STMP378X SPI master driver
- *
- * Author: dmitry pervushin <dimka@embeddedalley.com>
- *
- * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-
-#include <mach/platform.h>
-#include <mach/stmp3xxx.h>
-#include <mach/dma.h>
-#include <mach/regs-ssp.h>
-#include <mach/regs-apbh.h>
-
-
-/* 0 means DMA mode(recommended, default), !0 - PIO mode */
-static int pio;
-static int clock;
-
-/* default timeout for busy waits is 2 seconds */
-#define STMP_SPI_TIMEOUT       (2 * HZ)
-
-struct stmp_spi {
-       int             id;
-
-       void *  __iomem regs;   /* vaddr of the control registers */
-
-       int             irq, err_irq;
-       u32             dma;
-       struct stmp3xxx_dma_descriptor d;
-
-       u32             speed_khz;
-       u32             saved_timings;
-       u32             divider;
-
-       struct clk      *clk;
-       struct device   *master_dev;
-
-       struct work_struct work;
-       struct workqueue_struct *workqueue;
-
-       /* lock protects queue access */
-       spinlock_t lock;
-       struct list_head queue;
-
-       struct completion done;
-};
-
-#define busy_wait(cond)                                                        \
-       ({                                                              \
-       unsigned long end_jiffies = jiffies + STMP_SPI_TIMEOUT;         \
-       bool succeeded = false;                                         \
-       do {                                                            \
-               if (cond) {                                             \
-                       succeeded = true;                               \
-                       break;                                          \
-               }                                                       \
-               cpu_relax();                                            \
-       } while (time_before(jiffies, end_jiffies));                    \
-       succeeded;                                                      \
-       })
-
-/**
- * stmp_spi_init_hw
- * Initialize the SSP port
- */
-static int stmp_spi_init_hw(struct stmp_spi *ss)
-{
-       int err = 0;
-       void *pins = ss->master_dev->platform_data;
-
-       err = stmp3xxx_request_pin_group(pins, dev_name(ss->master_dev));
-       if (err)
-               goto out;
-
-       ss->clk = clk_get(NULL, "ssp");
-       if (IS_ERR(ss->clk)) {
-               err = PTR_ERR(ss->clk);
-               goto out_free_pins;
-       }
-       clk_enable(ss->clk);
-
-       stmp3xxx_reset_block(ss->regs, false);
-       stmp3xxx_dma_reset_channel(ss->dma);
-
-       return 0;
-
-out_free_pins:
-       stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
-out:
-       return err;
-}
-
-static void stmp_spi_release_hw(struct stmp_spi *ss)
-{
-       void *pins = ss->master_dev->platform_data;
-
-       if (ss->clk && !IS_ERR(ss->clk)) {
-               clk_disable(ss->clk);
-               clk_put(ss->clk);
-       }
-       stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
-}
-
-static int stmp_spi_setup_transfer(struct spi_device *spi,
-               struct spi_transfer *t)
-{
-       u8 bits_per_word;
-       u32 hz;
-       struct stmp_spi *ss = spi_master_get_devdata(spi->master);
-       u16 rate;
-
-       bits_per_word = spi->bits_per_word;
-       if (t && t->bits_per_word)
-               bits_per_word = t->bits_per_word;
-
-       /*
-        * Calculate speed:
-        *      - by default, use maximum speed from ssp clk
-        *      - if device overrides it, use it
-        *      - if transfer specifies other speed, use transfer's one
-        */
-       hz = 1000 * ss->speed_khz / ss->divider;
-       if (spi->max_speed_hz)
-               hz = min(hz, spi->max_speed_hz);
-       if (t && t->speed_hz)
-               hz = min(hz, t->speed_hz);
-
-       if (hz == 0) {
-               dev_err(&spi->dev, "Cannot continue with zero clock\n");
-               return -EINVAL;
-       }
-
-       if (bits_per_word != 8) {
-               dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-                       __func__, bits_per_word);
-               return -EINVAL;
-       }
-
-       dev_dbg(&spi->dev, "Requested clk rate = %uHz, max = %uHz/%d = %uHz\n",
-               hz, ss->speed_khz, ss->divider,
-               ss->speed_khz * 1000 / ss->divider);
-
-       if (ss->speed_khz * 1000 / ss->divider < hz) {
-               dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
-                       __func__, hz);
-               return -EINVAL;
-       }
-
-       rate = 1000 * ss->speed_khz/ss->divider/hz;
-
-       writel(BF(ss->divider, SSP_TIMING_CLOCK_DIVIDE)         |
-              BF(rate - 1, SSP_TIMING_CLOCK_RATE),
-              HW_SSP_TIMING + ss->regs);
-
-       writel(BF(1 /* mode SPI */, SSP_CTRL1_SSP_MODE)         |
-              BF(4 /* 8 bits   */, SSP_CTRL1_WORD_LENGTH)      |
-              ((spi->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
-              ((spi->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0) |
-              (pio ? 0 : BM_SSP_CTRL1_DMA_ENABLE),
-              ss->regs + HW_SSP_CTRL1);
-
-       return 0;
-}
-
-static int stmp_spi_setup(struct spi_device *spi)
-{
-       /* spi_setup() does basic checks,
-        * stmp_spi_setup_transfer() does more later
-        */
-       if (spi->bits_per_word != 8) {
-               dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-                       __func__, spi->bits_per_word);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static inline u32 stmp_spi_cs(unsigned cs)
-{
-       return  ((cs & 1) ? BM_SSP_CTRL0_WAIT_FOR_CMD : 0) |
-               ((cs & 2) ? BM_SSP_CTRL0_WAIT_FOR_IRQ : 0);
-}
-
-static int stmp_spi_txrx_dma(struct stmp_spi *ss, int cs,
-               unsigned char *buf, dma_addr_t dma_buf, int len,
-               int first, int last, bool write)
-{
-       u32 c0 = 0;
-       dma_addr_t spi_buf_dma = dma_buf;
-       int status = 0;
-       enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
-       c0 |= (first ? BM_SSP_CTRL0_LOCK_CS : 0);
-       c0 |= (last ? BM_SSP_CTRL0_IGNORE_CRC : 0);
-       c0 |= (write ? 0 : BM_SSP_CTRL0_READ);
-       c0 |= BM_SSP_CTRL0_DATA_XFER;
-
-       c0 |= stmp_spi_cs(cs);
-
-       c0 |= BF(len, SSP_CTRL0_XFER_COUNT);
-
-       if (!dma_buf)
-               spi_buf_dma = dma_map_single(ss->master_dev, buf, len, dir);
-
-       ss->d.command->cmd =
-               BF(len, APBH_CHn_CMD_XFER_COUNT)        |
-               BF(1, APBH_CHn_CMD_CMDWORDS)            |
-               BM_APBH_CHn_CMD_WAIT4ENDCMD             |
-               BM_APBH_CHn_CMD_IRQONCMPLT              |
-               BF(write ? BV_APBH_CHn_CMD_COMMAND__DMA_READ :
-                          BV_APBH_CHn_CMD_COMMAND__DMA_WRITE,
-                  APBH_CHn_CMD_COMMAND);
-       ss->d.command->pio_words[0] = c0;
-       ss->d.command->buf_ptr = spi_buf_dma;
-
-       stmp3xxx_dma_reset_channel(ss->dma);
-       stmp3xxx_dma_clear_interrupt(ss->dma);
-       stmp3xxx_dma_enable_interrupt(ss->dma);
-       init_completion(&ss->done);
-       stmp3xxx_dma_go(ss->dma, &ss->d, 1);
-       wait_for_completion(&ss->done);
-
-       if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN))
-               status = -ETIMEDOUT;
-
-       if (!dma_buf)
-               dma_unmap_single(ss->master_dev, spi_buf_dma, len, dir);
-
-       return status;
-}
-
-static inline void stmp_spi_enable(struct stmp_spi *ss)
-{
-       stmp3xxx_setl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
-       stmp3xxx_clearl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
-}
-
-static inline void stmp_spi_disable(struct stmp_spi *ss)
-{
-       stmp3xxx_clearl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
-       stmp3xxx_setl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
-}
-
-static int stmp_spi_txrx_pio(struct stmp_spi *ss, int cs,
-               unsigned char *buf, int len,
-               bool first, bool last, bool write)
-{
-       if (first)
-               stmp_spi_enable(ss);
-
-       stmp3xxx_setl(stmp_spi_cs(cs), ss->regs + HW_SSP_CTRL0);
-
-       while (len--) {
-               if (last && len <= 0)
-                       stmp_spi_disable(ss);
-
-               stmp3xxx_clearl(BM_SSP_CTRL0_XFER_COUNT,
-                               ss->regs + HW_SSP_CTRL0);
-               stmp3xxx_setl(1, ss->regs + HW_SSP_CTRL0);
-
-               if (write)
-                       stmp3xxx_clearl(BM_SSP_CTRL0_READ,
-                                       ss->regs + HW_SSP_CTRL0);
-               else
-                       stmp3xxx_setl(BM_SSP_CTRL0_READ,
-                                       ss->regs + HW_SSP_CTRL0);
-
-               /* Run! */
-               stmp3xxx_setl(BM_SSP_CTRL0_RUN, ss->regs + HW_SSP_CTRL0);
-
-               if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
-                               BM_SSP_CTRL0_RUN))
-                       break;
-
-               if (write)
-                       writel(*buf, ss->regs + HW_SSP_DATA);
-
-               /* Set TRANSFER */
-               stmp3xxx_setl(BM_SSP_CTRL0_DATA_XFER, ss->regs + HW_SSP_CTRL0);
-
-               if (!write) {
-                       if (busy_wait((readl(ss->regs + HW_SSP_STATUS) &
-                                       BM_SSP_STATUS_FIFO_EMPTY)))
-                               break;
-                       *buf = readl(ss->regs + HW_SSP_DATA) & 0xFF;
-               }
-
-               if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
-                                       BM_SSP_CTRL0_RUN))
-                       break;
-
-               /* advance to the next byte */
-               buf++;
-       }
-
-       return len < 0 ? 0 : -ETIMEDOUT;
-}
-
-static int stmp_spi_handle_message(struct stmp_spi *ss, struct spi_message *m)
-{
-       bool first, last;
-       struct spi_transfer *t, *tmp_t;
-       int status = 0;
-       int cs;
-
-       cs = m->spi->chip_select;
-
-       list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
-
-               first = (&t->transfer_list == m->transfers.next);
-               last = (&t->transfer_list == m->transfers.prev);
-
-               if (first || t->speed_hz || t->bits_per_word)
-                       stmp_spi_setup_transfer(m->spi, t);
-
-               /* reject "not last" transfers which request to change cs */
-               if (t->cs_change && !last) {
-                       dev_err(&m->spi->dev,
-                               "Message with t->cs_change has been skipped\n");
-                       continue;
-               }
-
-               if (t->tx_buf) {
-                       status = pio ?
-                          stmp_spi_txrx_pio(ss, cs, (void *)t->tx_buf,
-                                  t->len, first, last, true) :
-                          stmp_spi_txrx_dma(ss, cs, (void *)t->tx_buf,
-                                  t->tx_dma, t->len, first, last, true);
-#ifdef DEBUG
-                       if (t->len < 0x10)
-                               print_hex_dump_bytes("Tx ",
-                                       DUMP_PREFIX_OFFSET,
-                                       t->tx_buf, t->len);
-                       else
-                               pr_debug("Tx: %d bytes\n", t->len);
-#endif
-               }
-               if (t->rx_buf) {
-                       status = pio ?
-                          stmp_spi_txrx_pio(ss, cs, t->rx_buf,
-                                  t->len, first, last, false) :
-                          stmp_spi_txrx_dma(ss, cs, t->rx_buf,
-                                  t->rx_dma, t->len, first, last, false);
-#ifdef DEBUG
-                       if (t->len < 0x10)
-                               print_hex_dump_bytes("Rx ",
-                                       DUMP_PREFIX_OFFSET,
-                                       t->rx_buf, t->len);
-                       else
-                               pr_debug("Rx: %d bytes\n", t->len);
-#endif
-               }
-
-               if (t->delay_usecs)
-                       udelay(t->delay_usecs);
-
-               if (status)
-                       break;
-
-       }
-       return status;
-}
-
-/**
- * stmp_spi_handle - handle messages from the queue
- */
-static void stmp_spi_handle(struct work_struct *w)
-{
-       struct stmp_spi *ss = container_of(w, struct stmp_spi, work);
-       unsigned long flags;
-       struct spi_message *m;
-
-       spin_lock_irqsave(&ss->lock, flags);
-       while (!list_empty(&ss->queue)) {
-               m = list_entry(ss->queue.next, struct spi_message, queue);
-               list_del_init(&m->queue);
-               spin_unlock_irqrestore(&ss->lock, flags);
-
-               m->status = stmp_spi_handle_message(ss, m);
-               m->complete(m->context);
-
-               spin_lock_irqsave(&ss->lock, flags);
-       }
-       spin_unlock_irqrestore(&ss->lock, flags);
-
-       return;
-}
-
-/**
- * stmp_spi_transfer - perform message transfer.
- * Called indirectly from spi_async, queues all the messages to
- * spi_handle_message.
- * @spi: spi device
- * @m: message to be queued
- */
-static int stmp_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-       struct stmp_spi *ss = spi_master_get_devdata(spi->master);
-       unsigned long flags;
-
-       m->status = -EINPROGRESS;
-       spin_lock_irqsave(&ss->lock, flags);
-       list_add_tail(&m->queue, &ss->queue);
-       queue_work(ss->workqueue, &ss->work);
-       spin_unlock_irqrestore(&ss->lock, flags);
-       return 0;
-}
-
-static irqreturn_t stmp_spi_irq(int irq, void *dev_id)
-{
-       struct stmp_spi *ss = dev_id;
-
-       stmp3xxx_dma_clear_interrupt(ss->dma);
-       complete(&ss->done);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t stmp_spi_irq_err(int irq, void *dev_id)
-{
-       struct stmp_spi *ss = dev_id;
-       u32 c1, st;
-
-       c1 = readl(ss->regs + HW_SSP_CTRL1);
-       st = readl(ss->regs + HW_SSP_STATUS);
-       dev_err(ss->master_dev, "%s: status = 0x%08X, c1 = 0x%08X\n",
-               __func__, st, c1);
-       stmp3xxx_clearl(c1 & 0xCCCC0000, ss->regs + HW_SSP_CTRL1);
-
-       return IRQ_HANDLED;
-}
-
-static int __devinit stmp_spi_probe(struct platform_device *dev)
-{
-       int err = 0;
-       struct spi_master *master;
-       struct stmp_spi *ss;
-       struct resource *r;
-
-       master = spi_alloc_master(&dev->dev, sizeof(struct stmp_spi));
-       if (master == NULL) {
-               err = -ENOMEM;
-               goto out0;
-       }
-       master->flags = SPI_MASTER_HALF_DUPLEX;
-
-       ss = spi_master_get_devdata(master);
-       platform_set_drvdata(dev, master);
-
-       /* Get resources(memory, IRQ) associated with the device */
-       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               err = -ENODEV;
-               goto out_put_master;
-       }
-       ss->regs = ioremap(r->start, resource_size(r));
-       if (!ss->regs) {
-               err = -EINVAL;
-               goto out_put_master;
-       }
-
-       ss->master_dev = &dev->dev;
-       ss->id = dev->id;
-
-       INIT_WORK(&ss->work, stmp_spi_handle);
-       INIT_LIST_HEAD(&ss->queue);
-       spin_lock_init(&ss->lock);
-
-       ss->workqueue = create_singlethread_workqueue(dev_name(&dev->dev));
-       if (!ss->workqueue) {
-               err = -ENXIO;
-               goto out_put_master;
-       }
-       master->transfer = stmp_spi_transfer;
-       master->setup = stmp_spi_setup;
-
-       /* the spi->mode bits understood by this driver: */
-       master->mode_bits = SPI_CPOL | SPI_CPHA;
-
-       ss->irq = platform_get_irq(dev, 0);
-       if (ss->irq < 0) {
-               err = ss->irq;
-               goto out_put_master;
-       }
-       ss->err_irq = platform_get_irq(dev, 1);
-       if (ss->err_irq < 0) {
-               err = ss->err_irq;
-               goto out_put_master;
-       }
-
-       r = platform_get_resource(dev, IORESOURCE_DMA, 0);
-       if (r == NULL) {
-               err = -ENODEV;
-               goto out_put_master;
-       }
-
-       ss->dma = r->start;
-       err = stmp3xxx_dma_request(ss->dma, &dev->dev, dev_name(&dev->dev));
-       if (err)
-               goto out_put_master;
-
-       err = stmp3xxx_dma_allocate_command(ss->dma, &ss->d);
-       if (err)
-               goto out_free_dma;
-
-       master->bus_num = dev->id;
-       master->num_chipselect = 1;
-
-       /* SPI controller initializations */
-       err = stmp_spi_init_hw(ss);
-       if (err) {
-               dev_dbg(&dev->dev, "cannot initialize hardware\n");
-               goto out_free_dma_desc;
-       }
-
-       if (clock) {
-               dev_info(&dev->dev, "clock rate forced to %d\n", clock);
-               clk_set_rate(ss->clk, clock);
-       }
-       ss->speed_khz = clk_get_rate(ss->clk);
-       ss->divider = 2;
-       dev_info(&dev->dev, "max possible speed %d = %ld/%d kHz\n",
-               ss->speed_khz, clk_get_rate(ss->clk), ss->divider);
-
-       /* Register for SPI interrupt */
-       err = request_irq(ss->irq, stmp_spi_irq, 0,
-                         dev_name(&dev->dev), ss);
-       if (err) {
-               dev_dbg(&dev->dev, "request_irq failed, %d\n", err);
-               goto out_release_hw;
-       }
-
-       /* ..and shared interrupt for all SSP controllers */
-       err = request_irq(ss->err_irq, stmp_spi_irq_err, IRQF_SHARED,
-                         dev_name(&dev->dev), ss);
-       if (err) {
-               dev_dbg(&dev->dev, "request_irq(error) failed, %d\n", err);
-               goto out_free_irq;
-       }
-
-       err = spi_register_master(master);
-       if (err) {
-               dev_dbg(&dev->dev, "cannot register spi master, %d\n", err);
-               goto out_free_irq_2;
-       }
-       dev_info(&dev->dev, "at (mapped) 0x%08X, irq=%d, bus %d, %s mode\n",
-                       (u32)ss->regs, ss->irq, master->bus_num,
-                       pio ? "PIO" : "DMA");
-       return 0;
-
-out_free_irq_2:
-       free_irq(ss->err_irq, ss);
-out_free_irq:
-       free_irq(ss->irq, ss);
-out_free_dma_desc:
-       stmp3xxx_dma_free_command(ss->dma, &ss->d);
-out_free_dma:
-       stmp3xxx_dma_release(ss->dma);
-out_release_hw:
-       stmp_spi_release_hw(ss);
-out_put_master:
-       if (ss->workqueue)
-               destroy_workqueue(ss->workqueue);
-       if (ss->regs)
-               iounmap(ss->regs);
-       platform_set_drvdata(dev, NULL);
-       spi_master_put(master);
-out0:
-       return err;
-}
-
-static int __devexit stmp_spi_remove(struct platform_device *dev)
-{
-       struct stmp_spi *ss;
-       struct spi_master *master;
-
-       master = spi_master_get(platform_get_drvdata(dev));
-       ss = spi_master_get_devdata(master);
-
-       spi_unregister_master(master);
-
-       free_irq(ss->err_irq, ss);
-       free_irq(ss->irq, ss);
-       stmp3xxx_dma_free_command(ss->dma, &ss->d);
-       stmp3xxx_dma_release(ss->dma);
-       stmp_spi_release_hw(ss);
-       destroy_workqueue(ss->workqueue);
-       iounmap(ss->regs);
-       spi_master_put(master);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int stmp_spi_suspend(struct platform_device *pdev, pm_message_t pmsg)
-{
-       struct stmp_spi *ss;
-       struct spi_master *master;
-
-       master = platform_get_drvdata(pdev);
-       ss = spi_master_get_devdata(master);
-
-       ss->saved_timings = readl(HW_SSP_TIMING + ss->regs);
-       clk_disable(ss->clk);
-
-       return 0;
-}
-
-static int stmp_spi_resume(struct platform_device *pdev)
-{
-       struct stmp_spi *ss;
-       struct spi_master *master;
-
-       master = platform_get_drvdata(pdev);
-       ss = spi_master_get_devdata(master);
-
-       clk_enable(ss->clk);
-       stmp3xxx_reset_block(ss->regs, false);
-       writel(ss->saved_timings, ss->regs + HW_SSP_TIMING);
-
-       return 0;
-}
-
-#else
-#define stmp_spi_suspend NULL
-#define stmp_spi_resume  NULL
-#endif
-
-static struct platform_driver stmp_spi_driver = {
-       .probe  = stmp_spi_probe,
-       .remove = __devexit_p(stmp_spi_remove),
-       .driver = {
-               .name = "stmp3xxx_ssp",
-               .owner = THIS_MODULE,
-       },
-       .suspend = stmp_spi_suspend,
-       .resume  = stmp_spi_resume,
-};
-module_platform_driver(stmp_spi_driver);
-
-module_param(pio, int, S_IRUGO);
-module_param(clock, int, S_IRUGO);
-MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
-MODULE_DESCRIPTION("STMP3xxx SPI/SSP driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
new file mode 100644 (file)
index 0000000..448a8cc
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ * SPI driver for Nvidia's Tegra20 Serial Flash Controller.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-tegra.h>
+#include <mach/clk.h>
+
+#define SPI_COMMAND                            0x000
+#define SPI_GO                                 BIT(30)
+#define SPI_M_S                                        BIT(28)
+#define SPI_ACTIVE_SCLK_MASK                   (0x3 << 26)
+#define SPI_ACTIVE_SCLK_DRIVE_LOW              (0 << 26)
+#define SPI_ACTIVE_SCLK_DRIVE_HIGH             (1 << 26)
+#define SPI_ACTIVE_SCLK_PULL_LOW               (2 << 26)
+#define SPI_ACTIVE_SCLK_PULL_HIGH              (3 << 26)
+
+#define SPI_CK_SDA_FALLING                     (1 << 21)
+#define SPI_CK_SDA_RISING                      (0 << 21)
+#define SPI_CK_SDA_MASK                                (1 << 21)
+#define SPI_ACTIVE_SDA                         (0x3 << 18)
+#define SPI_ACTIVE_SDA_DRIVE_LOW               (0 << 18)
+#define SPI_ACTIVE_SDA_DRIVE_HIGH              (1 << 18)
+#define SPI_ACTIVE_SDA_PULL_LOW                        (2 << 18)
+#define SPI_ACTIVE_SDA_PULL_HIGH               (3 << 18)
+
+#define SPI_CS_POL_INVERT                      BIT(16)
+#define SPI_TX_EN                              BIT(15)
+#define SPI_RX_EN                              BIT(14)
+#define SPI_CS_VAL_HIGH                                BIT(13)
+#define SPI_CS_VAL_LOW                         0x0
+#define SPI_CS_SW                              BIT(12)
+#define SPI_CS_HW                              0x0
+#define SPI_CS_DELAY_MASK                      (7 << 9)
+#define SPI_CS3_EN                             BIT(8)
+#define SPI_CS2_EN                             BIT(7)
+#define SPI_CS1_EN                             BIT(6)
+#define SPI_CS0_EN                             BIT(5)
+
+#define SPI_CS_MASK                    (SPI_CS3_EN | SPI_CS2_EN |      \
+                                       SPI_CS1_EN | SPI_CS0_EN)
+#define SPI_BIT_LENGTH(x)              (((x) & 0x1f) << 0)
+
+#define SPI_MODES                      (SPI_ACTIVE_SCLK_MASK | SPI_CK_SDA_MASK)
+
+#define SPI_STATUS                     0x004
+#define SPI_BSY                                BIT(31)
+#define SPI_RDY                                BIT(30)
+#define SPI_TXF_FLUSH                  BIT(29)
+#define SPI_RXF_FLUSH                  BIT(28)
+#define SPI_RX_UNF                     BIT(27)
+#define SPI_TX_OVF                     BIT(26)
+#define SPI_RXF_EMPTY                  BIT(25)
+#define SPI_RXF_FULL                   BIT(24)
+#define SPI_TXF_EMPTY                  BIT(23)
+#define SPI_TXF_FULL                   BIT(22)
+#define SPI_BLK_CNT(count)             (((count) & 0xffff) + 1)
+
+#define SPI_FIFO_ERROR                 (SPI_RX_UNF | SPI_TX_OVF)
+#define SPI_FIFO_EMPTY                 (SPI_TX_EMPTY | SPI_RX_EMPTY)
+
+#define SPI_RX_CMP                     0x8
+#define SPI_DMA_CTL                    0x0C
+#define SPI_DMA_EN                     BIT(31)
+#define SPI_IE_RXC                     BIT(27)
+#define SPI_IE_TXC                     BIT(26)
+#define SPI_PACKED                     BIT(20)
+#define SPI_RX_TRIG_MASK               (0x3 << 18)
+#define SPI_RX_TRIG_1W                 (0x0 << 18)
+#define SPI_RX_TRIG_4W                 (0x1 << 18)
+#define SPI_TX_TRIG_MASK               (0x3 << 16)
+#define SPI_TX_TRIG_1W                 (0x0 << 16)
+#define SPI_TX_TRIG_4W                 (0x1 << 16)
+#define SPI_DMA_BLK_COUNT(count)       (((count) - 1) & 0xFFFF);
+
+#define SPI_TX_FIFO                    0x10
+#define SPI_RX_FIFO                    0x20
+
+#define DATA_DIR_TX                    (1 << 0)
+#define DATA_DIR_RX                    (1 << 1)
+
+#define MAX_CHIP_SELECT                        4
+#define SPI_FIFO_DEPTH                 4
+#define SPI_DMA_TIMEOUT               (msecs_to_jiffies(1000))
+
+struct tegra_sflash_data {
+       struct device                           *dev;
+       struct spi_master                       *master;
+       spinlock_t                              lock;
+
+       struct clk                              *clk;
+       void __iomem                            *base;
+       unsigned                                irq;
+       u32                                     spi_max_frequency;
+       u32                                     cur_speed;
+
+       struct spi_device                       *cur_spi;
+       unsigned                                cur_pos;
+       unsigned                                cur_len;
+       unsigned                                bytes_per_word;
+       unsigned                                cur_direction;
+       unsigned                                curr_xfer_words;
+
+       unsigned                                cur_rx_pos;
+       unsigned                                cur_tx_pos;
+
+       u32                                     tx_status;
+       u32                                     rx_status;
+       u32                                     status_reg;
+
+       u32                                     def_command_reg;
+       u32                                     command_reg;
+       u32                                     dma_control_reg;
+
+       struct completion                       xfer_completion;
+       struct spi_transfer                     *curr_xfer;
+};
+
+static int tegra_sflash_runtime_suspend(struct device *dev);
+static int tegra_sflash_runtime_resume(struct device *dev);
+
+static inline unsigned long tegra_sflash_readl(struct tegra_sflash_data *tsd,
+               unsigned long reg)
+{
+       return readl(tsd->base + reg);
+}
+
+static inline void tegra_sflash_writel(struct tegra_sflash_data *tsd,
+               unsigned long val, unsigned long reg)
+{
+       writel(val, tsd->base + reg);
+}
+
+static void tegra_sflash_clear_status(struct tegra_sflash_data *tsd)
+{
+       /* Write 1 to clear status register */
+       tegra_sflash_writel(tsd, SPI_RDY | SPI_FIFO_ERROR, SPI_STATUS);
+}
+
+static unsigned tegra_sflash_calculate_curr_xfer_param(
+       struct spi_device *spi, struct tegra_sflash_data *tsd,
+       struct spi_transfer *t)
+{
+       unsigned remain_len = t->len - tsd->cur_pos;
+       unsigned max_word;
+
+       tsd->bytes_per_word = (t->bits_per_word - 1) / 8 + 1;
+       max_word = remain_len / tsd->bytes_per_word;
+       if (max_word > SPI_FIFO_DEPTH)
+               max_word = SPI_FIFO_DEPTH;
+       tsd->curr_xfer_words = max_word;
+       return max_word;
+}
+
+static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
+       struct tegra_sflash_data *tsd, struct spi_transfer *t)
+{
+       unsigned nbytes;
+       unsigned long status;
+       unsigned max_n_32bit = tsd->curr_xfer_words;
+       u8 *tx_buf = (u8 *)t->tx_buf + tsd->cur_tx_pos;
+
+       if (max_n_32bit > SPI_FIFO_DEPTH)
+               max_n_32bit = SPI_FIFO_DEPTH;
+       nbytes = max_n_32bit * tsd->bytes_per_word;
+
+       status = tegra_sflash_readl(tsd, SPI_STATUS);
+       while (!(status & SPI_TXF_FULL)) {
+               int i;
+               unsigned int x = 0;
+
+               for (i = 0; nbytes && (i < tsd->bytes_per_word);
+                                                       i++, nbytes--)
+                               x |= ((*tx_buf++) << i*8);
+               tegra_sflash_writel(tsd, x, SPI_TX_FIFO);
+               if (!nbytes)
+                       break;
+
+               status = tegra_sflash_readl(tsd, SPI_STATUS);
+       }
+       tsd->cur_tx_pos += max_n_32bit * tsd->bytes_per_word;
+       return max_n_32bit;
+}
+
+static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
+               struct tegra_sflash_data *tsd, struct spi_transfer *t)
+{
+       unsigned long status;
+       unsigned int read_words = 0;
+       u8 *rx_buf = (u8 *)t->rx_buf + tsd->cur_rx_pos;
+
+       status = tegra_sflash_readl(tsd, SPI_STATUS);
+       while (!(status & SPI_RXF_EMPTY)) {
+               int i;
+               unsigned long x;
+
+               x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
+               for (i = 0; (i < tsd->bytes_per_word); i++)
+                       *rx_buf++ = (x >> (i*8)) & 0xFF;
+               read_words++;
+               status = tegra_sflash_readl(tsd, SPI_STATUS);
+       }
+       tsd->cur_rx_pos += read_words * tsd->bytes_per_word;
+       return 0;
+}
+
+static int tegra_sflash_start_cpu_based_transfer(
+               struct tegra_sflash_data *tsd, struct spi_transfer *t)
+{
+       unsigned long val = 0;
+       unsigned cur_words;
+
+       if (tsd->cur_direction & DATA_DIR_TX)
+               val |= SPI_IE_TXC;
+
+       if (tsd->cur_direction & DATA_DIR_RX)
+               val |= SPI_IE_RXC;
+
+       tegra_sflash_writel(tsd, val, SPI_DMA_CTL);
+       tsd->dma_control_reg = val;
+
+       if (tsd->cur_direction & DATA_DIR_TX)
+               cur_words = tegra_sflash_fill_tx_fifo_from_client_txbuf(tsd, t);
+       else
+               cur_words = tsd->curr_xfer_words;
+       val |= SPI_DMA_BLK_COUNT(cur_words);
+       tegra_sflash_writel(tsd, val, SPI_DMA_CTL);
+       tsd->dma_control_reg = val;
+       val |= SPI_DMA_EN;
+       tegra_sflash_writel(tsd, val, SPI_DMA_CTL);
+       return 0;
+}
+
+static int tegra_sflash_start_transfer_one(struct spi_device *spi,
+               struct spi_transfer *t, bool is_first_of_msg,
+               bool is_single_xfer)
+{
+       struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
+       u32 speed;
+       unsigned long command;
+
+       speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+       if (!speed)
+               speed = tsd->spi_max_frequency;
+       if (speed != tsd->cur_speed) {
+               clk_set_rate(tsd->clk, speed);
+               tsd->cur_speed = speed;
+       }
+
+       tsd->cur_spi = spi;
+       tsd->cur_pos = 0;
+       tsd->cur_rx_pos = 0;
+       tsd->cur_tx_pos = 0;
+       tsd->curr_xfer = t;
+       tegra_sflash_calculate_curr_xfer_param(spi, tsd, t);
+       if (is_first_of_msg) {
+               command = tsd->def_command_reg;
+               command |= SPI_BIT_LENGTH(t->bits_per_word - 1);
+               command |= SPI_CS_VAL_HIGH;
+
+               command &= ~SPI_MODES;
+               if (spi->mode & SPI_CPHA)
+                       command |= SPI_CK_SDA_FALLING;
+
+               if (spi->mode & SPI_CPOL)
+                       command |= SPI_ACTIVE_SCLK_DRIVE_HIGH;
+               else
+                       command |= SPI_ACTIVE_SCLK_DRIVE_LOW;
+               command |= SPI_CS0_EN << spi->chip_select;
+       } else {
+               command = tsd->command_reg;
+               command &= ~SPI_BIT_LENGTH(~0);
+               command |= SPI_BIT_LENGTH(t->bits_per_word - 1);
+               command &= ~(SPI_RX_EN | SPI_TX_EN);
+       }
+
+       tsd->cur_direction = 0;
+       if (t->rx_buf) {
+               command |= SPI_RX_EN;
+               tsd->cur_direction |= DATA_DIR_RX;
+       }
+       if (t->tx_buf) {
+               command |= SPI_TX_EN;
+               tsd->cur_direction |= DATA_DIR_TX;
+       }
+       tegra_sflash_writel(tsd, command, SPI_COMMAND);
+       tsd->command_reg = command;
+
+       return  tegra_sflash_start_cpu_based_transfer(tsd, t);
+}
+
+static int tegra_sflash_transfer_one_message(struct spi_master *master,
+                       struct spi_message *msg)
+{
+       bool is_first_msg = true;
+       int single_xfer;
+       struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+       struct spi_transfer *xfer;
+       struct spi_device *spi = msg->spi;
+       int ret;
+
+       ret = pm_runtime_get_sync(tsd->dev);
+       if (ret < 0) {
+               dev_err(tsd->dev, "pm_runtime_get() failed, err = %d\n", ret);
+               return ret;
+       }
+
+       msg->status = 0;
+       msg->actual_length = 0;
+       single_xfer = list_is_singular(&msg->transfers);
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               INIT_COMPLETION(tsd->xfer_completion);
+               ret = tegra_sflash_start_transfer_one(spi, xfer,
+                                       is_first_msg, single_xfer);
+               if (ret < 0) {
+                       dev_err(tsd->dev,
+                               "spi can not start transfer, err %d\n", ret);
+                       goto exit;
+               }
+               is_first_msg = false;
+               ret = wait_for_completion_timeout(&tsd->xfer_completion,
+                                               SPI_DMA_TIMEOUT);
+               if (WARN_ON(ret == 0)) {
+                       dev_err(tsd->dev,
+                               "spi trasfer timeout, err %d\n", ret);
+                       ret = -EIO;
+                       goto exit;
+               }
+
+               if (tsd->tx_status ||  tsd->rx_status) {
+                       dev_err(tsd->dev, "Error in Transfer\n");
+                       ret = -EIO;
+                       goto exit;
+               }
+               msg->actual_length += xfer->len;
+               if (xfer->cs_change && xfer->delay_usecs) {
+                       tegra_sflash_writel(tsd, tsd->def_command_reg,
+                                       SPI_COMMAND);
+                       udelay(xfer->delay_usecs);
+               }
+       }
+       ret = 0;
+exit:
+       tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
+       msg->status = ret;
+       spi_finalize_current_message(master);
+       pm_runtime_put(tsd->dev);
+       return ret;
+}
+
+static irqreturn_t handle_cpu_based_xfer(struct tegra_sflash_data *tsd)
+{
+       struct spi_transfer *t = tsd->curr_xfer;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tsd->lock, flags);
+       if (tsd->tx_status || tsd->rx_status || (tsd->status_reg & SPI_BSY)) {
+               dev_err(tsd->dev,
+                       "CpuXfer ERROR bit set 0x%x\n", tsd->status_reg);
+               dev_err(tsd->dev,
+                       "CpuXfer 0x%08x:0x%08x\n", tsd->command_reg,
+                               tsd->dma_control_reg);
+               tegra_periph_reset_assert(tsd->clk);
+               udelay(2);
+               tegra_periph_reset_deassert(tsd->clk);
+               complete(&tsd->xfer_completion);
+               goto exit;
+       }
+
+       if (tsd->cur_direction & DATA_DIR_RX)
+               tegra_sflash_read_rx_fifo_to_client_rxbuf(tsd, t);
+
+       if (tsd->cur_direction & DATA_DIR_TX)
+               tsd->cur_pos = tsd->cur_tx_pos;
+       else
+               tsd->cur_pos = tsd->cur_rx_pos;
+
+       if (tsd->cur_pos == t->len) {
+               complete(&tsd->xfer_completion);
+               goto exit;
+       }
+
+       tegra_sflash_calculate_curr_xfer_param(tsd->cur_spi, tsd, t);
+       tegra_sflash_start_cpu_based_transfer(tsd, t);
+exit:
+       spin_unlock_irqrestore(&tsd->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t tegra_sflash_isr(int irq, void *context_data)
+{
+       struct tegra_sflash_data *tsd = context_data;
+
+       tsd->status_reg = tegra_sflash_readl(tsd, SPI_STATUS);
+       if (tsd->cur_direction & DATA_DIR_TX)
+               tsd->tx_status = tsd->status_reg & SPI_TX_OVF;
+
+       if (tsd->cur_direction & DATA_DIR_RX)
+               tsd->rx_status = tsd->status_reg & SPI_RX_UNF;
+       tegra_sflash_clear_status(tsd);
+
+       return handle_cpu_based_xfer(tsd);
+}
+
+static struct tegra_spi_platform_data *tegra_sflash_parse_dt(
+               struct platform_device *pdev)
+{
+       struct tegra_spi_platform_data *pdata;
+       struct device_node *np = pdev->dev.of_node;
+       u32 max_freq;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "Memory alloc for pdata failed\n");
+               return NULL;
+       }
+
+       if (!of_property_read_u32(np, "spi-max-frequency", &max_freq))
+               pdata->spi_max_frequency = max_freq;
+
+       return pdata;
+}
+
+static struct of_device_id tegra_sflash_of_match[] = {
+       { .compatible = "nvidia,tegra20-sflash", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, tegra_sflash_of_match);
+
+static int tegra_sflash_probe(struct platform_device *pdev)
+{
+       struct spi_master       *master;
+       struct tegra_sflash_data        *tsd;
+       struct resource         *r;
+       struct tegra_spi_platform_data *pdata = pdev->dev.platform_data;
+       int ret;
+       const struct of_device_id *match;
+
+       match = of_match_device(of_match_ptr(tegra_sflash_of_match),
+                                       &pdev->dev);
+       if (!match) {
+               dev_err(&pdev->dev, "Error: No device match found\n");
+               return -ENODEV;
+       }
+
+       if (!pdata && pdev->dev.of_node)
+               pdata = tegra_sflash_parse_dt(pdev);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data, exiting\n");
+               return -ENODEV;
+       }
+
+       if (!pdata->spi_max_frequency)
+               pdata->spi_max_frequency = 25000000; /* 25MHz */
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*tsd));
+       if (!master) {
+               dev_err(&pdev->dev, "master allocation failed\n");
+               return -ENOMEM;
+       }
+
+       /* the spi->mode bits understood by this driver: */
+       master->mode_bits = SPI_CPOL | SPI_CPHA;
+       master->transfer_one_message = tegra_sflash_transfer_one_message;
+       master->num_chipselect = MAX_CHIP_SELECT;
+       master->bus_num = -1;
+
+       dev_set_drvdata(&pdev->dev, master);
+       tsd = spi_master_get_devdata(master);
+       tsd->master = master;
+       tsd->dev = &pdev->dev;
+       spin_lock_init(&tsd->lock);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               dev_err(&pdev->dev, "No IO memory resource\n");
+               ret = -ENODEV;
+               goto exit_free_master;
+       }
+       tsd->base = devm_request_and_ioremap(&pdev->dev, r);
+       if (!tsd->base) {
+               dev_err(&pdev->dev,
+                       "Cannot request memregion/iomap dma address\n");
+               ret = -EADDRNOTAVAIL;
+               goto exit_free_master;
+       }
+
+       tsd->irq = platform_get_irq(pdev, 0);
+       ret = request_irq(tsd->irq, tegra_sflash_isr, 0,
+                       dev_name(&pdev->dev), tsd);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
+                                       tsd->irq);
+               goto exit_free_master;
+       }
+
+       tsd->clk = devm_clk_get(&pdev->dev, "spi");
+       if (IS_ERR(tsd->clk)) {
+               dev_err(&pdev->dev, "can not get clock\n");
+               ret = PTR_ERR(tsd->clk);
+               goto exit_free_irq;
+       }
+
+       tsd->spi_max_frequency = pdata->spi_max_frequency;
+       init_completion(&tsd->xfer_completion);
+       pm_runtime_enable(&pdev->dev);
+       if (!pm_runtime_enabled(&pdev->dev)) {
+               ret = tegra_sflash_runtime_resume(&pdev->dev);
+               if (ret)
+                       goto exit_pm_disable;
+       }
+
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
+               goto exit_pm_disable;
+       }
+
+       /* Reset controller */
+       tegra_periph_reset_assert(tsd->clk);
+       udelay(2);
+       tegra_periph_reset_deassert(tsd->clk);
+
+       tsd->def_command_reg  = SPI_M_S | SPI_CS_SW;
+       tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
+       pm_runtime_put(&pdev->dev);
+
+       master->dev.of_node = pdev->dev.of_node;
+       ret = spi_register_master(master);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+               goto exit_pm_disable;
+       }
+       return ret;
+
+exit_pm_disable:
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               tegra_sflash_runtime_suspend(&pdev->dev);
+exit_free_irq:
+       free_irq(tsd->irq, tsd);
+exit_free_master:
+       spi_master_put(master);
+       return ret;
+}
+
+static int tegra_sflash_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = dev_get_drvdata(&pdev->dev);
+       struct tegra_sflash_data        *tsd = spi_master_get_devdata(master);
+
+       free_irq(tsd->irq, tsd);
+       spi_unregister_master(master);
+
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               tegra_sflash_runtime_suspend(&pdev->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_sflash_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+
+       return spi_master_suspend(master);
+}
+
+static int tegra_sflash_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+       int ret;
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0) {
+               dev_err(dev, "pm runtime failed, e = %d\n", ret);
+               return ret;
+       }
+       tegra_sflash_writel(tsd, tsd->command_reg, SPI_COMMAND);
+       pm_runtime_put(dev);
+
+       return spi_master_resume(master);
+}
+#endif
+
+static int tegra_sflash_runtime_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+
+       /* Flush all write which are in PPSB queue by reading back */
+       tegra_sflash_readl(tsd, SPI_COMMAND);
+
+       clk_disable_unprepare(tsd->clk);
+       return 0;
+}
+
+static int tegra_sflash_runtime_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+       int ret;
+
+       ret = clk_prepare_enable(tsd->clk);
+       if (ret < 0) {
+               dev_err(tsd->dev, "clk_prepare failed: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+static const struct dev_pm_ops slink_pm_ops = {
+       SET_RUNTIME_PM_OPS(tegra_sflash_runtime_suspend,
+               tegra_sflash_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(tegra_sflash_suspend, tegra_sflash_resume)
+};
+static struct platform_driver tegra_sflash_driver = {
+       .driver = {
+               .name           = "spi-tegra-sflash",
+               .owner          = THIS_MODULE,
+               .pm             = &slink_pm_ops,
+               .of_match_table = of_match_ptr(tegra_sflash_of_match),
+       },
+       .probe =        tegra_sflash_probe,
+       .remove =       tegra_sflash_remove,
+};
+module_platform_driver(tegra_sflash_driver);
+
+MODULE_ALIAS("platform:spi-tegra-sflash");
+MODULE_DESCRIPTION("NVIDIA Tegra20 Serial Flash Controller Driver");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
new file mode 100644 (file)
index 0000000..651167f
--- /dev/null
@@ -0,0 +1,1358 @@
+/*
+ * SPI driver for Nvidia's Tegra20/Tegra30 SLINK Controller.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-tegra.h>
+#include <mach/clk.h>
+
+#define SLINK_COMMAND                  0x000
+#define SLINK_BIT_LENGTH(x)            (((x) & 0x1f) << 0)
+#define SLINK_WORD_SIZE(x)             (((x) & 0x1f) << 5)
+#define SLINK_BOTH_EN                  (1 << 10)
+#define SLINK_CS_SW                    (1 << 11)
+#define SLINK_CS_VALUE                 (1 << 12)
+#define SLINK_CS_POLARITY              (1 << 13)
+#define SLINK_IDLE_SDA_DRIVE_LOW       (0 << 16)
+#define SLINK_IDLE_SDA_DRIVE_HIGH      (1 << 16)
+#define SLINK_IDLE_SDA_PULL_LOW                (2 << 16)
+#define SLINK_IDLE_SDA_PULL_HIGH       (3 << 16)
+#define SLINK_IDLE_SDA_MASK            (3 << 16)
+#define SLINK_CS_POLARITY1             (1 << 20)
+#define SLINK_CK_SDA                   (1 << 21)
+#define SLINK_CS_POLARITY2             (1 << 22)
+#define SLINK_CS_POLARITY3             (1 << 23)
+#define SLINK_IDLE_SCLK_DRIVE_LOW      (0 << 24)
+#define SLINK_IDLE_SCLK_DRIVE_HIGH     (1 << 24)
+#define SLINK_IDLE_SCLK_PULL_LOW       (2 << 24)
+#define SLINK_IDLE_SCLK_PULL_HIGH      (3 << 24)
+#define SLINK_IDLE_SCLK_MASK           (3 << 24)
+#define SLINK_M_S                      (1 << 28)
+#define SLINK_WAIT                     (1 << 29)
+#define SLINK_GO                       (1 << 30)
+#define SLINK_ENB                      (1 << 31)
+
+#define SLINK_MODES                    (SLINK_IDLE_SCLK_MASK | SLINK_CK_SDA)
+
+#define SLINK_COMMAND2                 0x004
+#define SLINK_LSBFE                    (1 << 0)
+#define SLINK_SSOE                     (1 << 1)
+#define SLINK_SPIE                     (1 << 4)
+#define SLINK_BIDIROE                  (1 << 6)
+#define SLINK_MODFEN                   (1 << 7)
+#define SLINK_INT_SIZE(x)              (((x) & 0x1f) << 8)
+#define SLINK_CS_ACTIVE_BETWEEN                (1 << 17)
+#define SLINK_SS_EN_CS(x)              (((x) & 0x3) << 18)
+#define SLINK_SS_SETUP(x)              (((x) & 0x3) << 20)
+#define SLINK_FIFO_REFILLS_0           (0 << 22)
+#define SLINK_FIFO_REFILLS_1           (1 << 22)
+#define SLINK_FIFO_REFILLS_2           (2 << 22)
+#define SLINK_FIFO_REFILLS_3           (3 << 22)
+#define SLINK_FIFO_REFILLS_MASK                (3 << 22)
+#define SLINK_WAIT_PACK_INT(x)         (((x) & 0x7) << 26)
+#define SLINK_SPC0                     (1 << 29)
+#define SLINK_TXEN                     (1 << 30)
+#define SLINK_RXEN                     (1 << 31)
+
+#define SLINK_STATUS                   0x008
+#define SLINK_COUNT(val)               (((val) >> 0) & 0x1f)
+#define SLINK_WORD(val)                        (((val) >> 5) & 0x1f)
+#define SLINK_BLK_CNT(val)             (((val) >> 0) & 0xffff)
+#define SLINK_MODF                     (1 << 16)
+#define SLINK_RX_UNF                   (1 << 18)
+#define SLINK_TX_OVF                   (1 << 19)
+#define SLINK_TX_FULL                  (1 << 20)
+#define SLINK_TX_EMPTY                 (1 << 21)
+#define SLINK_RX_FULL                  (1 << 22)
+#define SLINK_RX_EMPTY                 (1 << 23)
+#define SLINK_TX_UNF                   (1 << 24)
+#define SLINK_RX_OVF                   (1 << 25)
+#define SLINK_TX_FLUSH                 (1 << 26)
+#define SLINK_RX_FLUSH                 (1 << 27)
+#define SLINK_SCLK                     (1 << 28)
+#define SLINK_ERR                      (1 << 29)
+#define SLINK_RDY                      (1 << 30)
+#define SLINK_BSY                      (1 << 31)
+#define SLINK_FIFO_ERROR               (SLINK_TX_OVF | SLINK_RX_UNF |  \
+                                       SLINK_TX_UNF | SLINK_RX_OVF)
+
+#define SLINK_FIFO_EMPTY               (SLINK_TX_EMPTY | SLINK_RX_EMPTY)
+
+#define SLINK_MAS_DATA                 0x010
+#define SLINK_SLAVE_DATA               0x014
+
+#define SLINK_DMA_CTL                  0x018
+#define SLINK_DMA_BLOCK_SIZE(x)                (((x) & 0xffff) << 0)
+#define SLINK_TX_TRIG_1                        (0 << 16)
+#define SLINK_TX_TRIG_4                        (1 << 16)
+#define SLINK_TX_TRIG_8                        (2 << 16)
+#define SLINK_TX_TRIG_16               (3 << 16)
+#define SLINK_TX_TRIG_MASK             (3 << 16)
+#define SLINK_RX_TRIG_1                        (0 << 18)
+#define SLINK_RX_TRIG_4                        (1 << 18)
+#define SLINK_RX_TRIG_8                        (2 << 18)
+#define SLINK_RX_TRIG_16               (3 << 18)
+#define SLINK_RX_TRIG_MASK             (3 << 18)
+#define SLINK_PACKED                   (1 << 20)
+#define SLINK_PACK_SIZE_4              (0 << 21)
+#define SLINK_PACK_SIZE_8              (1 << 21)
+#define SLINK_PACK_SIZE_16             (2 << 21)
+#define SLINK_PACK_SIZE_32             (3 << 21)
+#define SLINK_PACK_SIZE_MASK           (3 << 21)
+#define SLINK_IE_TXC                   (1 << 26)
+#define SLINK_IE_RXC                   (1 << 27)
+#define SLINK_DMA_EN                   (1 << 31)
+
+#define SLINK_STATUS2                  0x01c
+#define SLINK_TX_FIFO_EMPTY_COUNT(val) (((val) & 0x3f) >> 0)
+#define SLINK_RX_FIFO_FULL_COUNT(val)  (((val) & 0x3f0000) >> 16)
+#define SLINK_SS_HOLD_TIME(val)                (((val) & 0xF) << 6)
+
+#define SLINK_TX_FIFO                  0x100
+#define SLINK_RX_FIFO                  0x180
+
+#define DATA_DIR_TX                    (1 << 0)
+#define DATA_DIR_RX                    (1 << 1)
+
+#define SLINK_DMA_TIMEOUT              (msecs_to_jiffies(1000))
+
+#define DEFAULT_SPI_DMA_BUF_LEN                (16*1024)
+#define TX_FIFO_EMPTY_COUNT_MAX                SLINK_TX_FIFO_EMPTY_COUNT(0x20)
+#define RX_FIFO_FULL_COUNT_ZERO                SLINK_RX_FIFO_FULL_COUNT(0)
+
+#define SLINK_STATUS2_RESET \
+       (TX_FIFO_EMPTY_COUNT_MAX | RX_FIFO_FULL_COUNT_ZERO << 16)
+
+#define MAX_CHIP_SELECT                        4
+#define SLINK_FIFO_DEPTH               32
+
+struct tegra_slink_chip_data {
+       bool cs_hold_time;
+};
+
+struct tegra_slink_data {
+       struct device                           *dev;
+       struct spi_master                       *master;
+       const struct tegra_slink_chip_data      *chip_data;
+       spinlock_t                              lock;
+
+       struct clk                              *clk;
+       void __iomem                            *base;
+       phys_addr_t                             phys;
+       unsigned                                irq;
+       int                                     dma_req_sel;
+       u32                                     spi_max_frequency;
+       u32                                     cur_speed;
+
+       struct spi_device                       *cur_spi;
+       unsigned                                cur_pos;
+       unsigned                                cur_len;
+       unsigned                                words_per_32bit;
+       unsigned                                bytes_per_word;
+       unsigned                                curr_dma_words;
+       unsigned                                cur_direction;
+
+       unsigned                                cur_rx_pos;
+       unsigned                                cur_tx_pos;
+
+       unsigned                                dma_buf_size;
+       unsigned                                max_buf_size;
+       bool                                    is_curr_dma_xfer;
+       bool                                    is_hw_based_cs;
+
+       struct completion                       rx_dma_complete;
+       struct completion                       tx_dma_complete;
+
+       u32                                     tx_status;
+       u32                                     rx_status;
+       u32                                     status_reg;
+       bool                                    is_packed;
+       unsigned long                           packed_size;
+
+       u32                                     command_reg;
+       u32                                     command2_reg;
+       u32                                     dma_control_reg;
+       u32                                     def_command_reg;
+       u32                                     def_command2_reg;
+
+       struct completion                       xfer_completion;
+       struct spi_transfer                     *curr_xfer;
+       struct dma_chan                         *rx_dma_chan;
+       u32                                     *rx_dma_buf;
+       dma_addr_t                              rx_dma_phys;
+       struct dma_async_tx_descriptor          *rx_dma_desc;
+
+       struct dma_chan                         *tx_dma_chan;
+       u32                                     *tx_dma_buf;
+       dma_addr_t                              tx_dma_phys;
+       struct dma_async_tx_descriptor          *tx_dma_desc;
+};
+
+static int tegra_slink_runtime_suspend(struct device *dev);
+static int tegra_slink_runtime_resume(struct device *dev);
+
+static inline unsigned long tegra_slink_readl(struct tegra_slink_data *tspi,
+               unsigned long reg)
+{
+       return readl(tspi->base + reg);
+}
+
+static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
+               unsigned long val, unsigned long reg)
+{
+       writel(val, tspi->base + reg);
+
+       /* Read back register to make sure that register writes completed */
+       if (reg != SLINK_TX_FIFO)
+               readl(tspi->base + SLINK_MAS_DATA);
+}
+
+static void tegra_slink_clear_status(struct tegra_slink_data *tspi)
+{
+       unsigned long val;
+       unsigned long val_write = 0;
+
+       val = tegra_slink_readl(tspi, SLINK_STATUS);
+
+       /* Write 1 to clear status register */
+       val_write = SLINK_RDY | SLINK_FIFO_ERROR;
+       tegra_slink_writel(tspi, val_write, SLINK_STATUS);
+}
+
+static unsigned long tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
+                                 struct spi_transfer *t)
+{
+       unsigned long val;
+
+       switch (tspi->bytes_per_word) {
+       case 0:
+               val = SLINK_PACK_SIZE_4;
+               break;
+       case 1:
+               val = SLINK_PACK_SIZE_8;
+               break;
+       case 2:
+               val = SLINK_PACK_SIZE_16;
+               break;
+       case 4:
+               val = SLINK_PACK_SIZE_32;
+               break;
+       default:
+               val = 0;
+       }
+       return val;
+}
+
+static unsigned tegra_slink_calculate_curr_xfer_param(
+       struct spi_device *spi, struct tegra_slink_data *tspi,
+       struct spi_transfer *t)
+{
+       unsigned remain_len = t->len - tspi->cur_pos;
+       unsigned max_word;
+       unsigned bits_per_word ;
+       unsigned max_len;
+       unsigned total_fifo_words;
+
+       bits_per_word = t->bits_per_word ? t->bits_per_word :
+                                               spi->bits_per_word;
+       tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
+
+       if (bits_per_word == 8 || bits_per_word == 16) {
+               tspi->is_packed = 1;
+               tspi->words_per_32bit = 32/bits_per_word;
+       } else {
+               tspi->is_packed = 0;
+               tspi->words_per_32bit = 1;
+       }
+       tspi->packed_size = tegra_slink_get_packed_size(tspi, t);
+
+       if (tspi->is_packed) {
+               max_len = min(remain_len, tspi->max_buf_size);
+               tspi->curr_dma_words = max_len/tspi->bytes_per_word;
+               total_fifo_words = max_len/4;
+       } else {
+               max_word = (remain_len - 1) / tspi->bytes_per_word + 1;
+               max_word = min(max_word, tspi->max_buf_size/4);
+               tspi->curr_dma_words = max_word;
+               total_fifo_words = max_word;
+       }
+       return total_fifo_words;
+}
+
+static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
+       struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+       unsigned nbytes;
+       unsigned tx_empty_count;
+       unsigned long fifo_status;
+       unsigned max_n_32bit;
+       unsigned i, count;
+       unsigned long x;
+       unsigned int written_words;
+       unsigned fifo_words_left;
+       u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
+
+       fifo_status = tegra_slink_readl(tspi, SLINK_STATUS2);
+       tx_empty_count = SLINK_TX_FIFO_EMPTY_COUNT(fifo_status);
+
+       if (tspi->is_packed) {
+               fifo_words_left = tx_empty_count * tspi->words_per_32bit;
+               written_words = min(fifo_words_left, tspi->curr_dma_words);
+               nbytes = written_words * tspi->bytes_per_word;
+               max_n_32bit = DIV_ROUND_UP(nbytes, 4);
+               for (count = 0; count < max_n_32bit; count++) {
+                       x = 0;
+                       for (i = 0; (i < 4) && nbytes; i++, nbytes--)
+                               x |= (*tx_buf++) << (i*8);
+                       tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
+               }
+       } else {
+               max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
+               written_words = max_n_32bit;
+               nbytes = written_words * tspi->bytes_per_word;
+               for (count = 0; count < max_n_32bit; count++) {
+                       x = 0;
+                       for (i = 0; nbytes && (i < tspi->bytes_per_word);
+                                                       i++, nbytes--)
+                               x |= ((*tx_buf++) << i*8);
+                       tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
+               }
+       }
+       tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
+       return written_words;
+}
+
+static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
+               struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+       unsigned rx_full_count;
+       unsigned long fifo_status;
+       unsigned i, count;
+       unsigned long x;
+       unsigned int read_words = 0;
+       unsigned len;
+       u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
+
+       fifo_status = tegra_slink_readl(tspi, SLINK_STATUS2);
+       rx_full_count = SLINK_RX_FIFO_FULL_COUNT(fifo_status);
+       if (tspi->is_packed) {
+               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               for (count = 0; count < rx_full_count; count++) {
+                       x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+                       for (i = 0; len && (i < 4); i++, len--)
+                               *rx_buf++ = (x >> i*8) & 0xFF;
+               }
+               tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
+               read_words += tspi->curr_dma_words;
+       } else {
+               unsigned int bits_per_word;
+
+               bits_per_word = t->bits_per_word ? t->bits_per_word :
+                                               tspi->cur_spi->bits_per_word;
+               for (count = 0; count < rx_full_count; count++) {
+                       x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+                       for (i = 0; (i < tspi->bytes_per_word); i++)
+                               *rx_buf++ = (x >> (i*8)) & 0xFF;
+               }
+               tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word;
+               read_words += rx_full_count;
+       }
+       return read_words;
+}
+
+static void tegra_slink_copy_client_txbuf_to_spi_txbuf(
+               struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+       unsigned len;
+
+       /* Make the dma buffer to read by cpu */
+       dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
+                               tspi->dma_buf_size, DMA_TO_DEVICE);
+
+       if (tspi->is_packed) {
+               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
+       } else {
+               unsigned int i;
+               unsigned int count;
+               u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
+               unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned int x;
+
+               for (count = 0; count < tspi->curr_dma_words; count++) {
+                       x = 0;
+                       for (i = 0; consume && (i < tspi->bytes_per_word);
+                                                       i++, consume--)
+                               x |= ((*tx_buf++) << i * 8);
+                       tspi->tx_dma_buf[count] = x;
+               }
+       }
+       tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
+
+       /* Make the dma buffer to read by dma */
+       dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
+                               tspi->dma_buf_size, DMA_TO_DEVICE);
+}
+
+static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf(
+               struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+       unsigned len;
+
+       /* Make the dma buffer to read by cpu */
+       dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys,
+               tspi->dma_buf_size, DMA_FROM_DEVICE);
+
+       if (tspi->is_packed) {
+               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
+       } else {
+               unsigned int i;
+               unsigned int count;
+               unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
+               unsigned int x;
+               unsigned int rx_mask, bits_per_word;
+
+               bits_per_word = t->bits_per_word ? t->bits_per_word :
+                                               tspi->cur_spi->bits_per_word;
+               rx_mask = (1 << bits_per_word) - 1;
+               for (count = 0; count < tspi->curr_dma_words; count++) {
+                       x = tspi->rx_dma_buf[count];
+                       x &= rx_mask;
+                       for (i = 0; (i < tspi->bytes_per_word); i++)
+                               *rx_buf++ = (x >> (i*8)) & 0xFF;
+               }
+       }
+       tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
+
+       /* Make the dma buffer to read by dma */
+       dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
+               tspi->dma_buf_size, DMA_FROM_DEVICE);
+}
+
+static void tegra_slink_dma_complete(void *args)
+{
+       struct completion *dma_complete = args;
+
+       complete(dma_complete);
+}
+
+static int tegra_slink_start_tx_dma(struct tegra_slink_data *tspi, int len)
+{
+       INIT_COMPLETION(tspi->tx_dma_complete);
+       tspi->tx_dma_desc = dmaengine_prep_slave_single(tspi->tx_dma_chan,
+                               tspi->tx_dma_phys, len, DMA_MEM_TO_DEV,
+                               DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
+       if (!tspi->tx_dma_desc) {
+               dev_err(tspi->dev, "Not able to get desc for Tx\n");
+               return -EIO;
+       }
+
+       tspi->tx_dma_desc->callback = tegra_slink_dma_complete;
+       tspi->tx_dma_desc->callback_param = &tspi->tx_dma_complete;
+
+       dmaengine_submit(tspi->tx_dma_desc);
+       dma_async_issue_pending(tspi->tx_dma_chan);
+       return 0;
+}
+
+static int tegra_slink_start_rx_dma(struct tegra_slink_data *tspi, int len)
+{
+       INIT_COMPLETION(tspi->rx_dma_complete);
+       tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma_chan,
+                               tspi->rx_dma_phys, len, DMA_DEV_TO_MEM,
+                               DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
+       if (!tspi->rx_dma_desc) {
+               dev_err(tspi->dev, "Not able to get desc for Rx\n");
+               return -EIO;
+       }
+
+       tspi->rx_dma_desc->callback = tegra_slink_dma_complete;
+       tspi->rx_dma_desc->callback_param = &tspi->rx_dma_complete;
+
+       dmaengine_submit(tspi->rx_dma_desc);
+       dma_async_issue_pending(tspi->rx_dma_chan);
+       return 0;
+}
+
+static int tegra_slink_start_dma_based_transfer(
+               struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+       unsigned long val;
+       unsigned long test_val;
+       unsigned int len;
+       int ret = 0;
+       unsigned long status;
+
+       /* Make sure that Rx and Tx fifo are empty */
+       status = tegra_slink_readl(tspi, SLINK_STATUS);
+       if ((status & SLINK_FIFO_EMPTY) != SLINK_FIFO_EMPTY) {
+               dev_err(tspi->dev,
+                       "Rx/Tx fifo are not empty status 0x%08lx\n", status);
+               return -EIO;
+       }
+
+       val = SLINK_DMA_BLOCK_SIZE(tspi->curr_dma_words - 1);
+       val |= tspi->packed_size;
+       if (tspi->is_packed)
+               len = DIV_ROUND_UP(tspi->curr_dma_words * tspi->bytes_per_word,
+                                       4) * 4;
+       else
+               len = tspi->curr_dma_words * 4;
+
+       /* Set attention level based on length of transfer */
+       if (len & 0xF)
+               val |= SLINK_TX_TRIG_1 | SLINK_RX_TRIG_1;
+       else if (((len) >> 4) & 0x1)
+               val |= SLINK_TX_TRIG_4 | SLINK_RX_TRIG_4;
+       else
+               val |= SLINK_TX_TRIG_8 | SLINK_RX_TRIG_8;
+
+       if (tspi->cur_direction & DATA_DIR_TX)
+               val |= SLINK_IE_TXC;
+
+       if (tspi->cur_direction & DATA_DIR_RX)
+               val |= SLINK_IE_RXC;
+
+       tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+       tspi->dma_control_reg = val;
+
+       if (tspi->cur_direction & DATA_DIR_TX) {
+               tegra_slink_copy_client_txbuf_to_spi_txbuf(tspi, t);
+               wmb();
+               ret = tegra_slink_start_tx_dma(tspi, len);
+               if (ret < 0) {
+                       dev_err(tspi->dev,
+                               "Starting tx dma failed, err %d\n", ret);
+                       return ret;
+               }
+
+               /* Wait for tx fifo to be fill before starting slink */
+               test_val = tegra_slink_readl(tspi, SLINK_STATUS);
+               while (!(test_val & SLINK_TX_FULL))
+                       test_val = tegra_slink_readl(tspi, SLINK_STATUS);
+       }
+
+       if (tspi->cur_direction & DATA_DIR_RX) {
+               /* Make the dma buffer to read by dma */
+               dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
+                               tspi->dma_buf_size, DMA_FROM_DEVICE);
+
+               ret = tegra_slink_start_rx_dma(tspi, len);
+               if (ret < 0) {
+                       dev_err(tspi->dev,
+                               "Starting rx dma failed, err %d\n", ret);
+                       if (tspi->cur_direction & DATA_DIR_TX)
+                               dmaengine_terminate_all(tspi->tx_dma_chan);
+                       return ret;
+               }
+       }
+       tspi->is_curr_dma_xfer = true;
+       if (tspi->is_packed) {
+               val |= SLINK_PACKED;
+               tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+               /* HW need small delay after settign Packed mode */
+               udelay(1);
+       }
+       tspi->dma_control_reg = val;
+
+       val |= SLINK_DMA_EN;
+       tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+       return ret;
+}
+
+static int tegra_slink_start_cpu_based_transfer(
+               struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+       unsigned long val;
+       unsigned cur_words;
+
+       val = tspi->packed_size;
+       if (tspi->cur_direction & DATA_DIR_TX)
+               val |= SLINK_IE_TXC;
+
+       if (tspi->cur_direction & DATA_DIR_RX)
+               val |= SLINK_IE_RXC;
+
+       tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+       tspi->dma_control_reg = val;
+
+       if (tspi->cur_direction & DATA_DIR_TX)
+               cur_words = tegra_slink_fill_tx_fifo_from_client_txbuf(tspi, t);
+       else
+               cur_words = tspi->curr_dma_words;
+       val |= SLINK_DMA_BLOCK_SIZE(cur_words - 1);
+       tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+       tspi->dma_control_reg = val;
+
+       tspi->is_curr_dma_xfer = false;
+       if (tspi->is_packed) {
+               val |= SLINK_PACKED;
+               tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+               udelay(1);
+               wmb();
+       }
+       tspi->dma_control_reg = val;
+       val |= SLINK_DMA_EN;
+       tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+       return 0;
+}
+
+static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi,
+                       bool dma_to_memory)
+{
+       struct dma_chan *dma_chan;
+       u32 *dma_buf;
+       dma_addr_t dma_phys;
+       int ret;
+       struct dma_slave_config dma_sconfig;
+       dma_cap_mask_t mask;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       dma_chan = dma_request_channel(mask, NULL, NULL);
+       if (!dma_chan) {
+               dev_err(tspi->dev,
+                       "Dma channel is not available, will try later\n");
+               return -EPROBE_DEFER;
+       }
+
+       dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size,
+                               &dma_phys, GFP_KERNEL);
+       if (!dma_buf) {
+               dev_err(tspi->dev, " Not able to allocate the dma buffer\n");
+               dma_release_channel(dma_chan);
+               return -ENOMEM;
+       }
+
+       dma_sconfig.slave_id = tspi->dma_req_sel;
+       if (dma_to_memory) {
+               dma_sconfig.src_addr = tspi->phys + SLINK_RX_FIFO;
+               dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               dma_sconfig.src_maxburst = 0;
+       } else {
+               dma_sconfig.dst_addr = tspi->phys + SLINK_TX_FIFO;
+               dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               dma_sconfig.dst_maxburst = 0;
+       }
+
+       ret = dmaengine_slave_config(dma_chan, &dma_sconfig);
+       if (ret)
+               goto scrub;
+       if (dma_to_memory) {
+               tspi->rx_dma_chan = dma_chan;
+               tspi->rx_dma_buf = dma_buf;
+               tspi->rx_dma_phys = dma_phys;
+       } else {
+               tspi->tx_dma_chan = dma_chan;
+               tspi->tx_dma_buf = dma_buf;
+               tspi->tx_dma_phys = dma_phys;
+       }
+       return 0;
+
+scrub:
+       dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
+       dma_release_channel(dma_chan);
+       return ret;
+}
+
+static void tegra_slink_deinit_dma_param(struct tegra_slink_data *tspi,
+       bool dma_to_memory)
+{
+       u32 *dma_buf;
+       dma_addr_t dma_phys;
+       struct dma_chan *dma_chan;
+
+       if (dma_to_memory) {
+               dma_buf = tspi->rx_dma_buf;
+               dma_chan = tspi->rx_dma_chan;
+               dma_phys = tspi->rx_dma_phys;
+               tspi->rx_dma_chan = NULL;
+               tspi->rx_dma_buf = NULL;
+       } else {
+               dma_buf = tspi->tx_dma_buf;
+               dma_chan = tspi->tx_dma_chan;
+               dma_phys = tspi->tx_dma_phys;
+               tspi->tx_dma_buf = NULL;
+               tspi->tx_dma_chan = NULL;
+       }
+       if (!dma_chan)
+               return;
+
+       dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
+       dma_release_channel(dma_chan);
+}
+
+static int tegra_slink_start_transfer_one(struct spi_device *spi,
+               struct spi_transfer *t, bool is_first_of_msg,
+               bool is_single_xfer)
+{
+       struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
+       u32 speed;
+       u8 bits_per_word;
+       unsigned total_fifo_words;
+       int ret;
+       struct tegra_spi_device_controller_data *cdata = spi->controller_data;
+       unsigned long command;
+       unsigned long command2;
+
+       bits_per_word = t->bits_per_word;
+       speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+       if (!speed)
+               speed = tspi->spi_max_frequency;
+       if (speed != tspi->cur_speed) {
+               clk_set_rate(tspi->clk, speed * 4);
+               tspi->cur_speed = speed;
+       }
+
+       tspi->cur_spi = spi;
+       tspi->cur_pos = 0;
+       tspi->cur_rx_pos = 0;
+       tspi->cur_tx_pos = 0;
+       tspi->curr_xfer = t;
+       total_fifo_words = tegra_slink_calculate_curr_xfer_param(spi, tspi, t);
+
+       if (is_first_of_msg) {
+               tegra_slink_clear_status(tspi);
+
+               command = tspi->def_command_reg;
+               command |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+               command2 = tspi->def_command2_reg;
+               command2 |= SLINK_SS_EN_CS(spi->chip_select);
+
+               /* possibly use the hw based chip select */
+               tspi->is_hw_based_cs = false;
+               if (cdata && cdata->is_hw_based_cs && is_single_xfer &&
+                       ((tspi->curr_dma_words * tspi->bytes_per_word) ==
+                                               (t->len - tspi->cur_pos))) {
+                       int setup_count;
+                       int sts2;
+
+                       setup_count = cdata->cs_setup_clk_count >> 1;
+                       setup_count = max(setup_count, 3);
+                       command2 |= SLINK_SS_SETUP(setup_count);
+                       if (tspi->chip_data->cs_hold_time) {
+                               int hold_count;
+
+                               hold_count = cdata->cs_hold_clk_count;
+                               hold_count = max(hold_count, 0xF);
+                               sts2 = tegra_slink_readl(tspi, SLINK_STATUS2);
+                               sts2 &= ~SLINK_SS_HOLD_TIME(0xF);
+                               sts2 |= SLINK_SS_HOLD_TIME(hold_count);
+                               tegra_slink_writel(tspi, sts2, SLINK_STATUS2);
+                       }
+                       tspi->is_hw_based_cs = true;
+               }
+
+               if (tspi->is_hw_based_cs)
+                       command &= ~SLINK_CS_SW;
+               else
+                       command |= SLINK_CS_SW | SLINK_CS_VALUE;
+
+               command &= ~SLINK_MODES;
+               if (spi->mode & SPI_CPHA)
+                       command |= SLINK_CK_SDA;
+
+               if (spi->mode & SPI_CPOL)
+                       command |= SLINK_IDLE_SCLK_DRIVE_HIGH;
+               else
+                       command |= SLINK_IDLE_SCLK_DRIVE_LOW;
+       } else {
+               command = tspi->command_reg;
+               command &= ~SLINK_BIT_LENGTH(~0);
+               command |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+               command2 = tspi->command2_reg;
+               command2 &= ~(SLINK_RXEN | SLINK_TXEN);
+       }
+
+       tegra_slink_writel(tspi, command, SLINK_COMMAND);
+       tspi->command_reg = command;
+
+       tspi->cur_direction = 0;
+       if (t->rx_buf) {
+               command2 |= SLINK_RXEN;
+               tspi->cur_direction |= DATA_DIR_RX;
+       }
+       if (t->tx_buf) {
+               command2 |= SLINK_TXEN;
+               tspi->cur_direction |= DATA_DIR_TX;
+       }
+       tegra_slink_writel(tspi, command2, SLINK_COMMAND2);
+       tspi->command2_reg = command2;
+
+       if (total_fifo_words > SLINK_FIFO_DEPTH)
+               ret = tegra_slink_start_dma_based_transfer(tspi, t);
+       else
+               ret = tegra_slink_start_cpu_based_transfer(tspi, t);
+       return ret;
+}
+
+static int tegra_slink_setup(struct spi_device *spi)
+{
+       struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
+       unsigned long val;
+       unsigned long flags;
+       int ret;
+       unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
+                       SLINK_CS_POLARITY,
+                       SLINK_CS_POLARITY1,
+                       SLINK_CS_POLARITY2,
+                       SLINK_CS_POLARITY3,
+       };
+
+       dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
+               spi->bits_per_word,
+               spi->mode & SPI_CPOL ? "" : "~",
+               spi->mode & SPI_CPHA ? "" : "~",
+               spi->max_speed_hz);
+
+       BUG_ON(spi->chip_select >= MAX_CHIP_SELECT);
+
+       ret = pm_runtime_get_sync(tspi->dev);
+       if (ret < 0) {
+               dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
+               return ret;
+       }
+
+       spin_lock_irqsave(&tspi->lock, flags);
+       val = tspi->def_command_reg;
+       if (spi->mode & SPI_CS_HIGH)
+               val |= cs_pol_bit[spi->chip_select];
+       else
+               val &= ~cs_pol_bit[spi->chip_select];
+       tspi->def_command_reg = val;
+       tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
+       spin_unlock_irqrestore(&tspi->lock, flags);
+
+       pm_runtime_put(tspi->dev);
+       return 0;
+}
+
+static int tegra_slink_prepare_transfer(struct spi_master *master)
+{
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+       return pm_runtime_get_sync(tspi->dev);
+}
+
+static int tegra_slink_unprepare_transfer(struct spi_master *master)
+{
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+       pm_runtime_put(tspi->dev);
+       return 0;
+}
+
+static int tegra_slink_transfer_one_message(struct spi_master *master,
+                       struct spi_message *msg)
+{
+       bool is_first_msg = true;
+       int single_xfer;
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+       struct spi_transfer *xfer;
+       struct spi_device *spi = msg->spi;
+       int ret;
+
+       msg->status = 0;
+       msg->actual_length = 0;
+       single_xfer = list_is_singular(&msg->transfers);
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               INIT_COMPLETION(tspi->xfer_completion);
+               ret = tegra_slink_start_transfer_one(spi, xfer,
+                                       is_first_msg, single_xfer);
+               if (ret < 0) {
+                       dev_err(tspi->dev,
+                               "spi can not start transfer, err %d\n", ret);
+                       goto exit;
+               }
+               is_first_msg = false;
+               ret = wait_for_completion_timeout(&tspi->xfer_completion,
+                                               SLINK_DMA_TIMEOUT);
+               if (WARN_ON(ret == 0)) {
+                       dev_err(tspi->dev,
+                               "spi trasfer timeout, err %d\n", ret);
+                       ret = -EIO;
+                       goto exit;
+               }
+
+               if (tspi->tx_status ||  tspi->rx_status) {
+                       dev_err(tspi->dev, "Error in Transfer\n");
+                       ret = -EIO;
+                       goto exit;
+               }
+               msg->actual_length += xfer->len;
+               if (xfer->cs_change && xfer->delay_usecs) {
+                       tegra_slink_writel(tspi, tspi->def_command_reg,
+                                       SLINK_COMMAND);
+                       udelay(xfer->delay_usecs);
+               }
+       }
+       ret = 0;
+exit:
+       tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
+       tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
+       msg->status = ret;
+       spi_finalize_current_message(master);
+       return ret;
+}
+
+static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi)
+{
+       struct spi_transfer *t = tspi->curr_xfer;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tspi->lock, flags);
+       if (tspi->tx_status ||  tspi->rx_status ||
+                               (tspi->status_reg & SLINK_BSY)) {
+               dev_err(tspi->dev,
+                       "CpuXfer ERROR bit set 0x%x\n", tspi->status_reg);
+               dev_err(tspi->dev,
+                       "CpuXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg,
+                               tspi->command2_reg, tspi->dma_control_reg);
+               tegra_periph_reset_assert(tspi->clk);
+               udelay(2);
+               tegra_periph_reset_deassert(tspi->clk);
+               complete(&tspi->xfer_completion);
+               goto exit;
+       }
+
+       if (tspi->cur_direction & DATA_DIR_RX)
+               tegra_slink_read_rx_fifo_to_client_rxbuf(tspi, t);
+
+       if (tspi->cur_direction & DATA_DIR_TX)
+               tspi->cur_pos = tspi->cur_tx_pos;
+       else
+               tspi->cur_pos = tspi->cur_rx_pos;
+
+       if (tspi->cur_pos == t->len) {
+               complete(&tspi->xfer_completion);
+               goto exit;
+       }
+
+       tegra_slink_calculate_curr_xfer_param(tspi->cur_spi, tspi, t);
+       tegra_slink_start_cpu_based_transfer(tspi, t);
+exit:
+       spin_unlock_irqrestore(&tspi->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t handle_dma_based_xfer(struct tegra_slink_data *tspi)
+{
+       struct spi_transfer *t = tspi->curr_xfer;
+       long wait_status;
+       int err = 0;
+       unsigned total_fifo_words;
+       unsigned long flags;
+
+       /* Abort dmas if any error */
+       if (tspi->cur_direction & DATA_DIR_TX) {
+               if (tspi->tx_status) {
+                       dmaengine_terminate_all(tspi->tx_dma_chan);
+                       err += 1;
+               } else {
+                       wait_status = wait_for_completion_interruptible_timeout(
+                               &tspi->tx_dma_complete, SLINK_DMA_TIMEOUT);
+                       if (wait_status <= 0) {
+                               dmaengine_terminate_all(tspi->tx_dma_chan);
+                               dev_err(tspi->dev, "TxDma Xfer failed\n");
+                               err += 1;
+                       }
+               }
+       }
+
+       if (tspi->cur_direction & DATA_DIR_RX) {
+               if (tspi->rx_status) {
+                       dmaengine_terminate_all(tspi->rx_dma_chan);
+                       err += 2;
+               } else {
+                       wait_status = wait_for_completion_interruptible_timeout(
+                               &tspi->rx_dma_complete, SLINK_DMA_TIMEOUT);
+                       if (wait_status <= 0) {
+                               dmaengine_terminate_all(tspi->rx_dma_chan);
+                               dev_err(tspi->dev, "RxDma Xfer failed\n");
+                               err += 2;
+                       }
+               }
+       }
+
+       spin_lock_irqsave(&tspi->lock, flags);
+       if (err) {
+               dev_err(tspi->dev,
+                       "DmaXfer: ERROR bit set 0x%x\n", tspi->status_reg);
+               dev_err(tspi->dev,
+                       "DmaXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg,
+                               tspi->command2_reg, tspi->dma_control_reg);
+               tegra_periph_reset_assert(tspi->clk);
+               udelay(2);
+               tegra_periph_reset_deassert(tspi->clk);
+               complete(&tspi->xfer_completion);
+               spin_unlock_irqrestore(&tspi->lock, flags);
+               return IRQ_HANDLED;
+       }
+
+       if (tspi->cur_direction & DATA_DIR_RX)
+               tegra_slink_copy_spi_rxbuf_to_client_rxbuf(tspi, t);
+
+       if (tspi->cur_direction & DATA_DIR_TX)
+               tspi->cur_pos = tspi->cur_tx_pos;
+       else
+               tspi->cur_pos = tspi->cur_rx_pos;
+
+       if (tspi->cur_pos == t->len) {
+               complete(&tspi->xfer_completion);
+               goto exit;
+       }
+
+       /* Continue transfer in current message */
+       total_fifo_words = tegra_slink_calculate_curr_xfer_param(tspi->cur_spi,
+                                                       tspi, t);
+       if (total_fifo_words > SLINK_FIFO_DEPTH)
+               err = tegra_slink_start_dma_based_transfer(tspi, t);
+       else
+               err = tegra_slink_start_cpu_based_transfer(tspi, t);
+
+exit:
+       spin_unlock_irqrestore(&tspi->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t tegra_slink_isr_thread(int irq, void *context_data)
+{
+       struct tegra_slink_data *tspi = context_data;
+
+       if (!tspi->is_curr_dma_xfer)
+               return handle_cpu_based_xfer(tspi);
+       return handle_dma_based_xfer(tspi);
+}
+
+static irqreturn_t tegra_slink_isr(int irq, void *context_data)
+{
+       struct tegra_slink_data *tspi = context_data;
+
+       tspi->status_reg = tegra_slink_readl(tspi, SLINK_STATUS);
+       if (tspi->cur_direction & DATA_DIR_TX)
+               tspi->tx_status = tspi->status_reg &
+                                       (SLINK_TX_OVF | SLINK_TX_UNF);
+
+       if (tspi->cur_direction & DATA_DIR_RX)
+               tspi->rx_status = tspi->status_reg &
+                                       (SLINK_RX_OVF | SLINK_RX_UNF);
+       tegra_slink_clear_status(tspi);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static struct tegra_spi_platform_data *tegra_slink_parse_dt(
+               struct platform_device *pdev)
+{
+       struct tegra_spi_platform_data *pdata;
+       const unsigned int *prop;
+       struct device_node *np = pdev->dev.of_node;
+       u32 of_dma[2];
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "Memory alloc for pdata failed\n");
+               return NULL;
+       }
+
+       if (of_property_read_u32_array(np, "nvidia,dma-request-selector",
+                               of_dma, 2) >= 0)
+               pdata->dma_req_sel = of_dma[1];
+
+       prop = of_get_property(np, "spi-max-frequency", NULL);
+       if (prop)
+               pdata->spi_max_frequency = be32_to_cpup(prop);
+
+       return pdata;
+}
+
+const struct tegra_slink_chip_data tegra30_spi_cdata = {
+       .cs_hold_time = true,
+};
+
+const struct tegra_slink_chip_data tegra20_spi_cdata = {
+       .cs_hold_time = false,
+};
+
+static struct of_device_id tegra_slink_of_match[] = {
+       { .compatible = "nvidia,tegra30-slink", .data = &tegra30_spi_cdata, },
+       { .compatible = "nvidia,tegra20-slink", .data = &tegra20_spi_cdata, },
+       {}
+};
+MODULE_DEVICE_TABLE(of, tegra_slink_of_match);
+
+static int tegra_slink_probe(struct platform_device *pdev)
+{
+       struct spi_master       *master;
+       struct tegra_slink_data *tspi;
+       struct resource         *r;
+       struct tegra_spi_platform_data *pdata = pdev->dev.platform_data;
+       int ret, spi_irq;
+       const struct tegra_slink_chip_data *cdata = NULL;
+       const struct of_device_id *match;
+
+       match = of_match_device(of_match_ptr(tegra_slink_of_match), &pdev->dev);
+       if (!match) {
+               dev_err(&pdev->dev, "Error: No device match found\n");
+               return -ENODEV;
+       }
+       cdata = match->data;
+       if (!pdata && pdev->dev.of_node)
+               pdata = tegra_slink_parse_dt(pdev);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data, exiting\n");
+               return -ENODEV;
+       }
+
+       if (!pdata->spi_max_frequency)
+               pdata->spi_max_frequency = 25000000; /* 25MHz */
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*tspi));
+       if (!master) {
+               dev_err(&pdev->dev, "master allocation failed\n");
+               return -ENOMEM;
+       }
+
+       /* the spi->mode bits understood by this driver: */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->setup = tegra_slink_setup;
+       master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
+       master->transfer_one_message = tegra_slink_transfer_one_message;
+       master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
+       master->num_chipselect = MAX_CHIP_SELECT;
+       master->bus_num = -1;
+
+       dev_set_drvdata(&pdev->dev, master);
+       tspi = spi_master_get_devdata(master);
+       tspi->master = master;
+       tspi->dma_req_sel = pdata->dma_req_sel;
+       tspi->dev = &pdev->dev;
+       tspi->chip_data = cdata;
+       spin_lock_init(&tspi->lock);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               dev_err(&pdev->dev, "No IO memory resource\n");
+               ret = -ENODEV;
+               goto exit_free_master;
+       }
+       tspi->phys = r->start;
+       tspi->base = devm_request_and_ioremap(&pdev->dev, r);
+       if (!tspi->base) {
+               dev_err(&pdev->dev,
+                       "Cannot request memregion/iomap dma address\n");
+               ret = -EADDRNOTAVAIL;
+               goto exit_free_master;
+       }
+
+       spi_irq = platform_get_irq(pdev, 0);
+       tspi->irq = spi_irq;
+       ret = request_threaded_irq(tspi->irq, tegra_slink_isr,
+                       tegra_slink_isr_thread, IRQF_ONESHOT,
+                       dev_name(&pdev->dev), tspi);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
+                                       tspi->irq);
+               goto exit_free_master;
+       }
+
+       tspi->clk = devm_clk_get(&pdev->dev, "slink");
+       if (IS_ERR(tspi->clk)) {
+               dev_err(&pdev->dev, "can not get clock\n");
+               ret = PTR_ERR(tspi->clk);
+               goto exit_free_irq;
+       }
+
+       tspi->max_buf_size = SLINK_FIFO_DEPTH << 2;
+       tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
+       tspi->spi_max_frequency = pdata->spi_max_frequency;
+
+       if (pdata->dma_req_sel) {
+               ret = tegra_slink_init_dma_param(tspi, true);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret);
+                       goto exit_free_irq;
+               }
+
+               ret = tegra_slink_init_dma_param(tspi, false);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "TxDma Init failed, err %d\n", ret);
+                       goto exit_rx_dma_free;
+               }
+               tspi->max_buf_size = tspi->dma_buf_size;
+               init_completion(&tspi->tx_dma_complete);
+               init_completion(&tspi->rx_dma_complete);
+       }
+
+       init_completion(&tspi->xfer_completion);
+
+       pm_runtime_enable(&pdev->dev);
+       if (!pm_runtime_enabled(&pdev->dev)) {
+               ret = tegra_slink_runtime_resume(&pdev->dev);
+               if (ret)
+                       goto exit_pm_disable;
+       }
+
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
+               goto exit_pm_disable;
+       }
+       tspi->def_command_reg  = SLINK_M_S;
+       tspi->def_command2_reg = SLINK_CS_ACTIVE_BETWEEN;
+       tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
+       tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
+       pm_runtime_put(&pdev->dev);
+
+       master->dev.of_node = pdev->dev.of_node;
+       ret = spi_register_master(master);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+               goto exit_pm_disable;
+       }
+       return ret;
+
+exit_pm_disable:
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               tegra_slink_runtime_suspend(&pdev->dev);
+       tegra_slink_deinit_dma_param(tspi, false);
+exit_rx_dma_free:
+       tegra_slink_deinit_dma_param(tspi, true);
+exit_free_irq:
+       free_irq(spi_irq, tspi);
+exit_free_master:
+       spi_master_put(master);
+       return ret;
+}
+
+static int tegra_slink_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = dev_get_drvdata(&pdev->dev);
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+       free_irq(tspi->irq, tspi);
+       spi_unregister_master(master);
+
+       if (tspi->tx_dma_chan)
+               tegra_slink_deinit_dma_param(tspi, false);
+
+       if (tspi->rx_dma_chan)
+               tegra_slink_deinit_dma_param(tspi, true);
+
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               tegra_slink_runtime_suspend(&pdev->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_slink_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+
+       return spi_master_suspend(master);
+}
+
+static int tegra_slink_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+       int ret;
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0) {
+               dev_err(dev, "pm runtime failed, e = %d\n", ret);
+               return ret;
+       }
+       tegra_slink_writel(tspi, tspi->command_reg, SLINK_COMMAND);
+       tegra_slink_writel(tspi, tspi->command2_reg, SLINK_COMMAND2);
+       pm_runtime_put(dev);
+
+       return spi_master_resume(master);
+}
+#endif
+
+static int tegra_slink_runtime_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+       /* Flush all write which are in PPSB queue by reading back */
+       tegra_slink_readl(tspi, SLINK_MAS_DATA);
+
+       clk_disable_unprepare(tspi->clk);
+       return 0;
+}
+
+static int tegra_slink_runtime_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+       int ret;
+
+       ret = clk_prepare_enable(tspi->clk);
+       if (ret < 0) {
+               dev_err(tspi->dev, "clk_prepare failed: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+static const struct dev_pm_ops slink_pm_ops = {
+       SET_RUNTIME_PM_OPS(tegra_slink_runtime_suspend,
+               tegra_slink_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(tegra_slink_suspend, tegra_slink_resume)
+};
+static struct platform_driver tegra_slink_driver = {
+       .driver = {
+               .name           = "spi-tegra-slink",
+               .owner          = THIS_MODULE,
+               .pm             = &slink_pm_ops,
+               .of_match_table = of_match_ptr(tegra_slink_of_match),
+       },
+       .probe =        tegra_slink_probe,
+       .remove =       tegra_slink_remove,
+};
+module_platform_driver(tegra_slink_driver);
+
+MODULE_ALIAS("platform:spi-tegra-slink");
+MODULE_DESCRIPTION("NVIDIA Tegra20/Tegra30 SLINK Controller Driver");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
index 3f6f6e81c65553a61bb146b66725b7473b5e5115..46992cab65f1c2a949716f02351d70e656adc219 100644 (file)
@@ -289,7 +289,7 @@ error_unlock:
        return error;
 }
 
-static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
+static int ti_ssp_spi_probe(struct platform_device *pdev)
 {
        const struct ti_ssp_spi_data *pdata;
        struct ti_ssp_spi *hw;
@@ -357,7 +357,7 @@ error_wq:
        return error;
 }
 
-static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
+static int ti_ssp_spi_remove(struct platform_device *pdev)
 {
        struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
        int error;
@@ -378,7 +378,7 @@ static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
 
 static struct platform_driver ti_ssp_spi_driver = {
        .probe          = ti_ssp_spi_probe,
-       .remove         = __devexit_p(ti_ssp_spi_remove),
+       .remove         = ti_ssp_spi_remove,
        .driver         = {
                .name   = "ti-ssp-spi",
                .owner  = THIS_MODULE,
index 24421024deaf6d6bd19b3da4063ba932f5a3ddb8..6b0874d782ed7aa1c9cd569637500e12a1d74dd1 100644 (file)
@@ -240,7 +240,7 @@ static int to_gpio_num(struct device_attribute *attr)
        return -1;
 }
 
-static int __devinit tle62x0_probe(struct spi_device *spi)
+static int tle62x0_probe(struct spi_device *spi)
 {
        struct tle62x0_state *st;
        struct tle62x0_pdata *pdata;
@@ -294,7 +294,7 @@ static int __devinit tle62x0_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit tle62x0_remove(struct spi_device *spi)
+static int tle62x0_remove(struct spi_device *spi)
 {
        struct tle62x0_state *st = spi_get_drvdata(spi);
        int ptr;
@@ -313,7 +313,7 @@ static struct spi_driver tle62x0_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tle62x0_probe,
-       .remove         = __devexit_p(tle62x0_remove),
+       .remove         = tle62x0_remove,
 };
 
 module_spi_driver(tle62x0_driver);
index 135f7406f4bfc3e34e37d39f76577e6089288bef..f756481b0fea7fd99af96622d04bb248436454cf 100644 (file)
@@ -1401,7 +1401,7 @@ static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
                                PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL);
 }
 
-static int __devinit pch_spi_pd_probe(struct platform_device *plat_dev)
+static int pch_spi_pd_probe(struct platform_device *plat_dev)
 {
        int ret;
        struct spi_master *master;
@@ -1498,7 +1498,7 @@ err_pci_iomap:
        return ret;
 }
 
-static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
+static int pch_spi_pd_remove(struct platform_device *plat_dev)
 {
        struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
        struct pch_spi_data *data = platform_get_drvdata(plat_dev);
@@ -1619,12 +1619,12 @@ static struct platform_driver pch_spi_pd_driver = {
                .owner = THIS_MODULE,
        },
        .probe = pch_spi_pd_probe,
-       .remove = __devexit_p(pch_spi_pd_remove),
+       .remove = pch_spi_pd_remove,
        .suspend = pch_spi_pd_suspend,
        .resume = pch_spi_pd_resume
 };
 
-static int __devinit pch_spi_probe(struct pci_dev *pdev,
+static int pch_spi_probe(struct pci_dev *pdev,
                                   const struct pci_device_id *id)
 {
        struct pch_spi_board_data *board_dat;
@@ -1705,7 +1705,7 @@ err_no_mem:
        return retval;
 }
 
-static void __devexit pch_spi_remove(struct pci_dev *pdev)
+static void pch_spi_remove(struct pci_dev *pdev)
 {
        int i;
        struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
@@ -1776,7 +1776,7 @@ static struct pci_driver pch_spi_pcidev_driver = {
        .name = "pch_spi",
        .id_table = pch_spi_pcidev_id,
        .probe = pch_spi_probe,
-       .remove = __devexit_p(pch_spi_remove),
+       .remove = pch_spi_remove,
        .suspend = pch_spi_suspend,
        .resume = pch_spi_resume,
 };
index 266a847e2992d372f4e216219b9387478a3c19bc..4d3ec8b9f4791cd2df02b0ec7a715af5e3ae7515 100644 (file)
@@ -217,7 +217,7 @@ static int spi_xcomm_setup(struct spi_device *spi)
        return 0;
 }
 
-static int __devinit spi_xcomm_probe(struct i2c_client *i2c,
+static int spi_xcomm_probe(struct i2c_client *i2c,
        const struct i2c_device_id *id)
 {
        struct spi_xcomm *spi_xcomm;
@@ -246,7 +246,7 @@ static int __devinit spi_xcomm_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit spi_xcomm_remove(struct i2c_client *i2c)
+static int spi_xcomm_remove(struct i2c_client *i2c)
 {
        struct spi_master *master = i2c_get_clientdata(i2c);
 
@@ -267,7 +267,7 @@ static struct i2c_driver spi_xcomm_driver = {
        },
        .id_table       = spi_xcomm_ids,
        .probe          = spi_xcomm_probe,
-       .remove         = __devexit_p(spi_xcomm_remove),
+       .remove         = spi_xcomm_remove,
 };
 module_i2c_driver(spi_xcomm_driver);
 
index 4c5a663b9fa897e4a510f6cf6dbba084efc6bfb6..e1d7696074253d9a76a1c1744ad94f973ba96616 100644 (file)
@@ -462,7 +462,7 @@ void xilinx_spi_deinit(struct spi_master *master)
 }
 EXPORT_SYMBOL(xilinx_spi_deinit);
 
-static int __devinit xilinx_spi_probe(struct platform_device *dev)
+static int xilinx_spi_probe(struct platform_device *dev)
 {
        struct xspi_platform_data *pdata;
        struct resource *r;
@@ -518,7 +518,7 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
+static int xilinx_spi_remove(struct platform_device *dev)
 {
        xilinx_spi_deinit(platform_get_drvdata(dev));
        platform_set_drvdata(dev, 0);
@@ -531,7 +531,7 @@ MODULE_ALIAS("platform:" XILINX_SPI_NAME);
 
 static struct platform_driver xilinx_spi_driver = {
        .probe = xilinx_spi_probe,
-       .remove = __devexit_p(xilinx_spi_remove),
+       .remove = xilinx_spi_remove,
        .driver = {
                .name = XILINX_SPI_NAME,
                .owner = THIS_MODULE,
index 718cc1f49230dded795bc309b231d957ec9c7068..ab095acdb2a8c17e1945652a3dd647ef7cef468a 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
+#include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/export.h>
 #include <linux/sched.h>
@@ -333,6 +334,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
        spi->dev.parent = &master->dev;
        spi->dev.bus = &spi_bus_type;
        spi->dev.release = spidev_release;
+       spi->cs_gpio = -EINVAL;
        device_initialize(&spi->dev);
        return spi;
 }
@@ -350,15 +352,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
 int spi_add_device(struct spi_device *spi)
 {
        static DEFINE_MUTEX(spi_add_lock);
-       struct device *dev = spi->master->dev.parent;
+       struct spi_master *master = spi->master;
+       struct device *dev = master->dev.parent;
        struct device *d;
        int status;
 
        /* Chipselects are numbered 0..max; validate. */
-       if (spi->chip_select >= spi->master->num_chipselect) {
+       if (spi->chip_select >= master->num_chipselect) {
                dev_err(dev, "cs%d >= max %d\n",
                        spi->chip_select,
-                       spi->master->num_chipselect);
+                       master->num_chipselect);
                return -EINVAL;
        }
 
@@ -382,6 +385,9 @@ int spi_add_device(struct spi_device *spi)
                goto done;
        }
 
+       if (master->cs_gpios)
+               spi->cs_gpio = master->cs_gpios[spi->chip_select];
+
        /* Drivers may modify this initial i/o setup, but will
         * normally rely on the device being setup.  Devices
         * using SPI_CS_HIGH can't coexist well otherwise...
@@ -492,8 +498,7 @@ static void spi_match_master_to_boardinfo(struct spi_master *master,
  * The board info passed can safely be __initdata ... but be careful of
  * any embedded pointers (platform_data, etc), they're copied as-is.
  */
-int __devinit
-spi_register_board_info(struct spi_board_info const *info, unsigned n)
+int spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
        struct boardinfo *bi;
        int i;
@@ -806,7 +811,7 @@ err_init_queue:
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_OF) && !defined(CONFIG_SPARC)
+#if defined(CONFIG_OF)
 /**
  * of_register_spi_devices() - Register child devices onto the SPI bus
  * @master:    Pointer to spi_master device
@@ -861,6 +866,8 @@ static void of_register_spi_devices(struct spi_master *master)
                        spi->mode |= SPI_CPOL;
                if (of_find_property(nc, "spi-cs-high", NULL))
                        spi->mode |= SPI_CS_HIGH;
+               if (of_find_property(nc, "spi-3wire", NULL))
+                       spi->mode |= SPI_3WIRE;
 
                /* Device speed */
                prop = of_get_property(nc, "spi-max-frequency", &len);
@@ -1046,6 +1053,44 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
 }
 EXPORT_SYMBOL_GPL(spi_alloc_master);
 
+#ifdef CONFIG_OF
+static int of_spi_register_master(struct spi_master *master)
+{
+       u16 nb;
+       int i, *cs;
+       struct device_node *np = master->dev.of_node;
+
+       if (!np)
+               return 0;
+
+       nb = of_gpio_named_count(np, "cs-gpios");
+       master->num_chipselect = max(nb, master->num_chipselect);
+
+       if (nb < 1)
+               return 0;
+
+       cs = devm_kzalloc(&master->dev,
+                         sizeof(int) * master->num_chipselect,
+                         GFP_KERNEL);
+       master->cs_gpios = cs;
+
+       if (!master->cs_gpios)
+               return -ENOMEM;
+
+       memset(cs, -EINVAL, master->num_chipselect);
+
+       for (i = 0; i < nb; i++)
+               cs[i] = of_get_named_gpio(np, "cs-gpios", i);
+
+       return 0;
+}
+#else
+static int of_spi_register_master(struct spi_master *master)
+{
+       return 0;
+}
+#endif
+
 /**
  * spi_register_master - register SPI master controller
  * @master: initialized master, originally from spi_alloc_master()
@@ -1077,6 +1122,10 @@ int spi_register_master(struct spi_master *master)
        if (!dev)
                return -ENODEV;
 
+       status = of_spi_register_master(master);
+       if (status)
+               return status;
+
        /* even if it's just one always-selected device, there must
         * be at least one chipselect
         */
@@ -1257,7 +1306,7 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
 int spi_setup(struct spi_device *spi)
 {
        unsigned        bad_bits;
-       int             status;
+       int             status = 0;
 
        /* help drivers fail *cleanly* when they need options
         * that aren't supported with their current master
@@ -1272,7 +1321,8 @@ int spi_setup(struct spi_device *spi)
        if (!spi->bits_per_word)
                spi->bits_per_word = 8;
 
-       status = spi->master->setup(spi);
+       if (spi->master->setup)
+               status = spi->master->setup(spi);
 
        dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
                                "%u bits/w, %u Hz max --> %d\n",
@@ -1291,6 +1341,7 @@ EXPORT_SYMBOL_GPL(spi_setup);
 static int __spi_async(struct spi_device *spi, struct spi_message *message)
 {
        struct spi_master *master = spi->master;
+       struct spi_transfer *xfer;
 
        /* Half-duplex links include original MicroWire, and ones with
         * only one data pin like SPI_3WIRE (switches direction) or where
@@ -1299,7 +1350,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
         */
        if ((master->flags & SPI_MASTER_HALF_DUPLEX)
                        || (spi->mode & SPI_3WIRE)) {
-               struct spi_transfer *xfer;
                unsigned flags = master->flags;
 
                list_for_each_entry(xfer, &message->transfers, transfer_list) {
@@ -1312,6 +1362,15 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                }
        }
 
+       /**
+        * Set transfer bits_per_word as spi device default if it is not
+        * set for this transfer.
+        */
+       list_for_each_entry(xfer, &message->transfers, transfer_list) {
+               if (!xfer->bits_per_word)
+                       xfer->bits_per_word = spi->bits_per_word;
+       }
+
        message->spi = spi;
        message->status = -EINPROGRESS;
        return master->transfer(spi, message);
@@ -1588,12 +1647,18 @@ int spi_write_then_read(struct spi_device *spi,
        struct spi_transfer     x[2];
        u8                      *local_buf;
 
-       /* Use preallocated DMA-safe buffer.  We can't avoid copying here,
-        * (as a pure convenience thing), but we can keep heap costs
-        * out of the hot path ...
+       /* Use preallocated DMA-safe buffer if we can.  We can't avoid
+        * copying here, (as a pure convenience thing), but we can
+        * keep heap costs out of the hot path unless someone else is
+        * using the pre-allocated buffer or the transfer is too large.
         */
-       if ((n_tx + n_rx) > SPI_BUFSIZ)
-               return -EINVAL;
+       if ((n_tx + n_rx) > SPI_BUFSIZ || !mutex_trylock(&lock)) {
+               local_buf = kmalloc(max((unsigned)SPI_BUFSIZ, n_tx + n_rx), GFP_KERNEL);
+               if (!local_buf)
+                       return -ENOMEM;
+       } else {
+               local_buf = buf;
+       }
 
        spi_message_init(&message);
        memset(x, 0, sizeof x);
@@ -1606,14 +1671,6 @@ int spi_write_then_read(struct spi_device *spi,
                spi_message_add_tail(&x[1], &message);
        }
 
-       /* ... unless someone else is using the pre-allocated buffer */
-       if (!mutex_trylock(&lock)) {
-               local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
-               if (!local_buf)
-                       return -ENOMEM;
-       } else
-               local_buf = buf;
-
        memcpy(local_buf, txbuf, n_tx);
        x[0].tx_buf = local_buf;
        x[1].rx_buf = local_buf + n_tx;
index 830adbed1d7ace083697312cf4ed585606c4a35b..2e0655dbe07040a25eb2d3c6b79d05a3e647bf20 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/compat.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spidev.h>
@@ -571,7 +573,7 @@ static struct class *spidev_class;
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit spidev_probe(struct spi_device *spi)
+static int spidev_probe(struct spi_device *spi)
 {
        struct spidev_data      *spidev;
        int                     status;
@@ -620,7 +622,7 @@ static int __devinit spidev_probe(struct spi_device *spi)
        return status;
 }
 
-static int __devexit spidev_remove(struct spi_device *spi)
+static int spidev_remove(struct spi_device *spi)
 {
        struct spidev_data      *spidev = spi_get_drvdata(spi);
 
@@ -642,13 +644,21 @@ static int __devexit spidev_remove(struct spi_device *spi)
        return 0;
 }
 
+static const struct of_device_id spidev_dt_ids[] = {
+       { .compatible = "rohm,dh2228fv" },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, spidev_dt_ids);
+
 static struct spi_driver spidev_spi_driver = {
        .driver = {
                .name =         "spidev",
                .owner =        THIS_MODULE,
+               .of_match_table = of_match_ptr(spidev_dt_ids),
        },
        .probe =        spidev_probe,
-       .remove =       __devexit_p(spidev_remove),
+       .remove =       spidev_remove,
 
        /* NOTE:  suspend/resume methods are not necessary here.
         * We don't do anything except pass the requests to/from
index 42cdaa9a4d8af3ca2587c2b6db269e4495c4b55a..ff3c8a21f10d90397dc9fda07b99dcfb08ebc9b9 100644 (file)
@@ -160,4 +160,13 @@ config SSB_DRIVER_GIGE
 
          If unsure, say N
 
+config SSB_DRIVER_GPIO
+       bool "SSB GPIO driver"
+       depends on SSB
+       select GPIOLIB
+       help
+         Driver to provide access to the GPIO pins on the bus.
+
+         If unsure, say N
+
 endmenu
index 656e58b926189d9741a4039933f864a9d78f7fb8..9159ba77c388086a06196767da05d87150d3aacd 100644 (file)
@@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS)         += driver_mipscore.o
 ssb-$(CONFIG_SSB_DRIVER_EXTIF)         += driver_extif.o
 ssb-$(CONFIG_SSB_DRIVER_PCICORE)       += driver_pcicore.o
 ssb-$(CONFIG_SSB_DRIVER_GIGE)          += driver_gige.o
+ssb-$(CONFIG_SSB_DRIVER_GPIO)          += driver_gpio.o
 
 # b43 pci-ssb-bridge driver
 # Not strictly a part of SSB, but kept here for convenience
index 95c33a05f434afda124a9b04300906d5ee9d15e2..71098a7b5fed2123319e5351a5a1157c5e2fc9a1 100644 (file)
@@ -349,6 +349,9 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
 {
        if (!cc->dev)
                return; /* We don't have a ChipCommon */
+
+       spin_lock_init(&cc->gpio_lock);
+
        if (cc->dev->id.revision >= 11)
                cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
        ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
@@ -505,28 +508,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
 
 u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-       return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-       return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-       return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 EXPORT_SYMBOL(ssb_chipco_gpio_control);
 
 u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-       return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-       return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
+}
+
+u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+       unsigned long flags;
+       u32 res = 0;
+
+       if (cc->dev->id.revision < 20)
+               return 0xffffffff;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
+}
+
+u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+       unsigned long flags;
+       u32 res = 0;
+
+       if (cc->dev->id.revision < 20)
+               return 0xffffffff;
+
+       spin_lock_irqsave(&cc->gpio_lock, flags);
+       res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value);
+       spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+       return res;
 }
 
 #ifdef CONFIG_SSB_SERIAL
index 553227a3062dfa739fd6868990dc4a70118ca045..59385fdab5b0d253dd26587e55390b7fac55a94f 100644 (file)
@@ -138,6 +138,13 @@ u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
        return ticks;
 }
 
+void ssb_extif_init(struct ssb_extif *extif)
+{
+       if (!extif->dev)
+               return; /* We don't have a Extif core */
+       spin_lock_init(&extif->gpio_lock);
+}
+
 u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 {
        return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
@@ -145,22 +152,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 
 u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
 {
-       return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&extif->gpio_lock, flags);
+       res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
                                   mask, value);
+       spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+       return res;
 }
 
 u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
 {
-       return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&extif->gpio_lock, flags);
+       res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
                                   mask, value);
+       spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+       return res;
 }
 
 u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
 {
-       return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&extif->gpio_lock, flags);
+       res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
+       spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+       return res;
 }
 
 u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
 {
-       return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
+       unsigned long flags;
+       u32 res = 0;
+
+       spin_lock_irqsave(&extif->gpio_lock, flags);
+       res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
+       spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+       return res;
 }
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
new file mode 100644 (file)
index 0000000..97ac0a3
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Sonics Silicon Backplane
+ * GPIO driver
+ *
+ * Copyright 2011, Broadcom Corporation
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/ssb/ssb.h>
+
+#include "ssb_private.h"
+
+static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
+{
+       return container_of(chip, struct ssb_bus, gpio);
+}
+
+static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
+}
+
+static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
+                                     int value)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
+                                          unsigned gpio)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
+       return 0;
+}
+
+static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
+                                           unsigned gpio, int value)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
+       ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
+       return 0;
+}
+
+static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
+       /* clear pulldown */
+       ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
+       /* Set pullup */
+       ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
+
+       return 0;
+}
+
+static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       /* clear pullup */
+       ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
+}
+
+static int ssb_gpio_chipco_init(struct ssb_bus *bus)
+{
+       struct gpio_chip *chip = &bus->gpio;
+
+       chip->label             = "ssb_chipco_gpio";
+       chip->owner             = THIS_MODULE;
+       chip->request           = ssb_gpio_chipco_request;
+       chip->free              = ssb_gpio_chipco_free;
+       chip->get               = ssb_gpio_chipco_get_value;
+       chip->set               = ssb_gpio_chipco_set_value;
+       chip->direction_input   = ssb_gpio_chipco_direction_input;
+       chip->direction_output  = ssb_gpio_chipco_direction_output;
+       chip->ngpio             = 16;
+       /* There is just one SoC in one device and its GPIO addresses should be
+        * deterministic to address them more easily. The other buses could get
+        * a random base number. */
+       if (bus->bustype == SSB_BUSTYPE_SSB)
+               chip->base              = 0;
+       else
+               chip->base              = -1;
+
+       return gpiochip_add(chip);
+}
+
+#ifdef CONFIG_SSB_DRIVER_EXTIF
+
+static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
+}
+
+static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
+                                    int value)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
+                                         unsigned gpio)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
+       return 0;
+}
+
+static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
+                                          unsigned gpio, int value)
+{
+       struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+       ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
+       ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
+       return 0;
+}
+
+static int ssb_gpio_extif_init(struct ssb_bus *bus)
+{
+       struct gpio_chip *chip = &bus->gpio;
+
+       chip->label             = "ssb_extif_gpio";
+       chip->owner             = THIS_MODULE;
+       chip->get               = ssb_gpio_extif_get_value;
+       chip->set               = ssb_gpio_extif_set_value;
+       chip->direction_input   = ssb_gpio_extif_direction_input;
+       chip->direction_output  = ssb_gpio_extif_direction_output;
+       chip->ngpio             = 5;
+       /* There is just one SoC in one device and its GPIO addresses should be
+        * deterministic to address them more easily. The other buses could get
+        * a random base number. */
+       if (bus->bustype == SSB_BUSTYPE_SSB)
+               chip->base              = 0;
+       else
+               chip->base              = -1;
+
+       return gpiochip_add(chip);
+}
+
+#else
+static int ssb_gpio_extif_init(struct ssb_bus *bus)
+{
+       return -ENOTSUPP;
+}
+#endif
+
+int ssb_gpio_init(struct ssb_bus *bus)
+{
+       if (ssb_chipco_available(&bus->chipco))
+               return ssb_gpio_chipco_init(bus);
+       else if (ssb_extif_available(&bus->extif))
+               return ssb_gpio_extif_init(bus);
+       else
+               SSB_WARN_ON(1);
+
+       return -1;
+}
index 6e0daaa0e04ba6b01417d7873c8dde129fe1883f..c82c5c95fe85022180971af93139b8fc33416c50 100644 (file)
@@ -804,7 +804,14 @@ static int __devinit ssb_bus_register(struct ssb_bus *bus,
        if (err)
                goto err_pcmcia_exit;
        ssb_chipcommon_init(&bus->chipco);
+       ssb_extif_init(&bus->extif);
        ssb_mipscore_init(&bus->mipscore);
+       err = ssb_gpio_init(bus);
+       if (err == -ENOTSUPP)
+               ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
+       else if (err)
+               ssb_dprintk(KERN_ERR PFX
+                          "Error registering GPIO driver: %i\n", err);
        err = ssb_fetch_invariants(bus, get_invariants);
        if (err) {
                ssb_bus_may_powerdown(bus);
index 8942db1d855af8ef69c6f3f4d639f4efe414fdd1..6c10b66c796cf7ee23ae3e9334086034198e911c 100644 (file)
@@ -242,4 +242,21 @@ static inline int ssb_watchdog_register(struct ssb_bus *bus)
 }
 #endif /* CONFIG_SSB_EMBEDDED */
 
+#ifdef CONFIG_SSB_DRIVER_EXTIF
+extern void ssb_extif_init(struct ssb_extif *extif);
+#else
+static inline void ssb_extif_init(struct ssb_extif *extif)
+{
+}
+#endif
+
+#ifdef CONFIG_SSB_DRIVER_GPIO
+extern int ssb_gpio_init(struct ssb_bus *bus);
+#else /* CONFIG_SSB_DRIVER_GPIO */
+static inline int ssb_gpio_init(struct ssb_bus *bus)
+{
+       return -ENOTSUPP;
+}
+#endif /* CONFIG_SSB_DRIVER_GPIO */
+
 #endif /* LINUX_SSB_PRIVATE_H_ */
index 78f3a2e013c4c3881894749f259e89c5ecd109cc..17b45ebb0553aeabb4ac0facf47d7a4b029719e4 100644 (file)
@@ -73,7 +73,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  *       And loads of cleaning up, in particular streamlining the
  *       bulk transfers.
  * 1.1:  moved EP4 transfers to EP1 to make space for a PWM output on EP4
- * 1.2:  added PWM suport via EP4
+ * 1.2:  added PWM support via EP4
  * 2.0:  PWM seems to be stable and is not interfering with the other functions
  * 2.1:  changed PWM API
  * 2.2:  added firmware kernel request to fix an udev problem
index 238910373f5c74cdc431725cf1d09bba8c33bd25..479c643da2f61c9382709161f9064747239df569 100644 (file)
@@ -396,7 +396,9 @@ dt3155_open(struct file *filp)
                pd->q->drv_priv = pd;
                pd->curr_buf = NULL;
                pd->field_count = 0;
-               vb2_queue_init(pd->q); /* cannot fail */
+               ret = vb2_queue_init(pd->q);
+               if (ret < 0)
+                       return ret;
                INIT_LIST_HEAD(&pd->dmaq);
                spin_lock_init(&pd->lock);
                /* disable all irqs, clear all irq flags */
index c9a6409edfe36f0153b976e9c63af42cbc37ad9c..f99c05b454b09f1ed1a7646178ccde517deef0b6 100644 (file)
@@ -382,8 +382,8 @@ static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
 
        buf = kzalloc(4096, GFP_KERNEL);
        if (buf == NULL) {
-               printk(KERN_ERR "go7007: unable to allocate 4096 bytes for "
-                               "firmware construction\n");
+               dev_err(go->dev,
+                       "unable to allocate 4096 bytes for firmware construction\n");
                return -1;
        }
 
@@ -652,8 +652,8 @@ static int gen_mpeg1hdr_to_package(struct go7007 *go,
 
        buf = kzalloc(5120, GFP_KERNEL);
        if (buf == NULL) {
-               printk(KERN_ERR "go7007: unable to allocate 5120 bytes for "
-                               "firmware construction\n");
+               dev_err(go->dev,
+                       "unable to allocate 5120 bytes for firmware construction\n");
                return -1;
        }
        framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
@@ -839,8 +839,8 @@ static int gen_mpeg4hdr_to_package(struct go7007 *go,
 
        buf = kzalloc(5120, GFP_KERNEL);
        if (buf == NULL) {
-               printk(KERN_ERR "go7007: unable to allocate 5120 bytes for "
-                               "firmware construction\n");
+               dev_err(go->dev,
+                       "unable to allocate 5120 bytes for firmware construction\n");
                return -1;
        }
        framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
@@ -1545,9 +1545,8 @@ static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
        case SPECIAL_MODET:
                return modet_to_package(go, code, space);
        }
-       printk(KERN_ERR
-               "go7007: firmware file contains unsupported feature %04x\n",
-               type);
+       dev_err(go->dev,
+               "firmware file contains unsupported feature %04x\n", type);
        return -1;
 }
 
@@ -1577,15 +1576,16 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
                return -1;
        }
        if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) {
-               printk(KERN_ERR
-                       "go7007: unable to load firmware from file \"%s\"\n",
+               dev_err(go->dev,
+                       "unable to load firmware from file \"%s\"\n",
                        go->board_info->firmware);
                return -1;
        }
        code = kzalloc(codespace * 2, GFP_KERNEL);
        if (code == NULL) {
-               printk(KERN_ERR "go7007: unable to allocate %d bytes for "
-                               "firmware construction\n", codespace * 2);
+               dev_err(go->dev,
+                       "unable to allocate %d bytes for firmware construction\n",
+                       codespace * 2);
                goto fw_failed;
        }
        src = (__le16 *)fw_entry->data;
@@ -1594,9 +1594,9 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
                chunk_flags = __le16_to_cpu(src[0]);
                chunk_len = __le16_to_cpu(src[1]);
                if (chunk_len + 2 > srclen) {
-                       printk(KERN_ERR "go7007: firmware file \"%s\" "
-                                       "appears to be corrupted\n",
-                                       go->board_info->firmware);
+                       dev_err(go->dev,
+                               "firmware file \"%s\" appears to be corrupted\n",
+                               go->board_info->firmware);
                        goto fw_failed;
                }
                if (chunk_flags & mode_flag) {
@@ -1604,17 +1604,15 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
                                ret = do_special(go, __le16_to_cpu(src[2]),
                                        &code[i], codespace - i, framelen);
                                if (ret < 0) {
-                                       printk(KERN_ERR "go7007: insufficient "
-                                                       "memory for firmware "
-                                                       "construction\n");
+                                       dev_err(go->dev,
+                                               "insufficient memory for firmware construction\n");
                                        goto fw_failed;
                                }
                                i += ret;
                        } else {
                                if (codespace - i < chunk_len) {
-                                       printk(KERN_ERR "go7007: insufficient "
-                                                       "memory for firmware "
-                                                       "construction\n");
+                                       dev_err(go->dev,
+                                               "insufficient memory for firmware construction\n");
                                        goto fw_failed;
                                }
                                memcpy(&code[i], &src[2], chunk_len * 2);
index 980371b0274966b45b71a38621f4452e8bf0cf72..a78133b67de2049f80190d3a2672c6fadbcaa68a 100644 (file)
@@ -812,7 +812,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
                return retval;
 
        mutex_lock(&gofh->lock);
-       if (buf->index < 0 || buf->index >= gofh->buf_count)
+       if (buf->index >= gofh->buf_count)
                goto unlock_and_return;
 
        gobuf = &gofh->bufs[buf->index];
index 014d38410c99bec9e100132fa875abd7938a33a9..b3974100c6cdccd0899da64fa8d5a2d9915365aa 100644 (file)
@@ -688,15 +688,4 @@ static struct i2c_driver s2250_driver = {
        .id_table       = s2250_id,
 };
 
-static __init int init_s2250(void)
-{
-       return i2c_add_driver(&s2250_driver);
-}
-
-static __exit void exit_s2250(void)
-{
-       i2c_del_driver(&s2250_driver);
-}
-
-module_init(init_s2250);
-module_exit(exit_s2250);
+module_i2c_driver(s2250_driver);
index 6bc9470fecb6f13de14d8bb1106a5209525f1102..9f01657f884ad5cbbccc29a6f3339e56fbe58dd0 100644 (file)
@@ -29,8 +29,7 @@ struct wis_ov7640 {
        int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
        0x12, 0x80,
        0x12, 0x54,
        0x14, 0x24,
@@ -60,12 +59,12 @@ static int wis_ov7640_probe(struct i2c_client *client,
 
        client->flags = I2C_CLIENT_SCCB;
 
-       printk(KERN_DEBUG
+       dev_dbg(&client->dev,
                "wis-ov7640: initializing OV7640 at address %d on %s\n",
                client->addr, adapter->name);
 
        if (write_regs(client, initial_registers) < 0) {
-               printk(KERN_ERR "wis-ov7640: error initializing OV7640\n");
+               dev_err(&client->dev, "wis-ov7640: error initializing OV7640\n");
                return -ENODEV;
        }
 
@@ -92,17 +91,6 @@ static struct i2c_driver wis_ov7640_driver = {
        .id_table       = wis_ov7640_id,
 };
 
-static int __init wis_ov7640_init(void)
-{
-       return i2c_add_driver(&wis_ov7640_driver);
-}
-
-static void __exit wis_ov7640_cleanup(void)
-{
-       i2c_del_driver(&wis_ov7640_driver);
-}
-
-module_init(wis_ov7640_init);
-module_exit(wis_ov7640_cleanup);
+module_i2c_driver(wis_ov7640_driver);
 
 MODULE_LICENSE("GPL v2");
index 05e0e108386427b4ee22677707f373fd699bda65..8810c1e6e1ed0e1253fb4539cf1cb17bc1dd550f 100644 (file)
@@ -32,8 +32,7 @@ struct wis_saa7113 {
        int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
        0x01, 0x08,
        0x02, 0xc0,
        0x03, 0x33,
@@ -282,12 +281,12 @@ static int wis_saa7113_probe(struct i2c_client *client,
        dec->hue = 0;
        i2c_set_clientdata(client, dec);
 
-       printk(KERN_DEBUG
+       dev_dbg(&client->dev,
                "wis-saa7113: initializing SAA7113 at address %d on %s\n",
                client->addr, adapter->name);
 
        if (write_regs(client, initial_registers) < 0) {
-               printk(KERN_ERR
+               dev_err(&client->dev,
                        "wis-saa7113: error initializing SAA7113\n");
                kfree(dec);
                return -ENODEV;
@@ -320,17 +319,6 @@ static struct i2c_driver wis_saa7113_driver = {
        .id_table       = wis_saa7113_id,
 };
 
-static int __init wis_saa7113_init(void)
-{
-       return i2c_add_driver(&wis_saa7113_driver);
-}
-
-static void __exit wis_saa7113_cleanup(void)
-{
-       i2c_del_driver(&wis_saa7113_driver);
-}
-
-module_init(wis_saa7113_init);
-module_exit(wis_saa7113_cleanup);
+module_i2c_driver(wis_saa7113_driver);
 
 MODULE_LICENSE("GPL v2");
index 46cff59e28b7faddddd41c259c3d56815dc446cc..fa86acd3fdf0d6f80dd9c9be1c50baa265bc2d7f 100644 (file)
@@ -32,8 +32,7 @@ struct wis_saa7115 {
        int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
        0x01, 0x08,
        0x02, 0xc0,
        0x03, 0x20,
@@ -415,12 +414,12 @@ static int wis_saa7115_probe(struct i2c_client *client,
        dec->hue = 0;
        i2c_set_clientdata(client, dec);
 
-       printk(KERN_DEBUG
+       dev_dbg(&client->dev,
                "wis-saa7115: initializing SAA7115 at address %d on %s\n",
                client->addr, adapter->name);
 
        if (write_regs(client, initial_registers) < 0) {
-               printk(KERN_ERR
+               dev_err(&client->dev,
                        "wis-saa7115: error initializing SAA7115\n");
                kfree(dec);
                return -ENODEV;
@@ -453,17 +452,6 @@ static struct i2c_driver wis_saa7115_driver = {
        .id_table       = wis_saa7115_id,
 };
 
-static int __init wis_saa7115_init(void)
-{
-       return i2c_add_driver(&wis_saa7115_driver);
-}
-
-static void __exit wis_saa7115_cleanup(void)
-{
-       i2c_del_driver(&wis_saa7115_driver);
-}
-
-module_init(wis_saa7115_init);
-module_exit(wis_saa7115_cleanup);
+module_i2c_driver(wis_saa7115_driver);
 
 MODULE_LICENSE("GPL v2");
index 8f1b7d4f6a2e976504a849c262d462b0916a2b49..1291ab79d2af1189f5e5f319fab87097de6ac96c 100644 (file)
@@ -704,17 +704,6 @@ static struct i2c_driver wis_sony_tuner_driver = {
        .id_table       = wis_sony_tuner_id,
 };
 
-static int __init wis_sony_tuner_init(void)
-{
-       return i2c_add_driver(&wis_sony_tuner_driver);
-}
-
-static void __exit wis_sony_tuner_cleanup(void)
-{
-       i2c_del_driver(&wis_sony_tuner_driver);
-}
-
-module_init(wis_sony_tuner_init);
-module_exit(wis_sony_tuner_cleanup);
+module_i2c_driver(wis_sony_tuner_driver);
 
 MODULE_LICENSE("GPL v2");
index 9134f03e3cf092aa36d4d918cc897f14a9d32172..d6410ee01be86fbaee8dbb9428d1313d9ed917b2 100644 (file)
@@ -341,17 +341,6 @@ static struct i2c_driver wis_tw2804_driver = {
        .id_table       = wis_tw2804_id,
 };
 
-static int __init wis_tw2804_init(void)
-{
-       return i2c_add_driver(&wis_tw2804_driver);
-}
-
-static void __exit wis_tw2804_cleanup(void)
-{
-       i2c_del_driver(&wis_tw2804_driver);
-}
-
-module_init(wis_tw2804_init);
-module_exit(wis_tw2804_cleanup);
+module_i2c_driver(wis_tw2804_driver);
 
 MODULE_LICENSE("GPL v2");
index 9230f4a8052926c13de75810aab6d40c00992814..94071def3bb47dd93bbeef5a0e8f8fe3e7a183df 100644 (file)
@@ -325,17 +325,6 @@ static struct i2c_driver wis_tw9903_driver = {
        .id_table       = wis_tw9903_id,
 };
 
-static int __init wis_tw9903_init(void)
-{
-       return i2c_add_driver(&wis_tw9903_driver);
-}
-
-static void __exit wis_tw9903_cleanup(void)
-{
-       i2c_del_driver(&wis_tw9903_driver);
-}
-
-module_init(wis_tw9903_init);
-module_exit(wis_tw9903_cleanup);
+module_i2c_driver(wis_tw9903_driver);
 
 MODULE_LICENSE("GPL v2");
index 0127be2f3be0b68135aaa1ceeb3e75cac5a98536..05ac798f35f7d3aca908bc8d8989c0bd0756a845 100644 (file)
@@ -98,17 +98,6 @@ static struct i2c_driver wis_uda1342_driver = {
        .id_table       = wis_uda1342_id,
 };
 
-static int __init wis_uda1342_init(void)
-{
-       return i2c_add_driver(&wis_uda1342_driver);
-}
-
-static void __exit wis_uda1342_cleanup(void)
-{
-       i2c_del_driver(&wis_uda1342_driver);
-}
-
-module_init(wis_uda1342_init);
-module_exit(wis_uda1342_cleanup);
+module_i2c_driver(wis_uda1342_driver);
 
 MODULE_LICENSE("GPL v2");
index 71e3bf2937f9bf0ffc0674f491d5ad67532c1d56..b5d0088f3102a4fb52062a5a4d528634b77eaa7b 100644 (file)
@@ -1239,6 +1239,10 @@ static int __init lirc_serial_init_module(void)
                }
        }
 
+       /* make sure sense is either -1, 0, or 1 */
+       if (sense != -1)
+               sense = !!sense;
+
        result = lirc_serial_init();
        if (result)
                return result;
@@ -1298,7 +1302,7 @@ MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
 module_param(share_irq, bool, S_IRUGO);
 MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
 
-module_param(sense, bool, S_IRUGO);
+module_param(sense, int, S_IRUGO);
 MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
                 " (0 = active high, 1 = active low )");
 
index d4823fd67768e2820ca10be48a8a1b898401215c..84943e5ba1d6563f49877ada93e022a1d67b5385 100644 (file)
@@ -565,6 +565,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = priv;
 
+       ret = omapdss_compat_init();
+       if (ret) {
+               dev_err(dev->dev, "coult not init omapdss\n");
+               dev->dev_private = NULL;
+               kfree(priv);
+               return ret;
+       }
+
        priv->wq = alloc_ordered_workqueue("omapdrm", 0);
 
        INIT_LIST_HEAD(&priv->obj_list);
@@ -576,6 +584,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
                dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
                dev->dev_private = NULL;
                kfree(priv);
+               omapdss_compat_uninit();
                return ret;
        }
 
@@ -610,6 +619,8 @@ static int dev_unload(struct drm_device *dev)
        flush_workqueue(priv->wq);
        destroy_workqueue(priv->wq);
 
+       omapdss_compat_uninit();
+
        kfree(dev->dev_private);
        dev->dev_private = NULL;
 
index 294e9b40f51666396c2a56c3d92036951e04382d..737f4a9d86a33fb7fcb865c11f43453d15bd7ecd 100644 (file)
@@ -736,7 +736,7 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
                case 4:
                        break;
                default:
-                       /* alignment value not suportted */
+                       /* alignment value not supportted */
                        status = -EPERM;
                        break;
                }
index ff6fd4fb624d44fc4791a62af7e837ba18c10fc1..0f03b7919d7c2d13b18221cac4e77cb962f195da 100644 (file)
@@ -235,7 +235,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
         * iSER/SCTP (TODO, software emulation with osc-iwarp)
         * iSER/IB (TODO, hardware available)
         *
-        * can be enabled with atributes under
+        * can be enabled with attributes under
         * sys/kernel/config/iscsi/$IQN/$TPG/np/$IP:$PORT/
         *
         */
index 8aacf611b86d43243677845c0a89b8abe825f5a0..8e6298cc8839711e03745c08f7be04446ac47f3b 100644 (file)
@@ -410,11 +410,11 @@ static int iscsit_dataout_pre_datapduinorder_yes(
        /*
         * For DataSequenceInOrder=Yes: If the offset is greater than the global
         * DataPDUInOrder=Yes offset counter in struct iscsi_cmd a protcol error has
-        * occured and fail the connection.
+        * occurred and fail the connection.
         *
         * For DataSequenceInOrder=No: If the offset is greater than the per
         * sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
-        * error has occured and fail the connection.
+        * error has occurred and fail the connection.
         */
        if (conn->sess->sess_ops->DataSequenceInOrder) {
                if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
@@ -801,7 +801,7 @@ void iscsit_start_time2retain_handler(struct iscsi_session *sess)
 {
        int tpg_active;
        /*
-        * Only start Time2Retain timer when the assoicated TPG is still in
+        * Only start Time2Retain timer when the associated TPG is still in
         * an ACTIVE (eg: not disabled or shutdown) state.
         */
        spin_lock(&ISCSI_TPG_S(sess)->tpg_state_lock);
index 90b740048f26ee7151eda956b092e12fad74e70c..1bf7432bfcbc659f8b27dc15400016b31173add3 100644 (file)
@@ -1432,6 +1432,7 @@ static struct iscsi_param *iscsi_check_key(
                        break;
                case PHASE_OPERATIONAL:
                        pr_debug("Operational phase.\n");
+                       break;
                default:
                        pr_debug("Unknown phase.\n");
                }
index 1a91195ab619a9ebbfa503cf7851c3cb8ca02b49..69e0cfd988704a9f18143d3231d9c2fb79daaf29 100644 (file)
@@ -684,7 +684,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
 void iscsit_free_cmd(struct iscsi_cmd *cmd)
 {
        /*
-        * Determine if a struct se_cmd is assoicated with
+        * Determine if a struct se_cmd is associated with
         * this struct iscsi_cmd.
         */
        switch (cmd->iscsi_opcode) {
index 8636fae1f7ecfa88909b5b4aa7eb39b71722933f..c2c77d1ac499d3ccb4d4c141d66986e88e980bf6 100644 (file)
@@ -98,7 +98,7 @@ config EXYNOS_THERMAL
        depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
        depends on CPU_THERMAL
        help
-         If you say yes here you get support for TMU (Thermal Managment
+         If you say yes here you get support for TMU (Thermal Management
          Unit) on SAMSUNG EXYNOS series of SoC.
 
 config DB8500_THERMAL
index d8e05eeab23213e503381422735f59fe7240281c..0ecf22b6a38e5c61a9d42670435ac60939ce82c4 100644 (file)
@@ -357,6 +357,7 @@ config TRACE_SINK
 config PPC_EPAPR_HV_BYTECHAN
        tristate "ePAPR hypervisor byte channel driver"
        depends on PPC
+       select EPAPR_PARAVIRT
        help
          This driver creates /dev entries for each ePAPR hypervisor byte
          channel, thereby allowing applications to communicate with byte
index be1a9a1e749e6761678fe1c135a1a64ff25160e7..cd69b48f6dfd390a8231f689b35f5d2588c16772 100644 (file)
@@ -178,7 +178,7 @@ static int hvc_opal_probe(struct platform_device *dev)
                proto = HV_PROTOCOL_HVSI;
                ops = &hvc_opal_hvsi_ops;
        } else {
-               pr_err("hvc_opal: Unkown protocol for %s\n",
+               pr_err("hvc_opal: Unknown protocol for %s\n",
                       dev->dev.of_node->full_name);
                return -ENXIO;
        }
index ed6f5f1f5a552e461af7ddb2941774194ea2c558..0c629807610e6576ff822f2b958d8894e4182dc7 100644 (file)
@@ -313,7 +313,7 @@ static int hvc_vio_probe(struct vio_dev *vdev,
                proto = HV_PROTOCOL_HVSI;
                ops = &hvterm_hvsi_ops;
        } else {
-               pr_err("hvc_vio: Unkown protocol for %s\n", vdev->dev.of_node->full_name);
+               pr_err("hvc_vio: Unknown protocol for %s\n", vdev->dev.of_node->full_name);
                return -ENXIO;
        }
 
index 9d6bcc77c73ca4fc253411557fb413082e2822ef..002c34e72521097525d478577fb2737b2faf7c0c 100644 (file)
@@ -59,7 +59,7 @@ struct tl_setup_config_done_msg {
        unsigned char sig_no;           /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
 } __attribute__ ((__packed__));
 
-/* Asyncronous messages */
+/* Asynchronous messages */
 struct tl_setup_open_msg {
        unsigned char sig_no;           /* TL_SETUP_SIGNO_OPEN_MSG */
        unsigned char port_no;
index f3d283f2e3aa280598867500de23f142cb050670..c31133a6ea8e0361f1f84103c469026bda82c077 100644 (file)
@@ -271,7 +271,7 @@ config SERIAL_8250_DW
          present in the Synopsys DesignWare APB UART.
 
 config SERIAL_8250_EM
-       tristate "Support for Emma Mobile intergrated serial port"
+       tristate "Support for Emma Mobile integrated serial port"
        depends on SERIAL_8250 && ARM && HAVE_CLK
        help
          Selecting this option will add support for the integrated serial
index e6a008f4939f47ac6aac0129ef0f1cf5b90c3998..2e2b2c1cb72252d607dd747305cb354c68dd2cb7 100644 (file)
@@ -815,7 +815,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
                lcr = WLS(5);
                break;
        default:
-               printk(KERN_ERR "%s: word lengh not supported\n",
+               printk(KERN_ERR "%s: word length not supported\n",
                        __func__);
        }
 
index 6197a69adb4d407e3011c37625cbca8faae66eb1..72b6334bcf1aacae37068258ec9d4cbd46e6bf3d 100644 (file)
@@ -505,7 +505,7 @@ static void load_code(struct icom_port *icom_port)
                /* Stop processor */
                stop_processor(icom_port);
 
-               dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
+               dev_err(&icom_port->adapter->pci_dev->dev,"Port not operational\n");
        }
 
        if (new_page != NULL)
index 88dde95b6795fcc66cf7016cc2ff1559b633d0f1..d938b2b99e31fcee332a2f83ae46e4998907190a 100644 (file)
@@ -222,7 +222,7 @@ static int usb_probe_device(struct device *dev)
        /* TODO: Add real matching code */
 
        /* The device should always appear to be in use
-        * unless the driver suports autosuspend.
+        * unless the driver supports autosuspend.
         */
        if (!udriver->supports_autosuspend)
                error = usb_autoresume_device(udev);
index 59dcea2f69574f9d62747b315c141201e130de1f..f4a21f6f081f280ea117860a46e0ec0bf13f573a 100644 (file)
@@ -51,7 +51,7 @@
  * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
  * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
  *
- * This driver expects the board has been wired with two GPIOs suppporting
+ * This driver expects the board has been wired with two GPIOs supporting
  * a VBUS sensing IRQ, and a D+ pullup.  (They may be omitted, but the
  * testing hasn't covered such cases.)
  *
index ea5f2586fbdd3f9b8279c2d7230a2dbe5f067334..6c3586a4c95635780cc4adf7a8f14ed62cda6b24 100644 (file)
@@ -883,7 +883,7 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                } else {
                        US_DEBUGP("%s: NOT working scsi, not SS\n", __func__);
                        chip->proto_handler_backup(srb, us);
-                       /* Check wether card is plugged in */
+                       /* Check whether card is plugged in */
                        if (srb->cmnd[0] == TEST_UNIT_READY) {
                                if (srb->result == SAM_STAT_GOOD) {
                                        SET_LUN_READY(chip, srb->device->lun);
index 79e7e4d45eb242b42aeb20ab14dfe73aaabfa565..d670130ee687e803407a10075608bb883ab70451 100644 (file)
@@ -230,7 +230,7 @@ static struct se_node_acl *tcm_vhost_alloc_fabric_acl(
 
        nacl = kzalloc(sizeof(struct tcm_vhost_nacl), GFP_KERNEL);
        if (!nacl) {
-               pr_err("Unable to alocate struct tcm_vhost_nacl\n");
+               pr_err("Unable to allocate struct tcm_vhost_nacl\n");
                return NULL;
        }
 
index d08d7998a4aae7835c607791b2308d6ed008a797..9c31277b3a811067a1e7985eaa2256e379a149e3 100644 (file)
@@ -2045,7 +2045,7 @@ config FB_S3C_DEBUG_REGWRITE
        bool "Debug register writes"
        depends on FB_S3C
        ---help---
-         Show all register writes via printk(KERN_DEBUG)
+         Show all register writes via pr_debug()
 
 config FB_S3C2410
        tristate "S3C2410 LCD framebuffer support"
@@ -2442,4 +2442,19 @@ config FB_SH_MOBILE_MERAM
          Up to 4 memory channels can be configured, allowing 4 RGB or
          2 YCbCr framebuffers to be configured.
 
+config FB_SSD1307
+       tristate "Solomon SSD1307 framebuffer support"
+       depends on FB && I2C
+       depends on OF
+       depends on GENERIC_GPIO
+       select FB_SYS_FOPS
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_DEFERRED_IO
+       select PWM
+       help
+         This driver implements support for the Solomon SSD1307
+         OLED controller over I2C.
+
 endmenu
index 23e948ebfab8931b790617cf9341a081b1f9edae..768a137a1bacd3f8eca7dfde548cce68c41176bb 100644 (file)
@@ -161,6 +161,7 @@ obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
 obj-$(CONFIG_FB_MX3)             += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)           += da8xx-fb.o
 obj-$(CONFIG_FB_MXS)             += mxsfb.o
+obj-$(CONFIG_FB_SSD1307)         += ssd1307fb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
index 6d1596629040794ca5147b3a477276d330536c8b..b05afd03729eb7c1155aac758ea538948d81fb9f 100644 (file)
@@ -327,9 +327,16 @@ out_unmap:
 
 static void newport_init(struct vc_data *vc, int init)
 {
-       vc->vc_cols = newport_xsize / 8;
-       vc->vc_rows = newport_ysize / 16;
+       int cols, rows;
+
+       cols = newport_xsize / 8;
+       rows = newport_ysize / 16;
        vc->vc_can_do_color = 1;
+       if (init) {
+               vc->vc_cols = cols;
+               vc->vc_rows = rows;
+       } else
+               vc_resize(vc, cols, rows);
 }
 
 static void newport_deinit(struct vc_data *c)
index 25f835bf3d72aa2f551eb78ad6c3f1ced7287e67..46dd8f5d2e9e1c899921893f314ce590ea998d10 100644 (file)
@@ -35,8 +35,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
        dsize = s_pitch * cursor->image.height;
 
        if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
-               if (ops->cursor_src != NULL)
-                       kfree(ops->cursor_src);
+               kfree(ops->cursor_src);
                ops->cursor_size = dsize + sizeof(struct fb_image);
 
                ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
index 80665f66ac1ab844b283bb432a39f0591908d84d..46534e00fe01eb575ae565fb5930b1c2d36ffa20 100644 (file)
@@ -213,62 +213,51 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
        .accel = FB_ACCEL_NONE
 };
 
-struct da8xx_panel {
-       const char      name[25];       /* Full name <vendor>_<model> */
-       unsigned short  width;
-       unsigned short  height;
-       int             hfp;            /* Horizontal front porch */
-       int             hbp;            /* Horizontal back porch */
-       int             hsw;            /* Horizontal Sync Pulse Width */
-       int             vfp;            /* Vertical front porch */
-       int             vbp;            /* Vertical back porch */
-       int             vsw;            /* Vertical Sync Pulse Width */
-       unsigned int    pxl_clk;        /* Pixel clock */
-       unsigned char   invert_pxl_clk; /* Invert Pixel clock */
-};
-
-static struct da8xx_panel known_lcd_panels[] = {
+static struct fb_videomode known_lcd_panels[] = {
        /* Sharp LCD035Q3DG01 */
        [0] = {
-               .name = "Sharp_LCD035Q3DG01",
-               .width = 320,
-               .height = 240,
-               .hfp = 8,
-               .hbp = 6,
-               .hsw = 0,
-               .vfp = 2,
-               .vbp = 2,
-               .vsw = 0,
-               .pxl_clk = 4608000,
-               .invert_pxl_clk = 1,
+               .name           = "Sharp_LCD035Q3DG01",
+               .xres           = 320,
+               .yres           = 240,
+               .pixclock       = 4608000,
+               .left_margin    = 6,
+               .right_margin   = 8,
+               .upper_margin   = 2,
+               .lower_margin   = 2,
+               .hsync_len      = 0,
+               .vsync_len      = 0,
+               .sync           = FB_SYNC_CLK_INVERT |
+                       FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
        },
        /* Sharp LK043T1DG01 */
        [1] = {
-               .name = "Sharp_LK043T1DG01",
-               .width = 480,
-               .height = 272,
-               .hfp = 2,
-               .hbp = 2,
-               .hsw = 41,
-               .vfp = 2,
-               .vbp = 2,
-               .vsw = 10,
-               .pxl_clk = 7833600,
-               .invert_pxl_clk = 0,
+               .name           = "Sharp_LK043T1DG01",
+               .xres           = 480,
+               .yres           = 272,
+               .pixclock       = 7833600,
+               .left_margin    = 2,
+               .right_margin   = 2,
+               .upper_margin   = 2,
+               .lower_margin   = 2,
+               .hsync_len      = 41,
+               .vsync_len      = 10,
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .flag           = 0,
        },
        [2] = {
                /* Hitachi SP10Q010 */
-               .name = "SP10Q010",
-               .width = 320,
-               .height = 240,
-               .hfp = 10,
-               .hbp = 10,
-               .hsw = 10,
-               .vfp = 10,
-               .vbp = 10,
-               .vsw = 10,
-               .pxl_clk = 7833600,
-               .invert_pxl_clk = 0,
+               .name           = "SP10Q010",
+               .xres           = 320,
+               .yres           = 240,
+               .pixclock       = 7833600,
+               .left_margin    = 10,
+               .right_margin   = 10,
+               .upper_margin   = 10,
+               .lower_margin   = 10,
+               .hsync_len      = 10,
+               .vsync_len      = 10,
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .flag           = 0,
        },
 };
 
@@ -399,10 +388,9 @@ static int lcd_cfg_dma(int burst_size, int fifo_th)
                reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
                break;
        case 16:
+       default:
                reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
                break;
-       default:
-               return -EINVAL;
        }
 
        reg |= (fifo_th << 8);
@@ -447,7 +435,8 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
        lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
 }
 
-static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
+static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
+               struct fb_videomode *panel)
 {
        u32 reg;
        u32 reg_int;
@@ -456,7 +445,7 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
                                                LCD_MONO_8BIT_MODE |
                                                LCD_MONOCHROME_MODE);
 
-       switch (cfg->p_disp_panel->panel_shade) {
+       switch (cfg->panel_shade) {
        case MONOCHROME:
                reg |= LCD_MONOCHROME_MODE;
                if (cfg->mono_8bit_mode)
@@ -469,7 +458,9 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
                break;
 
        case COLOR_PASSIVE:
-               if (cfg->stn_565_mode)
+               /* AC bias applicable only for Pasive panels */
+               lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
+               if (cfg->bpp == 12 && cfg->stn_565_mode)
                        reg |= LCD_STN_565_ENABLE;
                break;
 
@@ -490,22 +481,19 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 
        reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
 
-       if (cfg->sync_ctrl)
-               reg |= LCD_SYNC_CTRL;
-       else
-               reg &= ~LCD_SYNC_CTRL;
+       reg |= LCD_SYNC_CTRL;
 
        if (cfg->sync_edge)
                reg |= LCD_SYNC_EDGE;
        else
                reg &= ~LCD_SYNC_EDGE;
 
-       if (cfg->invert_line_clock)
+       if (panel->sync & FB_SYNC_HOR_HIGH_ACT)
                reg |= LCD_INVERT_LINE_CLOCK;
        else
                reg &= ~LCD_INVERT_LINE_CLOCK;
 
-       if (cfg->invert_frm_clock)
+       if (panel->sync & FB_SYNC_VERT_HIGH_ACT)
                reg |= LCD_INVERT_FRAME_CLOCK;
        else
                reg &= ~LCD_INVERT_FRAME_CLOCK;
@@ -728,7 +716,7 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
 }
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
-               struct da8xx_panel *panel)
+               struct fb_videomode *panel)
 {
        u32 bpp;
        int ret = 0;
@@ -738,7 +726,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
        /* Calculate the divider */
        lcd_calc_clk_divider(par);
 
-       if (panel->invert_pxl_clk)
+       if (panel->sync & FB_SYNC_CLK_INVERT)
                lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
                        LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
        else
@@ -750,30 +738,23 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
        if (ret < 0)
                return ret;
 
-       /* Configure the AC bias properties. */
-       lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
-
        /* Configure the vertical and horizontal sync properties. */
-       lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
-       lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
+       lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len,
+                       panel->upper_margin);
+       lcd_cfg_horizontal_sync(panel->right_margin, panel->hsync_len,
+                       panel->left_margin);
 
        /* Configure for disply */
-       ret = lcd_cfg_display(cfg);
+       ret = lcd_cfg_display(cfg, panel);
        if (ret < 0)
                return ret;
 
-       if (QVGA != cfg->p_disp_panel->panel_type)
-               return -EINVAL;
+       bpp = cfg->bpp;
 
-       if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
-           cfg->bpp >= cfg->p_disp_panel->min_bpp)
-               bpp = cfg->bpp;
-       else
-               bpp = cfg->p_disp_panel->max_bpp;
        if (bpp == 12)
                bpp = 16;
-       ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
-                               (unsigned int)panel->height, bpp,
+       ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
+                               (unsigned int)panel->yres, bpp,
                                cfg->raster_order);
        if (ret < 0)
                return ret;
@@ -1235,7 +1216,7 @@ static int __devinit fb_probe(struct platform_device *device)
        struct da8xx_lcdc_platform_data *fb_pdata =
                                                device->dev.platform_data;
        struct lcd_ctrl_config *lcd_cfg;
-       struct da8xx_panel *lcdc_info;
+       struct fb_videomode *lcdc_info;
        struct fb_info *da8xx_fb_info;
        struct clk *fb_clk = NULL;
        struct da8xx_fb_par *par;
@@ -1267,7 +1248,7 @@ static int __devinit fb_probe(struct platform_device *device)
                goto err_request_mem;
        }
 
-       fb_clk = clk_get(&device->dev, NULL);
+       fb_clk = clk_get(&device->dev, "fck");
        if (IS_ERR(fb_clk)) {
                dev_err(&device->dev, "Can not get device clock\n");
                ret = -ENODEV;
@@ -1283,6 +1264,7 @@ static int __devinit fb_probe(struct platform_device *device)
                lcd_revision = LCD_VERSION_1;
                break;
        case 0x4F200800:
+       case 0x4F201000:
                lcd_revision = LCD_VERSION_2;
                break;
        default:
@@ -1323,7 +1305,7 @@ static int __devinit fb_probe(struct platform_device *device)
 #ifdef CONFIG_CPU_FREQ
        par->lcd_fck_rate = clk_get_rate(fb_clk);
 #endif
-       par->pxl_clk = lcdc_info->pxl_clk;
+       par->pxl_clk = lcdc_info->pixclock;
        if (fb_pdata->panel_power_ctrl) {
                par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
                par->panel_power_ctrl(1);
@@ -1336,8 +1318,8 @@ static int __devinit fb_probe(struct platform_device *device)
        }
 
        /* allocate frame buffer */
-       par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
-       ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE);
+       par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
+       ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
        par->vram_size = roundup(par->vram_size/8, ulcm);
        par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
 
@@ -1355,10 +1337,10 @@ static int __devinit fb_probe(struct platform_device *device)
        da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
        da8xx_fb_fix.smem_start    = par->vram_phys;
        da8xx_fb_fix.smem_len      = par->vram_size;
-       da8xx_fb_fix.line_length   = (lcdc_info->width * lcd_cfg->bpp) / 8;
+       da8xx_fb_fix.line_length   = (lcdc_info->xres * lcd_cfg->bpp) / 8;
 
        par->dma_start = par->vram_phys;
-       par->dma_end   = par->dma_start + lcdc_info->height *
+       par->dma_end   = par->dma_start + lcdc_info->yres *
                da8xx_fb_fix.line_length - 1;
 
        /* allocate palette buffer */
@@ -1384,22 +1366,22 @@ static int __devinit fb_probe(struct platform_device *device)
        /* Initialize par */
        da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
 
-       da8xx_fb_var.xres = lcdc_info->width;
-       da8xx_fb_var.xres_virtual = lcdc_info->width;
+       da8xx_fb_var.xres = lcdc_info->xres;
+       da8xx_fb_var.xres_virtual = lcdc_info->xres;
 
-       da8xx_fb_var.yres         = lcdc_info->height;
-       da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS;
+       da8xx_fb_var.yres         = lcdc_info->yres;
+       da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
 
        da8xx_fb_var.grayscale =
-           lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
+           lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
        da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
 
-       da8xx_fb_var.hsync_len = lcdc_info->hsw;
-       da8xx_fb_var.vsync_len = lcdc_info->vsw;
-       da8xx_fb_var.right_margin = lcdc_info->hfp;
-       da8xx_fb_var.left_margin  = lcdc_info->hbp;
-       da8xx_fb_var.lower_margin = lcdc_info->vfp;
-       da8xx_fb_var.upper_margin = lcdc_info->vbp;
+       da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
+       da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
+       da8xx_fb_var.right_margin = lcdc_info->right_margin;
+       da8xx_fb_var.left_margin  = lcdc_info->left_margin;
+       da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
+       da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
        da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
 
        /* Initialize fbinfo */
index d55470e754126f4b8d54d0b4586682aaa1b00991..28fd686c6b8199429b98ca7d7c6014fc7225cf1b 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 
 #include <video/exynos_dp.h>
 
@@ -48,10 +49,6 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
 {
        int timeout_loop = 0;
 
-       exynos_dp_init_hpd(dp);
-
-       usleep_range(200, 210);
-
        while (exynos_dp_get_plug_in_status(dp) != 0) {
                timeout_loop++;
                if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
@@ -90,9 +87,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp)
         */
 
        /* Read Extension Flag, Number of 128-byte EDID extension blocks */
-       exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+       retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
                                EDID_EXTENSION_FLAG,
                                &extend_block);
+       if (retval)
+               return retval;
 
        if (extend_block > 0) {
                dev_dbg(dp->dev, "EDID data includes a single extension!\n");
@@ -181,14 +180,15 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
        int retval;
 
        /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-       exynos_dp_read_bytes_from_dpcd(dp,
-               DPCD_ADDR_DPCD_REV,
-               12, buf);
+       retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
+                               12, buf);
+       if (retval)
+               return retval;
 
        /* Read EDID */
        for (i = 0; i < 3; i++) {
                retval = exynos_dp_read_edid(dp);
-               if (retval == 0)
+               if (!retval)
                        break;
        }
 
@@ -261,11 +261,10 @@ 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)
+static int exynos_dp_link_start(struct exynos_dp_device *dp)
 {
        u8 buf[4];
-       int lane;
-       int lane_count;
+       int lane, lane_count, pll_tries, retval;
 
        lane_count = dp->link_train.lane_count;
 
@@ -275,10 +274,6 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
        for (lane = 0; lane < lane_count; lane++)
                dp->link_train.cr_loop[lane] = 0;
 
-       /* Set sink to D0 (Sink Not Ready) mode. */
-       exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
-                               DPCD_SET_POWER_STATE_D0);
-
        /* Set link rate and count as you want to establish*/
        exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
        exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
@@ -286,29 +281,46 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
        /* Setup RX configuration */
        buf[0] = dp->link_train.link_rate;
        buf[1] = dp->link_train.lane_count;
-       exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
+       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
                                2, buf);
+       if (retval)
+               return retval;
 
        /* Set TX pre-emphasis to minimum */
        for (lane = 0; lane < lane_count; lane++)
                exynos_dp_set_lane_lane_pre_emphasis(dp,
                        PRE_EMPHASIS_LEVEL_0, lane);
 
+       /* Wait for PLL lock */
+       pll_tries = 0;
+       while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+               if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+                       dev_err(dp->dev, "Wait for PLL lock timed out\n");
+                       return -ETIMEDOUT;
+               }
+
+               pll_tries++;
+               usleep_range(90, 120);
+       }
+
        /* Set training pattern 1 */
        exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
 
        /* Set RX training pattern */
-       exynos_dp_write_byte_to_dpcd(dp,
-               DPCD_ADDR_TRAINING_PATTERN_SET,
-               DPCD_SCRAMBLING_DISABLED |
-               DPCD_TRAINING_PATTERN_1);
+       retval = exynos_dp_write_byte_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_PATTERN_SET,
+                       DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
+       if (retval)
+               return retval;
 
        for (lane = 0; lane < lane_count; lane++)
                buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
                            DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
-       exynos_dp_write_bytes_to_dpcd(dp,
-               DPCD_ADDR_TRAINING_LANE0_SET,
-               lane_count, buf);
+
+       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+                       lane_count, buf);
+
+       return retval;
 }
 
 static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
@@ -332,18 +344,17 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
        return 0;
 }
 
-static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
+static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+                               int lane_count)
 {
        int lane;
-       u8 lane_align;
        u8 lane_status;
 
-       lane_align = link_align[2];
-       if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
+       if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
                return -EINVAL;
 
        for (lane = 0; lane < lane_count; lane++) {
-               lane_status = exynos_dp_get_lane_status(link_align, lane);
+               lane_status = exynos_dp_get_lane_status(link_status, lane);
                lane_status &= DPCD_CHANNEL_EQ_BITS;
                if (lane_status != DPCD_CHANNEL_EQ_BITS)
                        return -EINVAL;
@@ -427,60 +438,60 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
        dp->link_train.lt_state = FAILED;
 }
 
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
+                                       u8 adjust_request[2])
 {
-       u8 link_status[2];
-       int lane;
-       int lane_count;
+       int lane, lane_count;
+       u8 voltage_swing, pre_emphasis, training_lane;
 
-       u8 adjust_request[2];
-       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)
+                       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;
+       }
+}
+
+static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+{
+       int lane, lane_count, retval;
+       u8 voltage_swing, pre_emphasis, training_lane;
+       u8 link_status[2], adjust_request[2];
 
        usleep_range(100, 101);
 
        lane_count = dp->link_train.lane_count;
 
-       exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
-                               2, link_status);
+       retval =  exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+       if (retval)
+               return retval;
+
+       retval =  exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+       if (retval)
+               return retval;
 
        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);
 
-               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;
-
-                       exynos_dp_set_lane_link_training(dp,
-                               dp->link_train.training_lane[lane],
-                               lane);
-               }
-
-               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);
+               retval = exynos_dp_write_byte_to_dpcd(dp,
+                               DPCD_ADDR_TRAINING_PATTERN_SET,
+                               DPCD_SCRAMBLING_DISABLED |
+                               DPCD_TRAINING_PATTERN_2);
+               if (retval)
+                       return retval;
 
                dev_info(dp->dev, "Link Training Clock Recovery success\n");
                dp->link_train.lt_state = EQUALIZER_TRAINING;
@@ -488,152 +499,116 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
                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 (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;
-                       }
-
-                       if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
-                                       voltage_swing) &&
-                          (DPCD_PRE_EMPHASIS_GET(training_lane) ==
-                                       pre_emphasis)) {
+                       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;
+                       if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+                           voltage_swing == VOLTAGE_LEVEL_3 ||
+                           pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+                               dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+                                       dp->link_train.cr_loop[lane],
+                                       voltage_swing, pre_emphasis);
+                               exynos_dp_reduce_link_rate(dp);
+                               return -EIO;
+                       }
+               }
+       }
 
-                       dp->link_train.training_lane[lane] = training_lane;
+       exynos_dp_get_adjust_training_lane(dp, adjust_request);
 
-                       exynos_dp_set_lane_link_training(dp,
-                               dp->link_train.training_lane[lane], lane);
-               }
+       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,
+       retval = exynos_dp_write_bytes_to_dpcd(dp,
+                       DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
                        dp->link_train.training_lane);
-       }
-
-       return 0;
+       if (retval)
+               return retval;
 
-reduce_link_rate:
-       exynos_dp_reduce_link_rate(dp);
-       return -EIO;
+       return retval;
 }
 
 static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
 {
-       u8 link_status[2];
-       u8 link_align[3];
-       int lane;
-       int lane_count;
+       int lane, lane_count, retval;
        u32 reg;
-
-       u8 adjust_request[2];
-       u8 voltage_swing;
-       u8 pre_emphasis;
-       u8 training_lane;
+       u8 link_align, link_status[2], adjust_request[2];
 
        usleep_range(400, 401);
 
        lane_count = dp->link_train.lane_count;
 
-       exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
-                               2, link_status);
+       retval = exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+       if (retval)
+               return retval;
 
-       if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-               link_align[0] = link_status[0];
-               link_align[1] = link_status[1];
+       if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
+               exynos_dp_reduce_link_rate(dp);
+               return -EIO;
+       }
 
-               exynos_dp_read_byte_from_dpcd(dp,
-                       DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
-                       &link_align[2]);
+       retval = exynos_dp_read_bytes_from_dpcd(dp,
+                       DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+       if (retval)
+               return retval;
 
-               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);
+       retval = exynos_dp_read_byte_from_dpcd(dp,
+                       DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
+       if (retval)
+               return retval;
 
-                       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;
+       exynos_dp_get_adjust_training_lane(dp, adjust_request);
 
-                       dp->link_train.training_lane[lane] = training_lane;
-               }
+       if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+               /* traing pattern Set to Normal */
+               exynos_dp_training_pattern_dis(dp);
 
-               if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
-                       /* traing pattern Set to Normal */
-                       exynos_dp_training_pattern_dis(dp);
+               dev_info(dp->dev, "Link Training success!\n");
 
-                       dev_info(dp->dev, "Link Training success!\n");
-
-                       exynos_dp_get_link_bandwidth(dp, &reg);
-                       dp->link_train.link_rate = reg;
-                       dev_dbg(dp->dev, "final bandwidth = %.2x\n",
-                               dp->link_train.link_rate);
+               exynos_dp_get_link_bandwidth(dp, &reg);
+               dp->link_train.link_rate = reg;
+               dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+                       dp->link_train.link_rate);
 
-                       exynos_dp_get_lane_count(dp, &reg);
-                       dp->link_train.lane_count = reg;
-                       dev_dbg(dp->dev, "final lane count = %.2x\n",
-                               dp->link_train.lane_count);
+               exynos_dp_get_lane_count(dp, &reg);
+               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++;
+               /* set enhanced mode if available */
+               exynos_dp_set_enhanced_mode(dp);
+               dp->link_train.lt_state = FINISHED;
 
-                       if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-                               dev_err(dp->dev, "EQ Max loop\n");
-                               goto reduce_link_rate;
-                       }
+               return 0;
+       }
 
-                       for (lane = 0; lane < lane_count; lane++)
-                               exynos_dp_set_lane_link_training(dp,
-                                       dp->link_train.training_lane[lane],
-                                       lane);
+       /* not all locked */
+       dp->link_train.eq_loop++;
 
-                       exynos_dp_write_bytes_to_dpcd(dp,
-                               DPCD_ADDR_TRAINING_LANE0_SET,
-                               lane_count,
-                               dp->link_train.training_lane);
-               }
-       } else {
-               goto reduce_link_rate;
+       if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+               dev_err(dp->dev, "EQ Max loop\n");
+               exynos_dp_reduce_link_rate(dp);
+               return -EIO;
        }
 
-       return 0;
+       for (lane = 0; lane < lane_count; lane++)
+               exynos_dp_set_lane_link_training(dp,
+                       dp->link_train.training_lane[lane], lane);
+
+       retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+                       lane_count, dp->link_train.training_lane);
 
-reduce_link_rate:
-       exynos_dp_reduce_link_rate(dp);
-       return -EIO;
+       return retval;
 }
 
 static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
@@ -701,16 +676,17 @@ 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 = 0;
+       int retval = 0, training_finished = 0;
 
        dp->link_train.lt_state = START;
 
        /* Process here */
-       while (!training_finished) {
+       while (!retval && !training_finished) {
                switch (dp->link_train.lt_state) {
                case START:
-                       exynos_dp_link_start(dp);
+                       retval = exynos_dp_link_start(dp);
+                       if (retval)
+                               dev_err(dp->dev, "LT link start failed!\n");
                        break;
                case CLOCK_RECOVERY:
                        retval = exynos_dp_process_clock_recovery(dp);
@@ -729,6 +705,8 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
                        return -EREMOTEIO;
                }
        }
+       if (retval)
+               dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
 
        return retval;
 }
@@ -752,19 +730,15 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
        return retval;
 }
 
-static int exynos_dp_config_video(struct exynos_dp_device *dp,
-                       struct video_info *video_info)
+static int exynos_dp_config_video(struct exynos_dp_device *dp)
 {
        int retval = 0;
        int timeout_loop = 0;
        int done_count = 0;
 
-       exynos_dp_config_video_slave_mode(dp, video_info);
+       exynos_dp_config_video_slave_mode(dp);
 
-       exynos_dp_set_video_color_format(dp, video_info->color_depth,
-                       video_info->color_space,
-                       video_info->dynamic_range,
-                       video_info->ycbcr_coeff);
+       exynos_dp_set_video_color_format(dp);
 
        if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
                dev_err(dp->dev, "PLL is not locked yet.\n");
@@ -852,10 +826,213 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
 {
        struct exynos_dp_device *dp = arg;
 
-       dev_err(dp->dev, "exynos_dp_irq_handler\n");
+       enum dp_irq_type irq_type;
+
+       irq_type = exynos_dp_get_irq_type(dp);
+       switch (irq_type) {
+       case DP_IRQ_TYPE_HP_CABLE_IN:
+               dev_dbg(dp->dev, "Received irq - cable in\n");
+               schedule_work(&dp->hotplug_work);
+               exynos_dp_clear_hotplug_interrupts(dp);
+               break;
+       case DP_IRQ_TYPE_HP_CABLE_OUT:
+               dev_dbg(dp->dev, "Received irq - cable out\n");
+               exynos_dp_clear_hotplug_interrupts(dp);
+               break;
+       case DP_IRQ_TYPE_HP_CHANGE:
+               /*
+                * We get these change notifications once in a while, but there
+                * is nothing we can do with them. Just ignore it for now and
+                * only handle cable changes.
+                */
+               dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
+               exynos_dp_clear_hotplug_interrupts(dp);
+               break;
+       default:
+               dev_err(dp->dev, "Received irq - unknown type!\n");
+               break;
+       }
        return IRQ_HANDLED;
 }
 
+static void exynos_dp_hotplug(struct work_struct *work)
+{
+       struct exynos_dp_device *dp;
+       int ret;
+
+       dp = container_of(work, struct exynos_dp_device, hotplug_work);
+
+       ret = exynos_dp_detect_hpd(dp);
+       if (ret) {
+               /* Cable has been disconnected, we're done */
+               return;
+       }
+
+       ret = exynos_dp_handle_edid(dp);
+       if (ret) {
+               dev_err(dp->dev, "unable to handle edid\n");
+               return;
+       }
+
+       ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
+                                       dp->video_info->link_rate);
+       if (ret) {
+               dev_err(dp->dev, "unable to do link train\n");
+               return;
+       }
+
+       exynos_dp_enable_scramble(dp, 1);
+       exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
+       exynos_dp_enable_enhanced_mode(dp, 1);
+
+       exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
+       exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+
+       exynos_dp_init_video(dp);
+       ret = exynos_dp_config_video(dp);
+       if (ret)
+               dev_err(dp->dev, "unable to config video\n");
+}
+
+#ifdef CONFIG_OF
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+       struct device_node *dp_node = dev->of_node;
+       struct exynos_dp_platdata *pd;
+       struct video_info *dp_video_config;
+
+       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd) {
+               dev_err(dev, "memory allocation for pdata failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       dp_video_config = devm_kzalloc(dev,
+                               sizeof(*dp_video_config), GFP_KERNEL);
+
+       if (!dp_video_config) {
+               dev_err(dev, "memory allocation for video config failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       pd->video_info = dp_video_config;
+
+       dp_video_config->h_sync_polarity =
+               of_property_read_bool(dp_node, "hsync-active-high");
+
+       dp_video_config->v_sync_polarity =
+               of_property_read_bool(dp_node, "vsync-active-high");
+
+       dp_video_config->interlaced =
+               of_property_read_bool(dp_node, "interlaced");
+
+       if (of_property_read_u32(dp_node, "samsung,color-space",
+                               &dp_video_config->color_space)) {
+               dev_err(dev, "failed to get color-space\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+                               &dp_video_config->dynamic_range)) {
+               dev_err(dev, "failed to get dynamic-range\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+                               &dp_video_config->ycbcr_coeff)) {
+               dev_err(dev, "failed to get ycbcr-coeff\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,color-depth",
+                               &dp_video_config->color_depth)) {
+               dev_err(dev, "failed to get color-depth\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,link-rate",
+                               &dp_video_config->link_rate)) {
+               dev_err(dev, "failed to get link-rate\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(dp_node, "samsung,lane-count",
+                               &dp_video_config->lane_count)) {
+               dev_err(dev, "failed to get lane-count\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+       struct device_node *dp_phy_node;
+       u32 phy_base;
+
+       dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
+       if (!dp_phy_node) {
+               dev_err(dp->dev, "could not find dptx-phy node\n");
+               return -ENODEV;
+       }
+
+       if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+               dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+                               &dp->enable_mask)) {
+               dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+               return -EINVAL;
+       }
+
+       dp->phy_addr = ioremap(phy_base, SZ_4);
+       if (!dp->phy_addr) {
+               dev_err(dp->dev, "failed to ioremap dp-phy\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = __raw_readl(dp->phy_addr);
+       reg |= dp->enable_mask;
+       __raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       reg = __raw_readl(dp->phy_addr);
+       reg &= ~(dp->enable_mask);
+       __raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+       return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+       return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+       return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+       return;
+}
+#endif /* CONFIG_OF */
+
 static int __devinit exynos_dp_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -864,12 +1041,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
        int ret = 0;
 
-       pdata = pdev->dev.platform_data;
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data\n");
-               return -EINVAL;
-       }
-
        dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
                                GFP_KERNEL);
        if (!dp) {
@@ -879,6 +1050,22 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
        dp->dev = &pdev->dev;
 
+       if (pdev->dev.of_node) {
+               pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+
+               ret = exynos_dp_dt_parse_phydata(dp);
+               if (ret)
+                       return ret;
+       } else {
+               pdata = pdev->dev.platform_data;
+               if (!pdata) {
+                       dev_err(&pdev->dev, "no platform data\n");
+                       return -EINVAL;
+               }
+       }
+
        dp->clock = devm_clk_get(&pdev->dev, "dp");
        if (IS_ERR(dp->clock)) {
                dev_err(&pdev->dev, "failed to get clock\n");
@@ -896,50 +1083,29 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
        }
 
        dp->irq = platform_get_irq(pdev, 0);
-       if (!dp->irq) {
+       if (dp->irq == -ENXIO) {
                dev_err(&pdev->dev, "failed to get irq\n");
                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");
-               return ret;
-       }
+       INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
 
        dp->video_info = pdata->video_info;
-       if (pdata->phy_init)
-               pdata->phy_init();
-
-       exynos_dp_init_dp(dp);
-
-       ret = exynos_dp_detect_hpd(dp);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to detect hpd\n");
-               return ret;
-       }
 
-       exynos_dp_handle_edid(dp);
-
-       ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-                               dp->video_info->link_rate);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to do link train\n");
-               return ret;
+       if (pdev->dev.of_node) {
+               if (dp->phy_addr)
+                       exynos_dp_phy_init(dp);
+       } else {
+               if (pdata->phy_init)
+                       pdata->phy_init();
        }
 
-       exynos_dp_enable_scramble(dp, 1);
-       exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-       exynos_dp_enable_enhanced_mode(dp, 1);
-
-       exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-       exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+       exynos_dp_init_dp(dp);
 
-       exynos_dp_init_video(dp);
-       ret = exynos_dp_config_video(dp, dp->video_info);
+       ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
+                               "exynos-dp", dp);
        if (ret) {
-               dev_err(&pdev->dev, "unable to config video\n");
+               dev_err(&pdev->dev, "failed to request irq\n");
                return ret;
        }
 
@@ -953,23 +1119,41 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
        struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
        struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit();
+       disable_irq(dp->irq);
+
+       if (work_pending(&dp->hotplug_work))
+               flush_work(&dp->hotplug_work);
+
+       if (pdev->dev.of_node) {
+               if (dp->phy_addr)
+                       exynos_dp_phy_exit(dp);
+       } else {
+               if (pdata->phy_exit)
+                       pdata->phy_exit();
+       }
 
        clk_disable_unprepare(dp->clock);
 
+
        return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int exynos_dp_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
-       struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+       struct exynos_dp_platdata *pdata = dev->platform_data;
+       struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit();
+       if (work_pending(&dp->hotplug_work))
+               flush_work(&dp->hotplug_work);
+
+       if (dev->of_node) {
+               if (dp->phy_addr)
+                       exynos_dp_phy_exit(dp);
+       } else {
+               if (pdata->phy_exit)
+                       pdata->phy_exit();
+       }
 
        clk_disable_unprepare(dp->clock);
 
@@ -978,32 +1162,22 @@ static int exynos_dp_suspend(struct device *dev)
 
 static int exynos_dp_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
-       struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+       struct exynos_dp_platdata *pdata = dev->platform_data;
+       struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-       if (pdata && pdata->phy_init)
-               pdata->phy_init();
+       if (dev->of_node) {
+               if (dp->phy_addr)
+                       exynos_dp_phy_init(dp);
+       } else {
+               if (pdata->phy_init)
+                       pdata->phy_init();
+       }
 
        clk_prepare_enable(dp->clock);
 
        exynos_dp_init_dp(dp);
 
-       exynos_dp_detect_hpd(dp);
-       exynos_dp_handle_edid(dp);
-
-       exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-                               dp->video_info->link_rate);
-
-       exynos_dp_enable_scramble(dp, 1);
-       exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-       exynos_dp_enable_enhanced_mode(dp, 1);
-
-       exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-       exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
-       exynos_dp_init_video(dp);
-       exynos_dp_config_video(dp, dp->video_info);
+       enable_irq(dp->irq);
 
        return 0;
 }
@@ -1013,6 +1187,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
 };
 
+static const struct of_device_id exynos_dp_match[] = {
+       { .compatible = "samsung,exynos5-dp" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
 static struct platform_driver exynos_dp_driver = {
        .probe          = exynos_dp_probe,
        .remove         = __devexit_p(exynos_dp_remove),
@@ -1020,6 +1200,7 @@ static struct platform_driver exynos_dp_driver = {
                .name   = "exynos-dp",
                .owner  = THIS_MODULE,
                .pm     = &exynos_dp_pm_ops,
+               .of_match_table = of_match_ptr(exynos_dp_match),
        },
 };
 
index 57b8a6531c0ea1fb58c9babf5423ed26c586f826..6c567bbf2fb8fcec22f4f7949916e5a515b7b573 100644 (file)
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
+enum dp_irq_type {
+       DP_IRQ_TYPE_HP_CABLE_IN,
+       DP_IRQ_TYPE_HP_CABLE_OUT,
+       DP_IRQ_TYPE_HP_CHANGE,
+       DP_IRQ_TYPE_UNKNOWN,
+};
+
 struct link_train {
        int eq_loop;
        int cr_loop[4];
@@ -29,9 +36,12 @@ struct exynos_dp_device {
        struct clk              *clock;
        unsigned int            irq;
        void __iomem            *reg_base;
+       void __iomem            *phy_addr;
+       unsigned int            enable_mask;
 
        struct video_info       *video_info;
        struct link_train       link_train;
+       struct work_struct      hotplug_work;
 };
 
 /* exynos_dp_reg.c */
@@ -50,6 +60,8 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
                                bool enable);
 void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
 void exynos_dp_init_hpd(struct exynos_dp_device *dp);
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
 void exynos_dp_reset_aux(struct exynos_dp_device *dp);
 void exynos_dp_init_aux(struct exynos_dp_device *dp);
 int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
@@ -107,11 +119,7 @@ u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
 void exynos_dp_reset_macro(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,
-                               u32 color_space,
-                               u32 dynamic_range,
-                               u32 ycbcr_coeff);
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
 int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
 void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
                        enum clock_recovery_m_value_type type,
@@ -121,8 +129,7 @@ void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
 void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
 void exynos_dp_start_video(struct exynos_dp_device *dp);
 int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
-                       struct video_info *video_info);
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
 void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
 void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
 
index 3f5ca8a0d5ea45076d3929decfb514a1d9e5e52c..29d9d035c73a76e7313650fcbb6045b7dd0cfa38 100644 (file)
 #include "exynos_dp_core.h"
 #include "exynos_dp_reg.h"
 
-#define COMMON_INT_MASK_1 (0)
-#define COMMON_INT_MASK_2 (0)
-#define COMMON_INT_MASK_3 (0)
-#define COMMON_INT_MASK_4 (0)
-#define INT_STA_MASK (0)
+#define COMMON_INT_MASK_1      0
+#define COMMON_INT_MASK_2      0
+#define COMMON_INT_MASK_3      0
+#define COMMON_INT_MASK_4      (HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK           INT_HPD
 
 void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
 {
@@ -88,7 +88,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
 void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
 {
        /* Set interrupt pin assertion polarity as high */
-       writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
+       writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
 
        /* Clear pending regisers */
        writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
@@ -324,7 +324,7 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
        writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
 }
 
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
 {
        u32 reg;
 
@@ -333,12 +333,38 @@ void exynos_dp_init_hpd(struct exynos_dp_device *dp)
 
        reg = INT_HPD;
        writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+}
+
+void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       exynos_dp_clear_hotplug_interrupts(dp);
 
        reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
        reg &= ~(F_HPD | HPD_CTRL);
        writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
 }
 
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
+{
+       u32 reg;
+
+       /* Parse hotplug interrupt status register */
+       reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+       if (reg & PLUG)
+               return DP_IRQ_TYPE_HP_CABLE_IN;
+
+       if (reg & HPD_LOST)
+               return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+       if (reg & HOTPLUG_CHG)
+               return DP_IRQ_TYPE_HP_CHANGE;
+
+       return DP_IRQ_TYPE_UNKNOWN;
+}
+
 void exynos_dp_reset_aux(struct exynos_dp_device *dp)
 {
        u32 reg;
@@ -491,7 +517,7 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
        int i;
        int retval;
 
-       for (i = 0; i < 10; i++) {
+       for (i = 0; i < 3; i++) {
                /* Clear AUX CH data buffer */
                reg = BUF_CLR;
                writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
@@ -552,7 +578,7 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
                else
                        cur_data_count = count - start_offset;
 
-               for (i = 0; i < 10; i++) {
+               for (i = 0; i < 3; i++) {
                        /* Select DPCD device address */
                        reg = AUX_ADDR_7_0(reg_addr + start_offset);
                        writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
@@ -617,7 +643,7 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
                        cur_data_count = count - start_offset;
 
                /* AUX CH Request Transaction process */
-               for (i = 0; i < 10; i++) {
+               for (i = 0; i < 3; i++) {
                        /* Select DPCD device address */
                        reg = AUX_ADDR_7_0(reg_addr + start_offset);
                        writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
@@ -700,17 +726,15 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
        int i;
        int retval;
 
-       for (i = 0; i < 10; i++) {
+       for (i = 0; i < 3; i++) {
                /* Clear AUX CH data buffer */
                reg = BUF_CLR;
                writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
 
                /* Select EDID device */
                retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
-               if (retval != 0) {
-                       dev_err(dp->dev, "Select EDID device fail!\n");
+               if (retval != 0)
                        continue;
-               }
 
                /*
                 * Set I2C transaction and read data
@@ -750,7 +774,7 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
        int retval = 0;
 
        for (i = 0; i < count; i += 16) {
-               for (j = 0; j < 100; j++) {
+               for (j = 0; j < 3; j++) {
                        /* Clear AUX CH data buffer */
                        reg = BUF_CLR;
                        writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
@@ -1034,24 +1058,20 @@ void exynos_dp_init_video(struct exynos_dp_device *dp)
        writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
 }
 
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
-                       u32 color_depth,
-                       u32 color_space,
-                       u32 dynamic_range,
-                       u32 ycbcr_coeff)
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
 {
        u32 reg;
 
        /* Configure the input color depth, color space, dynamic range */
-       reg = (dynamic_range << IN_D_RANGE_SHIFT) |
-               (color_depth << IN_BPC_SHIFT) |
-               (color_space << IN_COLOR_F_SHIFT);
+       reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
+               (dp->video_info->color_depth << IN_BPC_SHIFT) |
+               (dp->video_info->color_space << IN_COLOR_F_SHIFT);
        writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
 
        /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
        reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
        reg &= ~IN_YC_COEFFI_MASK;
-       if (ycbcr_coeff)
+       if (dp->video_info->ycbcr_coeff)
                reg |= IN_YC_COEFFI_ITU709;
        else
                reg |= IN_YC_COEFFI_ITU601;
@@ -1178,8 +1198,7 @@ int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
        return 0;
 }
 
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
-                       struct video_info *video_info)
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
 {
        u32 reg;
 
@@ -1190,17 +1209,17 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
 
        reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
        reg &= ~INTERACE_SCAN_CFG;
-       reg |= (video_info->interlaced << 2);
+       reg |= (dp->video_info->interlaced << 2);
        writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 
        reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
        reg &= ~VSYNC_POLARITY_CFG;
-       reg |= (video_info->v_sync_polarity << 1);
+       reg |= (dp->video_info->v_sync_polarity << 1);
        writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 
        reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
        reg &= ~HSYNC_POLARITY_CFG;
-       reg |= (video_info->h_sync_polarity << 0);
+       reg |= (dp->video_info->h_sync_polarity << 0);
        writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 
        reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
index 1f2f014cfe88687c323428ba31c1e29c1cac9c2e..2e9bd0e0b9f2e1fc722b6c9ca0db4708f8cd4898 100644 (file)
 
 /* EXYNOS_DP_INT_CTL */
 #define SOFT_INT_CTRL                          (0x1 << 2)
-#define INT_POL                                        (0x1 << 0)
+#define INT_POL1                               (0x1 << 1)
+#define INT_POL0                               (0x1 << 0)
 
 /* EXYNOS_DP_SYS_CTL_1 */
 #define DET_STA                                        (0x1 << 2)
index ede9e55413f80ad33e932f48c652785069bb2fb8..d3fc92eaee8939bc0f35981342fbc6f5e2a47a28 100644 (file)
@@ -337,13 +337,11 @@ struct mfb_info {
        int registered;
        unsigned long pseudo_palette[16];
        struct diu_ad *ad;
-       int cursor_reset;
        unsigned char g_alpha;
        unsigned int count;
        int x_aoi_d;            /* aoi display x offset to physical screen */
        int y_aoi_d;            /* aoi display y offset to physical screen */
        struct fsl_diu_data *parent;
-       u8 *edid_data;
 };
 
 /**
@@ -378,6 +376,8 @@ struct fsl_diu_data {
        struct diu_ad ad[NUM_AOIS] __aligned(8);
        u8 gamma[256 * 3] __aligned(32);
        u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+       uint8_t edid_data[EDID_LENGTH];
+       bool has_edid;
 } __aligned(32);
 
 /* Determine the DMA address of a member of the fsl_diu_data structure */
@@ -430,6 +430,22 @@ static struct mfb_info mfb_template[] = {
        },
 };
 
+#ifdef DEBUG
+static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
+{
+       mb();
+       pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x "
+                "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x "
+                "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x "
+                "thresholds=%08x int_mask=%08x plut=%08x\n",
+                hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
+                hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode,
+                hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
+                hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
+       rmb();
+}
+#endif
+
 /**
  * fsl_diu_name_to_port - convert a port name to a monitor port enum
  *
@@ -481,8 +497,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
 
        switch (mfbi->index) {
        case PLANE0:
-               if (hw->desc[0] != ad->paddr)
-                       wr_reg_wa(&hw->desc[0], ad->paddr);
+               wr_reg_wa(&hw->desc[0], ad->paddr);
                break;
        case PLANE1_AOI0:
                cmfbi = &data->mfb[2];
@@ -534,8 +549,7 @@ static void fsl_diu_disable_panel(struct fb_info *info)
 
        switch (mfbi->index) {
        case PLANE0:
-               if (hw->desc[0] != data->dummy_ad.paddr)
-                       wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
+               wr_reg_wa(&hw->desc[0], 0);
                break;
        case PLANE1_AOI0:
                cmfbi = &data->mfb[2];
@@ -792,7 +806,8 @@ static void update_lcdc(struct fb_info *info)
 
        hw = data->diu_reg;
 
-       diu_ops.set_monitor_port(data->monitor_port);
+       if (diu_ops.set_monitor_port)
+               diu_ops.set_monitor_port(data->monitor_port);
        gamma_table_base = data->gamma;
 
        /* Prep for DIU init  - gamma table, cursor table */
@@ -811,12 +826,8 @@ static void update_lcdc(struct fb_info *info)
        out_be32(&hw->gamma, DMA_ADDR(data, gamma));
        out_be32(&hw->cursor, DMA_ADDR(data, cursor));
 
-       out_be32(&hw->bgnd, 0x007F7F7F);        /* BGND */
-       out_be32(&hw->bgnd_wb, 0);              /* BGND_WB */
-       out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
-                                               /* DISP SIZE */
-       out_be32(&hw->wb_size, 0); /* WB SIZE */
-       out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
+       out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
+       out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
 
        /* Horizontal and vertical configuration register */
        temp = var->left_margin << 22 | /* BP_H */
@@ -833,9 +844,20 @@ static void update_lcdc(struct fb_info *info)
 
        diu_ops.set_pixel_clock(var->pixclock);
 
-       out_be32(&hw->syn_pol, 0);      /* SYNC SIGNALS POLARITY */
-       out_be32(&hw->int_status, 0);   /* INTERRUPT STATUS */
+#ifndef CONFIG_PPC_MPC512x
+       /*
+        * The PLUT register is defined differently on the MPC5121 than it
+        * is on other SOCs.  Unfortunately, there's no documentation that
+        * explains how it's supposed to be programmed, so for now, we leave
+        * it at the default value on the MPC5121.
+        *
+        * For other SOCs, program it for the highest priority, which will
+        * reduce the chance of underrun. Technically, we should scale the
+        * priority to match the screen resolution, but doing that properly
+        * requires delicate fine-tuning for each use-case.
+        */
        out_be32(&hw->plut, 0x01F5F666);
+#endif
 
        /* Enable the DIU */
        enable_lcdc(info);
@@ -965,7 +987,6 @@ static int fsl_diu_set_par(struct fb_info *info)
        hw = data->diu_reg;
 
        set_fix(info);
-       mfbi->cursor_reset = 1;
 
        len = info->var.yres_virtual * info->fix.line_length;
        /* Alloc & dealloc each time resolution/bpp change */
@@ -1107,6 +1128,12 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
 
        if (!arg)
                return -EINVAL;
+
+       dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd,
+               _IOC_DIR(cmd) & _IOC_READ ? "R" : "",
+               _IOC_DIR(cmd) & _IOC_WRITE ? "W" : "",
+               _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
+
        switch (cmd) {
        case MFB_SET_PIXFMT_OLD:
                dev_warn(info->dev,
@@ -1180,6 +1207,23 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
                        ad->ckmin_b = ck.blue_min;
                }
                break;
+#ifdef CONFIG_PPC_MPC512x
+       case MFB_SET_GAMMA: {
+               struct fsl_diu_data *data = mfbi->parent;
+
+               if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
+                       return -EFAULT;
+               setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
+               break;
+       }
+       case MFB_GET_GAMMA: {
+               struct fsl_diu_data *data = mfbi->parent;
+
+               if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
+                       return -EFAULT;
+               break;
+       }
+#endif
        default:
                dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
                return -ENOIOCTLCMD;
@@ -1206,8 +1250,22 @@ static int fsl_diu_open(struct fb_info *info, int user)
                res = fsl_diu_set_par(info);
                if (res < 0)
                        mfbi->count--;
-               else
+               else {
+                       struct fsl_diu_data *data = mfbi->parent;
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+                       /*
+                        * Enable underrun detection and vertical sync
+                        * interrupts.
+                        */
+                       clrbits32(&data->diu_reg->int_mask,
+                                 INT_UNDRUN | INT_VSYNC);
+#else
+                       /* Enable underrun detection */
+                       clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
+#endif
                        fsl_diu_enable_panel(info);
+               }
        }
 
        spin_unlock(&diu_lock);
@@ -1223,8 +1281,13 @@ static int fsl_diu_release(struct fb_info *info, int user)
 
        spin_lock(&diu_lock);
        mfbi->count--;
-       if (mfbi->count == 0)
+       if (mfbi->count == 0) {
+               struct fsl_diu_data *data = mfbi->parent;
+
+               /* Disable interrupts */
+               out_be32(&data->diu_reg->int_mask, 0xffffffff);
                fsl_diu_disable_panel(info);
+       }
 
        spin_unlock(&diu_lock);
        return res;
@@ -1248,6 +1311,7 @@ static int __devinit install_fb(struct fb_info *info)
 {
        int rc;
        struct mfb_info *mfbi = info->par;
+       struct fsl_diu_data *data = mfbi->parent;
        const char *aoi_mode, *init_aoi_mode = "320x240";
        struct fb_videomode *db = fsl_diu_mode_db;
        unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
@@ -1264,9 +1328,9 @@ static int __devinit install_fb(struct fb_info *info)
                return rc;
 
        if (mfbi->index == PLANE0) {
-               if (mfbi->edid_data) {
+               if (data->has_edid) {
                        /* Now build modedb from EDID */
-                       fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
+                       fb_edid_to_monspecs(data->edid_data, &info->monspecs);
                        fb_videomode_to_modelist(info->monspecs.modedb,
                                                 info->monspecs.modedb_len,
                                                 &info->modelist);
@@ -1284,7 +1348,7 @@ static int __devinit install_fb(struct fb_info *info)
                 * For plane 0 we continue and look into
                 * driver's internal modedb.
                 */
-               if ((mfbi->index == PLANE0) && mfbi->edid_data)
+               if ((mfbi->index == PLANE0) && data->has_edid)
                        has_default_mode = 0;
                else
                        return -EINVAL;
@@ -1348,9 +1412,6 @@ static void uninstall_fb(struct fb_info *info)
        if (!mfbi->registered)
                return;
 
-       if (mfbi->index == PLANE0)
-               kfree(mfbi->edid_data);
-
        unregister_framebuffer(info);
        unmap_video_memory(info);
        if (&info->cmap)
@@ -1362,7 +1423,7 @@ static void uninstall_fb(struct fb_info *info)
 static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
 {
        struct diu __iomem *hw = dev_id;
-       unsigned int status = in_be32(&hw->int_status);
+       uint32_t status = in_be32(&hw->int_status);
 
        if (status) {
                /* This is the workaround for underrun */
@@ -1387,40 +1448,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
        return IRQ_NONE;
 }
 
-static int request_irq_local(struct fsl_diu_data *data)
-{
-       struct diu __iomem *hw = data->diu_reg;
-       u32 ints;
-       int ret;
-
-       /* Read to clear the status */
-       in_be32(&hw->int_status);
-
-       ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
-       if (!ret) {
-               ints = INT_PARERR | INT_LS_BF_VS;
-#if !defined(CONFIG_NOT_COHERENT_CACHE)
-               ints |= INT_VSYNC;
-#endif
-
-               /* Read to clear the status */
-               in_be32(&hw->int_status);
-               out_be32(&hw->int_mask, ints);
-       }
-
-       return ret;
-}
-
-static void free_irq_local(struct fsl_diu_data *data)
-{
-       struct diu __iomem *hw = data->diu_reg;
-
-       /* Disable all LCDC interrupt */
-       out_be32(&hw->int_mask, 0x1f);
-
-       free_irq(data->irq, NULL);
-}
-
 #ifdef CONFIG_PM
 /*
  * Power management hooks. Note that we won't be called from IRQ context,
@@ -1496,8 +1523,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct mfb_info *mfbi;
        struct fsl_diu_data *data;
-       int diu_mode;
        dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
+       const void *prop;
        unsigned int i;
        int ret;
 
@@ -1541,17 +1568,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
                memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
                mfbi->parent = data;
                mfbi->ad = &data->ad[i];
+       }
 
-               if (mfbi->index == PLANE0) {
-                       const u8 *prop;
-                       int len;
-
-                       /* Get EDID */
-                       prop = of_get_property(np, "edid", &len);
-                       if (prop && len == EDID_LENGTH)
-                               mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
-                                                         GFP_KERNEL);
-               }
+       /* Get the EDID data from the device tree, if present */
+       prop = of_get_property(np, "edid", &ret);
+       if (prop && ret == EDID_LENGTH) {
+               memcpy(data->edid_data, prop, EDID_LENGTH);
+               data->has_edid = true;
        }
 
        data->diu_reg = of_iomap(np, 0);
@@ -1561,10 +1584,6 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
                goto error;
        }
 
-       diu_mode = in_be32(&data->diu_reg->diu_mode);
-       if (diu_mode == MFB_MODE0)
-               out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
-
        /* Get the IRQ of the DIU */
        data->irq = irq_of_parse_and_map(np, 0);
 
@@ -1586,11 +1605,11 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
        data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
 
        /*
-        * Let DIU display splash screen if it was pre-initialized
-        * by the bootloader, set dummy area descriptor otherwise.
+        * Let DIU continue to display splash screen if it was pre-initialized
+        * by the bootloader; otherwise, clear the display.
         */
-       if (diu_mode == MFB_MODE0)
-               out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
+       if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
+               out_be32(&data->diu_reg->desc[0], 0);
 
        out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
        out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
@@ -1603,7 +1622,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
                }
        }
 
-       if (request_irq_local(data)) {
+       /*
+        * Older versions of U-Boot leave interrupts enabled, so disable
+        * all of them and clear the status register.
+        */
+       out_be32(&data->diu_reg->int_mask, 0xffffffff);
+       in_be32(&data->diu_reg->int_status);
+
+       ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
+                         &data->diu_reg);
+       if (ret) {
                dev_err(&pdev->dev, "could not claim irq\n");
                goto error;
        }
@@ -1638,7 +1666,8 @@ static int fsl_diu_remove(struct platform_device *pdev)
 
        data = dev_get_drvdata(&pdev->dev);
        disable_lcdc(&data->fsl_diu_info[0]);
-       free_irq_local(data);
+
+       free_irq(data->irq, &data->diu_reg);
 
        for (i = 0; i < NUM_AOIS; i++)
                uninstall_fb(&data->fsl_diu_info[i]);
@@ -1741,6 +1770,9 @@ static int __init fsl_diu_init(void)
        coherence_data_size = be32_to_cpup(prop) * 13;
        coherence_data_size /= 8;
 
+       pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
+                coherence_data_size);
+
        prop = of_get_property(np, "d-cache-line-size", NULL);
        if (prop == NULL) {
                pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
@@ -1750,10 +1782,17 @@ static int __init fsl_diu_init(void)
        }
        d_cache_line_size = be32_to_cpup(prop);
 
+       pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
+                d_cache_line_size);
+
        of_node_put(np);
        coherence_data = vmalloc(coherence_data_size);
-       if (!coherence_data)
+       if (!coherence_data) {
+               pr_err("fsl-diu-fb: could not allocate coherence data "
+                      "(size=%zu)\n", coherence_data_size);
                return -ENOMEM;
+       }
+
 #endif
 
        ret = platform_driver_register(&fsl_diu_driver);
index d877c361abdaa02405133cd12b9d23288aa82662..346d67d6cf4d5a24c6465388e4e7d166356dc5b3 100644 (file)
@@ -1,6 +1,3 @@
-config OMAP2_VRAM
-       bool
-
 config OMAP2_VRFB
        bool
 
index 5ddef129f79826e8fadda55cb052204b220cb041..5ea7cb9aed17b9d666bfdba808b889d745fa8ffb 100644 (file)
@@ -1,4 +1,3 @@
-obj-$(CONFIG_OMAP2_VRAM) += vram.o
 obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
 
 obj-$(CONFIG_OMAP2_DSS) += dss/
index c835aa70f96fb64829e7b7a8f8a328a64dd720e3..65eb76c840a113765ba6afdae85428c2f24e478f 100644 (file)
@@ -710,27 +710,6 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int acx_panel_suspend(struct omap_dss_device *dssdev)
-{
-       dev_dbg(&dssdev->dev, "%s\n", __func__);
-       acx_panel_power_off(dssdev);
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-       return 0;
-}
-
-static int acx_panel_resume(struct omap_dss_device *dssdev)
-{
-       int r;
-
-       dev_dbg(&dssdev->dev, "%s\n", __func__);
-       r = acx_panel_power_on(dssdev);
-       if (r)
-               return r;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-       return 0;
-}
-
 static void acx_panel_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
@@ -752,8 +731,6 @@ static struct omap_dss_driver acx_panel_driver = {
 
        .enable         = acx_panel_enable,
        .disable        = acx_panel_disable,
-       .suspend        = acx_panel_suspend,
-       .resume         = acx_panel_resume,
 
        .set_timings    = acx_panel_set_timings,
        .check_timings  = acx_panel_check_timings,
index 88295c526815e76a628e1e5641902e1ceac0b07d..54ca8ae21078c971496911443a110b89e32cae80 100644 (file)
@@ -688,40 +688,6 @@ static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
        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)
-{
-       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)
-               goto err;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-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)
 {
@@ -769,8 +735,6 @@ static struct omap_dss_driver dpi_driver = {
 
        .enable         = generic_dpi_panel_enable,
        .disable        = generic_dpi_panel_disable,
-       .suspend        = generic_dpi_panel_suspend,
-       .resume         = generic_dpi_panel_resume,
 
        .set_timings    = generic_dpi_panel_set_timings,
        .get_timings    = generic_dpi_panel_get_timings,
index 90c1cabf244e183ea7572b083a3a2b9a9fa3cc69..ace419b801eb6c302fadb26757ffcde8f78fba09 100644 (file)
@@ -143,46 +143,12 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&ld->lock);
 }
 
-static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
-{
-       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-
-       mutex_lock(&ld->lock);
-
-       lb035q02_panel_power_off(dssdev);
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       mutex_unlock(&ld->lock);
-       return 0;
-}
-
-static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
-{
-       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-       int r;
-
-       mutex_lock(&ld->lock);
-
-       r = lb035q02_panel_power_on(dssdev);
-       if (r)
-               goto err;
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       mutex_unlock(&ld->lock);
-       return 0;
-err:
-       mutex_unlock(&ld->lock);
-       return r;
-}
-
 static struct omap_dss_driver lb035q02_driver = {
        .probe          = lb035q02_panel_probe,
        .remove         = lb035q02_panel_remove,
 
        .enable         = lb035q02_panel_enable,
        .disable        = lb035q02_panel_disable,
-       .suspend        = lb035q02_panel_suspend,
-       .resume         = lb035q02_panel_resume,
 
        .driver         = {
                .name   = "lgphilips_lb035q02_panel",
index 3fc5ad081a212906c92c69497436ddbe08a8807f..d1cb722fcdbcea123247b6530d296d5539e3cc9e 100644 (file)
@@ -574,54 +574,6 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&ddata->lock);
 }
 
-static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = get_drv_data(dssdev);
-
-       dev_dbg(&dssdev->dev, "suspend\n");
-
-       mutex_lock(&ddata->lock);
-
-       rfbi_bus_lock();
-
-       n8x0_panel_power_off(dssdev);
-
-       rfbi_bus_unlock();
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       mutex_unlock(&ddata->lock);
-
-       return 0;
-}
-
-static int n8x0_panel_resume(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = get_drv_data(dssdev);
-       int r;
-
-       dev_dbg(&dssdev->dev, "resume\n");
-
-       mutex_lock(&ddata->lock);
-
-       rfbi_bus_lock();
-
-       r = n8x0_panel_power_on(dssdev);
-
-       rfbi_bus_unlock();
-
-       if (r) {
-               mutex_unlock(&ddata->lock);
-               return r;
-       }
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       mutex_unlock(&ddata->lock);
-
-       return 0;
-}
-
 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
                u16 *xres, u16 *yres)
 {
@@ -683,8 +635,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
 
        .enable         = n8x0_panel_enable,
        .disable        = n8x0_panel_disable,
-       .suspend        = n8x0_panel_suspend,
-       .resume         = n8x0_panel_resume,
 
        .update         = n8x0_panel_update,
        .sync           = n8x0_panel_sync,
@@ -702,18 +652,25 @@ static struct omap_dss_driver n8x0_panel_driver = {
 
 static int mipid_spi_probe(struct spi_device *spi)
 {
+       int r;
+
        dev_dbg(&spi->dev, "mipid_spi_probe\n");
 
        spi->mode = SPI_MODE_0;
 
        s_drv_data.spidev = spi;
 
-       return 0;
+       r = omap_dss_register_driver(&n8x0_panel_driver);
+       if (r)
+               pr_err("n8x0_panel: dss driver registration failed\n");
+
+       return r;
 }
 
 static int mipid_spi_remove(struct spi_device *spi)
 {
        dev_dbg(&spi->dev, "mipid_spi_remove\n");
+       omap_dss_unregister_driver(&n8x0_panel_driver);
        return 0;
 }
 
@@ -725,34 +682,6 @@ static struct spi_driver mipid_spi_driver = {
        .probe  = mipid_spi_probe,
        .remove = __devexit_p(mipid_spi_remove),
 };
+module_spi_driver(mipid_spi_driver);
 
-static int __init n8x0_panel_drv_init(void)
-{
-       int r;
-
-       r = spi_register_driver(&mipid_spi_driver);
-       if (r) {
-               pr_err("n8x0_panel: spi driver registration failed\n");
-               return r;
-       }
-
-       r = omap_dss_register_driver(&n8x0_panel_driver);
-       if (r) {
-               pr_err("n8x0_panel: dss driver registration failed\n");
-               spi_unregister_driver(&mipid_spi_driver);
-               return r;
-       }
-
-       return 0;
-}
-
-static void __exit n8x0_panel_drv_exit(void)
-{
-       spi_unregister_driver(&mipid_spi_driver);
-
-       omap_dss_unregister_driver(&n8x0_panel_driver);
-}
-
-module_init(n8x0_panel_drv_init);
-module_exit(n8x0_panel_drv_exit);
 MODULE_LICENSE("GPL");
index 908fd268f3dc90fd98b3eb4827166a5f5e94214f..2a79c283bebe471b3b9410b2649857b6ec2fe0d0 100644 (file)
@@ -236,28 +236,6 @@ static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
-{
-       nec_8048_panel_power_off(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       return 0;
-}
-
-static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
-{
-       int r;
-
-       r = nec_8048_panel_power_on(dssdev);
-       if (r)
-               return r;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return 0;
-}
-
 static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
 {
        return 16;
@@ -268,8 +246,6 @@ static struct omap_dss_driver nec_8048_driver = {
        .remove                 = nec_8048_panel_remove,
        .enable                 = nec_8048_panel_enable,
        .disable                = nec_8048_panel_disable,
-       .suspend                = nec_8048_panel_suspend,
-       .resume                 = nec_8048_panel_resume,
        .get_recommended_bpp    = nec_8048_recommended_bpp,
 
        .driver         = {
index 9df87640ddd2b0ed574d93e30c69492756167628..1b94018aac3e0c840f7c7f59e419c5e7eee993bb 100644 (file)
@@ -50,6 +50,7 @@ struct picodlp_i2c_data {
 
 static struct i2c_device_id picodlp_i2c_id[] = {
        { "picodlp_i2c_driver", 0 },
+       { }
 };
 
 struct picodlp_i2c_command {
@@ -503,47 +504,6 @@ static void picodlp_panel_disable(struct omap_dss_device *dssdev)
        dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
 }
 
-static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
-{
-       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-
-       mutex_lock(&picod->lock);
-       /* Turn off DLP Power */
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-               mutex_unlock(&picod->lock);
-               dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
-                                       " panel is not ACTIVE\n");
-               return -EINVAL;
-       }
-
-       picodlp_panel_power_off(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-       mutex_unlock(&picod->lock);
-
-       dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
-       return 0;
-}
-
-static int picodlp_panel_resume(struct omap_dss_device *dssdev)
-{
-       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-       int r;
-
-       mutex_lock(&picod->lock);
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-               mutex_unlock(&picod->lock);
-               dev_err(&dssdev->dev, "unable to resume picodlp panel,"
-                       " panel is not ACTIVE\n");
-               return -EINVAL;
-       }
-
-       r = picodlp_panel_power_on(dssdev);
-       mutex_unlock(&picod->lock);
-       dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
-       return r;
-}
-
 static void picodlp_get_resolution(struct omap_dss_device *dssdev,
                                        u16 *xres, u16 *yres)
 {
@@ -560,9 +520,6 @@ static struct omap_dss_driver picodlp_driver = {
 
        .get_resolution = picodlp_get_resolution,
 
-       .suspend        = picodlp_panel_suspend,
-       .resume         = picodlp_panel_resume,
-
        .driver         = {
                .name   = "picodlp_panel",
                .owner  = THIS_MODULE,
index 1ec3b277ff155edca2861be48f3d013b01334aa1..cada8c621e01bd2f4724c82f61b2557dce9237f5 100644 (file)
@@ -194,29 +194,12 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
-{
-       sharp_ls_power_off(dssdev);
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-       return 0;
-}
-
-static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
-{
-       int r;
-       r = sharp_ls_power_on(dssdev);
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-       return r;
-}
-
 static struct omap_dss_driver sharp_ls_driver = {
        .probe          = sharp_ls_panel_probe,
        .remove         = __exit_p(sharp_ls_panel_remove),
 
        .enable         = sharp_ls_panel_enable,
        .disable        = sharp_ls_panel_disable,
-       .suspend        = sharp_ls_panel_suspend,
-       .resume         = sharp_ls_panel_resume,
 
        .driver         = {
                .name   = "sharp_ls_panel",
index f2f644680ca8dfe2262fac39c42fcd50766982f0..a32407a5735af59b123c8865c6dcf2ec3220db7a 100644 (file)
@@ -1245,76 +1245,6 @@ static void taal_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&td->lock);
 }
 
-static int taal_suspend(struct omap_dss_device *dssdev)
-{
-       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       int r;
-
-       dev_dbg(&dssdev->dev, "suspend\n");
-
-       mutex_lock(&td->lock);
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-               r = -EINVAL;
-               goto err;
-       }
-
-       taal_cancel_ulps_work(dssdev);
-       taal_cancel_esd_work(dssdev);
-
-       dsi_bus_lock(dssdev);
-
-       r = taal_wake_up(dssdev);
-       if (!r)
-               taal_power_off(dssdev);
-
-       dsi_bus_unlock(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       mutex_unlock(&td->lock);
-
-       return 0;
-err:
-       mutex_unlock(&td->lock);
-       return r;
-}
-
-static int taal_resume(struct omap_dss_device *dssdev)
-{
-       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       int r;
-
-       dev_dbg(&dssdev->dev, "resume\n");
-
-       mutex_lock(&td->lock);
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-               r = -EINVAL;
-               goto err;
-       }
-
-       dsi_bus_lock(dssdev);
-
-       r = taal_power_on(dssdev);
-
-       dsi_bus_unlock(dssdev);
-
-       if (r) {
-               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-       } else {
-               dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-               taal_queue_esd_work(dssdev);
-       }
-
-       mutex_unlock(&td->lock);
-
-       return r;
-err:
-       mutex_unlock(&td->lock);
-       return r;
-}
-
 static void taal_framedone_cb(int err, void *data)
 {
        struct omap_dss_device *dssdev = data;
@@ -1818,8 +1748,6 @@ static struct omap_dss_driver taal_driver = {
 
        .enable         = taal_enable,
        .disable        = taal_disable,
-       .suspend        = taal_suspend,
-       .resume         = taal_resume,
 
        .update         = taal_update,
        .sync           = taal_sync,
index 383811cf8648bfb199847b9d183d5b50b562cd23..8281baafe1efd39127a628c70ecb3b720034d6f1 100644 (file)
@@ -189,37 +189,6 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&ddata->lock);
 }
 
-static int tfp410_suspend(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-
-       mutex_lock(&ddata->lock);
-
-       tfp410_power_off(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       mutex_unlock(&ddata->lock);
-
-       return 0;
-}
-
-static int tfp410_resume(struct omap_dss_device *dssdev)
-{
-       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-       int r;
-
-       mutex_lock(&ddata->lock);
-
-       r = tfp410_power_on(dssdev);
-       if (r == 0)
-               dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       mutex_unlock(&ddata->lock);
-
-       return r;
-}
-
 static void tfp410_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
@@ -355,8 +324,6 @@ static struct omap_dss_driver tfp410_driver = {
 
        .enable         = tfp410_enable,
        .disable        = tfp410_disable,
-       .suspend        = tfp410_suspend,
-       .resume         = tfp410_resume,
 
        .set_timings    = tfp410_set_timings,
        .get_timings    = tfp410_get_timings,
index b5e6dbc59f0a654c79d9d3b6b40eaba955680c2a..316b3da6d2cb99e356332b3ef218cf3f822c7ab0 100644 (file)
@@ -401,24 +401,6 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int tpo_td043_suspend(struct omap_dss_device *dssdev)
-{
-       dev_dbg(&dssdev->dev, "suspend\n");
-
-       tpo_td043_disable_dss(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       return 0;
-}
-
-static int tpo_td043_resume(struct omap_dss_device *dssdev)
-{
-       dev_dbg(&dssdev->dev, "resume\n");
-
-       return tpo_td043_enable_dss(dssdev);
-}
-
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 {
        struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
@@ -500,8 +482,6 @@ static struct omap_dss_driver tpo_td043_driver = {
 
        .enable         = tpo_td043_enable,
        .disable        = tpo_td043_disable,
-       .suspend        = tpo_td043_suspend,
-       .resume         = tpo_td043_resume,
        .set_mirror     = tpo_td043_set_hmirror,
        .get_mirror     = tpo_td043_get_hmirror,
 
index 80f5390aa1368984266071f21e15e6dca859b0e3..cb0f145c7077897721dce128aa0369ce4f6953c8 100644 (file)
@@ -1,33 +1,30 @@
 menuconfig OMAP2_DSS
         tristate "OMAP2+ Display Subsystem support"
-        depends on ARCH_OMAP2PLUS
         help
          OMAP2+ Display Subsystem support.
 
 if OMAP2_DSS
 
-config OMAP2_VRAM_SIZE
-       int "VRAM size (MB)"
-       range 0 32
-       default 0
+config OMAP2_DSS_DEBUG
+       bool "Debug support"
+       default n
        help
-         The amount of SDRAM to reserve at boot time for video RAM use.
-         This VRAM will be used by omapfb and other drivers that need
-         large continuous RAM area for video use.
+         This enables printing of debug messages. Alternatively, debug messages
+         can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
+         appropriate flags in <debugfs>/dynamic_debug/control.
 
-         You can also set this with "vram=<bytes>" kernel argument, or
-         in the board file.
-
-config OMAP2_DSS_DEBUG_SUPPORT
-        bool "Debug support"
-       default y
+config OMAP2_DSS_DEBUGFS
+       bool "Debugfs filesystem support"
+       depends on DEBUG_FS
+       default n
        help
-         This enables debug messages. You need to enable printing
-         with 'debug' module parameter.
+         This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
+         querying about clock configuration and register configuration of dss,
+         dispc, dsi, hdmi and rfbi.
 
 config OMAP2_DSS_COLLECT_IRQ_STATS
        bool "Collect DSS IRQ statistics"
-       depends on OMAP2_DSS_DEBUG_SUPPORT
+       depends on OMAP2_DSS_DEBUGFS
        default n
        help
          Collect DSS IRQ statistics, printable via debugfs.
@@ -62,7 +59,6 @@ config OMAP2_DSS_VENC
 
 config OMAP4_DSS_HDMI
        bool "HDMI support"
-       depends on ARCH_OMAP4
         default y
        help
          HDMI Interface. This adds the High Definition Multimedia Interface.
@@ -70,11 +66,9 @@ config OMAP4_DSS_HDMI
 
 config OMAP4_DSS_HDMI_AUDIO
        bool
-       depends on OMAP4_DSS_HDMI
 
 config OMAP2_DSS_SDI
        bool "SDI support"
-       depends on ARCH_OMAP3
         default n
        help
          SDI (Serial Display Interface) support.
@@ -84,7 +78,6 @@ config OMAP2_DSS_SDI
 
 config OMAP2_DSS_DSI
        bool "DSI support"
-       depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
         default n
        help
          MIPI DSI (Display Serial Interface) support.
index 4549869bfe1a75ef6ffb1262409d918295151754..61949ff7940cf4257d7d2c489eb6fe4960436b15 100644 (file)
@@ -1,6 +1,10 @@
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
+# Core DSS files
 omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
-       manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
+       output.o
+# DSS compat layer files
+omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
+       dispc-compat.o display-sysfs.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
@@ -8,3 +12,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
                                    hdmi_panel.o ti_hdmi_4xxx_ip.o
+ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
index 19d66f471b4bae9eafe0331b511a24265f4717ee..d446bdfc4c821fc4a26caf401716cc843cef370a 100644 (file)
@@ -18,6 +18,7 @@
 #define DSS_SUBSYS_NAME "APPLY"
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
@@ -26,6 +27,7 @@
 
 #include "dss.h"
 #include "dss_features.h"
+#include "dispc-compat.h"
 
 /*
  * We have 4 levels of cache for the dispc settings. First two are in SW and
@@ -70,7 +72,6 @@ struct ovl_priv_data {
        bool shadow_extra_info_dirty;
 
        bool enabled;
-       enum omap_channel channel;
        u32 fifo_low, fifo_high;
 
        /*
@@ -105,6 +106,9 @@ struct mgr_priv_data {
 
        struct omap_video_timings timings;
        struct dss_lcd_mgr_config lcd_config;
+
+       void (*framedone_handler)(void *);
+       void *framedone_handler_data;
 };
 
 static struct {
@@ -132,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
        return &dss_data.mgr_priv_data_array[mgr->id];
 }
 
-void dss_apply_init(void)
+static void apply_init_priv(void)
 {
        const int num_ovls = dss_feat_get_num_ovls();
        struct mgr_priv_data *mp;
@@ -414,11 +418,46 @@ static void wait_pending_extra_info_updates(void)
        r = wait_for_completion_timeout(&extra_updated_completion, t);
        if (r == 0)
                DSSWARN("timeout in wait_pending_extra_info_updates\n");
-       else if (r < 0)
-               DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
 }
 
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
+{
+       return ovl->manager ?
+               (ovl->manager->output ? ovl->manager->output->device : NULL) :
+               NULL;
+}
+
+static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
+{
+       return mgr->output ? mgr->output->device : NULL;
+}
+
+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;
+
+       r = dispc_runtime_get();
+       if (r)
+               return r;
+
+       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+               irq = DISPC_IRQ_EVSYNC_ODD;
+       else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
+               irq = DISPC_IRQ_EVSYNC_EVEN;
+       else
+               irq = dispc_mgr_get_vsync_irq(mgr->id);
+
+       r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+
+       dispc_runtime_put();
+
+       return r;
+}
+
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
        unsigned long timeout = msecs_to_jiffies(500);
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -488,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
        return r;
 }
 
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
 {
        unsigned long timeout = msecs_to_jiffies(500);
        struct ovl_priv_data *op;
@@ -573,7 +612,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
        struct mgr_priv_data *mp;
        int r;
 
-       DSSDBGF("%d", ovl->id);
+       DSSDBG("writing ovl %d regs", ovl->id);
 
        if (!op->enabled || !op->info_dirty)
                return;
@@ -608,7 +647,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        struct mgr_priv_data *mp;
 
-       DSSDBGF("%d", ovl->id);
+       DSSDBG("writing ovl %d regs extra", ovl->id);
 
        if (!op->extra_info_dirty)
                return;
@@ -617,7 +656,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
         * disabled */
 
        dispc_ovl_enable(ovl->id, op->enabled);
-       dispc_ovl_set_channel_out(ovl->id, op->channel);
        dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
        mp = get_mgr_priv(ovl->manager);
@@ -632,7 +670,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        struct omap_overlay *ovl;
 
-       DSSDBGF("%d", mgr->id);
+       DSSDBG("writing mgr %d regs", mgr->id);
 
        if (!mp->enabled)
                return;
@@ -658,7 +696,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
-       DSSDBGF("%d", mgr->id);
+       DSSDBG("writing mgr %d regs extra", mgr->id);
 
        if (!mp->extra_info_dirty)
                return;
@@ -666,22 +704,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
        dispc_mgr_set_timings(mgr->id, &mp->timings);
 
        /* lcd_config parameters */
-       if (dss_mgr_is_lcd(mgr->id)) {
-               dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
-
-               dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
-               dispc_mgr_enable_fifohandcheck(mgr->id,
-                       mp->lcd_config.fifohandcheck);
-
-               dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
-
-               dispc_mgr_set_tft_data_lines(mgr->id,
-                       mp->lcd_config.video_port_width);
-
-               dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
-
-               dispc_mgr_set_lcd_type_tft(mgr->id);
-       }
+       if (dss_mgr_is_lcd(mgr->id))
+               dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
 
        mp->extra_info_dirty = false;
        if (mp->updating)
@@ -761,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
        }
 }
 
-void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
@@ -786,9 +810,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
        if (!dss_data.irq_enabled && need_isr())
                dss_register_vsync_isr();
 
-       dispc_mgr_enable(mgr->id, true);
-
-       mgr_clear_shadow_dirty(mgr);
+       dispc_mgr_enable_sync(mgr->id);
 
        spin_unlock_irqrestore(&data_lock, flags);
 }
@@ -845,7 +867,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
        for (i = 0; i < num_mgrs; i++) {
                struct omap_overlay_manager *mgr;
                struct mgr_priv_data *mp;
-               bool was_updating;
 
                mgr = omap_dss_get_overlay_manager(i);
                mp = get_mgr_priv(mgr);
@@ -853,7 +874,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
                if (!mp->enabled)
                        continue;
 
-               was_updating = mp->updating;
                mp->updating = dispc_mgr_is_enabled(i);
 
                if (!mgr_manual_update(mgr)) {
@@ -872,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
        if (!extra_updating)
                complete_all(&extra_updated_completion);
 
+       /* call framedone handlers for manual update displays */
+       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 (!mgr_manual_update(mgr) || !mp->framedone_handler)
+                       continue;
+
+               if (mask & dispc_mgr_get_framedone_irq(i))
+                       mp->framedone_handler(mp->framedone_handler_data);
+       }
+
        if (!need_isr())
                dss_unregister_vsync_isr();
 
@@ -906,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
        mp->info = mp->user_info;
 }
 
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 {
        unsigned long flags;
        struct omap_overlay *ovl;
@@ -1005,7 +1040,7 @@ static void dss_setup_fifos(void)
        }
 }
 
-int dss_mgr_enable(struct omap_overlay_manager *mgr)
+static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
@@ -1035,10 +1070,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
        if (!mgr_manual_update(mgr))
                mp->updating = true;
 
+       if (!dss_data.irq_enabled && need_isr())
+               dss_register_vsync_isr();
+
        spin_unlock_irqrestore(&data_lock, flags);
 
        if (!mgr_manual_update(mgr))
-               dispc_mgr_enable(mgr->id, true);
+               dispc_mgr_enable_sync(mgr->id);
 
 out:
        mutex_unlock(&apply_lock);
@@ -1052,7 +1090,7 @@ err:
        return r;
 }
 
-void dss_mgr_disable(struct omap_overlay_manager *mgr)
+static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
@@ -1063,7 +1101,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
                goto out;
 
        if (!mgr_manual_update(mgr))
-               dispc_mgr_enable(mgr->id, false);
+               dispc_mgr_disable_sync(mgr->id);
 
        spin_lock_irqsave(&data_lock, flags);
 
@@ -1076,7 +1114,7 @@ out:
        mutex_unlock(&apply_lock);
 }
 
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
+static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
                struct omap_overlay_manager_info *info)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1097,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
        return 0;
 }
 
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
+static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
                struct omap_overlay_manager_info *info)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1110,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
        spin_unlock_irqrestore(&data_lock, flags);
 }
 
-int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
                struct omap_dss_output *output)
 {
        int r;
@@ -1142,7 +1180,7 @@ err:
        return r;
 }
 
-int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
+static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
 {
        int r;
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1189,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
        mp->extra_info_dirty = true;
 }
 
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
                const struct omap_video_timings *timings)
 {
        unsigned long flags;
@@ -1217,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
        mp->extra_info_dirty = true;
 }
 
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
                const struct dss_lcd_mgr_config *config)
 {
        unsigned long flags;
@@ -1236,7 +1274,7 @@ out:
        spin_unlock_irqrestore(&data_lock, flags);
 }
 
-int dss_ovl_set_info(struct omap_overlay *ovl,
+static int dss_ovl_set_info(struct omap_overlay *ovl,
                struct omap_overlay_info *info)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1257,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
        return 0;
 }
 
-void dss_ovl_get_info(struct omap_overlay *ovl,
+static void dss_ovl_get_info(struct omap_overlay *ovl,
                struct omap_overlay_info *info)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1270,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
        spin_unlock_irqrestore(&data_lock, flags);
 }
 
-int dss_ovl_set_manager(struct omap_overlay *ovl,
+static int dss_ovl_set_manager(struct omap_overlay *ovl,
                struct omap_overlay_manager *mgr)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1289,45 +1327,40 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
                goto err;
        }
 
+       r = dispc_runtime_get();
+       if (r)
+               goto err;
+
        spin_lock_irqsave(&data_lock, flags);
 
        if (op->enabled) {
                spin_unlock_irqrestore(&data_lock, flags);
                DSSERR("overlay has to be disabled to change the manager\n");
                r = -EINVAL;
-               goto err;
+               goto err1;
        }
 
-       op->channel = mgr->id;
-       op->extra_info_dirty = true;
+       dispc_ovl_set_channel_out(ovl->id, mgr->id);
 
        ovl->manager = mgr;
        list_add_tail(&ovl->list, &mgr->overlays);
 
        spin_unlock_irqrestore(&data_lock, flags);
 
-       /* XXX: When there is an overlay on a DSI manual update display, and
-        * the overlay is first disabled, then moved to tv, and enabled, we
-        * seem to get SYNC_LOST_DIGIT error.
-        *
-        * Waiting doesn't seem to help, but updating the manual update display
-        * after disabling the overlay seems to fix this. This hints that the
-        * overlay is perhaps somehow tied to the LCD output until the output
-        * is updated.
-        *
-        * Userspace workaround for this is to update the LCD after disabling
-        * the overlay, but before moving the overlay to TV.
-        */
+       dispc_runtime_put();
 
        mutex_unlock(&apply_lock);
 
        return 0;
+
+err1:
+       dispc_runtime_put();
 err:
        mutex_unlock(&apply_lock);
        return r;
 }
 
-int dss_ovl_unset_manager(struct omap_overlay *ovl)
+static int dss_ovl_unset_manager(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
@@ -1355,9 +1388,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
        /* wait for pending extra_info updates to ensure the ovl is disabled */
        wait_pending_extra_info_updates();
 
+       /*
+        * For a manual update display, there is no guarantee that the overlay
+        * is really disabled in HW, we may need an extra update from this
+        * manager before the configurations can go in. Return an error if the
+        * overlay needed an update from the manager.
+        *
+        * TODO: Instead of returning an error, try to do a dummy manager update
+        * here to disable the overlay in hardware. Use the *GATED fields in
+        * the DISPC_CONFIG registers to do a dummy update.
+        */
        spin_lock_irqsave(&data_lock, flags);
 
-       op->channel = -1;
+       if (ovl_manual_update(ovl) && op->extra_info_dirty) {
+               spin_unlock_irqrestore(&data_lock, flags);
+               DSSERR("need an update to change the manager\n");
+               r = -EINVAL;
+               goto err;
+       }
 
        ovl->manager = NULL;
        list_del(&ovl->list);
@@ -1372,7 +1420,7 @@ err:
        return r;
 }
 
-bool dss_ovl_is_enabled(struct omap_overlay *ovl)
+static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
@@ -1387,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
        return e;
 }
 
-int dss_ovl_enable(struct omap_overlay *ovl)
+static int dss_ovl_enable(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
@@ -1437,7 +1485,7 @@ err1:
        return r;
 }
 
-int dss_ovl_disable(struct omap_overlay *ovl)
+static int dss_ovl_disable(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
@@ -1472,3 +1520,152 @@ err:
        return r;
 }
 
+static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data)
+{
+       struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+       if (mp->framedone_handler)
+               return -EBUSY;
+
+       mp->framedone_handler = handler;
+       mp->framedone_handler_data = data;
+
+       return 0;
+}
+
+static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data)
+{
+       struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+       WARN_ON(mp->framedone_handler != handler ||
+                       mp->framedone_handler_data != data);
+
+       mp->framedone_handler = NULL;
+       mp->framedone_handler_data = NULL;
+}
+
+static const struct dss_mgr_ops apply_mgr_ops = {
+       .start_update = dss_mgr_start_update_compat,
+       .enable = dss_mgr_enable_compat,
+       .disable = dss_mgr_disable_compat,
+       .set_timings = dss_mgr_set_timings_compat,
+       .set_lcd_config = dss_mgr_set_lcd_config_compat,
+       .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
+       .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
+};
+
+static int compat_refcnt;
+static DEFINE_MUTEX(compat_init_lock);
+
+int omapdss_compat_init(void)
+{
+       struct platform_device *pdev = dss_get_core_pdev();
+       struct omap_dss_device *dssdev = NULL;
+       int i, r;
+
+       mutex_lock(&compat_init_lock);
+
+       if (compat_refcnt++ > 0)
+               goto out;
+
+       apply_init_priv();
+
+       dss_init_overlay_managers(pdev);
+       dss_init_overlays(pdev);
+
+       for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+               struct omap_overlay_manager *mgr;
+
+               mgr = omap_dss_get_overlay_manager(i);
+
+               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;
+       }
+
+       for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+               struct omap_overlay *ovl = omap_dss_get_overlay(i);
+
+               ovl->is_enabled = &dss_ovl_is_enabled;
+               ovl->enable = &dss_ovl_enable;
+               ovl->disable = &dss_ovl_disable;
+               ovl->set_manager = &dss_ovl_set_manager;
+               ovl->unset_manager = &dss_ovl_unset_manager;
+               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;
+       }
+
+       r = dss_install_mgr_ops(&apply_mgr_ops);
+       if (r)
+               goto err_mgr_ops;
+
+       for_each_dss_dev(dssdev) {
+               r = display_init_sysfs(pdev, dssdev);
+               /* XXX uninit sysfs files on error */
+               if (r)
+                       goto err_disp_sysfs;
+       }
+
+       dispc_runtime_get();
+
+       r = dss_dispc_initialize_irq();
+       if (r)
+               goto err_init_irq;
+
+       dispc_runtime_put();
+
+out:
+       mutex_unlock(&compat_init_lock);
+
+       return 0;
+
+err_init_irq:
+       dispc_runtime_put();
+
+err_disp_sysfs:
+       dss_uninstall_mgr_ops();
+
+err_mgr_ops:
+       dss_uninit_overlay_managers(pdev);
+       dss_uninit_overlays(pdev);
+
+       compat_refcnt--;
+
+       mutex_unlock(&compat_init_lock);
+
+       return r;
+}
+EXPORT_SYMBOL(omapdss_compat_init);
+
+void omapdss_compat_uninit(void)
+{
+       struct platform_device *pdev = dss_get_core_pdev();
+       struct omap_dss_device *dssdev = NULL;
+
+       mutex_lock(&compat_init_lock);
+
+       if (--compat_refcnt > 0)
+               goto out;
+
+       dss_dispc_uninitialize_irq();
+
+       for_each_dss_dev(dssdev)
+               display_uninit_sysfs(pdev, dssdev);
+
+       dss_uninstall_mgr_ops();
+
+       dss_uninit_overlay_managers(pdev);
+       dss_uninit_overlays(pdev);
+out:
+       mutex_unlock(&compat_init_lock);
+}
+EXPORT_SYMBOL(omapdss_compat_uninit);
index d94ef9e31a354b877f2eb3dcee6cb4be1bda2462..f8779d4750ba63f98908492f2b11b9bfe7cf4ea8 100644 (file)
@@ -53,15 +53,23 @@ static char *def_disp_name;
 module_param_named(def_disp, def_disp_name, charp, 0);
 MODULE_PARM_DESC(def_disp, "default display name");
 
-#ifdef DEBUG
-bool dss_debug;
-module_param_named(debug, dss_debug, bool, 0644);
-#endif
-
-const char *dss_get_default_display_name(void)
+const char *omapdss_get_default_display_name(void)
 {
        return core.default_display_name;
 }
+EXPORT_SYMBOL(omapdss_get_default_display_name);
+
+enum omapdss_version omapdss_get_version(void)
+{
+       struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+       return pdata->version;
+}
+EXPORT_SYMBOL(omapdss_get_version);
+
+struct platform_device *dss_get_core_pdev(void)
+{
+       return core.pdev;
+}
 
 /* REGULATORS */
 
@@ -93,21 +101,6 @@ struct regulator *dss_get_vdds_sdi(void)
        return reg;
 }
 
-int dss_get_ctx_loss_count(struct device *dev)
-{
-       struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
-       int cnt;
-
-       if (!board_data->get_context_loss_count)
-               return -ENOENT;
-
-       cnt = board_data->get_context_loss_count(dev);
-
-       WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
-       return cnt;
-}
-
 int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
        struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
@@ -122,7 +115,7 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
        struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
 
-       if (!board_data->dsi_enable_pads)
+       if (!board_data->dsi_disable_pads)
                return;
 
        return board_data->dsi_disable_pads(dsi_id, lane_mask);
@@ -138,7 +131,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
                return 0;
 }
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 static int dss_debug_show(struct seq_file *s, void *unused)
 {
        void (*func)(struct seq_file *) = s->private;
@@ -193,7 +186,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 
        return 0;
 }
-#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#else /* CONFIG_OMAP2_DSS_DEBUGFS */
 static inline int dss_initialize_debugfs(void)
 {
        return 0;
@@ -205,7 +198,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 {
        return 0;
 }
-#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
 
 /* PLATFORM DEVICE */
 static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
@@ -237,12 +230,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
 
        core.pdev = pdev;
 
-       dss_features_init(pdata->version);
-
-       dss_apply_init();
-
-       dss_init_overlay_managers(pdev);
-       dss_init_overlays(pdev);
+       dss_features_init(omapdss_get_version());
 
        r = dss_initialize_debugfs();
        if (r)
@@ -268,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)
 
        dss_uninitialize_debugfs();
 
-       dss_uninit_overlays(pdev);
-       dss_uninit_overlay_managers(pdev);
-
        return 0;
 }
 
@@ -358,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
                                dev_name(dev), dssdev->driver_name,
                                dssdrv->driver.name);
 
-       r = dss_init_device(core.pdev, dssdev);
-       if (r)
-               return r;
-
        r = dssdrv->probe(dssdev);
 
        if (r) {
                DSSERR("driver probe failed: %d\n", r);
-               dss_uninit_device(core.pdev, dssdev);
                return r;
        }
 
@@ -387,8 +367,6 @@ static int dss_driver_remove(struct device *dev)
 
        dssdrv->remove(dssdev);
 
-       dss_uninit_device(core.pdev, dssdev);
-
        dssdev->driver = NULL;
 
        return 0;
@@ -507,6 +485,9 @@ static int __init omap_dss_bus_register(void)
 
 /* INIT */
 static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+       dsi_init_platform_driver,
+#endif
 #ifdef CONFIG_OMAP2_DSS_DPI
        dpi_init_platform_driver,
 #endif
@@ -519,15 +500,15 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
 #ifdef CONFIG_OMAP2_DSS_VENC
        venc_init_platform_driver,
 #endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_init_platform_driver,
-#endif
 #ifdef CONFIG_OMAP4_DSS_HDMI
        hdmi_init_platform_driver,
 #endif
 };
 
 static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+       dsi_uninit_platform_driver,
+#endif
 #ifdef CONFIG_OMAP2_DSS_DPI
        dpi_uninit_platform_driver,
 #endif
@@ -540,9 +521,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
 #ifdef CONFIG_OMAP2_DSS_VENC
        venc_uninit_platform_driver,
 #endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_uninit_platform_driver,
-#endif
 #ifdef CONFIG_OMAP4_DSS_HDMI
        hdmi_uninit_platform_driver,
 #endif
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
new file mode 100644 (file)
index 0000000..928884c
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@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/>.
+ */
+
+#define DSS_SUBSYS_NAME "APPLY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "dispc-compat.h"
+
+#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+                                        DISPC_IRQ_OCP_ERR | \
+                                        DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+                                        DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+                                        DISPC_IRQ_SYNC_LOST | \
+                                        DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS              8
+
+struct omap_dispc_isr_data {
+       omap_dispc_isr_t        isr;
+       void                    *arg;
+       u32                     mask;
+};
+
+struct dispc_irq_stats {
+       unsigned long last_reset;
+       unsigned irq_count;
+       unsigned irqs[32];
+};
+
+static struct {
+       spinlock_t irq_lock;
+       u32 irq_error_mask;
+       struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+       u32 error_irqs;
+       struct work_struct error_work;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+       spinlock_t irq_stats_lock;
+       struct dispc_irq_stats irq_stats;
+#endif
+} dispc_compat;
+
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dispc_dump_irqs(struct seq_file *s)
+{
+       unsigned long flags;
+       struct dispc_irq_stats stats;
+
+       spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
+
+       stats = dispc_compat.irq_stats;
+       memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
+       dispc_compat.irq_stats.last_reset = jiffies;
+
+       spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
+
+       seq_printf(s, "period %u ms\n",
+                       jiffies_to_msecs(jiffies - stats.last_reset));
+
+       seq_printf(s, "irqs %d\n", stats.irq_count);
+#define PIS(x) \
+       seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
+
+       PIS(FRAMEDONE);
+       PIS(VSYNC);
+       PIS(EVSYNC_EVEN);
+       PIS(EVSYNC_ODD);
+       PIS(ACBIAS_COUNT_STAT);
+       PIS(PROG_LINE_NUM);
+       PIS(GFX_FIFO_UNDERFLOW);
+       PIS(GFX_END_WIN);
+       PIS(PAL_GAMMA_MASK);
+       PIS(OCP_ERR);
+       PIS(VID1_FIFO_UNDERFLOW);
+       PIS(VID1_END_WIN);
+       PIS(VID2_FIFO_UNDERFLOW);
+       PIS(VID2_END_WIN);
+       if (dss_feat_get_num_ovls() > 3) {
+               PIS(VID3_FIFO_UNDERFLOW);
+               PIS(VID3_END_WIN);
+       }
+       PIS(SYNC_LOST);
+       PIS(SYNC_LOST_DIGIT);
+       PIS(WAKEUP);
+       if (dss_has_feature(FEAT_MGR_LCD2)) {
+               PIS(FRAMEDONE2);
+               PIS(VSYNC2);
+               PIS(ACBIAS_COUNT_STAT2);
+               PIS(SYNC_LOST2);
+       }
+       if (dss_has_feature(FEAT_MGR_LCD3)) {
+               PIS(FRAMEDONE3);
+               PIS(VSYNC3);
+               PIS(ACBIAS_COUNT_STAT3);
+               PIS(SYNC_LOST3);
+       }
+#undef PIS
+}
+#endif
+
+/* dispc.irq_lock has to be locked by the caller */
+static void _omap_dispc_set_irqs(void)
+{
+       u32 mask;
+       int i;
+       struct omap_dispc_isr_data *isr_data;
+
+       mask = dispc_compat.irq_error_mask;
+
+       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+               isr_data = &dispc_compat.registered_isr[i];
+
+               if (isr_data->isr == NULL)
+                       continue;
+
+               mask |= isr_data->mask;
+       }
+
+       dispc_write_irqenable(mask);
+}
+
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+       int i;
+       int ret;
+       unsigned long flags;
+       struct omap_dispc_isr_data *isr_data;
+
+       if (isr == NULL)
+               return -EINVAL;
+
+       spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+       /* check for duplicate entry */
+       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+               isr_data = &dispc_compat.registered_isr[i];
+               if (isr_data->isr == isr && isr_data->arg == arg &&
+                               isr_data->mask == mask) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+       }
+
+       isr_data = NULL;
+       ret = -EBUSY;
+
+       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+               isr_data = &dispc_compat.registered_isr[i];
+
+               if (isr_data->isr != NULL)
+                       continue;
+
+               isr_data->isr = isr;
+               isr_data->arg = arg;
+               isr_data->mask = mask;
+               ret = 0;
+
+               break;
+       }
+
+       if (ret)
+               goto err;
+
+       _omap_dispc_set_irqs();
+
+       spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+       return 0;
+err:
+       spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(omap_dispc_register_isr);
+
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+       int i;
+       unsigned long flags;
+       int ret = -EINVAL;
+       struct omap_dispc_isr_data *isr_data;
+
+       spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+               isr_data = &dispc_compat.registered_isr[i];
+               if (isr_data->isr != isr || isr_data->arg != arg ||
+                               isr_data->mask != mask)
+                       continue;
+
+               /* found the correct isr */
+
+               isr_data->isr = NULL;
+               isr_data->arg = NULL;
+               isr_data->mask = 0;
+
+               ret = 0;
+               break;
+       }
+
+       if (ret == 0)
+               _omap_dispc_set_irqs();
+
+       spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(omap_dispc_unregister_isr);
+
+static void print_irq_status(u32 status)
+{
+       if ((status & dispc_compat.irq_error_mask) == 0)
+               return;
+
+#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
+
+       pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
+               status,
+               PIS(OCP_ERR),
+               PIS(GFX_FIFO_UNDERFLOW),
+               PIS(VID1_FIFO_UNDERFLOW),
+               PIS(VID2_FIFO_UNDERFLOW),
+               dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
+               PIS(SYNC_LOST),
+               PIS(SYNC_LOST_DIGIT),
+               dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
+               dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
+#undef PIS
+}
+
+/* Called from dss.c. Note that we don't touch clocks here,
+ * but we presume they are on because we got an IRQ. However,
+ * an irq handler may turn the clocks off, so we may not have
+ * clock later in the function. */
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
+{
+       int i;
+       u32 irqstatus, irqenable;
+       u32 handledirqs = 0;
+       u32 unhandled_errors;
+       struct omap_dispc_isr_data *isr_data;
+       struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+
+       spin_lock(&dispc_compat.irq_lock);
+
+       irqstatus = dispc_read_irqstatus();
+       irqenable = dispc_read_irqenable();
+
+       /* IRQ is not for us */
+       if (!(irqstatus & irqenable)) {
+               spin_unlock(&dispc_compat.irq_lock);
+               return IRQ_NONE;
+       }
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+       spin_lock(&dispc_compat.irq_stats_lock);
+       dispc_compat.irq_stats.irq_count++;
+       dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
+       spin_unlock(&dispc_compat.irq_stats_lock);
+#endif
+
+       print_irq_status(irqstatus);
+
+       /* Ack the interrupt. Do it here before clocks are possibly turned
+        * off */
+       dispc_clear_irqstatus(irqstatus);
+       /* flush posted write */
+       dispc_read_irqstatus();
+
+       /* make a copy and unlock, so that isrs can unregister
+        * themselves */
+       memcpy(registered_isr, dispc_compat.registered_isr,
+                       sizeof(registered_isr));
+
+       spin_unlock(&dispc_compat.irq_lock);
+
+       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+               isr_data = &registered_isr[i];
+
+               if (!isr_data->isr)
+                       continue;
+
+               if (isr_data->mask & irqstatus) {
+                       isr_data->isr(isr_data->arg, irqstatus);
+                       handledirqs |= isr_data->mask;
+               }
+       }
+
+       spin_lock(&dispc_compat.irq_lock);
+
+       unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
+
+       if (unhandled_errors) {
+               dispc_compat.error_irqs |= unhandled_errors;
+
+               dispc_compat.irq_error_mask &= ~unhandled_errors;
+               _omap_dispc_set_irqs();
+
+               schedule_work(&dispc_compat.error_work);
+       }
+
+       spin_unlock(&dispc_compat.irq_lock);
+
+       return IRQ_HANDLED;
+}
+
+static void dispc_error_worker(struct work_struct *work)
+{
+       int i;
+       u32 errors;
+       unsigned long flags;
+       static const unsigned fifo_underflow_bits[] = {
+               DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+               DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+               DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+               DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+       };
+
+       spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+       errors = dispc_compat.error_irqs;
+       dispc_compat.error_irqs = 0;
+       spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+       dispc_runtime_get();
+
+       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+               struct omap_overlay *ovl;
+               unsigned bit;
+
+               ovl = omap_dss_get_overlay(i);
+               bit = fifo_underflow_bits[i];
+
+               if (bit & errors) {
+                       DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
+                                       ovl->name);
+                       dispc_ovl_enable(ovl->id, false);
+                       dispc_mgr_go(ovl->manager->id);
+                       msleep(50);
+               }
+       }
+
+       for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+               struct omap_overlay_manager *mgr;
+               unsigned bit;
+
+               mgr = omap_dss_get_overlay_manager(i);
+               bit = dispc_mgr_get_sync_lost_irq(i);
+
+               if (bit & errors) {
+                       int j;
+
+                       DSSERR("SYNC_LOST on channel %s, restarting the output "
+                                       "with video overlays disabled\n",
+                                       mgr->name);
+
+                       dss_mgr_disable(mgr);
+
+                       for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
+                               struct omap_overlay *ovl;
+                               ovl = omap_dss_get_overlay(j);
+
+                               if (ovl->id != OMAP_DSS_GFX &&
+                                               ovl->manager == mgr)
+                                       ovl->disable(ovl);
+                       }
+
+                       dss_mgr_enable(mgr);
+               }
+       }
+
+       if (errors & DISPC_IRQ_OCP_ERR) {
+               DSSERR("OCP_ERR\n");
+               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+                       struct omap_overlay_manager *mgr;
+
+                       mgr = omap_dss_get_overlay_manager(i);
+                       dss_mgr_disable(mgr);
+               }
+       }
+
+       spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+       dispc_compat.irq_error_mask |= errors;
+       _omap_dispc_set_irqs();
+       spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+       dispc_runtime_put();
+}
+
+int dss_dispc_initialize_irq(void)
+{
+       int r;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+       spin_lock_init(&dispc_compat.irq_stats_lock);
+       dispc_compat.irq_stats.last_reset = jiffies;
+       dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
+#endif
+
+       spin_lock_init(&dispc_compat.irq_lock);
+
+       memset(dispc_compat.registered_isr, 0,
+                       sizeof(dispc_compat.registered_isr));
+
+       dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+       if (dss_has_feature(FEAT_MGR_LCD2))
+               dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+       if (dss_has_feature(FEAT_MGR_LCD3))
+               dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
+       if (dss_feat_get_num_ovls() > 3)
+               dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
+
+       /*
+        * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+        * so clear it
+        */
+       dispc_clear_irqstatus(dispc_read_irqstatus());
+
+       INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
+
+       _omap_dispc_set_irqs();
+
+       r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
+       if (r) {
+               DSSERR("dispc_request_irq failed\n");
+               return r;
+       }
+
+       return 0;
+}
+
+void dss_dispc_uninitialize_irq(void)
+{
+       dispc_free_irq(&dispc_compat);
+}
+
+static void dispc_mgr_disable_isr(void *data, u32 mask)
+{
+       struct completion *compl = data;
+       complete(compl);
+}
+
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
+{
+       dispc_mgr_enable(channel, true);
+}
+
+static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
+{
+       DECLARE_COMPLETION_ONSTACK(framedone_compl);
+       int r;
+       u32 irq;
+
+       if (dispc_mgr_is_enabled(channel) == false)
+               return;
+
+       /*
+        * When we disable LCD output, we need to wait for FRAMEDONE to know
+        * that DISPC has finished with the LCD output.
+        */
+
+       irq = dispc_mgr_get_framedone_irq(channel);
+
+       r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+                       irq);
+       if (r)
+               DSSERR("failed to register FRAMEDONE isr\n");
+
+       dispc_mgr_enable(channel, false);
+
+       /* if we couldn't register for framedone, just sleep and exit */
+       if (r) {
+               msleep(100);
+               return;
+       }
+
+       if (!wait_for_completion_timeout(&framedone_compl,
+                               msecs_to_jiffies(100)))
+               DSSERR("timeout waiting for FRAME DONE\n");
+
+       r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+                       irq);
+       if (r)
+               DSSERR("failed to unregister FRAMEDONE isr\n");
+}
+
+static void dispc_digit_out_enable_isr(void *data, u32 mask)
+{
+       struct completion *compl = data;
+
+       /* ignore any sync lost interrupts */
+       if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
+               complete(compl);
+}
+
+static void dispc_mgr_enable_digit_out(void)
+{
+       DECLARE_COMPLETION_ONSTACK(vsync_compl);
+       int r;
+       u32 irq_mask;
+
+       if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
+               return;
+
+       /*
+        * Digit output produces some sync lost interrupts during the first
+        * frame when enabling. Those need to be ignored, so we register for the
+        * sync lost irq to prevent the error handler from triggering.
+        */
+
+       irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
+               dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
+
+       r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
+                       irq_mask);
+       if (r) {
+               DSSERR("failed to register %x isr\n", irq_mask);
+               return;
+       }
+
+       dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
+
+       /* wait for the first evsync */
+       if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
+               DSSERR("timeout waiting for digit out to start\n");
+
+       r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
+                       irq_mask);
+       if (r)
+               DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+static void dispc_mgr_disable_digit_out(void)
+{
+       DECLARE_COMPLETION_ONSTACK(framedone_compl);
+       int r, i;
+       u32 irq_mask;
+       int num_irqs;
+
+       if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
+               return;
+
+       /*
+        * When we disable the digit output, we need to wait for FRAMEDONE to
+        * know that DISPC has finished with the output.
+        */
+
+       irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
+       num_irqs = 1;
+
+       if (!irq_mask) {
+               /*
+                * omap 2/3 don't have framedone irq for TV, so we need to use
+                * vsyncs for this.
+                */
+
+               irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
+               /*
+                * We need to wait for both even and odd vsyncs. Note that this
+                * is not totally reliable, as we could get a vsync interrupt
+                * before we disable the output, which leads to timeout in the
+                * wait_for_completion.
+                */
+               num_irqs = 2;
+       }
+
+       r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+                       irq_mask);
+       if (r)
+               DSSERR("failed to register %x isr\n", irq_mask);
+
+       dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
+
+       /* if we couldn't register the irq, just sleep and exit */
+       if (r) {
+               msleep(100);
+               return;
+       }
+
+       for (i = 0; i < num_irqs; ++i) {
+               if (!wait_for_completion_timeout(&framedone_compl,
+                                       msecs_to_jiffies(100)))
+                       DSSERR("timeout waiting for digit out to stop\n");
+       }
+
+       r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+                       irq_mask);
+       if (r)
+               DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+void dispc_mgr_enable_sync(enum omap_channel channel)
+{
+       if (dss_mgr_is_lcd(channel))
+               dispc_mgr_enable_lcd_out(channel);
+       else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+               dispc_mgr_enable_digit_out();
+       else
+               WARN_ON(1);
+}
+
+void dispc_mgr_disable_sync(enum omap_channel channel)
+{
+       if (dss_mgr_is_lcd(channel))
+               dispc_mgr_disable_lcd_out(channel);
+       else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+               dispc_mgr_disable_digit_out();
+       else
+               WARN_ON(1);
+}
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+               unsigned long timeout)
+{
+       void dispc_irq_wait_handler(void *data, u32 mask)
+       {
+               complete((struct completion *)data);
+       }
+
+       int r;
+       DECLARE_COMPLETION_ONSTACK(completion);
+
+       r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
+                       irqmask);
+
+       if (r)
+               return r;
+
+       timeout = wait_for_completion_interruptible_timeout(&completion,
+                       timeout);
+
+       omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
+
+       if (timeout == 0)
+               return -ETIMEDOUT;
+
+       if (timeout == -ERESTARTSYS)
+               return -ERESTARTSYS;
+
+       return 0;
+}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
new file mode 100644 (file)
index 0000000..14a69b3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@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/>.
+ */
+
+#ifndef __OMAP2_DSS_DISPC_COMPAT_H
+#define __OMAP2_DSS_DISPC_COMPAT_H
+
+void dispc_mgr_enable_sync(enum omap_channel channel);
+void dispc_mgr_disable_sync(enum omap_channel channel);
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+               unsigned long timeout);
+
+int dss_dispc_initialize_irq(void);
+void dss_dispc_uninitialize_irq(void);
+
+#endif
index a5ab354f267ae1a458ae1ba0fd5d6c8104f74b4f..05ff2b91d9e8a49ee1e11c3c957b634eb4698393 100644 (file)
@@ -33,9 +33,9 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/hardirq.h>
-#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sizes.h>
 
 #include <video/omapdss.h>
 
 /* DISPC */
 #define DISPC_SZ_REGS                  SZ_4K
 
-#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
-                                        DISPC_IRQ_OCP_ERR | \
-                                        DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
-                                        DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
-                                        DISPC_IRQ_SYNC_LOST | \
-                                        DISPC_IRQ_SYNC_LOST_DIGIT)
-
-#define DISPC_MAX_NR_ISRS              8
-
-struct omap_dispc_isr_data {
-       omap_dispc_isr_t        isr;
-       void                    *arg;
-       u32                     mask;
-};
-
 enum omap_burst_size {
        BURST_SIZE_X2 = 0,
        BURST_SIZE_X4 = 1,
@@ -73,12 +58,6 @@ enum omap_burst_size {
 #define REG_FLD_MOD(idx, val, start, end)                              \
        dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
 
-struct dispc_irq_stats {
-       unsigned long last_reset;
-       unsigned irq_count;
-       unsigned irqs[32];
-};
-
 struct dispc_features {
        u8 sw_start;
        u8 fp_start;
@@ -86,19 +65,26 @@ struct dispc_features {
        u16 sw_max;
        u16 vp_max;
        u16 hp_max;
-       int (*calc_scaling) (enum omap_plane plane,
+       u8 mgr_width_start;
+       u8 mgr_height_start;
+       u16 mgr_width_max;
+       u16 mgr_height_max;
+       int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
                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,
+       unsigned long (*calc_core_clk) (unsigned long pclk,
                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;
+
+       /* no DISPC_IRQ_FRAMEDONETV on this SoC */
+       bool no_framedone_tv:1;
 };
 
 #define DISPC_MAX_NR_FIFOS 5
@@ -110,27 +96,15 @@ static struct {
        int             ctx_loss_cnt;
 
        int irq;
-       struct clk *dss_clk;
 
        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;
-       struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-       u32 error_irqs;
-       struct work_struct error_work;
-
        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;
-#endif
 } dispc;
 
 enum omap_color_component {
@@ -186,7 +160,7 @@ static const struct {
        [OMAP_DSS_CHANNEL_DIGIT] = {
                .name           = "DIGIT",
                .vsync_irq      = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
-               .framedone_irq  = 0,
+               .framedone_irq  = DISPC_IRQ_FRAMEDONETV,
                .sync_lost_irq  = DISPC_IRQ_SYNC_LOST_DIGIT,
                .reg_desc       = {
                        [DISPC_MGR_FLD_ENABLE]          = { DISPC_CONTROL,  1,  1 },
@@ -241,7 +215,6 @@ struct color_conv_coef {
        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);
 
@@ -374,7 +347,7 @@ static void dispc_save_context(void)
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                SR(DIVISOR);
 
-       dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev);
+       dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
        dispc.ctx_valid = true;
 
        DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
@@ -389,7 +362,7 @@ static void dispc_restore_context(void)
        if (!dispc.ctx_valid)
                return;
 
-       ctx = dss_get_ctx_loss_count(&dispc.pdev->dev);
+       ctx = dss_get_ctx_loss_count();
 
        if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
                return;
@@ -496,7 +469,7 @@ static void dispc_restore_context(void)
        if (dss_has_feature(FEAT_MGR_LCD3))
                RR(CONTROL3);
        /* clear spurious SYNC_LOST_DIGIT interrupts */
-       dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+       dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
 
        /*
         * enable last so IRQs won't trigger before
@@ -520,6 +493,7 @@ int dispc_runtime_get(void)
        WARN_ON(r < 0);
        return r < 0 ? r : 0;
 }
+EXPORT_SYMBOL(dispc_runtime_get);
 
 void dispc_runtime_put(void)
 {
@@ -530,16 +504,28 @@ void dispc_runtime_put(void)
        r = pm_runtime_put_sync(&dispc.pdev->dev);
        WARN_ON(r < 0 && r != -ENOSYS);
 }
+EXPORT_SYMBOL(dispc_runtime_put);
 
 u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
 {
        return mgr_desc[channel].vsync_irq;
 }
+EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
 
 u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
 {
+       if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
+               return 0;
+
        return mgr_desc[channel].framedone_irq;
 }
+EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
+
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
+{
+       return mgr_desc[channel].sync_lost_irq;
+}
+EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
 
 u32 dispc_wb_get_framedone_irq(void)
 {
@@ -550,28 +536,18 @@ bool dispc_mgr_go_busy(enum omap_channel channel)
 {
        return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
 }
+EXPORT_SYMBOL(dispc_mgr_go_busy);
 
 void dispc_mgr_go(enum omap_channel channel)
 {
-       bool enable_bit, go_bit;
-
-       /* if the channel is not enabled, we don't need GO */
-       enable_bit = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE) == 1;
-
-       if (!enable_bit)
-               return;
-
-       go_bit = mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
-
-       if (go_bit) {
-               DSSERR("GO bit not down for channel %d\n", channel);
-               return;
-       }
+       WARN_ON(dispc_mgr_is_enabled(channel) == false);
+       WARN_ON(dispc_mgr_go_busy(channel));
 
        DSSDBG("GO %s\n", mgr_desc[channel].name);
 
        mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
 }
+EXPORT_SYMBOL(dispc_mgr_go);
 
 bool dispc_wb_go_busy(void)
 {
@@ -975,6 +951,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
        }
        dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
+EXPORT_SYMBOL(dispc_ovl_set_channel_out);
 
 static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
 {
@@ -1040,7 +1017,7 @@ static void dispc_configure_burst_sizes(void)
        const int burst_size = BURST_SIZE_X8;
 
        /* Configure burst size always to maximum size */
-       for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+       for (i = 0; i < dss_feat_get_num_ovls(); ++i)
                dispc_ovl_set_burst_size(i, burst_size);
 }
 
@@ -1074,7 +1051,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
 }
 
 static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
-               struct omap_dss_cpr_coefs *coefs)
+               const struct omap_dss_cpr_coefs *coefs)
 {
        u32 coef_r, coef_g, coef_b;
 
@@ -1122,7 +1099,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
 {
        u32 val;
 
-       val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+       val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
+               FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
+
        dispc_write_reg(DISPC_SIZE_MGR(channel), val);
 }
 
@@ -1244,7 +1223,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
 
        if (use_fifomerge) {
                total_fifo_size = 0;
-               for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+               for (i = 0; i < dss_feat_get_num_ovls(); ++i)
                        total_fifo_size += dispc_ovl_get_fifo_size(i);
        } else {
                total_fifo_size = ovl_fifo_size;
@@ -1989,16 +1968,14 @@ 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_plane plane,
+static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
                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);
+       const int ds = DIV_ROUND_UP(height, out_height);
        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;
@@ -2020,8 +1997,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
         */
        val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
        DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
-               val, max(0, DS - 2) * width);
-       if (val < max(0, DS - 2) * width)
+               val, max(0, ds - 2) * width);
+       if (val < max(0, ds - 2) * width)
                return -EINVAL;
 
        /*
@@ -2031,21 +2008,20 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
         */
        val =  div_u64((u64)nonactive * lclk, pclk);
        DSSDBG("nonactive * pcd  = %llu, max(0, DS - 1) * width = %d\n",
-               val, max(0, DS - 1) * width);
-       if (val < max(0, DS - 1) * width)
+               val, max(0, ds - 1) * width);
+       if (val < max(0, ds - 1) * width)
                return -EINVAL;
 
        return 0;
 }
 
-static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
+static unsigned long calc_core_clk_five_taps(unsigned long pclk,
                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;
-       unsigned long pclk = dispc_plane_pclk_rate(plane);
 
        if (height <= out_height && width <= out_width)
                return (unsigned long) pclk;
@@ -2079,22 +2055,19 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
        return core_clk;
 }
 
-static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_24xx(unsigned long pclk, 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,
+static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
                u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 {
        unsigned int hf, vf;
-       unsigned long pclk = dispc_plane_pclk_rate(plane);
 
        /*
         * FIXME how to determine the 'A' factor
@@ -2117,11 +2090,9 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
        return pclk * vf * hf;
 }
 
-static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_44xx(unsigned long pclk, 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
@@ -2131,15 +2102,13 @@ static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
        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,
+static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
                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,
@@ -2157,7 +2126,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
        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,
+               *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
                                in_height, out_width, out_height, mem_to_mem);
                error = (in_width > maxsinglelinewidth || !*core_clk ||
                        *core_clk > dispc_core_clk_rate());
@@ -2180,7 +2149,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
        return 0;
 }
 
-static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
                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,
@@ -2196,10 +2165,10 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
        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,
+               *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
                        in_width, in_height, out_width, out_height, color_mode);
 
-               error = check_horiz_timing_omap3(plane, mgr_timings,
+               error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
                                pos_x, in_width, in_height, out_width,
                                out_height);
 
@@ -2208,7 +2177,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
                                                in_height < out_height * 2)
                                *five_taps = false;
                if (!*five_taps)
-                       *core_clk = dispc.feat->calc_core_clk(plane, in_width,
+                       *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
                                        in_height, out_width, out_height,
                                        mem_to_mem);
 
@@ -2227,8 +2196,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
                }
        } 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)){
+       if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
+                               height, out_width, out_height)){
                        DSSERR("horizontal timing too tight\n");
                        return -EINVAL;
        }
@@ -2246,7 +2215,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
        return 0;
 }
 
-static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
                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,
@@ -2258,14 +2227,14 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
        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
+       if (mem_to_mem) {
+               in_width_max = 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);
 
@@ -2283,12 +2252,12 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
                return -EINVAL;
        }
 
-       *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
+       *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
                                out_width, out_height, mem_to_mem);
        return 0;
 }
 
-static int dispc_ovl_calc_scaling(enum omap_plane plane,
+static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
                enum omap_overlay_caps caps,
                const struct omap_video_timings *mgr_timings,
                u16 width, u16 height, u16 out_width, u16 out_height,
@@ -2307,9 +2276,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
                return -EINVAL;
 
-       *x_predecim = max_decim_limit;
-       *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
-                       dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
+       if (mem_to_mem) {
+               *x_predecim = *y_predecim = 1;
+       } else {
+               *x_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 ||
@@ -2330,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        if (decim_y > *y_predecim || out_height > height * 8)
                return -EINVAL;
 
-       ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
+       ret = dispc.feat->calc_scaling(pclk, lclk, 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);
@@ -2353,6 +2327,47 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        return 0;
 }
 
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
+               const struct omap_overlay_info *oi,
+               const struct omap_video_timings *timings,
+               int *x_predecim, int *y_predecim)
+{
+       enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
+       bool five_taps = true;
+       bool fieldmode = 0;
+       u16 in_height = oi->height;
+       u16 in_width = oi->width;
+       bool ilace = timings->interlace;
+       u16 out_width, out_height;
+       int pos_x = oi->pos_x;
+       unsigned long pclk = dispc_mgr_pclk_rate(channel);
+       unsigned long lclk = dispc_mgr_lclk_rate(channel);
+
+       out_width = oi->out_width == 0 ? oi->width : oi->out_width;
+       out_height = oi->out_height == 0 ? oi->height : oi->out_height;
+
+       if (ilace && oi->height == out_height)
+               fieldmode = 1;
+
+       if (ilace) {
+               if (fieldmode)
+                       in_height /= 2;
+               out_height /= 2;
+
+               DSSDBG("adjusting for ilace: height %d, out_height %d\n",
+                               in_height, out_height);
+       }
+
+       if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+               return -EINVAL;
+
+       return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
+                       in_height, out_width, out_height, oi->color_mode,
+                       &five_taps, x_predecim, y_predecim, pos_x,
+                       oi->rotation_type, false);
+}
+EXPORT_SYMBOL(dispc_ovl_check);
+
 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,
@@ -2368,12 +2383,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
        unsigned offset0, offset1;
        s32 row_inc;
        s32 pix_inc;
-       u16 frame_height = height;
+       u16 frame_width, frame_height;
        unsigned int field_offset = 0;
        u16 in_height = height;
        u16 in_width = width;
        int x_predecim = 1, y_predecim = 1;
        bool ilace = mgr_timings->interlace;
+       unsigned long pclk = dispc_plane_pclk_rate(plane);
+       unsigned long lclk = dispc_plane_lclk_rate(plane);
 
        if (paddr == 0)
                return -EINVAL;
@@ -2398,7 +2415,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
        if (!dss_feat_color_mode_supported(plane, color_mode))
                return -EINVAL;
 
-       r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
+       r = dispc_ovl_calc_scaling(pclk, lclk, 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);
@@ -2436,20 +2453,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
        row_inc = 0;
        pix_inc = 0;
 
+       if (plane == OMAP_DSS_WB) {
+               frame_width = out_width;
+               frame_height = out_height;
+       } else {
+               frame_width = in_width;
+               frame_height = height;
+       }
+
        if (rotation_type == OMAP_DSS_ROT_TILER)
-               calc_tiler_rotation_offset(screen_width, in_width,
+               calc_tiler_rotation_offset(screen_width, frame_width,
                                color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc,
                                x_predecim, y_predecim);
        else if (rotation_type == OMAP_DSS_ROT_DMA)
-               calc_dma_rotation_offset(rotation, mirror,
-                               screen_width, in_width, frame_height,
+               calc_dma_rotation_offset(rotation, mirror, screen_width,
+                               frame_width, frame_height,
                                color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc,
                                x_predecim, y_predecim);
        else
                calc_vrfb_rotation_offset(rotation, mirror,
-                               screen_width, in_width, frame_height,
+                               screen_width, frame_width, frame_height,
                                color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc,
                                x_predecim, y_predecim);
@@ -2503,7 +2528,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
                bool mem_to_mem)
 {
        int r;
-       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+       enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
        enum omap_channel channel;
 
        channel = dispc_ovl_get_channel_out(plane);
@@ -2514,7 +2539,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
                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,
+       r = dispc_ovl_setup_common(plane, 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,
@@ -2522,6 +2547,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 
        return r;
 }
+EXPORT_SYMBOL(dispc_ovl_setup);
 
 int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
                bool mem_to_mem, const struct omap_video_timings *mgr_timings)
@@ -2582,192 +2608,39 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
 
        return 0;
 }
+EXPORT_SYMBOL(dispc_ovl_enable);
 
-static void dispc_disable_isr(void *data, u32 mask)
+bool dispc_ovl_enabled(enum omap_plane plane)
 {
-       struct completion *compl = data;
-       complete(compl);
+       return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
 }
+EXPORT_SYMBOL(dispc_ovl_enabled);
 
-static void _enable_lcd_out(enum omap_channel channel, bool enable)
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
 {
        mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
        /* flush posted write */
        mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 }
-
-static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
-{
-       struct completion frame_done_completion;
-       bool is_on;
-       int r;
-       u32 irq;
-
-       /* When we disable LCD output, we need to wait until frame is done.
-        * Otherwise the DSS is still working, and turning off the clocks
-        * prevents DSS from going to OFF mode */
-       is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-
-       irq = mgr_desc[channel].framedone_irq;
-
-       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 FRAMEDONE isr\n");
-       }
-
-       _enable_lcd_out(channel, enable);
-
-       if (!enable && is_on) {
-               if (!wait_for_completion_timeout(&frame_done_completion,
-                                       msecs_to_jiffies(100)))
-                       DSSERR("timeout waiting for FRAME DONE\n");
-
-               r = omap_dispc_unregister_isr(dispc_disable_isr,
-                               &frame_done_completion, irq);
-
-               if (r)
-                       DSSERR("failed to unregister FRAMEDONE isr\n");
-       }
-}
-
-static void _enable_digit_out(bool enable)
-{
-       REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
-       /* flush posted write */
-       dispc_read_reg(DISPC_CONTROL);
-}
-
-static void dispc_mgr_enable_digit_out(bool enable)
-{
-       struct completion frame_done_completion;
-       enum dss_hdmi_venc_clk_source_select src;
-       int r, i;
-       u32 irq_mask;
-       int num_irqs;
-
-       if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
-               return;
-
-       src = dss_get_hdmi_venc_clk_source();
-
-       if (enable) {
-               unsigned long flags;
-               /* When we enable digit output, we'll get an extra digit
-                * sync lost interrupt, that we need to ignore */
-               spin_lock_irqsave(&dispc.irq_lock, flags);
-               dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
-               _omap_dispc_set_irqs();
-               spin_unlock_irqrestore(&dispc.irq_lock, flags);
-       }
-
-       /* When we disable digit output, we need to wait until fields are done.
-        * Otherwise the DSS is still working, and turning off the clocks
-        * prevents DSS from going to OFF mode. And when enabling, we need to
-        * wait for the extra sync losts */
-       init_completion(&frame_done_completion);
-
-       if (src == DSS_HDMI_M_PCLK && enable == false) {
-               irq_mask = DISPC_IRQ_FRAMEDONETV;
-               num_irqs = 1;
-       } else {
-               irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
-               /* XXX I understand from TRM that we should only wait for the
-                * current field to complete. But it seems we have to wait for
-                * both fields */
-               num_irqs = 2;
-       }
-
-       r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
-                       irq_mask);
-       if (r)
-               DSSERR("failed to register %x isr\n", irq_mask);
-
-       _enable_digit_out(enable);
-
-       for (i = 0; i < num_irqs; ++i) {
-               if (!wait_for_completion_timeout(&frame_done_completion,
-                                       msecs_to_jiffies(100)))
-                       DSSERR("timeout waiting for digit out to %s\n",
-                                       enable ? "start" : "stop");
-       }
-
-       r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
-                       irq_mask);
-       if (r)
-               DSSERR("failed to unregister %x isr\n", irq_mask);
-
-       if (enable) {
-               unsigned long flags;
-               spin_lock_irqsave(&dispc.irq_lock, flags);
-               dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
-               dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
-               _omap_dispc_set_irqs();
-               spin_unlock_irqrestore(&dispc.irq_lock, flags);
-       }
-}
+EXPORT_SYMBOL(dispc_mgr_enable);
 
 bool dispc_mgr_is_enabled(enum omap_channel channel)
 {
        return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 }
-
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
-{
-       if (dss_mgr_is_lcd(channel))
-               dispc_mgr_enable_lcd_out(channel, enable);
-       else if (channel == OMAP_DSS_CHANNEL_DIGIT)
-               dispc_mgr_enable_digit_out(enable);
-       else
-               BUG();
-}
+EXPORT_SYMBOL(dispc_mgr_is_enabled);
 
 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");
-       }
+       dispc_ovl_enable(OMAP_DSS_WB, enable);
 }
 
 bool dispc_wb_is_enabled(void)
 {
-       enum omap_plane plane = OMAP_DSS_WB;
-
-       return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+       return dispc_ovl_enabled(OMAP_DSS_WB);
 }
 
-void dispc_lcd_enable_signal_polarity(bool act_high)
+static void dispc_lcd_enable_signal_polarity(bool act_high)
 {
        if (!dss_has_feature(FEAT_LCDENABLEPOL))
                return;
@@ -2791,13 +2664,13 @@ void dispc_pck_free_enable(bool enable)
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
 }
 
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
        mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
 }
 
 
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
+static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
 {
        mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
 }
@@ -2840,7 +2713,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
 }
 
 void dispc_mgr_setup(enum omap_channel channel,
-               struct omap_overlay_manager_info *info)
+               const struct omap_overlay_manager_info *info)
 {
        dispc_mgr_set_default_color(channel, info->default_color);
        dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
@@ -2852,8 +2725,9 @@ void dispc_mgr_setup(enum omap_channel channel,
                dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
        }
 }
+EXPORT_SYMBOL(dispc_mgr_setup);
 
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 {
        int code;
 
@@ -2878,7 +2752,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
        mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
 }
 
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
+static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
 {
        u32 l;
        int gpout0, gpout1;
@@ -2907,15 +2781,33 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
        dispc_write_reg(DISPC_CONTROL, l);
 }
 
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
 {
        mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
 }
 
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+               const struct dss_lcd_mgr_config *config)
+{
+       dispc_mgr_set_io_pad_mode(config->io_pad_mode);
+
+       dispc_mgr_enable_stallmode(channel, config->stallmode);
+       dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
+
+       dispc_mgr_set_clock_div(channel, &config->clock_info);
+
+       dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
+
+       dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
+
+       dispc_mgr_set_lcd_type_tft(channel);
+}
+EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
+
 static bool _dispc_mgr_size_ok(u16 width, u16 height)
 {
-       return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
-               height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
+       return width <= dispc.feat->mgr_width_max &&
+               height <= dispc.feat->mgr_height_max;
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -3010,7 +2902,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
 
 /* change name to mode? */
 void dispc_mgr_set_timings(enum omap_channel channel,
-               struct omap_video_timings *timings)
+               const struct omap_video_timings *timings)
 {
        unsigned xtot, ytot;
        unsigned long ht, vt;
@@ -3049,6 +2941,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
 
        dispc_mgr_set_size(channel, t.x_res, t.y_res);
 }
+EXPORT_SYMBOL(dispc_mgr_set_timings);
 
 static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
                u16 pck_div)
@@ -3076,7 +2969,7 @@ unsigned long dispc_fclk_rate(void)
 
        switch (dss_get_dispc_clk_source()) {
        case OMAP_DSS_CLK_SRC_FCK:
-               r = clk_get_rate(dispc.dss_clk);
+               r = dss_get_dispc_clk_rate();
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                dsidev = dsi_get_dsidev_from_id(0);
@@ -3101,28 +2994,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
        unsigned long r;
        u32 l;
 
-       l = dispc_read_reg(DISPC_DIVISORo(channel));
+       if (dss_mgr_is_lcd(channel)) {
+               l = dispc_read_reg(DISPC_DIVISORo(channel));
 
-       lcd = FLD_GET(l, 23, 16);
+               lcd = FLD_GET(l, 23, 16);
 
-       switch (dss_get_lcd_clk_source(channel)) {
-       case OMAP_DSS_CLK_SRC_FCK:
-               r = clk_get_rate(dispc.dss_clk);
-               break;
-       case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-               dsidev = dsi_get_dsidev_from_id(0);
-               r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-               break;
-       case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-               dsidev = dsi_get_dsidev_from_id(1);
-               r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-               break;
-       default:
-               BUG();
-               return 0;
-       }
+               switch (dss_get_lcd_clk_source(channel)) {
+               case OMAP_DSS_CLK_SRC_FCK:
+                       r = dss_get_dispc_clk_rate();
+                       break;
+               case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+                       dsidev = dsi_get_dsidev_from_id(0);
+                       r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+                       break;
+               case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+                       dsidev = dsi_get_dsidev_from_id(1);
+                       r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+                       break;
+               default:
+                       BUG();
+                       return 0;
+               }
 
-       return r / lcd;
+               return r / lcd;
+       } else {
+               return dispc_fclk_rate();
+       }
 }
 
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3172,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void)
 
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
 {
-       enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+       enum omap_channel channel;
+
+       if (plane == OMAP_DSS_WB)
+               return 0;
+
+       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);
+       enum omap_channel channel;
 
-       if (dss_mgr_is_lcd(channel))
-               return dispc_mgr_lclk_rate(channel);
-       else
-               return dispc_fclk_rate();
+       if (plane == OMAP_DSS_WB)
+               return 0;
+
+       channel = dispc_ovl_get_channel_out(plane);
 
+       return dispc_mgr_lclk_rate(channel);
 }
+
 static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
 {
        int lcd, pcd;
@@ -3244,64 +3148,6 @@ void dispc_dump_clocks(struct seq_file *s)
        dispc_runtime_put();
 }
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-void dispc_dump_irqs(struct seq_file *s)
-{
-       unsigned long flags;
-       struct dispc_irq_stats stats;
-
-       spin_lock_irqsave(&dispc.irq_stats_lock, flags);
-
-       stats = dispc.irq_stats;
-       memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
-       dispc.irq_stats.last_reset = jiffies;
-
-       spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
-
-       seq_printf(s, "period %u ms\n",
-                       jiffies_to_msecs(jiffies - stats.last_reset));
-
-       seq_printf(s, "irqs %d\n", stats.irq_count);
-#define PIS(x) \
-       seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
-
-       PIS(FRAMEDONE);
-       PIS(VSYNC);
-       PIS(EVSYNC_EVEN);
-       PIS(EVSYNC_ODD);
-       PIS(ACBIAS_COUNT_STAT);
-       PIS(PROG_LINE_NUM);
-       PIS(GFX_FIFO_UNDERFLOW);
-       PIS(GFX_END_WIN);
-       PIS(PAL_GAMMA_MASK);
-       PIS(OCP_ERR);
-       PIS(VID1_FIFO_UNDERFLOW);
-       PIS(VID1_END_WIN);
-       PIS(VID2_FIFO_UNDERFLOW);
-       PIS(VID2_END_WIN);
-       if (dss_feat_get_num_ovls() > 3) {
-               PIS(VID3_FIFO_UNDERFLOW);
-               PIS(VID3_END_WIN);
-       }
-       PIS(SYNC_LOST);
-       PIS(SYNC_LOST_DIGIT);
-       PIS(WAKEUP);
-       if (dss_has_feature(FEAT_MGR_LCD2)) {
-               PIS(FRAMEDONE2);
-               PIS(VSYNC2);
-               PIS(ACBIAS_COUNT_STAT2);
-               PIS(SYNC_LOST2);
-       }
-       if (dss_has_feature(FEAT_MGR_LCD3)) {
-               PIS(FRAMEDONE3);
-               PIS(VSYNC3);
-               PIS(ACBIAS_COUNT_STAT3);
-               PIS(SYNC_LOST3);
-       }
-#undef PIS
-}
-#endif
-
 static void dispc_dump_regs(struct seq_file *s)
 {
        int i, j;
@@ -3351,7 +3197,7 @@ static void dispc_dump_regs(struct seq_file *s)
 
 #define DISPC_REG(i, name) name(i)
 #define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
-       48 - strlen(#r) - strlen(p_names[i]), " ", \
+       (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
        dispc_read_reg(DISPC_REG(i, r)))
 
        p_names = mgr_names;
@@ -3428,7 +3274,7 @@ static void dispc_dump_regs(struct seq_file *s)
 #define DISPC_REG(plane, name, i) name(plane, i)
 #define DUMPREG(plane, name, i) \
        seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
-       46 - strlen(#name) - strlen(p_names[plane]), " ", \
+       (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
        dispc_read_reg(DISPC_REG(plane, name, i)))
 
        /* Video pipeline coefficient registers */
@@ -3531,7 +3377,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 }
 
 void dispc_mgr_set_clock_div(enum omap_channel channel,
-               struct dispc_clock_info *cinfo)
+               const struct dispc_clock_info *cinfo)
 {
        DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
        DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
@@ -3555,403 +3401,34 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
        return 0;
 }
 
-/* dispc.irq_lock has to be locked by the caller */
-static void _omap_dispc_set_irqs(void)
+u32 dispc_read_irqstatus(void)
 {
-       u32 mask;
-       u32 old_mask;
-       int i;
-       struct omap_dispc_isr_data *isr_data;
-
-       mask = dispc.irq_error_mask;
-
-       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-               isr_data = &dispc.registered_isr[i];
-
-               if (isr_data->isr == NULL)
-                       continue;
-
-               mask |= isr_data->mask;
-       }
-
-       old_mask = dispc_read_reg(DISPC_IRQENABLE);
-       /* clear the irqstatus for newly enabled irqs */
-       dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
-
-       dispc_write_reg(DISPC_IRQENABLE, mask);
-}
-
-int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
-       int i;
-       int ret;
-       unsigned long flags;
-       struct omap_dispc_isr_data *isr_data;
-
-       if (isr == NULL)
-               return -EINVAL;
-
-       spin_lock_irqsave(&dispc.irq_lock, flags);
-
-       /* check for duplicate entry */
-       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-               isr_data = &dispc.registered_isr[i];
-               if (isr_data->isr == isr && isr_data->arg == arg &&
-                               isr_data->mask == mask) {
-                       ret = -EINVAL;
-                       goto err;
-               }
-       }
-
-       isr_data = NULL;
-       ret = -EBUSY;
-
-       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-               isr_data = &dispc.registered_isr[i];
-
-               if (isr_data->isr != NULL)
-                       continue;
-
-               isr_data->isr = isr;
-               isr_data->arg = arg;
-               isr_data->mask = mask;
-               ret = 0;
-
-               break;
-       }
-
-       if (ret)
-               goto err;
-
-       _omap_dispc_set_irqs();
-
-       spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-       return 0;
-err:
-       spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(omap_dispc_register_isr);
-
-int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
-       int i;
-       unsigned long flags;
-       int ret = -EINVAL;
-       struct omap_dispc_isr_data *isr_data;
-
-       spin_lock_irqsave(&dispc.irq_lock, flags);
-
-       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-               isr_data = &dispc.registered_isr[i];
-               if (isr_data->isr != isr || isr_data->arg != arg ||
-                               isr_data->mask != mask)
-                       continue;
-
-               /* found the correct isr */
-
-               isr_data->isr = NULL;
-               isr_data->arg = NULL;
-               isr_data->mask = 0;
-
-               ret = 0;
-               break;
-       }
-
-       if (ret == 0)
-               _omap_dispc_set_irqs();
-
-       spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(omap_dispc_unregister_isr);
-
-#ifdef DEBUG
-static void print_irq_status(u32 status)
-{
-       if ((status & dispc.irq_error_mask) == 0)
-               return;
-
-       printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
-
-#define PIS(x) \
-       if (status & DISPC_IRQ_##x) \
-               printk(#x " ");
-       PIS(GFX_FIFO_UNDERFLOW);
-       PIS(OCP_ERR);
-       PIS(VID1_FIFO_UNDERFLOW);
-       PIS(VID2_FIFO_UNDERFLOW);
-       if (dss_feat_get_num_ovls() > 3)
-               PIS(VID3_FIFO_UNDERFLOW);
-       PIS(SYNC_LOST);
-       PIS(SYNC_LOST_DIGIT);
-       if (dss_has_feature(FEAT_MGR_LCD2))
-               PIS(SYNC_LOST2);
-       if (dss_has_feature(FEAT_MGR_LCD3))
-               PIS(SYNC_LOST3);
-#undef PIS
-
-       printk("\n");
-}
-#endif
-
-/* Called from dss.c. Note that we don't touch clocks here,
- * but we presume they are on because we got an IRQ. However,
- * an irq handler may turn the clocks off, so we may not have
- * clock later in the function. */
-static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
-{
-       int i;
-       u32 irqstatus, irqenable;
-       u32 handledirqs = 0;
-       u32 unhandled_errors;
-       struct omap_dispc_isr_data *isr_data;
-       struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-
-       spin_lock(&dispc.irq_lock);
-
-       irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
-       irqenable = dispc_read_reg(DISPC_IRQENABLE);
-
-       /* IRQ is not for us */
-       if (!(irqstatus & irqenable)) {
-               spin_unlock(&dispc.irq_lock);
-               return IRQ_NONE;
-       }
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-       spin_lock(&dispc.irq_stats_lock);
-       dispc.irq_stats.irq_count++;
-       dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
-       spin_unlock(&dispc.irq_stats_lock);
-#endif
-
-#ifdef DEBUG
-       if (dss_debug)
-               print_irq_status(irqstatus);
-#endif
-       /* Ack the interrupt. Do it here before clocks are possibly turned
-        * off */
-       dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
-       /* flush posted write */
-       dispc_read_reg(DISPC_IRQSTATUS);
-
-       /* make a copy and unlock, so that isrs can unregister
-        * themselves */
-       memcpy(registered_isr, dispc.registered_isr,
-                       sizeof(registered_isr));
-
-       spin_unlock(&dispc.irq_lock);
-
-       for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-               isr_data = &registered_isr[i];
-
-               if (!isr_data->isr)
-                       continue;
-
-               if (isr_data->mask & irqstatus) {
-                       isr_data->isr(isr_data->arg, irqstatus);
-                       handledirqs |= isr_data->mask;
-               }
-       }
-
-       spin_lock(&dispc.irq_lock);
-
-       unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
-
-       if (unhandled_errors) {
-               dispc.error_irqs |= unhandled_errors;
-
-               dispc.irq_error_mask &= ~unhandled_errors;
-               _omap_dispc_set_irqs();
-
-               schedule_work(&dispc.error_work);
-       }
-
-       spin_unlock(&dispc.irq_lock);
-
-       return IRQ_HANDLED;
-}
-
-static void dispc_error_worker(struct work_struct *work)
-{
-       int i;
-       u32 errors;
-       unsigned long flags;
-       static const unsigned fifo_underflow_bits[] = {
-               DISPC_IRQ_GFX_FIFO_UNDERFLOW,
-               DISPC_IRQ_VID1_FIFO_UNDERFLOW,
-               DISPC_IRQ_VID2_FIFO_UNDERFLOW,
-               DISPC_IRQ_VID3_FIFO_UNDERFLOW,
-       };
-
-       spin_lock_irqsave(&dispc.irq_lock, flags);
-       errors = dispc.error_irqs;
-       dispc.error_irqs = 0;
-       spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-       dispc_runtime_get();
-
-       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-               struct omap_overlay *ovl;
-               unsigned bit;
-
-               ovl = omap_dss_get_overlay(i);
-               bit = fifo_underflow_bits[i];
-
-               if (bit & errors) {
-                       DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
-                                       ovl->name);
-                       dispc_ovl_enable(ovl->id, false);
-                       dispc_mgr_go(ovl->manager->id);
-                       msleep(50);
-               }
-       }
-
-       for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-               struct omap_overlay_manager *mgr;
-               unsigned bit;
-
-               mgr = omap_dss_get_overlay_manager(i);
-               bit = mgr_desc[i].sync_lost_irq;
-
-               if (bit & errors) {
-                       struct omap_dss_device *dssdev = mgr->get_device(mgr);
-                       bool enable;
-
-                       DSSERR("SYNC_LOST on channel %s, restarting the output "
-                                       "with video overlays disabled\n",
-                                       mgr->name);
-
-                       enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
-                       dssdev->driver->disable(dssdev);
-
-                       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                               struct omap_overlay *ovl;
-                               ovl = omap_dss_get_overlay(i);
-
-                               if (ovl->id != OMAP_DSS_GFX &&
-                                               ovl->manager == mgr)
-                                       dispc_ovl_enable(ovl->id, false);
-                       }
-
-                       dispc_mgr_go(mgr->id);
-                       msleep(50);
-
-                       if (enable)
-                               dssdev->driver->enable(dssdev);
-               }
-       }
-
-       if (errors & DISPC_IRQ_OCP_ERR) {
-               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);
-                       dssdev = mgr->get_device(mgr);
-
-                       if (dssdev && dssdev->driver)
-                               dssdev->driver->disable(dssdev);
-               }
-       }
-
-       spin_lock_irqsave(&dispc.irq_lock, flags);
-       dispc.irq_error_mask |= errors;
-       _omap_dispc_set_irqs();
-       spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-       dispc_runtime_put();
+       return dispc_read_reg(DISPC_IRQSTATUS);
 }
+EXPORT_SYMBOL(dispc_read_irqstatus);
 
-int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
+void dispc_clear_irqstatus(u32 mask)
 {
-       void dispc_irq_wait_handler(void *data, u32 mask)
-       {
-               complete((struct completion *)data);
-       }
-
-       int r;
-       DECLARE_COMPLETION_ONSTACK(completion);
-
-       r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
-                       irqmask);
-
-       if (r)
-               return r;
-
-       timeout = wait_for_completion_timeout(&completion, timeout);
-
-       omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
-       if (timeout == 0)
-               return -ETIMEDOUT;
-
-       if (timeout == -ERESTARTSYS)
-               return -ERESTARTSYS;
-
-       return 0;
+       dispc_write_reg(DISPC_IRQSTATUS, mask);
 }
+EXPORT_SYMBOL(dispc_clear_irqstatus);
 
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
-               unsigned long timeout)
+u32 dispc_read_irqenable(void)
 {
-       void dispc_irq_wait_handler(void *data, u32 mask)
-       {
-               complete((struct completion *)data);
-       }
-
-       int r;
-       DECLARE_COMPLETION_ONSTACK(completion);
-
-       r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
-                       irqmask);
-
-       if (r)
-               return r;
-
-       timeout = wait_for_completion_interruptible_timeout(&completion,
-                       timeout);
-
-       omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
-       if (timeout == 0)
-               return -ETIMEDOUT;
-
-       if (timeout == -ERESTARTSYS)
-               return -ERESTARTSYS;
-
-       return 0;
+       return dispc_read_reg(DISPC_IRQENABLE);
 }
+EXPORT_SYMBOL(dispc_read_irqenable);
 
-static void _omap_dispc_initialize_irq(void)
+void dispc_write_irqenable(u32 mask)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&dispc.irq_lock, flags);
-
-       memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
-
-       dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
-       if (dss_has_feature(FEAT_MGR_LCD2))
-               dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
-       if (dss_has_feature(FEAT_MGR_LCD3))
-               dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
-       if (dss_feat_get_num_ovls() > 3)
-               dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
-
-       /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
-        * so clear it */
-       dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+       u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
 
-       _omap_dispc_set_irqs();
+       /* clear the irqstatus for newly enabled irqs */
+       dispc_clear_irqstatus((mask ^ old_mask) & mask);
 
-       spin_unlock_irqrestore(&dispc.irq_lock, flags);
+       dispc_write_reg(DISPC_IRQENABLE, mask);
 }
+EXPORT_SYMBOL(dispc_write_irqenable);
 
 void dispc_enable_sidle(void)
 {
@@ -3998,9 +3475,14 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
        .sw_max                 =       64,
        .vp_max                 =       255,
        .hp_max                 =       256,
+       .mgr_width_start        =       10,
+       .mgr_height_start       =       26,
+       .mgr_width_max          =       2048,
+       .mgr_height_max         =       2048,
        .calc_scaling           =       dispc_ovl_calc_scaling_24xx,
        .calc_core_clk          =       calc_core_clk_24xx,
        .num_fifos              =       3,
+       .no_framedone_tv        =       true,
 };
 
 static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
@@ -4010,9 +3492,14 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
        .sw_max                 =       64,
        .vp_max                 =       255,
        .hp_max                 =       256,
+       .mgr_width_start        =       10,
+       .mgr_height_start       =       26,
+       .mgr_width_max          =       2048,
+       .mgr_height_max         =       2048,
        .calc_scaling           =       dispc_ovl_calc_scaling_34xx,
        .calc_core_clk          =       calc_core_clk_34xx,
        .num_fifos              =       3,
+       .no_framedone_tv        =       true,
 };
 
 static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
@@ -4022,9 +3509,14 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
        .sw_max                 =       256,
        .vp_max                 =       4095,
        .hp_max                 =       4096,
+       .mgr_width_start        =       10,
+       .mgr_height_start       =       26,
+       .mgr_width_max          =       2048,
+       .mgr_height_max         =       2048,
        .calc_scaling           =       dispc_ovl_calc_scaling_34xx,
        .calc_core_clk          =       calc_core_clk_34xx,
        .num_fifos              =       3,
+       .no_framedone_tv        =       true,
 };
 
 static const struct dispc_features omap44xx_dispc_feats __initconst = {
@@ -4034,6 +3526,27 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
        .sw_max                 =       256,
        .vp_max                 =       4095,
        .hp_max                 =       4096,
+       .mgr_width_start        =       10,
+       .mgr_height_start       =       26,
+       .mgr_width_max          =       2048,
+       .mgr_height_max         =       2048,
+       .calc_scaling           =       dispc_ovl_calc_scaling_44xx,
+       .calc_core_clk          =       calc_core_clk_44xx,
+       .num_fifos              =       5,
+       .gfx_fifo_workaround    =       true,
+};
+
+static const struct dispc_features omap54xx_dispc_feats __initconst = {
+       .sw_start               =       7,
+       .fp_start               =       19,
+       .bp_start               =       31,
+       .sw_max                 =       256,
+       .vp_max                 =       4095,
+       .hp_max                 =       4096,
+       .mgr_width_start        =       11,
+       .mgr_height_start       =       27,
+       .mgr_width_max          =       4096,
+       .mgr_height_max         =       4096,
        .calc_scaling           =       dispc_ovl_calc_scaling_44xx,
        .calc_core_clk          =       calc_core_clk_44xx,
        .num_fifos              =       5,
@@ -4042,7 +3555,6 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
 
 static int __init dispc_init_features(struct platform_device *pdev)
 {
-       struct omap_dss_board_info *pdata = pdev->dev.platform_data;
        const struct dispc_features *src;
        struct dispc_features *dst;
 
@@ -4052,7 +3564,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       switch (pdata->version) {
+       switch (omapdss_get_version()) {
        case OMAPDSS_VER_OMAP24xx:
                src = &omap24xx_dispc_feats;
                break;
@@ -4074,7 +3586,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
                break;
 
        case OMAPDSS_VER_OMAP5:
-               src = &omap44xx_dispc_feats;
+               src = &omap54xx_dispc_feats;
                break;
 
        default:
@@ -4087,13 +3599,25 @@ static int __init dispc_init_features(struct platform_device *pdev)
        return 0;
 }
 
+int dispc_request_irq(irq_handler_t handler, void *dev_id)
+{
+       return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
+                            IRQF_SHARED, "OMAP DISPC", dev_id);
+}
+EXPORT_SYMBOL(dispc_request_irq);
+
+void dispc_free_irq(void *dev_id)
+{
+       devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
+}
+EXPORT_SYMBOL(dispc_free_irq);
+
 /* DISPC HW IP initialisation */
 static int __init omap_dispchw_probe(struct platform_device *pdev)
 {
        u32 rev;
        int r = 0;
        struct resource *dispc_mem;
-       struct clk *clk;
 
        dispc.pdev = pdev;
 
@@ -4101,15 +3625,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
        if (r)
                return r;
 
-       spin_lock_init(&dispc.irq_lock);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-       spin_lock_init(&dispc.irq_stats_lock);
-       dispc.irq_stats.last_reset = jiffies;
-#endif
-
-       INIT_WORK(&dispc.error_work, dispc_error_worker);
-
        dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
        if (!dispc_mem) {
                DSSERR("can't get IORESOURCE_MEM DISPC\n");
@@ -4129,22 +3644,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
-                            IRQF_SHARED, "OMAP DISPC", dispc.pdev);
-       if (r < 0) {
-               DSSERR("request_irq failed\n");
-               return r;
-       }
-
-       clk = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get fck\n");
-               r = PTR_ERR(clk);
-               return r;
-       }
-
-       dispc.dss_clk = clk;
-
        pm_runtime_enable(&pdev->dev);
 
        r = dispc_runtime_get();
@@ -4153,8 +3652,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
        _omap_dispc_initial_config();
 
-       _omap_dispc_initialize_irq();
-
        rev = dispc_read_reg(DISPC_REVISION);
        dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -4163,14 +3660,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
        dss_debugfs_create_file("dispc", dispc_dump_regs);
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-       dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
-#endif
        return 0;
 
 err_runtime_get:
        pm_runtime_disable(&pdev->dev);
-       clk_put(dispc.dss_clk);
        return r;
 }
 
@@ -4178,8 +3671,6 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
 {
        pm_runtime_disable(&pdev->dev);
 
-       clk_put(dispc.dss_clk);
-
        return 0;
 }
 
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c
new file mode 100644 (file)
index 0000000..18211a9
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * 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 "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t display_enabled_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
+}
+
+static ssize_t display_enabled_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       int r;
+       bool enabled;
+
+       r = strtobool(buf, &enabled);
+       if (r)
+               return r;
+
+       if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
+               if (enabled) {
+                       r = dssdev->driver->enable(dssdev);
+                       if (r)
+                               return r;
+               } else {
+                       dssdev->driver->disable(dssdev);
+               }
+       }
+
+       return size;
+}
+
+static ssize_t display_tear_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       dssdev->driver->get_te ?
+                       dssdev->driver->get_te(dssdev) : 0);
+}
+
+static ssize_t display_tear_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       int r;
+       bool te;
+
+       if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
+               return -ENOENT;
+
+       r = strtobool(buf, &te);
+       if (r)
+               return r;
+
+       r = dssdev->driver->enable_te(dssdev, te);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t display_timings_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       struct omap_video_timings t;
+
+       if (!dssdev->driver->get_timings)
+               return -ENOENT;
+
+       dssdev->driver->get_timings(dssdev, &t);
+
+       return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+                       t.pixel_clock,
+                       t.x_res, t.hfp, t.hbp, t.hsw,
+                       t.y_res, t.vfp, t.vbp, t.vsw);
+}
+
+static ssize_t display_timings_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       struct omap_video_timings t = dssdev->panel.timings;
+       int r, found;
+
+       if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
+               return -ENOENT;
+
+       found = 0;
+#ifdef CONFIG_OMAP2_DSS_VENC
+       if (strncmp("pal", buf, 3) == 0) {
+               t = omap_dss_pal_timings;
+               found = 1;
+       } else if (strncmp("ntsc", buf, 4) == 0) {
+               t = omap_dss_ntsc_timings;
+               found = 1;
+       }
+#endif
+       if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
+                               &t.pixel_clock,
+                               &t.x_res, &t.hfp, &t.hbp, &t.hsw,
+                               &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+               return -EINVAL;
+
+       r = dssdev->driver->check_timings(dssdev, &t);
+       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;
+}
+
+static ssize_t display_rotate_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       int rotate;
+       if (!dssdev->driver->get_rotate)
+               return -ENOENT;
+       rotate = dssdev->driver->get_rotate(dssdev);
+       return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
+}
+
+static ssize_t display_rotate_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       int rot, r;
+
+       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+               return -ENOENT;
+
+       r = kstrtoint(buf, 0, &rot);
+       if (r)
+               return r;
+
+       r = dssdev->driver->set_rotate(dssdev, rot);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t display_mirror_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       int mirror;
+       if (!dssdev->driver->get_mirror)
+               return -ENOENT;
+       mirror = dssdev->driver->get_mirror(dssdev);
+       return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
+}
+
+static ssize_t display_mirror_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       int r;
+       bool mirror;
+
+       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+               return -ENOENT;
+
+       r = strtobool(buf, &mirror);
+       if (r)
+               return r;
+
+       r = dssdev->driver->set_mirror(dssdev, mirror);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t display_wss_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       unsigned int wss;
+
+       if (!dssdev->driver->get_wss)
+               return -ENOENT;
+
+       wss = dssdev->driver->get_wss(dssdev);
+
+       return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
+}
+
+static ssize_t display_wss_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       u32 wss;
+       int r;
+
+       if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
+               return -ENOENT;
+
+       r = kstrtou32(buf, 0, &wss);
+       if (r)
+               return r;
+
+       if (wss > 0xfffff)
+               return -EINVAL;
+
+       r = dssdev->driver->set_wss(dssdev, wss);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+               display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
+               display_tear_show, display_tear_store);
+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+               display_timings_show, display_timings_store);
+static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
+               display_rotate_show, display_rotate_store);
+static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
+               display_mirror_show, display_mirror_store);
+static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
+               display_wss_show, display_wss_store);
+
+static struct device_attribute *display_sysfs_attrs[] = {
+       &dev_attr_enabled,
+       &dev_attr_tear_elim,
+       &dev_attr_timings,
+       &dev_attr_rotate,
+       &dev_attr_mirror,
+       &dev_attr_wss,
+       NULL
+};
+
+int display_init_sysfs(struct platform_device *pdev,
+               struct omap_dss_device *dssdev)
+{
+       struct device_attribute *attr;
+       int i, r;
+
+       /* create device sysfs files */
+       i = 0;
+       while ((attr = display_sysfs_attrs[i++]) != NULL) {
+               r = device_create_file(&dssdev->dev, attr);
+               if (r) {
+                       for (i = i - 2; i >= 0; i--) {
+                               attr = display_sysfs_attrs[i];
+                               device_remove_file(&dssdev->dev, attr);
+                       }
+
+                       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) {
+               while ((attr = display_sysfs_attrs[i++]) != NULL)
+                       device_remove_file(&dssdev->dev, attr);
+
+               DSSERR("failed to create sysfs display link\n");
+               return r;
+       }
+
+       return 0;
+}
+
+void display_uninit_sysfs(struct platform_device *pdev,
+               struct omap_dss_device *dssdev)
+{
+       struct device_attribute *attr;
+       int i = 0;
+
+       sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
+
+       while ((attr = display_sysfs_attrs[i++]) != NULL)
+               device_remove_file(&dssdev->dev, attr);
+}
index ccf8550fafdedf5440a5fc6e585b7cf8d02f2b0d..0aa8ad8f96679db07b11c6221f7a3eff9f150ffe 100644 (file)
 #include "dss.h"
 #include "dss_features.h"
 
-static ssize_t display_enabled_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
-}
-
-static ssize_t display_enabled_store(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int r;
-       bool enabled;
-
-       r = strtobool(buf, &enabled);
-       if (r)
-               return r;
-
-       if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
-               if (enabled) {
-                       r = dssdev->driver->enable(dssdev);
-                       if (r)
-                               return r;
-               } else {
-                       dssdev->driver->disable(dssdev);
-               }
-       }
-
-       return size;
-}
-
-static ssize_t display_tear_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       dssdev->driver->get_te ?
-                       dssdev->driver->get_te(dssdev) : 0);
-}
-
-static ssize_t display_tear_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int r;
-       bool te;
-
-       if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
-               return -ENOENT;
-
-       r = strtobool(buf, &te);
-       if (r)
-               return r;
-
-       r = dssdev->driver->enable_te(dssdev, te);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t display_timings_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       struct omap_video_timings t;
-
-       if (!dssdev->driver->get_timings)
-               return -ENOENT;
-
-       dssdev->driver->get_timings(dssdev, &t);
-
-       return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
-                       t.pixel_clock,
-                       t.x_res, t.hfp, t.hbp, t.hsw,
-                       t.y_res, t.vfp, t.vbp, t.vsw);
-}
-
-static ssize_t display_timings_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       struct omap_video_timings t = dssdev->panel.timings;
-       int r, found;
-
-       if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
-               return -ENOENT;
-
-       found = 0;
-#ifdef CONFIG_OMAP2_DSS_VENC
-       if (strncmp("pal", buf, 3) == 0) {
-               t = omap_dss_pal_timings;
-               found = 1;
-       } else if (strncmp("ntsc", buf, 4) == 0) {
-               t = omap_dss_ntsc_timings;
-               found = 1;
-       }
-#endif
-       if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
-                               &t.pixel_clock,
-                               &t.x_res, &t.hfp, &t.hbp, &t.hsw,
-                               &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
-               return -EINVAL;
-
-       r = dssdev->driver->check_timings(dssdev, &t);
-       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;
-}
-
-static ssize_t display_rotate_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int rotate;
-       if (!dssdev->driver->get_rotate)
-               return -ENOENT;
-       rotate = dssdev->driver->get_rotate(dssdev);
-       return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
-}
-
-static ssize_t display_rotate_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int rot, r;
-
-       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
-               return -ENOENT;
-
-       r = kstrtoint(buf, 0, &rot);
-       if (r)
-               return r;
-
-       r = dssdev->driver->set_rotate(dssdev, rot);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t display_mirror_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int mirror;
-       if (!dssdev->driver->get_mirror)
-               return -ENOENT;
-       mirror = dssdev->driver->get_mirror(dssdev);
-       return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
-}
-
-static ssize_t display_mirror_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int r;
-       bool mirror;
-
-       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
-               return -ENOENT;
-
-       r = strtobool(buf, &mirror);
-       if (r)
-               return r;
-
-       r = dssdev->driver->set_mirror(dssdev, mirror);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static ssize_t display_wss_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       unsigned int wss;
-
-       if (!dssdev->driver->get_wss)
-               return -ENOENT;
-
-       wss = dssdev->driver->get_wss(dssdev);
-
-       return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
-}
-
-static ssize_t display_wss_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       u32 wss;
-       int r;
-
-       if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
-               return -ENOENT;
-
-       r = kstrtou32(buf, 0, &wss);
-       if (r)
-               return r;
-
-       if (wss > 0xfffff)
-               return -EINVAL;
-
-       r = dssdev->driver->set_wss(dssdev, wss);
-       if (r)
-               return r;
-
-       return size;
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
-               display_enabled_show, display_enabled_store);
-static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
-               display_tear_show, display_tear_store);
-static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
-               display_timings_show, display_timings_store);
-static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
-               display_rotate_show, display_rotate_store);
-static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
-               display_mirror_show, display_mirror_store);
-static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
-               display_wss_show, display_wss_store);
-
-static struct device_attribute *display_sysfs_attrs[] = {
-       &dev_attr_enabled,
-       &dev_attr_tear_elim,
-       &dev_attr_timings,
-       &dev_attr_rotate,
-       &dev_attr_mirror,
-       &dev_attr_wss,
-       NULL
-};
-
 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
                        u16 *xres, u16 *yres)
 {
@@ -320,136 +76,8 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_default_get_timings);
 
-/*
- * 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, 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) {
-                       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) {
-               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,
-               struct omap_dss_device *dssdev)
-{
-       struct device_attribute *attr;
-       int i = 0;
-
-       sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
-
-       while ((attr = display_sysfs_attrs[i++]) != NULL)
-               device_remove_file(&dssdev->dev, attr);
-
-       dss_uninit_connections(dssdev);
-}
-
 static int dss_suspend_device(struct device *dev, void *data)
 {
-       int r;
        struct omap_dss_device *dssdev = to_dss_device(dev);
 
        if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
@@ -457,15 +85,7 @@ static int dss_suspend_device(struct device *dev, void *data)
                return 0;
        }
 
-       if (!dssdev->driver->suspend) {
-               DSSERR("display '%s' doesn't implement suspend\n",
-                               dssdev->name);
-               return -ENOSYS;
-       }
-
-       r = dssdev->driver->suspend(dssdev);
-       if (r)
-               return r;
+       dssdev->driver->disable(dssdev);
 
        dssdev->activate_after_resume = true;
 
@@ -492,8 +112,8 @@ static int dss_resume_device(struct device *dev, void *data)
        int r;
        struct omap_dss_device *dssdev = to_dss_device(dev);
 
-       if (dssdev->activate_after_resume && dssdev->driver->resume) {
-               r = dssdev->driver->resume(dssdev);
+       if (dssdev->activate_after_resume) {
+               r = dssdev->driver->enable(dssdev);
                if (r)
                        return r;
        }
index 56748cf8760e52cce7d51245fb2f4dc1808e98c8..4af136a04e53ce4fafc67a3435a0121062e53674 100644 (file)
@@ -49,34 +49,53 @@ static struct {
        struct omap_dss_output output;
 } dpi;
 
-static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
+static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
 {
-       int dsi_module;
-
-       dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
+       /*
+        * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
+        * would also be used for DISPC fclk. Meaning, when the DPI output is
+        * disabled, DISPC clock will be disabled, and TV out will stop.
+        */
+       switch (omapdss_get_version()) {
+       case OMAPDSS_VER_OMAP24xx:
+       case OMAPDSS_VER_OMAP34xx_ES1:
+       case OMAPDSS_VER_OMAP34xx_ES3:
+       case OMAPDSS_VER_OMAP3630:
+       case OMAPDSS_VER_AM35xx:
+               return NULL;
+       default:
+               break;
+       }
 
-       return dsi_get_dsidev_from_id(dsi_module);
+       switch (channel) {
+       case OMAP_DSS_CHANNEL_LCD:
+               return dsi_get_dsidev_from_id(0);
+       case OMAP_DSS_CHANNEL_LCD2:
+               return dsi_get_dsidev_from_id(1);
+       default:
+               return NULL;
+       }
 }
 
-static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
+static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 {
-       if (dssdev->clocks.dispc.dispc_fclk_src ==
-                       OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
-                       dssdev->clocks.dispc.dispc_fclk_src ==
-                       OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
-                       dssdev->clocks.dispc.channel.lcd_clk_src ==
-                       OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
-                       dssdev->clocks.dispc.channel.lcd_clk_src ==
-                       OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
-               return true;
-       else
-               return false;
+       switch (channel) {
+       case OMAP_DSS_CHANNEL_LCD:
+               return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
+       case OMAP_DSS_CHANNEL_LCD2:
+               return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+       default:
+               /* this shouldn't happen */
+               WARN_ON(1);
+               return OMAP_DSS_CLK_SRC_FCK;
+       }
 }
 
 static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
                unsigned long pck_req, unsigned long *fck, int *lck_div,
                int *pck_div)
 {
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
        struct dsi_clock_info dsi_cinfo;
        struct dispc_clock_info dispc_cinfo;
        int r;
@@ -90,7 +109,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
        if (r)
                return r;
 
-       dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
+       dss_select_lcd_clk_source(mgr->id,
+                       dpi_get_alt_clk_src(mgr->id));
 
        dpi.mgr_config.clock_info = dispc_cinfo;
 
@@ -135,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
        unsigned long pck;
        int r = 0;
 
-       if (dpi_use_dsi_pll(dssdev))
+       if (dpi.dsidev)
                r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
                                &lck_div, &pck_div);
        else
@@ -214,7 +234,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_src_sel;
 
-       if (dpi_use_dsi_pll(dssdev)) {
+       if (dpi.dsidev) {
                r = dsi_runtime_get(dpi.dsidev);
                if (r)
                        goto err_get_dsi;
@@ -242,10 +262,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 err_mgr_enable:
 err_set_mode:
-       if (dpi_use_dsi_pll(dssdev))
+       if (dpi.dsidev)
                dsi_pll_uninit(dpi.dsidev, true);
 err_dsi_pll_init:
-       if (dpi_use_dsi_pll(dssdev))
+       if (dpi.dsidev)
                dsi_runtime_put(dpi.dsidev);
 err_get_dsi:
 err_src_sel:
@@ -271,8 +291,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 
        dss_mgr_disable(mgr);
 
-       if (dpi_use_dsi_pll(dssdev)) {
-               dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+       if (dpi.dsidev) {
+               dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
                dsi_pll_uninit(dpi.dsidev, true);
                dsi_runtime_put(dpi.dsidev);
        }
@@ -311,13 +331,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
        unsigned long pck;
        struct dispc_clock_info dispc_cinfo;
 
-       if (dss_mgr_check_timings(mgr, timings))
+       if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
                return -EINVAL;
 
        if (timings->pixel_clock == 0)
                return -EINVAL;
 
-       if (dpi_use_dsi_pll(dssdev)) {
+       if (dpi.dsidev) {
                struct dsi_clock_info dsi_cinfo;
                r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
                                timings->pixel_clock * 1000,
@@ -359,8 +379,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
 }
 EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
 
+static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
+{
+       int r;
+
+       /* do initial setup with the PLL to see if it is operational */
+
+       r = dsi_runtime_get(dsidev);
+       if (r)
+               return r;
+
+       r = dsi_pll_init(dsidev, 0, 1);
+       if (r) {
+               dsi_runtime_put(dsidev);
+               return r;
+       }
+
+       dsi_pll_uninit(dsidev, true);
+       dsi_runtime_put(dsidev);
+
+       return 0;
+}
+
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 {
+       struct platform_device *dsidev;
+
        DSSDBG("init_display\n");
 
        if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
@@ -377,19 +421,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
                dpi.vdds_dsi_reg = vdds_dsi;
        }
 
-       if (dpi_use_dsi_pll(dssdev)) {
-               enum omap_dss_clk_source dispc_fclk_src =
-                       dssdev->clocks.dispc.dispc_fclk_src;
-               dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
+       /*
+        * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
+        * source for DPI is SoC integration detail, not something that should
+        * be configured in the dssdev
+        */
+       dsidev = dpi_get_dsidev(dssdev->channel);
+
+       if (dsidev && dpi_verify_dsi_pll(dsidev)) {
+               dsidev = NULL;
+               DSSWARN("DSI PLL not operational\n");
        }
 
+       if (dsidev)
+               DSSDBG("using DSI PLL for DPI clock\n");
+
+       dpi.dsidev = dsidev;
+
        return 0;
 }
 
 static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       const char *def_disp_name = dss_get_default_display_name();
+       const char *def_disp_name = omapdss_get_default_display_name();
        struct omap_dss_device *def_dssdev;
        int i;
 
@@ -438,9 +493,18 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
                return;
        }
 
+       r = omapdss_output_set_device(&dpi.output, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device: %s\n",
+                               dssdev->name);
+               dss_put_device(dssdev);
+               return;
+       }
+
        r = dss_add_device(dssdev);
        if (r) {
                DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               omapdss_output_unset_device(&dpi.output);
                dss_put_device(dssdev);
                return;
        }
index bee92846cfab930f6304a9ebb4316b25b8780bc7..28d41d16b7be45aa10d646ba8983cd57e418e363 100644 (file)
@@ -45,7 +45,6 @@
 #include "dss.h"
 #include "dss_features.h"
 
-/*#define VERBOSE_IRQ*/
 #define DSI_CATCH_MISSING_TE
 
 struct dsi_reg { u16 idx; };
@@ -535,42 +534,38 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
 }
 #endif
 
+static int verbose_irq;
+
 static void print_irq_status(u32 status)
 {
        if (status == 0)
                return;
 
-#ifndef VERBOSE_IRQ
-       if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+       if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
                return;
-#endif
-       printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
 
-#define PIS(x) \
-       if (status & DSI_IRQ_##x) \
-               printk(#x " ");
-#ifdef VERBOSE_IRQ
-       PIS(VC0);
-       PIS(VC1);
-       PIS(VC2);
-       PIS(VC3);
-#endif
-       PIS(WAKEUP);
-       PIS(RESYNC);
-       PIS(PLL_LOCK);
-       PIS(PLL_UNLOCK);
-       PIS(PLL_RECALL);
-       PIS(COMPLEXIO_ERR);
-       PIS(HS_TX_TIMEOUT);
-       PIS(LP_RX_TIMEOUT);
-       PIS(TE_TRIGGER);
-       PIS(ACK_TRIGGER);
-       PIS(SYNC_LOST);
-       PIS(LDO_POWER_GOOD);
-       PIS(TA_TIMEOUT);
+#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
+
+       pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+               status,
+               verbose_irq ? PIS(VC0) : "",
+               verbose_irq ? PIS(VC1) : "",
+               verbose_irq ? PIS(VC2) : "",
+               verbose_irq ? PIS(VC3) : "",
+               PIS(WAKEUP),
+               PIS(RESYNC),
+               PIS(PLL_LOCK),
+               PIS(PLL_UNLOCK),
+               PIS(PLL_RECALL),
+               PIS(COMPLEXIO_ERR),
+               PIS(HS_TX_TIMEOUT),
+               PIS(LP_RX_TIMEOUT),
+               PIS(TE_TRIGGER),
+               PIS(ACK_TRIGGER),
+               PIS(SYNC_LOST),
+               PIS(LDO_POWER_GOOD),
+               PIS(TA_TIMEOUT));
 #undef PIS
-
-       printk("\n");
 }
 
 static void print_irq_status_vc(int channel, u32 status)
@@ -578,28 +573,24 @@ static void print_irq_status_vc(int channel, u32 status)
        if (status == 0)
                return;
 
-#ifndef VERBOSE_IRQ
-       if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+       if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
                return;
-#endif
-       printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
 
-#define PIS(x) \
-       if (status & DSI_VC_IRQ_##x) \
-               printk(#x " ");
-       PIS(CS);
-       PIS(ECC_CORR);
-#ifdef VERBOSE_IRQ
-       PIS(PACKET_SENT);
-#endif
-       PIS(FIFO_TX_OVF);
-       PIS(FIFO_RX_OVF);
-       PIS(BTA);
-       PIS(ECC_NO_CORR);
-       PIS(FIFO_TX_UDF);
-       PIS(PP_BUSY_CHANGE);
+#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
+
+       pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
+               channel,
+               status,
+               PIS(CS),
+               PIS(ECC_CORR),
+               PIS(ECC_NO_CORR),
+               verbose_irq ? PIS(PACKET_SENT) : "",
+               PIS(BTA),
+               PIS(FIFO_TX_OVF),
+               PIS(FIFO_RX_OVF),
+               PIS(FIFO_TX_UDF),
+               PIS(PP_BUSY_CHANGE));
 #undef PIS
-       printk("\n");
 }
 
 static void print_irq_status_cio(u32 status)
@@ -607,34 +598,31 @@ static void print_irq_status_cio(u32 status)
        if (status == 0)
                return;
 
-       printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
-
-#define PIS(x) \
-       if (status & DSI_CIO_IRQ_##x) \
-               printk(#x " ");
-       PIS(ERRSYNCESC1);
-       PIS(ERRSYNCESC2);
-       PIS(ERRSYNCESC3);
-       PIS(ERRESC1);
-       PIS(ERRESC2);
-       PIS(ERRESC3);
-       PIS(ERRCONTROL1);
-       PIS(ERRCONTROL2);
-       PIS(ERRCONTROL3);
-       PIS(STATEULPS1);
-       PIS(STATEULPS2);
-       PIS(STATEULPS3);
-       PIS(ERRCONTENTIONLP0_1);
-       PIS(ERRCONTENTIONLP1_1);
-       PIS(ERRCONTENTIONLP0_2);
-       PIS(ERRCONTENTIONLP1_2);
-       PIS(ERRCONTENTIONLP0_3);
-       PIS(ERRCONTENTIONLP1_3);
-       PIS(ULPSACTIVENOT_ALL0);
-       PIS(ULPSACTIVENOT_ALL1);
+#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
+
+       pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+               status,
+               PIS(ERRSYNCESC1),
+               PIS(ERRSYNCESC2),
+               PIS(ERRSYNCESC3),
+               PIS(ERRESC1),
+               PIS(ERRESC2),
+               PIS(ERRESC3),
+               PIS(ERRCONTROL1),
+               PIS(ERRCONTROL2),
+               PIS(ERRCONTROL3),
+               PIS(STATEULPS1),
+               PIS(STATEULPS2),
+               PIS(STATEULPS3),
+               PIS(ERRCONTENTIONLP0_1),
+               PIS(ERRCONTENTIONLP1_1),
+               PIS(ERRCONTENTIONLP0_2),
+               PIS(ERRCONTENTIONLP1_2),
+               PIS(ERRCONTENTIONLP0_3),
+               PIS(ERRCONTENTIONLP1_3),
+               PIS(ULPSACTIVENOT_ALL0),
+               PIS(ULPSACTIVENOT_ALL1));
 #undef PIS
-
-       printk("\n");
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -1116,28 +1104,16 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
        }
 }
 
-#ifdef DEBUG
 static void _dsi_print_reset_status(struct platform_device *dsidev)
 {
        u32 l;
        int b0, b1, b2;
 
-       if (!dss_debug)
-               return;
-
        /* A dummy read using the SCP interface to any DSIPHY register is
         * required after DSIPHY reset to complete the reset of the DSI complex
         * I/O. */
        l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
 
-       printk(KERN_DEBUG "DSI resets: ");
-
-       l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
-       printk("PLL (%d) ", FLD_GET(l, 0, 0));
-
-       l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
-       printk("CIO (%d) ", FLD_GET(l, 29, 29));
-
        if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
                b0 = 28;
                b1 = 27;
@@ -1148,18 +1124,21 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
                b2 = 26;
        }
 
-       l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
-       printk("PHY (%x%x%x, %d, %d, %d)\n",
-                       FLD_GET(l, b0, b0),
-                       FLD_GET(l, b1, b1),
-                       FLD_GET(l, b2, b2),
-                       FLD_GET(l, 29, 29),
-                       FLD_GET(l, 30, 30),
-                       FLD_GET(l, 31, 31));
+#define DSI_FLD_GET(fld, start, end)\
+       FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
+
+       pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
+               DSI_FLD_GET(PLL_STATUS, 0, 0),
+               DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
+               DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
+               DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
+               DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
+               DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
+               DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
+               DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
+
+#undef DSI_FLD_GET
 }
-#else
-#define _dsi_print_reset_status(x)
-#endif
 
 static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
 {
@@ -1407,6 +1386,11 @@ retry:
                                cur.dsi_pll_hsdiv_dispc_clk =
                                        cur.clkin4ddr / cur.regm_dispc;
 
+                               if (cur.regm_dispc > 1 &&
+                                               cur.regm_dispc % 2 != 0 &&
+                                               req_pck >= 1000000)
+                                       continue;
+
                                /* this will narrow down the search a bit,
                                 * but still give pixclocks below what was
                                 * requested */
@@ -1621,7 +1605,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
        u8 regn_start, regn_end, regm_start, regm_end;
        u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
 
-       DSSDBGF();
+       DSSDBG("DSI PLL clock config starts");
 
        dsi->current_cinfo.clkin = cinfo->clkin;
        dsi->current_cinfo.fint = cinfo->fint;
@@ -1757,11 +1741,21 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 
        DSSDBG("PLL init\n");
 
+       /*
+        * It seems that on many OMAPs we need to enable both to have a
+        * functional HSDivider.
+        */
+       enable_hsclk = enable_hsdiv = true;
+
        if (dsi->vdds_dsi_reg == NULL) {
                struct regulator *vdds_dsi;
 
                vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 
+               /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+               if (IS_ERR(vdds_dsi))
+                       vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
                if (IS_ERR(vdds_dsi)) {
                        DSSERR("can't get VDDS_DSI regulator\n");
                        return PTR_ERR(vdds_dsi);
@@ -2440,7 +2434,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
        int r;
        u32 l;
 
-       DSSDBGF();
+       DSSDBG("DSI CIO init starts");
 
        r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
        if (r)
@@ -2791,7 +2785,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
 {
        u32 r;
 
-       DSSDBGF("%d", channel);
+       DSSDBG("Initial config of virtual channel %d", channel);
 
        r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
 
@@ -2823,7 +2817,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
        if (dsi->vc[channel].source == source)
                return 0;
 
-       DSSDBGF("%d", channel);
+       DSSDBG("Source config of virtual channel %d", channel);
 
        dsi_sync_vc(dsidev, channel);
 
@@ -3581,7 +3575,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
        int r, i;
        unsigned mask;
 
-       DSSDBGF();
+       DSSDBG("Entering ULPS");
 
        WARN_ON(!dsi_bus_is_locked(dsidev));
 
@@ -4285,7 +4279,7 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
        unsigned long pck;
        int r;
 
-       DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
+       DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
 
        mutex_lock(&dsi->lock);
 
@@ -4541,7 +4535,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
        dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
 }
 
-static void dsi_framedone_irq_callback(void *data, u32 mask)
+static void dsi_framedone_irq_callback(void *data)
 {
        struct platform_device *dsidev = (struct platform_device *) data;
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4615,7 +4609,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        struct omap_overlay_manager *mgr = dssdev->output->manager;
        int r;
-       u32 irq = 0;
 
        if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
                dsi->timings.hsw = 1;
@@ -4625,12 +4618,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
                dsi->timings.vfp = 0;
                dsi->timings.vbp = 0;
 
-               irq = dispc_mgr_get_framedone_irq(mgr->id);
-
-               r = omap_dispc_register_isr(dsi_framedone_irq_callback,
-                       (void *) dsidev, irq);
+               r = dss_mgr_register_framedone_handler(mgr,
+                               dsi_framedone_irq_callback, dsidev);
                if (r) {
-                       DSSERR("can't get FRAMEDONE irq\n");
+                       DSSERR("can't register FRAMEDONE handler\n");
                        goto err;
                }
 
@@ -4668,8 +4659,8 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
        return 0;
 err1:
        if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
-               omap_dispc_unregister_isr(dsi_framedone_irq_callback,
-                       (void *) dsidev, irq);
+               dss_mgr_unregister_framedone_handler(mgr,
+                               dsi_framedone_irq_callback, dsidev);
 err:
        return r;
 }
@@ -4680,14 +4671,9 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *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(mgr->id);
-
-               omap_dispc_unregister_isr(dsi_framedone_irq_callback,
-                       (void *) dsidev, irq);
-       }
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
+               dss_mgr_unregister_framedone_handler(mgr,
+                               dsi_framedone_irq_callback, dsidev);
 }
 
 static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4730,7 +4716,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
        if (r)
                goto err1;
 
-       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(mgr->id,
                        dssdev->clocks.dispc.channel.lcd_clk_src);
@@ -4765,7 +4750,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 err3:
        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(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 
@@ -4792,7 +4776,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
        dsi_vc_enable(dsidev, 2, 0);
        dsi_vc_enable(dsidev, 3, 0);
 
-       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(mgr->id, OMAP_DSS_CLK_SRC_FCK);
        dsi_cio_uninit(dsidev);
@@ -4981,6 +4964,10 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
 
                vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 
+               /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+               if (IS_ERR(vdds_dsi))
+                       vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
                if (IS_ERR(vdds_dsi)) {
                        DSSERR("can't get VDDS_DSI regulator\n");
                        return PTR_ERR(vdds_dsi);
@@ -5121,7 +5108,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
 {
        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();
+       const char *def_disp_name = omapdss_get_default_display_name();
        struct omap_dss_device *def_dssdev;
        int i;
 
@@ -5151,6 +5138,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
 
 static void __init dsi_probe_pdata(struct platform_device *dsidev)
 {
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        struct omap_dss_device *plat_dssdev;
        struct omap_dss_device *dssdev;
        int r;
@@ -5173,9 +5161,18 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
                return;
        }
 
+       r = omapdss_output_set_device(&dsi->output, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device: %s\n",
+                               dssdev->name);
+               dss_put_device(dssdev);
+               return;
+       }
+
        r = dss_add_device(dssdev);
        if (r) {
                DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               omapdss_output_unset_device(&dsi->output);
                dss_put_device(dssdev);
                return;
        }
index 602102cebcbf790240c6404db9a075941164931f..054c2a22b3f1c650aca01037bd6d125d3a55235f 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/gfp.h>
+#include <linux/sizes.h>
 
 #include <video/omapdss.h>
 
@@ -76,6 +77,7 @@ static struct {
 
        struct clk      *dpll4_m4_ck;
        struct clk      *dss_clk;
+       unsigned long   dss_clk_rate;
 
        unsigned long   cache_req_pck;
        unsigned long   cache_prate;
@@ -96,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = {
        [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]  = "DSI_PLL_HSDIV_DISPC",
        [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]    = "DSI_PLL_HSDIV_DSI",
        [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_FCK",
+       [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
+       [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]   = "DSI_PLL2_HSDIV_DSI",
 };
 
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -151,6 +155,21 @@ static void dss_restore_context(void)
 #undef SR
 #undef RR
 
+int dss_get_ctx_loss_count(void)
+{
+       struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
+       int cnt;
+
+       if (!board_data->get_context_loss_count)
+               return -ENOENT;
+
+       cnt = board_data->get_context_loss_count(&dss.pdev->dev);
+
+       WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+       return cnt;
+}
+
 void dss_sdi_init(int datapairs)
 {
        u32 l;
@@ -301,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s)
 #undef DUMPREG
 }
 
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
 {
        struct platform_device *dsidev;
        int b;
@@ -372,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
        struct platform_device *dsidev;
        int b, ix, pos;
 
-       if (!dss_has_feature(FEAT_LCD_CLK_SRC))
+       if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
+               dss_select_dispc_clk_source(clk_src);
                return;
+       }
 
        switch (clk_src) {
        case OMAP_DSS_CLK_SRC_FCK:
@@ -429,6 +450,29 @@ 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;
+
+               if (cinfo->fck_div > dss.feat->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 *
+                       dss.feat->dss_fck_multiplier;
+       } 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) {
@@ -446,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
                        return -EINVAL;
        }
 
+       dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
+       WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
+
        DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
 
        return 0;
@@ -459,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void)
                return 0;
 }
 
+unsigned long dss_get_dispc_clk_rate(void)
+{
+       return dss.dss_clk_rate;
+}
+
+static int dss_setup_default_clock(void)
+{
+       unsigned long max_dss_fck, prate;
+       unsigned fck_div;
+       struct dss_clock_info dss_cinfo = { 0 };
+       int r;
+
+       if (dss.dpll4_m4_ck == NULL)
+               return 0;
+
+       max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+       prate = dss_get_dpll4_rate();
+
+       fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
+                       max_dss_fck);
+
+       dss_cinfo.fck_div = fck_div;
+
+       r = dss_calc_clock_rates(&dss_cinfo);
+       if (r)
+               return r;
+
+       r = dss_set_clock_div(&dss_cinfo);
+       if (r)
+               return r;
+
+       return 0;
+}
+
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
                struct dispc_clock_info *dispc_cinfo)
 {
@@ -748,7 +831,7 @@ static void dss_runtime_put(void)
 }
 
 /* DEBUGFS */
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
        dss_dump_clocks(s);
@@ -796,7 +879,6 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
 
 static int __init dss_init_features(struct platform_device *pdev)
 {
-       struct omap_dss_board_info *pdata = pdev->dev.platform_data;
        const struct dss_features *src;
        struct dss_features *dst;
 
@@ -806,7 +888,7 @@ static int __init dss_init_features(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       switch (pdata->version) {
+       switch (omapdss_get_version()) {
        case OMAPDSS_VER_OMAP24xx:
                src = &omap24xx_dss_feats;
                break;
@@ -871,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
        if (r)
                return r;
 
+       r = dss_setup_default_clock();
+       if (r)
+               goto err_setup_clocks;
+
        pm_runtime_enable(&pdev->dev);
 
        r = dss_runtime_get();
        if (r)
                goto err_runtime_get;
 
+       dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
        /* Select DPLL */
        REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
 
+       dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+
 #ifdef CONFIG_OMAP2_DSS_VENC
        REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
        REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
@@ -903,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
 err_runtime_get:
        pm_runtime_disable(&pdev->dev);
+err_setup_clocks:
        dss_put_clocks();
        return r;
 }
index 6728892f9dad596040c8c5ae0c270036f4ba5975..610c8e563daa2033750c3eec12f3328ad7db38e4 100644 (file)
 #ifndef __OMAP2_DSS_H
 #define __OMAP2_DSS_H
 
-#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
-#define DEBUG
-#endif
+#include <linux/interrupt.h>
 
-#ifdef DEBUG
-extern bool dss_debug;
-#ifdef DSS_SUBSYS_NAME
-#define DSSDBG(format, ...) \
-       if (dss_debug) \
-               printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
-               ## __VA_ARGS__)
-#else
-#define DSSDBG(format, ...) \
-       if (dss_debug) \
-               printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
+#ifdef pr_fmt
+#undef pr_fmt
 #endif
 
 #ifdef DSS_SUBSYS_NAME
-#define DSSDBGF(format, ...) \
-       if (dss_debug) \
-               printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
-                               ": %s(" format ")\n", \
-                               __func__, \
-                               ## __VA_ARGS__)
+#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
 #else
-#define DSSDBGF(format, ...) \
-       if (dss_debug) \
-               printk(KERN_DEBUG "omapdss: " \
-                               ": %s(" format ")\n", \
-                               __func__, \
-                               ## __VA_ARGS__)
-#endif
-
-#else /* DEBUG */
-#define DSSDBG(format, ...)
-#define DSSDBGF(format, ...)
+#define pr_fmt(fmt) fmt
 #endif
 
+#define DSSDBG(format, ...) \
+       pr_debug(format, ## __VA_ARGS__)
 
 #ifdef DSS_SUBSYS_NAME
 #define DSSERR(format, ...) \
@@ -186,11 +162,10 @@ struct seq_file;
 struct platform_device;
 
 /* core */
-const char *dss_get_default_display_name(void);
+struct platform_device *dss_get_core_pdev(void);
 struct bus_type *dss_get_bus(void);
 struct regulator *dss_get_vdds_dsi(void);
 struct regulator *dss_get_vdds_sdi(void);
-int dss_get_ctx_loss_count(struct device *dev);
 int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
 void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
 int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
@@ -204,55 +179,18 @@ 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);
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
-void dss_mgr_start_update(struct omap_overlay_manager *mgr);
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
-
-int dss_mgr_enable(struct omap_overlay_manager *mgr);
-void dss_mgr_disable(struct omap_overlay_manager *mgr);
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
-               struct omap_overlay_manager_info *info);
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
-               struct omap_overlay_manager_info *info);
-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,
-               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);
-
-bool dss_ovl_is_enabled(struct omap_overlay *ovl);
-int dss_ovl_enable(struct omap_overlay *ovl);
-int dss_ovl_disable(struct omap_overlay *ovl);
-int dss_ovl_set_info(struct omap_overlay *ovl,
-               struct omap_overlay_info *info);
-void dss_ovl_get_info(struct omap_overlay *ovl,
-               struct omap_overlay_info *info);
-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);
 
-int dss_init_device(struct platform_device *pdev,
+int display_init_sysfs(struct platform_device *pdev,
                struct omap_dss_device *dssdev);
-void dss_uninit_device(struct platform_device *pdev,
+void display_uninit_sysfs(struct platform_device *pdev,
                struct omap_dss_device *dssdev);
 
 /* manager */
@@ -299,21 +237,23 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
 int dss_init_platform_driver(void) __init;
 void dss_uninit_platform_driver(void);
 
+unsigned long dss_get_dispc_clk_rate(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);
 void dss_dump_clocks(struct seq_file *s);
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s);
 #endif
 
+int dss_get_ctx_loss_count(void);
+
 void dss_sdi_init(int datapairs);
 int dss_sdi_enable(void);
 void dss_sdi_disable(void);
 
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
 void dss_select_dsi_clk_source(int dsi_module,
                enum omap_dss_clk_source clk_src);
 void dss_select_lcd_clk_source(enum omap_channel channel,
@@ -326,6 +266,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_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
                struct dispc_clock_info *dispc_cinfo);
@@ -413,8 +354,6 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
 }
 static inline struct platform_device *dsi_get_dsidev_from_id(int module)
 {
-       WARN("%s: DSI not compiled in, returning platform device as NULL\n",
-                       __func__);
        return NULL;
 }
 #endif
@@ -427,15 +366,10 @@ void dpi_uninit_platform_driver(void) __exit;
 int dispc_init_platform_driver(void) __init;
 void dispc_uninit_platform_driver(void) __exit;
 void dispc_dump_clocks(struct seq_file *s);
-void dispc_irq_handler(void);
-
-int dispc_runtime_get(void);
-void dispc_runtime_put(void);
 
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
 
-void dispc_lcd_enable_signal_polarity(bool act_high);
 void dispc_lcd_enable_signal(bool enable);
 void dispc_pck_free_enable(bool enable);
 void dispc_enable_fifomerge(bool enable);
@@ -455,36 +389,14 @@ 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, 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);
-
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
-u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
-u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
-bool dispc_mgr_go_busy(enum omap_channel channel);
-void dispc_mgr_go(enum omap_channel channel);
-bool dispc_mgr_is_enabled(enum omap_channel channel);
-void dispc_mgr_enable(enum omap_channel channel, bool enable);
-bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel);
-void dispc_mgr_set_timings(enum omap_channel channel,
-               struct omap_video_timings *timings);
+
 unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
 unsigned long dispc_core_clk_rate(void);
 void dispc_mgr_set_clock_div(enum omap_channel channel,
-               struct dispc_clock_info *cinfo);
+               const struct dispc_clock_info *cinfo);
 int dispc_mgr_get_clock_div(enum omap_channel channel,
                struct dispc_clock_info *cinfo);
-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);
@@ -536,6 +448,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);
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_core_disable(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,
index 3e8287c8709dcfe2175ac4f36bc143b8df30eeaa..18688c12e30d9e5399d732ce6d972d101ae46b55 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -429,8 +430,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
         * scaler cannot scale a image with width more than 768.
         */
        [FEAT_PARAM_LINEWIDTH]                  = { 1, 768 },
-       [FEAT_PARAM_MGR_WIDTH]                  = { 1, 2048 },
-       [FEAT_PARAM_MGR_HEIGHT]                 = { 1, 2048 },
 };
 
 static const struct dss_param_range omap3_dss_param_range[] = {
@@ -445,8 +444,6 @@ static const struct dss_param_range omap3_dss_param_range[] = {
        [FEAT_PARAM_DSI_FCK]                    = { 0, 173000000 },
        [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
        [FEAT_PARAM_LINEWIDTH]                  = { 1, 1024 },
-       [FEAT_PARAM_MGR_WIDTH]                  = { 1, 2048 },
-       [FEAT_PARAM_MGR_HEIGHT]                 = { 1, 2048 },
 };
 
 static const struct dss_param_range omap4_dss_param_range[] = {
@@ -461,8 +458,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
        [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[] = {
@@ -477,8 +472,6 @@ static const struct dss_param_range omap5_dss_param_range[] = {
        [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 enum dss_feat_id omap2_dss_feat_list[] = {
@@ -820,6 +813,7 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
        .audio_start            =       ti_hdmi_4xxx_audio_start,
        .audio_stop             =       ti_hdmi_4xxx_audio_stop,
        .audio_config           =       ti_hdmi_4xxx_audio_config,
+       .audio_get_dma_port     =       ti_hdmi_4xxx_audio_get_dma_port,
 #endif
 
 };
@@ -846,11 +840,13 @@ int dss_feat_get_num_mgrs(void)
 {
        return omap_current_dss_features->num_mgrs;
 }
+EXPORT_SYMBOL(dss_feat_get_num_mgrs);
 
 int dss_feat_get_num_ovls(void)
 {
        return omap_current_dss_features->num_ovls;
 }
+EXPORT_SYMBOL(dss_feat_get_num_ovls);
 
 int dss_feat_get_num_wbs(void)
 {
@@ -871,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
 {
        return omap_current_dss_features->supported_displays[channel];
 }
+EXPORT_SYMBOL(dss_feat_get_supported_displays);
 
 enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
 {
        return omap_current_dss_features->supported_outputs[channel];
 }
+EXPORT_SYMBOL(dss_feat_get_supported_outputs);
 
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
 {
        return omap_current_dss_features->supported_color_modes[plane];
 }
+EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
 
 enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
 {
index fc492ef72a51b35f523b09a7c8622cbd3103851c..489b9bec4a6d5ceebbc0cc01caaf9b96b7583673 100644 (file)
@@ -98,19 +98,12 @@ enum dss_range_param {
        FEAT_PARAM_DSI_FCK,
        FEAT_PARAM_DOWNSCALE,
        FEAT_PARAM_LINEWIDTH,
-       FEAT_PARAM_MGR_WIDTH,
-       FEAT_PARAM_MGR_HEIGHT,
 };
 
 /* 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,
                enum omap_color_mode color_mode);
index 0d6d7213a858634122951fcdc6b78e1e698ca2e5..769d0828581ccfec1f350b49b8d1d791732e9b04 100644 (file)
@@ -60,6 +60,7 @@
 static struct {
        struct mutex lock;
        struct platform_device *pdev;
+
        struct hdmi_ip_data ip_data;
 
        struct clk *sys_clk;
@@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
                        false, },
                { 0x55, HDMI_DVI },
        },
+       {
+               { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
+                       OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+                       false, },
+               { 0x44, HDMI_DVI },
+       },
 };
 
 static int hdmi_runtime_get(void)
@@ -323,7 +330,6 @@ static void hdmi_runtime_put(void)
 
 static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 {
-       struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data;
        int r;
 
        struct gpio gpios[] = {
@@ -334,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 
        DSSDBG("init_display\n");
 
-       dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version);
+       dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
 
        if (hdmi.vdda_hdmi_dac_reg == NULL) {
                struct regulator *reg;
 
                reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
 
+               /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
+               if (IS_ERR(reg))
+                       reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
+
                if (IS_ERR(reg)) {
                        DSSERR("can't get VDDA_HDMI_DAC regulator\n");
                        return PTR_ERR(reg);
@@ -356,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
        return 0;
 }
 
-static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
+static void hdmi_uninit_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("uninit_display\n");
 
@@ -399,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
 {
        int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 
-       if ((timing2->pixel_clock == timing1->pixel_clock) &&
+       if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
+                       DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
                (timing2->x_res == timing1->x_res) &&
                (timing2->y_res == timing1->y_res)) {
 
@@ -501,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
        DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 
-static int hdmi_power_on(struct omap_dss_device *dssdev)
+static int hdmi_power_on_core(struct omap_dss_device *dssdev)
 {
        int r;
-       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);
@@ -522,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        if (r)
                goto err_runtime_get;
 
+       /* Make selection of HDMI in DSS */
+       dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+       return 0;
+
+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 r;
+}
+
+static void hdmi_power_off_core(struct omap_dss_device *dssdev)
+{
+       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);
+}
+
+static int hdmi_power_on_full(struct omap_dss_device *dssdev)
+{
+       int r;
+       struct omap_video_timings *p;
+       struct omap_overlay_manager *mgr = dssdev->output->manager;
+       unsigned long phy;
+
+       r = hdmi_power_on_core(dssdev);
+       if (r)
+               return r;
+
        dss_mgr_disable(mgr);
 
        p = &hdmi.ip_data.cfg.timings;
@@ -549,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
        hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 
-       /* Make selection of HDMI in DSS */
-       dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
-
-       /* Select the dispc clock source as PRCM clock, to ensure that it is not
-        * DSI PLL source as the clock selected by DSI PLL might not be
-        * sufficient for the resolution selected / that can be changed
-        * dynamically by user. This can be moved to single location , say
-        * Boardfile.
-        */
-       dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
-
        /* bypass TV gamma table */
        dispc_enable_gamma_table(0);
 
@@ -583,16 +612,11 @@ err_vid_enable:
 err_phy_enable:
        hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 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);
+       hdmi_power_off_core(dssdev);
        return -EIO;
 }
 
-static void hdmi_power_off(struct omap_dss_device *dssdev)
+static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 {
        struct omap_overlay_manager *mgr = dssdev->output->manager;
 
@@ -601,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
        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);
+       hdmi_power_off_core(dssdev);
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -716,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
-       r = hdmi_power_on(dssdev);
+       r = hdmi_power_on_full(dssdev);
        if (r) {
                DSSERR("failed to power on device\n");
                goto err1;
@@ -738,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
 
        mutex_lock(&hdmi.lock);
 
-       hdmi_power_off(dssdev);
+       hdmi_power_off_full(dssdev);
 
        omap_dss_stop_device(dssdev);
 
        mutex_unlock(&hdmi.lock);
 }
 
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       DSSDBG("ENTER omapdss_hdmi_core_enable\n");
+
+       mutex_lock(&hdmi.lock);
+
+       hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
+
+       r = hdmi_power_on_core(dssdev);
+       if (r) {
+               DSSERR("failed to power on device\n");
+               goto err0;
+       }
+
+       mutex_unlock(&hdmi.lock);
+       return 0;
+
+err0:
+       mutex_unlock(&hdmi.lock);
+       return r;
+}
+
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
+{
+       DSSDBG("Enter omapdss_hdmi_core_disable\n");
+
+       mutex_lock(&hdmi.lock);
+
+       hdmi_power_off_core(dssdev);
+
+       mutex_unlock(&hdmi.lock);
+}
+
 static int hdmi_get_clocks(struct platform_device *pdev)
 {
        struct clk *clk;
@@ -913,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
 static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       const char *def_disp_name = dss_get_default_display_name();
+       const char *def_disp_name = omapdss_get_default_display_name();
        struct omap_dss_device *def_dssdev;
        int i;
 
@@ -971,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
                return;
        }
 
+       r = omapdss_output_set_device(&hdmi.output, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device: %s\n",
+                               dssdev->name);
+               dss_put_device(dssdev);
+               return;
+       }
+
        r = dss_add_device(dssdev);
        if (r) {
                DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               omapdss_output_unset_device(&hdmi.output);
+               hdmi_uninit_display(dssdev);
                dss_put_device(dssdev);
                return;
        }
@@ -1000,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
 /* HDMI HW IP initialisation */
 static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 {
-       struct resource *hdmi_mem;
+       struct resource *res;
        int r;
 
        hdmi.pdev = pdev;
 
        mutex_init(&hdmi.lock);
+       mutex_init(&hdmi.ip_data.lock);
 
-       hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
-       if (!hdmi_mem) {
+       res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
+       if (!res) {
                DSSERR("can't get IORESOURCE_MEM HDMI\n");
                return -EINVAL;
        }
 
        /* Base address taken from platform */
-       hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
-                                               resource_size(hdmi_mem));
+       hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
        if (!hdmi.ip_data.base_wp) {
                DSSERR("can't ioremap WP\n");
                return -ENOMEM;
@@ -1023,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 
        r = hdmi_get_clocks(pdev);
        if (r) {
-               iounmap(hdmi.ip_data.base_wp);
+               DSSERR("can't get clocks\n");
                return r;
        }
 
@@ -1034,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
        hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
        hdmi.ip_data.phy_offset = HDMI_PHY;
 
-       mutex_init(&hdmi.ip_data.lock);
-
-       hdmi_panel_init();
+       r = hdmi_panel_init();
+       if (r) {
+               DSSERR("can't init panel\n");
+               goto err_panel_init;
+       }
 
        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
@@ -1045,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
        hdmi_probe_pdata(pdev);
 
        return 0;
+
+err_panel_init:
+       hdmi_put_clocks();
+       return r;
 }
 
 static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1068,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
        hdmi_put_clocks();
 
-       iounmap(hdmi.ip_data.base_wp);
-
        return 0;
 }
 
index 69fb115bab32928d7ce58574cb0120020b5720fe..dfb8eda81b61d85169e55b424fa92dbc5a7ce8c5 100644 (file)
@@ -280,58 +280,6 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&hdmi.lock);
 }
 
-static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
-{
-       int r = 0;
-
-       mutex_lock(&hdmi.lock);
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-               r = -EINVAL;
-               goto err;
-       }
-
-       /*
-        * TODO: notify audio users that the display was suspended. For now,
-        * disable audio locally to not break our audio state machine.
-        */
-       hdmi_panel_audio_disable(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-       omapdss_hdmi_display_disable(dssdev);
-
-err:
-       mutex_unlock(&hdmi.lock);
-
-       return r;
-}
-
-static int hdmi_panel_resume(struct omap_dss_device *dssdev)
-{
-       int r = 0;
-
-       mutex_lock(&hdmi.lock);
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-               r = -EINVAL;
-               goto err;
-       }
-
-       r = omapdss_hdmi_display_enable(dssdev);
-       if (r) {
-               DSSERR("failed to power on\n");
-               goto err;
-       }
-       /* TODO: notify audio users that the panel resumed. */
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
-       mutex_unlock(&hdmi.lock);
-
-       return r;
-}
-
 static void hdmi_get_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
@@ -379,20 +327,22 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
 static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
 {
        int r;
+       bool need_enable;
 
        mutex_lock(&hdmi.lock);
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-               r = omapdss_hdmi_display_enable(dssdev);
+       need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+       if (need_enable) {
+               r = omapdss_hdmi_core_enable(dssdev);
                if (r)
                        goto err;
        }
 
        r = omapdss_hdmi_read_edid(buf, len);
 
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-               omapdss_hdmi_display_disable(dssdev);
+       if (need_enable)
+               omapdss_hdmi_core_disable(dssdev);
 err:
        mutex_unlock(&hdmi.lock);
 
@@ -402,20 +352,22 @@ err:
 static bool hdmi_detect(struct omap_dss_device *dssdev)
 {
        int r;
+       bool need_enable;
 
        mutex_lock(&hdmi.lock);
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-               r = omapdss_hdmi_display_enable(dssdev);
+       need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+       if (need_enable) {
+               r = omapdss_hdmi_core_enable(dssdev);
                if (r)
                        goto err;
        }
 
        r = omapdss_hdmi_detect();
 
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-               omapdss_hdmi_display_disable(dssdev);
+       if (need_enable)
+               omapdss_hdmi_core_disable(dssdev);
 err:
        mutex_unlock(&hdmi.lock);
 
@@ -427,8 +379,6 @@ static struct omap_dss_driver hdmi_driver = {
        .remove         = hdmi_panel_remove,
        .enable         = hdmi_panel_enable,
        .disable        = hdmi_panel_disable,
-       .suspend        = hdmi_panel_suspend,
-       .resume         = hdmi_panel_resume,
        .get_timings    = hdmi_get_timings,
        .set_timings    = hdmi_set_timings,
        .check_timings  = hdmi_check_timings,
@@ -454,9 +404,7 @@ int hdmi_panel_init(void)
        spin_lock_init(&hdmi.audio_lock);
 #endif
 
-       omap_dss_register_driver(&hdmi_driver);
-
-       return 0;
+       return omap_dss_register_driver(&hdmi_driver);
 }
 
 void hdmi_panel_exit(void)
index c54d2f620ce3e5d94c4fb65ef39fb4fd150c44ab..2551eaa14c42537fb8ed38464b68eb42b0259b85 100644 (file)
 static int num_managers;
 static struct omap_overlay_manager *managers;
 
-static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
-{
-       return mgr->output ? mgr->output->device : NULL;
-}
-
-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;
-
-       r = dispc_runtime_get();
-       if (r)
-               return r;
-
-       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
-               irq = DISPC_IRQ_EVSYNC_ODD;
-       else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
-               irq = DISPC_IRQ_EVSYNC_EVEN;
-       else
-               irq = dispc_mgr_get_vsync_irq(mgr->id);
-
-       r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-
-       dispc_runtime_put();
-
-       return r;
-}
-
 int dss_init_overlay_managers(struct platform_device *pdev)
 {
        int i, r;
@@ -99,15 +69,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                        break;
                }
 
-               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);
index 813f26682b7a836f127449517f9ed82dd2c33dac..79dea1a1a7320a6f4198891b10172ee10f7afe6b 100644 (file)
@@ -114,35 +114,67 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
        return NULL;
 }
 
-struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
+static const struct dss_mgr_ops *dss_mgr_ops;
+
+int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
 {
-       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;
-       }
+       if (dss_mgr_ops)
+               return -EBUSY;
+
+       dss_mgr_ops = mgr_ops;
+
+       return 0;
+}
+EXPORT_SYMBOL(dss_install_mgr_ops);
+
+void dss_uninstall_mgr_ops(void)
+{
+       dss_mgr_ops = NULL;
+}
+EXPORT_SYMBOL(dss_uninstall_mgr_ops);
+
+void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+               const struct omap_video_timings *timings)
+{
+       dss_mgr_ops->set_timings(mgr, timings);
+}
+EXPORT_SYMBOL(dss_mgr_set_timings);
+
+void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+               const struct dss_lcd_mgr_config *config)
+{
+       dss_mgr_ops->set_lcd_config(mgr, config);
+}
+EXPORT_SYMBOL(dss_mgr_set_lcd_config);
+
+int dss_mgr_enable(struct omap_overlay_manager *mgr)
+{
+       return dss_mgr_ops->enable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_enable);
+
+void dss_mgr_disable(struct omap_overlay_manager *mgr)
+{
+       dss_mgr_ops->disable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_disable);
 
-       return out;
+void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+{
+       dss_mgr_ops->start_update(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_start_update);
+
+int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data)
+{
+       return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
+}
+EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
+
+void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data)
+{
+       dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
 }
+EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
index 45f4994bc6b06b64056db0cc9a7075532757bdc3..eccde322c28a53b72bece7945a809a5ddd6f843a 100644 (file)
 static int num_overlays;
 static struct omap_overlay *overlays;
 
-static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
-{
-       return ovl->manager ?
-               (ovl->manager->output ? ovl->manager->output->device : NULL) :
-               NULL;
-}
-
 int omap_dss_get_num_overlays(void)
 {
        return num_overlays;
@@ -93,16 +86,6 @@ void dss_init_overlays(struct platform_device *pdev)
                        break;
                }
 
-               ovl->is_enabled = &dss_ovl_is_enabled;
-               ovl->enable = &dss_ovl_enable;
-               ovl->disable = &dss_ovl_disable;
-               ovl->set_manager = &dss_ovl_set_manager;
-               ovl->unset_manager = &dss_ovl_unset_manager;
-               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);
index 7282e5af3e1a2e2458605c5a6f76b7d371269be3..e903dd3f54d9466e802126e3801ac0c86dc10d4c 100644 (file)
@@ -342,7 +342,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
        return 0;
 }
 
-static void framedone_callback(void *data, u32 mask)
+static void framedone_callback(void *data)
 {
        void (*callback)(void *data);
 
@@ -908,8 +908,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
-       r = omap_dispc_register_isr(framedone_callback, NULL,
-                       DISPC_IRQ_FRAMEDONE);
+       r = dss_mgr_register_framedone_handler(out->manager,
+                       framedone_callback, NULL);
        if (r) {
                DSSERR("can't get FRAMEDONE irq\n");
                goto err1;
@@ -933,8 +933,10 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
 
 void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
 {
-       omap_dispc_unregister_isr(framedone_callback, NULL,
-                       DISPC_IRQ_FRAMEDONE);
+       struct omap_dss_output *out = dssdev->output;
+
+       dss_mgr_unregister_framedone_handler(out->manager,
+                       framedone_callback, NULL);
        omap_dss_stop_device(dssdev);
 
        rfbi_runtime_put();
@@ -950,7 +952,7 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
 static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       const char *def_disp_name = dss_get_default_display_name();
+       const char *def_disp_name = omapdss_get_default_display_name();
        struct omap_dss_device *def_dssdev;
        int i;
 
@@ -999,9 +1001,18 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
                return;
        }
 
+       r = omapdss_output_set_device(&rfbi.output, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device: %s\n",
+                               dssdev->name);
+               dss_put_device(dssdev);
+               return;
+       }
+
        r = dss_add_device(dssdev);
        if (r) {
                DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               omapdss_output_unset_device(&rfbi.output);
                dss_put_device(dssdev);
                return;
        }
index 7760851f6e5d5ad5dc9adcc3b540ee4f2f5301d2..62b5374ce438f3ff7e4db23d4ad5c6d5165456cd 100644 (file)
@@ -205,7 +205,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
 static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       const char *def_disp_name = dss_get_default_display_name();
+       const char *def_disp_name = omapdss_get_default_display_name();
        struct omap_dss_device *def_dssdev;
        int i;
 
@@ -254,9 +254,18 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
                return;
        }
 
+       r = omapdss_output_set_device(&sdi.output, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device: %s\n",
+                               dssdev->name);
+               dss_put_device(dssdev);
+               return;
+       }
+
        r = dss_add_device(dssdev);
        if (r) {
                DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               omapdss_output_unset_device(&sdi.output);
                dss_put_device(dssdev);
                return;
        }
index b046c208cb9708fc30db861759c6a2cf01fde3be..216aa704f9d72ef08b06a82865d5b8fda03cc876 100644 (file)
@@ -102,6 +102,8 @@ struct ti_hdmi_ip_ops {
 
        int (*audio_config)(struct hdmi_ip_data *ip_data,
                struct omap_dss_audio *audio);
+
+       int (*audio_get_dma_port)(u32 *offset, u32 *size);
 #endif
 
 };
@@ -183,5 +185,6 @@ int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
 void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
 int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
                struct omap_dss_audio *audio);
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
 #endif
 #endif
index c23b85a20cdc5b84cd6aeec9743a4f931a9470a2..e18b222ed739081819c35ef6276e7b7094068fa4 100644 (file)
@@ -899,7 +899,7 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
 #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
                hdmi_read_reg(hdmi_av_base(ip_data), r))
 #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
-               (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
+               (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
                hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
 
        DUMPCORE(HDMI_CORE_SYS_VND_IDL);
@@ -1418,4 +1418,13 @@ void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
        REG_FLD_MOD(hdmi_wp_base(ip_data),
                    HDMI_WP_AUDIO_CTRL, false, 30, 30);
 }
+
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
+{
+       if (!offset || !size)
+               return -EINVAL;
+       *offset = HDMI_WP_AUDIO_DATA;
+       *size = 4;
+       return 0;
+}
 #endif
index 56efa3bb465d1ef4dd8011b89ead18ae36e41e03..006caf3cb509778d472d0a28d528cc3bde16748e 100644 (file)
@@ -744,7 +744,7 @@ static void venc_put_clocks(void)
 static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       const char *def_disp_name = dss_get_default_display_name();
+       const char *def_disp_name = omapdss_get_default_display_name();
        struct omap_dss_device *def_dssdev;
        int i;
 
@@ -795,9 +795,18 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
                return;
        }
 
+       r = omapdss_output_set_device(&venc.output, dssdev);
+       if (r) {
+               DSSERR("failed to connect output to new device: %s\n",
+                               dssdev->name);
+               dss_put_device(dssdev);
+               return;
+       }
+
        r = dss_add_device(dssdev);
        if (r) {
                DSSERR("device %s register failed: %d\n", dssdev->name, r);
+               omapdss_output_unset_device(&venc.output);
                dss_put_device(dssdev);
                return;
        }
index d55b8784ecfde6ddfa184a6d86f5a5d659f5b9c4..0d2b1a0834a0cb17dc4902db8c74273d319c6d5b 100644 (file)
@@ -157,12 +157,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
        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;
@@ -170,17 +164,6 @@ 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)
 {
@@ -222,8 +205,6 @@ static struct omap_dss_driver venc_driver = {
 
        .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,
index 4ea17dc3258c02d056fe838245c37f4cf8a9c9e1..4cb12ce68855ae998644a8454e8802494173659a 100644 (file)
@@ -2,7 +2,6 @@ menuconfig FB_OMAP2
         tristate "OMAP2+ frame buffer support"
         depends on FB && OMAP2_DSS && !DRM_OMAP
 
-       select OMAP2_VRAM
        select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
         select FB_CFB_FILLRECT
         select FB_CFB_COPYAREA
index 532a31b3d96be89286b4c22857486c3a298ff4da..d30b45d7264972590a4cf39a9131cc619eb9fbb2 100644 (file)
 #include <linux/omapfb.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
+#include <linux/sizes.h>
 
 #include <video/omapdss.h>
 #include <video/omapvrfb.h>
-#include <plat/vram.h>
 
 #include "omapfb.h"
 
@@ -211,6 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 {
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
+       struct omap_dss_device *display = fb2display(fbi);
        struct omapfb2_mem_region *rg;
        int r = 0, i;
        size_t size;
@@ -220,6 +221,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 
        size = PAGE_ALIGN(mi->size);
 
+       if (display && display->driver->sync)
+               display->driver->sync(display);
+
        rg = ofbi->region;
 
        down_write_nested(&rg->lock, rg->id);
@@ -279,7 +283,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
        return 0;
 }
 
-static int omapfb_update_window_nolock(struct fb_info *fbi,
+static int omapfb_update_window(struct fb_info *fbi,
                u32 x, u32 y, u32 w, u32 h)
 {
        struct omap_dss_device *display = fb2display(fbi);
@@ -299,27 +303,6 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
        return display->driver->update(display, x, y, w, h);
 }
 
-/* This function is exported for SGX driver use */
-int omapfb_update_window(struct fb_info *fbi,
-               u32 x, u32 y, u32 w, u32 h)
-{
-       struct omapfb_info *ofbi = FB2OFB(fbi);
-       struct omapfb2_device *fbdev = ofbi->fbdev;
-       int r;
-
-       if (!lock_fb_info(fbi))
-               return -ENODEV;
-       omapfb_lock(fbdev);
-
-       r = omapfb_update_window_nolock(fbi, x, y, w, h);
-
-       omapfb_unlock(fbdev);
-       unlock_fb_info(fbi);
-
-       return r;
-}
-EXPORT_SYMBOL(omapfb_update_window);
-
 int omapfb_set_update_mode(struct fb_info *fbi,
                                   enum omapfb_update_mode mode)
 {
@@ -646,7 +629,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        break;
                }
 
-               r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y,
+               r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
                                p.uwnd_o.width, p.uwnd_o.height);
                break;
 
@@ -663,7 +646,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        break;
                }
 
-               r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y,
+               r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
                                p.uwnd.width, p.uwnd.height);
                break;
 
@@ -853,14 +836,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                break;
 
        case OMAPFB_GET_VRAM_INFO: {
-               unsigned long vram, free, largest;
-
                DBG("ioctl GET_VRAM_INFO\n");
 
-               omap_vram_get_info(&vram, &free, &largest);
-               p.vram_info.total = vram;
-               p.vram_info.free = free;
-               p.vram_info.largest_free_block = largest;
+               /*
+                * We don't have the ability to get this vram info anymore.
+                * Fill in something that should keep the applications working.
+                */
+               p.vram_info.total = SZ_1M * 64;
+               p.vram_info.free = SZ_1M * 64;
+               p.vram_info.largest_free_block = SZ_1M * 64;
 
                if (copy_to_user((void __user *)arg, &p.vram_info,
                                        sizeof(p.vram_info)))
index bc225e46fdd2da8125bf48d1dfd7cf2cbda9625e..ca585ef37f2528d36d0534200a911db95b07baff 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/omapfb.h>
 
 #include <video/omapdss.h>
-#include <plat/vram.h>
 #include <video/omapvrfb.h>
 
 #include "omapfb.h"
@@ -1258,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 
        switch (blank) {
        case FB_BLANK_UNBLANK:
-               if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+               if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
                        goto exit;
 
-               if (display->driver->resume)
-                       r = display->driver->resume(display);
+               r = display->driver->enable(display);
 
                if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
                                d->update_mode == OMAPFB_AUTO_UPDATE &&
@@ -1283,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (d->auto_update_work_enabled)
                        omapfb_stop_auto_update(fbdev, display);
 
-               if (display->driver->suspend)
-                       r = display->driver->suspend(display);
+               display->driver->disable(display);
 
                break;
 
@@ -1335,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
 
        rg = ofbi->region;
 
-       WARN_ON(atomic_read(&rg->map_count));
-
-       if (rg->paddr)
-               if (omap_vram_free(rg->paddr, rg->size))
-                       dev_err(fbdev->dev, "VRAM FREE failed\n");
+       if (rg->token == NULL)
+               return;
 
-       if (rg->vaddr)
-               iounmap(rg->vaddr);
+       WARN_ON(atomic_read(&rg->map_count));
 
        if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
                /* unmap the 0 angle rotation */
                if (rg->vrfb.vaddr[0]) {
                        iounmap(rg->vrfb.vaddr[0]);
-                       omap_vrfb_release_ctx(&rg->vrfb);
                        rg->vrfb.vaddr[0] = NULL;
                }
+
+               omap_vrfb_release_ctx(&rg->vrfb);
        }
 
+       dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
+                       &rg->attrs);
+
+       rg->token = NULL;
        rg->vaddr = NULL;
        rg->paddr = 0;
        rg->alloc = 0;
@@ -1387,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
        struct omapfb2_mem_region *rg;
-       void __iomem *vaddr;
+       void *token;
+       DEFINE_DMA_ATTRS(attrs);
+       dma_addr_t dma_handle;
        int r;
 
        rg = ofbi->region;
@@ -1402,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 
        size = PAGE_ALIGN(size);
 
-       if (!paddr) {
-               DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
-               r = omap_vram_alloc(size, &paddr);
-       } else {
-               DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
-                               ofbi->id);
-               r = omap_vram_reserve(paddr, size);
-       }
+       dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
 
-       if (r) {
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+               dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+
+       DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+
+       token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
+                       GFP_KERNEL, &attrs);
+
+       if (token == NULL) {
                dev_err(fbdev->dev, "failed to allocate framebuffer\n");
                return -ENOMEM;
        }
 
-       if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
-               vaddr = ioremap_wc(paddr, size);
-
-               if (!vaddr) {
-                       dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
-                       omap_vram_free(paddr, size);
-                       return -ENOMEM;
-               }
+       DBG("allocated VRAM paddr %lx, vaddr %p\n",
+                       (unsigned long)dma_handle, token);
 
-               DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
-       } else {
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
                r = omap_vrfb_request_ctx(&rg->vrfb);
                if (r) {
+                       dma_free_attrs(fbdev->dev, size, token, dma_handle,
+                                       &attrs);
                        dev_err(fbdev->dev, "vrfb create ctx failed\n");
                        return r;
                }
-
-               vaddr = NULL;
        }
 
-       rg->paddr = paddr;
-       rg->vaddr = vaddr;
+       rg->attrs = attrs;
+       rg->token = token;
+       rg->dma_handle = dma_handle;
+
+       rg->paddr = (unsigned long)dma_handle;
+       rg->vaddr = (void __iomem *)token;
        rg->size = size;
        rg->alloc = 1;
 
@@ -1531,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
 
                }
 
+               WARN_ONCE(paddr,
+                       "reserving memory at predefined address not supported\n");
+
                paddrs[fbnum] = paddr;
                sizes[fbnum] = size;
 
@@ -1610,7 +1611,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
 {
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
-       struct omap_dss_device *display = fb2display(fbi);
        struct omapfb2_mem_region *rg = ofbi->region;
        unsigned long old_size = rg->size;
        unsigned long old_paddr = rg->paddr;
@@ -1625,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
        if (old_size == size && old_type == type)
                return 0;
 
-       if (display && display->driver->sync)
-                       display->driver->sync(display);
-
        omapfb_free_fbmem(fbi);
 
        if (size == 0) {
@@ -1882,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
        }
 
        dev_set_drvdata(fbdev->dev, NULL);
-       kfree(fbdev);
 }
 
 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
@@ -2258,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
 {
        struct fb_monspecs *specs;
        u8 *edid;
-       int r, i, best_xres, best_idx, len;
+       int r, i, best_idx, len;
 
        if (!display->driver->read_edid)
                return -ENODEV;
 
        len = 0x80 * 2;
        edid = kmalloc(len, GFP_KERNEL);
+       if (edid == NULL)
+               return -ENOMEM;
 
        r = display->driver->read_edid(display, edid, len);
        if (r < 0)
                goto err1;
 
        specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+       if (specs == NULL) {
+               r = -ENOMEM;
+               goto err1;
+       }
 
        fb_edid_to_monspecs(edid, specs);
 
-       if (edid[126] > 0)
-               fb_edid_add_monspecs(edid + 0x80, specs);
-
-       best_xres = 0;
        best_idx = -1;
 
        for (i = 0; i < specs->modedb_len; ++i) {
@@ -2293,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
                if (m->xres == 2880 || m->xres == 1440)
                        continue;
 
+               if (m->vmode & FB_VMODE_INTERLACED ||
+                               m->vmode & FB_VMODE_DOUBLE)
+                       continue;
+
                fb_videomode_to_omap_timings(m, display, &t);
 
                r = display->driver->check_timings(display, &t);
-               if (r == 0 && best_xres < m->xres) {
-                       best_xres = m->xres;
+               if (r == 0) {
                        best_idx = i;
+                       break;
                }
        }
 
-       if (best_xres == 0) {
+       if (best_idx == -1) {
                r = -ENOENT;
                goto err2;
        }
@@ -2371,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
        return 0;
 }
 
+static int omapfb_init_connections(struct omapfb2_device *fbdev,
+               struct omap_dss_device *def_dssdev)
+{
+       int i, r;
+       struct omap_overlay_manager *mgr;
+
+       if (!def_dssdev->output) {
+               dev_err(fbdev->dev, "no output for the default display\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < fbdev->num_displays; ++i) {
+               struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+               struct omap_dss_output *out = dssdev->output;
+
+               mgr = omap_dss_get_overlay_manager(dssdev->channel);
+
+               if (!mgr || !out)
+                       continue;
+
+               if (mgr->output)
+                       mgr->unset_output(mgr);
+
+               mgr->set_output(mgr, out);
+       }
+
+       mgr = def_dssdev->output->manager;
+
+       if (!mgr) {
+               dev_err(fbdev->dev, "no ovl manager for the default display\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < fbdev->num_overlays; i++) {
+               struct omap_overlay *ovl = fbdev->overlays[i];
+
+               if (ovl->manager)
+                       ovl->unset_manager(ovl);
+
+               r = ovl->set_manager(ovl, mgr);
+               if (r)
+                       dev_warn(fbdev->dev,
+                                       "failed to connect overlay %s to manager %s\n",
+                                       ovl->name, mgr->name);
+       }
+
+       return 0;
+}
+
 static int __init omapfb_probe(struct platform_device *pdev)
 {
        struct omapfb2_device *fbdev = NULL;
        int r = 0;
        int i;
-       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");
 
@@ -2389,7 +2438,8 @@ static int __init omapfb_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
+       fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
+                       GFP_KERNEL);
        if (fbdev == NULL) {
                r = -ENOMEM;
                goto err0;
@@ -2401,13 +2451,15 @@ static int __init omapfb_probe(struct platform_device *pdev)
                                "ignoring the module parameter vrfb=y\n");
        }
 
+       r = omapdss_compat_init();
+       if (r)
+               goto err0;
 
        mutex_init(&fbdev->mtx);
 
        fbdev->dev = &pdev->dev;
        platform_set_drvdata(pdev, fbdev);
 
-       r = 0;
        fbdev->num_displays = 0;
        dssdev = NULL;
        for_each_dss_dev(dssdev) {
@@ -2430,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
                        d->update_mode = OMAPFB_AUTO_UPDATE;
        }
 
-       if (r)
-               goto cleanup;
-
        if (fbdev->num_displays == 0) {
                dev_err(&pdev->dev, "no displays\n");
                r = -EINVAL;
@@ -2447,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev)
        for (i = 0; i < fbdev->num_managers; i++)
                fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
-       /* 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);
-       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;
+       def_display = NULL;
+
+       for (i = 0; i < fbdev->num_displays; ++i) {
+               struct omap_dss_device *dssdev;
+               const char *def_name;
+
+               def_name = omapdss_get_default_display_name();
+
+               dssdev = fbdev->displays[i].dssdev;
+
+               if (def_name == NULL ||
+                       (dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
+                       def_display = dssdev;
+                       break;
+               }
+       }
+
+       if (def_display == NULL) {
+               dev_err(fbdev->dev, "failed to find default display\n");
+               r = -EINVAL;
+               goto cleanup;
+       }
+
+       r = omapfb_init_connections(fbdev, def_display);
+       if (r) {
+               dev_err(fbdev->dev, "failed to init overlay connections\n");
+               goto cleanup;
        }
 
        if (def_mode && strlen(def_mode) > 0) {
@@ -2506,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
 
 cleanup:
        omapfb_free_resources(fbdev);
+       omapdss_compat_uninit();
 err0:
        dev_err(&pdev->dev, "failed to setup omapfb\n");
        return r;
@@ -2521,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
 
        omapfb_free_resources(fbdev);
 
+       omapdss_compat_uninit();
+
        return 0;
 }
 
index 17aa174e187c94cb617065ebeeccb2b45985ba94..18fa9e1d003319e62388aa12bac398f12e5927ec 100644 (file)
@@ -441,6 +441,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
+       struct omap_dss_device *display = fb2display(fbi);
        struct omapfb2_mem_region *rg;
        unsigned long size;
        int r;
@@ -455,6 +456,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
        if (!lock_fb_info(fbi))
                return -ENODEV;
 
+       if (display && display->driver->sync)
+               display->driver->sync(display);
+
        rg = ofbi->region;
 
        down_write_nested(&rg->lock, rg->id);
index 5ced9b334d35e5861f8fcf3dccee914862405120..623cd872a36788f3dc8cccd25fa53b475995cb3a 100644 (file)
@@ -28,6 +28,8 @@
 #endif
 
 #include <linux/rwsem.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-mapping.h>
 
 #include <video/omapdss.h>
 
@@ -49,6 +51,9 @@ extern bool omapfb_debug;
 
 struct omapfb2_mem_region {
        int             id;
+       struct dma_attrs attrs;
+       void            *token;
+       dma_addr_t      dma_handle;
        u32             paddr;
        void __iomem    *vaddr;
        struct vrfb     vrfb;
@@ -124,9 +129,6 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
 
 int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
 
-int omapfb_update_window(struct fb_info *fbi,
-               u32 x, u32 y, u32 w, u32 h);
-
 int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
                        struct fb_var_screeninfo *var);
 
@@ -144,16 +146,16 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
 static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 {
        struct omapfb_info *ofbi = FB2OFB(fbi);
-       int i;
+       struct omap_overlay *ovl;
 
        /* XXX: returns the display connected to first attached overlay */
-       for (i = 0; i < ofbi->num_overlays; i++) {
-               struct omap_overlay *ovl = ofbi->overlays[i];
 
-               return ovl->get_device(ovl);
-       }
+       if (ofbi->num_overlays == 0)
+               return NULL;
 
-       return NULL;
+       ovl = ofbi->overlays[0];
+
+       return ovl->get_device(ovl);
 }
 
 static inline struct omapfb_display_data *get_display_data(
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
deleted file mode 100644 (file)
index f2b15c4..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*#define DEBUG*/
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/memblock.h>
-#include <linux/completion.h>
-#include <linux/debugfs.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-
-#include <asm/setup.h>
-
-#include <plat/vram.h>
-
-#ifdef DEBUG
-#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-/* postponed regions are used to temporarily store region information at boot
- * time when we cannot yet allocate the region list */
-#define MAX_POSTPONED_REGIONS 10
-
-static bool vram_initialized;
-static int postponed_cnt;
-static struct {
-       unsigned long paddr;
-       size_t size;
-} postponed_regions[MAX_POSTPONED_REGIONS];
-
-struct vram_alloc {
-       struct list_head list;
-       unsigned long paddr;
-       unsigned pages;
-};
-
-struct vram_region {
-       struct list_head list;
-       struct list_head alloc_list;
-       unsigned long paddr;
-       unsigned pages;
-};
-
-static DEFINE_MUTEX(region_mutex);
-static LIST_HEAD(region_list);
-
-static struct vram_region *omap_vram_create_region(unsigned long paddr,
-               unsigned pages)
-{
-       struct vram_region *rm;
-
-       rm = kzalloc(sizeof(*rm), GFP_KERNEL);
-
-       if (rm) {
-               INIT_LIST_HEAD(&rm->alloc_list);
-               rm->paddr = paddr;
-               rm->pages = pages;
-       }
-
-       return rm;
-}
-
-#if 0
-static void omap_vram_free_region(struct vram_region *vr)
-{
-       list_del(&vr->list);
-       kfree(vr);
-}
-#endif
-
-static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
-               unsigned long paddr, unsigned pages)
-{
-       struct vram_alloc *va;
-       struct vram_alloc *new;
-
-       new = kzalloc(sizeof(*va), GFP_KERNEL);
-
-       if (!new)
-               return NULL;
-
-       new->paddr = paddr;
-       new->pages = pages;
-
-       list_for_each_entry(va, &vr->alloc_list, list) {
-               if (va->paddr > new->paddr)
-                       break;
-       }
-
-       list_add_tail(&new->list, &va->list);
-
-       return new;
-}
-
-static void omap_vram_free_allocation(struct vram_alloc *va)
-{
-       list_del(&va->list);
-       kfree(va);
-}
-
-int omap_vram_add_region(unsigned long paddr, size_t size)
-{
-       struct vram_region *rm;
-       unsigned pages;
-
-       if (vram_initialized) {
-               DBG("adding region paddr %08lx size %d\n",
-                               paddr, size);
-
-               size &= PAGE_MASK;
-               pages = size >> PAGE_SHIFT;
-
-               rm = omap_vram_create_region(paddr, pages);
-               if (rm == NULL)
-                       return -ENOMEM;
-
-               list_add(&rm->list, &region_list);
-       } else {
-               if (postponed_cnt == MAX_POSTPONED_REGIONS)
-                       return -ENOMEM;
-
-               postponed_regions[postponed_cnt].paddr = paddr;
-               postponed_regions[postponed_cnt].size = size;
-
-               ++postponed_cnt;
-       }
-       return 0;
-}
-
-int omap_vram_free(unsigned long paddr, size_t size)
-{
-       struct vram_region *rm;
-       struct vram_alloc *alloc;
-       unsigned start, end;
-
-       DBG("free mem paddr %08lx size %d\n", paddr, size);
-
-       size = PAGE_ALIGN(size);
-
-       mutex_lock(&region_mutex);
-
-       list_for_each_entry(rm, &region_list, list) {
-               list_for_each_entry(alloc, &rm->alloc_list, list) {
-                       start = alloc->paddr;
-                       end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
-
-                       if (start >= paddr && end < paddr + size)
-                               goto found;
-               }
-       }
-
-       mutex_unlock(&region_mutex);
-       return -EINVAL;
-
-found:
-       omap_vram_free_allocation(alloc);
-
-       mutex_unlock(&region_mutex);
-       return 0;
-}
-EXPORT_SYMBOL(omap_vram_free);
-
-static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
-{
-       struct vram_region *rm;
-       struct vram_alloc *alloc;
-       size_t size;
-
-       size = pages << PAGE_SHIFT;
-
-       list_for_each_entry(rm, &region_list, list) {
-               unsigned long start, end;
-
-               DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
-               start = rm->paddr;
-               end = start + (rm->pages << PAGE_SHIFT) - 1;
-               if (start > paddr || end < paddr + size - 1)
-                       continue;
-
-               DBG("block ok, checking allocs\n");
-
-               list_for_each_entry(alloc, &rm->alloc_list, list) {
-                       end = alloc->paddr - 1;
-
-                       if (start <= paddr && end >= paddr + size - 1)
-                               goto found;
-
-                       start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
-               }
-
-               end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
-
-               if (!(start <= paddr && end >= paddr + size - 1))
-                       continue;
-found:
-               DBG("found area start %lx, end %lx\n", start, end);
-
-               if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
-                       return -ENOMEM;
-
-               return 0;
-       }
-
-       return -ENOMEM;
-}
-
-int omap_vram_reserve(unsigned long paddr, size_t size)
-{
-       unsigned pages;
-       int r;
-
-       DBG("reserve mem paddr %08lx size %d\n", paddr, size);
-
-       size = PAGE_ALIGN(size);
-       pages = size >> PAGE_SHIFT;
-
-       mutex_lock(&region_mutex);
-
-       r = _omap_vram_reserve(paddr, pages);
-
-       mutex_unlock(&region_mutex);
-
-       return r;
-}
-EXPORT_SYMBOL(omap_vram_reserve);
-
-static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
-{
-       struct vram_region *rm;
-       struct vram_alloc *alloc;
-
-       list_for_each_entry(rm, &region_list, list) {
-               unsigned long start, end;
-
-               DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
-               start = rm->paddr;
-
-               list_for_each_entry(alloc, &rm->alloc_list, list) {
-                       end = alloc->paddr;
-
-                       if (end - start >= pages << PAGE_SHIFT)
-                               goto found;
-
-                       start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
-               }
-
-               end = rm->paddr + (rm->pages << PAGE_SHIFT);
-found:
-               if (end - start < pages << PAGE_SHIFT)
-                       continue;
-
-               DBG("found %lx, end %lx\n", start, end);
-
-               alloc = omap_vram_create_allocation(rm, start, pages);
-               if (alloc == NULL)
-                       return -ENOMEM;
-
-               *paddr = start;
-
-               return 0;
-       }
-
-       return -ENOMEM;
-}
-
-int omap_vram_alloc(size_t size, unsigned long *paddr)
-{
-       unsigned pages;
-       int r;
-
-       BUG_ON(!size);
-
-       DBG("alloc mem size %d\n", size);
-
-       size = PAGE_ALIGN(size);
-       pages = size >> PAGE_SHIFT;
-
-       mutex_lock(&region_mutex);
-
-       r = _omap_vram_alloc(pages, paddr);
-
-       mutex_unlock(&region_mutex);
-
-       return r;
-}
-EXPORT_SYMBOL(omap_vram_alloc);
-
-void omap_vram_get_info(unsigned long *vram,
-               unsigned long *free_vram,
-               unsigned long *largest_free_block)
-{
-       struct vram_region *vr;
-       struct vram_alloc *va;
-
-       *vram = 0;
-       *free_vram = 0;
-       *largest_free_block = 0;
-
-       mutex_lock(&region_mutex);
-
-       list_for_each_entry(vr, &region_list, list) {
-               unsigned free;
-               unsigned long pa;
-
-               pa = vr->paddr;
-               *vram += vr->pages << PAGE_SHIFT;
-
-               list_for_each_entry(va, &vr->alloc_list, list) {
-                       free = va->paddr - pa;
-                       *free_vram += free;
-                       if (free > *largest_free_block)
-                               *largest_free_block = free;
-                       pa = va->paddr + (va->pages << PAGE_SHIFT);
-               }
-
-               free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
-               *free_vram += free;
-               if (free > *largest_free_block)
-                       *largest_free_block = free;
-       }
-
-       mutex_unlock(&region_mutex);
-}
-EXPORT_SYMBOL(omap_vram_get_info);
-
-#if defined(CONFIG_DEBUG_FS)
-static int vram_debug_show(struct seq_file *s, void *unused)
-{
-       struct vram_region *vr;
-       struct vram_alloc *va;
-       unsigned size;
-
-       mutex_lock(&region_mutex);
-
-       list_for_each_entry(vr, &region_list, list) {
-               size = vr->pages << PAGE_SHIFT;
-               seq_printf(s, "%08lx-%08lx (%d bytes)\n",
-                               vr->paddr, vr->paddr + size - 1,
-                               size);
-
-               list_for_each_entry(va, &vr->alloc_list, list) {
-                       size = va->pages << PAGE_SHIFT;
-                       seq_printf(s, "    %08lx-%08lx (%d bytes)\n",
-                                       va->paddr, va->paddr + size - 1,
-                                       size);
-               }
-       }
-
-       mutex_unlock(&region_mutex);
-
-       return 0;
-}
-
-static int vram_debug_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, vram_debug_show, inode->i_private);
-}
-
-static const struct file_operations vram_debug_fops = {
-       .open           = vram_debug_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init omap_vram_create_debugfs(void)
-{
-       struct dentry *d;
-
-       d = debugfs_create_file("vram", S_IRUGO, NULL,
-                       NULL, &vram_debug_fops);
-       if (IS_ERR(d))
-               return PTR_ERR(d);
-
-       return 0;
-}
-#endif
-
-static __init int omap_vram_init(void)
-{
-       int i;
-
-       vram_initialized = 1;
-
-       for (i = 0; i < postponed_cnt; i++)
-               omap_vram_add_region(postponed_regions[i].paddr,
-                               postponed_regions[i].size);
-
-#ifdef CONFIG_DEBUG_FS
-       if (omap_vram_create_debugfs())
-               pr_err("VRAM: Failed to create debugfs file\n");
-#endif
-
-       return 0;
-}
-
-arch_initcall(omap_vram_init);
-
-/* boottime vram alloc stuff */
-
-/* set from board file */
-static u32 omap_vram_sdram_start __initdata;
-static u32 omap_vram_sdram_size __initdata;
-
-/* set from kernel cmdline */
-static u32 omap_vram_def_sdram_size __initdata;
-static u32 omap_vram_def_sdram_start __initdata;
-
-static int __init omap_vram_early_vram(char *p)
-{
-       omap_vram_def_sdram_size = memparse(p, &p);
-       if (*p == ',')
-               omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
-       return 0;
-}
-early_param("vram", omap_vram_early_vram);
-
-/*
- * Called from map_io. We need to call to this early enough so that we
- * can reserve the fixed SDRAM regions before VM could get hold of them.
- */
-void __init omap_vram_reserve_sdram_memblock(void)
-{
-       u32 paddr;
-       u32 size = 0;
-
-       /* cmdline arg overrides the board file definition */
-       if (omap_vram_def_sdram_size) {
-               size = omap_vram_def_sdram_size;
-               paddr = omap_vram_def_sdram_start;
-       }
-
-       if (!size) {
-               size = omap_vram_sdram_size;
-               paddr = omap_vram_sdram_start;
-       }
-
-#ifdef CONFIG_OMAP2_VRAM_SIZE
-       if (!size) {
-               size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
-               paddr = 0;
-       }
-#endif
-
-       if (!size)
-               return;
-
-       size = ALIGN(size, SZ_2M);
-
-       if (paddr) {
-               if (paddr & ~PAGE_MASK) {
-                       pr_err("VRAM start address 0x%08x not page aligned\n",
-                                       paddr);
-                       return;
-               }
-
-               if (!memblock_is_region_memory(paddr, size)) {
-                       pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
-                                       paddr, paddr + size - 1);
-                       return;
-               }
-
-               if (memblock_is_region_reserved(paddr, size)) {
-                       pr_err("FB: failed to reserve VRAM - busy\n");
-                       return;
-               }
-
-               if (memblock_reserve(paddr, size) < 0) {
-                       pr_err("FB: failed to reserve VRAM - no memory\n");
-                       return;
-               }
-       } else {
-               paddr = memblock_alloc(size, SZ_2M);
-       }
-
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
-
-       omap_vram_add_region(paddr, size);
-
-       pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
-}
-
-void __init omap_vram_set_sdram_vram(u32 size, u32 start)
-{
-       omap_vram_sdram_start = start;
-       omap_vram_sdram_size = size;
-}
index 2ed7b633bbd9656352d10e5201efc462c065f991..1a00ad241edd3dcd10ac83e22d03a50c079920c6 100644 (file)
@@ -189,7 +189,7 @@ struct s3c_fb_vsync {
 
 /**
  * struct s3c_fb - overall hardware state of the hardware
- * @slock: The spinlock protection for this data sturucture.
+ * @slock: The spinlock protection for this data structure.
  * @dev: The device that we bound to, for printing, etc.
  * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
  * @lcd_clk: The clk (sclk) feeding pixclk.
@@ -268,10 +268,10 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
        case 8:
                if (sfb->variant.palette[win->index] != 0) {
                        /* non palletised, A:1,R:2,G:3,B:2 mode */
-                       var->red.offset         = 4;
+                       var->red.offset         = 5;
                        var->green.offset       = 2;
                        var->blue.offset        = 0;
-                       var->red.length         = 5;
+                       var->red.length         = 2;
                        var->green.length       = 3;
                        var->blue.length        = 2;
                        var->transp.offset      = 7;
@@ -288,6 +288,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
                /* 666 with one bit alpha/transparency */
                var->transp.offset      = 18;
                var->transp.length      = 1;
+               /* drop through */
        case 18:
                var->bits_per_pixel     = 32;
 
@@ -329,6 +330,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
 
        default:
                dev_err(sfb->dev, "invalid bpp\n");
+               return -EINVAL;
        }
 
        dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
@@ -1544,8 +1546,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int s3c_fb_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct s3c_fb *sfb = platform_get_drvdata(pdev);
+       struct s3c_fb *sfb = dev_get_drvdata(dev);
        struct s3c_fb_win *win;
        int win_no;
 
@@ -1572,8 +1573,7 @@ static int s3c_fb_suspend(struct device *dev)
 
 static int s3c_fb_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct s3c_fb *sfb = platform_get_drvdata(pdev);
+       struct s3c_fb *sfb = dev_get_drvdata(dev);
        struct s3c_fb_platdata *pd = sfb->pdata;
        struct s3c_fb_win *win;
        int win_no;
@@ -1623,7 +1623,7 @@ static int s3c_fb_resume(struct device *dev)
                if (!win)
                        continue;
 
-               dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
+               dev_dbg(dev, "resuming window %d\n", win_no);
                s3c_fb_set_par(win->fbinfo);
        }
 
@@ -1636,8 +1636,7 @@ static int s3c_fb_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int s3c_fb_runtime_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct s3c_fb *sfb = platform_get_drvdata(pdev);
+       struct s3c_fb *sfb = dev_get_drvdata(dev);
 
        if (!sfb->variant.has_clksel)
                clk_disable_unprepare(sfb->lcd_clk);
@@ -1649,8 +1648,7 @@ static int s3c_fb_runtime_suspend(struct device *dev)
 
 static int s3c_fb_runtime_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct s3c_fb *sfb = platform_get_drvdata(pdev);
+       struct s3c_fb *sfb = dev_get_drvdata(dev);
        struct s3c_fb_platdata *pd = sfb->pdata;
 
        clk_prepare_enable(sfb->bus_clk);
@@ -1910,7 +1908,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
 static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
        .variant = {
                .nr_windows     = 5,
-               .vidtcon        = VIDTCON0,
+               .vidtcon        = FIMD_V8_VIDTCON0,
                .wincon         = WINCON(0),
                .winmap         = WINxMAP(0),
                .keycon         = WKEYCON,
index 3951fdae5f6847694f97627638f6d64857554247..f4962292792c6fd305af02d70709c5b43e203027 100644 (file)
@@ -127,13 +127,12 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
        sh_mipi_dsi_enable(mipi, false);
 }
 
-static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
+static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode)
 {
        void __iomem *base = mipi->base;
-       struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
+       struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
        u32 pctype, datatype, pixfmt, linelength, vmctr2;
        u32 tmp, top, bottom, delay, div;
-       bool yuv;
        int bpp;
 
        /*
@@ -146,95 +145,79 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
                pctype = 0;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-               linelength = ch->lcd_modes[0].xres * 3;
-               yuv = false;
+               linelength = mode->xres * 3;
                break;
        case MIPI_RGB565:
                pctype = 1;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-               linelength = ch->lcd_modes[0].xres * 2;
-               yuv = false;
+               linelength = mode->xres * 2;
                break;
        case MIPI_RGB666_LP:
                pctype = 2;
                datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-               linelength = ch->lcd_modes[0].xres * 3;
-               yuv = false;
+               linelength = mode->xres * 3;
                break;
        case MIPI_RGB666:
                pctype = 3;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
                pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
-               linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
-               yuv = false;
+               linelength = (mode->xres * 18 + 7) / 8;
                break;
        case MIPI_BGR888:
                pctype = 8;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-               linelength = ch->lcd_modes[0].xres * 3;
-               yuv = false;
+               linelength = mode->xres * 3;
                break;
        case MIPI_BGR565:
                pctype = 9;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-               linelength = ch->lcd_modes[0].xres * 2;
-               yuv = false;
+               linelength = mode->xres * 2;
                break;
        case MIPI_BGR666_LP:
                pctype = 0xa;
                datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-               linelength = ch->lcd_modes[0].xres * 3;
-               yuv = false;
+               linelength = mode->xres * 3;
                break;
        case MIPI_BGR666:
                pctype = 0xb;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
                pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
-               linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
-               yuv = false;
+               linelength = (mode->xres * 18 + 7) / 8;
                break;
        case MIPI_YUYV:
                pctype = 4;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-               linelength = ch->lcd_modes[0].xres * 2;
-               yuv = true;
+               linelength = mode->xres * 2;
                break;
        case MIPI_UYVY:
                pctype = 5;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-               linelength = ch->lcd_modes[0].xres * 2;
-               yuv = true;
+               linelength = mode->xres * 2;
                break;
        case MIPI_YUV420_L:
                pctype = 6;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
                pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
-               linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
-               yuv = true;
+               linelength = (mode->xres * 12 + 7) / 8;
                break;
        case MIPI_YUV420:
                pctype = 7;
                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
                pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
                /* Length of U/V line */
-               linelength = (ch->lcd_modes[0].xres + 1) / 2;
-               yuv = true;
+               linelength = (mode->xres + 1) / 2;
                break;
        default:
                return -EINVAL;
        }
 
-       if ((yuv && ch->interface_type != YUV422) ||
-           (!yuv && ch->interface_type != RGB24))
-               return -EINVAL;
-
        if (!pdata->lane)
                return -EINVAL;
 
@@ -293,7 +276,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
         */
        iowrite32(0x00000006, mipi->linkbase + DTCTR);
        /* VSYNC width = 2 (<< 17) */
-       iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
+       iowrite32((mode->vsync_len << pdata->vsynw_offset) |
                  (pdata->clksrc << 16) | (pctype << 12) | datatype,
                  mipi->linkbase + VMCTR1);
 
@@ -327,7 +310,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
        top = linelength << 16; /* RGBLEN */
        bottom = 0x00000001;
        if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
-               bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
+               bottom = (pdata->lane * mode->hsync_len) - 10;
        iowrite32(top | bottom , mipi->linkbase + VMLEN1);
 
        /*
@@ -347,18 +330,18 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
                div = 2;
 
        if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
-               top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
+               top = mode->hsync_len + mode->left_margin;
                top = ((pdata->lane * top / div) - 10) << 16;
        }
        if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
-               bottom = ch->lcd_modes[0].right_margin;
+               bottom = mode->right_margin;
                bottom = (pdata->lane * bottom / div) - 12;
        }
 
-       bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
+       bpp = linelength / mode->xres; /* byte / pixel */
        if ((pdata->lane / div) > bpp) {
-               tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
-               tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
+               tmp = mode->xres / bpp; /* output cycle */
+               tmp = mode->xres - tmp; /* (input - output) cycle */
                delay = (pdata->lane * tmp);
        }
 
@@ -369,7 +352,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
        /* setup LCD panel */
 
        /* cf. drivers/video/omap/lcd_mipid.c */
-       sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
+       sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE);
        msleep(120);
        /*
         * [7] - Page Address Mode
@@ -381,11 +364,11 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
         * [1] - Flip Horizontal
         * [0] - Flip Vertical
         */
-       sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+       sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
        /* cf. set_data_lines() */
-       sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
+       sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT,
                          pixfmt << 4);
-       sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
+       sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON);
 
        /* Enable timeout counters */
        iowrite32(0x00000f00, base + DSICTRL);
@@ -405,7 +388,7 @@ static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
        if (ret < 0)
                goto mipi_display_on_fail1;
 
-       ret = sh_mipi_setup(mipi, pdata);
+       ret = sh_mipi_setup(mipi, &entity->def_mode);
        if (ret < 0)
                goto mipi_display_on_fail2;
 
index 699487c287b2b201a0d2d263aeadbcfa250a0f92..e78fe4bc15249c21612020b858273b0c8884f3da 100644 (file)
@@ -438,7 +438,7 @@ static unsigned long lcdc_sys_read_data(void *handle)
        return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
 }
 
-struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
        lcdc_sys_write_index,
        lcdc_sys_write_data,
        lcdc_sys_read_data,
@@ -586,8 +586,8 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
                                 * Just turn on, if we run a resume here, the
                                 * logo disappears.
                                 */
-                               info->var.width = monspec->max_x * 10;
-                               info->var.height = monspec->max_y * 10;
+                               info->var.width = ch->display.width;
+                               info->var.height = ch->display.height;
                                sh_mobile_lcdc_display_on(ch);
                        } else {
                                /* New monitor or have to wake up */
@@ -1614,6 +1614,15 @@ static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
        return 1;
 }
 
+static int
+sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+       return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
+                                ovl->dma_handle, ovl->fb_size);
+}
+
 static struct fb_ops sh_mobile_lcdc_overlay_ops = {
        .owner          = THIS_MODULE,
        .fb_read        = fb_sys_read,
@@ -1626,6 +1635,7 @@ static struct fb_ops sh_mobile_lcdc_overlay_ops = {
        .fb_ioctl       = sh_mobile_lcdc_overlay_ioctl,
        .fb_check_var   = sh_mobile_lcdc_overlay_check_var,
        .fb_set_par     = sh_mobile_lcdc_overlay_set_par,
+       .fb_mmap        = sh_mobile_lcdc_overlay_mmap,
 };
 
 static void
@@ -2093,6 +2103,15 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
        return 0;
 }
 
+static int
+sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       struct sh_mobile_lcdc_chan *ch = info->par;
+
+       return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
+                                ch->dma_handle, ch->fb_size);
+}
+
 static struct fb_ops sh_mobile_lcdc_ops = {
        .owner          = THIS_MODULE,
        .fb_setcolreg   = sh_mobile_lcdc_setcolreg,
@@ -2108,6 +2127,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
        .fb_release     = sh_mobile_lcdc_release,
        .fb_check_var   = sh_mobile_lcdc_check_var,
        .fb_set_par     = sh_mobile_lcdc_set_par,
+       .fb_mmap        = sh_mobile_lcdc_mmap,
 };
 
 static void
@@ -2167,7 +2187,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
 
 static int __devinit
 sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
-                              const struct fb_videomode *mode,
+                              const struct fb_videomode *modes,
                               unsigned int num_modes)
 {
        struct sh_mobile_lcdc_priv *priv = ch->lcdc;
@@ -2193,7 +2213,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
        info->pseudo_palette = &ch->pseudo_palette;
        info->par = ch;
 
-       fb_videomode_to_modelist(mode, num_modes, &info->modelist);
+       fb_videomode_to_modelist(modes, num_modes, &info->modelist);
 
        ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
        if (ret < 0) {
@@ -2227,9 +2247,9 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
         * default.
         */
        var = &info->var;
-       fb_videomode_to_var(var, mode);
-       var->width = ch->cfg->panel_cfg.width;
-       var->height = ch->cfg->panel_cfg.height;
+       fb_videomode_to_var(var, modes);
+       var->width = ch->display.width;
+       var->height = ch->display.height;
        var->xres_virtual = ch->xres_virtual;
        var->yres_virtual = ch->yres_virtual;
        var->activate = FB_ACTIVATE_NOW;
@@ -2262,6 +2282,7 @@ static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
            bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
                brightness = 0;
 
+       ch->bl_brightness = brightness;
        return ch->cfg->bl_info.set_brightness(brightness);
 }
 
@@ -2269,7 +2290,7 @@ static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
 {
        struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
 
-       return ch->cfg->bl_info.get_brightness();
+       return ch->bl_brightness;
 }
 
 static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
@@ -2516,10 +2537,10 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
 }
 
 static int __devinit
-sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
-                         struct sh_mobile_lcdc_overlay *ovl)
+sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
 {
        const struct sh_mobile_lcdc_format_info *format;
+       struct device *dev = ovl->channel->lcdc->dev;
        int ret;
 
        if (ovl->cfg->fourcc == 0)
@@ -2528,7 +2549,7 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
        /* Validate the format. */
        format = sh_mobile_format_info(ovl->cfg->fourcc);
        if (format == NULL) {
-               dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
+               dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
                return -EINVAL;
        }
 
@@ -2556,10 +2577,10 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
        /* Allocate frame buffer memory. */
        ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
                       * format->bpp / 8 * 2;
-       ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size,
-                                          &ovl->dma_handle, GFP_KERNEL);
+       ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
+                                        GFP_KERNEL);
        if (!ovl->fb_mem) {
-               dev_err(priv->dev, "unable to allocate buffer\n");
+               dev_err(dev, "unable to allocate buffer\n");
                return -ENOMEM;
        }
 
@@ -2571,11 +2592,11 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
 }
 
 static int __devinit
-sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
-                           struct sh_mobile_lcdc_chan *ch)
+sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
 {
        const struct sh_mobile_lcdc_format_info *format;
        const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
+       struct device *dev = ch->lcdc->dev;
        const struct fb_videomode *max_mode;
        const struct fb_videomode *mode;
        unsigned int num_modes;
@@ -2588,7 +2609,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
        /* Validate the format. */
        format = sh_mobile_format_info(cfg->fourcc);
        if (format == NULL) {
-               dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
+               dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
                return -EINVAL;
        }
 
@@ -2604,7 +2625,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
                /* NV12/NV21 buffers must have even number of lines */
                if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
                     cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
-                       dev_err(priv->dev, "yres must be multiple of 2 for "
+                       dev_err(dev, "yres must be multiple of 2 for "
                                "YCbCr420 mode.\n");
                        return -EINVAL;
                }
@@ -2618,7 +2639,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
        if (!max_size)
                max_size = MAX_XRES * MAX_YRES;
        else
-               dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
+               dev_dbg(dev, "Found largest videomode %ux%u\n",
                        max_mode->xres, max_mode->yres);
 
        if (cfg->lcd_modes == NULL) {
@@ -2652,10 +2673,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 
        /* Allocate frame buffer memory. */
        ch->fb_size = max_size * format->bpp / 8 * 2;
-       ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle,
+       ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
                                        GFP_KERNEL);
        if (ch->fb_mem == NULL) {
-               dev_err(priv->dev, "unable to allocate buffer\n");
+               dev_err(dev, "unable to allocate buffer\n");
                return -ENOMEM;
        }
 
@@ -2663,8 +2684,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
        if (cfg->tx_dev) {
                if (!cfg->tx_dev->dev.driver ||
                    !try_module_get(cfg->tx_dev->dev.driver->owner)) {
-                       dev_warn(priv->dev,
-                                "unable to get transmitter device\n");
+                       dev_warn(dev, "unable to get transmitter device\n");
                        return -EINVAL;
                }
                ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
@@ -2772,9 +2792,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
 
        for (i = 0; i < num_channels; i++) {
-               struct sh_mobile_lcdc_chan *ch = priv->ch + i;
+               struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
 
-               error = sh_mobile_lcdc_channel_init(priv, ch);
+               error = sh_mobile_lcdc_channel_init(ch);
                if (error)
                        goto err1;
        }
@@ -2785,7 +2805,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
                ovl->cfg = &pdata->overlays[i];
                ovl->channel = &priv->ch[0];
 
-               error = sh_mobile_lcdc_overlay_init(priv, ovl);
+               error = sh_mobile_lcdc_overlay_init(ovl);
                if (error)
                        goto err1;
        }
index 0f92f6544b94907a7a51b503101c07a705421aed..f839adef1d90a58128a922b78bf28a21bd6d047b 100644 (file)
@@ -94,6 +94,7 @@ struct sh_mobile_lcdc_chan {
 
        /* Backlight */
        struct backlight_device *bl;
+       unsigned int bl_brightness;
 
        /* FB */
        struct fb_info *info;
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
new file mode 100644 (file)
index 0000000..6101f5c
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * Driver for the Solomon SSD1307 OLED controler
+ *
+ * Copyright 2012 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#define SSD1307FB_WIDTH                        96
+#define SSD1307FB_HEIGHT               16
+
+#define SSD1307FB_DATA                 0x40
+#define SSD1307FB_COMMAND              0x80
+
+#define SSD1307FB_CONTRAST             0x81
+#define SSD1307FB_SEG_REMAP_ON         0xa1
+#define SSD1307FB_DISPLAY_OFF          0xae
+#define SSD1307FB_DISPLAY_ON           0xaf
+#define SSD1307FB_START_PAGE_ADDRESS   0xb0
+
+struct ssd1307fb_par {
+       struct i2c_client *client;
+       struct fb_info *info;
+       struct pwm_device *pwm;
+       u32 pwm_period;
+       int reset;
+};
+
+static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
+       .id             = "Solomon SSD1307",
+       .type           = FB_TYPE_PACKED_PIXELS,
+       .visual         = FB_VISUAL_MONO10,
+       .xpanstep       = 0,
+       .ypanstep       = 0,
+       .ywrapstep      = 0,
+       .line_length    = SSD1307FB_WIDTH / 8,
+       .accel          = FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
+       .xres           = SSD1307FB_WIDTH,
+       .yres           = SSD1307FB_HEIGHT,
+       .xres_virtual   = SSD1307FB_WIDTH,
+       .yres_virtual   = SSD1307FB_HEIGHT,
+       .bits_per_pixel = 1,
+};
+
+static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len)
+{
+       u8 *buf;
+       int ret = 0;
+
+       buf = kzalloc(len + 1, GFP_KERNEL);
+       if (!buf) {
+               dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
+               return -ENOMEM;
+       }
+
+       buf[0] = type;
+       memcpy(buf + 1, cmd, len);
+
+       ret = i2c_master_send(client, buf, len + 1);
+       if (ret != len + 1) {
+               dev_err(&client->dev, "Couldn't send I2C command.\n");
+               goto error;
+       }
+
+error:
+       kfree(buf);
+       return ret;
+}
+
+static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+       return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
+}
+
+static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
+{
+       return ssd1307fb_write_cmd_array(client, &cmd, 1);
+}
+
+static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+       return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
+}
+
+static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+{
+       return ssd1307fb_write_data_array(client, &data, 1);
+}
+
+static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+{
+       u8 *vmem = par->info->screen_base;
+       int i, j, k;
+
+       /*
+        * The screen is divided in pages, each having a height of 8
+        * pixels, and the width of the screen. When sending a byte of
+        * data to the controller, it gives the 8 bits for the current
+        * column. I.e, the first byte are the 8 bits of the first
+        * column, then the 8 bits for the second column, etc.
+        *
+        *
+        * Representation of the screen, assuming it is 5 bits
+        * wide. Each letter-number combination is a bit that controls
+        * one pixel.
+        *
+        * A0 A1 A2 A3 A4
+        * B0 B1 B2 B3 B4
+        * C0 C1 C2 C3 C4
+        * D0 D1 D2 D3 D4
+        * E0 E1 E2 E3 E4
+        * F0 F1 F2 F3 F4
+        * G0 G1 G2 G3 G4
+        * H0 H1 H2 H3 H4
+        *
+        * If you want to update this screen, you need to send 5 bytes:
+        *  (1) A0 B0 C0 D0 E0 F0 G0 H0
+        *  (2) A1 B1 C1 D1 E1 F1 G1 H1
+        *  (3) A2 B2 C2 D2 E2 F2 G2 H2
+        *  (4) A3 B3 C3 D3 E3 F3 G3 H3
+        *  (5) A4 B4 C4 D4 E4 F4 G4 H4
+        */
+
+       for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
+               ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
+               ssd1307fb_write_cmd(par->client, 0x00);
+               ssd1307fb_write_cmd(par->client, 0x10);
+
+               for (j = 0; j < SSD1307FB_WIDTH; j++) {
+                       u8 buf = 0;
+                       for (k = 0; k < 8; k++) {
+                               u32 page_length = SSD1307FB_WIDTH * i;
+                               u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
+                               u8 byte = *(vmem + index);
+                               u8 bit = byte & (1 << (7 - (j % 8)));
+                               bit = bit >> (7 - (j % 8));
+                               buf |= bit << k;
+                       }
+                       ssd1307fb_write_data(par->client, buf);
+               }
+       }
+}
+
+
+static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
+               size_t count, loff_t *ppos)
+{
+       struct ssd1307fb_par *par = info->par;
+       unsigned long total_size;
+       unsigned long p = *ppos;
+       u8 __iomem *dst;
+
+       total_size = info->fix.smem_len;
+
+       if (p > total_size)
+               return -EINVAL;
+
+       if (count + p > total_size)
+               count = total_size - p;
+
+       if (!count)
+               return -EINVAL;
+
+       dst = (void __force *) (info->screen_base + p);
+
+       if (copy_from_user(dst, buf, count))
+               return -EFAULT;
+
+       ssd1307fb_update_display(par);
+
+       *ppos += count;
+
+       return count;
+}
+
+static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       struct ssd1307fb_par *par = info->par;
+       sys_fillrect(info, rect);
+       ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+       struct ssd1307fb_par *par = info->par;
+       sys_copyarea(info, area);
+       ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct ssd1307fb_par *par = info->par;
+       sys_imageblit(info, image);
+       ssd1307fb_update_display(par);
+}
+
+static struct fb_ops ssd1307fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_read        = fb_sys_read,
+       .fb_write       = ssd1307fb_write,
+       .fb_fillrect    = ssd1307fb_fillrect,
+       .fb_copyarea    = ssd1307fb_copyarea,
+       .fb_imageblit   = ssd1307fb_imageblit,
+};
+
+static void ssd1307fb_deferred_io(struct fb_info *info,
+                               struct list_head *pagelist)
+{
+       ssd1307fb_update_display(info->par);
+}
+
+static struct fb_deferred_io ssd1307fb_defio = {
+       .delay          = HZ,
+       .deferred_io    = ssd1307fb_deferred_io,
+};
+
+static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       struct fb_info *info;
+       u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
+       struct ssd1307fb_par *par;
+       u8 *vmem;
+       int ret;
+
+       if (!client->dev.of_node) {
+               dev_err(&client->dev, "No device tree data found!\n");
+               return -EINVAL;
+       }
+
+       info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
+       if (!info) {
+               dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
+               return -ENOMEM;
+       }
+
+       vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+       if (!vmem) {
+               dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
+               ret = -ENOMEM;
+               goto fb_alloc_error;
+       }
+
+       info->fbops = &ssd1307fb_ops;
+       info->fix = ssd1307fb_fix;
+       info->fbdefio = &ssd1307fb_defio;
+
+       info->var = ssd1307fb_var;
+       info->var.red.length = 1;
+       info->var.red.offset = 0;
+       info->var.green.length = 1;
+       info->var.green.offset = 0;
+       info->var.blue.length = 1;
+       info->var.blue.offset = 0;
+
+       info->screen_base = (u8 __force __iomem *)vmem;
+       info->fix.smem_start = (unsigned long)vmem;
+       info->fix.smem_len = vmem_size;
+
+       fb_deferred_io_init(info);
+
+       par = info->par;
+       par->info = info;
+       par->client = client;
+
+       par->reset = of_get_named_gpio(client->dev.of_node,
+                                        "reset-gpios", 0);
+       if (!gpio_is_valid(par->reset)) {
+               ret = -EINVAL;
+               goto reset_oled_error;
+       }
+
+       ret = devm_gpio_request_one(&client->dev, par->reset,
+                                   GPIOF_OUT_INIT_HIGH,
+                                   "oled-reset");
+       if (ret) {
+               dev_err(&client->dev,
+                       "failed to request gpio %d: %d\n",
+                       par->reset, ret);
+               goto reset_oled_error;
+       }
+
+       par->pwm = pwm_get(&client->dev, NULL);
+       if (IS_ERR(par->pwm)) {
+               dev_err(&client->dev, "Could not get PWM from device tree!\n");
+               ret = PTR_ERR(par->pwm);
+               goto pwm_error;
+       }
+
+       par->pwm_period = pwm_get_period(par->pwm);
+
+       dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
+
+       ret = register_framebuffer(info);
+       if (ret) {
+               dev_err(&client->dev, "Couldn't register the framebuffer\n");
+               goto fbreg_error;
+       }
+
+       i2c_set_clientdata(client, info);
+
+       /* Reset the screen */
+       gpio_set_value(par->reset, 0);
+       udelay(4);
+       gpio_set_value(par->reset, 1);
+       udelay(4);
+
+       /* Enable the PWM */
+       pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+       pwm_enable(par->pwm);
+
+       /* Map column 127 of the OLED to segment 0 */
+       ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
+       if (ret < 0) {
+               dev_err(&client->dev, "Couldn't remap the screen.\n");
+               goto remap_error;
+       }
+
+       /* Turn on the display */
+       ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
+       if (ret < 0) {
+               dev_err(&client->dev, "Couldn't turn the display on.\n");
+               goto remap_error;
+       }
+
+       dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
+
+       return 0;
+
+remap_error:
+       unregister_framebuffer(info);
+       pwm_disable(par->pwm);
+fbreg_error:
+       pwm_put(par->pwm);
+pwm_error:
+reset_oled_error:
+       fb_deferred_io_cleanup(info);
+fb_alloc_error:
+       framebuffer_release(info);
+       return ret;
+}
+
+static int __devexit ssd1307fb_remove(struct i2c_client *client)
+{
+       struct fb_info *info = i2c_get_clientdata(client);
+       struct ssd1307fb_par *par = info->par;
+
+       unregister_framebuffer(info);
+       pwm_disable(par->pwm);
+       pwm_put(par->pwm);
+       fb_deferred_io_cleanup(info);
+       framebuffer_release(info);
+
+       return 0;
+}
+
+static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+       { "ssd1307fb", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+static const struct of_device_id ssd1307fb_of_match[] = {
+       { .compatible = "solomon,ssd1307fb-i2c" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+
+static struct i2c_driver ssd1307fb_driver = {
+       .probe = ssd1307fb_probe,
+       .remove = __devexit_p(ssd1307fb_remove),
+       .id_table = ssd1307fb_i2c_id,
+       .driver = {
+               .name = "ssd1307fb",
+               .of_match_table = of_match_ptr(ssd1307fb_of_match),
+               .owner = THIS_MODULE,
+       },
+};
+
+module_i2c_driver(ssd1307fb_driver);
+
+MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");
index 2dcdbc9364d8802ed26154f18097a8995b5c5271..99ebdde590f8266dc1b734c9c827fd40693d227f 100644 (file)
@@ -15,6 +15,7 @@ if VIRT_DRIVERS
 config FSL_HV_MANAGER
        tristate "Freescale hypervisor management driver"
        depends on FSL_SOC
+       select EPAPR_PARAVIRT
        help
           The Freescale hypervisor management driver provides several services
          to drivers and applications related to the Freescale hypervisor:
index 5b06d31ab6a98678320b8c88456f0d3abde2cb35..c0bc92d8e438f40a1dba75e078a636fb56c7b99f 100644 (file)
@@ -212,7 +212,7 @@ static long booke_wdt_ioctl(struct file *file,
        return 0;
 }
 
-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
+/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
 static unsigned long wdt_is_active;
 
 static int booke_wdt_open(struct inode *inode, struct file *file)
index 126d8ce591ce5fc7e69348f746e91e60b04bc4ee..cabfa97f4674ef12c1fcd13d1a55c4affd47f635 100644 (file)
@@ -206,4 +206,7 @@ config XEN_MCE_LOG
          Allow kernel fetching MCE error from Xen platform and
          converting it into Linux mcelog format for mcelog tools
 
+config XEN_HAVE_PVMMU
+       bool
+
 endmenu
index 74354708c6c4e7dd9040ead14affbfa88924ca74..fb213cf81a7bc79a94bea376ab7e540cfddaec95 100644 (file)
@@ -1,9 +1,9 @@
 ifneq ($(CONFIG_ARM),y)
-obj-y  += manage.o balloon.o
+obj-y  += manage.o
 obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
 endif
 obj-$(CONFIG_X86)                      += fallback.o
-obj-y  += grant-table.o features.o events.o
+obj-y  += grant-table.o features.o events.o balloon.o
 obj-y  += xenbus/
 
 nostackp := $(call cc-option, -fno-stack-protector)
@@ -11,7 +11,8 @@ CFLAGS_features.o                     := $(nostackp)
 
 dom0-$(CONFIG_PCI) += pci.o
 dom0-$(CONFIG_USB_SUPPORT) += dbgp.o
-dom0-$(CONFIG_ACPI) += acpi.o
+dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y)
+xen-pad-$(CONFIG_X86) += xen-acpi-pad.o
 dom0-$(CONFIG_X86) += pcpu.o
 obj-$(CONFIG_XEN_DOM0)                 += $(dom0-y)
 obj-$(CONFIG_BLOCK)                    += biomerge.o
index d6886d90ccfd53eed62773a755ee282e9553a55f..a56776dbe0958ece67b1c12a4a13b8be5bdb023c 100644 (file)
@@ -359,6 +359,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
                set_phys_to_machine(pfn, frame_list[i]);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
                /* Link back into the page tables if not highmem. */
                if (xen_pv_domain() && !PageHighMem(page)) {
                        int ret;
@@ -368,6 +369,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
                                0);
                        BUG_ON(ret);
                }
+#endif
 
                /* Relinquish the page back to the allocator. */
                ClearPageReserved(page);
@@ -416,13 +418,14 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
                if (xen_pv_domain() && !PageHighMem(page)) {
                        ret = HYPERVISOR_update_va_mapping(
                                (unsigned long)__va(pfn << PAGE_SHIFT),
                                __pte_ma(0), 0);
                        BUG_ON(ret);
                }
-
+#endif
        }
 
        /* Ensure that ballooned highmem pages don't have kmaps. */
index 71f5c459b088aa5e21066b77adbcb5f34f7b9843..0bbbccbb1f1296ea305414795b6915679b26d94d 100644 (file)
 #include <xen/features.h>
 #include <xen/page.h>
 #include <xen/xen-ops.h>
+#include <xen/balloon.h>
 
 #include "privcmd.h"
 
 MODULE_LICENSE("GPL");
 
+#define PRIV_VMA_LOCKED ((void *)1)
+
 #ifndef HAVE_ARCH_PRIVCMD_MMAP
 static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
 #endif
@@ -178,7 +181,7 @@ static int mmap_mfn_range(void *data, void *state)
                                        msg->va & PAGE_MASK,
                                        msg->mfn, msg->npages,
                                        vma->vm_page_prot,
-                                       st->domain);
+                                       st->domain, NULL);
        if (rc < 0)
                return rc;
 
@@ -199,6 +202,10 @@ static long privcmd_ioctl_mmap(void __user *udata)
        if (!xen_initial_domain())
                return -EPERM;
 
+       /* We only support privcmd_ioctl_mmap_batch for auto translated. */
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return -ENOSYS;
+
        if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
                return -EFAULT;
 
@@ -246,6 +253,7 @@ struct mmap_batch_state {
        domid_t domain;
        unsigned long va;
        struct vm_area_struct *vma;
+       int index;
        /* A tristate:
         *      0 for no errors
         *      1 if at least one error has happened (and no
@@ -260,14 +268,24 @@ struct mmap_batch_state {
        xen_pfn_t __user *user_mfn;
 };
 
+/* auto translated dom0 note: if domU being created is PV, then mfn is
+ * mfn(addr on bus). If it's auto xlated, then mfn is pfn (input to HAP).
+ */
 static int mmap_batch_fn(void *data, void *state)
 {
        xen_pfn_t *mfnp = data;
        struct mmap_batch_state *st = state;
+       struct vm_area_struct *vma = st->vma;
+       struct page **pages = vma->vm_private_data;
+       struct page *cur_page = NULL;
        int ret;
 
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               cur_page = pages[st->index++];
+
        ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1,
-                                        st->vma->vm_page_prot, st->domain);
+                                        st->vma->vm_page_prot, st->domain,
+                                        &cur_page);
 
        /* Store error code for second pass. */
        *(st->err++) = ret;
@@ -303,6 +321,32 @@ static int mmap_return_errors_v1(void *data, void *state)
        return __put_user(*mfnp, st->user_mfn++);
 }
 
+/* Allocate pfns that are then mapped with gmfns from foreign domid. Update
+ * the vma with the page info to use later.
+ * Returns: 0 if success, otherwise -errno
+ */
+static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
+{
+       int rc;
+       struct page **pages;
+
+       pages = kcalloc(numpgs, sizeof(pages[0]), GFP_KERNEL);
+       if (pages == NULL)
+               return -ENOMEM;
+
+       rc = alloc_xenballooned_pages(numpgs, pages, 0);
+       if (rc != 0) {
+               pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__,
+                       numpgs, rc);
+               kfree(pages);
+               return -ENOMEM;
+       }
+       BUG_ON(vma->vm_private_data != PRIV_VMA_LOCKED);
+       vma->vm_private_data = pages;
+
+       return 0;
+}
+
 static struct vm_operations_struct privcmd_vm_ops;
 
 static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
@@ -370,10 +414,18 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
                ret = -EINVAL;
                goto out;
        }
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+               ret = alloc_empty_pages(vma, m.num);
+               if (ret < 0) {
+                       up_write(&mm->mmap_sem);
+                       goto out;
+               }
+       }
 
        state.domain        = m.dom;
        state.vma           = vma;
        state.va            = m.addr;
+       state.index         = 0;
        state.global_error  = 0;
        state.err           = err_array;
 
@@ -442,6 +494,19 @@ static long privcmd_ioctl(struct file *file,
        return ret;
 }
 
+static void privcmd_close(struct vm_area_struct *vma)
+{
+       struct page **pages = vma->vm_private_data;
+       int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+
+       if (!xen_feature(XENFEAT_auto_translated_physmap || !numpgs || !pages))
+               return;
+
+       xen_unmap_domain_mfn_range(vma, numpgs, pages);
+       free_xenballooned_pages(numpgs, pages);
+       kfree(pages);
+}
+
 static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
@@ -452,6 +517,7 @@ static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 }
 
 static struct vm_operations_struct privcmd_vm_ops = {
+       .close = privcmd_close,
        .fault = privcmd_fault
 };
 
@@ -469,7 +535,7 @@ static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
 {
-       return (xchg(&vma->vm_private_data, (void *)1) == NULL);
+       return !cmpxchg(&vma->vm_private_data, NULL, PRIV_VMA_LOCKED);
 }
 
 const struct file_operations xen_privcmd_fops = {
diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c
new file mode 100644 (file)
index 0000000..da39191
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * xen-acpi-pad.c - Xen pad interface
+ *
+ * Copyright (c) 2012, Intel Corporation.
+ *    Author: Liu, Jinsong <jinsong.liu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/xen/hypercall.h>
+#include <xen/interface/version.h>
+#include <xen/xen-ops.h>
+
+#define ACPI_PROCESSOR_AGGREGATOR_CLASS        "acpi_pad"
+#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
+#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
+static DEFINE_MUTEX(xen_cpu_lock);
+
+static int xen_acpi_pad_idle_cpus(unsigned int idle_nums)
+{
+       struct xen_platform_op op;
+
+       op.cmd = XENPF_core_parking;
+       op.u.core_parking.type = XEN_CORE_PARKING_SET;
+       op.u.core_parking.idle_nums = idle_nums;
+
+       return HYPERVISOR_dom0_op(&op);
+}
+
+static int xen_acpi_pad_idle_cpus_num(void)
+{
+       struct xen_platform_op op;
+
+       op.cmd = XENPF_core_parking;
+       op.u.core_parking.type = XEN_CORE_PARKING_GET;
+
+       return HYPERVISOR_dom0_op(&op)
+              ?: op.u.core_parking.idle_nums;
+}
+
+/*
+ * Query firmware how many CPUs should be idle
+ * return -1 on failure
+ */
+static int acpi_pad_pur(acpi_handle handle)
+{
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       union acpi_object *package;
+       int num = -1;
+
+       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
+               return num;
+
+       if (!buffer.length || !buffer.pointer)
+               return num;
+
+       package = buffer.pointer;
+
+       if (package->type == ACPI_TYPE_PACKAGE &&
+               package->package.count == 2 &&
+               package->package.elements[0].integer.value == 1) /* rev 1 */
+               num = package->package.elements[1].integer.value;
+
+       kfree(buffer.pointer);
+       return num;
+}
+
+/* Notify firmware how many CPUs are idle */
+static void acpi_pad_ost(acpi_handle handle, int stat,
+       uint32_t idle_nums)
+{
+       union acpi_object params[3] = {
+               {.type = ACPI_TYPE_INTEGER,},
+               {.type = ACPI_TYPE_INTEGER,},
+               {.type = ACPI_TYPE_BUFFER,},
+       };
+       struct acpi_object_list arg_list = {3, params};
+
+       params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY;
+       params[1].integer.value =  stat;
+       params[2].buffer.length = 4;
+       params[2].buffer.pointer = (void *)&idle_nums;
+       acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
+}
+
+static void acpi_pad_handle_notify(acpi_handle handle)
+{
+       int idle_nums;
+
+       mutex_lock(&xen_cpu_lock);
+       idle_nums = acpi_pad_pur(handle);
+       if (idle_nums < 0) {
+               mutex_unlock(&xen_cpu_lock);
+               return;
+       }
+
+       idle_nums = xen_acpi_pad_idle_cpus(idle_nums)
+                   ?: xen_acpi_pad_idle_cpus_num();
+       if (idle_nums >= 0)
+               acpi_pad_ost(handle, 0, idle_nums);
+       mutex_unlock(&xen_cpu_lock);
+}
+
+static void acpi_pad_notify(acpi_handle handle, u32 event,
+       void *data)
+{
+       switch (event) {
+       case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
+               acpi_pad_handle_notify(handle);
+               break;
+       default:
+               pr_warn("Unsupported event [0x%x]\n", event);
+               break;
+       }
+}
+
+static int acpi_pad_add(struct acpi_device *device)
+{
+       acpi_status status;
+
+       strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS);
+
+       status = acpi_install_notify_handler(device->handle,
+               ACPI_DEVICE_NOTIFY, acpi_pad_notify, device);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       return 0;
+}
+
+static int acpi_pad_remove(struct acpi_device *device,
+       int type)
+{
+       mutex_lock(&xen_cpu_lock);
+       xen_acpi_pad_idle_cpus(0);
+       mutex_unlock(&xen_cpu_lock);
+
+       acpi_remove_notify_handler(device->handle,
+               ACPI_DEVICE_NOTIFY, acpi_pad_notify);
+       return 0;
+}
+
+static const struct acpi_device_id pad_device_ids[] = {
+       {"ACPI000C", 0},
+       {"", 0},
+};
+
+static struct acpi_driver acpi_pad_driver = {
+       .name = "processor_aggregator",
+       .class = ACPI_PROCESSOR_AGGREGATOR_CLASS,
+       .ids = pad_device_ids,
+       .ops = {
+               .add = acpi_pad_add,
+               .remove = acpi_pad_remove,
+       },
+};
+
+static int __init xen_acpi_pad_init(void)
+{
+       /* Only DOM0 is responsible for Xen acpi pad */
+       if (!xen_initial_domain())
+               return -ENODEV;
+
+       /* Only Xen4.2 or later support Xen acpi pad */
+       if (!xen_running_on_version_or_later(4, 2))
+               return -ENODEV;
+
+       return acpi_bus_register_driver(&acpi_pad_driver);
+}
+subsys_initcall(xen_acpi_pad_init);
index 961d664e2d2faacde4272fa83023919c6ebcf3ca..cd50d251998ee629fc5244add466129d4662e398 100644 (file)
@@ -142,7 +142,8 @@ static struct pcistub_device *pcistub_device_find(int domain, int bus,
                if (psdev->dev != NULL
                    && domain == pci_domain_nr(psdev->dev->bus)
                    && bus == psdev->dev->bus->number
-                   && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+                   && slot == PCI_SLOT(psdev->dev->devfn)
+                   && func == PCI_FUNC(psdev->dev->devfn)) {
                        pcistub_device_get(psdev);
                        goto out;
                }
@@ -191,7 +192,8 @@ struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
                if (psdev->dev != NULL
                    && domain == pci_domain_nr(psdev->dev->bus)
                    && bus == psdev->dev->bus->number
-                   && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+                   && slot == PCI_SLOT(psdev->dev->devfn)
+                   && func == PCI_FUNC(psdev->dev->devfn)) {
                        found_dev = pcistub_device_get_pci_dev(pdev, psdev);
                        break;
                }
@@ -360,7 +362,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
        if (!dev_data->pci_saved_state)
                dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
        else {
-               dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+               dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
                __pci_reset_function_locked(dev);
                pci_restore_state(dev);
        }
@@ -897,42 +899,35 @@ static struct pci_driver xen_pcibk_pci_driver = {
 static inline int str_to_slot(const char *buf, int *domain, int *bus,
                              int *slot, int *func)
 {
-       int err;
-       char wc = '*';
+       int parsed = 0;
 
-       err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
-       switch (err) {
+       switch (sscanf(buf, " %x:%x:%x.%x %n", domain, bus, slot, func,
+                      &parsed)) {
        case 3:
                *func = -1;
-               err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc);
+               sscanf(buf, " %x:%x:%x.* %n", domain, bus, slot, &parsed);
                break;
        case 2:
                *slot = *func = -1;
-               err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc);
-               if (err >= 2)
-                       ++err;
+               sscanf(buf, " %x:%x:*.* %n", domain, bus, &parsed);
                break;
        }
-       if (err == 4 && wc == '*')
+       if (parsed && !buf[parsed])
                return 0;
-       else if (err < 0)
-               return -EINVAL;
 
        /* try again without domain */
        *domain = 0;
-       wc = '*';
-       err = sscanf(buf, " %x:%x.%x", bus, slot, func);
-       switch (err) {
+       switch (sscanf(buf, " %x:%x.%x %n", bus, slot, func, &parsed)) {
        case 2:
                *func = -1;
-               err = sscanf(buf, " %x:%x.%c", bus, slot, &wc);
+               sscanf(buf, " %x:%x.* %n", bus, slot, &parsed);
                break;
        case 1:
                *slot = *func = -1;
-               err = sscanf(buf, " %x:*.%c", bus, &wc) + 1;
+               sscanf(buf, " %x:*.* %n", bus, &parsed);
                break;
        }
-       if (err == 3 && wc == '*')
+       if (parsed && !buf[parsed])
                return 0;
 
        return -EINVAL;
@@ -941,13 +936,20 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus,
 static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
                               *slot, int *func, int *reg, int *size, int *mask)
 {
-       int err;
+       int parsed = 0;
 
-       err =
-           sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot,
-                  func, reg, size, mask);
-       if (err == 7)
+       sscanf(buf, " %x:%x:%x.%x-%x:%x:%x %n", domain, bus, slot, func,
+              reg, size, mask, &parsed);
+       if (parsed && !buf[parsed])
                return 0;
+
+       /* try again without domain */
+       *domain = 0;
+       sscanf(buf, " %x:%x.%x-%x:%x:%x %n", bus, slot, func, reg, size,
+              mask, &parsed);
+       if (parsed && !buf[parsed])
+               return 0;
+
        return -EINVAL;
 }
 
@@ -955,7 +957,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
 {
        struct pcistub_device_id *pci_dev_id;
        unsigned long flags;
-       int rc = 0;
+       int rc = 0, devfn = PCI_DEVFN(slot, func);
 
        if (slot < 0) {
                for (slot = 0; !rc && slot < 32; ++slot)
@@ -969,13 +971,24 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
                return rc;
        }
 
+       if ((
+#if !defined(MODULE) /* pci_domains_supported is not being exported */ \
+    || !defined(CONFIG_PCI_DOMAINS)
+            !pci_domains_supported ? domain :
+#endif
+            domain < 0 || domain > 0xffff)
+           || bus < 0 || bus > 0xff
+           || PCI_SLOT(devfn) != slot
+           || PCI_FUNC(devfn) != func)
+               return -EINVAL;
+
        pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
        if (!pci_dev_id)
                return -ENOMEM;
 
        pci_dev_id->domain = domain;
        pci_dev_id->bus = bus;
-       pci_dev_id->devfn = PCI_DEVFN(slot, func);
+       pci_dev_id->devfn = devfn;
 
        pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n",
                 domain, bus, slot, func);
@@ -1016,14 +1029,18 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
        return err;
 }
 
-static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
-                          int size, int mask)
+static int pcistub_reg_add(int domain, int bus, int slot, int func,
+                          unsigned int reg, unsigned int size,
+                          unsigned int mask)
 {
        int err = 0;
        struct pcistub_device *psdev;
        struct pci_dev *dev;
        struct config_field *field;
 
+       if (reg > 0xfff || (size < 4 && (mask >> (size * 8))))
+               return -EINVAL;
+
        psdev = pcistub_device_find(domain, bus, slot, func);
        if (!psdev) {
                err = -ENODEV;
@@ -1254,13 +1271,11 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf,
        int err;
        struct pcistub_device *psdev;
        struct xen_pcibk_dev_data *dev_data;
+
        err = str_to_slot(buf, &domain, &bus, &slot, &func);
        if (err)
                goto out;
-       if (slot < 0 || func < 0) {
-               err = -EINVAL;
-               goto out;
-       }
+
        psdev = pcistub_device_find(domain, bus, slot, func);
        if (!psdev) {
                err = -ENODEV;
@@ -1339,8 +1354,6 @@ static int __init pcistub_init(void)
 
        if (pci_devs_to_hide && *pci_devs_to_hide) {
                do {
-                       char wc = '*';
-
                        parsed = 0;
 
                        err = sscanf(pci_devs_to_hide + pos,
@@ -1349,51 +1362,48 @@ static int __init pcistub_init(void)
                        switch (err) {
                        case 3:
                                func = -1;
-                               err = sscanf(pci_devs_to_hide + pos,
-                                            " (%x:%x:%x.%c) %n",
-                                            &domain, &bus, &slot, &wc,
-                                            &parsed);
+                               sscanf(pci_devs_to_hide + pos,
+                                      " (%x:%x:%x.*) %n",
+                                      &domain, &bus, &slot, &parsed);
                                break;
                        case 2:
                                slot = func = -1;
-                               err = sscanf(pci_devs_to_hide + pos,
-                                            " (%x:%x:*.%c) %n",
-                                            &domain, &bus, &wc, &parsed) + 1;
+                               sscanf(pci_devs_to_hide + pos,
+                                      " (%x:%x:*.*) %n",
+                                      &domain, &bus, &parsed);
                                break;
                        }
 
-                       if (err != 4 || wc != '*') {
+                       if (!parsed) {
                                domain = 0;
-                               wc = '*';
                                err = sscanf(pci_devs_to_hide + pos,
                                             " (%x:%x.%x) %n",
                                             &bus, &slot, &func, &parsed);
                                switch (err) {
                                case 2:
                                        func = -1;
-                                       err = sscanf(pci_devs_to_hide + pos,
-                                                    " (%x:%x.%c) %n",
-                                                    &bus, &slot, &wc,
-                                                    &parsed);
+                                       sscanf(pci_devs_to_hide + pos,
+                                              " (%x:%x.*) %n",
+                                              &bus, &slot, &parsed);
                                        break;
                                case 1:
                                        slot = func = -1;
-                                       err = sscanf(pci_devs_to_hide + pos,
-                                                    " (%x:*.%c) %n",
-                                                    &bus, &wc, &parsed) + 1;
+                                       sscanf(pci_devs_to_hide + pos,
+                                              " (%x:*.*) %n",
+                                              &bus, &parsed);
                                        break;
                                }
-                               if (err != 3 || wc != '*')
-                                       goto parse_error;
                        }
 
+                       if (parsed <= 0)
+                               goto parse_error;
+
                        err = pcistub_device_id_add(domain, bus, slot, func);
                        if (err)
                                goto out;
 
-                       /* if parsed<=0, we've reached the end of the string */
                        pos += parsed;
-               } while (parsed > 0 && pci_devs_to_hide[pos]);
+               } while (pci_devs_to_hide[pos]);
        }
 
        /* If we're the first PCI Device Driver to register, we're the
index acedeabe589c94eaecd5ab5d478f7e7b3bfbe4af..88e677b0de74042f017ef017bf08a1029311c3ce 100644 (file)
@@ -48,7 +48,6 @@
 #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;
index 842d00048a652f8cb9ebda7eeea40d62e9cb6720..01443ce43ee75f072158afbc313a6e206bb2f10d 100644 (file)
@@ -548,15 +548,6 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 
                spin_lock(&sbi->fs_lock);
                ino->flags &= ~AUTOFS_INF_EXPIRING;
-               spin_lock(&dentry->d_lock);
-               if (!ret) {
-                       if ((IS_ROOT(dentry) ||
-                           (autofs_type_indirect(sbi->type) &&
-                            IS_ROOT(dentry->d_parent))) &&
-                           !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
-                               __managed_dentry_set_automount(dentry);
-               }
-               spin_unlock(&dentry->d_lock);
                complete_all(&ino->expire_complete);
                spin_unlock(&sbi->fs_lock);
                dput(dentry);
index 91b11650722e517e2066219fac803aefdae78470..c93447604da859bf5b3de0435c4d26852811bb95 100644 (file)
@@ -124,13 +124,10 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
         * it.
         */
        spin_lock(&sbi->lookup_lock);
-       spin_lock(&dentry->d_lock);
-       if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
-               spin_unlock(&dentry->d_lock);
+       if (!d_mountpoint(dentry) && simple_empty(dentry)) {
                spin_unlock(&sbi->lookup_lock);
                return -ENOENT;
        }
-       spin_unlock(&dentry->d_lock);
        spin_unlock(&sbi->lookup_lock);
 
 out:
@@ -355,7 +352,6 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
                status = autofs4_mount_wait(dentry);
                if (status)
                        return ERR_PTR(status);
-               spin_lock(&sbi->fs_lock);
                goto done;
        }
 
@@ -364,8 +360,11 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
         * having d_mountpoint() true, so there's no need to call back
         * to the daemon.
         */
-       if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))
+       if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
+               spin_unlock(&sbi->fs_lock);
                goto done;
+       }
+
        if (!d_mountpoint(dentry)) {
                /*
                 * It's possible that user space hasn't removed directories
@@ -379,15 +378,13 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
                 * require user space behave.
                 */
                if (sbi->version > 4) {
-                       if (have_submounts(dentry))
+                       if (have_submounts(dentry)) {
+                               spin_unlock(&sbi->fs_lock);
                                goto done;
+                       }
                } else {
-                       spin_lock(&dentry->d_lock);
-                       if (!list_empty(&dentry->d_subdirs)) {
-                               spin_unlock(&dentry->d_lock);
+                       if (!simple_empty(dentry))
                                goto done;
-                       }
-                       spin_unlock(&dentry->d_lock);
                }
                ino->flags |= AUTOFS_INF_PENDING;
                spin_unlock(&sbi->fs_lock);
@@ -399,28 +396,8 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
                        return ERR_PTR(status);
                }
        }
-done:
-       if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
-               /*
-                * Any needed mounting has been completed and the path
-                * updated so clear DCACHE_NEED_AUTOMOUNT so we don't
-                * call ->d_automount() on rootless multi-mounts since
-                * it can lead to an incorrect ELOOP error return.
-                *
-                * Only clear DMANAGED_AUTOMOUNT for rootless multi-mounts and
-                * symlinks as in all other cases the dentry will be covered by
-                * an actual mount so ->d_automount() won't be called during
-                * the follow.
-                */
-               spin_lock(&dentry->d_lock);
-               if ((!d_mountpoint(dentry) &&
-                   !list_empty(&dentry->d_subdirs)) ||
-                   (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
-                       __managed_dentry_clear_automount(dentry);
-               spin_unlock(&dentry->d_lock);
-       }
        spin_unlock(&sbi->fs_lock);
-
+done:
        /* Mount succeeded, check if we ended up with a new dentry */
        dentry = autofs4_mountpoint_changed(path);
        if (!dentry)
@@ -432,6 +409,8 @@ done:
 int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+       struct autofs_info *ino = autofs4_dentry_ino(dentry);
+       int status;
 
        DPRINTK("dentry=%p %.*s",
                dentry, dentry->d_name.len, dentry->d_name.name);
@@ -456,7 +435,32 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
         * This dentry may be under construction so wait on mount
         * completion.
         */
-       return autofs4_mount_wait(dentry);
+       status = autofs4_mount_wait(dentry);
+       if (status)
+               return status;
+
+       spin_lock(&sbi->fs_lock);
+       /*
+        * If the dentry has been selected for expire while we slept
+        * on the lock then it might go away. We'll deal with that in
+        * ->d_automount() and wait on a new mount if the expire
+        * succeeds or return here if it doesn't (since there's no
+        * mount to follow with a rootless multi-mount).
+        */
+       if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
+               /*
+                * Any needed mounting has been completed and the path
+                * updated so check if this is a rootless multi-mount so
+                * we can avoid needless calls ->d_automount() and avoid
+                * an incorrect ELOOP error return.
+                */
+               if ((!d_mountpoint(dentry) && !simple_empty(dentry)) ||
+                   (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
+                       status = -EISDIR;
+       }
+       spin_unlock(&sbi->fs_lock);
+
+       return status;
 }
 
 /* Lookups in the root directory */
@@ -599,9 +603,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
 
        spin_lock(&sbi->lookup_lock);
        __autofs4_add_expiring(dentry);
-       spin_lock(&dentry->d_lock);
-       __d_drop(dentry);
-       spin_unlock(&dentry->d_lock);
+       d_drop(dentry);
        spin_unlock(&sbi->lookup_lock);
 
        return 0;
@@ -672,15 +674,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
                return -EACCES;
 
        spin_lock(&sbi->lookup_lock);
-       spin_lock(&dentry->d_lock);
-       if (!list_empty(&dentry->d_subdirs)) {
-               spin_unlock(&dentry->d_lock);
+       if (!simple_empty(dentry)) {
                spin_unlock(&sbi->lookup_lock);
                return -ENOTEMPTY;
        }
        __autofs4_add_expiring(dentry);
-       __d_drop(dentry);
-       spin_unlock(&dentry->d_lock);
+       d_drop(dentry);
        spin_unlock(&sbi->lookup_lock);
 
        if (sbi->version < 5)
index c72ead869507412ac9939c0748a482035baaf2aa..596617ecd3296e22eebb4bb08ec57cf4170a100e 100644 (file)
@@ -413,7 +413,7 @@ struct btrfs_root_backup {
        __le64 bytes_used;
        __le64 num_devices;
        /* future */
-       __le64 unsed_64[4];
+       __le64 unused_64[4];
 
        u8 tree_root_level;
        u8 chunk_root_level;
index 3d3e2c17d8d12234a4a5fdcf2fc1af0eb717b6dd..06b2635073f37dbd15969803f4387020344f26ec 100644 (file)
@@ -3888,7 +3888,7 @@ static int flush_space(struct btrfs_root *root,
  * @root - the root we're allocating for
  * @block_rsv - the block_rsv we're allocating for
  * @orig_bytes - the number of bytes we want
- * @flush - wether or not we can flush to make our reservation
+ * @flush - whether or not we can flush to make our reservation
  *
  * This will reserve orgi_bytes number of bytes from the space info associated
  * with the block_rsv.  If there is not enough space it will make an attempt to
index b8cbc8d5c7f7cb39ed770fb2b256427f25bb9c69..ce9f79216723fbfcfc563d17e5e8974cbd2e9b00 100644 (file)
@@ -234,12 +234,11 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
 }
 
 /**
- * unpint_extent_cache - unpin an extent from the cache
+ * unpin_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
index dd27a0b46a37d1dfd878828672dfb0dbe99f5ac8..853fc7beedfaae7fd7ed03750e786693839b3f47 100644 (file)
@@ -76,7 +76,7 @@ struct btrfs_ordered_sum {
 
 #define BTRFS_ORDERED_IOERR 6 /* We had an io error when writing this out */
 
-#define BTRFS_ORDERED_UPDATED_ISIZE 7 /* indicates wether this ordered extent
+#define BTRFS_ORDERED_UPDATED_ISIZE 7 /* indicates whether this ordered extent
                                       * has done its due diligence in updating
                                       * the isize. */
 
index 0f5ebb72a5ea01693b339d66e3f928de9b783f78..e3c6ee3cc2ba3904cd623433a136f78fe2f3ada6 100644 (file)
@@ -4294,7 +4294,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
 
                        rcu_read_lock();
                        name = rcu_dereference(dev->name);
-                       pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu "
+                       pr_debug("btrfs_map_bio: rw %d, sector=%llu, dev=%lu "
                                 "(%s id %llu), size=%u\n", rw,
                                 (u64)bio->bi_sector, (u_long)dev->bdev->bd_dev,
                                 name->str, dev->devid, bio->bi_size);
index 6e9ed48064fc0c9e5ea98abfc1c4603be6955e4b..c017a2dfb9097e73837230d244ffb14f73dd0e1c 100644 (file)
@@ -46,8 +46,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
 
-inline void
-init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
+void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
 {
        bh->b_end_io = handler;
        bh->b_private = private;
@@ -850,13 +849,10 @@ try_again:
                if (!bh)
                        goto no_grow;
 
-               bh->b_bdev = NULL;
                bh->b_this_page = head;
                bh->b_blocknr = -1;
                head = bh;
 
-               bh->b_state = 0;
-               atomic_set(&bh->b_count, 0);
                bh->b_size = size;
 
                /* Link the buffer to its page */
index 22ab7b5b8da7eda6bf38d19aff3415eade104c5c..2d5622f60e1121aafc4dc96bcea96cf491180d9e 100644 (file)
@@ -480,7 +480,7 @@ A partial list of the supported mount options follows:
                Unicode on the wire.
  nomapchars     Do not translate any of these seven characters (default).
  nocase         Request case insensitive path name matching (case
-               sensitive is the default if the server suports it).
+               sensitive is the default if the server supports it).
                (mount option "ignorecase" is identical to "nocase")
  posixpaths     If CIFS Unix extensions are supported, attempt to
                negotiate posix path name support which allows certain
index 3c20de1d59d0d44586199ade586864758e2ce204..df163da388c9ccfe82348c51be596c9fcfd8cc55 100644 (file)
@@ -2455,7 +2455,7 @@ TAS_BUFFER_FNS(Uninit, uninit)
 BUFFER_FNS(Da_Mapped, da_mapped)
 
 /*
- * Add new method to test wether block and inode bitmaps are properly
+ * Add new method to test whether block and inode bitmaps are properly
  * initialized. With uninit_bg reading the block from disk is not enough
  * to mark the bitmap uptodate. We need to also zero-out the bitmap
  */
index f775bfdd6e4a7f3e0700b8ea556261ad8c13e3ba..cccdc874bb55df99eb10f89f33a7bcb1f92ddc99 100644 (file)
@@ -22,7 +22,7 @@ static long do_sys_name_to_handle(struct path *path,
        struct file_handle *handle = NULL;
 
        /*
-        * We need t make sure wether the file system
+        * We need to make sure whether the file system
         * support decoding of the file handle
         */
        if (!path->dentry->d_sb->s_export_op ||
@@ -40,7 +40,7 @@ static long do_sys_name_to_handle(struct path *path,
        if (!handle)
                return -ENOMEM;
 
-       /* convert handle size to  multiple of sizeof(u32) */
+       /* convert handle size to multiple of sizeof(u32) */
        handle_dwords = f_handle.handle_bytes >> 2;
 
        /* we ask for a non connected handle */
index 3e3422f7f0a4b4c46080cf798c4185af0642e05d..310972b72a6654c1597fc11f717954606561c47e 100644 (file)
@@ -1034,7 +1034,7 @@ int bdi_writeback_thread(void *data)
        while (!kthread_freezable_should_stop(NULL)) {
                /*
                 * Remove own delayed wake-up timer, since we are already awake
-                * and we'll take care of the preriodic write-back.
+                * and we'll take care of the periodic write-back.
                 */
                del_timer(&wb->wakeup_timer);
 
index 01c4975da4bc6252a9ce41e4c23ebd183c80a47c..30de4f2a2ea90f45d0108f2a571f9d1f233ed4e0 100644 (file)
@@ -643,7 +643,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
                        goto out_unlock;
 
                requested = data_blocks + ind_blocks;
-               error = gfs2_inplace_reserve(ip, requested);
+               error = gfs2_inplace_reserve(ip, requested, 0);
                if (error)
                        goto out_qunlock;
        }
index 1fd3ae237bdde3faee7b67d68bfc50b496b6e976..a68e91bcef3ddf7d005665955ecff7909ccb171f 100644 (file)
@@ -991,6 +991,41 @@ unlock:
        return err;
 }
 
+/**
+ * gfs2_journaled_truncate - Wrapper for truncate_pagecache for jdata files
+ * @inode: The inode being truncated
+ * @oldsize: The original (larger) size
+ * @newsize: The new smaller size
+ *
+ * With jdata files, we have to journal a revoke for each block which is
+ * truncated. As a result, we need to split this into separate transactions
+ * if the number of pages being truncated gets too large.
+ */
+
+#define GFS2_JTRUNC_REVOKES 8192
+
+static int gfs2_journaled_truncate(struct inode *inode, u64 oldsize, u64 newsize)
+{
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       u64 max_chunk = GFS2_JTRUNC_REVOKES * sdp->sd_vfs->s_blocksize;
+       u64 chunk;
+       int error;
+
+       while (oldsize != newsize) {
+               chunk = oldsize - newsize;
+               if (chunk > max_chunk)
+                       chunk = max_chunk;
+               truncate_pagecache(inode, oldsize, oldsize - chunk);
+               oldsize -= chunk;
+               gfs2_trans_end(sdp);
+               error = gfs2_trans_begin(sdp, RES_DINODE, GFS2_JTRUNC_REVOKES);
+               if (error)
+                       return error;
+       }
+
+       return 0;
+}
+
 static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -1000,8 +1035,10 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
        int journaled = gfs2_is_jdata(ip);
        int error;
 
-       error = gfs2_trans_begin(sdp,
-                                RES_DINODE + (journaled ? RES_JDATA : 0), 0);
+       if (journaled)
+               error = gfs2_trans_begin(sdp, RES_DINODE + RES_JDATA, GFS2_JTRUNC_REVOKES);
+       else
+               error = gfs2_trans_begin(sdp, RES_DINODE, 0);
        if (error)
                return error;
 
@@ -1026,7 +1063,16 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_dinode_out(ip, dibh->b_data);
 
-       truncate_pagecache(inode, oldsize, newsize);
+       if (journaled)
+               error = gfs2_journaled_truncate(inode, oldsize, newsize);
+       else
+               truncate_pagecache(inode, oldsize, newsize);
+
+       if (error) {
+               brelse(dibh);
+               return error;
+       }
+
 out_brelse:
        brelse(dibh);
 out:
@@ -1178,7 +1224,7 @@ static int do_grow(struct inode *inode, u64 size)
                if (error)
                        return error;
 
-               error = gfs2_inplace_reserve(ip, 1);
+               error = gfs2_inplace_reserve(ip, 1, 0);
                if (error)
                        goto do_grow_qunlock;
                unstuff = 1;
index 259b088cfc4c64d5ce434dc5e3a65dc0eb250fd0..9a35670fdc38e916df54315ad38c879f8a483820 100644 (file)
@@ -1676,16 +1676,11 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
                                be16_add_cpu(&leaf->lf_entries, 1);
                        }
                        brelse(bh);
-                       error = gfs2_meta_inode_buffer(ip, &bh);
-                       if (error)
-                               break;
-                       gfs2_trans_add_bh(ip->i_gl, bh, 1);
                        ip->i_entries++;
                        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
                        if (S_ISDIR(nip->i_inode.i_mode))
                                inc_nlink(&ip->i_inode);
-                       gfs2_dinode_out(ip, bh->b_data);
-                       brelse(bh);
+                       mark_inode_dirty(inode);
                        error = 0;
                        break;
                }
index e056b4ce487777bbe794d64a11e4cbe2756205d3..dfe2d8cb9b2c0a57717fb3a3b7175b30eacffe76 100644 (file)
@@ -432,7 +432,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (ret)
                goto out_unlock;
        gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
-       ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
+       ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
        if (ret)
                goto out_quota_unlock;
 
@@ -825,7 +825,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
 retry:
                gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
 
-               error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
+               error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
                if (error) {
                        if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
                                bytes >>= 1;
index 0f22d09f358dc5b46b8fb5ed67e8992fa6c77414..992c5c0cb5045144f61f7d06032d61301ee484d6 100644 (file)
@@ -55,8 +55,6 @@ struct gfs2_glock_iter {
 
 typedef void (*glock_examiner) (struct gfs2_glock * gl);
 
-static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
-#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0)
 static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
 
 static struct dentry *gfs2_root;
@@ -107,10 +105,12 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
 {
        struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
 
-       if (gl->gl_ops->go_flags & GLOF_ASPACE)
+       if (gl->gl_ops->go_flags & GLOF_ASPACE) {
                kmem_cache_free(gfs2_glock_aspace_cachep, gl);
-       else
+       } else {
+               kfree(gl->gl_lksb.sb_lvbptr);
                kmem_cache_free(gfs2_glock_cachep, gl);
+       }
 }
 
 void gfs2_glock_free(struct gfs2_glock *gl)
@@ -537,8 +537,8 @@ __acquires(&gl->gl_spin)
            (lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
                clear_bit(GLF_BLOCKING, &gl->gl_flags);
        spin_unlock(&gl->gl_spin);
-       if (glops->go_xmote_th)
-               glops->go_xmote_th(gl);
+       if (glops->go_sync)
+               glops->go_sync(gl);
        if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
                glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
        clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
@@ -547,7 +547,10 @@ __acquires(&gl->gl_spin)
        if (sdp->sd_lockstruct.ls_ops->lm_lock) {
                /* lock_dlm */
                ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
-               GLOCK_BUG_ON(gl, ret);
+               if (ret) {
+                       printk(KERN_ERR "GFS2: lm_lock ret %d\n", ret);
+                       GLOCK_BUG_ON(gl, 1);
+               }
        } else { /* lock_nolock */
                finish_xmote(gl, target);
                if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
@@ -736,6 +739,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        if (!gl)
                return -ENOMEM;
 
+       memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
+
+       if (glops->go_flags & GLOF_LVB) {
+               gl->gl_lksb.sb_lvbptr = kzalloc(GFS2_MIN_LVB_SIZE, GFP_KERNEL);
+               if (!gl->gl_lksb.sb_lvbptr) {
+                       kmem_cache_free(cachep, gl);
+                       return -ENOMEM;
+               }
+       }
+
        atomic_inc(&sdp->sd_glock_disposal);
        gl->gl_sbd = sdp;
        gl->gl_flags = 0;
@@ -753,9 +766,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        preempt_enable();
        gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0;
        gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0;
-       memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
-       memset(gl->gl_lvb, 0, 32 * sizeof(char));
-       gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
        gl->gl_tchange = jiffies;
        gl->gl_object = NULL;
        gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
@@ -777,6 +787,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        tmp = search_bucket(hash, sdp, &name);
        if (tmp) {
                spin_unlock_bucket(hash);
+               kfree(gl->gl_lksb.sb_lvbptr);
                kmem_cache_free(cachep, gl);
                atomic_dec(&sdp->sd_glock_disposal);
                gl = tmp;
@@ -1013,7 +1024,7 @@ trap_recursive:
        printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid));
        printk(KERN_ERR "lock type: %d req lock state : %d\n",
               gh->gh_gl->gl_name.ln_type, gh->gh_state);
-       __dump_glock(NULL, gl);
+       gfs2_dump_glock(NULL, gl);
        BUG();
 }
 
@@ -1508,7 +1519,7 @@ static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
 {
        int ret;
        spin_lock(&gl->gl_spin);
-       ret = __dump_glock(seq, gl);
+       ret = gfs2_dump_glock(seq, gl);
        spin_unlock(&gl->gl_spin);
        return ret;
 }
@@ -1528,6 +1539,7 @@ static void dump_glock_func(struct gfs2_glock *gl)
 
 void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
 {
+       set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
        glock_hash_walk(clear_glock, sdp);
        flush_workqueue(glock_workqueue);
        wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
@@ -1655,7 +1667,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
 }
 
 /**
- * __dump_glock - print information about a glock
+ * gfs2_dump_glock - print information about a glock
  * @seq: The seq_file struct
  * @gl: the glock
  *
@@ -1672,7 +1684,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
  * Returns: 0 on success, -ENOBUFS when we run out of space
  */
 
-static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
+int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
 {
        const struct gfs2_glock_operations *glops = gl->gl_ops;
        unsigned long long dtime;
index 307ac31df781ea80ac8f77e01bfe5f4970710cb3..fd580b7861d5b940170092a719ddf4fe15cf3a26 100644 (file)
@@ -178,33 +178,33 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
        return NULL;
 }
 
-int gfs2_glock_get(struct gfs2_sbd *sdp,
-                  u64 number, const struct gfs2_glock_operations *glops,
-                  int create, struct gfs2_glock **glp);
-void gfs2_glock_hold(struct gfs2_glock *gl);
-void gfs2_glock_put_nolock(struct gfs2_glock *gl);
-void gfs2_glock_put(struct gfs2_glock *gl);
-void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
-                     struct gfs2_holder *gh);
-void gfs2_holder_reinit(unsigned int state, unsigned flags,
-                       struct gfs2_holder *gh);
-void gfs2_holder_uninit(struct gfs2_holder *gh);
-int gfs2_glock_nq(struct gfs2_holder *gh);
-int gfs2_glock_poll(struct gfs2_holder *gh);
-int gfs2_glock_wait(struct gfs2_holder *gh);
-void gfs2_glock_dq(struct gfs2_holder *gh);
-void gfs2_glock_dq_wait(struct gfs2_holder *gh);
-
-void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
-int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
-                     u64 number, const struct gfs2_glock_operations *glops,
-                     unsigned int state, int flags, struct gfs2_holder *gh);
-
-int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
-
-__printf(2, 3)
+extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
+                         const struct gfs2_glock_operations *glops,
+                         int create, struct gfs2_glock **glp);
+extern void gfs2_glock_hold(struct gfs2_glock *gl);
+extern void gfs2_glock_put_nolock(struct gfs2_glock *gl);
+extern void gfs2_glock_put(struct gfs2_glock *gl);
+extern void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
+                            unsigned flags, struct gfs2_holder *gh);
+extern void gfs2_holder_reinit(unsigned int state, unsigned flags,
+                              struct gfs2_holder *gh);
+extern void gfs2_holder_uninit(struct gfs2_holder *gh);
+extern int gfs2_glock_nq(struct gfs2_holder *gh);
+extern int gfs2_glock_poll(struct gfs2_holder *gh);
+extern int gfs2_glock_wait(struct gfs2_holder *gh);
+extern void gfs2_glock_dq(struct gfs2_holder *gh);
+extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
+extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
+extern int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
+                            const struct gfs2_glock_operations *glops,
+                            unsigned int state, int flags,
+                            struct gfs2_holder *gh);
+extern int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
+#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { gfs2_dump_glock(NULL, gl); BUG(); } } while(0)
+extern __printf(2, 3)
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
 
 /**
index 32cc4fde975c2d74aa19d7134f61ed712a1599fa..78d4184ffc7d496eac9bd7adcef248d3f0a5689c 100644 (file)
@@ -74,7 +74,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
                gfs2_trans_add_revoke(sdp, bd);
        }
-       BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
+       GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
        spin_unlock(&sdp->sd_ail_lock);
        gfs2_log_unlock(sdp);
 }
@@ -96,7 +96,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
        tr.tr_ip = (unsigned long)__builtin_return_address(0);
        sb_start_intwrite(sdp->sd_vfs);
        gfs2_log_reserve(sdp, tr.tr_reserved);
-       BUG_ON(current->journal_info);
+       WARN_ON_ONCE(current->journal_info);
        current->journal_info = &tr;
 
        __gfs2_ail_flush(gl, 0);
@@ -139,7 +139,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
-       BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+       GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
        gfs2_log_flush(gl->gl_sbd, gl);
        filemap_fdatawrite(metamapping);
@@ -168,7 +168,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
        struct address_space *mapping = gfs2_glock2aspace(gl);
 
-       BUG_ON(!(flags & DIO_METADATA));
+       WARN_ON_ONCE(!(flags & DIO_METADATA));
        gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
        truncate_inode_pages(mapping, 0);
 
@@ -197,7 +197,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
 
-       BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+       GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
        gfs2_log_flush(gl->gl_sbd, gl);
        filemap_fdatawrite(metamapping);
@@ -536,7 +536,7 @@ const struct gfs2_glock_operations gfs2_meta_glops = {
 };
 
 const struct gfs2_glock_operations gfs2_inode_glops = {
-       .go_xmote_th = inode_go_sync,
+       .go_sync = inode_go_sync,
        .go_inval = inode_go_inval,
        .go_demote_ok = inode_go_demote_ok,
        .go_lock = inode_go_lock,
@@ -546,17 +546,17 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
 };
 
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
-       .go_xmote_th = rgrp_go_sync,
+       .go_sync = rgrp_go_sync,
        .go_inval = rgrp_go_inval,
        .go_lock = gfs2_rgrp_go_lock,
        .go_unlock = gfs2_rgrp_go_unlock,
        .go_dump = gfs2_rgrp_dump,
        .go_type = LM_TYPE_RGRP,
-       .go_flags = GLOF_ASPACE,
+       .go_flags = GLOF_ASPACE | GLOF_LVB,
 };
 
 const struct gfs2_glock_operations gfs2_trans_glops = {
-       .go_xmote_th = trans_go_sync,
+       .go_sync = trans_go_sync,
        .go_xmote_bh = trans_go_xmote_bh,
        .go_demote_ok = trans_go_demote_ok,
        .go_type = LM_TYPE_NONDISK,
@@ -577,6 +577,7 @@ const struct gfs2_glock_operations gfs2_nondisk_glops = {
 
 const struct gfs2_glock_operations gfs2_quota_glops = {
        .go_type = LM_TYPE_QUOTA,
+       .go_flags = GLOF_LVB,
 };
 
 const struct gfs2_glock_operations gfs2_journal_glops = {
index 3d469d37345ebfad798578830b9d768a59c6a35c..c373a24fedd9f50a66f5d0ace7a2a542d5d581dc 100644 (file)
@@ -205,7 +205,7 @@ struct lm_lockname {
 
 
 struct gfs2_glock_operations {
-       void (*go_xmote_th) (struct gfs2_glock *gl);
+       void (*go_sync) (struct gfs2_glock *gl);
        int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh);
        void (*go_inval) (struct gfs2_glock *gl, int flags);
        int (*go_demote_ok) (const struct gfs2_glock *gl);
@@ -216,6 +216,7 @@ struct gfs2_glock_operations {
        const int go_type;
        const unsigned long go_flags;
 #define GLOF_ASPACE 1
+#define GLOF_LVB    2
 };
 
 enum {
@@ -321,7 +322,6 @@ struct gfs2_glock {
        ktime_t gl_dstamp;
        struct gfs2_lkstats gl_stats;
        struct dlm_lksb gl_lksb;
-       char gl_lvb[32];
        unsigned long gl_tchange;
        void *gl_object;
 
@@ -539,6 +539,7 @@ enum {
        SDF_DEMOTE              = 5,
        SDF_NOJOURNALID         = 6,
        SDF_RORECOVERY          = 7, /* read only recovery */
+       SDF_SKIP_DLM_UNLOCK     = 8,
 };
 
 #define GFS2_FSNAME_LEN                256
@@ -621,6 +622,7 @@ struct gfs2_sbd {
        u32 sd_hash_bsize_shift;
        u32 sd_hash_ptrs;       /* Number of pointers in a hash block */
        u32 sd_qc_per_block;
+       u32 sd_blocks_per_bitmap;
        u32 sd_max_dirres;      /* Max blocks needed to add a directory entry */
        u32 sd_max_height;      /* Max height of a file's metadata tree */
        u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
index 381893ceefa43b1c58fed94a0417ce4ff6de2631..2b6f5698ef18fb3ae489bc64e88ab5fd919855dd 100644 (file)
@@ -364,34 +364,34 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
        return 0;
 }
 
-static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode,
-                              unsigned int *uid, unsigned int *gid)
+static void munge_mode_uid_gid(const struct gfs2_inode *dip,
+                              struct inode *inode)
 {
        if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
            (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
-               if (S_ISDIR(*mode))
-                       *mode |= S_ISUID;
+               if (S_ISDIR(inode->i_mode))
+                       inode->i_mode |= S_ISUID;
                else if (dip->i_inode.i_uid != current_fsuid())
-                       *mode &= ~07111;
-               *uid = dip->i_inode.i_uid;
+                       inode->i_mode &= ~07111;
+               inode->i_uid = dip->i_inode.i_uid;
        } else
-               *uid = current_fsuid();
+               inode->i_uid = current_fsuid();
 
        if (dip->i_inode.i_mode & S_ISGID) {
-               if (S_ISDIR(*mode))
-                       *mode |= S_ISGID;
-               *gid = dip->i_inode.i_gid;
+               if (S_ISDIR(inode->i_mode))
+                       inode->i_mode |= S_ISGID;
+               inode->i_gid = dip->i_inode.i_gid;
        } else
-               *gid = current_fsgid();
+               inode->i_gid = current_fsgid();
 }
 
-static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
+static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
 {
-       struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
+       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        int error;
        int dblocks = 1;
 
-       error = gfs2_inplace_reserve(dip, RES_DINODE);
+       error = gfs2_inplace_reserve(ip, RES_DINODE, flags);
        if (error)
                goto out;
 
@@ -399,12 +399,15 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
        if (error)
                goto out_ipreserv;
 
-       error = gfs2_alloc_blocks(dip, no_addr, &dblocks, 1, generation);
+       error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation);
+       ip->i_no_formal_ino = ip->i_generation;
+       ip->i_inode.i_ino = ip->i_no_addr;
+       ip->i_goal = ip->i_no_addr;
 
        gfs2_trans_end(sdp);
 
 out_ipreserv:
-       gfs2_inplace_release(dip);
+       gfs2_inplace_release(ip);
 out:
        return error;
 }
@@ -429,52 +432,42 @@ static void gfs2_init_dir(struct buffer_head *dibh,
 /**
  * init_dinode - Fill in a new dinode structure
  * @dip: The directory this inode is being created in
- * @gl: The glock covering the new inode
- * @inum: The inode number
- * @mode: The file permissions
- * @uid: The uid of the new inode
- * @gid: The gid of the new inode
- * @generation: The generation number of the new inode
- * @dev: The device number (if a device node)
+ * @ip: The inode
  * @symname: The symlink destination (if a symlink)
- * @size: The inode size (ignored for directories)
  * @bhp: The buffer head (returned to caller)
  *
  */
 
-static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-                       const struct gfs2_inum_host *inum, umode_t mode,
-                       unsigned int uid, unsigned int gid,
-                       const u64 *generation, dev_t dev, const char *symname,
-                       unsigned size, struct buffer_head **bhp)
+static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
+                       const char *symname, struct buffer_head **bhp)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_dinode *di;
        struct buffer_head *dibh;
        struct timespec tv = CURRENT_TIME;
 
-       dibh = gfs2_meta_new(gl, inum->no_addr);
-       gfs2_trans_add_bh(gl, dibh, 1);
+       dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr);
+       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);
        gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
        di = (struct gfs2_dinode *)dibh->b_data;
 
-       di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);
-       di->di_num.no_addr = cpu_to_be64(inum->no_addr);
-       di->di_mode = cpu_to_be32(mode);
-       di->di_uid = cpu_to_be32(uid);
-       di->di_gid = cpu_to_be32(gid);
+       di->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+       di->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
+       di->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+       di->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+       di->di_gid = cpu_to_be32(ip->i_inode.i_gid);
        di->di_nlink = 0;
-       di->di_size = cpu_to_be64(size);
+       di->di_size = cpu_to_be64(ip->i_inode.i_size);
        di->di_blocks = cpu_to_be64(1);
        di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
-       di->di_major = cpu_to_be32(MAJOR(dev));
-       di->di_minor = cpu_to_be32(MINOR(dev));
-       di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
-       di->di_generation = cpu_to_be64(*generation);
+       di->di_major = cpu_to_be32(MAJOR(ip->i_inode.i_rdev));
+       di->di_minor = cpu_to_be32(MINOR(ip->i_inode.i_rdev));
+       di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_no_addr);
+       di->di_generation = cpu_to_be64(ip->i_generation);
        di->di_flags = 0;
        di->__pad1 = 0;
-       di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0);
+       di->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) ? GFS2_FORMAT_DE : 0);
        di->di_height = 0;
        di->__pad2 = 0;
        di->__pad3 = 0;
@@ -487,7 +480,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
        memset(&di->di_reserved, 0, sizeof(di->di_reserved));
 
-       switch(mode & S_IFMT) { 
+       switch(ip->i_inode.i_mode & S_IFMT) {
        case S_IFREG:
                if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
                    gfs2_tune_get(sdp, gt_new_files_jdata))
@@ -502,7 +495,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
                gfs2_init_dir(dibh, dip);
                break;
        case S_IFLNK:
-               memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size);
+               memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, ip->i_inode.i_size);
                break;
        }
 
@@ -511,25 +504,22 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        *bhp = dibh;
 }
 
-static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-                      umode_t mode, const struct gfs2_inum_host *inum,
-                      const u64 *generation, dev_t dev, const char *symname,
-                      unsigned int size, struct buffer_head **bhp)
+static int make_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
+                      const char *symname, struct buffer_head **bhp)
 {
+       struct inode *inode = &ip->i_inode;
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-       unsigned int uid, gid;
        int error;
 
-       munge_mode_uid_gid(dip, &mode, &uid, &gid);
        error = gfs2_rindex_update(sdp);
        if (error)
                return error;
 
-       error = gfs2_quota_lock(dip, uid, gid);
+       error = gfs2_quota_lock(dip, inode->i_uid, inode->i_gid);
        if (error)
                return error;
 
-       error = gfs2_quota_check(dip, uid, gid);
+       error = gfs2_quota_check(dip, inode->i_uid, inode->i_gid);
        if (error)
                goto out_quota;
 
@@ -537,8 +527,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        if (error)
                goto out_quota;
 
-       init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp);
-       gfs2_quota_change(dip, +1, uid, gid);
+       init_dinode(dip, ip, symname, bhp);
+       gfs2_quota_change(dip, +1, inode->i_uid, inode->i_gid);
        gfs2_trans_end(sdp);
 
 out_quota:
@@ -570,7 +560,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
                if (error)
                        goto fail_quota_locks;
 
-               error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
+               error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
                if (error)
                        goto fail_quota_locks;
 
@@ -657,19 +647,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        struct inode *inode = NULL;
        struct gfs2_inode *dip = GFS2_I(dir), *ip;
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-       struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
+       struct gfs2_glock *io_gl;
        int error;
-       u64 generation;
        struct buffer_head *bh = NULL;
+       u32 aflags = 0;
 
        if (!name->len || name->len > GFS2_FNAMESIZE)
                return -ENAMETOOLONG;
 
-       /* We need a reservation to allocate the new dinode block. The
-          directory ip temporarily points to the reservation, but this is
-          being done to get a set of contiguous blocks for the new dinode.
-          Since this is a create, we don't have a sizehint yet, so it will
-          have to use the minimum reservation size. */
        error = gfs2_rs_alloc(dip);
        if (error)
                return error;
@@ -688,45 +673,72 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        if (error)
                goto fail_gunlock;
 
-       error = alloc_dinode(dip, &inum.no_addr, &generation);
+       inode = new_inode(sdp->sd_vfs);
+       if (!inode) {
+               gfs2_glock_dq_uninit(ghs);
+               return -ENOMEM;
+       }
+       ip = GFS2_I(inode);
+       error = gfs2_rs_alloc(ip);
        if (error)
-               goto fail_gunlock;
-       inum.no_formal_ino = generation;
+               goto fail_free_inode;
+
+       set_bit(GIF_INVALID, &ip->i_flags);
+       inode->i_mode = mode;
+       inode->i_rdev = dev;
+       inode->i_size = size;
+       munge_mode_uid_gid(dip, inode);
+       ip->i_goal = dip->i_goal;
 
-       error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops,
-                                 LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+       if ((GFS2_I(sdp->sd_root_dir->d_inode) == dip) ||
+           (dip->i_diskflags & GFS2_DIF_TOPDIR))
+               aflags |= GFS2_AF_ORLOV;
+
+       error = alloc_dinode(ip, aflags);
        if (error)
-               goto fail_gunlock;
+               goto fail_free_inode;
 
-       error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh);
+       error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
        if (error)
-               goto fail_gunlock2;
+               goto fail_free_inode;
 
-       inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr,
-                                 inum.no_formal_ino, 0);
-       if (IS_ERR(inode))
+       ip->i_gl->gl_object = ip;
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+       if (error)
+               goto fail_free_inode;
+
+       error = make_dinode(dip, ip, symname, &bh);
+       if (error)
                goto fail_gunlock2;
 
-       ip = GFS2_I(inode);
-       error = gfs2_inode_refresh(ip);
+       error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
        if (error)
                goto fail_gunlock2;
 
-       error = gfs2_rs_alloc(ip);
+       error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
        if (error)
                goto fail_gunlock2;
 
+       ip->i_iopen_gh.gh_gl->gl_object = ip;
+       gfs2_glock_put(io_gl);
+       gfs2_set_iop(inode);
+       insert_inode_hash(inode);
+
+       error = gfs2_inode_refresh(ip);
+       if (error)
+               goto fail_gunlock3;
+
        error = gfs2_acl_create(dip, inode);
        if (error)
-               goto fail_gunlock2;
+               goto fail_gunlock3;
 
        error = gfs2_security_init(dip, ip, name);
        if (error)
-               goto fail_gunlock2;
+               goto fail_gunlock3;
 
        error = link_dinode(dip, name, ip);
        if (error)
-               goto fail_gunlock2;
+               goto fail_gunlock3;
 
        if (bh)
                brelse(bh);
@@ -739,8 +751,20 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        d_instantiate(dentry, inode);
        return 0;
 
+fail_gunlock3:
+       gfs2_glock_dq_uninit(ghs + 1);
+       if (ip->i_gl)
+               gfs2_glock_put(ip->i_gl);
+       goto fail_gunlock;
+
 fail_gunlock2:
        gfs2_glock_dq_uninit(ghs + 1);
+fail_free_inode:
+       if (ip->i_gl)
+               gfs2_glock_put(ip->i_gl);
+       gfs2_rs_delete(ip);
+       free_inode_nonrcu(inode);
+       inode = NULL;
 fail_gunlock:
        gfs2_glock_dq_uninit(ghs);
        if (inode && !IS_ERR(inode)) {
@@ -748,7 +772,6 @@ fail_gunlock:
                iput(inode);
        }
 fail:
-       gfs2_rs_delete(dip);
        if (bh)
                brelse(bh);
        return error;
@@ -884,7 +907,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
                if (error)
                        goto out_gunlock;
 
-               error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
+               error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
                if (error)
                        goto out_gunlock_q;
 
@@ -977,7 +1000,6 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
  * gfs2_unlink_inode - Removes an inode from its parent dir and unlinks it
  * @dip: The parent directory
  * @name: The name of the entry in the parent directory
- * @bh: The inode buffer for the inode to be removed
  * @inode: The inode to be removed
  *
  * Called with all the locks and in a transaction. This will only be
@@ -987,8 +1009,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
  */
 
 static int gfs2_unlink_inode(struct gfs2_inode *dip,
-                            const struct dentry *dentry,
-                            struct buffer_head *bh)
+                            const struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -1028,7 +1049,6 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
        struct gfs2_sbd *sdp = GFS2_SB(dir);
        struct inode *inode = dentry->d_inode;
        struct gfs2_inode *ip = GFS2_I(inode);
-       struct buffer_head *bh;
        struct gfs2_holder ghs[3];
        struct gfs2_rgrpd *rgd;
        int error;
@@ -1076,15 +1096,10 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
                goto out_gunlock;
 
        error = gfs2_trans_begin(sdp, 2*RES_DINODE + 3*RES_LEAF + RES_RG_BIT, 0);
-       if (error)
-               goto out_gunlock;
-
-       error = gfs2_meta_inode_buffer(ip, &bh);
        if (error)
                goto out_end_trans;
 
-       error = gfs2_unlink_inode(dip, dentry, bh);
-       brelse(bh);
+       error = gfs2_unlink_inode(dip, dentry);
 
 out_end_trans:
        gfs2_trans_end(sdp);
@@ -1365,7 +1380,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                if (error)
                        goto out_gunlock;
 
-               error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres);
+               error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres, 0);
                if (error)
                        goto out_gunlock_q;
 
@@ -1384,14 +1399,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 
        /* Remove the target file, if it exists */
 
-       if (nip) {
-               struct buffer_head *bh;
-               error = gfs2_meta_inode_buffer(nip, &bh);
-               if (error)
-                       goto out_end_trans;
-               error = gfs2_unlink_inode(ndip, ndentry, bh);
-               brelse(bh);
-       }
+       if (nip)
+               error = gfs2_unlink_inode(ndip, ndentry);
 
        if (dir_rename) {
                error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
index 0fb6539b0c8cc0d64bbce7ff047eae815f1bafe3..8dad6b09371660ff66d5fb17dba7c6e38bbd0d53 100644 (file)
@@ -120,8 +120,8 @@ static void gdlm_ast(void *arg)
        gfs2_update_reply_times(gl);
        BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
 
-       if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID)
-               memset(gl->gl_lvb, 0, GDLM_LVB_SIZE);
+       if ((gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID) && gl->gl_lksb.sb_lvbptr)
+               memset(gl->gl_lksb.sb_lvbptr, 0, GDLM_LVB_SIZE);
 
        switch (gl->gl_lksb.sb_status) {
        case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
@@ -203,8 +203,10 @@ static int make_mode(const unsigned int lmstate)
 static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
                      const int req)
 {
-       u32 lkf = DLM_LKF_VALBLK;
-       u32 lkid = gl->gl_lksb.sb_lkid;
+       u32 lkf = 0;
+
+       if (gl->gl_lksb.sb_lvbptr)
+               lkf |= DLM_LKF_VALBLK;
 
        if (gfs_flags & LM_FLAG_TRY)
                lkf |= DLM_LKF_NOQUEUE;
@@ -228,7 +230,7 @@ static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
                        BUG();
        }
 
-       if (lkid != 0) {
+       if (gl->gl_lksb.sb_lkid != 0) {
                lkf |= DLM_LKF_CONVERT;
                if (test_bit(GLF_BLOCKING, &gl->gl_flags))
                        lkf |= DLM_LKF_QUECVT;
@@ -289,6 +291,14 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
        gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
        gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
        gfs2_update_request_times(gl);
+
+       /* don't want to skip dlm_unlock writing the lvb when lock is ex */
+       if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
+           gl->gl_lksb.sb_lvbptr && (gl->gl_state != LM_ST_EXCLUSIVE)) {
+               gfs2_glock_free(gl);
+               return;
+       }
+
        error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
                           NULL, gl);
        if (error) {
index e443966c810697e50f71b37afb807db62828335f..0e3554edb8f25d2f5d82932294eca6b5b4d54020 100644 (file)
@@ -278,6 +278,9 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
        sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
                                sizeof(struct gfs2_meta_header)) /
                                sizeof(struct gfs2_quota_change);
+       sdp->sd_blocks_per_bitmap = (sdp->sd_sb.sb_bsize -
+                                    sizeof(struct gfs2_meta_header))
+               * GFS2_NBBY; /* not the rgrp bitmap, subsequent bitmaps only */
 
        /* Compute maximum reservation required to add a entry to a directory */
 
index c5af8e18f27af8a3b0c899ce1fe5404fede93831..ae55e248c3b75054bd2ade8438eb9cd09f88ec5c 100644 (file)
@@ -816,7 +816,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
        blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3;
 
        reserved = 1 + (nalloc * (data_blocks + ind_blocks));
-       error = gfs2_inplace_reserve(ip, reserved);
+       error = gfs2_inplace_reserve(ip, reserved, 0);
        if (error)
                goto out_alloc;
 
@@ -869,7 +869,7 @@ static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
        if (error < 0)
                return error;
 
-       qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
+       qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
        qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC);
        qlvb->__pad = 0;
        qlvb->qb_limit = q.qu_limit;
@@ -893,7 +893,7 @@ restart:
        if (error)
                return error;
 
-       qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
+       qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
 
        if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) {
                gfs2_glock_dq_uninit(q_gh);
@@ -1506,7 +1506,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
        if (error)
                goto out;
 
-       qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
+       qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
        fdq->d_version = FS_DQUOT_VERSION;
        fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
        fdq->d_id = from_kqid(&init_user_ns, qid);
@@ -1605,7 +1605,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
                gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
                                       &data_blocks, &ind_blocks);
                blocks = 1 + data_blocks + ind_blocks;
-               error = gfs2_inplace_reserve(ip, blocks);
+               error = gfs2_inplace_reserve(ip, blocks, 0);
                if (error)
                        goto out_i;
                blocks += gfs2_rg_blocks(ip, blocks);
index 38fe18f2f055af2e5e842573a475e7b6836bb940..37ee061d899e81a8eb45f5bc64382634e573c108 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/prefetch.h>
 #include <linux/blkdev.h>
 #include <linux/rbtree.h>
+#include <linux/random.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -251,22 +252,25 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
 static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
 {
        u64 rblock = block - rbm->rgd->rd_data0;
-       u32 goal = (u32)rblock;
-       int x;
+       u32 x;
 
        if (WARN_ON_ONCE(rblock > UINT_MAX))
                return -EINVAL;
        if (block >= rbm->rgd->rd_data0 + rbm->rgd->rd_data)
                return -E2BIG;
 
-       for (x = 0; x < rbm->rgd->rd_length; x++) {
-               rbm->bi = rbm->rgd->rd_bits + x;
-               if (goal < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY) {
-                       rbm->offset = goal - (rbm->bi->bi_start * GFS2_NBBY);
-                       break;
-               }
-       }
+       rbm->bi = rbm->rgd->rd_bits;
+       rbm->offset = (u32)(rblock);
+       /* Check if the block is within the first block */
+       if (rbm->offset < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY)
+               return 0;
 
+       /* Adjust for the size diff between gfs2_meta_header and gfs2_rgrp */
+       rbm->offset += (sizeof(struct gfs2_rgrp) -
+                       sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
+       x = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
+       rbm->offset -= x * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
+       rbm->bi += x;
        return 0;
 }
 
@@ -875,7 +879,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
                goto fail;
 
        rgd->rd_gl->gl_object = rgd;
-       rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lvb;
+       rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr;
        rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
        if (rgd->rd_data > sdp->sd_max_rg_data)
                sdp->sd_max_rg_data = rgd->rd_data;
@@ -1678,13 +1682,105 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
        return;
 }
 
+/**
+ * gfs2_rgrp_congested - Use stats to figure out whether an rgrp is congested
+ * @rgd: The rgrp in question
+ * @loops: An indication of how picky we can be (0=very, 1=less so)
+ *
+ * This function uses the recently added glock statistics in order to
+ * figure out whether a parciular resource group is suffering from
+ * contention from multiple nodes. This is done purely on the basis
+ * of timings, since this is the only data we have to work with and
+ * our aim here is to reject a resource group which is highly contended
+ * but (very important) not to do this too often in order to ensure that
+ * we do not land up introducing fragmentation by changing resource
+ * groups when not actually required.
+ *
+ * The calculation is fairly simple, we want to know whether the SRTTB
+ * (i.e. smoothed round trip time for blocking operations) to acquire
+ * the lock for this rgrp's glock is significantly greater than the
+ * time taken for resource groups on average. We introduce a margin in
+ * the form of the variable @var which is computed as the sum of the two
+ * respective variences, and multiplied by a factor depending on @loops
+ * and whether we have a lot of data to base the decision on. This is
+ * then tested against the square difference of the means in order to
+ * decide whether the result is statistically significant or not.
+ *
+ * Returns: A boolean verdict on the congestion status
+ */
+
+static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
+{
+       const struct gfs2_glock *gl = rgd->rd_gl;
+       const struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct gfs2_lkstats *st;
+       s64 r_dcount, l_dcount;
+       s64 r_srttb, l_srttb;
+       s64 srttb_diff;
+       s64 sqr_diff;
+       s64 var;
+
+       preempt_disable();
+       st = &this_cpu_ptr(sdp->sd_lkstats)->lkstats[LM_TYPE_RGRP];
+       r_srttb = st->stats[GFS2_LKS_SRTTB];
+       r_dcount = st->stats[GFS2_LKS_DCOUNT];
+       var = st->stats[GFS2_LKS_SRTTVARB] +
+             gl->gl_stats.stats[GFS2_LKS_SRTTVARB];
+       preempt_enable();
+
+       l_srttb = gl->gl_stats.stats[GFS2_LKS_SRTTB];
+       l_dcount = gl->gl_stats.stats[GFS2_LKS_DCOUNT];
+
+       if ((l_dcount < 1) || (r_dcount < 1) || (r_srttb == 0))
+               return false;
+
+       srttb_diff = r_srttb - l_srttb;
+       sqr_diff = srttb_diff * srttb_diff;
+
+       var *= 2;
+       if (l_dcount < 8 || r_dcount < 8)
+               var *= 2;
+       if (loops == 1)
+               var *= 2;
+
+       return ((srttb_diff < 0) && (sqr_diff > var));
+}
+
+/**
+ * gfs2_rgrp_used_recently
+ * @rs: The block reservation with the rgrp to test
+ * @msecs: The time limit in milliseconds
+ *
+ * Returns: True if the rgrp glock has been used within the time limit
+ */
+static bool gfs2_rgrp_used_recently(const struct gfs2_blkreserv *rs,
+                                   u64 msecs)
+{
+       u64 tdiff;
+
+       tdiff = ktime_to_ns(ktime_sub(ktime_get_real(),
+                            rs->rs_rbm.rgd->rd_gl->gl_dstamp));
+
+       return tdiff > (msecs * 1000 * 1000);
+}
+
+static u32 gfs2_orlov_skip(const struct gfs2_inode *ip)
+{
+       const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       u32 skip;
+
+       get_random_bytes(&skip, sizeof(skip));
+       return skip % sdp->sd_rgrps;
+}
+
 static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin)
 {
        struct gfs2_rgrpd *rgd = *pos;
+       struct gfs2_sbd *sdp = rgd->rd_sbd;
 
        rgd = gfs2_rgrpd_get_next(rgd);
        if (rgd == NULL)
-               rgd = gfs2_rgrpd_get_next(NULL);
+               rgd = gfs2_rgrpd_get_first(sdp);
        *pos = rgd;
        if (rgd != begin) /* If we didn't wrap */
                return true;
@@ -1699,14 +1795,15 @@ static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *b
  * Returns: errno
  */
 
-int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
+int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_rgrpd *begin = NULL;
        struct gfs2_blkreserv *rs = ip->i_res;
-       int error = 0, rg_locked, flags = LM_FLAG_TRY;
+       int error = 0, rg_locked, flags = 0;
        u64 last_unlinked = NO_BLOCK;
        int loops = 0;
+       u32 skip = 0;
 
        if (sdp->sd_args.ar_rgrplvb)
                flags |= GL_SKIP;
@@ -1720,6 +1817,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
        } else {
                rs->rs_rbm.rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1);
        }
+       if (S_ISDIR(ip->i_inode.i_mode) && (aflags & GFS2_AF_ORLOV))
+               skip = gfs2_orlov_skip(ip);
        if (rs->rs_rbm.rgd == NULL)
                return -EBADSLT;
 
@@ -1728,13 +1827,20 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
 
                if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) {
                        rg_locked = 0;
+                       if (skip && skip--)
+                               goto next_rgrp;
+                       if (!gfs2_rs_active(rs) && (loops < 2) &&
+                            gfs2_rgrp_used_recently(rs, 1000) &&
+                            gfs2_rgrp_congested(rs->rs_rbm.rgd, loops))
+                               goto next_rgrp;
                        error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl,
                                                   LM_ST_EXCLUSIVE, flags,
                                                   &rs->rs_rgd_gh);
-                       if (error == GLR_TRYFAILED)
-                               goto next_rgrp;
                        if (unlikely(error))
                                return error;
+                       if (!gfs2_rs_active(rs) && (loops < 2) &&
+                           gfs2_rgrp_congested(rs->rs_rbm.rgd, loops))
+                               goto skip_rgrp;
                        if (sdp->sd_args.ar_rgrplvb) {
                                error = update_rgrp_lvb(rs->rs_rbm.rgd);
                                if (unlikely(error)) {
@@ -1781,12 +1887,13 @@ next_rgrp:
                /* Find the next rgrp, and continue looking */
                if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin))
                        continue;
+               if (skip)
+                       continue;
 
                /* If we've scanned all the rgrps, but found no free blocks
                 * then this checks for some less likely conditions before
                 * trying again.
                 */
-               flags &= ~LM_FLAG_TRY;
                loops++;
                /* Check that fs hasn't grown if writing to rindex */
                if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) {
index 24077958dcf6a072bd9baf0f117b8060ba36eaee..842185853f6b2a990f37359590afebd6e61ddc2c 100644 (file)
@@ -39,7 +39,8 @@ extern void gfs2_rgrp_go_unlock(struct gfs2_holder *gh);
 
 extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
 
-extern int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested);
+#define GFS2_AF_ORLOV 1
+extern int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 flags);
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
 extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
index bbdc78af60caa050d2a789ab7722f396b5cf196e..2ee13e841e9f6268f2be1efd4a6920eb3972ab72 100644 (file)
@@ -486,7 +486,7 @@ TRACE_EVENT(gfs2_block_alloc,
        ),
 
        TP_fast_assign(
-               __entry->dev            = ip->i_gl->gl_sbd->sd_vfs->s_dev;
+               __entry->dev            = rgd->rd_gl->gl_sbd->sd_vfs->s_dev;
                __entry->start          = block;
                __entry->inum           = ip->i_no_addr;
                __entry->len            = len;
index db330e5518cdafe8aacef6ee3ae00f1d912b5b51..76c144b3c9bbdc4fe98d018ebf7303cebf423816 100644 (file)
@@ -734,7 +734,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
        if (error)
                return error;
 
-       error = gfs2_inplace_reserve(ip, blks);
+       error = gfs2_inplace_reserve(ip, blks, 0);
        if (error)
                goto out_gunlock_q;
 
index 4a55f35a6cedb81cb0f7ce81893d57fa10d0a4b8..78bde32ea9518d3fffe72d24864b6959bb369781 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * hugetlbpage-backed filesystem.  Based on ramfs.
  *
- * William Irwin, 2002
+ * Nadia Yvette Chambers, 2002
  *
  * Copyright (C) 2002 Linus Torvalds.
  */
index 7f5120bf0ec29cff214cc8ccb2a23bfb02ad3419..071d6905f0dd92c57dc2a8e6a5e62f81993ca5e8 100644 (file)
@@ -1259,7 +1259,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
                goto not_jbd;
        }
 
-       /* keep track of wether or not this transaction modified us */
+       /* keep track of whether or not this transaction modified us */
        was_modified = jh->b_modified;
 
        /*
index a74ba46595499690186dc2a46eff5160550032ae..d8da40e99d84b7f3de4471603dd51dc7e26b7f1b 100644 (file)
@@ -1261,7 +1261,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
                goto not_jbd;
        }
 
-       /* keep track of wether or not this transaction modified us */
+       /* keep track of whether or not this transaction modified us */
        was_modified = jh->b_modified;
 
        /*
index adb90116d36b1b2b0f0328a58cae9cdf0dde1794..af49e2d6941a7c2f8120ee3ca99095e0bb2ea767 100644 (file)
@@ -33,7 +33,7 @@
  * are being written out - and waiting for GC to make progress, naturally.
  *
  * So we cannot just call iget() or some variant of it, but first have to check
- * wether the inode in question might be in I_FREEING state.  Therefore we
+ * whether the inode in question might be in I_FREEING state.  Therefore we
  * maintain our own per-sb list of "almost deleted" inodes and check against
  * that list first.  Normally this should be at most 1-2 entries long.
  *
index be20a7e171a0f18ebe24d32d0ebed2b4d71a6040..63d14a99483d5d39ec58bfd8419c53173721da99 100644 (file)
@@ -89,7 +89,7 @@ static int ncp_file_mmap_fault(struct vm_area_struct *area,
        /*
         * If I understand ncp_read_kernel() properly, the above always
         * fetches from the network, here the analogue of disk.
-        * -- wli
+        * -- nyc
         */
        count_vm_event(PGMAJFAULT);
        mem_cgroup_count_vm_event(area->vm_mm, PGMAJFAULT);
index 7dceff005a6745eb353187c93b6e11fa3b326cdd..e5f911bd80d2488689966cfd9cddf704fae07aa2 100644 (file)
@@ -4,7 +4,7 @@ config FANOTIFY
        select ANON_INODES
        default n
        ---help---
-          Say Y here to enable fanotify suport.  fanotify is a file access
+          Say Y here to enable fanotify support.  fanotify is a file access
           notification system which differs from inotify in that it sends
           an open file descriptor to the userspace listener along with
           the event.
index c887b1378f7ed5087eca0df3ca745e15d9a88cc6..48cb994e4922cf0d32fb3f61ad1eb05291231a7c 100644 (file)
@@ -18,7 +18,7 @@
 
 /*
  * Basic idea behind the notification queue: An fsnotify group (like inotify)
- * sends the userspace notification about events asyncronously some time after
+ * sends the userspace notification about events asynchronously some time after
  * the event happened.  When inotify gets an event it will need to add that
  * event to the group notify queue.  Since a single event might need to be on
  * multiple group's notification queues we can't add the event directly to each
index 86c67eee439fbbc4770591e0b82cb3882a168317..e96d4f18ca3a93e5dd62e1be430028bc3413d250 100644 (file)
@@ -249,7 +249,7 @@ static int kcore_update_ram(void)
        /* Not inialized....update now */
        /* find out "max pfn" */
        end_pfn = 0;
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                unsigned long node_end;
                node_end  = NODE_DATA(nid)->node_start_pfn +
                        NODE_DATA(nid)->node_spanned_pages;
index 90c63f9392a595318c5d1e03e1d69305bf9413fa..48775628abbfe43b54d0505d7afb9c3d1c481ba9 100644 (file)
@@ -643,7 +643,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
        spinlock_t *ptl;
        struct page *page;
 
-       split_huge_page_pmd(walk->mm, pmd);
+       split_huge_page_pmd(vma, addr, pmd);
        if (pmd_trans_unstable(pmd))
                return 0;
 
@@ -1126,7 +1126,7 @@ static struct page *can_gather_numa_stats(pte_t pte, struct vm_area_struct *vma,
                return NULL;
 
        nid = page_to_nid(page);
-       if (!node_isset(nid, node_states[N_HIGH_MEMORY]))
+       if (!node_isset(nid, node_states[N_MEMORY]))
                return NULL;
 
        return page;
@@ -1279,7 +1279,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        if (md->writeback)
                seq_printf(m, " writeback=%lu", md->writeback);
 
-       for_each_node_state(n, N_HIGH_MEMORY)
+       for_each_node_state(n, N_MEMORY)
                if (md->node[n])
                        seq_printf(m, " N%d=%lu", n, md->node[n]);
 out:
index 2d57e1ac0115ae12357e108c22ef8d783637ab87..43b12807a51d71ad39c41e55e8ac83473e5ac7a6 100644 (file)
@@ -28,7 +28,9 @@
 #include "internal.h"
 
 static void notrace pstore_ftrace_call(unsigned long ip,
-                                      unsigned long parent_ip)
+                                      unsigned long parent_ip,
+                                      struct ftrace_ops *op,
+                                      struct pt_regs *regs)
 {
        unsigned long flags;
        struct pstore_ftrace_record rec = {};
index 2bfa36e0ffe8d464dde8b74c37c91c46d16d49ae..f883e7e74305c9935b2f26e27e92f01c7e138aa9 100644 (file)
@@ -188,7 +188,7 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
                                            struct pstore_info *psi)
 {
        struct ramoops_context *cxt = psi->data;
-       struct persistent_ram_zone *prz = cxt->przs[cxt->dump_write_cnt];
+       struct persistent_ram_zone *prz;
        size_t hlen;
 
        if (type == PSTORE_TYPE_CONSOLE) {
@@ -225,6 +225,11 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
        if (part != 1)
                return -ENOSPC;
 
+       if (!cxt->przs)
+               return -ENOSPC;
+
+       prz = cxt->przs[cxt->dump_write_cnt];
+
        hlen = ramoops_write_kmsg_hdr(prz);
        if (size + hlen > prz->buffer_size)
                size = prz->buffer_size - hlen;
@@ -286,8 +291,9 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
        kfree(cxt->przs);
 }
 
-static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
-                             phys_addr_t *paddr, size_t dump_mem_sz)
+static int __devinit ramoops_init_przs(struct device *dev,
+                                      struct ramoops_context *cxt,
+                                      phys_addr_t *paddr, size_t dump_mem_sz)
 {
        int err = -ENOMEM;
        int i;
@@ -295,6 +301,11 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
        if (!cxt->record_size)
                return 0;
 
+       if (*paddr + dump_mem_sz - cxt->phys_addr > cxt->size) {
+               dev_err(dev, "no room for dumps\n");
+               return -ENOMEM;
+       }
+
        cxt->max_dump_cnt = dump_mem_sz / cxt->record_size;
        if (!cxt->max_dump_cnt)
                return -ENOMEM;
@@ -325,15 +336,20 @@ fail_prz:
        return err;
 }
 
-static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
-                           struct persistent_ram_zone **prz,
-                           phys_addr_t *paddr, size_t sz, u32 sig)
+static int __devinit ramoops_init_prz(struct device *dev,
+                                     struct ramoops_context *cxt,
+                                     struct persistent_ram_zone **prz,
+                                     phys_addr_t *paddr, size_t sz, u32 sig)
 {
        if (!sz)
                return 0;
 
-       if (*paddr + sz > *paddr + cxt->size)
+       if (*paddr + sz - cxt->phys_addr > cxt->size) {
+               dev_err(dev, "no room for mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
+                       sz, (unsigned long long)*paddr,
+                       cxt->size, (unsigned long long)cxt->phys_addr);
                return -ENOMEM;
+       }
 
        *prz = persistent_ram_new(*paddr, sz, sig, cxt->ecc_size);
        if (IS_ERR(*prz)) {
@@ -373,10 +389,14 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
                goto fail_out;
        }
 
-       pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
-       pdata->record_size = rounddown_pow_of_two(pdata->record_size);
-       pdata->console_size = rounddown_pow_of_two(pdata->console_size);
-       pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
+       if (!is_power_of_2(pdata->mem_size))
+               pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
+       if (!is_power_of_2(pdata->record_size))
+               pdata->record_size = rounddown_pow_of_two(pdata->record_size);
+       if (!is_power_of_2(pdata->console_size))
+               pdata->console_size = rounddown_pow_of_two(pdata->console_size);
+       if (!is_power_of_2(pdata->ftrace_size))
+               pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
 
        cxt->dump_read_cnt = 0;
        cxt->size = pdata->mem_size;
index bb145e4b935e79760146f17d5f6bd4c70843278d..8b1d7a6a9695c44582890dc2a89acdd0e709e7b4 100644 (file)
@@ -92,8 +92,8 @@ int acpi_pci_link_free_irq(acpi_handle handle);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus);
-void acpi_pci_irq_del_prt(struct pci_bus *bus);
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
+void acpi_pci_irq_del_prt(int segment, int bus);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
index 448303bdb85fd8009fdb6a6367fa9f2ed69b80ba..9e0ebe0512435f5ca8045f9f42f47460b8b95ac0 100644 (file)
@@ -83,19 +83,25 @@ static inline void __raw_writel(u32 b, volatile void __iomem *addr)
 #define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)
 
 #ifdef CONFIG_64BIT
+#ifndef __raw_readq
 static inline u64 __raw_readq(const volatile void __iomem *addr)
 {
        return *(const volatile u64 __force *) addr;
 }
+#endif
+
 #define readq(addr) __le64_to_cpu(__raw_readq(addr))
 
+#ifndef __raw_writeq
 static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
 {
        *(volatile u64 __force *) addr = b;
 }
-#define writeq(b,addr) __raw_writeq(__cpu_to_le64(b),addr)
 #endif
 
+#define writeq(b, addr) __raw_writeq(__cpu_to_le64(b), addr)
+#endif /* CONFIG_64BIT */
+
 #ifndef PCI_IOBASE
 #define PCI_IOBASE ((void __iomem *) 0)
 #endif
@@ -286,15 +292,20 @@ static inline void writesb(const void __iomem *addr, const void *buf, int len)
 
 #ifndef CONFIG_GENERIC_IOMAP
 struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+
+#ifndef pci_iounmap
 static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
 {
 }
+#endif
 #endif /* CONFIG_GENERIC_IOMAP */
 
 /*
  * Change virtual addresses to physical addresses and vv.
  * These are pretty trivial
  */
+#ifndef virt_to_phys
 static inline unsigned long virt_to_phys(volatile void *address)
 {
        return __pa((unsigned long)address);
@@ -304,6 +315,7 @@ static inline void *phys_to_virt(unsigned long address)
 {
        return __va(address);
 }
+#endif
 
 /*
  * Change "struct page" to physical address.
@@ -363,9 +375,16 @@ static inline void *bus_to_virt(unsigned long address)
 }
 #endif
 
+#ifndef memset_io
 #define memset_io(a, b, c)     memset(__io_virt(a), (b), (c))
+#endif
+
+#ifndef memcpy_fromio
 #define memcpy_fromio(a, b, c) memcpy((a), __io_virt(b), (c))
+#endif
+#ifndef memcpy_toio
 #define memcpy_toio(a, b, c)   memcpy(__io_virt(a), (b), (c))
+#endif
 
 #endif /* __KERNEL__ */
 
index b36ce40bd1c6c929e8b408044440df4ce5931825..284e80831d2c4beff475ea7ab84269e7d8b028eb 100644 (file)
@@ -449,6 +449,32 @@ extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
                        unsigned long size);
 #endif
 
+#ifdef __HAVE_COLOR_ZERO_PAGE
+static inline int is_zero_pfn(unsigned long pfn)
+{
+       extern unsigned long zero_pfn;
+       unsigned long offset_from_zero_pfn = pfn - zero_pfn;
+       return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
+}
+
+static inline unsigned long my_zero_pfn(unsigned long addr)
+{
+       return page_to_pfn(ZERO_PAGE(addr));
+}
+#else
+static inline int is_zero_pfn(unsigned long pfn)
+{
+       extern unsigned long zero_pfn;
+       return pfn == zero_pfn;
+}
+
+static inline unsigned long my_zero_pfn(unsigned long addr)
+{
+       extern unsigned long zero_pfn;
+       return zero_pfn;
+}
+#endif
+
 #ifdef CONFIG_MMU
 
 #ifndef CONFIG_TRANSPARENT_HUGEPAGE
index 586183a0406e8d90b09e8226156fa7888fdb908e..14fbf39d6380dd4f24c5319564e778400989199c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <crypto/cast_common.h>
 
 #define CAST5_BLOCK_SIZE 8
 #define CAST5_MIN_KEY_SIZE 5
@@ -19,9 +20,4 @@ int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen);
 void __cast5_encrypt(struct cast5_ctx *ctx, u8 *dst, const u8 *src);
 void __cast5_decrypt(struct cast5_ctx *ctx, u8 *dst, const u8 *src);
 
-extern const u32 cast5_s1[256];
-extern const u32 cast5_s2[256];
-extern const u32 cast5_s3[256];
-extern const u32 cast5_s4[256];
-
 #endif
index 157af6f342c80229d008c345ac2a5dfc640de587..32b60eb8bd24ee67996674440346b7c9e7e9352c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <crypto/cast_common.h>
 
 #define CAST6_BLOCK_SIZE 16
 #define CAST6_MIN_KEY_SIZE 16
@@ -20,9 +21,4 @@ int cast6_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen);
 void __cast6_encrypt(struct cast6_ctx *ctx, u8 *dst, const u8 *src);
 void __cast6_decrypt(struct cast6_ctx *ctx, u8 *dst, const u8 *src);
 
-extern const u32 cast6_s1[256];
-extern const u32 cast6_s2[256];
-extern const u32 cast6_s3[256];
-extern const u32 cast6_s4[256];
-
 #endif
diff --git a/include/crypto/cast_common.h b/include/crypto/cast_common.h
new file mode 100644 (file)
index 0000000..b7df35c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _CRYPTO_CAST_COMMON_H
+#define _CRYPTO_CAST_COMMON_H
+
+extern const u32 cast_s1[256];
+extern const u32 cast_s2[256];
+extern const u32 cast_s3[256];
+extern const u32 cast_s4[256];
+
+#endif
index c4467c55df1e56a1cf22cf70a82dac467db1c711..6b700c7b2fe1cba3cd054a200eac450ac4bde7be 100644 (file)
@@ -56,6 +56,8 @@ typedef u64 vmac_t;
 struct vmac_ctx_t {
        struct crypto_cipher *child;
        struct vmac_ctx __vmac_ctx;
+       u8 partial[VMAC_NHBYTES];       /* partial block */
+       int partial_size;               /* size of the partial block */
 };
 
 #endif /* __CRYPTO_VMAC_H */
index c33fa3ce9b7c3bb61745b0d520e54a6c5666f6e5..3994d7790b2309d0ff8bc7ba8f518a75fe4ffd7a 100644 (file)
@@ -78,6 +78,14 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 
 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void acpi_initrd_override(void *data, size_t size);
+#else
+static inline void acpi_initrd_override(void *data, size_t size)
+{
+}
+#endif
+
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);
@@ -479,6 +487,14 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 
 acpi_status acpi_os_prepare_sleep(u8 sleep_state,
                                  u32 pm1a_control, u32 pm1b_control);
+#ifdef CONFIG_X86
+void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
+#else
+static inline void arch_reserve_mem_area(acpi_physical_address addr,
+                                         size_t size)
+{
+}
+#endif /* CONFIG_X86 */
 #else
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
index b856a2a590d96c8b376b3c2ebcdb3f0fbc6be022..fe9989636b6252536b6abf7042e598c7d6da39fd 100644 (file)
@@ -22,8 +22,6 @@ extern int __devinit __pata_platform_probe(struct device *dev,
                                           unsigned int ioport_shift,
                                           int __pio_mask);
 
-extern int __devexit __pata_platform_remove(struct device *dev);
-
 /*
  * Marvell SATA private data
  */
index 4eb31752e2b77592e8a2fdbf3fde779d4851504d..deb0ae58b99bb3724bee4376b0a376b563c29cff 100644 (file)
@@ -5,10 +5,16 @@
 #include <linux/list.h>
 #include <linux/io.h>
 
+struct atmel_ssc_platform_data {
+       int                     use_dma;
+};
+
 struct ssc_device {
        struct list_head        list;
+       resource_size_t         phybase;
        void __iomem            *regs;
        struct platform_device  *pdev;
+       struct atmel_ssc_platform_data *pdata;
        struct clk              *clk;
        int                     user;
        int                     irq;
index e51359180b6f7c6bdd85bdd33c86eb6792301ca7..9a0e3fa3ca9539123f1a5494cb0007c17b4c9a26 100644 (file)
@@ -2,6 +2,7 @@
 #define LINUX_BCMA_DRIVER_CC_H_
 
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 
 /** ChipCommon core registers. **/
 #define BCMA_CC_ID                     0x0000
@@ -574,6 +575,12 @@ struct bcma_drv_cc {
 #endif /* CONFIG_BCMA_DRIVER_MIPS */
        u32 ticks_per_ms;
        struct platform_device *watchdog;
+
+       /* Lock for GPIO register access. */
+       spinlock_t gpio_lock;
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+       struct gpio_chip gpio;
+#endif
 };
 
 /* Register access */
@@ -610,6 +617,8 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
 u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
 u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
 u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
+u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value);
+u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value);
 
 /* PMU support */
 extern void bcma_pmu_init(struct bcma_drv_cc *cc);
index 7b74452c531769e0e032ad8eb05cda3bf4117fa7..3f778c27f8259aa91452fa85895890bcc7007f4f 100644 (file)
@@ -137,9 +137,6 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
 #define alloc_bootmem_low_pages_node(pgdat, x) \
        __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0)
 
-extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
-                                  int flags);
-
 #ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
 extern void *alloc_remap(int nid, unsigned long size);
 #else
diff --git a/include/linux/clk/mvebu.h b/include/linux/clk/mvebu.h
new file mode 100644 (file)
index 0000000..8c4ae71
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __CLK_MVEBU_H_
+#define __CLK_MVEBU_H_
+
+void __init mvebu_clocks_init(void);
+
+#endif
index 838320fc3d1d33d9823ab71df011c59f75303e4b..8c8a60d294079af6f7488536cf33e8cbb070d58e 100644 (file)
@@ -144,7 +144,7 @@ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
        return node_possible_map;
 }
 
-#define cpuset_current_mems_allowed (node_states[N_HIGH_MEMORY])
+#define cpuset_current_mems_allowed (node_states[N_MEMORY])
 static inline void cpuset_init_current_mems_allowed(void) {}
 
 static inline int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
index 05292e488346697a40614b356eef82e2425f423b..43dcda937ddf82fcb8661372a68899953209e3f2 100644 (file)
@@ -498,6 +498,10 @@ ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
                        char *buf);
 ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
                         const char *buf, size_t count);
+ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count);
 
 #define DEVICE_ATTR(_name, _mode, _show, _store) \
        struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
@@ -507,6 +511,9 @@ ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
 #define DEVICE_INT_ATTR(_name, _mode, _var) \
        struct dev_ext_attribute dev_attr_##_name = \
                { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }
+#define DEVICE_BOOL_ATTR(_name, _mode, _var) \
+       struct dev_ext_attribute dev_attr_##_name = \
+               { __ATTR(_name, _mode, device_show_bool, device_store_bool), &(_var) }
 #define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
        struct device_attribute dev_attr_##_name =              \
                __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
index 1d47dcce11e1011e8a39a96b1c5fa10d0eb7bbca..d02da2c6fc1a615a1d2c3223a3c19c4686fea3bd 100644 (file)
@@ -98,7 +98,7 @@ int dlm_release_lockspace(dlm_lockspace_t *lockspace, int force);
 /*
  * dlm_lock
  *
- * Make an asyncronous request to acquire or convert a lock on a named
+ * Make an asynchronous request to acquire or convert a lock on a named
  * resource.
  *
  * lockspace: context for the request
diff --git a/include/linux/dvb/Kbuild b/include/linux/dvb/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
deleted file mode 100644 (file)
index 0be6d8f..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * dmx.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                  & Ralph  Metzler <ralph@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- */
-#ifndef _DVBDMX_H_
-#define _DVBDMX_H_
-
-#include <linux/time.h>
-#include <uapi/linux/dvb/dmx.h>
-
-#endif /*_DVBDMX_H_*/
diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h
deleted file mode 100644 (file)
index 85c20d9..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * video.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                  & Ralph  Metzler <ralph@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- */
-#ifndef _DVBVIDEO_H_
-#define _DVBVIDEO_H_
-
-#include <linux/compiler.h>
-#include <uapi/linux/dvb/video.h>
-
-#endif /*_DVBVIDEO_H_*/
diff --git a/include/linux/earlycpio.h b/include/linux/earlycpio.h
new file mode 100644 (file)
index 0000000..111f46d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _LINUX_EARLYCPIO_H
+#define _LINUX_EARLYCPIO_H
+
+#include <linux/types.h>
+
+#define MAX_CPIO_FILE_NAME 18
+
+struct cpio_data {
+       void *data;
+       size_t size;
+       char name[MAX_CPIO_FILE_NAME];
+};
+
+struct cpio_data find_cpio_data(const char *path, void *data, size_t len,
+                               long *offset);
+
+#endif /* _LINUX_EARLYCPIO_H */
index c47ec36f3f39cc71e53420e9e9433b181780f680..02a69418be1850bd7ebe71ea891436e96cc9da12 100644 (file)
 #define EFI_UNSUPPORTED                ( 3 | (1UL << (BITS_PER_LONG-1)))
 #define EFI_BAD_BUFFER_SIZE     ( 4 | (1UL << (BITS_PER_LONG-1)))
 #define EFI_BUFFER_TOO_SMALL   ( 5 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_READY          ( 6 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_DEVICE_ERROR       ( 7 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_WRITE_PROTECTED    ( 8 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_OUT_OF_RESOURCES   ( 9 | (1UL << (BITS_PER_LONG-1)))
 #define EFI_NOT_FOUND          (14 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))
 
 typedef unsigned long efi_status_t;
 typedef u8 efi_bool_t;
@@ -196,6 +201,77 @@ typedef struct {
        void *create_event_ex;
 } efi_boot_services_t;
 
+typedef enum {
+       EfiPciIoWidthUint8,
+       EfiPciIoWidthUint16,
+       EfiPciIoWidthUint32,
+       EfiPciIoWidthUint64,
+       EfiPciIoWidthFifoUint8,
+       EfiPciIoWidthFifoUint16,
+       EfiPciIoWidthFifoUint32,
+       EfiPciIoWidthFifoUint64,
+       EfiPciIoWidthFillUint8,
+       EfiPciIoWidthFillUint16,
+       EfiPciIoWidthFillUint32,
+       EfiPciIoWidthFillUint64,
+       EfiPciIoWidthMaximum
+} EFI_PCI_IO_PROTOCOL_WIDTH;
+
+typedef enum {
+       EfiPciIoAttributeOperationGet,
+       EfiPciIoAttributeOperationSet,
+       EfiPciIoAttributeOperationEnable,
+       EfiPciIoAttributeOperationDisable,
+       EfiPciIoAttributeOperationSupported,
+    EfiPciIoAttributeOperationMaximum
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
+
+
+typedef struct {
+       void *read;
+       void *write;
+} efi_pci_io_protocol_access_t;
+
+typedef struct {
+       void *poll_mem;
+       void *poll_io;
+       efi_pci_io_protocol_access_t mem;
+       efi_pci_io_protocol_access_t io;
+       efi_pci_io_protocol_access_t pci;
+       void *copy_mem;
+       void *map;
+       void *unmap;
+       void *allocate_buffer;
+       void *free_buffer;
+       void *flush;
+       void *get_location;
+       void *attributes;
+       void *get_bar_attributes;
+       void *set_bar_attributes;
+       uint64_t romsize;
+       void *romimage;
+} efi_pci_io_protocol;
+
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
+
 /*
  * Types and defines for EFI ResetSystem
  */
@@ -511,8 +587,6 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
 extern int __init efi_uart_console_only (void);
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
                struct resource *data_resource, struct resource *bss_resource);
-extern unsigned long efi_get_time(void);
-extern int efi_set_rtc_mmss(unsigned long nowtime);
 extern void efi_reserve_boot_services(void);
 extern struct efi_memory_map memmap;
 
@@ -658,6 +732,7 @@ struct efivars {
        spinlock_t lock;
        struct list_head list;
        struct kset *kset;
+       struct kobject *kobject;
        struct bin_attribute *new_var, *del_var;
        const struct efivar_operations *ops;
        struct efivar_entry *walk_entry;
index 11c16a1fb9e3d8316ac4098ca450af8089dffdb3..a1e8277120c71b93b4b85db620dcee91925ef333 100644 (file)
@@ -46,6 +46,15 @@ struct aoi_display_offset {
 #define MFB_SET_PIXFMT         _IOW('M', 8, __u32)
 #define MFB_GET_PIXFMT         _IOR('M', 8, __u32)
 
+/*
+ * The MPC5121 BSP comes with a gamma_set utility that initializes the
+ * gamma table.  Unfortunately, it uses bad values for the IOCTL commands,
+ * but there's nothing we can do about it now.  These ioctls are only
+ * supported on the MPC5121.
+ */
+#define MFB_SET_GAMMA          _IOW('M', 1, __u8)
+#define MFB_GET_GAMMA          _IOR('M', 1, __u8)
+
 /*
  * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the
  * wrong value for 'size' field of the ioctl.  The current macros above use the
index 31e8041274f6ce32fec6b69cf1197f5c5f31b74b..f74856e17e488deb9698f610511fcfed44f35ba3 100644 (file)
@@ -34,6 +34,7 @@ struct vm_area_struct;
 #define ___GFP_NO_KSWAPD       0x400000u
 #define ___GFP_OTHER_NODE      0x800000u
 #define ___GFP_WRITE           0x1000000u
+/* If the above are modified, __GFP_BITS_SHIFT may need updating */
 
 /*
  * GFP bitmasks..
index 24df9e70406ffb94fb98faf91c174e236155a639..61c97ae22e01881d7e1744401e52705c7986fb99 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _LINUX_HASH_H
 #define _LINUX_HASH_H
 /* Fast hashing routine for ints,  longs and pointers.
-   (C) 2002 William Lee Irwin III, IBM */
+   (C) 2002 Nadia Yvette Chambers, IBM */
 
 /*
  * Knuth recommends primes in approximately golden ratio to the maximum
index ca8d7e94eb3cfe59d6baf497d47423d2feb86248..55f277372fed00e6b454d9fd7249bd531ccbbb8d 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _HID_SENSORS_IDS_H
 #define _HID_SENSORS_IDS_H
 
-#define HID_UP_SENSOR                                          0x00200000
 #define HID_MAX_PHY_DEVICES                                    0xFF
 
 /* Accel 3D (200073) */
index c076041a069e88ee700e12d1bf5d3ca4b6f0a2eb..7330a0fef0c073b41a409882145eb36add87dc02 100644 (file)
@@ -167,6 +167,7 @@ struct hid_item {
 #define HID_UP_MSVENDOR                0xff000000
 #define HID_UP_CUSTOM          0x00ff0000
 #define HID_UP_LOGIVENDOR      0xffbc0000
+#define HID_UP_SENSOR          0x00200000
 
 #define HID_USAGE              0x0000ffff
 
@@ -292,6 +293,7 @@ struct hid_item {
  */
 #define HID_GROUP_GENERIC                      0x0001
 #define HID_GROUP_MULTITOUCH                   0x0002
+#define HID_GROUP_SENSOR_HUB                   0x0003
 
 /*
  * This is the global environment of the parser. This information is
@@ -342,6 +344,7 @@ struct hid_collection {
 struct hid_usage {
        unsigned  hid;                  /* hid usage code */
        unsigned  collection_index;     /* index into collection array */
+       unsigned  usage_index;          /* index into usage array */
        /* hidinput data */
        __u16     code;                 /* input driver code */
        __u8      type;                 /* input driver type */
@@ -684,6 +687,7 @@ struct hid_ll_driver {
 
 extern int hid_debug;
 
+extern bool hid_ignore(struct hid_device *);
 extern int hid_add_device(struct hid_device *);
 extern void hid_destroy_device(struct hid_device *);
 
@@ -706,6 +710,7 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int);
 int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
 struct hid_field *hidinput_get_led_field(struct hid_device *hid);
 unsigned int hidinput_count_leds(struct hid_device *hid);
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
 void hid_output_report(struct hid_report *report, __u8 *data);
 struct hid_device *hid_allocate_device(void);
 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
@@ -716,6 +721,7 @@ int hid_connect(struct hid_device *hid, unsigned int connect_mask);
 void hid_disconnect(struct hid_device *hid);
 const struct hid_device_id *hid_match_id(struct hid_device *hdev,
                                         const struct hid_device_id *id);
+s32 hid_snto32(__u32 value, unsigned n);
 
 /**
  * hid_map_usage - map usage input bits
index 1af47755245944e9f25d794a1f18717960f49d46..092dc5305a327b65708f3fe7f5c75ab2cad5f28c 100644 (file)
@@ -39,6 +39,7 @@ enum transparent_hugepage_flag {
        TRANSPARENT_HUGEPAGE_DEFRAG_FLAG,
        TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG,
        TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG,
+       TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG,
 #ifdef CONFIG_DEBUG_VM
        TRANSPARENT_HUGEPAGE_DEBUG_COW_FLAG,
 #endif
@@ -78,6 +79,9 @@ extern bool is_vma_temporary_stack(struct vm_area_struct *vma);
         (transparent_hugepage_flags &                                  \
          (1<<TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG) &&             \
          (__vma)->vm_flags & VM_HUGEPAGE))
+#define transparent_hugepage_use_zero_page()                           \
+       (transparent_hugepage_flags &                                   \
+        (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG))
 #ifdef CONFIG_DEBUG_VM
 #define transparent_hugepage_debug_cow()                               \
        (transparent_hugepage_flags &                                   \
@@ -95,12 +99,14 @@ extern int handle_pte_fault(struct mm_struct *mm,
                            struct vm_area_struct *vma, unsigned long address,
                            pte_t *pte, pmd_t *pmd, unsigned int flags);
 extern int split_huge_page(struct page *page);
-extern void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd);
-#define split_huge_page_pmd(__mm, __pmd)                               \
+extern void __split_huge_page_pmd(struct vm_area_struct *vma,
+               unsigned long address, pmd_t *pmd);
+#define split_huge_page_pmd(__vma, __address, __pmd)                   \
        do {                                                            \
                pmd_t *____pmd = (__pmd);                               \
                if (unlikely(pmd_trans_huge(*____pmd)))                 \
-                       __split_huge_page_pmd(__mm, ____pmd);           \
+                       __split_huge_page_pmd(__vma, __address,         \
+                                       ____pmd);                       \
        }  while (0)
 #define wait_split_huge_page(__anon_vma, __pmd)                                \
        do {                                                            \
@@ -110,6 +116,8 @@ extern void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd);
                BUG_ON(pmd_trans_splitting(*____pmd) ||                 \
                       pmd_trans_huge(*____pmd));                       \
        } while (0)
+extern void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
+               pmd_t *pmd);
 #if HPAGE_PMD_ORDER > MAX_ORDER
 #error "hugepages can't be allocated by the buddy allocator"
 #endif
@@ -177,10 +185,12 @@ static inline int split_huge_page(struct page *page)
 {
        return 0;
 }
-#define split_huge_page_pmd(__mm, __pmd)       \
+#define split_huge_page_pmd(__vma, __address, __pmd)   \
        do { } while (0)
 #define wait_split_huge_page(__anon_vma, __pmd)        \
        do { } while (0)
+#define split_huge_page_pmd_mm(__mm, __address, __pmd) \
+       do { } while (0)
 #define compound_trans_head(page) compound_head(page)
 static inline int hugepage_madvise(struct vm_area_struct *vma,
                                   unsigned long *vm_flags, int advice)
diff --git a/include/linux/i2c/i2c-hid.h b/include/linux/i2c/i2c-hid.h
new file mode 100644 (file)
index 0000000..60e411d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * HID over I2C protocol implementation
+ *
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
+ *
+ * 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 __LINUX_I2C_HID_H
+#define __LINUX_I2C_HID_H
+
+#include <linux/types.h>
+
+/**
+ * struct i2chid_platform_data - used by hid over i2c implementation.
+ * @hid_descriptor_address: i2c register where the HID descriptor is stored.
+ *
+ * Note that it is the responsibility of the platform driver (or the acpi 5.0
+ * driver) to setup the irq related to the gpio in the struct i2c_board_info.
+ * The platform driver should also setup the gpio according to the device:
+ *
+ * A typical example is the following:
+ *     irq = gpio_to_irq(intr_gpio);
+ *     hkdk4412_i2c_devs5[0].irq = irq; // store the irq in i2c_board_info
+ *     gpio_request(intr_gpio, "elan-irq");
+ *     s3c_gpio_setpull(intr_gpio, S3C_GPIO_PULL_UP);
+ */
+struct i2c_hid_platform_data {
+       u16 hid_descriptor_address;
+};
+
+#endif /* __LINUX_I2C_HID_H */
index cc5cca774bab14590e544f682c96a4ab72cd89c4..2e86bd0bfba11cbc6263ba8942ddbe4ca0760701 100644 (file)
@@ -69,6 +69,12 @@ static inline bool input_mt_is_active(const struct input_mt_slot *slot)
        return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0;
 }
 
+static inline bool input_mt_is_used(const struct input_mt *mt,
+                                   const struct input_mt_slot *slot)
+{
+       return slot->frame == mt->frame;
+}
+
 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
                        unsigned int flags);
 void input_mt_destroy_slots(struct input_dev *dev);
index fcb5d44ea6358b8165a2a1b80ddca56fb3d80595..8ea3fe0b97598428723615c13a042145685adb99 100644 (file)
@@ -216,7 +216,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf);
 
 /*
  * The lower layer reports received messages through this interface.
- * The data_size should be zero if this is an asyncronous message.  If
+ * The data_size should be zero if this is an asynchronous message.  If
  * the lower layer gets an error sending a message, it should format
  * an error response in the message response.
  */
index 526f10a637c1fa46989e70f077e8208d67812580..fdf2c4a238cc605390b63bcdefb1f41533ae426b 100644 (file)
@@ -10,9 +10,6 @@
  */
 
 #include <linux/smp.h>
-
-#ifndef CONFIG_S390
-
 #include <linux/linkage.h>
 #include <linux/cache.h>
 #include <linux/spinlock.h>
@@ -746,8 +743,11 @@ static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
 static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
 #endif
 
-#endif /* CONFIG_GENERIC_HARDIRQS */
+#else /* !CONFIG_GENERIC_HARDIRQS */
 
-#endif /* !CONFIG_S390 */
+extern struct msi_desc *irq_get_msi_desc(unsigned int irq);
+extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry);
+
+#endif /* CONFIG_GENERIC_HARDIRQS */
 
 #endif /* _LINUX_IRQ_H */
diff --git a/include/linux/irqchip/spear-shirq.h b/include/linux/irqchip/spear-shirq.h
new file mode 100644 (file)
index 0000000..c8be16d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SPEAr platform shared irq layer header file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __SPEAR_SHIRQ_H
+#define __SPEAR_SHIRQ_H
+
+#include <linux/irq.h>
+#include <linux/types.h>
+
+/*
+ * struct shirq_regs: shared irq register configuration
+ *
+ * enb_reg: enable register offset
+ * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
+ * status_reg: status register offset
+ * status_reg_mask: status register valid mask
+ * clear_reg: clear register offset
+ * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
+ */
+struct shirq_regs {
+       u32 enb_reg;
+       u32 reset_to_enb;
+       u32 status_reg;
+       u32 clear_reg;
+       u32 reset_to_clear;
+};
+
+/*
+ * struct spear_shirq: shared irq structure
+ *
+ * irq: hardware irq number
+ * irq_base: base irq in linux domain
+ * irq_nr: no. of shared interrupts in a particular block
+ * irq_bit_off: starting bit offset in the status register
+ * invalid_irq: irq group is currently disabled
+ * base: base address of shared irq register
+ * regs: register configuration for shared irq block
+ */
+struct spear_shirq {
+       u32 irq;
+       u32 irq_base;
+       u32 irq_nr;
+       u32 irq_bit_off;
+       int invalid_irq;
+       void __iomem *base;
+       struct shirq_regs regs;
+};
+
+int __init spear300_shirq_of_init(struct device_node *np,
+               struct device_node *parent);
+int __init spear310_shirq_of_init(struct device_node *np,
+               struct device_node *parent);
+int __init spear320_shirq_of_init(struct device_node *np,
+               struct device_node *parent);
+
+#endif /* __SPEAR_SHIRQ_H */
index d5cddd8dcc5c787713b7ea726d2bdadf94345d41..2c497ab0d03d41f7c8e85531a46776cba47f8d14 100644 (file)
 
 /*
  * For the normal pfn, the highest 12 bits should be zero,
- * so we can mask these bits to indicate the error.
+ * so we can mask bit 62 ~ bit 52  to indicate the error pfn,
+ * mask bit 63 to indicate the noslot pfn.
  */
-#define KVM_PFN_ERR_MASK       (0xfffULL << 52)
+#define KVM_PFN_ERR_MASK       (0x7ffULL << 52)
+#define KVM_PFN_ERR_NOSLOT_MASK        (0xfffULL << 52)
+#define KVM_PFN_NOSLOT         (0x1ULL << 63)
 
 #define KVM_PFN_ERR_FAULT      (KVM_PFN_ERR_MASK)
 #define KVM_PFN_ERR_HWPOISON   (KVM_PFN_ERR_MASK + 1)
-#define KVM_PFN_ERR_BAD                (KVM_PFN_ERR_MASK + 2)
-#define KVM_PFN_ERR_RO_FAULT   (KVM_PFN_ERR_MASK + 3)
+#define KVM_PFN_ERR_RO_FAULT   (KVM_PFN_ERR_MASK + 2)
 
+/*
+ * error pfns indicate that the gfn is in slot but faild to
+ * translate it to pfn on host.
+ */
 static inline bool is_error_pfn(pfn_t pfn)
 {
        return !!(pfn & KVM_PFN_ERR_MASK);
 }
 
-static inline bool is_noslot_pfn(pfn_t pfn)
+/*
+ * error_noslot pfns indicate that the gfn can not be
+ * translated to pfn - it is not in slot or failed to
+ * translate it to pfn.
+ */
+static inline bool is_error_noslot_pfn(pfn_t pfn)
 {
-       return pfn == KVM_PFN_ERR_BAD;
+       return !!(pfn & KVM_PFN_ERR_NOSLOT_MASK);
 }
 
-static inline bool is_invalid_pfn(pfn_t pfn)
+/* noslot pfn indicates that the gfn is not in slot. */
+static inline bool is_noslot_pfn(pfn_t pfn)
 {
-       return !is_noslot_pfn(pfn) && is_error_pfn(pfn);
+       return pfn == KVM_PFN_NOSLOT;
 }
 
 #define KVM_HVA_ERR_BAD                (PAGE_OFFSET)
@@ -107,6 +119,9 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_IMMEDIATE_EXIT    15
 #define KVM_REQ_PMU               16
 #define KVM_REQ_PMI               17
+#define KVM_REQ_WATCHDOG          18
+#define KVM_REQ_MASTERCLOCK_UPDATE 19
+#define KVM_REQ_MCLOCK_INPROGRESS 20
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID            0
 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID       1
@@ -516,6 +531,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
 
 void kvm_flush_remote_tlbs(struct kvm *kvm);
 void kvm_reload_remote_mmus(struct kvm *kvm);
+void kvm_make_mclock_inprogress_request(struct kvm *kvm);
 
 long kvm_arch_dev_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg);
@@ -569,9 +585,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu);
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id);
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
 
-int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu);
 int kvm_arch_hardware_enable(void *garbage);
 void kvm_arch_hardware_disable(void *garbage);
 int kvm_arch_hardware_setup(void);
@@ -666,6 +682,7 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
                                   unsigned long *deliver_bitmask);
 #endif
 int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level);
+int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level);
 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm,
                int irq_source_id, int level);
 void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin);
@@ -838,9 +855,9 @@ extern struct kvm_stats_debugfs_item debugfs_entries[];
 extern struct dentry *kvm_debugfs_dir;
 
 #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
-static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_seq)
+static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
 {
-       if (unlikely(vcpu->kvm->mmu_notifier_count))
+       if (unlikely(kvm->mmu_notifier_count))
                return 1;
        /*
         * Ensure the read of mmu_notifier_count happens before the read
@@ -853,7 +870,7 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se
         * can't rely on kvm->mmu_lock to keep things ordered.
         */
        smp_rmb();
-       if (vcpu->kvm->mmu_notifier_seq != mmu_seq)
+       if (kvm->mmu_notifier_seq != mmu_seq)
                return 1;
        return 0;
 }
@@ -881,10 +898,20 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}
 #ifdef CONFIG_HAVE_KVM_EVENTFD
 
 void kvm_eventfd_init(struct kvm *kvm);
+int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
+
+#ifdef CONFIG_HAVE_KVM_IRQCHIP
 int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
 void kvm_irqfd_release(struct kvm *kvm);
 void kvm_irq_routing_update(struct kvm *, struct kvm_irq_routing_table *);
-int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
+#else
+static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
+{
+       return -EINVAL;
+}
+
+static inline void kvm_irqfd_release(struct kvm *kvm) {}
+#endif
 
 #else
 
index 6e53bb31c220d9f33224f2660bc52a1d9c44f0db..0d9b5eed714ecd9f46323d334a6d2e7e27ddc8ff 100644 (file)
@@ -179,6 +179,23 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
                                      unsigned long *delay_on,
                                      unsigned long *delay_off,
                                      int invert);
+/**
+ * led_trigger_rename_static - rename a trigger
+ * @name: the new trigger name
+ * @trig: the LED trigger to rename
+ *
+ * Change a LED trigger name by copying the string passed in
+ * name into current trigger name, which MUST be large
+ * enough for the new string.
+ *
+ * Note that name must NOT point to the same string used
+ * during LED registration, as that could lead to races.
+ *
+ * This is meant to be used on triggers with statically
+ * allocated name.
+ */
+extern void led_trigger_rename_static(const char *name,
+                                     struct led_trigger *trig);
 
 #else
 
index 77eeeda2b6e2cbcab6cda30aaa5269885344150c..83ba0ab2c915c1bdb66fc7c922343b3f027ad120 100644 (file)
@@ -163,6 +163,7 @@ enum {
 
        ATA_DFLAG_DA            = (1 << 26), /* device supports Device Attention */
        ATA_DFLAG_DEVSLP        = (1 << 27), /* device supports Device Sleep */
+       ATA_DFLAG_ACPI_DISABLED = (1 << 28), /* ACPI for the device is disabled */
 
        ATA_DEV_UNKNOWN         = 0,    /* unknown device */
        ATA_DEV_ATA             = 1,    /* ATA device */
@@ -1114,6 +1115,10 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PCI */
 
+struct platform_device;
+
+extern int ata_platform_remove_one(struct platform_device *pdev);
+
 /*
  * ACPI - drivers/ata/libata-acpi.c
  */
index 7a71ffad037c7ebd07aa79d7e23c08b6b38554bb..cafc7f99e124ec0c5a39743f048527a9875a3b55 100644 (file)
@@ -52,8 +52,8 @@ We replicate IO (more or less synchronously) to local and remote disk.
 
 For crash recovery after replication node failure,
   we need to resync all regions that have been target of in-flight WRITE IO
-  (in use, or "hot", regions), as we don't know wether or not those WRITEs have
-  made it to stable storage.
+  (in use, or "hot", regions), as we don't know whether or not those WRITEs
+  have made it to stable storage.
 
   To avoid a "full resync", we need to persistently track these regions.
 
index 11ddc7ffeba88972f21937a8b45d65191d40fc35..e98a74c0c9c0e872eb20fd29e5a24b3c3cd3d5ed 100644 (file)
@@ -181,7 +181,14 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
                                                gfp_t gfp_mask,
                                                unsigned long *total_scanned);
 
-void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
+void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
+static inline void mem_cgroup_count_vm_event(struct mm_struct *mm,
+                                            enum vm_event_item idx)
+{
+       if (mem_cgroup_disabled())
+               return;
+       __mem_cgroup_count_vm_event(mm, idx);
+}
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void mem_cgroup_split_huge_fixup(struct page *head);
 #endif
index a09216d0dcc71baad9369580cb962ce53cc7682d..45e93b4688785a9502c870758220e57498723a94 100644 (file)
@@ -54,6 +54,7 @@ struct memory_notify {
        unsigned long start_pfn;
        unsigned long nr_pages;
        int status_change_nid_normal;
+       int status_change_nid_high;
        int status_change_nid;
 };
 
index 5d5298d56026e6a8681769c68b0f4927b2f60930..2138bd33021a629f59b868d5a3938aefa4f87449 100644 (file)
@@ -267,39 +267,21 @@ struct abx500_bm_data {
        int gnd_lift_resistance;
        const struct abx500_maxim_parameters *maxi;
        const struct abx500_bm_capacity_levels *cap_levels;
-       const struct abx500_battery_type *bat_type;
+       struct abx500_battery_type *bat_type;
        const struct abx500_bm_charger_parameters *chg_params;
        const struct abx500_fg_parameters *fg_params;
 };
 
-struct abx500_chargalg_platform_data {
-       char **supplied_to;
-       size_t num_supplicants;
-};
-
-struct abx500_charger_platform_data {
-       char **supplied_to;
-       size_t num_supplicants;
-       bool autopower_cfg;
-};
+extern struct abx500_bm_data ab8500_bm_data;
 
-struct abx500_btemp_platform_data {
-       char **supplied_to;
-       size_t num_supplicants;
+enum {
+       NTC_EXTERNAL = 0,
+       NTC_INTERNAL,
 };
 
-struct abx500_fg_platform_data {
-       char **supplied_to;
-       size_t num_supplicants;
-};
-
-struct abx500_bm_plat_data {
-       struct abx500_bm_data *battery;
-       struct abx500_charger_platform_data *charger;
-       struct abx500_btemp_platform_data *btemp;
-       struct abx500_fg_platform_data *fg;
-       struct abx500_chargalg_platform_data *chargalg;
-};
+int bmdevs_of_probe(struct device *dev,
+               struct device_node *np,
+               struct abx500_bm_data **battery);
 
 int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
        u8 value);
index dd231ac0bb1fd8ac678d475404bc95ebaa104cec..a580363a7d29723e6656cbed8d9d94b4b1801bea 100644 (file)
@@ -78,6 +78,8 @@ enum arizona_type {
 
 #define ARIZONA_NUM_IRQ                   50
 
+struct snd_soc_dapm_context;
+
 struct arizona {
        struct regmap *regmap;
        struct device *dev;
@@ -98,6 +100,8 @@ struct arizona {
 
        struct mutex clk_lock;
        int clk32k_ref;
+
+       struct snd_soc_dapm_context *dapm;
 };
 
 int arizona_clk32k_enable(struct arizona *arizona);
index 7ab442905a57b209b10c042cf141ac2b2ba2275e..8b1d1daaae16c27e59d037f46899a1f6c631acc4 100644 (file)
@@ -62,6 +62,9 @@
 
 #define ARIZONA_MAX_OUTPUT 6
 
+#define ARIZONA_HAP_ACT_ERM 0
+#define ARIZONA_HAP_ACT_LRA 2
+
 #define ARIZONA_MAX_PDM_SPK 2
 
 struct regulator_init_data;
@@ -114,6 +117,9 @@ struct arizona_pdata {
 
        /** PDM speaker format */
        unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK];
+
+       /** Haptic actuator type */
+       unsigned int hap_act;
 };
 
 #endif
index 7671a287dfee4f592e909c15bcc0c14cac47bb7a..ba26e99c388d0a7f6105ce9181cdc0f94e42736a 100644 (file)
@@ -76,6 +76,7 @@
 #define ARIZONA_RATE_ESTIMATOR_3                 0x154
 #define ARIZONA_RATE_ESTIMATOR_4                 0x155
 #define ARIZONA_RATE_ESTIMATOR_5                 0x156
+#define ARIZONA_DYNAMIC_FREQUENCY_SCALING_1      0x161
 #define ARIZONA_FLL1_CONTROL_1                   0x171
 #define ARIZONA_FLL1_CONTROL_2                   0x172
 #define ARIZONA_FLL1_CONTROL_3                   0x173
 #define ARIZONA_FLL2_GPIO_CLOCK                  0x1AA
 #define ARIZONA_MIC_CHARGE_PUMP_1                0x200
 #define ARIZONA_LDO1_CONTROL_1                   0x210
+#define ARIZONA_LDO1_CONTROL_2                   0x212
 #define ARIZONA_LDO2_CONTROL_1                   0x213
 #define ARIZONA_MIC_BIAS_CTRL_1                  0x218
 #define ARIZONA_MIC_BIAS_CTRL_2                  0x219
 #define ARIZONA_SAMPLE_RATE_DETECT_D_SHIFT            0  /* SAMPLE_RATE_DETECT_D - [4:0] */
 #define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH            5  /* SAMPLE_RATE_DETECT_D - [4:0] */
 
+/*
+ * R353 (0x161) - Dynamic Frequency Scaling 1
+ */
+#define ARIZONA_SUBSYS_MAX_FREQ                  0x0001  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_SHIFT                 0  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_WIDTH                 1  /* SUBSYS_MAX_FREQ */
+
 /*
  * R369 (0x171) - FLL1 Control 1
  */
 #define ARIZONA_LDO1_ENA_SHIFT                        0  /* LDO1_ENA */
 #define ARIZONA_LDO1_ENA_WIDTH                        1  /* LDO1_ENA */
 
+/*
+ * R530 (0x212) - LDO1 Control 2
+ */
+#define ARIZONA_LDO1_HI_PWR                      0x0001  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_SHIFT                     0  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_WIDTH                     1  /* LDO1_HI_PWR */
+
 /*
  * R531 (0x213) - LDO2 Control 1
  */
index 147293b4471d6811248388c3932e89e65a3b844b..f87a6c172a917f860976e90a62ddd8c790e4266e 100644 (file)
@@ -25,8 +25,29 @@ struct da9055_pdata {
        int gpio_base;
 
        struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
-       bool reset_enable;              /* Enable RTC in RESET Mode */
-       enum gpio_select *gpio_rsel;    /* Select regulator set thru GPIO 1/2 */
-       enum gpio_select *gpio_ren;     /* Enable regulator thru GPIO 1/2 */
+       /* Enable RTC in RESET Mode */
+       bool reset_enable;
+       /*
+        * GPI muxed pin to control
+        * regulator state A/B, 0 if not available.
+        */
+       int *gpio_ren;
+       /*
+        * GPI muxed pin to control
+        * regulator set, 0 if not available.
+        */
+       int *gpio_rsel;
+       /*
+        * Regulator mode control bits value (GPI offset) that
+        * that controls the regulator state, 0 if not available.
+        */
+       enum gpio_select *reg_ren;
+       /*
+        * Regulator mode control bits value (GPI offset) that
+        * controls the regulator set A/B, 0 if  not available.
+        */
+       enum gpio_select *reg_rsel;
+       /* GPIOs to enable regulator, 0 if not available */
+       int *ena_gpio;
 };
 #endif /* __DA9055_PDATA_H */
index cec364bdccfaa4aae6cee96b086aea857bc8227d..2a32b16f79cb88c2e3649f190508b7abb980818d 100644 (file)
@@ -211,16 +211,16 @@ struct lp8788_chg_param {
 
 /*
  * struct lp8788_charger_platform_data
- * @vbatt_adc         : adc selection id for battery voltage
- * @batt_temp_adc     : adc selection id for battery temperature
+ * @adc_vbatt         : adc channel name for battery voltage
+ * @adc_batt_temp     : adc channel name for battery temperature
  * @max_vbatt_mv      : used for calculating battery capacity
  * @chg_params        : initial charging parameters
  * @num_chg_params    : numbers of charging parameters
  * @charger_event     : the charger event can be reported to the platform side
  */
 struct lp8788_charger_platform_data {
-       enum lp8788_adc_id vbatt_adc;
-       enum lp8788_adc_id batt_temp_adc;
+       const char *adc_vbatt;
+       const char *adc_batt_temp;
        unsigned int max_vbatt_mv;
        struct lp8788_chg_param *chg_params;
        int num_chg_params;
index 830152cfae339727ad1d70875a61dbdaa34a6c67..6ae21bf47d644fe8424587b31afd880701720434 100644 (file)
@@ -316,6 +316,7 @@ enum max8997_irq {
 #define MAX8997_NUM_GPIO       12
 struct max8997_dev {
        struct device *dev;
+       struct max8997_platform_data *pdata;
        struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
        struct i2c_client *rtc; /* slave addr 0x0c */
        struct i2c_client *haptic; /* slave addr 0x90 */
index 328d8e24b533acaf524746d01dbf1cba76656782..1d4a4fe6ac33e9341f8b90bb0a0f32a015b490b5 100644 (file)
@@ -75,6 +75,7 @@ enum max8998_regulators {
 struct max8997_regulator_data {
        int id;
        struct regulator_init_data *initdata;
+       struct device_node *reg_node;
 };
 
 enum max8997_muic_usb_type {
index 6bc31d854626b26f62994f0810a143ee00027e17..804e280c1e1d9a2a18157b377bfef9f622834cc7 100644 (file)
 
 #include <linux/irq.h>
 
+/* TPS65090 Regulator ID */
+enum {
+       TPS65090_REGULATOR_DCDC1,
+       TPS65090_REGULATOR_DCDC2,
+       TPS65090_REGULATOR_DCDC3,
+       TPS65090_REGULATOR_FET1,
+       TPS65090_REGULATOR_FET2,
+       TPS65090_REGULATOR_FET3,
+       TPS65090_REGULATOR_FET4,
+       TPS65090_REGULATOR_FET5,
+       TPS65090_REGULATOR_FET6,
+       TPS65090_REGULATOR_FET7,
+       TPS65090_REGULATOR_LDO1,
+       TPS65090_REGULATOR_LDO2,
+
+       /* Last entry for maximum ID */
+       TPS65090_REGULATOR_MAX,
+};
+
 struct tps65090 {
        struct mutex            lock;
        struct device           *dev;
@@ -41,10 +60,26 @@ struct tps65090_subdev_info {
        void            *platform_data;
 };
 
+/*
+ * struct tps65090_regulator_plat_data
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_ext_control: Enable extrenal control or not. Only available for
+ *     DCDC1, DCDC2 and DCDC3.
+ * @gpio: Gpio number if external control is enabled and controlled through
+ *     gpio.
+ */
+struct tps65090_regulator_plat_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_ext_control;
+       int gpio;
+};
+
 struct tps65090_platform_data {
        int irq_base;
        int num_subdevs;
        struct tps65090_subdev_info *subdevs;
+       struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
 };
 
 /*
index 2dd123194958afe1551c63d30cc16dc200410f1e..f8da0e152567059e0d0928c844e70dda7a94cc4a 100644 (file)
@@ -29,6 +29,7 @@ enum {
        TPS6586X_ID_LDO_8,
        TPS6586X_ID_LDO_9,
        TPS6586X_ID_LDO_RTC,
+       TPS6586X_ID_MAX_REGULATOR,
 };
 
 enum {
@@ -79,6 +80,8 @@ struct tps6586x_platform_data {
        int gpio_base;
        int irq_base;
        bool pm_off;
+
+       struct regulator_init_data *reg_init_data[TPS6586X_ID_MAX_REGULATOR];
 };
 
 /*
index 1f173306bf0508ddeb3a18de8175fac44c857ee3..ae5c249530b4e7f527a22f44e242d4d4bce66419 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/interrupt.h>
 #include <linux/regmap.h>
 
+#include <linux/mfd/wm8994/pdata.h>
+
 enum wm8994_type {
        WM8994 = 0,
        WM8958 = 1,
@@ -55,6 +57,8 @@ struct regulator_bulk_data;
 struct wm8994 {
        struct mutex irq_lock;
 
+       struct wm8994_pdata pdata;
+
        enum wm8994_type type;
        int revision;
        int cust_id;
index fc87be4fdc2501a8106b18664102c793ccdb588b..8e21a094836d21566bec6f08c027ad5c765fa715 100644 (file)
@@ -176,6 +176,11 @@ struct wm8994_pdata {
         unsigned int lineout1fb:1;
         unsigned int lineout2fb:1;
 
+       /* Delay between detecting a jack and starting microphone
+        * detect (specified in ms)
+        */
+       int micdet_delay;
+
        /* IRQ for microphone detection if brought out directly as a
         * signal.
         */
index e0deeb2cc93901f393125e793d7137a26dcee105..09c2300ddb3723188636867fa9b5c21bddab47df 100644 (file)
@@ -34,6 +34,7 @@
 #define MWAVE_MINOR            219     /* ACP/Mwave Modem */
 #define MPT_MINOR              220
 #define MPT2SAS_MINOR          221
+#define MPT3SAS_MINOR          222
 #define UINPUT_MINOR           223
 #define MISC_MCELOG_MINOR      227
 #define HPET_MINOR             228
index 6d1acb04cd17c1babf6d477c0554156afd6d5950..21821da2abfd321f3755b8c0eb5481033183abeb 100644 (file)
@@ -142,6 +142,8 @@ enum {
        MLX4_DEV_CAP_FLAG_COUNTERS      = 1LL << 48,
        MLX4_DEV_CAP_FLAG_SENSE_SUPPORT = 1LL << 55,
        MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV = 1LL << 59,
+       MLX4_DEV_CAP_FLAG_64B_EQE       = 1LL << 61,
+       MLX4_DEV_CAP_FLAG_64B_CQE       = 1LL << 62
 };
 
 enum {
@@ -151,6 +153,20 @@ enum {
        MLX4_DEV_CAP_FLAG2_FS_EN                = 1LL <<  3
 };
 
+enum {
+       MLX4_DEV_CAP_64B_EQE_ENABLED    = 1LL << 0,
+       MLX4_DEV_CAP_64B_CQE_ENABLED    = 1LL << 1
+};
+
+enum {
+       MLX4_USER_DEV_CAP_64B_CQE       = 1L << 0
+};
+
+enum {
+       MLX4_FUNC_CAP_64B_EQE_CQE       = 1L << 0
+};
+
+
 #define MLX4_ATTR_EXTENDED_PORT_INFO   cpu_to_be16(0xff90)
 
 enum {
@@ -419,6 +435,11 @@ struct mlx4_caps {
        u32                     max_counters;
        u8                      port_ib_mtu[MLX4_MAX_PORTS + 1];
        u16                     sqp_demux;
+       u32                     eqe_size;
+       u32                     cqe_size;
+       u8                      eqe_factor;
+       u32                     userspace_caps; /* userspace must be aware of these */
+       u32                     function_caps;  /* VFs must be aware of these */
 };
 
 struct mlx4_buf_list {
index 0c0b1d608a6936b85cabad0372ffa63fd69b1673..cd55dad56aac087b138ea79acd57261e8355e91f 100644 (file)
@@ -460,17 +460,44 @@ struct zone {
        unsigned long           zone_start_pfn;
 
        /*
-        * zone_start_pfn, spanned_pages and present_pages are all
-        * protected by span_seqlock.  It is a seqlock because it has
-        * to be read outside of zone->lock, and it is done in the main
-        * allocator path.  But, it is written quite infrequently.
+        * spanned_pages is the total pages spanned by the zone, including
+        * holes, which is calculated as:
+        *      spanned_pages = zone_end_pfn - zone_start_pfn;
         *
-        * The lock is declared along with zone->lock because it is
+        * present_pages is physical pages existing within the zone, which
+        * is calculated as:
+        *      present_pages = spanned_pages - absent_pages(pags in holes);
+        *
+        * managed_pages is present pages managed by the buddy system, which
+        * is calculated as (reserved_pages includes pages allocated by the
+        * bootmem allocator):
+        *      managed_pages = present_pages - reserved_pages;
+        *
+        * So present_pages may be used by memory hotplug or memory power
+        * management logic to figure out unmanaged pages by checking
+        * (present_pages - managed_pages). And managed_pages should be used
+        * by page allocator and vm scanner to calculate all kinds of watermarks
+        * and thresholds.
+        *
+        * Locking rules:
+        *
+        * zone_start_pfn and spanned_pages are protected by span_seqlock.
+        * It is a seqlock because it has to be read outside of zone->lock,
+        * and it is done in the main allocator path.  But, it is written
+        * quite infrequently.
+        *
+        * The span_seq lock is declared along with zone->lock because it is
         * frequently read in proximity to zone->lock.  It's good to
         * give them a chance of being in the same cacheline.
+        *
+        * Write access to present_pages and managed_pages at runtime should
+        * be protected by lock_memory_hotplug()/unlock_memory_hotplug().
+        * Any reader who can't tolerant drift of present_pages and
+        * managed_pages should hold memory hotplug lock to get a stable value.
         */
-       unsigned long           spanned_pages;  /* total size, including holes */
-       unsigned long           present_pages;  /* amount of memory (excluding holes) */
+       unsigned long           spanned_pages;
+       unsigned long           present_pages;
+       unsigned long           managed_pages;
 
        /*
         * rarely used fields:
index ef9336c9d4648c00ade2eee1c423cd46bfc8b02b..02e0f6b156c3f2dc7c2cae5c663cbdbfd6341484 100644 (file)
@@ -369,7 +369,7 @@ typedef enum gro_result gro_result_t;
  *
  * If the rx_handler consider the skb should be ignored, it should return
  * RX_HANDLER_EXACT. The skb will only be delivered to protocol handlers that
- * are registred on exact device (ptype->dev == skb->dev).
+ * are registered on exact device (ptype->dev == skb->dev).
  *
  * If the rx_handler didn't changed skb->dev, but want the skb to be normally
  * delivered, it should return RX_HANDLER_PASS.
index 7afc36334d52ba7a188e15713ae46f52ed0fa28d..4e2cbfa640b7241d0ddf803a68010e20b5991115 100644 (file)
@@ -379,6 +379,11 @@ enum node_states {
        N_HIGH_MEMORY,          /* The node has regular or high memory */
 #else
        N_HIGH_MEMORY = N_NORMAL_MEMORY,
+#endif
+#ifdef CONFIG_MOVABLE_NODE
+       N_MEMORY,               /* The node has memory(regular, high, movable) */
+#else
+       N_MEMORY = N_HIGH_MEMORY,
 #endif
        N_CPU,          /* The node has one or more cpus */
        NR_NODE_STATES
index 60053bd7e79a8c835099c474aad86c030754a3ac..6cfea9aa401f766651956f97c389c0e209202279 100644 (file)
@@ -273,7 +273,7 @@ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
 extern struct device_node *of_parse_phandle(const struct device_node *np,
                                            const char *phandle_name,
                                            int index);
-extern int of_parse_phandle_with_args(struct device_node *np,
+extern int of_parse_phandle_with_args(const struct device_node *np,
        const char *list_name, const char *cells_name, int index,
        struct of_phandle_args *out_args);
 
index 1cb775f8e663d6d2dc60d79b9be79ddaae480273..cfb545cd86b5a1baaf6c39b7ba91f2d90c129c43 100644 (file)
@@ -29,6 +29,18 @@ static inline void of_i2c_register_devices(struct i2c_adapter *adap)
 {
        return;
 }
+
+static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
+{
+       return NULL;
+}
+
+/* must call put_device() when done with returned i2c_adapter device */
+static inline struct i2c_adapter *of_find_i2c_adapter_by_node(
+                                               struct device_node *node)
+{
+       return NULL;
+}
 #endif /* CONFIG_OF_I2C */
 
 #endif /* __LINUX_OF_I2C_H */
index af8229244ee2875f323af682ef90bb3d9b37134b..15472d691ee68c6aad5dbeb0a75933ec18f00404 100644 (file)
@@ -333,6 +333,8 @@ struct pci_dev {
        };
        struct pci_ats  *ats;   /* Address Translation Service */
 #endif
+       phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
+       size_t romlen; /* Length of ROM if it's not from the BAR */
 };
 
 static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
@@ -538,6 +540,9 @@ enum pci_ers_result {
 
        /* Device driver is fully recovered and operational */
        PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5,
+
+       /* No AER capabilities registered for the driver */
+       PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
 };
 
 /* PCI bus error event callbacks */
@@ -573,6 +578,7 @@ struct pci_driver {
        int  (*resume_early) (struct pci_dev *dev);
        int  (*resume) (struct pci_dev *dev);                   /* Device woken up */
        void (*shutdown) (struct pci_dev *dev);
+       int (*sriov_configure) (struct pci_dev *dev, int num_vfs); /* PF pdev */
        const struct pci_error_handlers *err_handler;
        struct device_driver    driver;
        struct pci_dynids dynids;
@@ -726,6 +732,8 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+void pci_stop_root_bus(struct pci_bus *bus);
+void pci_remove_root_bus(struct pci_bus *bus);
 void pci_setup_cardbus(struct pci_bus *bus);
 extern void pci_sort_breadthfirst(void);
 #define dev_is_pci(d) ((d)->bus == &pci_bus_type)
@@ -970,6 +978,7 @@ void pci_bus_size_bridges(struct pci_bus *bus);
 int pci_claim_resource(struct pci_dev *, int);
 void pci_assign_unassigned_resources(void);
 void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
 void pdev_enable_device(struct pci_dev *);
 int pci_enable_resources(struct pci_dev *, int mask);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
@@ -1604,6 +1613,7 @@ void pcibios_disable_device(struct pci_dev *dev);
 void pcibios_set_master(struct pci_dev *dev);
 int pcibios_set_pcie_reset_state(struct pci_dev *dev,
                                 enum pcie_reset_state state);
+int pcibios_add_device(struct pci_dev *dev);
 
 #ifdef CONFIG_PCI_MMCONFIG
 extern void __init pci_mmcfg_early_init(void);
@@ -1613,7 +1623,7 @@ static inline void pci_mmcfg_early_init(void) { }
 static inline void pci_mmcfg_late_init(void) { }
 #endif
 
-int pci_ext_cfg_avail(struct pci_dev *dev);
+int pci_ext_cfg_avail(void);
 
 void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
 
@@ -1622,6 +1632,8 @@ extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
 extern void pci_disable_sriov(struct pci_dev *dev);
 extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 extern int pci_num_vf(struct pci_dev *dev);
+extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
+extern int pci_sriov_get_totalvfs(struct pci_dev *dev);
 #else
 static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 {
@@ -1638,6 +1650,14 @@ static inline int pci_num_vf(struct pci_dev *dev)
 {
        return 0;
 }
+static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
+{
+       return 0;
+}
+static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
+{
+       return 0;
+}
 #endif
 
 #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
index aa9875f77c40489527279342ca8b1d1da89866c4..88272591a8951d09fb18d8b7967ed3e885ca8855 100644 (file)
@@ -38,12 +38,6 @@ struct samsung_i2s {
 #define QUIRK_NEED_RSTCLR      (1 << 3)
        /* Quirks of the I2S controller */
        u32 quirks;
-
-       /*
-        * Array of clock names that can be used to generate I2S signals.
-        * Also corresponds to clocks of I2SMOD[10]
-        */
-       const char **src_clk;
        dma_addr_t idma_addr;
 };
 
index d0c5825876f8a2d1d124a3d51fac880951a63b2f..8db5ae03b6e3f679c16988e492e8241f1567b2f5 100644 (file)
 #ifndef __DAVINCI_ASP_H
 #define __DAVINCI_ASP_H
 
+#include <linux/genalloc.h>
+
 struct snd_platform_data {
        u32 tx_dma_offset;
        u32 rx_dma_offset;
        int asp_chan_q; /* event queue number for ASP channel */
        int ram_chan_q; /* event queue number for RAM channel */
-       unsigned int codec_fmt;
        /*
         * Allowing this is more efficient and eliminates left and right swaps
         * caused by underruns, but will swap the left and right channels
@@ -30,6 +31,7 @@ struct snd_platform_data {
        unsigned enable_channel_combine:1;
        unsigned sram_size_playback;
        unsigned sram_size_capture;
+       struct gen_pool *sram_pool;
 
        /*
         * If McBSP peripheral gets the clock from an external pin,
index 2ba1f7d76eef0e414c6ff8ba5ee4e2fa6f4622cf..8ec18f64e3965e68fcf6ffbfae436687987f3466 100644 (file)
 #include <linux/dmaengine.h>
 #include <linux/mbus.h>
 
-#define MV_XOR_SHARED_NAME     "mv_xor_shared"
-#define MV_XOR_NAME            "mv_xor"
+#define MV_XOR_NAME    "mv_xor"
 
-struct mv_xor_platform_data {
-       struct platform_device          *shared;
-       int                             hw_id;
+struct mv_xor_channel_data {
        dma_cap_mask_t                  cap_mask;
-       size_t                          pool_size;
 };
 
+struct mv_xor_platform_data {
+       struct mv_xor_channel_data    *channels;
+};
 
 #endif
index c7bef788daabd14735d053e5c8ad680b247e11f1..ee60ef79d79270262bfb1992f4f7695f422323fc 100644 (file)
 #ifndef _OMAP_TWL4030_H_
 #define _OMAP_TWL4030_H_
 
+/* To select if only one channel is connected in a stereo port */
+#define OMAP_TWL4030_LEFT      (1 << 0)
+#define OMAP_TWL4030_RIGHT     (1 << 1)
+
 struct omap_tw4030_pdata {
        const char *card_name;
+       /* Voice port is connected to McBSP3 */
+       bool voice_connected;
+
+       /* The driver will parse the connection flags if this flag is set */
+       bool    custom_routing;
+       /* Flags to indicate connected audio ports. */
+       u8      has_hs;
+       u8      has_hf;
+       u8      has_predriv;
+       u8      has_carkit;
+       bool    has_ear;
+
+       bool    has_mainmic;
+       bool    has_submic;
+       bool    has_hsmic;
+       bool    has_carkitmic;
+       bool    has_digimic0;
+       bool    has_digimic1;
+       u8      has_linein;
+
+       /* Jack detect GPIO or  <= 0 if it is not implemented */
+       int jack_detect;
 };
 
 #endif /* _OMAP_TWL4030_H_ */
diff --git a/include/linux/platform_data/spi-clps711x.h b/include/linux/platform_data/spi-clps711x.h
new file mode 100644 (file)
index 0000000..301956e
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  CLPS711X SPI bus driver definitions
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * 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 ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
+#define ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
+
+/* Board specific platform_data */
+struct spi_clps711x_pdata {
+       int *chipselect;        /* Array of GPIO-numbers */
+       int num_chipselect;     /* Total count of GPIOs */
+};
+
+#endif
index a357eb26bd258dfd6a969bf218da86d322f41ba1..a65572d53211cf2dc51b97c7ca438c2020520862 100644 (file)
@@ -7,9 +7,13 @@
 
 #define OMAP4_MCSPI_REG_OFFSET 0x100
 
+#define MCSPI_PINDIR_D0_IN_D1_OUT      0
+#define MCSPI_PINDIR_D0_OUT_D1_IN      1
+
 struct omap2_mcspi_platform_config {
        unsigned short  num_cs;
        unsigned int regs_offset;
+       unsigned int pin_dir:1;
 };
 
 struct omap2_mcspi_dev_attr {
diff --git a/include/linux/power/bq2415x_charger.h b/include/linux/power/bq2415x_charger.h
new file mode 100644 (file)
index 0000000..97a1665
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * bq2415x charger driver
+ *
+ * Copyright (C) 2011-2012  Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BQ2415X_CHARGER_H
+#define BQ2415X_CHARGER_H
+
+/*
+ * This is platform data for bq2415x chip. It contains default board
+ * voltages and currents which can be also later configured via sysfs. If
+ * value is -1 then default chip value (specified in datasheet) will be
+ * used.
+ *
+ * Value resistor_sense is needed for for configuring charge and
+ * termination current. It it is less or equal to zero, configuring charge
+ * and termination current will not be possible.
+ *
+ * Function set_mode_hook is needed for automode (setting correct current
+ * limit when charger is connected/disconnected or setting boost mode).
+ * When is NULL, automode function is disabled. When is not NULL, it must
+ * have this prototype:
+ *
+ *    int (*set_mode_hook)(
+ *      void (*hook)(enum bq2415x_mode mode, void *data),
+ *      void *data)
+ *
+ * hook is hook function (see below) and data is pointer to driver private
+ * data
+ *
+ * bq2415x driver will call it as:
+ *
+ *    platform_data->set_mode_hook(bq2415x_hook_function, bq2415x_device);
+ *
+ * Board/platform function set_mode_hook return non zero value when hook
+ * function was successful registered. Platform code should call that hook
+ * function (which get from pointer, with data) every time when charger
+ * was connected/disconnected or require to enable boost mode. bq2415x
+ * driver then will set correct current limit, enable/disable charger or
+ * boost mode.
+ *
+ * Hook function has this prototype:
+ *
+ *    void hook(enum bq2415x_mode mode, void *data);
+ *
+ * mode is bq2415x mode (charger or boost)
+ * data is pointer to driver private data (which get from
+ * set_charger_type_hook)
+ *
+ * When bq driver is being unloaded, it call function:
+ *
+ *    platform_data->set_mode_hook(NULL, NULL);
+ *
+ * (hook function and driver private data are NULL)
+ *
+ * After that board/platform code must not call driver hook function! It
+ * is possible that pointer to hook function will not be valid and calling
+ * will cause undefined result.
+ */
+
+/* Supported modes with maximal current limit */
+enum bq2415x_mode {
+       BQ2415X_MODE_NONE,              /* unknown or no charger (100mA) */
+       BQ2415X_MODE_HOST_CHARGER,      /* usb host/hub charger (500mA) */
+       BQ2415X_MODE_DEDICATED_CHARGER, /* dedicated charger (unlimited) */
+       BQ2415X_MODE_BOOST,             /* boost mode (charging disabled) */
+};
+
+struct bq2415x_platform_data {
+       int current_limit;              /* mA */
+       int weak_battery_voltage;       /* mV */
+       int battery_regulation_voltage; /* mV */
+       int charge_current;             /* mA */
+       int termination_current;        /* mA */
+       int resistor_sense;             /* m ohm */
+       int (*set_mode_hook)(void (*hook)(enum bq2415x_mode mode, void *data),
+                            void *data);
+};
+
+#endif
index e5ef45834c3c415e05af46d66b0d38599c12ec85..1f0ab90aff00ccbfc5075d49225d9d56ef73e4c8 100644 (file)
@@ -114,6 +114,8 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
+       POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
        POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
        POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
        POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -186,6 +188,7 @@ struct power_supply {
        struct work_struct changed_work;
 #ifdef CONFIG_THERMAL
        struct thermal_zone_device *tzd;
+       struct thermal_cooling_device *tcd;
 #endif
 
 #ifdef CONFIG_LEDS_TRIGGERS
diff --git a/include/linux/pvclock_gtod.h b/include/linux/pvclock_gtod.h
new file mode 100644 (file)
index 0000000..0ca7582
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _PVCLOCK_GTOD_H
+#define _PVCLOCK_GTOD_H
+
+#include <linux/notifier.h>
+
+extern int pvclock_gtod_register_notifier(struct notifier_block *nb);
+extern int pvclock_gtod_unregister_notifier(struct notifier_block *nb);
+
+#endif /* _PVCLOCK_GTOD_H */
index c43cd3556b1f5b789bae79de586f7e85a4cafacc..7bc732ce6e50c5793f3db777d07a2ced422f91ef 100644 (file)
@@ -160,6 +160,7 @@ int regulator_bulk_force_disable(int num_consumers,
 void regulator_bulk_free(int num_consumers,
                         struct regulator_bulk_data *consumers);
 
+int regulator_can_change_voltage(struct regulator *regulator);
 int regulator_count_voltages(struct regulator *regulator);
 int regulator_list_voltage(struct regulator *regulator, unsigned selector);
 int regulator_is_supported_voltage(struct regulator *regulator,
@@ -358,6 +359,10 @@ static inline void regulator_set_drvdata(struct regulator *regulator,
 {
 }
 
+static inline int regulator_count_voltages(struct regulator *regulator)
+{
+       return 0;
+}
 #endif
 
 static inline int regulator_set_voltage_tol(struct regulator *regulator,
@@ -367,4 +372,12 @@ static inline int regulator_set_voltage_tol(struct regulator *regulator,
                                     new_uV - tol_uV, new_uV + tol_uV);
 }
 
+static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
+                                                    int target_uV, int tol_uV)
+{
+       return regulator_is_supported_voltage(regulator,
+                                             target_uV - tol_uV,
+                                             target_uV + tol_uV);
+}
+
 #endif
index 7932a3bf21bdba89f84275b7b990bcaa3a5773b0..d10bb0f39c5e72fd6bb7747e47761d062f75c981 100644 (file)
@@ -181,10 +181,13 @@ enum regulator_type {
  * @type: Indicates if the regulator is a voltage or current regulator.
  * @owner: Module providing the regulator, used for refcounting.
  *
+ * @continuous_voltage_range: Indicates if the regulator can set any
+ *                            voltage within constrains range.
  * @n_voltages: Number of selectors available for ops.list_voltage().
  *
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
+ * @linear_min_sel: Minimal selector for starting linear mapping
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @volt_table: Voltage mapping table (if table based mapping)
  *
@@ -199,6 +202,7 @@ struct regulator_desc {
        const char *name;
        const char *supply_name;
        int id;
+       bool continuous_voltage_range;
        unsigned n_voltages;
        struct regulator_ops *ops;
        int irq;
@@ -207,6 +211,7 @@ struct regulator_desc {
 
        unsigned int min_uV;
        unsigned int uV_step;
+       unsigned int linear_min_sel;
        unsigned int ramp_delay;
 
        const unsigned int *volt_table;
diff --git a/include/linux/regulator/max8973-regulator.h b/include/linux/regulator/max8973-regulator.h
new file mode 100644 (file)
index 0000000..f8acc05
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * max8973-regulator.h -- MAXIM 8973 regulator
+ *
+ * Interface for regulator driver for MAXIM 8973 DC-DC step-down
+ * switching regulator.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8973_H
+#define __LINUX_REGULATOR_MAX8973_H
+
+/*
+ * Control flags for configuration of the device.
+ * Client need to pass this information with ORed
+ */
+#define MAX8973_CONTROL_REMOTE_SENSE_ENABLE                    0x00000001
+#define MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE               0x00000002
+#define MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE             0x00000004
+#define MAX8973_CONTROL_BIAS_ENABLE                            0x00000008
+#define MAX8973_CONTROL_PULL_DOWN_ENABLE                       0x00000010
+#define MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE                 0x00000020
+
+#define MAX8973_CONTROL_CLKADV_TRIP_DISABLED                   0x00000000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US                        0x00010000
+#define MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US               0x00020000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS       0x00030000
+
+#define MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL                 0x00000000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER            0x00100000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER             0x00200000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER             0x00300000
+
+/*
+ * struct max8973_regulator_platform_data - max8973 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @control_flags: Control flags which are ORed value of above flags to
+ *             configure device.
+ * @enable_ext_control: Enable the voltage enable/disable through external
+ *             control signal from EN input pin. If it is false then
+ *             voltage output will be enabled/disabled through EN bit of
+ *             device register.
+ * @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic.
+ * @dvs_def_state: Default state of dvs. 1 if it is high else 0.
+ */
+struct max8973_regulator_platform_data {
+       struct regulator_init_data *reg_init_data;
+       unsigned long control_flags;
+       bool enable_ext_control;
+       int dvs_gpio;
+       unsigned dvs_def_state:1;
+};
+
+#endif /* __LINUX_REGULATOR_MAX8973_H */
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644 (file)
index 0000000..d00841e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * tps51632-regulator.h -- TPS51632 regulator
+ *
+ * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
+ * Driverless Controller with serial VID control and DVFS.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_TPS51632_H
+#define __LINUX_REGULATOR_TPS51632_H
+
+/*
+ * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_pwm_dvfs: Enable PWM DVFS or not.
+ * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
+ * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
+ * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
+ */
+struct tps51632_regulator_platform_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_pwm_dvfs;
+       bool dvfs_step_20mV;
+       int max_voltage_uV;
+       int base_voltage_uV;
+};
+
+#endif /* __LINUX_REGULATOR_TPS51632_H */
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
deleted file mode 100644 (file)
index 0fa04b6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Regulator driver interface for TI TPS65090 PMIC family
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __REGULATOR_TPS65090_H
-#define __REGULATOR_TPS65090_H
-
-#include <linux/regulator/machine.h>
-
-#define tps65090_rails(_name) "tps65090_"#_name
-
-enum {
-       TPS65090_ID_DCDC1,
-       TPS65090_ID_DCDC2,
-       TPS65090_ID_DCDC3,
-       TPS65090_ID_FET1,
-       TPS65090_ID_FET2,
-       TPS65090_ID_FET3,
-       TPS65090_ID_FET4,
-       TPS65090_ID_FET5,
-       TPS65090_ID_FET6,
-       TPS65090_ID_FET7,
-};
-
-/*
- * struct tps65090_regulator_platform_data
- *
- * @regulator: The regulator init data.
- * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
- */
-
-struct tps65090_regulator_platform_data {
-       struct regulator_init_data regulator;
-};
-
-#endif /* __REGULATOR_TPS65090_H */
index 7d7fbe2ef7822089c802c5654b4e0ec243f24a80..6f54e40fa218a3d09aa38aa49513d0c5616a83b5 100644 (file)
@@ -74,14 +74,9 @@ ssize_t res_counter_read(struct res_counter *counter, int member,
                const char __user *buf, size_t nbytes, loff_t *pos,
                int (*read_strategy)(unsigned long long val, char *s));
 
-typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val);
-
 int res_counter_memparse_write_strategy(const char *buf,
                                        unsigned long long *res);
 
-int res_counter_write(struct res_counter *counter, int member,
-                     const char *buffer, write_strategy_fn write_strategy);
-
 /*
  * the field descriptors. one for each member of res_counter
  */
index 651b51a36711103162ff9a9dc13eaca1c93bddc3..2c2f3072beef061faf0a2eb721ee2f05aad58d4a 100644 (file)
@@ -107,6 +107,14 @@ extern unsigned long this_cpu_load(void);
 extern void calc_global_load(unsigned long ticks);
 extern void update_cpu_load_nohz(void);
 
+/* Notifier for when a task gets migrated to a new CPU */
+struct task_migration_notifier {
+       struct task_struct *task;
+       int from_cpu;
+       int to_cpu;
+};
+extern void register_task_migration_notifier(struct notifier_block *n);
+
 extern unsigned long get_parent_ip(unsigned long addr);
 
 extern void dump_cpu_task(int cpu);
diff --git a/include/linux/spi/spi-tegra.h b/include/linux/spi/spi-tegra.h
new file mode 100644 (file)
index 0000000..786932c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * spi-tegra.h: SPI interface for Nvidia Tegra20 SLINK controller.
+ *
+ * Copyright (C) 2011 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _LINUX_SPI_TEGRA_H
+#define _LINUX_SPI_TEGRA_H
+
+struct tegra_spi_platform_data {
+       int dma_req_sel;
+       unsigned int spi_max_frequency;
+};
+
+/*
+ * Controller data from device to pass some info like
+ * hw based chip select can be used or not and if yes
+ * then CS hold and setup time.
+ */
+struct tegra_spi_device_controller_data {
+       bool is_hw_based_cs;
+       int cs_setup_clk_count;
+       int cs_hold_clk_count;
+};
+
+#endif /* _LINUX_SPI_TEGRA_H */
index fa702aeb5038d40b096e61cc65ba1b8d54d7ef39..f62918946d86502ed69b6668ee677c7abea343eb 100644 (file)
@@ -90,6 +90,7 @@ struct spi_device {
        void                    *controller_state;
        void                    *controller_data;
        char                    modalias[SPI_NAME_SIZE];
+       int                     cs_gpio;        /* chip select gpio */
 
        /*
         * likely need more hooks for more protocol options affecting how
@@ -362,6 +363,8 @@ struct spi_master {
        int (*transfer_one_message)(struct spi_master *master,
                                    struct spi_message *mesg);
        int (*unprepare_transfer_hardware)(struct spi_master *master);
+       /* gpio chip select */
+       int                     *cs_gpios;
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
index 1f64e3f1f22b52f5d1db2f57bfb69c4a80bca0e8..22958d68ecfe19016e721eb552cd5f901bbbbf89 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
+#include <linux/gpio.h>
 #include <linux/mod_devicetable.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
@@ -435,6 +436,9 @@ struct ssb_bus {
        spinlock_t gpio_lock;
        struct platform_device *watchdog;
 #endif /* EMBEDDED */
+#ifdef CONFIG_SSB_DRIVER_GPIO
+       struct gpio_chip gpio;
+#endif /* DRIVER_GPIO */
 
        /* Internal-only stuff follows. Do not touch. */
        struct list_head list;
index 38339fd68a5f101ee34393fab98ccfe7db2b0886..9e492be5244b40d8ead3340aa7ac475cb51e56ff 100644 (file)
@@ -590,6 +590,7 @@ struct ssb_chipcommon {
        u32 status;
        /* Fast Powerup Delay constant */
        u16 fast_pwrup_delay;
+       spinlock_t gpio_lock;
        struct ssb_chipcommon_pmu pmu;
        u32 ticks_per_ms;
        u32 max_timer_ms;
@@ -645,6 +646,8 @@ u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
 u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value);
 u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value);
 u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value);
 
 #ifdef CONFIG_SSB_SERIAL
 extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
index 99511d0e931d717dca4cabae0e70be102179e19f..a410e841eb9102a36835b6ad6be15ede096df7d3 100644 (file)
 
 struct ssb_extif {
        struct ssb_device *dev;
+       spinlock_t gpio_lock;
 };
 
 static inline bool ssb_extif_available(struct ssb_extif *extif)
index de5b2f8176ce27d5c1dad489129585e3296d0d0a..c1b3ed3fb78715fbe868ab531d07e20b00fc05cd 100644 (file)
@@ -61,7 +61,7 @@
 #define STMMAC_CSR_I_16                0xE     /* clk_csr_i/16 */
 #define STMMAC_CSR_I_18                0xF     /* clk_csr_i/18 */
 
-/* AXI DMA Burst length suported */
+/* AXI DMA Burst length supported */
 #define DMA_AXI_BLEN_4         (1 << 1)
 #define DMA_AXI_BLEN_8         (1 << 2)
 #define DMA_AXI_BLEN_16                (1 << 3)
index 0ee42d9acdc0f605dc0264b071834cb53dcd95e9..2c02f3a8d2ba3f4ba079a51f537be25742b17162 100644 (file)
@@ -78,7 +78,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
  *     This function acquires VGA resources for the given
  *     card and mark those resources locked. If the resource requested
  *     are "normal" (and not legacy) resources, the arbiter will first check
- *     wether the card is doing legacy decoding for that type of resource. If
+ *     whether the card is doing legacy decoding for that type of resource. If
  *     yes, the lock is "converted" into a legacy resource lock.
  *     The arbiter will first look for all VGA cards that might conflict
  *     and disable their IOs and/or Memory access, including VGA forwarding
@@ -89,7 +89,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
  *     This function will block if some conflicting card is already locking
  *     one of the required resources (or any resource on a different bus
  *     segment, since P2P bridges don't differenciate VGA memory and IO
- *     afaik). You can indicate wether this blocking should be interruptible
+ *     afaik). You can indicate whether this blocking should be interruptible
  *     by a signal (for userland interface) or not.
  *     Must not be called at interrupt time or in atomic context.
  *     If the card already owns the resources, the function succeeds.
index 3d3114594370118addc16ee1156e9b19f6d97fef..fe786f07d2bd9e0d3149fd72f8c629609e94d89e 100644 (file)
@@ -58,6 +58,8 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                THP_COLLAPSE_ALLOC,
                THP_COLLAPSE_ALLOC_FAILED,
                THP_SPLIT,
+               THP_ZERO_PAGE_ALLOC,
+               THP_ZERO_PAGE_ALLOC_FAILED,
 #endif
                NR_VM_EVENT_ITEMS
 };
index b7f45d48b2de6b4a81dcad34dd13ecc6e68443db..87490ac4bd87c72909aa8171e12ec8381af54f8c 100644 (file)
@@ -105,7 +105,7 @@ struct watchdog_device {
 #define WATCHDOG_NOWAYOUT_INIT_STATUS  0
 #endif
 
-/* Use the following function to check wether or not the watchdog is active */
+/* Use the following function to check whether or not the watchdog is active */
 static inline bool watchdog_active(struct watchdog_device *wdd)
 {
        return test_bit(WDOG_ACTIVE, &wdd->status);
index 50a1af88aed0b9b6d04d408bc5201fbd7876898e..1d9b48a3bd80aa0def7af5e8d76a7ecd28cdea59 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008--2011 Nokia Corporation
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * Contributors:
- *     Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *     Sakari Ailus <sakari.ailus@iki.fi>
  *     Tuukka Toivonen <tuukkat76@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
index dbf6b37682cd1c70f40b4bd06b8f99dc375527f0..8dffffedbb590ecaf7a5454fad2d84d21a557ebb 100644 (file)
@@ -16,7 +16,7 @@
 /* Header files */
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
 #include <media/davinci/vpbe_types.h>
 #include <media/davinci/vpbe_osd.h>
 #include <media/davinci/vpbe.h>
@@ -62,6 +62,11 @@ struct display_layer_info {
        enum osd_v_exp_ratio v_exp;
 };
 
+struct vpbe_disp_buffer {
+       struct vb2_buffer vb;
+       struct list_head list;
+};
+
 /* vpbe display object structure */
 struct vpbe_layer {
        /* number of buffers in fbuffers */
@@ -69,13 +74,15 @@ struct vpbe_layer {
        /* Pointer to the vpbe_display */
        struct vpbe_display *disp_dev;
        /* Pointer pointing to current v4l2_buffer */
-       struct videobuf_buffer *cur_frm;
+       struct vpbe_disp_buffer *cur_frm;
        /* Pointer pointing to next v4l2_buffer */
-       struct videobuf_buffer *next_frm;
+       struct vpbe_disp_buffer *next_frm;
        /* videobuf specific parameters
         * Buffer queue used in video-buf
         */
-       struct videobuf_queue buffer_queue;
+       struct vb2_queue buffer_queue;
+       /* allocator-specific contexts for each plane */
+       struct vb2_alloc_ctx *alloc_ctx;
        /* Queue of filled frames */
        struct list_head dma_queue;
        /* Used in video-buf */
index d7e397a444e68baa9a240646d927f692719b251c..5ab0d8d41f6827b6cd582e669e536de3b106ee69 100644 (file)
@@ -357,7 +357,7 @@ struct osd_state {
        spinlock_t lock;
        struct device *dev;
        dma_addr_t osd_base_phys;
-       unsigned long osd_base;
+       void __iomem *osd_base;
        unsigned long osd_size;
        /* 1-->the isr will toggle the VID0 ping-pong buffer */
        int pingpong;
index 768aa77925cd952049cff78ae1c6ff8116369d90..e221bc74020b2f5505e02f114789bb24a46d2fd1 100644 (file)
@@ -37,7 +37,7 @@ enum ir_kbd_get_key_fn {
 struct IR_i2c_init_data {
        char                    *ir_codes;
        const char              *name;
-       u64                     type; /* RC_TYPE_RC5, etc */
+       u64                     type; /* RC_BIT_RC5, etc */
        u32                     polling_interval; /* 0 means DEFAULT_POLLING_INTERVAL */
 
        /*
diff --git a/include/media/mt9v022.h b/include/media/mt9v022.h
new file mode 100644 (file)
index 0000000..4056180
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * mt9v022 sensor
+ *
+ * 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 __MT9V022_H__
+#define __MT9V022_H__
+
+struct mt9v022_platform_data {
+       unsigned short y_skip_top;      /* Lines to skip at the top */
+};
+
+#endif
index b0c494a6907904b9ceb38dac8be868f06b276d5a..f03445f3c767d662b2b08bb57830cfd1ae8c3892 100644 (file)
@@ -50,7 +50,7 @@ enum rc_driver_type {
  * @input_dev: the input child device used to communicate events to userspace
  * @driver_type: specifies if protocol decoding is done in hardware or software
  * @idle: used to keep track of RX state
- * @allowed_protos: bitmask with the supported RC_TYPE_* protocols
+ * @allowed_protos: bitmask with the supported RC_BIT_* protocols
  * @scanmask: some hardware decoders are not capable of providing the full
  *     scancode to the application. As this is a hardware limit, we can't do
  *     anything with it. Yet, as the same keycode table can be used with other
@@ -113,7 +113,7 @@ struct rc_dev {
        u32                             max_timeout;
        u32                             rx_resolution;
        u32                             tx_resolution;
-       int                             (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+       int                             (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
        int                             (*open)(struct rc_dev *dev);
        void                            (*close)(struct rc_dev *dev);
        int                             (*s_tx_mask)(struct rc_dev *dev, u32 mask);
index cfd5163ff7f3dc7dfb95cbe4ac8b00141a0cd9db..74f55a3f14eb80905186e927bd1d5f34bef070c6 100644 (file)
 
 #include <linux/input.h>
 
-#define RC_TYPE_UNKNOWN        0
-#define RC_TYPE_RC5    (1  << 0)       /* Philips RC5 protocol */
-#define RC_TYPE_NEC    (1  << 1)
-#define RC_TYPE_RC6    (1  << 2)       /* Philips RC6 protocol */
-#define RC_TYPE_JVC    (1  << 3)       /* JVC protocol */
-#define RC_TYPE_SONY   (1  << 4)       /* Sony12/15/20 protocol */
-#define RC_TYPE_RC5_SZ (1  << 5)       /* RC5 variant used by Streamzap */
-#define RC_TYPE_SANYO   (1  << 6)      /* Sanyo protocol */
-#define RC_TYPE_MCE_KBD        (1  << 29)      /* RC6-ish MCE keyboard/mouse */
-#define RC_TYPE_LIRC   (1  << 30)      /* Pass raw IR to lirc userspace */
-#define RC_TYPE_OTHER  (1u << 31)
+enum rc_type {
+       RC_TYPE_UNKNOWN         = 0,    /* Protocol not known */
+       RC_TYPE_OTHER           = 1,    /* Protocol known but proprietary */
+       RC_TYPE_LIRC            = 2,    /* Pass raw IR to lirc userspace */
+       RC_TYPE_RC5             = 3,    /* Philips RC5 protocol */
+       RC_TYPE_RC5X            = 4,    /* Philips RC5x protocol */
+       RC_TYPE_RC5_SZ          = 5,    /* StreamZap variant of RC5 */
+       RC_TYPE_JVC             = 6,    /* JVC protocol */
+       RC_TYPE_SONY12          = 7,    /* Sony 12 bit protocol */
+       RC_TYPE_SONY15          = 8,    /* Sony 15 bit protocol */
+       RC_TYPE_SONY20          = 9,    /* Sony 20 bit protocol */
+       RC_TYPE_NEC             = 10,   /* NEC protocol */
+       RC_TYPE_SANYO           = 11,   /* Sanyo protocol */
+       RC_TYPE_MCE_KBD         = 12,   /* RC6-ish MCE keyboard/mouse */
+       RC_TYPE_RC6_0           = 13,   /* Philips RC6-0-16 protocol */
+       RC_TYPE_RC6_6A_20       = 14,   /* Philips RC6-6A-20 protocol */
+       RC_TYPE_RC6_6A_24       = 15,   /* Philips RC6-6A-24 protocol */
+       RC_TYPE_RC6_6A_32       = 16,   /* Philips RC6-6A-32 protocol */
+       RC_TYPE_RC6_MCE         = 17,   /* MCE (Philips RC6-6A-32 subtype) protocol */
+};
+
+#define RC_BIT_NONE            0
+#define RC_BIT_UNKNOWN         (1 << RC_TYPE_UNKNOWN)
+#define RC_BIT_OTHER           (1 << RC_TYPE_OTHER)
+#define RC_BIT_LIRC            (1 << RC_TYPE_LIRC)
+#define RC_BIT_RC5             (1 << RC_TYPE_RC5)
+#define RC_BIT_RC5X            (1 << RC_TYPE_RC5X)
+#define RC_BIT_RC5_SZ          (1 << RC_TYPE_RC5_SZ)
+#define RC_BIT_JVC             (1 << RC_TYPE_JVC)
+#define RC_BIT_SONY12          (1 << RC_TYPE_SONY12)
+#define RC_BIT_SONY15          (1 << RC_TYPE_SONY15)
+#define RC_BIT_SONY20          (1 << RC_TYPE_SONY20)
+#define RC_BIT_NEC             (1 << RC_TYPE_NEC)
+#define RC_BIT_SANYO           (1 << RC_TYPE_SANYO)
+#define RC_BIT_MCE_KBD         (1 << RC_TYPE_MCE_KBD)
+#define RC_BIT_RC6_0           (1 << RC_TYPE_RC6_0)
+#define RC_BIT_RC6_6A_20       (1 << RC_TYPE_RC6_6A_20)
+#define RC_BIT_RC6_6A_24       (1 << RC_TYPE_RC6_6A_24)
+#define RC_BIT_RC6_6A_32       (1 << RC_TYPE_RC6_6A_32)
+#define RC_BIT_RC6_MCE         (1 << RC_TYPE_RC6_MCE)
 
-#define RC_TYPE_ALL (RC_TYPE_RC5    | RC_TYPE_NEC   | RC_TYPE_RC6     | \
-                    RC_TYPE_JVC    | RC_TYPE_SONY  | RC_TYPE_LIRC    | \
-                    RC_TYPE_RC5_SZ | RC_TYPE_SANYO | RC_TYPE_MCE_KBD | \
-                    RC_TYPE_OTHER)
+#define RC_BIT_ALL     (RC_BIT_UNKNOWN | RC_BIT_OTHER | RC_BIT_LIRC | \
+                        RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
+                        RC_BIT_JVC | \
+                        RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20 | \
+                        RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \
+                        RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
+                        RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)
 
 struct rc_map_table {
        u32     scancode;
@@ -38,7 +70,7 @@ struct rc_map {
        unsigned int            size;   /* Max number of entries */
        unsigned int            len;    /* Used number of entries */
        unsigned int            alloc;  /* Size of *scan in bytes */
-       u64                     rc_type;
+       enum rc_type            rc_type;
        const char              *name;
        spinlock_t              lock;
 };
diff --git a/include/media/s3c_camif.h b/include/media/s3c_camif.h
new file mode 100644 (file)
index 0000000..df96c2c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
+ *
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@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.
+*/
+
+#ifndef MEDIA_S3C_CAMIF_
+#define MEDIA_S3C_CAMIF_
+
+#include <linux/i2c.h>
+#include <media/v4l2-mediabus.h>
+
+/**
+ * struct s3c_camif_sensor_info - an image sensor description
+ * @i2c_board_info: pointer to an I2C sensor subdevice board info
+ * @clock_frequency: frequency of the clock the host provides to a sensor
+ * @mbus_type: media bus type
+ * @i2c_bus_num: i2c control bus id the sensor is attached to
+ * @flags: the parallel bus flags defining signals polarity (V4L2_MBUS_*)
+ * @use_field: 1 if parallel bus FIELD signal is used (only s3c64xx)
+ */
+struct s3c_camif_sensor_info {
+       struct i2c_board_info i2c_board_info;
+       unsigned long clock_frequency;
+       enum v4l2_mbus_type mbus_type;
+       u16 i2c_bus_num;
+       u16 flags;
+       u8 use_field;
+};
+
+struct s3c_camif_plat_data {
+       struct s3c_camif_sensor_info sensor;
+       int (*gpio_get)(void);
+       int (*gpio_put)(void);
+};
+
+/* Platform default helper functions */
+int s3c_camif_gpio_get(void);
+int s3c_camif_gpio_put(void);
+
+#endif /* MEDIA_S3C_CAMIF_ */
index 9ab07fd45d5cd1f71af1c5a8d98b90c5ff5794ba..07f96a89e189fa2a9414ca3ca8bb201b43b21ff4 100644 (file)
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index e7c5d170a9cd48c42ae8876d279c1be1dd0479ec..eff85f934b247a70f6a4cd6cd0b445ad79f23663 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 52513c225c182c6d8d5a4906b78a40a45834f112..a62ee18cb7b799c3982decdb63dc57f520e9b93a 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index e48b571ca37d512111125bd8f49463622b38aae2..4118ad1324c91a20dcdf8afafa080b9619986695 100644 (file)
@@ -111,6 +111,8 @@ struct v4l2_ioctl_ops {
        int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
        int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
        int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_expbuf)  (struct file *file, void *fh,
+                               struct v4l2_exportbuffer *e);
        int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
 
        int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
index 131cc4a53675eb97f14c7cd4c5355e06640200d7..7e82d2b193d5625702594fe59f1484e1b09c3d06 100644 (file)
@@ -111,6 +111,9 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
                   struct v4l2_buffer *buf);
 
+int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+                  struct v4l2_exportbuffer *eb);
+
 int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
                      enum v4l2_buf_type type);
 int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
index e04252a9fea65e5f5db25a901368e82a3aa8b4d6..9cfd4ee9e56f1eb7dec09704b15a4fabcbb976a4 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/videodev2.h>
+#include <linux/dma-buf.h>
 
 struct vb2_alloc_ctx;
 struct vb2_fileio_data;
@@ -41,6 +42,24 @@ struct vb2_fileio_data;
  *              argument to other ops in this structure
  * @put_userptr: inform the allocator that a USERPTR buffer will no longer
  *              be used
+ * @attach_dmabuf: attach a shared struct dma_buf for a hardware operation;
+ *                used for DMABUF memory types; alloc_ctx is the alloc context
+ *                dbuf is the shared dma_buf; returns NULL on failure;
+ *                allocator private per-buffer structure on success;
+ *                this needs to be used for further accesses to the buffer
+ * @detach_dmabuf: inform the exporter of the buffer that the current DMABUF
+ *                buffer is no longer used; the buf_priv argument is the
+ *                allocator private per-buffer structure previously returned
+ *                from the attach_dmabuf callback
+ * @map_dmabuf: request for access to the dmabuf from allocator; the allocator
+ *             of dmabuf is informed that this driver is going to use the
+ *             dmabuf
+ * @unmap_dmabuf: releases access control to the dmabuf - allocator is notified
+ *               that this driver is done using the dmabuf for now
+ * @prepare:   called every time the buffer is passed from userspace to the
+ *             driver, useful for cache synchronisation, optional
+ * @finish:    called every time the buffer is passed back from the driver
+ *             to the userspace, also optional
  * @vaddr:     return a kernel virtual address to a given memory buffer
  *             associated with the passed private structure or NULL if no
  *             such mapping exists
@@ -56,15 +75,27 @@ struct vb2_fileio_data;
  * Required ops for USERPTR types: get_userptr, put_userptr.
  * Required ops for MMAP types: alloc, put, num_users, mmap.
  * Required ops for read/write access types: alloc, put, num_users, vaddr
+ * Required ops for DMABUF types: attach_dmabuf, detach_dmabuf, map_dmabuf,
+ *                               unmap_dmabuf.
  */
 struct vb2_mem_ops {
        void            *(*alloc)(void *alloc_ctx, unsigned long size);
        void            (*put)(void *buf_priv);
+       struct dma_buf *(*get_dmabuf)(void *buf_priv);
 
        void            *(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
                                        unsigned long size, int write);
        void            (*put_userptr)(void *buf_priv);
 
+       void            (*prepare)(void *buf_priv);
+       void            (*finish)(void *buf_priv);
+
+       void            *(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
+                               unsigned long size, int write);
+       void            (*detach_dmabuf)(void *buf_priv);
+       int             (*map_dmabuf)(void *buf_priv);
+       void            (*unmap_dmabuf)(void *buf_priv);
+
        void            *(*vaddr)(void *buf_priv);
        void            *(*cookie)(void *buf_priv);
 
@@ -75,6 +106,8 @@ struct vb2_mem_ops {
 
 struct vb2_plane {
        void                    *mem_priv;
+       struct dma_buf          *dbuf;
+       unsigned int            dbuf_mapped;
 };
 
 /**
@@ -83,12 +116,14 @@ struct vb2_plane {
  * @VB2_USERPTR:       driver supports USERPTR with streaming API
  * @VB2_READ:          driver supports read() style access
  * @VB2_WRITE:         driver supports write() style access
+ * @VB2_DMABUF:                driver supports DMABUF with streaming API
  */
 enum vb2_io_modes {
        VB2_MMAP        = (1 << 0),
        VB2_USERPTR     = (1 << 1),
        VB2_READ        = (1 << 2),
        VB2_WRITE       = (1 << 3),
+       VB2_DMABUF      = (1 << 4),
 };
 
 /**
@@ -329,6 +364,7 @@ int __must_check vb2_queue_init(struct vb2_queue *q);
 void vb2_queue_release(struct vb2_queue *q);
 
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
 int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
 
 int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
@@ -438,6 +474,8 @@ int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
 int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
 int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
 int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
+int vb2_ioctl_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *p);
 
 /* struct v4l2_file_operations helpers */
 
index 84e1f6c031c53515367ef0ba26d641f2f6ff212c..f05444ca8c0cd4f8bf0469b3a4b0fe978fc359cc 100644 (file)
@@ -33,11 +33,6 @@ extern const struct vm_operations_struct vb2_common_vm_ops;
 int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
                           struct vm_area_struct **res_vma, dma_addr_t *res_pa);
 
-int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
-                               unsigned long size,
-                               const struct vm_operations_struct *vm_ops,
-                               void *priv);
-
 struct vm_area_struct *vb2_get_vma(struct vm_area_struct *vma);
 void vb2_put_vma(struct vm_area_struct *vma);
 
index fff11b7fe8a44c67e6641bcc39a48fb3278012da..591f78631f137f7a235e7dea3768ba6bbca47f61 100644 (file)
@@ -134,7 +134,7 @@ typedef struct {
 } CACHE_ENTRY;
 
 /*
- *  Information about each registred IrLAP layer
+ *  Information about each registered IrLAP layer
  */
 struct lap_cb {
        irda_queue_t queue; /* Must be first */
index 0a9a01a5b0d7bf9e2f88b3614165dbdcd1920a8c..93a6745bfdb2bb14933018a9bbc497e6b1c0cde7 100644 (file)
@@ -231,7 +231,7 @@ struct cg_proto;
   *    @sk_sndbuf: size of send buffer in bytes
   *    @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
   *               %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
-  *    @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+  *    @sk_no_check: %SO_NO_CHECK setting, whether or not checkup packets
   *    @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *    @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
   *    @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
index ea56f76c0c2208dd2a9aea0d599b67e3b51b6a18..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,6 +0,0 @@
-header-y += ib_user_cm.h
-header-y += ib_user_mad.h
-header-y += ib_user_sa.h
-header-y += ib_user_verbs.h
-header-y += rdma_netlink.h
-header-y += rdma_user_cm.h
diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h
deleted file mode 100644 (file)
index f79014a..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_CM_H
-#define IB_USER_CM_H
-
-#include <linux/types.h>
-#include <rdma/ib_user_sa.h>
-
-#define IB_USER_CM_ABI_VERSION 5
-
-enum {
-       IB_USER_CM_CMD_CREATE_ID,
-       IB_USER_CM_CMD_DESTROY_ID,
-       IB_USER_CM_CMD_ATTR_ID,
-
-       IB_USER_CM_CMD_LISTEN,
-       IB_USER_CM_CMD_NOTIFY,
-
-       IB_USER_CM_CMD_SEND_REQ,
-       IB_USER_CM_CMD_SEND_REP,
-       IB_USER_CM_CMD_SEND_RTU,
-       IB_USER_CM_CMD_SEND_DREQ,
-       IB_USER_CM_CMD_SEND_DREP,
-       IB_USER_CM_CMD_SEND_REJ,
-       IB_USER_CM_CMD_SEND_MRA,
-       IB_USER_CM_CMD_SEND_LAP,
-       IB_USER_CM_CMD_SEND_APR,
-       IB_USER_CM_CMD_SEND_SIDR_REQ,
-       IB_USER_CM_CMD_SEND_SIDR_REP,
-
-       IB_USER_CM_CMD_EVENT,
-       IB_USER_CM_CMD_INIT_QP_ATTR,
-};
-/*
- * command ABI structures.
- */
-struct ib_ucm_cmd_hdr {
-       __u32 cmd;
-       __u16 in;
-       __u16 out;
-};
-
-struct ib_ucm_create_id {
-       __u64 uid;
-       __u64 response;
-};
-
-struct ib_ucm_create_id_resp {
-       __u32 id;
-};
-
-struct ib_ucm_destroy_id {
-       __u64 response;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct ib_ucm_destroy_id_resp {
-       __u32 events_reported;
-};
-
-struct ib_ucm_attr_id {
-       __u64 response;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct ib_ucm_attr_id_resp {
-       __be64 service_id;
-       __be64 service_mask;
-       __be32 local_id;
-       __be32 remote_id;
-};
-
-struct ib_ucm_init_qp_attr {
-       __u64 response;
-       __u32 id;
-       __u32 qp_state;
-};
-
-struct ib_ucm_listen {
-       __be64 service_id;
-       __be64 service_mask;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct ib_ucm_notify {
-       __u32 id;
-       __u32 event;
-};
-
-struct ib_ucm_private_data {
-       __u64 data;
-       __u32 id;
-       __u8  len;
-       __u8  reserved[3];
-};
-
-struct ib_ucm_req {
-       __u32 id;
-       __u32 qpn;
-       __u32 qp_type;
-       __u32 psn;
-       __be64 sid;
-       __u64 data;
-       __u64 primary_path;
-       __u64 alternate_path;
-       __u8  len;
-       __u8  peer_to_peer;
-       __u8  responder_resources;
-       __u8  initiator_depth;
-       __u8  remote_cm_response_timeout;
-       __u8  flow_control;
-       __u8  local_cm_response_timeout;
-       __u8  retry_count;
-       __u8  rnr_retry_count;
-       __u8  max_cm_retries;
-       __u8  srq;
-       __u8  reserved[5];
-};
-
-struct ib_ucm_rep {
-       __u64 uid;
-       __u64 data;
-       __u32 id;
-       __u32 qpn;
-       __u32 psn;
-       __u8  len;
-       __u8  responder_resources;
-       __u8  initiator_depth;
-       __u8  target_ack_delay;
-       __u8  failover_accepted;
-       __u8  flow_control;
-       __u8  rnr_retry_count;
-       __u8  srq;
-       __u8  reserved[4];
-};
-
-struct ib_ucm_info {
-       __u32 id;
-       __u32 status;
-       __u64 info;
-       __u64 data;
-       __u8  info_len;
-       __u8  data_len;
-       __u8  reserved[6];
-};
-
-struct ib_ucm_mra {
-       __u64 data;
-       __u32 id;
-       __u8  len;
-       __u8  timeout;
-       __u8  reserved[2];
-};
-
-struct ib_ucm_lap {
-       __u64 path;
-       __u64 data;
-       __u32 id;
-       __u8  len;
-       __u8  reserved[3];
-};
-
-struct ib_ucm_sidr_req {
-       __u32 id;
-       __u32 timeout;
-       __be64 sid;
-       __u64 data;
-       __u64 path;
-       __u16 reserved_pkey;
-       __u8  len;
-       __u8  max_cm_retries;
-       __u8  reserved[4];
-};
-
-struct ib_ucm_sidr_rep {
-       __u32 id;
-       __u32 qpn;
-       __u32 qkey;
-       __u32 status;
-       __u64 info;
-       __u64 data;
-       __u8  info_len;
-       __u8  data_len;
-       __u8  reserved[6];
-};
-/*
- * event notification ABI structures.
- */
-struct ib_ucm_event_get {
-       __u64 response;
-       __u64 data;
-       __u64 info;
-       __u8  data_len;
-       __u8  info_len;
-       __u8  reserved[6];
-};
-
-struct ib_ucm_req_event_resp {
-       struct ib_user_path_rec primary_path;
-       struct ib_user_path_rec alternate_path;
-       __be64                 remote_ca_guid;
-       __u32                  remote_qkey;
-       __u32                  remote_qpn;
-       __u32                  qp_type;
-       __u32                  starting_psn;
-       __u8  responder_resources;
-       __u8  initiator_depth;
-       __u8  local_cm_response_timeout;
-       __u8  flow_control;
-       __u8  remote_cm_response_timeout;
-       __u8  retry_count;
-       __u8  rnr_retry_count;
-       __u8  srq;
-       __u8  port;
-       __u8  reserved[7];
-};
-
-struct ib_ucm_rep_event_resp {
-       __be64 remote_ca_guid;
-       __u32 remote_qkey;
-       __u32 remote_qpn;
-       __u32 starting_psn;
-       __u8  responder_resources;
-       __u8  initiator_depth;
-       __u8  target_ack_delay;
-       __u8  failover_accepted;
-       __u8  flow_control;
-       __u8  rnr_retry_count;
-       __u8  srq;
-       __u8  reserved[5];
-};
-
-struct ib_ucm_rej_event_resp {
-       __u32 reason;
-       /* ari in ib_ucm_event_get info field. */
-};
-
-struct ib_ucm_mra_event_resp {
-       __u8  timeout;
-       __u8  reserved[3];
-};
-
-struct ib_ucm_lap_event_resp {
-       struct ib_user_path_rec path;
-};
-
-struct ib_ucm_apr_event_resp {
-       __u32 status;
-       /* apr info in ib_ucm_event_get info field. */
-};
-
-struct ib_ucm_sidr_req_event_resp {
-       __u16 pkey;
-       __u8  port;
-       __u8  reserved;
-};
-
-struct ib_ucm_sidr_rep_event_resp {
-       __u32 status;
-       __u32 qkey;
-       __u32 qpn;
-       /* info in ib_ucm_event_get info field. */
-};
-
-#define IB_UCM_PRES_DATA      0x01
-#define IB_UCM_PRES_INFO      0x02
-#define IB_UCM_PRES_PRIMARY   0x04
-#define IB_UCM_PRES_ALTERNATE 0x08
-
-struct ib_ucm_event_resp {
-       __u64 uid;
-       __u32 id;
-       __u32 event;
-       __u32 present;
-       __u32 reserved;
-       union {
-               struct ib_ucm_req_event_resp req_resp;
-               struct ib_ucm_rep_event_resp rep_resp;
-               struct ib_ucm_rej_event_resp rej_resp;
-               struct ib_ucm_mra_event_resp mra_resp;
-               struct ib_ucm_lap_event_resp lap_resp;
-               struct ib_ucm_apr_event_resp apr_resp;
-
-               struct ib_ucm_sidr_req_event_resp sidr_req_resp;
-               struct ib_ucm_sidr_rep_event_resp sidr_rep_resp;
-
-               __u32                             send_status;
-       } u;
-};
-
-#endif /* IB_USER_CM_H */
diff --git a/include/rdma/ib_user_mad.h b/include/rdma/ib_user_mad.h
deleted file mode 100644 (file)
index d6fce1c..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_MAD_H
-#define IB_USER_MAD_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_MAD_ABI_VERSION        5
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- */
-
-/**
- * ib_user_mad_hdr_old - Old version of MAD packet header without pkey_index
- * @id - ID of agent MAD received with/to be sent with
- * @status - 0 on successful receive, ETIMEDOUT if no response
- *   received (transaction ID in data[] will be set to TID of original
- *   request) (ignored on send)
- * @timeout_ms - Milliseconds to wait for response (unset on receive)
- * @retries - Number of automatic retries to attempt
- * @qpn - Remote QP number received from/to be sent to
- * @qkey - Remote Q_Key to be sent with (unset on receive)
- * @lid - Remote lid received from/to be sent to
- * @sl - Service level received with/to be sent with
- * @path_bits - Local path bits received with/to be sent with
- * @grh_present - If set, GRH was received/should be sent
- * @gid_index - Local GID index to send with (unset on receive)
- * @hop_limit - Hop limit in GRH
- * @traffic_class - Traffic class in GRH
- * @gid - Remote GID in GRH
- * @flow_label - Flow label in GRH
- */
-struct ib_user_mad_hdr_old {
-       __u32   id;
-       __u32   status;
-       __u32   timeout_ms;
-       __u32   retries;
-       __u32   length;
-       __be32  qpn;
-       __be32  qkey;
-       __be16  lid;
-       __u8    sl;
-       __u8    path_bits;
-       __u8    grh_present;
-       __u8    gid_index;
-       __u8    hop_limit;
-       __u8    traffic_class;
-       __u8    gid[16];
-       __be32  flow_label;
-};
-
-/**
- * ib_user_mad_hdr - MAD packet header
- *   This layout allows specifying/receiving the P_Key index.  To use
- *   this capability, an application must call the
- *   IB_USER_MAD_ENABLE_PKEY ioctl on the user MAD file handle before
- *   any other actions with the file handle.
- * @id - ID of agent MAD received with/to be sent with
- * @status - 0 on successful receive, ETIMEDOUT if no response
- *   received (transaction ID in data[] will be set to TID of original
- *   request) (ignored on send)
- * @timeout_ms - Milliseconds to wait for response (unset on receive)
- * @retries - Number of automatic retries to attempt
- * @qpn - Remote QP number received from/to be sent to
- * @qkey - Remote Q_Key to be sent with (unset on receive)
- * @lid - Remote lid received from/to be sent to
- * @sl - Service level received with/to be sent with
- * @path_bits - Local path bits received with/to be sent with
- * @grh_present - If set, GRH was received/should be sent
- * @gid_index - Local GID index to send with (unset on receive)
- * @hop_limit - Hop limit in GRH
- * @traffic_class - Traffic class in GRH
- * @gid - Remote GID in GRH
- * @flow_label - Flow label in GRH
- * @pkey_index - P_Key index
- */
-struct ib_user_mad_hdr {
-       __u32   id;
-       __u32   status;
-       __u32   timeout_ms;
-       __u32   retries;
-       __u32   length;
-       __be32  qpn;
-       __be32  qkey;
-       __be16  lid;
-       __u8    sl;
-       __u8    path_bits;
-       __u8    grh_present;
-       __u8    gid_index;
-       __u8    hop_limit;
-       __u8    traffic_class;
-       __u8    gid[16];
-       __be32  flow_label;
-       __u16   pkey_index;
-       __u8    reserved[6];
-};
-
-/**
- * ib_user_mad - MAD packet
- * @hdr - MAD packet header
- * @data - Contents of MAD
- *
- */
-struct ib_user_mad {
-       struct ib_user_mad_hdr hdr;
-       __u64   data[0];
-};
-
-/*
- * Earlier versions of this interface definition declared the
- * method_mask[] member as an array of __u32 but treated it as a
- * bitmap made up of longs in the kernel.  This ambiguity meant that
- * 32-bit big-endian applications that can run on both 32-bit and
- * 64-bit kernels had no consistent ABI to rely on, and 64-bit
- * big-endian applications that treated method_mask as being made up
- * of 32-bit words would have their bitmap misinterpreted.
- *
- * To clear up this confusion, we change the declaration of
- * method_mask[] to use unsigned long and handle the conversion from
- * 32-bit userspace to 64-bit kernel for big-endian systems in the
- * compat_ioctl method.  Unfortunately, to keep the structure layout
- * the same, we need the method_mask[] array to be aligned only to 4
- * bytes even when long is 64 bits, which forces us into this ugly
- * typedef.
- */
-typedef unsigned long __attribute__((aligned(4))) packed_ulong;
-#define IB_USER_MAD_LONGS_PER_METHOD_MASK (128 / (8 * sizeof (long)))
-
-/**
- * ib_user_mad_reg_req - MAD registration request
- * @id - Set by the kernel; used to identify agent in future requests.
- * @qpn - Queue pair number; must be 0 or 1.
- * @method_mask - The caller will receive unsolicited MADs for any method
- *   where @method_mask = 1.
- * @mgmt_class - Indicates which management class of MADs should be receive
- *   by the caller.  This field is only required if the user wishes to
- *   receive unsolicited MADs, otherwise it should be 0.
- * @mgmt_class_version - Indicates which version of MADs for the given
- *   management class to receive.
- * @oui: Indicates IEEE OUI when mgmt_class is a vendor class
- *   in the range from 0x30 to 0x4f. Otherwise not used.
- * @rmpp_version: If set, indicates the RMPP version used.
- *
- */
-struct ib_user_mad_reg_req {
-       __u32   id;
-       packed_ulong method_mask[IB_USER_MAD_LONGS_PER_METHOD_MASK];
-       __u8    qpn;
-       __u8    mgmt_class;
-       __u8    mgmt_class_version;
-       __u8    oui[3];
-       __u8    rmpp_version;
-};
-
-#define IB_IOCTL_MAGIC         0x1b
-
-#define IB_USER_MAD_REGISTER_AGENT     _IOWR(IB_IOCTL_MAGIC, 1, \
-                                             struct ib_user_mad_reg_req)
-
-#define IB_USER_MAD_UNREGISTER_AGENT   _IOW(IB_IOCTL_MAGIC, 2, __u32)
-
-#define IB_USER_MAD_ENABLE_PKEY                _IO(IB_IOCTL_MAGIC, 3)
-
-#endif /* IB_USER_MAD_H */
diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h
deleted file mode 100644 (file)
index cfc7c9b..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2005 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_SA_H
-#define IB_USER_SA_H
-
-#include <linux/types.h>
-
-enum {
-       IB_PATH_GMP             = 1,
-       IB_PATH_PRIMARY         = (1<<1),
-       IB_PATH_ALTERNATE       = (1<<2),
-       IB_PATH_OUTBOUND        = (1<<3),
-       IB_PATH_INBOUND         = (1<<4),
-       IB_PATH_INBOUND_REVERSE = (1<<5),
-       IB_PATH_BIDIRECTIONAL   = IB_PATH_OUTBOUND | IB_PATH_INBOUND_REVERSE
-};
-
-struct ib_path_rec_data {
-       __u32   flags;
-       __u32   reserved;
-       __u32   path_rec[16];
-};
-
-struct ib_user_path_rec {
-       __u8    dgid[16];
-       __u8    sgid[16];
-       __be16  dlid;
-       __be16  slid;
-       __u32   raw_traffic;
-       __be32  flow_label;
-       __u32   reversible;
-       __u32   mtu;
-       __be16  pkey;
-       __u8    hop_limit;
-       __u8    traffic_class;
-       __u8    numb_path;
-       __u8    sl;
-       __u8    mtu_selector;
-       __u8    rate_selector;
-       __u8    rate;
-       __u8    packet_life_time_selector;
-       __u8    packet_life_time;
-       __u8    preference;
-};
-
-#endif /* IB_USER_SA_H */
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
deleted file mode 100644 (file)
index 81aba3a..0000000
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
- * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
- * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_VERBS_H
-#define IB_USER_VERBS_H
-
-#include <linux/types.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_VERBS_ABI_VERSION      6
-
-enum {
-       IB_USER_VERBS_CMD_GET_CONTEXT,
-       IB_USER_VERBS_CMD_QUERY_DEVICE,
-       IB_USER_VERBS_CMD_QUERY_PORT,
-       IB_USER_VERBS_CMD_ALLOC_PD,
-       IB_USER_VERBS_CMD_DEALLOC_PD,
-       IB_USER_VERBS_CMD_CREATE_AH,
-       IB_USER_VERBS_CMD_MODIFY_AH,
-       IB_USER_VERBS_CMD_QUERY_AH,
-       IB_USER_VERBS_CMD_DESTROY_AH,
-       IB_USER_VERBS_CMD_REG_MR,
-       IB_USER_VERBS_CMD_REG_SMR,
-       IB_USER_VERBS_CMD_REREG_MR,
-       IB_USER_VERBS_CMD_QUERY_MR,
-       IB_USER_VERBS_CMD_DEREG_MR,
-       IB_USER_VERBS_CMD_ALLOC_MW,
-       IB_USER_VERBS_CMD_BIND_MW,
-       IB_USER_VERBS_CMD_DEALLOC_MW,
-       IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
-       IB_USER_VERBS_CMD_CREATE_CQ,
-       IB_USER_VERBS_CMD_RESIZE_CQ,
-       IB_USER_VERBS_CMD_DESTROY_CQ,
-       IB_USER_VERBS_CMD_POLL_CQ,
-       IB_USER_VERBS_CMD_PEEK_CQ,
-       IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
-       IB_USER_VERBS_CMD_CREATE_QP,
-       IB_USER_VERBS_CMD_QUERY_QP,
-       IB_USER_VERBS_CMD_MODIFY_QP,
-       IB_USER_VERBS_CMD_DESTROY_QP,
-       IB_USER_VERBS_CMD_POST_SEND,
-       IB_USER_VERBS_CMD_POST_RECV,
-       IB_USER_VERBS_CMD_ATTACH_MCAST,
-       IB_USER_VERBS_CMD_DETACH_MCAST,
-       IB_USER_VERBS_CMD_CREATE_SRQ,
-       IB_USER_VERBS_CMD_MODIFY_SRQ,
-       IB_USER_VERBS_CMD_QUERY_SRQ,
-       IB_USER_VERBS_CMD_DESTROY_SRQ,
-       IB_USER_VERBS_CMD_POST_SRQ_RECV,
-       IB_USER_VERBS_CMD_OPEN_XRCD,
-       IB_USER_VERBS_CMD_CLOSE_XRCD,
-       IB_USER_VERBS_CMD_CREATE_XSRQ,
-       IB_USER_VERBS_CMD_OPEN_QP
-};
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- * Specifically:
- *  - Do not use pointer types -- pass pointers in __u64 instead.
- *  - Make sure that any structure larger than 4 bytes is padded to a
- *    multiple of 8 bytes.  Otherwise the structure size will be
- *    different between 32-bit and 64-bit architectures.
- */
-
-struct ib_uverbs_async_event_desc {
-       __u64 element;
-       __u32 event_type;       /* enum ib_event_type */
-       __u32 reserved;
-};
-
-struct ib_uverbs_comp_event_desc {
-       __u64 cq_handle;
-};
-
-/*
- * All commands from userspace should start with a __u32 command field
- * followed by __u16 in_words and out_words fields (which give the
- * length of the command block and response buffer if any in 32-bit
- * words).  The kernel driver will read these fields first and read
- * the rest of the command struct based on these value.
- */
-
-struct ib_uverbs_cmd_hdr {
-       __u32 command;
-       __u16 in_words;
-       __u16 out_words;
-};
-
-struct ib_uverbs_get_context {
-       __u64 response;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_get_context_resp {
-       __u32 async_fd;
-       __u32 num_comp_vectors;
-};
-
-struct ib_uverbs_query_device {
-       __u64 response;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_device_resp {
-       __u64 fw_ver;
-       __be64 node_guid;
-       __be64 sys_image_guid;
-       __u64 max_mr_size;
-       __u64 page_size_cap;
-       __u32 vendor_id;
-       __u32 vendor_part_id;
-       __u32 hw_ver;
-       __u32 max_qp;
-       __u32 max_qp_wr;
-       __u32 device_cap_flags;
-       __u32 max_sge;
-       __u32 max_sge_rd;
-       __u32 max_cq;
-       __u32 max_cqe;
-       __u32 max_mr;
-       __u32 max_pd;
-       __u32 max_qp_rd_atom;
-       __u32 max_ee_rd_atom;
-       __u32 max_res_rd_atom;
-       __u32 max_qp_init_rd_atom;
-       __u32 max_ee_init_rd_atom;
-       __u32 atomic_cap;
-       __u32 max_ee;
-       __u32 max_rdd;
-       __u32 max_mw;
-       __u32 max_raw_ipv6_qp;
-       __u32 max_raw_ethy_qp;
-       __u32 max_mcast_grp;
-       __u32 max_mcast_qp_attach;
-       __u32 max_total_mcast_qp_attach;
-       __u32 max_ah;
-       __u32 max_fmr;
-       __u32 max_map_per_fmr;
-       __u32 max_srq;
-       __u32 max_srq_wr;
-       __u32 max_srq_sge;
-       __u16 max_pkeys;
-       __u8  local_ca_ack_delay;
-       __u8  phys_port_cnt;
-       __u8  reserved[4];
-};
-
-struct ib_uverbs_query_port {
-       __u64 response;
-       __u8  port_num;
-       __u8  reserved[7];
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_port_resp {
-       __u32 port_cap_flags;
-       __u32 max_msg_sz;
-       __u32 bad_pkey_cntr;
-       __u32 qkey_viol_cntr;
-       __u32 gid_tbl_len;
-       __u16 pkey_tbl_len;
-       __u16 lid;
-       __u16 sm_lid;
-       __u8  state;
-       __u8  max_mtu;
-       __u8  active_mtu;
-       __u8  lmc;
-       __u8  max_vl_num;
-       __u8  sm_sl;
-       __u8  subnet_timeout;
-       __u8  init_type_reply;
-       __u8  active_width;
-       __u8  active_speed;
-       __u8  phys_state;
-       __u8  link_layer;
-       __u8  reserved[2];
-};
-
-struct ib_uverbs_alloc_pd {
-       __u64 response;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_alloc_pd_resp {
-       __u32 pd_handle;
-};
-
-struct ib_uverbs_dealloc_pd {
-       __u32 pd_handle;
-};
-
-struct ib_uverbs_open_xrcd {
-       __u64 response;
-       __u32 fd;
-       __u32 oflags;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_open_xrcd_resp {
-       __u32 xrcd_handle;
-};
-
-struct ib_uverbs_close_xrcd {
-       __u32 xrcd_handle;
-};
-
-struct ib_uverbs_reg_mr {
-       __u64 response;
-       __u64 start;
-       __u64 length;
-       __u64 hca_va;
-       __u32 pd_handle;
-       __u32 access_flags;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_reg_mr_resp {
-       __u32 mr_handle;
-       __u32 lkey;
-       __u32 rkey;
-};
-
-struct ib_uverbs_dereg_mr {
-       __u32 mr_handle;
-};
-
-struct ib_uverbs_create_comp_channel {
-       __u64 response;
-};
-
-struct ib_uverbs_create_comp_channel_resp {
-       __u32 fd;
-};
-
-struct ib_uverbs_create_cq {
-       __u64 response;
-       __u64 user_handle;
-       __u32 cqe;
-       __u32 comp_vector;
-       __s32 comp_channel;
-       __u32 reserved;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_create_cq_resp {
-       __u32 cq_handle;
-       __u32 cqe;
-};
-
-struct ib_uverbs_resize_cq {
-       __u64 response;
-       __u32 cq_handle;
-       __u32 cqe;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_resize_cq_resp {
-       __u32 cqe;
-       __u32 reserved;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_poll_cq {
-       __u64 response;
-       __u32 cq_handle;
-       __u32 ne;
-};
-
-struct ib_uverbs_wc {
-       __u64 wr_id;
-       __u32 status;
-       __u32 opcode;
-       __u32 vendor_err;
-       __u32 byte_len;
-       union {
-               __u32 imm_data;
-               __u32 invalidate_rkey;
-       } ex;
-       __u32 qp_num;
-       __u32 src_qp;
-       __u32 wc_flags;
-       __u16 pkey_index;
-       __u16 slid;
-       __u8 sl;
-       __u8 dlid_path_bits;
-       __u8 port_num;
-       __u8 reserved;
-};
-
-struct ib_uverbs_poll_cq_resp {
-       __u32 count;
-       __u32 reserved;
-       struct ib_uverbs_wc wc[0];
-};
-
-struct ib_uverbs_req_notify_cq {
-       __u32 cq_handle;
-       __u32 solicited_only;
-};
-
-struct ib_uverbs_destroy_cq {
-       __u64 response;
-       __u32 cq_handle;
-       __u32 reserved;
-};
-
-struct ib_uverbs_destroy_cq_resp {
-       __u32 comp_events_reported;
-       __u32 async_events_reported;
-};
-
-struct ib_uverbs_global_route {
-       __u8  dgid[16];
-       __u32 flow_label;
-       __u8  sgid_index;
-       __u8  hop_limit;
-       __u8  traffic_class;
-       __u8  reserved;
-};
-
-struct ib_uverbs_ah_attr {
-       struct ib_uverbs_global_route grh;
-       __u16 dlid;
-       __u8  sl;
-       __u8  src_path_bits;
-       __u8  static_rate;
-       __u8  is_global;
-       __u8  port_num;
-       __u8  reserved;
-};
-
-struct ib_uverbs_qp_attr {
-       __u32   qp_attr_mask;
-       __u32   qp_state;
-       __u32   cur_qp_state;
-       __u32   path_mtu;
-       __u32   path_mig_state;
-       __u32   qkey;
-       __u32   rq_psn;
-       __u32   sq_psn;
-       __u32   dest_qp_num;
-       __u32   qp_access_flags;
-
-       struct ib_uverbs_ah_attr ah_attr;
-       struct ib_uverbs_ah_attr alt_ah_attr;
-
-       /* ib_qp_cap */
-       __u32   max_send_wr;
-       __u32   max_recv_wr;
-       __u32   max_send_sge;
-       __u32   max_recv_sge;
-       __u32   max_inline_data;
-
-       __u16   pkey_index;
-       __u16   alt_pkey_index;
-       __u8    en_sqd_async_notify;
-       __u8    sq_draining;
-       __u8    max_rd_atomic;
-       __u8    max_dest_rd_atomic;
-       __u8    min_rnr_timer;
-       __u8    port_num;
-       __u8    timeout;
-       __u8    retry_cnt;
-       __u8    rnr_retry;
-       __u8    alt_port_num;
-       __u8    alt_timeout;
-       __u8    reserved[5];
-};
-
-struct ib_uverbs_create_qp {
-       __u64 response;
-       __u64 user_handle;
-       __u32 pd_handle;
-       __u32 send_cq_handle;
-       __u32 recv_cq_handle;
-       __u32 srq_handle;
-       __u32 max_send_wr;
-       __u32 max_recv_wr;
-       __u32 max_send_sge;
-       __u32 max_recv_sge;
-       __u32 max_inline_data;
-       __u8  sq_sig_all;
-       __u8  qp_type;
-       __u8  is_srq;
-       __u8  reserved;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_open_qp {
-       __u64 response;
-       __u64 user_handle;
-       __u32 pd_handle;
-       __u32 qpn;
-       __u8  qp_type;
-       __u8  reserved[7];
-       __u64 driver_data[0];
-};
-
-/* also used for open response */
-struct ib_uverbs_create_qp_resp {
-       __u32 qp_handle;
-       __u32 qpn;
-       __u32 max_send_wr;
-       __u32 max_recv_wr;
-       __u32 max_send_sge;
-       __u32 max_recv_sge;
-       __u32 max_inline_data;
-       __u32 reserved;
-};
-
-/*
- * This struct needs to remain a multiple of 8 bytes to keep the
- * alignment of the modify QP parameters.
- */
-struct ib_uverbs_qp_dest {
-       __u8  dgid[16];
-       __u32 flow_label;
-       __u16 dlid;
-       __u16 reserved;
-       __u8  sgid_index;
-       __u8  hop_limit;
-       __u8  traffic_class;
-       __u8  sl;
-       __u8  src_path_bits;
-       __u8  static_rate;
-       __u8  is_global;
-       __u8  port_num;
-};
-
-struct ib_uverbs_query_qp {
-       __u64 response;
-       __u32 qp_handle;
-       __u32 attr_mask;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_qp_resp {
-       struct ib_uverbs_qp_dest dest;
-       struct ib_uverbs_qp_dest alt_dest;
-       __u32 max_send_wr;
-       __u32 max_recv_wr;
-       __u32 max_send_sge;
-       __u32 max_recv_sge;
-       __u32 max_inline_data;
-       __u32 qkey;
-       __u32 rq_psn;
-       __u32 sq_psn;
-       __u32 dest_qp_num;
-       __u32 qp_access_flags;
-       __u16 pkey_index;
-       __u16 alt_pkey_index;
-       __u8  qp_state;
-       __u8  cur_qp_state;
-       __u8  path_mtu;
-       __u8  path_mig_state;
-       __u8  sq_draining;
-       __u8  max_rd_atomic;
-       __u8  max_dest_rd_atomic;
-       __u8  min_rnr_timer;
-       __u8  port_num;
-       __u8  timeout;
-       __u8  retry_cnt;
-       __u8  rnr_retry;
-       __u8  alt_port_num;
-       __u8  alt_timeout;
-       __u8  sq_sig_all;
-       __u8  reserved[5];
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_modify_qp {
-       struct ib_uverbs_qp_dest dest;
-       struct ib_uverbs_qp_dest alt_dest;
-       __u32 qp_handle;
-       __u32 attr_mask;
-       __u32 qkey;
-       __u32 rq_psn;
-       __u32 sq_psn;
-       __u32 dest_qp_num;
-       __u32 qp_access_flags;
-       __u16 pkey_index;
-       __u16 alt_pkey_index;
-       __u8  qp_state;
-       __u8  cur_qp_state;
-       __u8  path_mtu;
-       __u8  path_mig_state;
-       __u8  en_sqd_async_notify;
-       __u8  max_rd_atomic;
-       __u8  max_dest_rd_atomic;
-       __u8  min_rnr_timer;
-       __u8  port_num;
-       __u8  timeout;
-       __u8  retry_cnt;
-       __u8  rnr_retry;
-       __u8  alt_port_num;
-       __u8  alt_timeout;
-       __u8  reserved[2];
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_modify_qp_resp {
-};
-
-struct ib_uverbs_destroy_qp {
-       __u64 response;
-       __u32 qp_handle;
-       __u32 reserved;
-};
-
-struct ib_uverbs_destroy_qp_resp {
-       __u32 events_reported;
-};
-
-/*
- * The ib_uverbs_sge structure isn't used anywhere, since we assume
- * the ib_sge structure is packed the same way on 32-bit and 64-bit
- * architectures in both kernel and user space.  It's just here to
- * document the ABI.
- */
-struct ib_uverbs_sge {
-       __u64 addr;
-       __u32 length;
-       __u32 lkey;
-};
-
-struct ib_uverbs_send_wr {
-       __u64 wr_id;
-       __u32 num_sge;
-       __u32 opcode;
-       __u32 send_flags;
-       union {
-               __u32 imm_data;
-               __u32 invalidate_rkey;
-       } ex;
-       union {
-               struct {
-                       __u64 remote_addr;
-                       __u32 rkey;
-                       __u32 reserved;
-               } rdma;
-               struct {
-                       __u64 remote_addr;
-                       __u64 compare_add;
-                       __u64 swap;
-                       __u32 rkey;
-                       __u32 reserved;
-               } atomic;
-               struct {
-                       __u32 ah;
-                       __u32 remote_qpn;
-                       __u32 remote_qkey;
-                       __u32 reserved;
-               } ud;
-       } wr;
-};
-
-struct ib_uverbs_post_send {
-       __u64 response;
-       __u32 qp_handle;
-       __u32 wr_count;
-       __u32 sge_count;
-       __u32 wqe_size;
-       struct ib_uverbs_send_wr send_wr[0];
-};
-
-struct ib_uverbs_post_send_resp {
-       __u32 bad_wr;
-};
-
-struct ib_uverbs_recv_wr {
-       __u64 wr_id;
-       __u32 num_sge;
-       __u32 reserved;
-};
-
-struct ib_uverbs_post_recv {
-       __u64 response;
-       __u32 qp_handle;
-       __u32 wr_count;
-       __u32 sge_count;
-       __u32 wqe_size;
-       struct ib_uverbs_recv_wr recv_wr[0];
-};
-
-struct ib_uverbs_post_recv_resp {
-       __u32 bad_wr;
-};
-
-struct ib_uverbs_post_srq_recv {
-       __u64 response;
-       __u32 srq_handle;
-       __u32 wr_count;
-       __u32 sge_count;
-       __u32 wqe_size;
-       struct ib_uverbs_recv_wr recv[0];
-};
-
-struct ib_uverbs_post_srq_recv_resp {
-       __u32 bad_wr;
-};
-
-struct ib_uverbs_create_ah {
-       __u64 response;
-       __u64 user_handle;
-       __u32 pd_handle;
-       __u32 reserved;
-       struct ib_uverbs_ah_attr attr;
-};
-
-struct ib_uverbs_create_ah_resp {
-       __u32 ah_handle;
-};
-
-struct ib_uverbs_destroy_ah {
-       __u32 ah_handle;
-};
-
-struct ib_uverbs_attach_mcast {
-       __u8  gid[16];
-       __u32 qp_handle;
-       __u16 mlid;
-       __u16 reserved;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_detach_mcast {
-       __u8  gid[16];
-       __u32 qp_handle;
-       __u16 mlid;
-       __u16 reserved;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_create_srq {
-       __u64 response;
-       __u64 user_handle;
-       __u32 pd_handle;
-       __u32 max_wr;
-       __u32 max_sge;
-       __u32 srq_limit;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_create_xsrq {
-       __u64 response;
-       __u64 user_handle;
-       __u32 srq_type;
-       __u32 pd_handle;
-       __u32 max_wr;
-       __u32 max_sge;
-       __u32 srq_limit;
-       __u32 reserved;
-       __u32 xrcd_handle;
-       __u32 cq_handle;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_create_srq_resp {
-       __u32 srq_handle;
-       __u32 max_wr;
-       __u32 max_sge;
-       __u32 srqn;
-};
-
-struct ib_uverbs_modify_srq {
-       __u32 srq_handle;
-       __u32 attr_mask;
-       __u32 max_wr;
-       __u32 srq_limit;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_srq {
-       __u64 response;
-       __u32 srq_handle;
-       __u32 reserved;
-       __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_srq_resp {
-       __u32 max_wr;
-       __u32 max_sge;
-       __u32 srq_limit;
-       __u32 reserved;
-};
-
-struct ib_uverbs_destroy_srq {
-       __u64 response;
-       __u32 srq_handle;
-       __u32 reserved;
-};
-
-struct ib_uverbs_destroy_srq_resp {
-       __u32 events_reported;
-};
-
-#endif /* IB_USER_VERBS_H */
index bd3d8b24b42024f848ffd0c55f2dc58dc6de1b28..e38de79eeb48f9070a65d806a38eff84a3f92914 100644 (file)
@@ -1,41 +1,9 @@
 #ifndef _RDMA_NETLINK_H
 #define _RDMA_NETLINK_H
 
-#include <linux/types.h>
-
-enum {
-       RDMA_NL_RDMA_CM = 1
-};
-
-#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10)
-#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
-#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
-
-enum {
-       RDMA_NL_RDMA_CM_ID_STATS = 0,
-       RDMA_NL_RDMA_CM_NUM_OPS
-};
-
-enum {
-       RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
-       RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
-       RDMA_NL_RDMA_CM_NUM_ATTR,
-};
-
-struct rdma_cm_id_stats {
-       __u32   qp_num;
-       __u32   bound_dev_if;
-       __u32   port_space;
-       __s32   pid;
-       __u8    cm_state;
-       __u8    node_type;
-       __u8    port_num;
-       __u8    qp_type;
-};
-
-#ifdef __KERNEL__
 
 #include <linux/netlink.h>
+#include <uapi/rdma/rdma_netlink.h>
 
 struct ibnl_client_cbs {
        int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb);
@@ -88,6 +56,4 @@ void *ibnl_put_msg(struct sk_buff *skb, struct nlmsghdr **nlh, int seq,
 int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
                  int len, void *data, int type);
 
-#endif /* __KERNEL__ */
-
 #endif /* _RDMA_NETLINK_H */
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
deleted file mode 100644 (file)
index 1ee9239..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef RDMA_USER_CM_H
-#define RDMA_USER_CM_H
-
-#include <linux/types.h>
-#include <linux/in6.h>
-#include <rdma/ib_user_verbs.h>
-#include <rdma/ib_user_sa.h>
-
-#define RDMA_USER_CM_ABI_VERSION       4
-
-#define RDMA_MAX_PRIVATE_DATA          256
-
-enum {
-       RDMA_USER_CM_CMD_CREATE_ID,
-       RDMA_USER_CM_CMD_DESTROY_ID,
-       RDMA_USER_CM_CMD_BIND_ADDR,
-       RDMA_USER_CM_CMD_RESOLVE_ADDR,
-       RDMA_USER_CM_CMD_RESOLVE_ROUTE,
-       RDMA_USER_CM_CMD_QUERY_ROUTE,
-       RDMA_USER_CM_CMD_CONNECT,
-       RDMA_USER_CM_CMD_LISTEN,
-       RDMA_USER_CM_CMD_ACCEPT,
-       RDMA_USER_CM_CMD_REJECT,
-       RDMA_USER_CM_CMD_DISCONNECT,
-       RDMA_USER_CM_CMD_INIT_QP_ATTR,
-       RDMA_USER_CM_CMD_GET_EVENT,
-       RDMA_USER_CM_CMD_GET_OPTION,
-       RDMA_USER_CM_CMD_SET_OPTION,
-       RDMA_USER_CM_CMD_NOTIFY,
-       RDMA_USER_CM_CMD_JOIN_MCAST,
-       RDMA_USER_CM_CMD_LEAVE_MCAST,
-       RDMA_USER_CM_CMD_MIGRATE_ID
-};
-
-/*
- * command ABI structures.
- */
-struct rdma_ucm_cmd_hdr {
-       __u32 cmd;
-       __u16 in;
-       __u16 out;
-};
-
-struct rdma_ucm_create_id {
-       __u64 uid;
-       __u64 response;
-       __u16 ps;
-       __u8  qp_type;
-       __u8  reserved[5];
-};
-
-struct rdma_ucm_create_id_resp {
-       __u32 id;
-};
-
-struct rdma_ucm_destroy_id {
-       __u64 response;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct rdma_ucm_destroy_id_resp {
-       __u32 events_reported;
-};
-
-struct rdma_ucm_bind_addr {
-       __u64 response;
-       struct sockaddr_in6 addr;
-       __u32 id;
-};
-
-struct rdma_ucm_resolve_addr {
-       struct sockaddr_in6 src_addr;
-       struct sockaddr_in6 dst_addr;
-       __u32 id;
-       __u32 timeout_ms;
-};
-
-struct rdma_ucm_resolve_route {
-       __u32 id;
-       __u32 timeout_ms;
-};
-
-struct rdma_ucm_query_route {
-       __u64 response;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct rdma_ucm_query_route_resp {
-       __u64 node_guid;
-       struct ib_user_path_rec ib_route[2];
-       struct sockaddr_in6 src_addr;
-       struct sockaddr_in6 dst_addr;
-       __u32 num_paths;
-       __u8 port_num;
-       __u8 reserved[3];
-};
-
-struct rdma_ucm_conn_param {
-       __u32 qp_num;
-       __u32 reserved;
-       __u8  private_data[RDMA_MAX_PRIVATE_DATA];
-       __u8  private_data_len;
-       __u8  srq;
-       __u8  responder_resources;
-       __u8  initiator_depth;
-       __u8  flow_control;
-       __u8  retry_count;
-       __u8  rnr_retry_count;
-       __u8  valid;
-};
-
-struct rdma_ucm_ud_param {
-       __u32 qp_num;
-       __u32 qkey;
-       struct ib_uverbs_ah_attr ah_attr;
-       __u8  private_data[RDMA_MAX_PRIVATE_DATA];
-       __u8  private_data_len;
-       __u8  reserved[7];
-};
-
-struct rdma_ucm_connect {
-       struct rdma_ucm_conn_param conn_param;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct rdma_ucm_listen {
-       __u32 id;
-       __u32 backlog;
-};
-
-struct rdma_ucm_accept {
-       __u64 uid;
-       struct rdma_ucm_conn_param conn_param;
-       __u32 id;
-       __u32 reserved;
-};
-
-struct rdma_ucm_reject {
-       __u32 id;
-       __u8  private_data_len;
-       __u8  reserved[3];
-       __u8  private_data[RDMA_MAX_PRIVATE_DATA];
-};
-
-struct rdma_ucm_disconnect {
-       __u32 id;
-};
-
-struct rdma_ucm_init_qp_attr {
-       __u64 response;
-       __u32 id;
-       __u32 qp_state;
-};
-
-struct rdma_ucm_notify {
-       __u32 id;
-       __u32 event;
-};
-
-struct rdma_ucm_join_mcast {
-       __u64 response;         /* rdma_ucm_create_id_resp */
-       __u64 uid;
-       struct sockaddr_in6 addr;
-       __u32 id;
-};
-
-struct rdma_ucm_get_event {
-       __u64 response;
-};
-
-struct rdma_ucm_event_resp {
-       __u64 uid;
-       __u32 id;
-       __u32 event;
-       __u32 status;
-       union {
-               struct rdma_ucm_conn_param conn;
-               struct rdma_ucm_ud_param   ud;
-       } param;
-};
-
-/* Option levels */
-enum {
-       RDMA_OPTION_ID          = 0,
-       RDMA_OPTION_IB          = 1
-};
-
-/* Option details */
-enum {
-       RDMA_OPTION_ID_TOS       = 0,
-       RDMA_OPTION_ID_REUSEADDR = 1,
-       RDMA_OPTION_ID_AFONLY    = 2,
-       RDMA_OPTION_IB_PATH      = 1
-};
-
-struct rdma_ucm_set_option {
-       __u64 optval;
-       __u32 id;
-       __u32 level;
-       __u32 optname;
-       __u32 optlen;
-};
-
-struct rdma_ucm_migrate_id {
-       __u64 response;
-       __u32 id;
-       __u32 fd;
-};
-
-struct rdma_ucm_migrate_resp {
-       __u32 events_reported;
-};
-
-#endif /* RDMA_USER_CM_H */
index 55367b04dc9445e142369e98d2134d459eb5ef83..e65c62e82c5a6db8577667faabe95539f3893b47 100644 (file)
@@ -137,6 +137,7 @@ struct scsi_device {
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
        unsigned no_report_opcodes:1;   /* no REPORT SUPPORTED OPERATION CODES */
        unsigned no_write_same:1;       /* no WRITE SAME command */
+       unsigned use_16_for_rw:1; /* Use read/write(16) over read/write(10) */
        unsigned skip_ms_page_8:1;      /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;     /* do not use MODE SENSE page 0x3f */
        unsigned skip_vpd_pages:1;      /* do not read VPD pages */
index 98b3a20a01026be42c16bbf742f067347d186680..9b8e08879cfc9d7f7038245cf12e9b162f0f7f4e 100644 (file)
@@ -36,6 +36,7 @@ enum sas_linkrate {
        SAS_LINK_RATE_3_0_GBPS = 9,
        SAS_LINK_RATE_G2 = SAS_LINK_RATE_3_0_GBPS,
        SAS_LINK_RATE_6_0_GBPS = 10,
+       SAS_LINK_RATE_12_0_GBPS = 11,
        /* These are virtual to the transport class and may never
         * be signalled normally since the standard defined field
         * is only 4 bits */
index 9c60ca1c08c5a12ac77ba84f3d046cbd21fc60df..ff0f04ac91aad7c2311f9b889aa09c0accb90cc6 100644 (file)
@@ -14,13 +14,21 @@ struct srp_rport_identifiers {
 };
 
 struct srp_rport {
+       /* for initiator and target drivers */
+
        struct device dev;
 
        u8 port_id[16];
        u8 roles;
+
+       /* for initiator drivers */
+
+       void *lld_data; /* LLD private data */
 };
 
 struct srp_function_template {
+       /* for initiator drivers */
+       void (*rport_delete)(struct srp_rport *rport);
        /* for target drivers */
        int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
        int (* it_nexus_response)(struct Scsi_Host *, u64, int);
index 6df30ed1581c5b750f13335a3fd1b1743e05159e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,10 +0,0 @@
-header-y += asequencer.h
-header-y += asound.h
-header-y += asound_fm.h
-header-y += emu10k1.h
-header-y += hdsp.h
-header-y += hdspm.h
-header-y += sb16_csp.h
-header-y += sfnt_info.h
-header-y += compress_params.h
-header-y += compress_offload.h
index 1505e6d5ef8241081c24c74b6218e01a37afc8d2..75935ce739c555109feeadf97347d5beb75528a0 100644 (file)
 #ifndef __SOUND_ASEQUENCER_H
 #define __SOUND_ASEQUENCER_H
 
-#ifdef __KERNEL__
 #include <linux/ioctl.h>
 #include <sound/asound.h>
-#endif
-
-/** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
-
-/**
- * definition of sequencer event types
- */
-
-/** system messages
- * event data type = #snd_seq_result
- */
-#define SNDRV_SEQ_EVENT_SYSTEM         0
-#define SNDRV_SEQ_EVENT_RESULT         1
-
-/** note messages (channel specific)
- * event data type = #snd_seq_ev_note
- */
-#define SNDRV_SEQ_EVENT_NOTE           5
-#define SNDRV_SEQ_EVENT_NOTEON         6
-#define SNDRV_SEQ_EVENT_NOTEOFF                7
-#define SNDRV_SEQ_EVENT_KEYPRESS       8
-       
-/** control messages (channel specific)
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_CONTROLLER     10
-#define SNDRV_SEQ_EVENT_PGMCHANGE      11
-#define SNDRV_SEQ_EVENT_CHANPRESS      12
-#define SNDRV_SEQ_EVENT_PITCHBEND      13      /**< from -8192 to 8191 */
-#define SNDRV_SEQ_EVENT_CONTROL14      14      /**< 14 bit controller value */
-#define SNDRV_SEQ_EVENT_NONREGPARAM    15      /**< 14 bit NRPN address + 14 bit unsigned value */
-#define SNDRV_SEQ_EVENT_REGPARAM       16      /**< 14 bit RPN address + 14 bit unsigned value */
-
-/** synchronisation messages
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_SONGPOS                20      /* Song Position Pointer with LSB and MSB values */
-#define SNDRV_SEQ_EVENT_SONGSEL                21      /* Song Select with song ID number */
-#define SNDRV_SEQ_EVENT_QFRAME         22      /* midi time code quarter frame */
-#define SNDRV_SEQ_EVENT_TIMESIGN       23      /* SMF Time Signature event */
-#define SNDRV_SEQ_EVENT_KEYSIGN                24      /* SMF Key Signature event */
-               
-/** timer messages
- * event data type = snd_seq_ev_queue_control
- */
-#define SNDRV_SEQ_EVENT_START          30      /* midi Real Time Start message */
-#define SNDRV_SEQ_EVENT_CONTINUE       31      /* midi Real Time Continue message */
-#define SNDRV_SEQ_EVENT_STOP           32      /* midi Real Time Stop message */       
-#define        SNDRV_SEQ_EVENT_SETPOS_TICK     33      /* set tick queue position */
-#define SNDRV_SEQ_EVENT_SETPOS_TIME    34      /* set realtime queue position */
-#define SNDRV_SEQ_EVENT_TEMPO          35      /* (SMF) Tempo event */
-#define SNDRV_SEQ_EVENT_CLOCK          36      /* midi Real Time Clock message */
-#define SNDRV_SEQ_EVENT_TICK           37      /* midi Real Time Tick message */
-#define SNDRV_SEQ_EVENT_QUEUE_SKEW     38      /* skew queue tempo */
-
-/** others
- * event data type = none
- */
-#define SNDRV_SEQ_EVENT_TUNE_REQUEST   40      /* tune request */
-#define SNDRV_SEQ_EVENT_RESET          41      /* reset to power-on state */
-#define SNDRV_SEQ_EVENT_SENSING                42      /* "active sensing" event */
-
-/** echo back, kernel private messages
- * event data type = any type
- */
-#define SNDRV_SEQ_EVENT_ECHO           50      /* echo event */
-#define SNDRV_SEQ_EVENT_OSS            51      /* OSS raw event */
-
-/** system status messages (broadcast for subscribers)
- * event data type = snd_seq_addr
- */
-#define SNDRV_SEQ_EVENT_CLIENT_START   60      /* new client has connected */
-#define SNDRV_SEQ_EVENT_CLIENT_EXIT    61      /* client has left the system */
-#define SNDRV_SEQ_EVENT_CLIENT_CHANGE  62      /* client status/info has changed */
-#define SNDRV_SEQ_EVENT_PORT_START     63      /* new port was created */
-#define SNDRV_SEQ_EVENT_PORT_EXIT      64      /* port was deleted from system */
-#define SNDRV_SEQ_EVENT_PORT_CHANGE    65      /* port status/info has changed */
-
-/** port connection changes
- * event data type = snd_seq_connect
- */
-#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED        66      /* ports connected */
-#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67   /* ports disconnected */
-
-/* 70-89:  synthesizer events - obsoleted */
-
-/** user-defined events with fixed length
- * event data type = any
- */
-#define SNDRV_SEQ_EVENT_USR0           90
-#define SNDRV_SEQ_EVENT_USR1           91
-#define SNDRV_SEQ_EVENT_USR2           92
-#define SNDRV_SEQ_EVENT_USR3           93
-#define SNDRV_SEQ_EVENT_USR4           94
-#define SNDRV_SEQ_EVENT_USR5           95
-#define SNDRV_SEQ_EVENT_USR6           96
-#define SNDRV_SEQ_EVENT_USR7           97
-#define SNDRV_SEQ_EVENT_USR8           98
-#define SNDRV_SEQ_EVENT_USR9           99
-
-/* 100-118: instrument layer - obsoleted */
-/* 119-129: reserved */
-
-/* 130-139: variable length events
- * event data type = snd_seq_ev_ext
- * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
- */
-#define SNDRV_SEQ_EVENT_SYSEX          130     /* system exclusive data (variable length) */
-#define SNDRV_SEQ_EVENT_BOUNCE         131     /* error event */
-/* 132-134: reserved */
-#define SNDRV_SEQ_EVENT_USR_VAR0       135
-#define SNDRV_SEQ_EVENT_USR_VAR1       136
-#define SNDRV_SEQ_EVENT_USR_VAR2       137
-#define SNDRV_SEQ_EVENT_USR_VAR3       138
-#define SNDRV_SEQ_EVENT_USR_VAR4       139
-
-/* 150-151: kernel events with quote - DO NOT use in user clients */
-#define SNDRV_SEQ_EVENT_KERNEL_ERROR   150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE   151     /* obsolete */
-
-/* 152-191: reserved */
-
-/* 192-254: hardware specific events */
-
-/* 255: special event */
-#define SNDRV_SEQ_EVENT_NONE           255
-
-
-typedef unsigned char snd_seq_event_type_t;
-
-/** event address */
-struct snd_seq_addr {
-       unsigned char client;   /**< Client number:         0..255, 255 = broadcast to all clients */
-       unsigned char port;     /**< Port within client:    0..255, 255 = broadcast to all ports */
-};
-
-/** port connection */
-struct snd_seq_connect {
-       struct snd_seq_addr sender;
-       struct snd_seq_addr dest;
-};
-
-
-#define SNDRV_SEQ_ADDRESS_UNKNOWN      253     /* unknown source */
-#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS  254     /* send event to all subscribed ports */
-#define SNDRV_SEQ_ADDRESS_BROADCAST    255     /* send event to all queues/clients/ports/channels */
-#define SNDRV_SEQ_QUEUE_DIRECT         253     /* direct dispatch */
-
-       /* event mode flag - NOTE: only 8 bits available! */
-#define SNDRV_SEQ_TIME_STAMP_TICK      (0<<0) /* timestamp in clock ticks */
-#define SNDRV_SEQ_TIME_STAMP_REAL      (1<<0) /* timestamp in real time */
-#define SNDRV_SEQ_TIME_STAMP_MASK      (1<<0)
-
-#define SNDRV_SEQ_TIME_MODE_ABS                (0<<1)  /* absolute timestamp */
-#define SNDRV_SEQ_TIME_MODE_REL                (1<<1)  /* relative to current time */
-#define SNDRV_SEQ_TIME_MODE_MASK       (1<<1)
-
-#define SNDRV_SEQ_EVENT_LENGTH_FIXED   (0<<2)  /* fixed event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE        (1<<2)  /* variable event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARUSR  (2<<2)  /* variable event size - user memory space */
-#define SNDRV_SEQ_EVENT_LENGTH_MASK    (3<<2)
-
-#define SNDRV_SEQ_PRIORITY_NORMAL      (0<<4)  /* normal priority */
-#define SNDRV_SEQ_PRIORITY_HIGH                (1<<4)  /* event should be processed before others */
-#define SNDRV_SEQ_PRIORITY_MASK                (1<<4)
-
-
-       /* note event */
-struct snd_seq_ev_note {
-       unsigned char channel;
-       unsigned char note;
-       unsigned char velocity;
-       unsigned char off_velocity;     /* only for SNDRV_SEQ_EVENT_NOTE */
-       unsigned int duration;          /* only for SNDRV_SEQ_EVENT_NOTE */
-};
-
-       /* controller event */
-struct snd_seq_ev_ctrl {
-       unsigned char channel;
-       unsigned char unused1, unused2, unused3;        /* pad */
-       unsigned int param;
-       signed int value;
-};
-
-       /* generic set of bytes (12x8 bit) */
-struct snd_seq_ev_raw8 {
-       unsigned char d[12];    /* 8 bit value */
-};
-
-       /* generic set of integers (3x32 bit) */
-struct snd_seq_ev_raw32 {
-       unsigned int d[3];      /* 32 bit value */
-};
-
-       /* external stored data */
-struct snd_seq_ev_ext {
-       unsigned int len;       /* length of data */
-       void *ptr;              /* pointer to data (note: maybe 64-bit) */
-} __attribute__((packed));
-
-struct snd_seq_result {
-       int event;              /* processed event type */
-       int result;
-};
-
-
-struct snd_seq_real_time {
-       unsigned int tv_sec;    /* seconds */
-       unsigned int tv_nsec;   /* nanoseconds */
-};
-
-typedef unsigned int snd_seq_tick_time_t;      /* midi ticks */
-
-union snd_seq_timestamp {
-       snd_seq_tick_time_t tick;
-       struct snd_seq_real_time time;
-};
-
-struct snd_seq_queue_skew {
-       unsigned int value;
-       unsigned int base;
-};
-
-       /* queue timer control */
-struct snd_seq_ev_queue_control {
-       unsigned char queue;                    /* affected queue */
-       unsigned char pad[3];                   /* reserved */
-       union {
-               signed int value;               /* affected value (e.g. tempo) */
-               union snd_seq_timestamp time;   /* time */
-               unsigned int position;          /* sync position */
-               struct snd_seq_queue_skew skew;
-               unsigned int d32[2];
-               unsigned char d8[8];
-       } param;
-};
-
-       /* quoted event - inside the kernel only */
-struct snd_seq_ev_quote {
-       struct snd_seq_addr origin;             /* original sender */
-       unsigned short value;           /* optional data */
-       struct snd_seq_event *event;            /* quoted event */
-} __attribute__((packed));
-
-
-       /* sequencer event */
-struct snd_seq_event {
-       snd_seq_event_type_t type;      /* event type */
-       unsigned char flags;            /* event flags */
-       char tag;
-       
-       unsigned char queue;            /* schedule queue */
-       union snd_seq_timestamp time;   /* schedule time */
-
-
-       struct snd_seq_addr source;     /* source address */
-       struct snd_seq_addr dest;       /* destination address */
-
-       union {                         /* event data... */
-               struct snd_seq_ev_note note;
-               struct snd_seq_ev_ctrl control;
-               struct snd_seq_ev_raw8 raw8;
-               struct snd_seq_ev_raw32 raw32;
-               struct snd_seq_ev_ext ext;
-               struct snd_seq_ev_queue_control queue;
-               union snd_seq_timestamp time;
-               struct snd_seq_addr addr;
-               struct snd_seq_connect connect;
-               struct snd_seq_result result;
-               struct snd_seq_ev_quote quote;
-       } data;
-};
-
-
-/*
- * bounce event - stored as variable size data
- */
-struct snd_seq_event_bounce {
-       int err;
-       struct snd_seq_event event;
-       /* external data follows here. */
-};
-
-#ifdef __KERNEL__
+#include <uapi/sound/asequencer.h>
 
 /* helper macro */
 #define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce)))
@@ -368,311 +83,4 @@ struct snd_seq_event_bounce {
 /* queue sync port */
 #define snd_seq_queue_sync_port(q)     ((q) + 16)
 
-#endif /* __KERNEL__ */
-
-       /* system information */
-struct snd_seq_system_info {
-       int queues;                     /* maximum queues count */
-       int clients;                    /* maximum clients count */
-       int ports;                      /* maximum ports per client */
-       int channels;                   /* maximum channels per port */
-       int cur_clients;                /* current clients */
-       int cur_queues;                 /* current queues */
-       char reserved[24];
-};
-
-
-       /* system running information */
-struct snd_seq_running_info {
-       unsigned char client;           /* client id */
-       unsigned char big_endian;       /* 1 = big-endian */
-       unsigned char cpu_mode;         /* 4 = 32bit, 8 = 64bit */
-       unsigned char pad;              /* reserved */
-       unsigned char reserved[12];
-};
-
-
-       /* known client numbers */
-#define SNDRV_SEQ_CLIENT_SYSTEM                0
-       /* internal client numbers */
-#define SNDRV_SEQ_CLIENT_DUMMY         14      /* midi through */
-#define SNDRV_SEQ_CLIENT_OSS           15      /* oss sequencer emulator */
-
-
-       /* client types */
-typedef int __bitwise snd_seq_client_type_t;
-#define        NO_CLIENT       ((__force snd_seq_client_type_t) 0)
-#define        USER_CLIENT     ((__force snd_seq_client_type_t) 1)
-#define        KERNEL_CLIENT   ((__force snd_seq_client_type_t) 2)
-                        
-       /* event filter flags */
-#define SNDRV_SEQ_FILTER_BROADCAST     (1<<0)  /* accept broadcast messages */
-#define SNDRV_SEQ_FILTER_MULTICAST     (1<<1)  /* accept multicast messages */
-#define SNDRV_SEQ_FILTER_BOUNCE                (1<<2)  /* accept bounce event in error */
-#define SNDRV_SEQ_FILTER_USE_EVENT     (1<<31) /* use event filter */
-
-struct snd_seq_client_info {
-       int client;                     /* client number to inquire */
-       snd_seq_client_type_t type;     /* client type */
-       char name[64];                  /* client name */
-       unsigned int filter;            /* filter flags */
-       unsigned char multicast_filter[8]; /* multicast filter bitmap */
-       unsigned char event_filter[32]; /* event filter bitmap */
-       int num_ports;                  /* RO: number of ports */
-       int event_lost;                 /* number of lost events */
-       char reserved[64];              /* for future use */
-};
-
-
-/* client pool size */
-struct snd_seq_client_pool {
-       int client;                     /* client number to inquire */
-       int output_pool;                /* outgoing (write) pool size */
-       int input_pool;                 /* incoming (read) pool size */
-       int output_room;                /* minimum free pool size for select/blocking mode */
-       int output_free;                /* unused size */
-       int input_free;                 /* unused size */
-       char reserved[64];
-};
-
-
-/* Remove events by specified criteria */
-
-#define SNDRV_SEQ_REMOVE_INPUT         (1<<0)  /* Flush input queues */
-#define SNDRV_SEQ_REMOVE_OUTPUT                (1<<1)  /* Flush output queues */
-#define SNDRV_SEQ_REMOVE_DEST          (1<<2)  /* Restrict by destination q:client:port */
-#define SNDRV_SEQ_REMOVE_DEST_CHANNEL  (1<<3)  /* Restrict by channel */
-#define SNDRV_SEQ_REMOVE_TIME_BEFORE   (1<<4)  /* Restrict to before time */
-#define SNDRV_SEQ_REMOVE_TIME_AFTER    (1<<5)  /* Restrict to time or after */
-#define SNDRV_SEQ_REMOVE_TIME_TICK     (1<<6)  /* Time is in ticks */
-#define SNDRV_SEQ_REMOVE_EVENT_TYPE    (1<<7)  /* Restrict to event type */
-#define SNDRV_SEQ_REMOVE_IGNORE_OFF    (1<<8)  /* Do not flush off events */
-#define SNDRV_SEQ_REMOVE_TAG_MATCH     (1<<9)  /* Restrict to events with given tag */
-
-struct snd_seq_remove_events {
-       unsigned int  remove_mode;      /* Flags that determine what gets removed */
-
-       union snd_seq_timestamp time;
-
-       unsigned char queue;    /* Queue for REMOVE_DEST */
-       struct snd_seq_addr dest;       /* Address for REMOVE_DEST */
-       unsigned char channel;  /* Channel for REMOVE_DEST */
-
-       int  type;      /* For REMOVE_EVENT_TYPE */
-       char  tag;      /* Tag for REMOVE_TAG */
-
-       int  reserved[10];      /* To allow for future binary compatibility */
-
-};
-
-
-       /* known port numbers */
-#define SNDRV_SEQ_PORT_SYSTEM_TIMER    0
-#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
-
-       /* port capabilities (32 bits) */
-#define SNDRV_SEQ_PORT_CAP_READ                (1<<0)  /* readable from this port */
-#define SNDRV_SEQ_PORT_CAP_WRITE       (1<<1)  /* writable to this port */
-
-#define SNDRV_SEQ_PORT_CAP_SYNC_READ   (1<<2)
-#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE  (1<<3)
-
-#define SNDRV_SEQ_PORT_CAP_DUPLEX      (1<<4)
-
-#define SNDRV_SEQ_PORT_CAP_SUBS_READ   (1<<5)  /* allow read subscription */
-#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE  (1<<6)  /* allow write subscription */
-#define SNDRV_SEQ_PORT_CAP_NO_EXPORT   (1<<7)  /* routing not allowed */
-
-       /* port type */
-#define SNDRV_SEQ_PORT_TYPE_SPECIFIC   (1<<0)  /* hardware specific */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1)        /* generic MIDI device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM    (1<<2)  /* General MIDI compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GS    (1<<3)  /* GS compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_XG    (1<<4)  /* XG compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32  (1<<5)  /* MT-32 compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2   (1<<6)  /* General MIDI 2 compatible device */
-
-/* other standards...*/
-#define SNDRV_SEQ_PORT_TYPE_SYNTH      (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
-#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)      /* Sampling device (support sample download) */
-#define SNDRV_SEQ_PORT_TYPE_SAMPLE     (1<<12) /* Sampling device (sample can be downloaded at any time) */
-/*...*/
-#define SNDRV_SEQ_PORT_TYPE_HARDWARE   (1<<16) /* driver for a hardware device */
-#define SNDRV_SEQ_PORT_TYPE_SOFTWARE   (1<<17) /* implemented in software */
-#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER        (1<<18) /* generates sound */
-#define SNDRV_SEQ_PORT_TYPE_PORT       (1<<19) /* connects to other device(s) */
-#define SNDRV_SEQ_PORT_TYPE_APPLICATION        (1<<20) /* application (sequencer/editor) */
-
-/* misc. conditioning flags */
-#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT  (1<<0)
-#define SNDRV_SEQ_PORT_FLG_TIMESTAMP   (1<<1)
-#define SNDRV_SEQ_PORT_FLG_TIME_REAL   (1<<2)
-
-struct snd_seq_port_info {
-       struct snd_seq_addr addr;       /* client/port numbers */
-       char name[64];                  /* port name */
-
-       unsigned int capability;        /* port capability bits */
-       unsigned int type;              /* port type bits */
-       int midi_channels;              /* channels per MIDI port */
-       int midi_voices;                /* voices per MIDI port */
-       int synth_voices;               /* voices per SYNTH port */
-
-       int read_use;                   /* R/O: subscribers for output (from this port) */
-       int write_use;                  /* R/O: subscribers for input (to this port) */
-
-       void *kernel;                   /* reserved for kernel use (must be NULL) */
-       unsigned int flags;             /* misc. conditioning */
-       unsigned char time_queue;       /* queue # for timestamping */
-       char reserved[59];              /* for future use */
-};
-
-
-/* queue flags */
-#define SNDRV_SEQ_QUEUE_FLG_SYNC       (1<<0)  /* sync enabled */
-
-/* queue information */
-struct snd_seq_queue_info {
-       int queue;              /* queue id */
-
-       /*
-        *  security settings, only owner of this queue can start/stop timer
-        *  etc. if the queue is locked for other clients
-        */
-       int owner;              /* client id for owner of the queue */
-       unsigned locked:1;      /* timing queue locked for other queues */
-       char name[64];          /* name of this queue */
-       unsigned int flags;     /* flags */
-       char reserved[60];      /* for future use */
-
-};
-
-/* queue info/status */
-struct snd_seq_queue_status {
-       int queue;                      /* queue id */
-       int events;                     /* read-only - queue size */
-       snd_seq_tick_time_t tick;       /* current tick */
-       struct snd_seq_real_time time;  /* current time */
-       int running;                    /* running state of queue */
-       int flags;                      /* various flags */
-       char reserved[64];              /* for the future */
-};
-
-
-/* queue tempo */
-struct snd_seq_queue_tempo {
-       int queue;                      /* sequencer queue */
-       unsigned int tempo;             /* current tempo, us/tick */
-       int ppq;                        /* time resolution, ticks/quarter */
-       unsigned int skew_value;        /* queue skew */
-       unsigned int skew_base;         /* queue skew base */
-       char reserved[24];              /* for the future */
-};
-
-
-/* sequencer timer sources */
-#define SNDRV_SEQ_TIMER_ALSA           0       /* ALSA timer */
-#define SNDRV_SEQ_TIMER_MIDI_CLOCK     1       /* Midi Clock (CLOCK event) */
-#define SNDRV_SEQ_TIMER_MIDI_TICK      2       /* Midi Timer Tick (TICK event) */
-
-/* queue timer info */
-struct snd_seq_queue_timer {
-       int queue;                      /* sequencer queue */
-       int type;                       /* source timer type */
-       union {
-               struct {
-                       struct snd_timer_id id; /* ALSA's timer ID */
-                       unsigned int resolution;        /* resolution in Hz */
-               } alsa;
-       } u;
-       char reserved[64];              /* for the future use */
-};
-
-
-struct snd_seq_queue_client {
-       int queue;              /* sequencer queue */
-       int client;             /* sequencer client */
-       int used;               /* queue is used with this client
-                                  (must be set for accepting events) */
-       /* per client watermarks */
-       char reserved[64];      /* for future use */
-};
-
-
-#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE  (1<<0)  /* exclusive connection */
-#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP  (1<<1)
-#define SNDRV_SEQ_PORT_SUBS_TIME_REAL  (1<<2)
-
-struct snd_seq_port_subscribe {
-       struct snd_seq_addr sender;     /* sender address */
-       struct snd_seq_addr dest;       /* destination address */
-       unsigned int voices;            /* number of voices to be allocated (0 = don't care) */
-       unsigned int flags;             /* modes */
-       unsigned char queue;            /* input time-stamp queue (optional) */
-       unsigned char pad[3];           /* reserved */
-       char reserved[64];
-};
-
-/* type of query subscription */
-#define SNDRV_SEQ_QUERY_SUBS_READ      0
-#define SNDRV_SEQ_QUERY_SUBS_WRITE     1
-
-struct snd_seq_query_subs {
-       struct snd_seq_addr root;       /* client/port id to be searched */
-       int type;               /* READ or WRITE */
-       int index;              /* 0..N-1 */
-       int num_subs;           /* R/O: number of subscriptions on this port */
-       struct snd_seq_addr addr;       /* R/O: result */
-       unsigned char queue;    /* R/O: result */
-       unsigned int flags;     /* R/O: result */
-       char reserved[64];      /* for future use */
-};
-
-
-/*
- *  IOCTL commands
- */
-
-#define SNDRV_SEQ_IOCTL_PVERSION       _IOR ('S', 0x00, int)
-#define SNDRV_SEQ_IOCTL_CLIENT_ID      _IOR ('S', 0x01, int)
-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO    _IOWR('S', 0x02, struct snd_seq_system_info)
-#define SNDRV_SEQ_IOCTL_RUNNING_MODE   _IOWR('S', 0x03, struct snd_seq_running_info)
-
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO        _IOWR('S', 0x10, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO        _IOW ('S', 0x11, struct snd_seq_client_info)
-
-#define SNDRV_SEQ_IOCTL_CREATE_PORT    _IOWR('S', 0x20, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_DELETE_PORT    _IOW ('S', 0x21, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO  _IOWR('S', 0x22, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO  _IOW ('S', 0x23, struct snd_seq_port_info)
-
-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
-
-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE   _IOWR('S', 0x32, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE   _IOW ('S', 0x33, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE        _IOWR('S', 0x36, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO        _IOWR('S', 0x41, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO        _IOW ('S', 0x42, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER        _IOWR('S', 0x43, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER        _IOW ('S', 0x44, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER        _IOWR('S', 0x45, struct snd_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER        _IOW ('S', 0x46, struct snd_seq_queue_timer)
-/* XXX
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
-*/
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT       _IOWR('S', 0x49, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT       _IOW ('S', 0x4a, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL        _IOWR('S', 0x4b, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL        _IOW ('S', 0x4c, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS  _IOW ('S', 0x4e, struct snd_seq_remove_events)
-#define SNDRV_SEQ_IOCTL_QUERY_SUBS     _IOWR('S', 0x4f, struct snd_seq_query_subs)
-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION       _IOWR('S', 0x50, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT      _IOWR('S', 0x51, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT        _IOWR('S', 0x52, struct snd_seq_port_info)
-
 #endif /* __SOUND_ASEQUENCER_H */
index dfe7d441748c208501d0cc3c3806ba293da9b862..c2dff5369d339d07f181ab5fd75887e976cfffb0 100644 (file)
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
-
 #ifndef __SOUND_ASOUND_H
 #define __SOUND_ASOUND_H
 
-#include <linux/types.h>
-
-#ifdef __KERNEL__
 #include <linux/ioctl.h>
 #include <linux/time.h>
 #include <asm/byteorder.h>
 #endif
 #endif
 
-#endif /* __KERNEL__ **/
-
-/*
- *  protocol version
- */
-
-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
-       (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
-        (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
-          SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
-
-/****************************************************************************
- *                                                                          *
- *        Digital audio interface                                          *
- *                                                                          *
- ****************************************************************************/
-
-struct snd_aes_iec958 {
-       unsigned char status[24];       /* AES/IEC958 channel status bits */
-       unsigned char subcode[147];     /* AES/IEC958 subcode bits */
-       unsigned char pad;              /* nothing */
-       unsigned char dig_subframe[4];  /* AES/IEC958 subframe bits */
-};
-
-/****************************************************************************
- *                                                                          *
- *        CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort                    *
- *                                                                          *
- ****************************************************************************/
-
-struct snd_cea_861_aud_if {
-       unsigned char db1_ct_cc; /* coding type and channel count */
-       unsigned char db2_sf_ss; /* sample frequency and size */
-       unsigned char db3; /* not used, all zeros */
-       unsigned char db4_ca; /* channel allocation code */
-       unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
-};
-
-/****************************************************************************
- *                                                                          *
- *      Section for driver hardware dependent interface - /dev/snd/hw?      *
- *                                                                          *
- ****************************************************************************/
-
-#define SNDRV_HWDEP_VERSION            SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-enum {
-       SNDRV_HWDEP_IFACE_OPL2 = 0,
-       SNDRV_HWDEP_IFACE_OPL3,
-       SNDRV_HWDEP_IFACE_OPL4,
-       SNDRV_HWDEP_IFACE_SB16CSP,      /* Creative Signal Processor */
-       SNDRV_HWDEP_IFACE_EMU10K1,      /* FX8010 processor in EMU10K1 chip */
-       SNDRV_HWDEP_IFACE_YSS225,       /* Yamaha FX processor */
-       SNDRV_HWDEP_IFACE_ICS2115,      /* Wavetable synth */
-       SNDRV_HWDEP_IFACE_SSCAPE,       /* Ensoniq SoundScape ISA card (MC68EC000) */
-       SNDRV_HWDEP_IFACE_VX,           /* Digigram VX cards */
-       SNDRV_HWDEP_IFACE_MIXART,       /* Digigram miXart cards */
-       SNDRV_HWDEP_IFACE_USX2Y,        /* Tascam US122, US224 & US428 usb */
-       SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */  
-       SNDRV_HWDEP_IFACE_BLUETOOTH,    /* Bluetooth audio */
-       SNDRV_HWDEP_IFACE_USX2Y_PCM,    /* Tascam US122, US224 & US428 rawusb pcm */
-       SNDRV_HWDEP_IFACE_PCXHR,        /* Digigram PCXHR */
-       SNDRV_HWDEP_IFACE_SB_RC,        /* SB Extigy/Audigy2NX remote control */
-       SNDRV_HWDEP_IFACE_HDA,          /* HD-audio */
-       SNDRV_HWDEP_IFACE_USB_STREAM,   /* direct access to usb stream */
-
-       /* Don't forget to change the following: */
-       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
-};
-
-struct snd_hwdep_info {
-       unsigned int device;            /* WR: device number */
-       int card;                       /* R: card number */
-       unsigned char id[64];           /* ID (user selectable) */
-       unsigned char name[80];         /* hwdep name */
-       int iface;                      /* hwdep interface */
-       unsigned char reserved[64];     /* reserved for future */
-};
-
-/* generic DSP loader */
-struct snd_hwdep_dsp_status {
-       unsigned int version;           /* R: driver-specific version */
-       unsigned char id[32];           /* R: driver-specific ID string */
-       unsigned int num_dsps;          /* R: number of DSP images to transfer */
-       unsigned int dsp_loaded;        /* R: bit flags indicating the loaded DSPs */
-       unsigned int chip_ready;        /* R: 1 = initialization finished */
-       unsigned char reserved[16];     /* reserved for future use */
-};
-
-struct snd_hwdep_dsp_image {
-       unsigned int index;             /* W: DSP index */
-       unsigned char name[64];         /* W: ID (e.g. file name) */
-       unsigned char __user *image;    /* W: binary image */
-       size_t length;                  /* W: size of image in bytes */
-       unsigned long driver_data;      /* W: driver-specific data */
-};
-
-#define SNDRV_HWDEP_IOCTL_PVERSION     _IOR ('H', 0x00, int)
-#define SNDRV_HWDEP_IOCTL_INFO         _IOR ('H', 0x01, struct snd_hwdep_info)
-#define SNDRV_HWDEP_IOCTL_DSP_STATUS   _IOR('H', 0x02, struct snd_hwdep_dsp_status)
-#define SNDRV_HWDEP_IOCTL_DSP_LOAD     _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-
-/*****************************************************************************
- *                                                                           *
- *             Digital Audio (PCM) interface - /dev/snd/pcm??                *
- *                                                                           *
- *****************************************************************************/
-
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 10)
-
-typedef unsigned long snd_pcm_uframes_t;
-typedef signed long snd_pcm_sframes_t;
-
-enum {
-       SNDRV_PCM_CLASS_GENERIC = 0,    /* standard mono or stereo device */
-       SNDRV_PCM_CLASS_MULTI,          /* multichannel device */
-       SNDRV_PCM_CLASS_MODEM,          /* software modem class */
-       SNDRV_PCM_CLASS_DIGITIZER,      /* digitizer class */
-       /* Don't forget to change the following: */
-       SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
-};
-
-enum {
-       SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
-       SNDRV_PCM_SUBCLASS_MULTI_MIX,   /* multichannel subdevices are mixed together */
-       /* Don't forget to change the following: */
-       SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
-};
-
-enum {
-       SNDRV_PCM_STREAM_PLAYBACK = 0,
-       SNDRV_PCM_STREAM_CAPTURE,
-       SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
-};
-
-typedef int __bitwise snd_pcm_access_t;
-#define        SNDRV_PCM_ACCESS_MMAP_INTERLEAVED       ((__force snd_pcm_access_t) 0) /* interleaved mmap */
-#define        SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED    ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
-#define        SNDRV_PCM_ACCESS_MMAP_COMPLEX           ((__force snd_pcm_access_t) 2) /* complex mmap */
-#define        SNDRV_PCM_ACCESS_RW_INTERLEAVED         ((__force snd_pcm_access_t) 3) /* readi/writei */
-#define        SNDRV_PCM_ACCESS_RW_NONINTERLEAVED      ((__force snd_pcm_access_t) 4) /* readn/writen */
-#define        SNDRV_PCM_ACCESS_LAST           SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
-
-typedef int __bitwise snd_pcm_format_t;
-#define        SNDRV_PCM_FORMAT_S8     ((__force snd_pcm_format_t) 0)
-#define        SNDRV_PCM_FORMAT_U8     ((__force snd_pcm_format_t) 1)
-#define        SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
-#define        SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
-#define        SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
-#define        SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
-#define        SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
-#define        SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
-#define        SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
-#define        SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
-#define        SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
-#define        SNDRV_PCM_FORMAT_FLOAT_LE       ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_FLOAT_BE       ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_FLOAT64_LE     ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_FLOAT64_BE     ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
-#define        SNDRV_PCM_FORMAT_MU_LAW         ((__force snd_pcm_format_t) 20)
-#define        SNDRV_PCM_FORMAT_A_LAW          ((__force snd_pcm_format_t) 21)
-#define        SNDRV_PCM_FORMAT_IMA_ADPCM      ((__force snd_pcm_format_t) 22)
-#define        SNDRV_PCM_FORMAT_MPEG           ((__force snd_pcm_format_t) 23)
-#define        SNDRV_PCM_FORMAT_GSM            ((__force snd_pcm_format_t) 24)
-#define        SNDRV_PCM_FORMAT_SPECIAL        ((__force snd_pcm_format_t) 31)
-#define        SNDRV_PCM_FORMAT_S24_3LE        ((__force snd_pcm_format_t) 32) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S24_3BE        ((__force snd_pcm_format_t) 33) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U24_3LE        ((__force snd_pcm_format_t) 34) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U24_3BE        ((__force snd_pcm_format_t) 35) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S20_3LE        ((__force snd_pcm_format_t) 36) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S20_3BE        ((__force snd_pcm_format_t) 37) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U20_3LE        ((__force snd_pcm_format_t) 38) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U20_3BE        ((__force snd_pcm_format_t) 39) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S18_3LE        ((__force snd_pcm_format_t) 40) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_S18_3BE        ((__force snd_pcm_format_t) 41) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U18_3LE        ((__force snd_pcm_format_t) 42) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_U18_3BE        ((__force snd_pcm_format_t) 43) /* in three bytes */
-#define        SNDRV_PCM_FORMAT_G723_24        ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
-#define        SNDRV_PCM_FORMAT_G723_24_1B     ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
-#define        SNDRV_PCM_FORMAT_G723_40        ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
-#define        SNDRV_PCM_FORMAT_G723_40_1B     ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
-#define        SNDRV_PCM_FORMAT_LAST           SNDRV_PCM_FORMAT_G723_40_1B
-
-#ifdef SNDRV_LITTLE_ENDIAN
-#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_LE
-#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_LE
-#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_LE
-#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_LE
-#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_LE
-#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_LE
-#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_LE
-#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_LE
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#endif
-#ifdef SNDRV_BIG_ENDIAN
-#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_BE
-#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_BE
-#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_BE
-#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_BE
-#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_BE
-#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_BE
-#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_BE
-#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_BE
-#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#endif
-
-typedef int __bitwise snd_pcm_subformat_t;
-#define        SNDRV_PCM_SUBFORMAT_STD         ((__force snd_pcm_subformat_t) 0)
-#define        SNDRV_PCM_SUBFORMAT_LAST        SNDRV_PCM_SUBFORMAT_STD
-
-#define SNDRV_PCM_INFO_MMAP            0x00000001      /* hardware supports mmap */
-#define SNDRV_PCM_INFO_MMAP_VALID      0x00000002      /* period data are valid during transfer */
-#define SNDRV_PCM_INFO_DOUBLE          0x00000004      /* Double buffering needed for PCM start/stop */
-#define SNDRV_PCM_INFO_BATCH           0x00000010      /* double buffering */
-#define SNDRV_PCM_INFO_INTERLEAVED     0x00000100      /* channels are interleaved */
-#define SNDRV_PCM_INFO_NONINTERLEAVED  0x00000200      /* channels are not interleaved */
-#define SNDRV_PCM_INFO_COMPLEX         0x00000400      /* complex frame organization (mmap only) */
-#define SNDRV_PCM_INFO_BLOCK_TRANSFER  0x00010000      /* hardware transfer block of samples */
-#define SNDRV_PCM_INFO_OVERRANGE       0x00020000      /* hardware supports ADC (capture) overrange detection */
-#define SNDRV_PCM_INFO_RESUME          0x00040000      /* hardware supports stream resume after suspend */
-#define SNDRV_PCM_INFO_PAUSE           0x00080000      /* pause ioctl is supported */
-#define SNDRV_PCM_INFO_HALF_DUPLEX     0x00100000      /* only half duplex */
-#define SNDRV_PCM_INFO_JOINT_DUPLEX    0x00200000      /* playback and capture stream are somewhat correlated */
-#define SNDRV_PCM_INFO_SYNC_START      0x00400000      /* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP        0x00800000      /* period wakeup can be disabled */
-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
-
-typedef int __bitwise snd_pcm_state_t;
-#define        SNDRV_PCM_STATE_OPEN            ((__force snd_pcm_state_t) 0) /* stream is open */
-#define        SNDRV_PCM_STATE_SETUP           ((__force snd_pcm_state_t) 1) /* stream has a setup */
-#define        SNDRV_PCM_STATE_PREPARED        ((__force snd_pcm_state_t) 2) /* stream is ready to start */
-#define        SNDRV_PCM_STATE_RUNNING         ((__force snd_pcm_state_t) 3) /* stream is running */
-#define        SNDRV_PCM_STATE_XRUN            ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
-#define        SNDRV_PCM_STATE_DRAINING        ((__force snd_pcm_state_t) 5) /* stream is draining */
-#define        SNDRV_PCM_STATE_PAUSED          ((__force snd_pcm_state_t) 6) /* stream is paused */
-#define        SNDRV_PCM_STATE_SUSPENDED       ((__force snd_pcm_state_t) 7) /* hardware is suspended */
-#define        SNDRV_PCM_STATE_DISCONNECTED    ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
-#define        SNDRV_PCM_STATE_LAST            SNDRV_PCM_STATE_DISCONNECTED
-
-enum {
-       SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
-       SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
-       SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
-};
-
-union snd_pcm_sync_id {
-       unsigned char id[16];
-       unsigned short id16[8];
-       unsigned int id32[4];
-};
-
-struct snd_pcm_info {
-       unsigned int device;            /* RO/WR (control): device number */
-       unsigned int subdevice;         /* RO/WR (control): subdevice number */
-       int stream;                     /* RO/WR (control): stream direction */
-       int card;                       /* R: card number */
-       unsigned char id[64];           /* ID (user selectable) */
-       unsigned char name[80];         /* name of this device */
-       unsigned char subname[32];      /* subdevice name */
-       int dev_class;                  /* SNDRV_PCM_CLASS_* */
-       int dev_subclass;               /* SNDRV_PCM_SUBCLASS_* */
-       unsigned int subdevices_count;
-       unsigned int subdevices_avail;
-       union snd_pcm_sync_id sync;     /* hardware synchronization ID */
-       unsigned char reserved[64];     /* reserved for future... */
-};
-
-typedef int snd_pcm_hw_param_t;
-#define        SNDRV_PCM_HW_PARAM_ACCESS       0       /* Access type */
-#define        SNDRV_PCM_HW_PARAM_FORMAT       1       /* Format */
-#define        SNDRV_PCM_HW_PARAM_SUBFORMAT    2       /* Subformat */
-#define        SNDRV_PCM_HW_PARAM_FIRST_MASK   SNDRV_PCM_HW_PARAM_ACCESS
-#define        SNDRV_PCM_HW_PARAM_LAST_MASK    SNDRV_PCM_HW_PARAM_SUBFORMAT
-
-#define        SNDRV_PCM_HW_PARAM_SAMPLE_BITS  8       /* Bits per sample */
-#define        SNDRV_PCM_HW_PARAM_FRAME_BITS   9       /* Bits per frame */
-#define        SNDRV_PCM_HW_PARAM_CHANNELS     10      /* Channels */
-#define        SNDRV_PCM_HW_PARAM_RATE         11      /* Approx rate */
-#define        SNDRV_PCM_HW_PARAM_PERIOD_TIME  12      /* Approx distance between
-                                                * interrupts in us
-                                                */
-#define        SNDRV_PCM_HW_PARAM_PERIOD_SIZE  13      /* Approx frames between
-                                                * interrupts
-                                                */
-#define        SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14      /* Approx bytes between
-                                                * interrupts
-                                                */
-#define        SNDRV_PCM_HW_PARAM_PERIODS      15      /* Approx interrupts per
-                                                * buffer
-                                                */
-#define        SNDRV_PCM_HW_PARAM_BUFFER_TIME  16      /* Approx duration of buffer
-                                                * in us
-                                                */
-#define        SNDRV_PCM_HW_PARAM_BUFFER_SIZE  17      /* Size of buffer in frames */
-#define        SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18      /* Size of buffer in bytes */
-#define        SNDRV_PCM_HW_PARAM_TICK_TIME    19      /* Approx tick duration in us */
-#define        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL       SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define        SNDRV_PCM_HW_PARAM_LAST_INTERVAL        SNDRV_PCM_HW_PARAM_TICK_TIME
-
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
-#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER      (1<<1)  /* export buffer */
-#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP   (1<<2)  /* disable period wakeups */
-
-struct snd_interval {
-       unsigned int min, max;
-       unsigned int openmin:1,
-                    openmax:1,
-                    integer:1,
-                    empty:1;
-};
-
-#define SNDRV_MASK_MAX 256
-
-struct snd_mask {
-       __u32 bits[(SNDRV_MASK_MAX+31)/32];
-};
-
-struct snd_pcm_hw_params {
-       unsigned int flags;
-       struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - 
-                              SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
-       struct snd_mask mres[5];        /* reserved masks */
-       struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
-                                       SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
-       struct snd_interval ires[9];    /* reserved intervals */
-       unsigned int rmask;             /* W: requested masks */
-       unsigned int cmask;             /* R: changed masks */
-       unsigned int info;              /* R: Info flags for returned setup */
-       unsigned int msbits;            /* R: used most significant bits */
-       unsigned int rate_num;          /* R: rate numerator */
-       unsigned int rate_den;          /* R: rate denominator */
-       snd_pcm_uframes_t fifo_size;    /* R: chip FIFO size in frames */
-       unsigned char reserved[64];     /* reserved for future */
-};
-
-enum {
-       SNDRV_PCM_TSTAMP_NONE = 0,
-       SNDRV_PCM_TSTAMP_ENABLE,
-       SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
-};
-
-struct snd_pcm_sw_params {
-       int tstamp_mode;                        /* timestamp mode */
-       unsigned int period_step;
-       unsigned int sleep_min;                 /* min ticks to sleep */
-       snd_pcm_uframes_t avail_min;            /* min avail frames for wakeup */
-       snd_pcm_uframes_t xfer_align;           /* obsolete: xfer size need to be a multiple */
-       snd_pcm_uframes_t start_threshold;      /* min hw_avail frames for automatic start */
-       snd_pcm_uframes_t stop_threshold;       /* min avail frames for automatic stop */
-       snd_pcm_uframes_t silence_threshold;    /* min distance from noise for silence filling */
-       snd_pcm_uframes_t silence_size;         /* silence block size */
-       snd_pcm_uframes_t boundary;             /* pointers wrap point */
-       unsigned char reserved[64];             /* reserved for future */
-};
-
-struct snd_pcm_channel_info {
-       unsigned int channel;
-       __kernel_off_t offset;          /* mmap offset */
-       unsigned int first;             /* offset to first sample in bits */
-       unsigned int step;              /* samples distance in bits */
-};
-
-struct snd_pcm_status {
-       snd_pcm_state_t state;          /* stream state */
-       struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
-       struct timespec tstamp;         /* reference timestamp */
-       snd_pcm_uframes_t appl_ptr;     /* appl ptr */
-       snd_pcm_uframes_t hw_ptr;       /* hw ptr */
-       snd_pcm_sframes_t delay;        /* current delay in frames */
-       snd_pcm_uframes_t avail;        /* number of frames available */
-       snd_pcm_uframes_t avail_max;    /* max frames available on hw since last status */
-       snd_pcm_uframes_t overrange;    /* count of ADC (capture) overrange detections from last status */
-       snd_pcm_state_t suspended_state; /* suspended stream state */
-       unsigned char reserved[60];     /* must be filled with zero */
-};
-
-struct snd_pcm_mmap_status {
-       snd_pcm_state_t state;          /* RO: state - SNDRV_PCM_STATE_XXXX */
-       int pad1;                       /* Needed for 64 bit alignment */
-       snd_pcm_uframes_t hw_ptr;       /* RO: hw ptr (0...boundary-1) */
-       struct timespec tstamp;         /* Timestamp */
-       snd_pcm_state_t suspended_state; /* RO: suspended stream state */
-};
-
-struct snd_pcm_mmap_control {
-       snd_pcm_uframes_t appl_ptr;     /* RW: appl ptr (0...boundary-1) */
-       snd_pcm_uframes_t avail_min;    /* RW: min available frames for wakeup */
-};
-
-#define SNDRV_PCM_SYNC_PTR_HWSYNC      (1<<0)  /* execute hwsync */
-#define SNDRV_PCM_SYNC_PTR_APPL                (1<<1)  /* get appl_ptr from driver (r/w op) */
-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN   (1<<2)  /* get avail_min from driver */
-
-struct snd_pcm_sync_ptr {
-       unsigned int flags;
-       union {
-               struct snd_pcm_mmap_status status;
-               unsigned char reserved[64];
-       } s;
-       union {
-               struct snd_pcm_mmap_control control;
-               unsigned char reserved[64];
-       } c;
-};
-
-struct snd_xferi {
-       snd_pcm_sframes_t result;
-       void __user *buf;
-       snd_pcm_uframes_t frames;
-};
-
-struct snd_xfern {
-       snd_pcm_sframes_t result;
-       void __user * __user *bufs;
-       snd_pcm_uframes_t frames;
-};
-
-enum {
-       SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
-       SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,        /* posix_clock_monotonic equivalent */
-       SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
-};
-
-/* channel positions */
-enum {
-       SNDRV_CHMAP_UNKNOWN = 0,
-       SNDRV_CHMAP_NA,         /* N/A, silent */
-       SNDRV_CHMAP_MONO,       /* mono stream */
-       /* this follows the alsa-lib mixer channel value + 3 */
-       SNDRV_CHMAP_FL,         /* front left */
-       SNDRV_CHMAP_FR,         /* front right */
-       SNDRV_CHMAP_RL,         /* rear left */
-       SNDRV_CHMAP_RR,         /* rear right */
-       SNDRV_CHMAP_FC,         /* front center */
-       SNDRV_CHMAP_LFE,        /* LFE */
-       SNDRV_CHMAP_SL,         /* side left */
-       SNDRV_CHMAP_SR,         /* side right */
-       SNDRV_CHMAP_RC,         /* rear center */
-       /* new definitions */
-       SNDRV_CHMAP_FLC,        /* front left center */
-       SNDRV_CHMAP_FRC,        /* front right center */
-       SNDRV_CHMAP_RLC,        /* rear left center */
-       SNDRV_CHMAP_RRC,        /* rear right center */
-       SNDRV_CHMAP_FLW,        /* front left wide */
-       SNDRV_CHMAP_FRW,        /* front right wide */
-       SNDRV_CHMAP_FLH,        /* front left high */
-       SNDRV_CHMAP_FCH,        /* front center high */
-       SNDRV_CHMAP_FRH,        /* front right high */
-       SNDRV_CHMAP_TC,         /* top center */
-       SNDRV_CHMAP_TFL,        /* top front left */
-       SNDRV_CHMAP_TFR,        /* top front right */
-       SNDRV_CHMAP_TFC,        /* top front center */
-       SNDRV_CHMAP_TRL,        /* top rear left */
-       SNDRV_CHMAP_TRR,        /* top rear right */
-       SNDRV_CHMAP_TRC,        /* top rear center */
-       SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
-};
-
-#define SNDRV_CHMAP_POSITION_MASK      0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE      (0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC                (0x02 << 16)
-
-#define SNDRV_PCM_IOCTL_PVERSION       _IOR('A', 0x00, int)
-#define SNDRV_PCM_IOCTL_INFO           _IOR('A', 0x01, struct snd_pcm_info)
-#define SNDRV_PCM_IOCTL_TSTAMP         _IOW('A', 0x02, int)
-#define SNDRV_PCM_IOCTL_TTSTAMP                _IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_HW_REFINE      _IOWR('A', 0x10, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_PARAMS      _IOWR('A', 0x11, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_FREE                _IO('A', 0x12)
-#define SNDRV_PCM_IOCTL_SW_PARAMS      _IOWR('A', 0x13, struct snd_pcm_sw_params)
-#define SNDRV_PCM_IOCTL_STATUS         _IOR('A', 0x20, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_DELAY          _IOR('A', 0x21, snd_pcm_sframes_t)
-#define SNDRV_PCM_IOCTL_HWSYNC         _IO('A', 0x22)
-#define SNDRV_PCM_IOCTL_SYNC_PTR       _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
-#define SNDRV_PCM_IOCTL_CHANNEL_INFO   _IOR('A', 0x32, struct snd_pcm_channel_info)
-#define SNDRV_PCM_IOCTL_PREPARE                _IO('A', 0x40)
-#define SNDRV_PCM_IOCTL_RESET          _IO('A', 0x41)
-#define SNDRV_PCM_IOCTL_START          _IO('A', 0x42)
-#define SNDRV_PCM_IOCTL_DROP           _IO('A', 0x43)
-#define SNDRV_PCM_IOCTL_DRAIN          _IO('A', 0x44)
-#define SNDRV_PCM_IOCTL_PAUSE          _IOW('A', 0x45, int)
-#define SNDRV_PCM_IOCTL_REWIND         _IOW('A', 0x46, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_RESUME         _IO('A', 0x47)
-#define SNDRV_PCM_IOCTL_XRUN           _IO('A', 0x48)
-#define SNDRV_PCM_IOCTL_FORWARD                _IOW('A', 0x49, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES  _IOW('A', 0x50, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_READI_FRAMES   _IOR('A', 0x51, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES  _IOW('A', 0x52, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_READN_FRAMES   _IOR('A', 0x53, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_LINK           _IOW('A', 0x60, int)
-#define SNDRV_PCM_IOCTL_UNLINK         _IO('A', 0x61)
-
-/*****************************************************************************
- *                                                                           *
- *                            MIDI v1.0 interface                            *
- *                                                                           *
- *****************************************************************************/
-
-/*
- *  Raw MIDI section - /dev/snd/midi??
- */
-
-#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 0)
-
-enum {
-       SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
-       SNDRV_RAWMIDI_STREAM_INPUT,
-       SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
-};
-
-#define SNDRV_RAWMIDI_INFO_OUTPUT              0x00000001
-#define SNDRV_RAWMIDI_INFO_INPUT               0x00000002
-#define SNDRV_RAWMIDI_INFO_DUPLEX              0x00000004
-
-struct snd_rawmidi_info {
-       unsigned int device;            /* RO/WR (control): device number */
-       unsigned int subdevice;         /* RO/WR (control): subdevice number */
-       int stream;                     /* WR: stream */
-       int card;                       /* R: card number */
-       unsigned int flags;             /* SNDRV_RAWMIDI_INFO_XXXX */
-       unsigned char id[64];           /* ID (user selectable) */
-       unsigned char name[80];         /* name of device */
-       unsigned char subname[32];      /* name of active or selected subdevice */
-       unsigned int subdevices_count;
-       unsigned int subdevices_avail;
-       unsigned char reserved[64];     /* reserved for future use */
-};
-
-struct snd_rawmidi_params {
-       int stream;
-       size_t buffer_size;             /* queue size in bytes */
-       size_t avail_min;               /* minimum avail bytes for wakeup */
-       unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
-       unsigned char reserved[16];     /* reserved for future use */
-};
-
-struct snd_rawmidi_status {
-       int stream;
-       struct timespec tstamp;         /* Timestamp */
-       size_t avail;                   /* available bytes */
-       size_t xruns;                   /* count of overruns since last status (in bytes) */
-       unsigned char reserved[16];     /* reserved for future use */
-};
-
-#define SNDRV_RAWMIDI_IOCTL_PVERSION   _IOR('W', 0x00, int)
-#define SNDRV_RAWMIDI_IOCTL_INFO       _IOR('W', 0x01, struct snd_rawmidi_info)
-#define SNDRV_RAWMIDI_IOCTL_PARAMS     _IOWR('W', 0x10, struct snd_rawmidi_params)
-#define SNDRV_RAWMIDI_IOCTL_STATUS     _IOWR('W', 0x20, struct snd_rawmidi_status)
-#define SNDRV_RAWMIDI_IOCTL_DROP       _IOW('W', 0x30, int)
-#define SNDRV_RAWMIDI_IOCTL_DRAIN      _IOW('W', 0x31, int)
-
-/*
- *  Timer section - /dev/snd/timer
- */
-
-#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-enum {
-       SNDRV_TIMER_CLASS_NONE = -1,
-       SNDRV_TIMER_CLASS_SLAVE = 0,
-       SNDRV_TIMER_CLASS_GLOBAL,
-       SNDRV_TIMER_CLASS_CARD,
-       SNDRV_TIMER_CLASS_PCM,
-       SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
-};
-
-/* slave timer classes */
-enum {
-       SNDRV_TIMER_SCLASS_NONE = 0,
-       SNDRV_TIMER_SCLASS_APPLICATION,
-       SNDRV_TIMER_SCLASS_SEQUENCER,           /* alias */
-       SNDRV_TIMER_SCLASS_OSS_SEQUENCER,       /* alias */
-       SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
-};
-
-/* global timers (device member) */
-#define SNDRV_TIMER_GLOBAL_SYSTEM      0
-#define SNDRV_TIMER_GLOBAL_RTC         1
-#define SNDRV_TIMER_GLOBAL_HPET                2
-#define SNDRV_TIMER_GLOBAL_HRTIMER     3
-
-/* info flags */
-#define SNDRV_TIMER_FLG_SLAVE          (1<<0)  /* cannot be controlled */
-
-struct snd_timer_id {
-       int dev_class;
-       int dev_sclass;
-       int card;
-       int device;
-       int subdevice;
-};
-
-struct snd_timer_ginfo {
-       struct snd_timer_id tid;        /* requested timer ID */
-       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
-       int card;                       /* card number */
-       unsigned char id[64];           /* timer identification */
-       unsigned char name[80];         /* timer name */
-       unsigned long reserved0;        /* reserved for future use */
-       unsigned long resolution;       /* average period resolution in ns */
-       unsigned long resolution_min;   /* minimal period resolution in ns */
-       unsigned long resolution_max;   /* maximal period resolution in ns */
-       unsigned int clients;           /* active timer clients */
-       unsigned char reserved[32];
-};
-
-struct snd_timer_gparams {
-       struct snd_timer_id tid;        /* requested timer ID */
-       unsigned long period_num;       /* requested precise period duration (in seconds) - numerator */
-       unsigned long period_den;       /* requested precise period duration (in seconds) - denominator */
-       unsigned char reserved[32];
-};
-
-struct snd_timer_gstatus {
-       struct snd_timer_id tid;        /* requested timer ID */
-       unsigned long resolution;       /* current period resolution in ns */
-       unsigned long resolution_num;   /* precise current period resolution (in seconds) - numerator */
-       unsigned long resolution_den;   /* precise current period resolution (in seconds) - denominator */
-       unsigned char reserved[32];
-};
-
-struct snd_timer_select {
-       struct snd_timer_id id; /* bind to timer ID */
-       unsigned char reserved[32];     /* reserved */
-};
-
-struct snd_timer_info {
-       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
-       int card;                       /* card number */
-       unsigned char id[64];           /* timer identificator */
-       unsigned char name[80];         /* timer name */
-       unsigned long reserved0;        /* reserved for future use */
-       unsigned long resolution;       /* average period resolution in ns */
-       unsigned char reserved[64];     /* reserved */
-};
-
-#define SNDRV_TIMER_PSFLG_AUTO         (1<<0)  /* auto start, otherwise one-shot */
-#define SNDRV_TIMER_PSFLG_EXCLUSIVE    (1<<1)  /* exclusive use, precise start/stop/pause/continue */
-#define SNDRV_TIMER_PSFLG_EARLY_EVENT  (1<<2)  /* write early event to the poll queue */
-
-struct snd_timer_params {
-       unsigned int flags;             /* flags - SNDRV_MIXER_PSFLG_* */
-       unsigned int ticks;             /* requested resolution in ticks */
-       unsigned int queue_size;        /* total size of queue (32-1024) */
-       unsigned int reserved0;         /* reserved, was: failure locations */
-       unsigned int filter;            /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
-       unsigned char reserved[60];     /* reserved */
-};
-
-struct snd_timer_status {
-       struct timespec tstamp;         /* Timestamp - last update */
-       unsigned int resolution;        /* current period resolution in ns */
-       unsigned int lost;              /* counter of master tick lost */
-       unsigned int overrun;           /* count of read queue overruns */
-       unsigned int queue;             /* used queue size */
-       unsigned char reserved[64];     /* reserved */
-};
-
-#define SNDRV_TIMER_IOCTL_PVERSION     _IOR('T', 0x00, int)
-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE  _IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD                _IOW('T', 0x02, int)
-#define SNDRV_TIMER_IOCTL_GINFO                _IOWR('T', 0x03, struct snd_timer_ginfo)
-#define SNDRV_TIMER_IOCTL_GPARAMS      _IOW('T', 0x04, struct snd_timer_gparams)
-#define SNDRV_TIMER_IOCTL_GSTATUS      _IOWR('T', 0x05, struct snd_timer_gstatus)
-#define SNDRV_TIMER_IOCTL_SELECT       _IOW('T', 0x10, struct snd_timer_select)
-#define SNDRV_TIMER_IOCTL_INFO         _IOR('T', 0x11, struct snd_timer_info)
-#define SNDRV_TIMER_IOCTL_PARAMS       _IOW('T', 0x12, struct snd_timer_params)
-#define SNDRV_TIMER_IOCTL_STATUS       _IOR('T', 0x14, struct snd_timer_status)
-/* The following four ioctls are changed since 1.0.9 due to confliction */
-#define SNDRV_TIMER_IOCTL_START                _IO('T', 0xa0)
-#define SNDRV_TIMER_IOCTL_STOP         _IO('T', 0xa1)
-#define SNDRV_TIMER_IOCTL_CONTINUE     _IO('T', 0xa2)
-#define SNDRV_TIMER_IOCTL_PAUSE                _IO('T', 0xa3)
-
-struct snd_timer_read {
-       unsigned int resolution;
-       unsigned int ticks;
-};
-
-enum {
-       SNDRV_TIMER_EVENT_RESOLUTION = 0,       /* val = resolution in ns */
-       SNDRV_TIMER_EVENT_TICK,                 /* val = ticks */
-       SNDRV_TIMER_EVENT_START,                /* val = resolution in ns */
-       SNDRV_TIMER_EVENT_STOP,                 /* val = 0 */
-       SNDRV_TIMER_EVENT_CONTINUE,             /* val = resolution in ns */
-       SNDRV_TIMER_EVENT_PAUSE,                /* val = 0 */
-       SNDRV_TIMER_EVENT_EARLY,                /* val = 0, early event */
-       SNDRV_TIMER_EVENT_SUSPEND,              /* val = 0 */
-       SNDRV_TIMER_EVENT_RESUME,               /* val = resolution in ns */
-       /* master timer events for slave timer instances */
-       SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
-       SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
-       SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
-       SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
-       SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
-       SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
-};
-
-struct snd_timer_tread {
-       int event;
-       struct timespec tstamp;
-       unsigned int val;
-};
-
-/****************************************************************************
- *                                                                          *
- *        Section for driver control interface - /dev/snd/control?          *
- *                                                                          *
- ****************************************************************************/
-
-#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 7)
-
-struct snd_ctl_card_info {
-       int card;                       /* card number */
-       int pad;                        /* reserved for future (was type) */
-       unsigned char id[16];           /* ID of card (user selectable) */
-       unsigned char driver[16];       /* Driver name */
-       unsigned char name[32];         /* Short name of soundcard */
-       unsigned char longname[80];     /* name + info text about soundcard */
-       unsigned char reserved_[16];    /* reserved for future (was ID of mixer) */
-       unsigned char mixername[80];    /* visual mixer identification */
-       unsigned char components[128];  /* card components / fine identification, delimited with one space (AC97 etc..) */
-};
-
-typedef int __bitwise snd_ctl_elem_type_t;
-#define        SNDRV_CTL_ELEM_TYPE_NONE        ((__force snd_ctl_elem_type_t) 0) /* invalid */
-#define        SNDRV_CTL_ELEM_TYPE_BOOLEAN     ((__force snd_ctl_elem_type_t) 1) /* boolean type */
-#define        SNDRV_CTL_ELEM_TYPE_INTEGER     ((__force snd_ctl_elem_type_t) 2) /* integer type */
-#define        SNDRV_CTL_ELEM_TYPE_ENUMERATED  ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
-#define        SNDRV_CTL_ELEM_TYPE_BYTES       ((__force snd_ctl_elem_type_t) 4) /* byte array */
-#define        SNDRV_CTL_ELEM_TYPE_IEC958      ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
-#define        SNDRV_CTL_ELEM_TYPE_INTEGER64   ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
-#define        SNDRV_CTL_ELEM_TYPE_LAST        SNDRV_CTL_ELEM_TYPE_INTEGER64
-
-typedef int __bitwise snd_ctl_elem_iface_t;
-#define        SNDRV_CTL_ELEM_IFACE_CARD       ((__force snd_ctl_elem_iface_t) 0) /* global control */
-#define        SNDRV_CTL_ELEM_IFACE_HWDEP      ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
-#define        SNDRV_CTL_ELEM_IFACE_MIXER      ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
-#define        SNDRV_CTL_ELEM_IFACE_PCM        ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
-#define        SNDRV_CTL_ELEM_IFACE_RAWMIDI    ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
-#define        SNDRV_CTL_ELEM_IFACE_TIMER      ((__force snd_ctl_elem_iface_t) 5) /* timer device */
-#define        SNDRV_CTL_ELEM_IFACE_SEQUENCER  ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
-#define        SNDRV_CTL_ELEM_IFACE_LAST       SNDRV_CTL_ELEM_IFACE_SEQUENCER
-
-#define SNDRV_CTL_ELEM_ACCESS_READ             (1<<0)
-#define SNDRV_CTL_ELEM_ACCESS_WRITE            (1<<1)
-#define SNDRV_CTL_ELEM_ACCESS_READWRITE                (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE         (1<<2)  /* control value may be changed without a notification */
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP                (1<<3)  /* when was control changed */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ         (1<<4)  /* TLV read is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE                (1<<5)  /* TLV write is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE    (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND      (1<<6)  /* TLV command is possible */
-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE         (1<<8)  /* control does actually nothing, but may be updated */
-#define SNDRV_CTL_ELEM_ACCESS_LOCK             (1<<9)  /* write lock */
-#define SNDRV_CTL_ELEM_ACCESS_OWNER            (1<<10) /* write lock owner */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK     (1<<28) /* kernel use a TLV callback */ 
-#define SNDRV_CTL_ELEM_ACCESS_USER             (1<<29) /* user space element */
-/* bits 30 and 31 are obsoleted (for indirect access) */
-
-/* for further details see the ACPI and PCI power management specification */
-#define SNDRV_CTL_POWER_D0             0x0000  /* full On */
-#define SNDRV_CTL_POWER_D1             0x0100  /* partial On */
-#define SNDRV_CTL_POWER_D2             0x0200  /* partial On */
-#define SNDRV_CTL_POWER_D3             0x0300  /* Off */
-#define SNDRV_CTL_POWER_D3hot          (SNDRV_CTL_POWER_D3|0x0000)     /* Off, with power */
-#define SNDRV_CTL_POWER_D3cold         (SNDRV_CTL_POWER_D3|0x0001)     /* Off, without power */
-
-struct snd_ctl_elem_id {
-       unsigned int numid;             /* numeric identifier, zero = invalid */
-       snd_ctl_elem_iface_t iface;     /* interface identifier */
-       unsigned int device;            /* device/client number */
-       unsigned int subdevice;         /* subdevice (substream) number */
-       unsigned char name[44];         /* ASCII name of item */
-       unsigned int index;             /* index of item */
-};
-
-struct snd_ctl_elem_list {
-       unsigned int offset;            /* W: first element ID to get */
-       unsigned int space;             /* W: count of element IDs to get */
-       unsigned int used;              /* R: count of element IDs set */
-       unsigned int count;             /* R: count of all elements */
-       struct snd_ctl_elem_id __user *pids; /* R: IDs */
-       unsigned char reserved[50];
-};
-
-struct snd_ctl_elem_info {
-       struct snd_ctl_elem_id id;      /* W: element ID */
-       snd_ctl_elem_type_t type;       /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
-       unsigned int access;            /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
-       unsigned int count;             /* count of values */
-       __kernel_pid_t owner;           /* owner's PID of this control */
-       union {
-               struct {
-                       long min;               /* R: minimum value */
-                       long max;               /* R: maximum value */
-                       long step;              /* R: step (0 variable) */
-               } integer;
-               struct {
-                       long long min;          /* R: minimum value */
-                       long long max;          /* R: maximum value */
-                       long long step;         /* R: step (0 variable) */
-               } integer64;
-               struct {
-                       unsigned int items;     /* R: number of items */
-                       unsigned int item;      /* W: item number */
-                       char name[64];          /* R: value name */
-                       __u64 names_ptr;        /* W: names list (ELEM_ADD only) */
-                       unsigned int names_length;
-               } enumerated;
-               unsigned char reserved[128];
-       } value;
-       union {
-               unsigned short d[4];            /* dimensions */
-               unsigned short *d_ptr;          /* indirect - obsoleted */
-       } dimen;
-       unsigned char reserved[64-4*sizeof(unsigned short)];
-};
-
-struct snd_ctl_elem_value {
-       struct snd_ctl_elem_id id;      /* W: element ID */
-       unsigned int indirect: 1;       /* W: indirect access - obsoleted */
-       union {
-               union {
-                       long value[128];
-                       long *value_ptr;        /* obsoleted */
-               } integer;
-               union {
-                       long long value[64];
-                       long long *value_ptr;   /* obsoleted */
-               } integer64;
-               union {
-                       unsigned int item[128];
-                       unsigned int *item_ptr; /* obsoleted */
-               } enumerated;
-               union {
-                       unsigned char data[512];
-                       unsigned char *data_ptr;        /* obsoleted */
-               } bytes;
-               struct snd_aes_iec958 iec958;
-       } value;                /* RO */
-       struct timespec tstamp;
-       unsigned char reserved[128-sizeof(struct timespec)];
-};
-
-struct snd_ctl_tlv {
-       unsigned int numid;     /* control element numeric identification */
-       unsigned int length;    /* in bytes aligned to 4 */
-       unsigned int tlv[0];    /* first TLV */
-};
-
-#define SNDRV_CTL_IOCTL_PVERSION       _IOR('U', 0x00, int)
-#define SNDRV_CTL_IOCTL_CARD_INFO      _IOR('U', 0x01, struct snd_ctl_card_info)
-#define SNDRV_CTL_IOCTL_ELEM_LIST      _IOWR('U', 0x10, struct snd_ctl_elem_list)
-#define SNDRV_CTL_IOCTL_ELEM_INFO      _IOWR('U', 0x11, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_READ      _IOWR('U', 0x12, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_WRITE     _IOWR('U', 0x13, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_LOCK      _IOW('U', 0x14, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK    _IOW('U', 0x15, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
-#define SNDRV_CTL_IOCTL_ELEM_ADD       _IOWR('U', 0x17, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REPLACE   _IOWR('U', 0x18, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REMOVE    _IOWR('U', 0x19, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_TLV_READ       _IOWR('U', 0x1a, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_WRITE      _IOWR('U', 0x1b, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_COMMAND    _IOWR('U', 0x1c, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
-#define SNDRV_CTL_IOCTL_HWDEP_INFO     _IOR('U', 0x21, struct snd_hwdep_info)
-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE        _IOR('U', 0x30, int)
-#define SNDRV_CTL_IOCTL_PCM_INFO       _IOWR('U', 0x31, struct snd_pcm_info)
-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO   _IOWR('U', 0x41, struct snd_rawmidi_info)
-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
-#define SNDRV_CTL_IOCTL_POWER          _IOWR('U', 0xd0, int)
-#define SNDRV_CTL_IOCTL_POWER_STATE    _IOR('U', 0xd1, int)
-
-/*
- *  Read interface.
- */
-
-enum sndrv_ctl_event_type {
-       SNDRV_CTL_EVENT_ELEM = 0,
-       SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
-};
-
-#define SNDRV_CTL_EVENT_MASK_VALUE     (1<<0)  /* element value was changed */
-#define SNDRV_CTL_EVENT_MASK_INFO      (1<<1)  /* element info was changed */
-#define SNDRV_CTL_EVENT_MASK_ADD       (1<<2)  /* element was added */
-#define SNDRV_CTL_EVENT_MASK_TLV       (1<<3)  /* element TLV tree was changed */
-#define SNDRV_CTL_EVENT_MASK_REMOVE    (~0U)   /* element was removed */
-
-struct snd_ctl_event {
-       int type;       /* event type - SNDRV_CTL_EVENT_* */
-       union {
-               struct {
-                       unsigned int mask;
-                       struct snd_ctl_elem_id id;
-               } elem;
-               unsigned char data8[60];
-       } data;
-};
-
-/*
- *  Control names
- */
-
-#define SNDRV_CTL_NAME_NONE                            ""
-#define SNDRV_CTL_NAME_PLAYBACK                                "Playback "
-#define SNDRV_CTL_NAME_CAPTURE                         "Capture "
-
-#define SNDRV_CTL_NAME_IEC958_NONE                     ""
-#define SNDRV_CTL_NAME_IEC958_SWITCH                   "Switch"
-#define SNDRV_CTL_NAME_IEC958_VOLUME                   "Volume"
-#define SNDRV_CTL_NAME_IEC958_DEFAULT                  "Default"
-#define SNDRV_CTL_NAME_IEC958_MASK                     "Mask"
-#define SNDRV_CTL_NAME_IEC958_CON_MASK                 "Con Mask"
-#define SNDRV_CTL_NAME_IEC958_PRO_MASK                 "Pro Mask"
-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM               "PCM Stream"
-#define SNDRV_CTL_NAME_IEC958(expl,direction,what)     "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
-
+#include <uapi/sound/asound.h>
 #endif /* __SOUND_ASOUND_H */
diff --git a/include/sound/asound_fm.h b/include/sound/asound_fm.h
deleted file mode 100644 (file)
index c2a4b96..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef __SOUND_ASOUND_FM_H
-#define __SOUND_ASOUND_FM_H
-
-/*
- *  Advanced Linux Sound Architecture - ALSA
- *
- *  Interface file between ALSA driver & user space
- *  Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
- *                           4Front Technologies
- *
- *  Direct FM control
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#define SNDRV_DM_FM_MODE_OPL2  0x00
-#define SNDRV_DM_FM_MODE_OPL3  0x01
-
-struct snd_dm_fm_info {
-       unsigned char fm_mode;          /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
-       unsigned char rhythm;           /* percussion mode flag */
-};
-
-/*
- *  Data structure composing an FM "note" or sound event.
- */
-
-struct snd_dm_fm_voice {
-       unsigned char op;               /* operator cell (0 or 1) */
-       unsigned char voice;            /* FM voice (0 to 17) */
-
-       unsigned char am;               /* amplitude modulation */
-       unsigned char vibrato;          /* vibrato effect */
-       unsigned char do_sustain;       /* sustain phase */
-       unsigned char kbd_scale;        /* keyboard scaling */
-       unsigned char harmonic;         /* 4 bits: harmonic and multiplier */
-       unsigned char scale_level;      /* 2 bits: decrease output freq rises */
-       unsigned char volume;           /* 6 bits: volume */
-
-       unsigned char attack;           /* 4 bits: attack rate */
-       unsigned char decay;            /* 4 bits: decay rate */
-       unsigned char sustain;          /* 4 bits: sustain level */
-       unsigned char release;          /* 4 bits: release rate */
-
-       unsigned char feedback;         /* 3 bits: feedback for op0 */
-       unsigned char connection;       /* 0 for serial, 1 for parallel */
-       unsigned char left;             /* stereo left */
-       unsigned char right;            /* stereo right */
-       unsigned char waveform;         /* 3 bits: waveform shape */
-};
-
-/*
- *  This describes an FM note by its voice, octave, frequency number (10bit)
- *  and key on/off.
- */
-
-struct snd_dm_fm_note {
-       unsigned char voice;    /* 0-17 voice channel */
-       unsigned char octave;   /* 3 bits: what octave to play */
-       unsigned int fnum;      /* 10 bits: frequency number */
-       unsigned char key_on;   /* set for active, clear for silent */
-};
-
-/*
- *  FM parameters that apply globally to all voices, and thus are not "notes"
- */
-
-struct snd_dm_fm_params {
-       unsigned char am_depth;         /* amplitude modulation depth (1=hi) */
-       unsigned char vib_depth;        /* vibrato depth (1=hi) */
-       unsigned char kbd_split;        /* keyboard split */
-       unsigned char rhythm;           /* percussion mode select */
-
-       /* This block is the percussion instrument data */
-       unsigned char bass;
-       unsigned char snare;
-       unsigned char tomtom;
-       unsigned char cymbal;
-       unsigned char hihat;
-};
-
-/*
- *  FM mode ioctl settings
- */
-
-#define SNDRV_DM_FM_IOCTL_INFO         _IOR('H', 0x20, struct snd_dm_fm_info)
-#define SNDRV_DM_FM_IOCTL_RESET                _IO ('H', 0x21)
-#define SNDRV_DM_FM_IOCTL_PLAY_NOTE    _IOW('H', 0x22, struct snd_dm_fm_note)
-#define SNDRV_DM_FM_IOCTL_SET_VOICE    _IOW('H', 0x23, struct snd_dm_fm_voice)
-#define SNDRV_DM_FM_IOCTL_SET_PARAMS   _IOW('H', 0x24, struct snd_dm_fm_params)
-#define SNDRV_DM_FM_IOCTL_SET_MODE     _IOW('H', 0x25, int)
-/* for OPL3 only */
-#define SNDRV_DM_FM_IOCTL_SET_CONNECTION       _IOW('H', 0x26, int)
-/* SBI patch management */
-#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES        _IO ('H', 0x40)
-
-#define SNDRV_DM_FM_OSS_IOCTL_RESET            0x20
-#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE                0x21
-#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE                0x22
-#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS       0x23
-#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE         0x24
-#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL          0x25
-
-/*
- * Patch Record - fixed size for write
- */
-
-#define FM_KEY_SBI     "SBI\032"
-#define FM_KEY_2OP     "2OP\032"
-#define FM_KEY_4OP     "4OP\032"
-
-struct sbi_patch {
-       unsigned char prog;
-       unsigned char bank;
-       char key[4];
-       char name[25];
-       char extension[7];
-       unsigned char data[32];
-};
-
-#endif /* __SOUND_ASOUND_FM_H */
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
deleted file mode 100644 (file)
index 05341a4..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *  compress_offload.h - compress offload header definations
- *
- *  Copyright (C) 2011 Intel Corporation
- *  Authors:   Vinod Koul <vinod.koul@linux.intel.com>
- *             Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-#ifndef __COMPRESS_OFFLOAD_H
-#define __COMPRESS_OFFLOAD_H
-
-#include <linux/types.h>
-#include <sound/asound.h>
-#include <sound/compress_params.h>
-
-
-#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
-/**
- * struct snd_compressed_buffer: compressed buffer
- * @fragment_size: size of buffer fragment in bytes
- * @fragments: number of such fragments
- */
-struct snd_compressed_buffer {
-       __u32 fragment_size;
-       __u32 fragments;
-};
-
-/**
- * struct snd_compr_params: compressed stream params
- * @buffer: buffer description
- * @codec: codec parameters
- * @no_wake_mode: dont wake on fragment elapsed
- */
-struct snd_compr_params {
-       struct snd_compressed_buffer buffer;
-       struct snd_codec codec;
-       __u8 no_wake_mode;
-};
-
-/**
- * struct snd_compr_tstamp: timestamp descriptor
- * @byte_offset: Byte offset in ring buffer to DSP
- * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
- * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
- *     large steps and should only be used to monitor encoding/decoding
- *     progress. It shall not be used for timing estimates.
- * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
- * output/input. This field should be used for A/V sync or time estimates.
- * @sampling_rate: sampling rate of audio
- */
-struct snd_compr_tstamp {
-       __u32 byte_offset;
-       __u32 copied_total;
-       snd_pcm_uframes_t pcm_frames;
-       snd_pcm_uframes_t pcm_io_frames;
-       __u32 sampling_rate;
-};
-
-/**
- * struct snd_compr_avail: avail descriptor
- * @avail: Number of bytes available in ring buffer for writing/reading
- * @tstamp: timestamp infomation
- */
-struct snd_compr_avail {
-       __u64 avail;
-       struct snd_compr_tstamp tstamp;
-};
-
-enum snd_compr_direction {
-       SND_COMPRESS_PLAYBACK = 0,
-       SND_COMPRESS_CAPTURE
-};
-
-/**
- * struct snd_compr_caps: caps descriptor
- * @codecs: pointer to array of codecs
- * @direction: direction supported. Of type snd_compr_direction
- * @min_fragment_size: minimum fragment supported by DSP
- * @max_fragment_size: maximum fragment supported by DSP
- * @min_fragments: min fragments supported by DSP
- * @max_fragments: max fragments supported by DSP
- * @num_codecs: number of codecs supported
- * @reserved: reserved field
- */
-struct snd_compr_caps {
-       __u32 num_codecs;
-       __u32 direction;
-       __u32 min_fragment_size;
-       __u32 max_fragment_size;
-       __u32 min_fragments;
-       __u32 max_fragments;
-       __u32 codecs[MAX_NUM_CODECS];
-       __u32 reserved[11];
-};
-
-/**
- * struct snd_compr_codec_caps: query capability of codec
- * @codec: codec for which capability is queried
- * @num_descriptors: number of codec descriptors
- * @descriptor: array of codec capability descriptor
- */
-struct snd_compr_codec_caps {
-       __u32 codec;
-       __u32 num_descriptors;
-       struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
-};
-
-/**
- * compress path ioctl definitions
- * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
- * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
- * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
- * Note: only codec params can be changed runtime and stream params cant be
- * SNDRV_COMPRESS_GET_PARAMS: Query codec params
- * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
- * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
- * This also queries the tstamp properties
- * SNDRV_COMPRESS_PAUSE: Pause the running stream
- * SNDRV_COMPRESS_RESUME: resume a paused stream
- * SNDRV_COMPRESS_START: Start a stream
- * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
- * and the buffers currently with DSP
- * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
- * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
- */
-#define SNDRV_COMPRESS_IOCTL_VERSION   _IOR('C', 0x00, int)
-#define SNDRV_COMPRESS_GET_CAPS                _IOWR('C', 0x10, struct snd_compr_caps)
-#define SNDRV_COMPRESS_GET_CODEC_CAPS  _IOWR('C', 0x11,\
-                                               struct snd_compr_codec_caps)
-#define SNDRV_COMPRESS_SET_PARAMS      _IOW('C', 0x12, struct snd_compr_params)
-#define SNDRV_COMPRESS_GET_PARAMS      _IOR('C', 0x13, struct snd_codec)
-#define SNDRV_COMPRESS_TSTAMP          _IOR('C', 0x20, struct snd_compr_tstamp)
-#define SNDRV_COMPRESS_AVAIL           _IOR('C', 0x21, struct snd_compr_avail)
-#define SNDRV_COMPRESS_PAUSE           _IO('C', 0x30)
-#define SNDRV_COMPRESS_RESUME          _IO('C', 0x31)
-#define SNDRV_COMPRESS_START           _IO('C', 0x32)
-#define SNDRV_COMPRESS_STOP            _IO('C', 0x33)
-#define SNDRV_COMPRESS_DRAIN           _IO('C', 0x34)
-/*
- * TODO
- * 1. add mmap support
- *
- */
-#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
-#endif
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
deleted file mode 100644 (file)
index 602dc6c..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- *  compress_params.h - codec types and parameters for compressed data
- *  streaming interface
- *
- *  Copyright (C) 2011 Intel Corporation
- *  Authors:   Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
- *              Vinod Koul <vinod.koul@linux.intel.com>
- *
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * The definitions in this file are derived from the OpenMAX AL version 1.1
- * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
- *
- * Copyright (c) 2007-2010 The Khronos Group Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and/or associated documentation files (the
- * "Materials "), to deal in the Materials without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Materials, and to
- * permit persons to whom the Materials are furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Materials.
- *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
- *
- */
-#ifndef __SND_COMPRESS_PARAMS_H
-#define __SND_COMPRESS_PARAMS_H
-
-#include <linux/types.h>
-
-/* AUDIO CODECS SUPPORTED */
-#define MAX_NUM_CODECS 32
-#define MAX_NUM_CODEC_DESCRIPTORS 32
-#define MAX_NUM_BITRATES 32
-
-/* Codecs are listed linearly to allow for extensibility */
-#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
-#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
-#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
-#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
-#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
-#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
-#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
-#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
-#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
-#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
-#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
-#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
-#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
-#define SND_AUDIOCODEC_MAX                   SND_AUDIOCODEC_G729
-
-/*
- * Profile and modes are listed with bit masks. This allows for a
- * more compact representation of fields that will not evolve
- * (in contrast to the list of codecs)
- */
-
-#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
-
-/* MP3 modes are only useful for encoders */
-#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
-#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
-#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
-#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
-
-#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
-
-/* AMR modes are only useful for encoders */
-#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
-#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
-#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
-
-#define SND_AUDIOSTREAMFORMAT_UNDEFINED             ((__u32) 0x00000000)
-#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
-#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
-#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
-#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
-#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
-#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
-
-#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
-
-/* AMRWB modes are only useful for encoders */
-#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
-#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
-#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
-
-#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
-
-#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
-
-/* AAC modes are required for encoders and decoders */
-#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
-#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
-#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
-#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
-#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
-#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
-#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
-#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
-#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
-#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
-
-/* AAC formats are required for encoders and decoders */
-#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
-#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
-#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
-#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
-#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
-#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
-#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
-
-#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
-#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
-#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
-#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
-
-#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
-#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
-#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
-#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
-#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
-#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
-#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
-#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
-
-#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
-/*
- * Some implementations strip the ASF header and only send ASF packets
- * to the DSP
- */
-#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
-
-#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
-#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
-#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
-#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
-
-#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
-
-#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
-
-/*
- * Define quality levels for FLAC encoders, from LEVEL0 (fast)
- * to LEVEL8 (best)
- */
-#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
-#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
-#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
-#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
-#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
-#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
-#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
-#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
-#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
-
-#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
-#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
-
-/* IEC61937 payloads without CUVP and preambles */
-#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
-/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
-#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
-
-/*
- * IEC modes are mandatory for decoders. Format autodetection
- * will only happen on the DSP side with mode 0. The PCM mode should
- * not be used, the PCM codec should be used instead.
- */
-#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
-#define SND_AUDIOMODE_IEC_LPCM              ((__u32) 0x00000001)
-#define SND_AUDIOMODE_IEC_AC3               ((__u32) 0x00000002)
-#define SND_AUDIOMODE_IEC_MPEG1                     ((__u32) 0x00000004)
-#define SND_AUDIOMODE_IEC_MP3               ((__u32) 0x00000008)
-#define SND_AUDIOMODE_IEC_MPEG2                     ((__u32) 0x00000010)
-#define SND_AUDIOMODE_IEC_AACLC                     ((__u32) 0x00000020)
-#define SND_AUDIOMODE_IEC_DTS               ((__u32) 0x00000040)
-#define SND_AUDIOMODE_IEC_ATRAC                     ((__u32) 0x00000080)
-#define SND_AUDIOMODE_IEC_SACD              ((__u32) 0x00000100)
-#define SND_AUDIOMODE_IEC_EAC3              ((__u32) 0x00000200)
-#define SND_AUDIOMODE_IEC_DTS_HD            ((__u32) 0x00000400)
-#define SND_AUDIOMODE_IEC_MLP               ((__u32) 0x00000800)
-#define SND_AUDIOMODE_IEC_DST               ((__u32) 0x00001000)
-#define SND_AUDIOMODE_IEC_WMAPRO            ((__u32) 0x00002000)
-#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
-#define SND_AUDIOMODE_IEC_HE_AAC            ((__u32) 0x00008000)
-#define SND_AUDIOMODE_IEC_HE_AAC2           ((__u32) 0x00010000)
-#define SND_AUDIOMODE_IEC_MPEG_SURROUND             ((__u32) 0x00020000)
-
-#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
-#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
-#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
-
-#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
-#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
-
-/* <FIXME: multichannel encoders aren't supported for now. Would need
-   an additional definition of channel arrangement> */
-
-/* VBR/CBR definitions */
-#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
-#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
-
-/* Encoder options */
-
-struct snd_enc_wma {
-       __u32 super_block_align; /* WMA Type-specific data */
-};
-
-
-/**
- * struct snd_enc_vorbis
- * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
- * In the default mode of operation, the quality level is 3.
- * Normal quality range is 0 - 10.
- * @managed: Boolean. Set  bitrate  management  mode. This turns off the
- * normal VBR encoding, but allows hard or soft bitrate constraints to be
- * enforced by the encoder. This mode can be slower, and may also be
- * lower quality. It is primarily useful for streaming.
- * @max_bit_rate: Enabled only if managed is TRUE
- * @min_bit_rate: Enabled only if managed is TRUE
- * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
- * non-stereo streams). Useful for lower-bitrate encoding.
- *
- * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
- * properties
- *
- * For best quality users should specify VBR mode and set quality levels.
- */
-
-struct snd_enc_vorbis {
-       __s32 quality;
-       __u32 managed;
-       __u32 max_bit_rate;
-       __u32 min_bit_rate;
-       __u32 downmix;
-};
-
-
-/**
- * struct snd_enc_real
- * @quant_bits: number of coupling quantization bits in the stream
- * @start_region: coupling start region in the stream
- * @num_regions: number of regions value
- *
- * These options were extracted from the OpenMAX IL spec
- */
-
-struct snd_enc_real {
-       __u32 quant_bits;
-       __u32 start_region;
-       __u32 num_regions;
-};
-
-/**
- * struct snd_enc_flac
- * @num: serial number, valid only for OGG formats
- *     needs to be set by application
- * @gain: Add replay gain tags
- *
- * These options were extracted from the FLAC online documentation
- * at http://flac.sourceforge.net/documentation_tools_flac.html
- *
- * To make the API simpler, it is assumed that the user will select quality
- * profiles. Additional options that affect encoding quality and speed can
- * be added at a later stage if needed.
- *
- * By default the Subset format is used by encoders.
- *
- * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
- * not supported in this API.
- */
-
-struct snd_enc_flac {
-       __u32 num;
-       __u32 gain;
-};
-
-struct snd_enc_generic {
-       __u32 bw;       /* encoder bandwidth */
-       __s32 reserved[15];
-};
-
-union snd_codec_options {
-       struct snd_enc_wma wma;
-       struct snd_enc_vorbis vorbis;
-       struct snd_enc_real real;
-       struct snd_enc_flac flac;
-       struct snd_enc_generic generic;
-};
-
-/** struct snd_codec_desc - description of codec capabilities
- * @max_ch: Maximum number of audio channels
- * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
- * @bit_rate: Indexed array containing supported bit rates
- * @num_bitrates: Number of valid values in bit_rate array
- * @rate_control: value is specified by SND_RATECONTROLMODE defines.
- * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
- * @modes: Supported modes. See SND_AUDIOMODE defines
- * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
- * @min_buffer: Minimum buffer size handled by codec implementation
- * @reserved: reserved for future use
- *
- * This structure provides a scalar value for profiles, modes and stream
- * format fields.
- * If an implementation supports multiple combinations, they will be listed as
- * codecs with different descriptors, for example there would be 2 descriptors
- * for AAC-RAW and AAC-ADTS.
- * This entails some redundancy but makes it easier to avoid invalid
- * configurations.
- *
- */
-
-struct snd_codec_desc {
-       __u32 max_ch;
-       __u32 sample_rates;
-       __u32 bit_rate[MAX_NUM_BITRATES];
-       __u32 num_bitrates;
-       __u32 rate_control;
-       __u32 profiles;
-       __u32 modes;
-       __u32 formats;
-       __u32 min_buffer;
-       __u32 reserved[15];
-};
-
-/** struct snd_codec
- * @id: Identifies the supported audio encoder/decoder.
- *             See SND_AUDIOCODEC macros.
- * @ch_in: Number of input audio channels
- * @ch_out: Number of output channels. In case of contradiction between
- *             this field and the channelMode field, the channelMode field
- *             overrides.
- * @sample_rate: Audio sample rate of input data
- * @bit_rate: Bitrate of encoded data. May be ignored by decoders
- * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
- *               Encoders may rely on profiles for quality levels.
- *              May be ignored by decoders.
- * @profile: Mandatory for encoders, can be mandatory for specific
- *             decoders as well. See SND_AUDIOPROFILE defines.
- * @level: Supported level (Only used by WMA at the moment)
- * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
- * @format: Format of encoded bistream. Mandatory when defined.
- *             See SND_AUDIOSTREAMFORMAT defines.
- * @align: Block alignment in bytes of an audio sample.
- *             Only required for PCM or IEC formats.
- * @options: encoder-specific settings
- * @reserved: reserved for future use
- */
-
-struct snd_codec {
-       __u32 id;
-       __u32 ch_in;
-       __u32 ch_out;
-       __u32 sample_rate;
-       __u32 bit_rate;
-       __u32 rate_control;
-       __u32 profile;
-       __u32 level;
-       __u32 ch_mode;
-       __u32 format;
-       __u32 align;
-       union snd_codec_options options;
-       __u32 reserved[3];
-};
-
-#endif
index 50a059e7d11616d4eb836cf7f0cc738cc0eaed3f..6d9e15ed1dcf0cb2875a10ca6795b14f3d4e0c51 100644 (file)
@@ -19,6 +19,7 @@
 
 struct cs4271_platform_data {
        int gpio_nreset;        /* GPIO driving Reset pin, if any */
+       int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
index 1a33f48ebe7875f6ae6b6769583646a2e501dae9..f841ba4bacb81985f1a52257c8230a22de0333e2 100644 (file)
@@ -1,8 +1,3 @@
-#ifndef __SOUND_EMU10K1_H
-#define __SOUND_EMU10K1_H
-
-#include <linux/types.h>
-
 /*
  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
  *                  Creative Labs, Inc.
@@ -24,8 +19,9 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+#ifndef __SOUND_EMU10K1_H
+#define __SOUND_EMU10K1_H
 
-#ifdef __KERNEL__
 
 #include <sound/pcm.h>
 #include <sound/rawmidi.h>
 #include <sound/timer.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
+#include <linux/firmware.h>
 
 #include <asm/io.h>
+#include <uapi/sound/emu10k1.h>
 
 /* ------------------- DEFINES -------------------- */
 
@@ -1788,6 +1786,8 @@ struct snd_emu10k1 {
        unsigned int efx_voices_mask[2];
        unsigned int next_free_voice;
 
+       const struct firmware *firmware;
+
 #ifdef CONFIG_PM_SLEEP
        unsigned int *saved_ptr;
        unsigned int *saved_gpr;
@@ -1796,6 +1796,7 @@ struct snd_emu10k1 {
        unsigned int *saved_icode;
        unsigned int *p16v_saved;
        unsigned int saved_a_iocfg, saved_hcfg;
+       bool suspend;
 #endif
 
 };
@@ -1899,350 +1900,4 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
 int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
                                              struct snd_emu10k1_fx8010_irq *irq);
 
-#endif /* __KERNEL__ */
-
-/*
- * ---- FX8010 ----
- */
-
-#define EMU10K1_CARD_CREATIVE                  0x00000000
-#define EMU10K1_CARD_EMUAPS                    0x00000001
-
-#define EMU10K1_FX8010_PCM_COUNT               8
-
-/* instruction set */
-#define iMAC0   0x00   /* R = A + (X * Y >> 31)   ; saturation */
-#define iMAC1   0x01   /* R = A + (-X * Y >> 31)  ; saturation */
-#define iMAC2   0x02   /* R = A + (X * Y >> 31)   ; wraparound */
-#define iMAC3   0x03   /* R = A + (-X * Y >> 31)  ; wraparound */
-#define iMACINT0 0x04  /* R = A + X * Y           ; saturation */
-#define iMACINT1 0x05  /* R = A + X * Y           ; wraparound (31-bit) */
-#define iACC3   0x06   /* R = A + X + Y           ; saturation */
-#define iMACMV   0x07  /* R = A, acc += X * Y >> 31 */
-#define iANDXOR  0x08  /* R = (A & X) ^ Y */
-#define iTSTNEG  0x09  /* R = (A >= Y) ? X : ~X */
-#define iLIMITGE 0x0a  /* R = (A >= Y) ? X : Y */
-#define iLIMITLT 0x0b  /* R = (A < Y) ? X : Y */
-#define iLOG    0x0c   /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
-#define iEXP    0x0d   /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
-#define iINTERP  0x0e  /* R = A + (X * (Y - A) >> 31)  ; saturation */
-#define iSKIP    0x0f  /* R = A (cc_reg), X (count), Y (cc_test) */
-
-/* GPRs */
-#define FXBUS(x)       (0x00 + (x))    /* x = 0x00 - 0x0f */
-#define EXTIN(x)       (0x10 + (x))    /* x = 0x00 - 0x0f */
-#define EXTOUT(x)      (0x20 + (x))    /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
-#define FXBUS2(x)      (0x30 + (x))    /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
-                                       /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
-
-#define C_00000000     0x40
-#define C_00000001     0x41
-#define C_00000002     0x42
-#define C_00000003     0x43
-#define C_00000004     0x44
-#define C_00000008     0x45
-#define C_00000010     0x46
-#define C_00000020     0x47
-#define C_00000100     0x48
-#define C_00010000     0x49
-#define C_00080000     0x4a
-#define C_10000000     0x4b
-#define C_20000000     0x4c
-#define C_40000000     0x4d
-#define C_80000000     0x4e
-#define C_7fffffff     0x4f
-#define C_ffffffff     0x50
-#define C_fffffffe     0x51
-#define C_c0000000     0x52
-#define C_4f1bbcdc     0x53
-#define C_5a7ef9db     0x54
-#define C_00100000     0x55            /* ?? */
-#define GPR_ACCU       0x56            /* ACCUM, accumulator */
-#define GPR_COND       0x57            /* CCR, condition register */
-#define GPR_NOISE0     0x58            /* noise source */
-#define GPR_NOISE1     0x59            /* noise source */
-#define GPR_IRQ                0x5a            /* IRQ register */
-#define GPR_DBAC       0x5b            /* TRAM Delay Base Address Counter */
-#define GPR(x)         (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
-#define ITRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-#define ITRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-
-#define A_ITRAM_DATA(x)        (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_DATA(x)        (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-
-#define A_FXBUS(x)     (0x00 + (x))    /* x = 0x00 - 0x3f FX buses */
-#define A_EXTIN(x)     (0x40 + (x))    /* x = 0x00 - 0x0f physical ins */
-#define A_P16VIN(x)    (0x50 + (x))    /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
-#define A_EXTOUT(x)    (0x60 + (x))    /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
-#define A_FXBUS2(x)    (0x80 + (x))    /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
-#define A_EMU32OUTH(x) (0xa0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
-#define A_EMU32OUTL(x) (0xb0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
-#define A3_EMU32IN(x)  (0x160 + (x))   /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
-#define A3_EMU32OUT(x) (0x1E0 + (x))   /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
-#define A_GPR(x)       (A_FXGPREGBASE + (x))
-
-/* cc_reg constants */
-#define CC_REG_NORMALIZED C_00000001
-#define CC_REG_BORROW  C_00000002
-#define CC_REG_MINUS   C_00000004
-#define CC_REG_ZERO    C_00000008
-#define CC_REG_SATURATE        C_00000010
-#define CC_REG_NONZERO C_00000100
-
-/* FX buses */
-#define FXBUS_PCM_LEFT         0x00
-#define FXBUS_PCM_RIGHT                0x01
-#define FXBUS_PCM_LEFT_REAR    0x02
-#define FXBUS_PCM_RIGHT_REAR   0x03
-#define FXBUS_MIDI_LEFT                0x04
-#define FXBUS_MIDI_RIGHT       0x05
-#define FXBUS_PCM_CENTER       0x06
-#define FXBUS_PCM_LFE          0x07
-#define FXBUS_PCM_LEFT_FRONT   0x08
-#define FXBUS_PCM_RIGHT_FRONT  0x09
-#define FXBUS_MIDI_REVERB      0x0c
-#define FXBUS_MIDI_CHORUS      0x0d
-#define FXBUS_PCM_LEFT_SIDE    0x0e
-#define FXBUS_PCM_RIGHT_SIDE   0x0f
-#define FXBUS_PT_LEFT          0x14
-#define FXBUS_PT_RIGHT         0x15
-
-/* Inputs */
-#define EXTIN_AC97_L      0x00 /* AC'97 capture channel - left */
-#define EXTIN_AC97_R      0x01 /* AC'97 capture channel - right */
-#define EXTIN_SPDIF_CD_L   0x02        /* internal S/PDIF CD - onboard - left */
-#define EXTIN_SPDIF_CD_R   0x03        /* internal S/PDIF CD - onboard - right */
-#define EXTIN_ZOOM_L      0x04 /* Zoom Video I2S - left */
-#define EXTIN_ZOOM_R      0x05 /* Zoom Video I2S - right */
-#define EXTIN_TOSLINK_L           0x06 /* LiveDrive - TOSLink Optical - left */
-#define EXTIN_TOSLINK_R    0x07        /* LiveDrive - TOSLink Optical - right */
-#define EXTIN_LINE1_L     0x08 /* LiveDrive - Line/Mic 1 - left */
-#define EXTIN_LINE1_R     0x09 /* LiveDrive - Line/Mic 1 - right */
-#define EXTIN_COAX_SPDIF_L 0x0a        /* LiveDrive - Coaxial S/PDIF - left */
-#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
-#define EXTIN_LINE2_L     0x0c /* LiveDrive - Line/Mic 2 - left */
-#define EXTIN_LINE2_R     0x0d /* LiveDrive - Line/Mic 2 - right */
-
-/* Outputs */
-#define EXTOUT_AC97_L     0x00 /* AC'97 playback channel - left */
-#define EXTOUT_AC97_R     0x01 /* AC'97 playback channel - right */
-#define EXTOUT_TOSLINK_L   0x02        /* LiveDrive - TOSLink Optical - left */
-#define EXTOUT_TOSLINK_R   0x03        /* LiveDrive - TOSLink Optical - right */
-#define EXTOUT_AC97_CENTER 0x04        /* SB Live 5.1 - center */
-#define EXTOUT_AC97_LFE           0x05 /* SB Live 5.1 - LFE */
-#define EXTOUT_HEADPHONE_L 0x06        /* LiveDrive - Headphone - left */
-#define EXTOUT_HEADPHONE_R 0x07        /* LiveDrive - Headphone - right */
-#define EXTOUT_REAR_L     0x08 /* Rear channel - left */
-#define EXTOUT_REAR_R     0x09 /* Rear channel - right */
-#define EXTOUT_ADC_CAP_L   0x0a        /* ADC Capture buffer - left */
-#define EXTOUT_ADC_CAP_R   0x0b        /* ADC Capture buffer - right */
-#define EXTOUT_MIC_CAP    0x0c /* MIC Capture buffer */
-#define EXTOUT_AC97_REAR_L 0x0d        /* SB Live 5.1 (c) 2003 - Rear Left */
-#define EXTOUT_AC97_REAR_R 0x0e        /* SB Live 5.1 (c) 2003 - Rear Right */
-#define EXTOUT_ACENTER    0x11 /* Analog Center */
-#define EXTOUT_ALFE       0x12 /* Analog LFE */
-
-/* Audigy Inputs */
-#define A_EXTIN_AC97_L         0x00    /* AC'97 capture channel - left */
-#define A_EXTIN_AC97_R         0x01    /* AC'97 capture channel - right */
-#define A_EXTIN_SPDIF_CD_L     0x02    /* digital CD left */
-#define A_EXTIN_SPDIF_CD_R     0x03    /* digital CD left */
-#define A_EXTIN_OPT_SPDIF_L     0x04    /* audigy drive Optical SPDIF - left */
-#define A_EXTIN_OPT_SPDIF_R     0x05    /*                              right */ 
-#define A_EXTIN_LINE2_L                0x08    /* audigy drive line2/mic2 - left */
-#define A_EXTIN_LINE2_R                0x09    /*                           right */
-#define A_EXTIN_ADC_L          0x0a    /* Philips ADC - left */
-#define A_EXTIN_ADC_R          0x0b    /*               right */
-#define A_EXTIN_AUX2_L         0x0c    /* audigy drive aux2 - left */
-#define A_EXTIN_AUX2_R         0x0d    /*                   - right */
-
-/* Audigiy Outputs */
-#define A_EXTOUT_FRONT_L       0x00    /* digital front left */
-#define A_EXTOUT_FRONT_R       0x01    /*               right */
-#define A_EXTOUT_CENTER                0x02    /* digital front center */
-#define A_EXTOUT_LFE           0x03    /* digital front lfe */
-#define A_EXTOUT_HEADPHONE_L   0x04    /* headphone audigy drive left */
-#define A_EXTOUT_HEADPHONE_R   0x05    /*                        right */
-#define A_EXTOUT_REAR_L                0x06    /* digital rear left */
-#define A_EXTOUT_REAR_R                0x07    /*              right */
-#define A_EXTOUT_AFRONT_L      0x08    /* analog front left */
-#define A_EXTOUT_AFRONT_R      0x09    /*              right */
-#define A_EXTOUT_ACENTER       0x0a    /* analog center */
-#define A_EXTOUT_ALFE          0x0b    /* analog LFE */
-#define A_EXTOUT_ASIDE_L       0x0c    /* analog side left  - Audigy 2 ZS */
-#define A_EXTOUT_ASIDE_R       0x0d    /*             right - Audigy 2 ZS */
-#define A_EXTOUT_AREAR_L       0x0e    /* analog rear left */
-#define A_EXTOUT_AREAR_R       0x0f    /*             right */
-#define A_EXTOUT_AC97_L                0x10    /* AC97 left (front) */
-#define A_EXTOUT_AC97_R                0x11    /*      right */
-#define A_EXTOUT_ADC_CAP_L     0x16    /* ADC capture buffer left */
-#define A_EXTOUT_ADC_CAP_R     0x17    /*                    right */
-#define A_EXTOUT_MIC_CAP       0x18    /* Mic capture buffer */
-
-/* Audigy constants */
-#define A_C_00000000   0xc0
-#define A_C_00000001   0xc1
-#define A_C_00000002   0xc2
-#define A_C_00000003   0xc3
-#define A_C_00000004   0xc4
-#define A_C_00000008   0xc5
-#define A_C_00000010   0xc6
-#define A_C_00000020   0xc7
-#define A_C_00000100   0xc8
-#define A_C_00010000   0xc9
-#define A_C_00000800   0xca
-#define A_C_10000000   0xcb
-#define A_C_20000000   0xcc
-#define A_C_40000000   0xcd
-#define A_C_80000000   0xce
-#define A_C_7fffffff   0xcf
-#define A_C_ffffffff   0xd0
-#define A_C_fffffffe   0xd1
-#define A_C_c0000000   0xd2
-#define A_C_4f1bbcdc   0xd3
-#define A_C_5a7ef9db   0xd4
-#define A_C_00100000   0xd5
-#define A_GPR_ACCU     0xd6            /* ACCUM, accumulator */
-#define A_GPR_COND     0xd7            /* CCR, condition register */
-#define A_GPR_NOISE0   0xd8            /* noise source */
-#define A_GPR_NOISE1   0xd9            /* noise source */
-#define A_GPR_IRQ      0xda            /* IRQ register */
-#define A_GPR_DBAC     0xdb            /* TRAM Delay Base Address Counter - internal */
-#define A_GPR_DBACE    0xde            /* TRAM Delay Base Address Counter - external */
-
-/* definitions for debug register */
-#define EMU10K1_DBG_ZC                 0x80000000      /* zero tram counter */
-#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000      /* saturation control */
-#define EMU10K1_DBG_SATURATION_ADDR    0x01ff0000      /* saturation address */
-#define EMU10K1_DBG_SINGLE_STEP                0x00008000      /* single step mode */
-#define EMU10K1_DBG_STEP               0x00004000      /* start single step */
-#define EMU10K1_DBG_CONDITION_CODE     0x00003e00      /* condition code */
-#define EMU10K1_DBG_SINGLE_STEP_ADDR   0x000001ff      /* single step address */
-
-/* tank memory address line */
-#ifndef __KERNEL__
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff    /* 20 bit tank address field                    */
-#define TANKMEMADDRREG_CLEAR    0x00800000     /* Clear tank memory                            */
-#define TANKMEMADDRREG_ALIGN    0x00400000     /* Align read or write relative to tank access  */
-#define TANKMEMADDRREG_WRITE    0x00200000     /* Write to tank memory                         */
-#define TANKMEMADDRREG_READ     0x00100000     /* Read from tank memory                        */
-#endif
-
-struct snd_emu10k1_fx8010_info {
-       unsigned int internal_tram_size;        /* in samples */
-       unsigned int external_tram_size;        /* in samples */
-       char fxbus_names[16][32];               /* names of FXBUSes */
-       char extin_names[16][32];               /* names of external inputs */
-       char extout_names[32][32];              /* names of external outputs */
-       unsigned int gpr_controls;              /* count of GPR controls */
-};
-
-#define EMU10K1_GPR_TRANSLATION_NONE           0
-#define EMU10K1_GPR_TRANSLATION_TABLE100       1
-#define EMU10K1_GPR_TRANSLATION_BASS           2
-#define EMU10K1_GPR_TRANSLATION_TREBLE         3
-#define EMU10K1_GPR_TRANSLATION_ONOFF          4
-
-struct snd_emu10k1_fx8010_control_gpr {
-       struct snd_ctl_elem_id id;              /* full control ID definition */
-       unsigned int vcount;            /* visible count */
-       unsigned int count;             /* count of GPR (1..16) */
-       unsigned short gpr[32];         /* GPR number(s) */
-       unsigned int value[32];         /* initial values */
-       unsigned int min;               /* minimum range */
-       unsigned int max;               /* maximum range */
-       unsigned int translation;       /* translation type (EMU10K1_GPR_TRANSLATION*) */
-       const unsigned int *tlv;
-};
-
-/* old ABI without TLV support */
-struct snd_emu10k1_fx8010_control_old_gpr {
-       struct snd_ctl_elem_id id;
-       unsigned int vcount;
-       unsigned int count;
-       unsigned short gpr[32];
-       unsigned int value[32];
-       unsigned int min;
-       unsigned int max;
-       unsigned int translation;
-};
-
-struct snd_emu10k1_fx8010_code {
-       char name[128];
-
-       DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
-       __u32 __user *gpr_map;          /* initializers */
-
-       unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
-       struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
-
-       unsigned int gpr_del_control_count; /* count of GPR controls to remove */
-       struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
-
-       unsigned int gpr_list_control_count; /* count of GPR controls to list */
-       unsigned int gpr_list_control_total; /* total count of GPR controls */
-       struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
-
-       DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
-       __u32 __user *tram_data_map;      /* data initializers */
-       __u32 __user *tram_addr_map;      /* map initializers */
-
-       DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
-       __u32 __user *code;               /* one instruction - 64 bits */
-};
-
-struct snd_emu10k1_fx8010_tram {
-       unsigned int address;           /* 31.bit == 1 -> external TRAM */
-       unsigned int size;              /* size in samples (4 bytes) */
-       unsigned int *samples;          /* pointer to samples (20-bit) */
-                                       /* NULL->clear memory */
-};
-
-struct snd_emu10k1_fx8010_pcm_rec {
-       unsigned int substream;         /* substream number */
-       unsigned int res1;              /* reserved */
-       unsigned int channels;          /* 16-bit channels count, zero = remove this substream */
-       unsigned int tram_start;        /* ring buffer position in TRAM (in samples) */
-       unsigned int buffer_size;       /* count of buffered samples */
-       unsigned short gpr_size;                /* GPR containing size of ringbuffer in samples (host) */
-       unsigned short gpr_ptr;         /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
-       unsigned short gpr_count;       /* GPR containing count of samples between two interrupts (host) */
-       unsigned short gpr_tmpcount;    /* GPR containing current count of samples to interrupt (host = set, FX8010) */
-       unsigned short gpr_trigger;     /* GPR containing trigger (activate) information (host) */
-       unsigned short gpr_running;     /* GPR containing info if PCM is running (FX8010) */
-       unsigned char pad;              /* reserved */
-       unsigned char etram[32];        /* external TRAM address & data (one per channel) */
-       unsigned int res2;              /* reserved */
-};
-
-#define SNDRV_EMU10K1_VERSION          SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-#define SNDRV_EMU10K1_IOCTL_INFO       _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
-#define SNDRV_EMU10K1_IOCTL_CODE_POKE  _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK  _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE  _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK  _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_PCM_POKE   _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK   _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PVERSION   _IOR ('H', 0x40, int)
-#define SNDRV_EMU10K1_IOCTL_STOP       _IO  ('H', 0x80)
-#define SNDRV_EMU10K1_IOCTL_CONTINUE   _IO  ('H', 0x81)
-#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
-#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP        _IOW ('H', 0x83, int)
-#define SNDRV_EMU10K1_IOCTL_DBG_READ   _IOR ('H', 0x84, int)
-
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-
 #endif /* __SOUND_EMU10K1_H */
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
deleted file mode 100644 (file)
index 0909a38..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef __SOUND_HDSP_H
-#define __SOUND_HDSP_H
-
-/*
- *   Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
- *    
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-
-#define HDSP_MATRIX_MIXER_SIZE 2048
-
-enum HDSP_IO_Type {
-       Digiface,
-       Multiface,
-       H9652,
-       H9632,
-       RPM,
-       Undefined,
-};
-
-struct hdsp_peak_rms {
-       __u32 input_peaks[26];
-       __u32 playback_peaks[26];
-       __u32 output_peaks[28];
-       __u64 input_rms[26];
-       __u64 playback_rms[26];
-       /* These are only used for H96xx cards */
-       __u64 output_rms[26];
-};
-
-#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
-
-struct hdsp_config_info {
-       unsigned char pref_sync_ref;
-       unsigned char wordclock_sync_check;
-       unsigned char spdif_sync_check;
-       unsigned char adatsync_sync_check;
-       unsigned char adat_sync_check[3];
-       unsigned char spdif_in;
-       unsigned char spdif_out;
-       unsigned char spdif_professional;
-       unsigned char spdif_emphasis;
-       unsigned char spdif_nonaudio;
-       unsigned int spdif_sample_rate;
-       unsigned int system_sample_rate;
-       unsigned int autosync_sample_rate;
-       unsigned char system_clock_mode;
-       unsigned char clock_source;
-       unsigned char autosync_ref;
-       unsigned char line_out;
-       unsigned char passthru; 
-       unsigned char da_gain;
-       unsigned char ad_gain;
-       unsigned char phone_gain;
-       unsigned char xlr_breakout_cable;
-       unsigned char analog_extension_board;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
-
-struct hdsp_firmware {
-       void __user *firmware_data;     /* 24413 x 4 bytes */
-};
-
-#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
-
-struct hdsp_version {
-       enum HDSP_IO_Type io_type;
-       unsigned short firmware_rev;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
-
-struct hdsp_mixer {
-       unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
-};
-
-#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
-
-struct hdsp_9632_aeb {
-       int aebi;
-       int aebo;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
-
-/* typedefs for compatibility to user-space */
-typedef enum HDSP_IO_Type HDSP_IO_Type;
-typedef struct hdsp_peak_rms hdsp_peak_rms_t;
-typedef struct hdsp_config_info hdsp_config_info_t;
-typedef struct hdsp_firmware hdsp_firmware_t;
-typedef struct hdsp_version hdsp_version_t;
-typedef struct hdsp_mixer hdsp_mixer_t;
-typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
-
-#endif /* __SOUND_HDSP_H */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
deleted file mode 100644 (file)
index 1f59ea2..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-#ifndef __SOUND_HDSPM_H
-#define __SOUND_HDSPM_H
-/*
- *   Copyright (C) 2003 Winfried Ritsch (IEM)
- *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
- *
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
-#define HDSPM_MAX_CHANNELS      64
-
-enum hdspm_io_type {
-       MADI,
-       MADIface,
-       AIO,
-       AES32,
-       RayDAT
-};
-
-enum hdspm_speed {
-       ss,
-       ds,
-       qs
-};
-
-/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-
-struct hdspm_peak_rms {
-       uint32_t input_peaks[64];
-       uint32_t playback_peaks[64];
-       uint32_t output_peaks[64];
-
-       uint64_t input_rms[64];
-       uint64_t playback_rms[64];
-       uint64_t output_rms[64];
-
-       uint8_t speed; /* enum {ss, ds, qs} */
-       int status2;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
-       _IOR('H', 0x42, struct hdspm_peak_rms)
-
-/* ------------ CONFIG block IOCTL ---------------------- */
-
-struct hdspm_config {
-       unsigned char pref_sync_ref;
-       unsigned char wordclock_sync_check;
-       unsigned char madi_sync_check;
-       unsigned int system_sample_rate;
-       unsigned int autosync_sample_rate;
-       unsigned char system_clock_mode;
-       unsigned char clock_source;
-       unsigned char autosync_ref;
-       unsigned char line_out;
-       unsigned int passthru;
-       unsigned int analog_out;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
-       _IOR('H', 0x41, struct hdspm_config)
-
-/**
- * If there's a TCO (TimeCode Option) board installed,
- * there are further options and status data available.
- * The hdspm_ltc structure contains the current SMPTE
- * timecode and some status information and can be
- * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
- * hdspm_status struct.
- **/
-
-enum hdspm_ltc_format {
-       format_invalid,
-       fps_24,
-       fps_25,
-       fps_2997,
-       fps_30
-};
-
-enum hdspm_ltc_frame {
-       frame_invalid,
-       drop_frame,
-       full_frame
-};
-
-enum hdspm_ltc_input_format {
-       ntsc,
-       pal,
-       no_video
-};
-
-struct hdspm_ltc {
-       unsigned int ltc;
-
-       enum hdspm_ltc_format format;
-       enum hdspm_ltc_frame frame;
-       enum hdspm_ltc_input_format input_format;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
-
-/**
- * The status data reflects the device's current state
- * as determined by the card's configuration and
- * connection status.
- **/
-
-enum hdspm_sync {
-       hdspm_sync_no_lock = 0,
-       hdspm_sync_lock = 1,
-       hdspm_sync_sync = 2
-};
-
-enum hdspm_madi_input {
-       hdspm_input_optical = 0,
-       hdspm_input_coax = 1
-};
-
-enum hdspm_madi_channel_format {
-       hdspm_format_ch_64 = 0,
-       hdspm_format_ch_56 = 1
-};
-
-enum hdspm_madi_frame_format {
-       hdspm_frame_48 = 0,
-       hdspm_frame_96 = 1
-};
-
-enum hdspm_syncsource {
-       syncsource_wc = 0,
-       syncsource_madi = 1,
-       syncsource_tco = 2,
-       syncsource_sync = 3,
-       syncsource_none = 4
-};
-
-struct hdspm_status {
-       uint8_t card_type; /* enum hdspm_io_type */
-       enum hdspm_syncsource autosync_source;
-
-       uint64_t card_clock;
-       uint32_t master_period;
-
-       union {
-               struct {
-                       uint8_t sync_wc; /* enum hdspm_sync */
-                       uint8_t sync_madi; /* enum hdspm_sync */
-                       uint8_t sync_tco; /* enum hdspm_sync */
-                       uint8_t sync_in; /* enum hdspm_sync */
-                       uint8_t madi_input; /* enum hdspm_madi_input */
-                       uint8_t channel_format; /* enum hdspm_madi_channel_format */
-                       uint8_t frame_format; /* enum hdspm_madi_frame_format */
-               } madi;
-       } card_specific;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_STATUS \
-       _IOR('H', 0x47, struct hdspm_status)
-
-/**
- * Get information about the card and its add-ons.
- **/
-
-#define HDSPM_ADDON_TCO 1
-
-struct hdspm_version {
-       uint8_t card_type; /* enum hdspm_io_type */
-       char cardname[20];
-       unsigned int serial;
-       unsigned short firmware_rev;
-       int addons;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
-
-/* ------------- get Matrix Mixer IOCTL --------------- */
-
-/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
- * 32768 Bytes
- */
-
-/* organisation is 64 channelfader in a continuous memory block */
-/* equivalent to hardware definition, maybe for future feature of mmap of
- * them
- */
-/* each of 64 outputs has 64 infader and 64 outfader:
-   Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
-
-#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
-
-struct hdspm_channelfader {
-       unsigned int in[HDSPM_MIXER_CHANNELS];
-       unsigned int pb[HDSPM_MIXER_CHANNELS];
-};
-
-struct hdspm_mixer {
-       struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
-};
-
-struct hdspm_mixer_ioctl {
-       struct hdspm_mixer *mixer;
-};
-
-/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
-
-/* typedefs for compatibility to user-space */
-typedef struct hdspm_peak_rms hdspm_peak_rms_t;
-typedef struct hdspm_config_info hdspm_config_info_t;
-typedef struct hdspm_version hdspm_version_t;
-typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
-typedef struct hdspm_mixer hdspm_mixer_t;
-
-
-#endif
index 6268a4192d5c4a3300a5792ceb08610386b9256d..45c1981c9ca2b67fa7fb5ce76f609a87bc5a08a4 100644 (file)
@@ -71,6 +71,8 @@ struct snd_pcm_ops {
        int (*prepare)(struct snd_pcm_substream *substream);
        int (*trigger)(struct snd_pcm_substream *substream, int cmd);
        snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
+       int (*wall_clock)(struct snd_pcm_substream *substream,
+                         struct timespec *audio_ts);
        int (*copy)(struct snd_pcm_substream *substream, int channel,
                    snd_pcm_uframes_t pos,
                    void __user *buf, snd_pcm_uframes_t count);
@@ -281,6 +283,7 @@ struct snd_pcm_runtime {
        unsigned long hw_ptr_jiffies;   /* Time when hw_ptr is updated */
        unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
        snd_pcm_sframes_t delay;        /* extra delay; typically FIFO size */
+       u64 hw_ptr_wrap;                /* offset for hw_ptr due to boundary wrap-around */
 
        /* -- HW params -- */
        snd_pcm_access_t access;        /* access mode */
index 7e950560e5912dc8e1b20dc58b31c795fb94d6e5..c7c7788005e460bd8c41615ae5f86f4854839349 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef __SOUND_SB16_CSP_H
-#define __SOUND_SB16_CSP_H
-
 /*
  *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
  *                        Takashi Iwai <tiwai@suse.de>
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+#ifndef __SOUND_SB16_CSP_H
+#define __SOUND_SB16_CSP_H
 
-/* CSP modes */
-#define SNDRV_SB_CSP_MODE_NONE         0x00
-#define SNDRV_SB_CSP_MODE_DSP_READ     0x01    /* Record from DSP */
-#define SNDRV_SB_CSP_MODE_DSP_WRITE    0x02    /* Play to DSP */
-#define SNDRV_SB_CSP_MODE_QSOUND               0x04    /* QSound */
-
-/* CSP load flags */
-#define SNDRV_SB_CSP_LOAD_FROMUSER     0x01
-#define SNDRV_SB_CSP_LOAD_INITBLOCK    0x02
-
-/* CSP sample width */
-#define SNDRV_SB_CSP_SAMPLE_8BIT               0x01
-#define SNDRV_SB_CSP_SAMPLE_16BIT              0x02
-
-/* CSP channels */
-#define SNDRV_SB_CSP_MONO                      0x01
-#define SNDRV_SB_CSP_STEREO            0x02
-
-/* CSP rates */
-#define SNDRV_SB_CSP_RATE_8000         0x01
-#define SNDRV_SB_CSP_RATE_11025                0x02
-#define SNDRV_SB_CSP_RATE_22050                0x04
-#define SNDRV_SB_CSP_RATE_44100                0x08
-#define SNDRV_SB_CSP_RATE_ALL          0x0f
-
-/* CSP running state */
-#define SNDRV_SB_CSP_ST_IDLE           0x00
-#define SNDRV_SB_CSP_ST_LOADED         0x01
-#define SNDRV_SB_CSP_ST_RUNNING                0x02
-#define SNDRV_SB_CSP_ST_PAUSED         0x04
-#define SNDRV_SB_CSP_ST_AUTO           0x08
-#define SNDRV_SB_CSP_ST_QSOUND         0x10
-
-/* maximum QSound value (180 degrees right) */
-#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT  0x20
-
-/* maximum microcode RIFF file size */
-#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE   0x3000
-
-/* microcode header */
-struct snd_sb_csp_mc_header {
-       char codec_name[16];            /* id name of codec */
-       unsigned short func_req;        /* requested function */
-};
-
-/* microcode to be loaded */
-struct snd_sb_csp_microcode {
-       struct snd_sb_csp_mc_header info;
-       unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
-};
-
-/* start CSP with sample_width in mono/stereo */
-struct snd_sb_csp_start {
-       int sample_width;       /* sample width, look above */
-       int channels;           /* channels, look above */
-};
-
-/* CSP information */
-struct snd_sb_csp_info {
-       char codec_name[16];            /* id name of codec */
-       unsigned short func_nr;         /* function number */
-       unsigned int acc_format;        /* accepted PCM formats */
-       unsigned short acc_channels;    /* accepted channels */
-       unsigned short acc_width;       /* accepted sample width */
-       unsigned short acc_rates;       /* accepted sample rates */
-       unsigned short csp_mode;        /* CSP mode, see above */
-       unsigned short run_channels;    /* current channels  */
-       unsigned short run_width;       /* current sample width */
-       unsigned short version;         /* version id: 0x10 - 0x1f */
-       unsigned short state;           /* state bits */
-};
-
-/* HWDEP controls */
-/* get CSP information */
-#define SNDRV_SB_CSP_IOCTL_INFO                _IOR('H', 0x10, struct snd_sb_csp_info)
-/* load microcode to CSP */
-/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
- * defined for some architectures like MIPS, and it leads to build errors.
- * (x86 and co have 14-bit size, thus it's valid, though.)
- * As a workaround for skipping the size-limit check, here we don't use the
- * normal _IOW() macro but _IOC() with the manual argument.
- */
-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE   \
-       _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
-/* unload microcode from CSP */
-#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
-/* start CSP */
-#define SNDRV_SB_CSP_IOCTL_START               _IOW('H', 0x13, struct snd_sb_csp_start)
-/* stop CSP */
-#define SNDRV_SB_CSP_IOCTL_STOP                _IO('H', 0x14)
-/* pause CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_PAUSE               _IO('H', 0x15)
-/* restart CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_RESTART     _IO('H', 0x16)
-
-#ifdef __KERNEL__
 #include <sound/sb.h>
 #include <sound/hwdep.h>
 #include <linux/firmware.h>
+#include <uapi/sound/sb16_csp.h>
 
 struct snd_sb_csp;
 
@@ -183,6 +87,4 @@ struct snd_sb_csp {
 };
 
 int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
-#endif
-
 #endif /* __SOUND_SB16_CSP */
diff --git a/include/sound/sfnt_info.h b/include/sound/sfnt_info.h
deleted file mode 100644 (file)
index 1bce7fd..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-#ifndef __SOUND_SFNT_INFO_H
-#define __SOUND_SFNT_INFO_H
-
-/*
- *  Patch record compatible with AWE driver on OSS
- *
- *  Copyright (C) 1999-2000 Takashi Iwai
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/asound.h>
-
-/*
- * patch information record
- */
-
-#ifdef SNDRV_BIG_ENDIAN
-#define SNDRV_OSS_PATCHKEY(id) (0xfd00|id)
-#else
-#define SNDRV_OSS_PATCHKEY(id) ((id<<8)|0xfd)
-#endif
-
-/* patch interface header: 16 bytes */
-struct soundfont_patch_info {
-       unsigned short key;             /* use the key below */
-#define SNDRV_OSS_SOUNDFONT_PATCH              SNDRV_OSS_PATCHKEY(0x07)
-
-       short device_no;                /* synthesizer number */
-       unsigned short sf_id;           /* file id (should be zero) */
-       short optarg;                   /* optional argument */
-       int len;                        /* data length (without this header) */
-
-       short type;                     /* patch operation type */
-#define SNDRV_SFNT_LOAD_INFO           0       /* awe_voice_rec */
-#define SNDRV_SFNT_LOAD_DATA           1       /* awe_sample_info */
-#define SNDRV_SFNT_OPEN_PATCH  2       /* awe_open_parm */
-#define SNDRV_SFNT_CLOSE_PATCH 3       /* none */
-       /* 4 is obsolete */
-#define SNDRV_SFNT_REPLACE_DATA        5       /* awe_sample_info (optarg=#channels)*/
-#define SNDRV_SFNT_MAP_PRESET  6       /* awe_voice_map */
-       /* 7 is not used */
-#define SNDRV_SFNT_PROBE_DATA          8       /* optarg=sample */
-#define SNDRV_SFNT_REMOVE_INFO         9       /* optarg=(bank<<8)|instr */
-
-       short reserved;                 /* word alignment data */
-
-       /* the actual patch data begins after this */
-};
-
-
-/*
- * open patch
- */
-
-#define SNDRV_SFNT_PATCH_NAME_LEN      32
-
-struct soundfont_open_parm {
-       unsigned short type;            /* sample type */
-#define SNDRV_SFNT_PAT_TYPE_MISC       0
-#define SNDRV_SFNT_PAT_TYPE_GUS        6
-#define SNDRV_SFNT_PAT_TYPE_MAP        7
-#define SNDRV_SFNT_PAT_LOCKED  0x100   /* lock the samples */
-#define SNDRV_SFNT_PAT_SHARED  0x200   /* sample is shared */
-
-       short reserved;
-       char name[SNDRV_SFNT_PATCH_NAME_LEN];
-};
-
-
-/*
- * raw voice information record
- */
-
-/* wave table envelope & effect parameters to control EMU8000 */
-struct soundfont_voice_parm {
-       unsigned short moddelay;        /* modulation delay (0x8000) */
-       unsigned short modatkhld;       /* modulation attack & hold time (0x7f7f) */
-       unsigned short moddcysus;       /* modulation decay & sustain (0x7f7f) */
-       unsigned short modrelease;      /* modulation release time (0x807f) */
-       short modkeyhold, modkeydecay;  /* envelope change per key (not used) */
-       unsigned short voldelay;        /* volume delay (0x8000) */
-       unsigned short volatkhld;       /* volume attack & hold time (0x7f7f) */
-       unsigned short voldcysus;       /* volume decay & sustain (0x7f7f) */
-       unsigned short volrelease;      /* volume release time (0x807f) */
-       short volkeyhold, volkeydecay;  /* envelope change per key (not used) */
-       unsigned short lfo1delay;       /* LFO1 delay (0x8000) */
-       unsigned short lfo2delay;       /* LFO2 delay (0x8000) */
-       unsigned short pefe;            /* modulation pitch & cutoff (0x0000) */
-       unsigned short fmmod;           /* LFO1 pitch & cutoff (0x0000) */
-       unsigned short tremfrq;         /* LFO1 volume & freq (0x0000) */
-       unsigned short fm2frq2;         /* LFO2 pitch & freq (0x0000) */
-       unsigned char cutoff;           /* initial cutoff (0xff) */
-       unsigned char filterQ;          /* initial filter Q [0-15] (0x0) */
-       unsigned char chorus;           /* chorus send (0x00) */
-       unsigned char reverb;           /* reverb send (0x00) */
-       unsigned short reserved[4];     /* not used */
-};
-
-
-/* wave table parameters: 92 bytes */
-struct soundfont_voice_info {
-       unsigned short sf_id;           /* file id (should be zero) */
-       unsigned short sample;          /* sample id */
-       int start, end;                 /* sample offset correction */
-       int loopstart, loopend;         /* loop offset correction */
-       short rate_offset;              /* sample rate pitch offset */
-       unsigned short mode;            /* sample mode */
-#define SNDRV_SFNT_MODE_ROMSOUND               0x8000
-#define SNDRV_SFNT_MODE_STEREO         1
-#define SNDRV_SFNT_MODE_LOOPING                2
-#define SNDRV_SFNT_MODE_NORELEASE              4       /* obsolete */
-#define SNDRV_SFNT_MODE_INIT_PARM              8
-
-       short root;                     /* midi root key */
-       short tune;                     /* pitch tuning (in cents) */
-       unsigned char low, high;        /* key note range */
-       unsigned char vellow, velhigh;  /* velocity range */
-       signed char fixkey, fixvel;     /* fixed key, velocity */
-       signed char pan, fixpan;        /* panning, fixed panning */
-       short exclusiveClass;           /* exclusive class (0 = none) */
-       unsigned char amplitude;        /* sample volume (127 max) */
-       unsigned char attenuation;      /* attenuation (0.375dB) */
-       short scaleTuning;              /* pitch scale tuning(%), normally 100 */
-       struct soundfont_voice_parm parm;       /* voice envelope parameters */
-       unsigned short sample_mode;     /* sample mode_flag (set by driver) */
-};
-
-
-/* instrument info header: 4 bytes */
-struct soundfont_voice_rec_hdr {
-       unsigned char bank;             /* midi bank number */
-       unsigned char instr;            /* midi preset number */
-       char nvoices;                   /* number of voices */
-       char write_mode;                /* write mode; normally 0 */
-#define SNDRV_SFNT_WR_APPEND           0       /* append anyway */
-#define SNDRV_SFNT_WR_EXCLUSIVE                1       /* skip if already exists */
-#define SNDRV_SFNT_WR_REPLACE          2       /* replace if already exists */
-};
-
-
-/*
- * sample wave information
- */
-
-/* wave table sample header: 32 bytes */
-struct soundfont_sample_info {
-       unsigned short sf_id;           /* file id (should be zero) */
-       unsigned short sample;          /* sample id */
-       int start, end;                 /* start & end offset */
-       int loopstart, loopend;         /* loop start & end offset */
-       int size;                       /* size (0 = ROM) */
-       short dummy;                    /* not used */
-       unsigned short mode_flags;      /* mode flags */
-#define SNDRV_SFNT_SAMPLE_8BITS                1       /* wave data is 8bits */
-#define SNDRV_SFNT_SAMPLE_UNSIGNED     2       /* wave data is unsigned */
-#define SNDRV_SFNT_SAMPLE_NO_BLANK     4       /* no blank loop is attached */
-#define SNDRV_SFNT_SAMPLE_SINGLESHOT   8       /* single-shot w/o loop */
-#define SNDRV_SFNT_SAMPLE_BIDIR_LOOP   16      /* bidirectional looping */
-#define SNDRV_SFNT_SAMPLE_STEREO_LEFT  32      /* stereo left sound */
-#define SNDRV_SFNT_SAMPLE_STEREO_RIGHT 64      /* stereo right sound */
-#define SNDRV_SFNT_SAMPLE_REVERSE_LOOP 128     /* reverse looping */
-       unsigned int truesize;          /* used memory size (set by driver) */
-};
-
-
-/*
- * voice preset mapping (aliasing)
- */
-
-struct soundfont_voice_map {
-       int map_bank, map_instr, map_key;       /* key = -1 means all keys */
-       int src_bank, src_instr, src_key;
-};
-
-
-/*
- * ioctls for hwdep
- */
-
-#define SNDRV_EMUX_HWDEP_NAME  "Emux WaveTable"
-
-#define SNDRV_EMUX_VERSION     ((1 << 16) | (0 << 8) | 0)      /* 1.0.0 */
-
-struct snd_emux_misc_mode {
-       int port;       /* -1 = all */
-       int mode;
-       int value;
-       int value2;     /* reserved */
-};
-
-#define SNDRV_EMUX_IOCTL_VERSION       _IOR('H', 0x80, unsigned int)
-#define SNDRV_EMUX_IOCTL_LOAD_PATCH    _IOWR('H', 0x81, struct soundfont_patch_info)
-#define SNDRV_EMUX_IOCTL_RESET_SAMPLES _IO('H', 0x82)
-#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83)
-#define SNDRV_EMUX_IOCTL_MEM_AVAIL     _IOW('H', 0x84, int)
-#define SNDRV_EMUX_IOCTL_MISC_MODE     _IOWR('H', 0x84, struct snd_emux_misc_mode)
-
-#endif /* __SOUND_SFNT_INFO_H */
index 906010344dd7e0a227449f674d64b00a07dc1e86..cc1c919c64365898c47f7f6871b906dce0e5e1d4 100644 (file)
@@ -26,6 +26,7 @@
  * A:  inversion
  * B:  format mode
  * C:  chip specific
+ * D:  clock selecter if master mode
  */
 
 /* A: clock inversion */
 #define SH_FSI_OPTION_MASK     0x00000F00
 #define SH_FSI_ENABLE_STREAM_MODE      (1 << 8) /* for 16bit data */
 
+/* D:  clock selecter if master mode */
+#define SH_FSI_CLK_MASK                0x0000F000
+#define SH_FSI_CLK_EXTERNAL    (0 << 12)
+#define SH_FSI_CLK_CPG         (1 << 12) /* FSIxCK + FSI-DIV */
+
 /*
  * set_rate return value
  *
index c009f70b40293a70fa4b54afeb8fb4b879cac449..24e5d991f148be2d8b16cc309e1af7dca5f5f14b 100644 (file)
@@ -26,6 +26,7 @@ struct aic32x4_pdata {
        u32 power_cfg;
        u32 micpga_routing;
        bool swapdacs;
+       int rstn_gpio;
 };
 
 #endif
index 4f67c762cd744fae8380cec92f1a0b8a83ac2119..f634f8f85db53addf02c5f9e85d94363aee23de6 100644 (file)
 #include <sound/hwdep.h>
 #include <linux/interrupt.h>
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_VXLOADER) && !defined(CONFIG_SND_VX_LIB) /* built-in kernel */
-#define SND_VX_FW_LOADER       /* use the standard firmware loader */
-#endif
-#endif
-
 struct firmware;
 struct device;
 
index be8c41e2dc1589f8e899dee0642418f76628a551..0c9b44871df07b3f7e09de4a2d922f421a4895b5 100644 (file)
@@ -503,9 +503,20 @@ union ethtool_flow_union {
        __u8                                    hdata[52];
 };
 
+/**
+ * struct ethtool_flow_ext - additional RX flow fields
+ * @h_dest: destination MAC address
+ * @vlan_etype: VLAN EtherType
+ * @vlan_tci: VLAN tag control information
+ * @data: user defined data
+ *
+ * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT
+ * is set in &struct ethtool_rx_flow_spec @flow_type.
+ * @h_dest is valid if %FLOW_MAC_EXT is set.
+ */
 struct ethtool_flow_ext {
        __u8            padding[2];
-       unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
+       unsigned char   h_dest[ETH_ALEN];
        __be16          vlan_etype;
        __be16          vlan_tci;
        __be32          data[2];
@@ -519,7 +530,8 @@ struct ethtool_flow_ext {
  * @m_u: Masks for flow field bits to be matched
  * @m_ext: Masks for additional field bits to be matched
  *     Note, all additional fields must be ignored unless @flow_type
- *     includes the %FLOW_EXT flag.
+ *     includes the %FLOW_EXT or %FLOW_MAC_EXT flag
+ *     (see &struct ethtool_flow_ext description).
  * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
  *     if packets should be discarded
  * @location: Location of rule in the table.  Locations must be
index 558828590a6972f83b923f958a498a90222ad973..935119c698acd27270bbc0b18ae97bf97bf1ae9a 100644 (file)
@@ -851,6 +851,7 @@ struct input_keymap_entry {
 #define MSC_GESTURE            0x02
 #define MSC_RAW                        0x03
 #define MSC_SCAN               0x04
+#define MSC_TIMESTAMP          0x05
 #define MSC_MAX                        0x07
 #define MSC_CNT                        (MSC_MAX+1)
 
index 0a6d6ba44c858959cd2ed6b912751c5f36810989..e6e5d4b1370826328cee8771d523e2a1043c0889 100644 (file)
@@ -167,10 +167,15 @@ struct kvm_pit_config {
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL      19
 #define KVM_EXIT_S390_UCONTROL   20
+#define KVM_EXIT_WATCHDOG         21
 
 /* For KVM_EXIT_INTERNAL_ERROR */
-#define KVM_INTERNAL_ERROR_EMULATION 1
-#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Emulate instruction failed. */
+#define KVM_INTERNAL_ERROR_EMULATION   1
+/* Encounter unexpected simultaneous exceptions. */
+#define KVM_INTERNAL_ERROR_SIMUL_EX    2
+/* Encounter unexpected vm-exit due to delivery event. */
+#define KVM_INTERNAL_ERROR_DELIVERY_EV 3
 
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
@@ -477,6 +482,8 @@ struct kvm_ppc_smmu_info {
        struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +633,8 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_READONLY_MEM 81
 #endif
 #define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
+#define KVM_CAP_PPC_HTAB_FD 84
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -848,6 +857,11 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_SMMU_INFO    _IOR(KVMIO,  0xa6, struct kvm_ppc_smmu_info)
 /* Available with KVM_CAP_PPC_ALLOC_HTAB */
 #define KVM_PPC_ALLOCATE_HTAB    _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_PPC_HTAB_FD */
+#define KVM_PPC_GET_HTAB_FD      _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 
 /*
  * ioctls for vcpu fds
@@ -911,9 +925,6 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS             _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS             _IOW(KVMIO,  0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_SW_TLB */
 #define KVM_DIRTY_TLB            _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
 /* Available with KVM_CAP_ONE_REG */
index e15192cb9cf40c31ac54f23ac234cd521277b57c..12f68c7ceba65694dba0af1149995ddc21b13283 100644 (file)
@@ -27,6 +27,7 @@
 #define ISOFS_SUPER_MAGIC      0x9660
 #define JFFS2_SUPER_MAGIC      0x72b6
 #define PSTOREFS_MAGIC         0x6165676C
+#define EFIVARFS_MAGIC         0xde5e81e4
 
 #define MINIX_SUPER_MAGIC      0x137F          /* minix v1 fs, 14 char names */
 #define MINIX_SUPER_MAGIC2     0x138F          /* minix v1 fs, 30 char names */
index 20ae747ddf3483af636aef6f729fe90a33fa852d..6b7b6f1e2fd6a697dd26427c1130a5b51823d899 100644 (file)
 #define  PCI_AF_STATUS_TP      0x01
 #define PCI_CAP_AF_SIZEOF      6       /* size of AF registers */
 
-/* PCI-X registers */
+/* PCI-X registers (Type 0 (non-bridge) devices) */
 
 #define PCI_X_CMD              2       /* Modes & Features */
 #define  PCI_X_CMD_DPERR_E     0x0001  /* Data Parity Error Recovery Enable */
 #define PCI_CAP_PCIX_SIZEOF_V1 24      /* size for Version 1 */
 #define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1  /* Same for v2 */
 
+/* PCI-X registers (Type 1 (bridge) devices) */
+
+#define PCI_X_BRIDGE_SSTATUS   2       /* Secondary Status */
+#define  PCI_X_SSTATUS_64BIT   0x0001  /* Secondary AD interface is 64 bits */
+#define  PCI_X_SSTATUS_133MHZ  0x0002  /* 133 MHz capable */
+#define  PCI_X_SSTATUS_FREQ    0x03c0  /* Secondary Bus Mode and Frequency */
+#define  PCI_X_SSTATUS_VERS    0x3000  /* PCI-X Capability Version */
+#define  PCI_X_SSTATUS_V1      0x1000  /* Mode 2, not Mode 1 */
+#define  PCI_X_SSTATUS_V2      0x2000  /* Mode 1 or Modes 1 and 2 */
+#define  PCI_X_SSTATUS_266MHZ  0x4000  /* 266 MHz capable */
+#define  PCI_X_SSTATUS_533MHZ  0x8000  /* 533 MHz capable */
+#define PCI_X_BRIDGE_STATUS    4       /* Bridge Status */
+
 /* PCI Bridge Subsystem ID registers */
 
 #define PCI_SSVID_VENDOR_ID     4      /* PCI-Bridge subsystem vendor id register */
 #define  PCI_EXP_LNKCAP_PN     0xff000000 /* Port Number */
 #define PCI_EXP_LNKCTL         16      /* Link Control */
 #define  PCI_EXP_LNKCTL_ASPMC  0x0003  /* ASPM Control */
+#define  PCI_EXP_LNKCTL_ASPM_L0S  0x01 /* L0s Enable */
+#define  PCI_EXP_LNKCTL_ASPM_L1   0x02 /* L1 Enable */
 #define  PCI_EXP_LNKCTL_RCB    0x0008  /* Read Completion Boundary */
 #define  PCI_EXP_LNKCTL_LD     0x0010  /* Link Disable */
 #define  PCI_EXP_LNKCTL_RL     0x0020  /* Retrain Link */
 #define  PCI_EXP_OBFF_WAKE_EN  0x6000  /* OBFF using WAKE# signaling */
 #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44      /* v2 endpoints end here */
 #define PCI_EXP_LNKCAP2                44      /* Link Capability 2 */
-#define  PCI_EXP_LNKCAP2_SLS_2_5GB 0x01        /* Current Link Speed 2.5GT/s */
-#define  PCI_EXP_LNKCAP2_SLS_5_0GB 0x02        /* Current Link Speed 5.0GT/s */
-#define  PCI_EXP_LNKCAP2_SLS_8_0GB 0x04        /* Current Link Speed 8.0GT/s */
+#define  PCI_EXP_LNKCAP2_SLS_2_5GB 0x02        /* Supported Link Speed 2.5GT/s */
+#define  PCI_EXP_LNKCAP2_SLS_5_0GB 0x04        /* Supported Link Speed 5.0GT/s */
+#define  PCI_EXP_LNKCAP2_SLS_8_0GB 0x08        /* Supported Link Speed 8.0GT/s */
 #define  PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
 #define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
 #define PCI_EXP_LNKSTA2                50      /* Link Status 2 */
index 57bfa59cda74f3add633e7f6c0a7f6da9879b0b3..3cf3e946e331ee6ee006b03b5d569dc24719438b 100644 (file)
@@ -186,6 +186,7 @@ enum v4l2_memory {
        V4L2_MEMORY_MMAP             = 1,
        V4L2_MEMORY_USERPTR          = 2,
        V4L2_MEMORY_OVERLAY          = 3,
+       V4L2_MEMORY_DMABUF           = 4,
 };
 
 /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
@@ -602,6 +603,8 @@ struct v4l2_requestbuffers {
  *                     should be passed to mmap() called on the video node)
  * @userptr:           when memory is V4L2_MEMORY_USERPTR, a userspace pointer
  *                     pointing to this plane
+ * @fd:                        when memory is V4L2_MEMORY_DMABUF, a userspace file
+ *                     descriptor associated with this plane
  * @data_offset:       offset in the plane to the start of data; usually 0,
  *                     unless there is a header in front of the data
  *
@@ -616,6 +619,7 @@ struct v4l2_plane {
        union {
                __u32           mem_offset;
                unsigned long   userptr;
+               __s32           fd;
        } m;
        __u32                   data_offset;
        __u32                   reserved[11];
@@ -640,6 +644,8 @@ struct v4l2_plane {
  *             (or a "cookie" that should be passed to mmap() as offset)
  * @userptr:   for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
  *             a userspace pointer pointing to this buffer
+ * @fd:                for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF;
+ *             a userspace file descriptor associated with this buffer
  * @planes:    for multiplanar buffers; userspace pointer to the array of plane
  *             info structs for this buffer
  * @length:    size in bytes of the buffer (NOT its payload) for single-plane
@@ -666,6 +672,7 @@ struct v4l2_buffer {
                __u32           offset;
                unsigned long   userptr;
                struct v4l2_plane *planes;
+               __s32           fd;
        } m;
        __u32                   length;
        __u32                   reserved2;
@@ -687,6 +694,33 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE      0x0800
 #define V4L2_BUF_FLAG_NO_CACHE_CLEAN           0x1000
 
+/**
+ * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
+ *
+ * @index:     id number of the buffer
+ * @type:      enum v4l2_buf_type; buffer type (type == *_MPLANE for
+ *             multiplanar buffers);
+ * @plane:     index of the plane to be exported, 0 for single plane queues
+ * @flags:     flags for newly created file, currently only O_CLOEXEC is
+ *             supported, refer to manual of open syscall for more details
+ * @fd:                file descriptor associated with DMABUF (set by driver)
+ *
+ * Contains data used for exporting a video buffer as DMABUF file descriptor.
+ * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
+ * (identical to the cookie used to mmap() the buffer to userspace). All
+ * reserved fields must be set to zero. The field reserved0 is expected to
+ * become a structure 'type' allowing an alternative layout of the structure
+ * content. Therefore this field should not be used for any other extensions.
+ */
+struct v4l2_exportbuffer {
+       __u32           type; /* enum v4l2_buf_type */
+       __u32           index;
+       __u32           plane;
+       __u32           flags;
+       __s32           fd;
+       __u32           reserved[11];
+};
+
 /*
  *     O V E R L A Y   P R E V I E W
  */
@@ -737,7 +771,7 @@ struct v4l2_window {
 struct v4l2_captureparm {
        __u32              capability;    /*  Supported modes */
        __u32              capturemode;   /*  Current mode */
-       struct v4l2_fract  timeperframe;  /*  Time per frame in .1us units */
+       struct v4l2_fract  timeperframe;  /*  Time per frame in seconds */
        __u32              extendedmode;  /*  Driver-specific extensions */
        __u32              readbuffers;   /*  # of buffers for read */
        __u32              reserved[4];
@@ -1888,6 +1922,7 @@ struct v4l2_create_buffers {
 #define VIDIOC_S_FBUF           _IOW('V', 11, struct v4l2_framebuffer)
 #define VIDIOC_OVERLAY          _IOW('V', 14, int)
 #define VIDIOC_QBUF            _IOWR('V', 15, struct v4l2_buffer)
+#define VIDIOC_EXPBUF          _IOWR('V', 16, struct v4l2_exportbuffer)
 #define VIDIOC_DQBUF           _IOWR('V', 17, struct v4l2_buffer)
 #define VIDIOC_STREAMON                 _IOW('V', 18, int)
 #define VIDIOC_STREAMOFF        _IOW('V', 19, int)
index aafaa5aa54d46bb9a93a8137a22344408298223f..687ae332200f9f76f6c3a557b257ecb45b0a458f 100644 (file)
@@ -1 +1,7 @@
 # UAPI Header export list
+header-y += ib_user_cm.h
+header-y += ib_user_mad.h
+header-y += ib_user_sa.h
+header-y += ib_user_verbs.h
+header-y += rdma_netlink.h
+header-y += rdma_user_cm.h
diff --git a/include/uapi/rdma/ib_user_cm.h b/include/uapi/rdma/ib_user_cm.h
new file mode 100644 (file)
index 0000000..f79014a
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_CM_H
+#define IB_USER_CM_H
+
+#include <linux/types.h>
+#include <rdma/ib_user_sa.h>
+
+#define IB_USER_CM_ABI_VERSION 5
+
+enum {
+       IB_USER_CM_CMD_CREATE_ID,
+       IB_USER_CM_CMD_DESTROY_ID,
+       IB_USER_CM_CMD_ATTR_ID,
+
+       IB_USER_CM_CMD_LISTEN,
+       IB_USER_CM_CMD_NOTIFY,
+
+       IB_USER_CM_CMD_SEND_REQ,
+       IB_USER_CM_CMD_SEND_REP,
+       IB_USER_CM_CMD_SEND_RTU,
+       IB_USER_CM_CMD_SEND_DREQ,
+       IB_USER_CM_CMD_SEND_DREP,
+       IB_USER_CM_CMD_SEND_REJ,
+       IB_USER_CM_CMD_SEND_MRA,
+       IB_USER_CM_CMD_SEND_LAP,
+       IB_USER_CM_CMD_SEND_APR,
+       IB_USER_CM_CMD_SEND_SIDR_REQ,
+       IB_USER_CM_CMD_SEND_SIDR_REP,
+
+       IB_USER_CM_CMD_EVENT,
+       IB_USER_CM_CMD_INIT_QP_ATTR,
+};
+/*
+ * command ABI structures.
+ */
+struct ib_ucm_cmd_hdr {
+       __u32 cmd;
+       __u16 in;
+       __u16 out;
+};
+
+struct ib_ucm_create_id {
+       __u64 uid;
+       __u64 response;
+};
+
+struct ib_ucm_create_id_resp {
+       __u32 id;
+};
+
+struct ib_ucm_destroy_id {
+       __u64 response;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct ib_ucm_destroy_id_resp {
+       __u32 events_reported;
+};
+
+struct ib_ucm_attr_id {
+       __u64 response;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct ib_ucm_attr_id_resp {
+       __be64 service_id;
+       __be64 service_mask;
+       __be32 local_id;
+       __be32 remote_id;
+};
+
+struct ib_ucm_init_qp_attr {
+       __u64 response;
+       __u32 id;
+       __u32 qp_state;
+};
+
+struct ib_ucm_listen {
+       __be64 service_id;
+       __be64 service_mask;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct ib_ucm_notify {
+       __u32 id;
+       __u32 event;
+};
+
+struct ib_ucm_private_data {
+       __u64 data;
+       __u32 id;
+       __u8  len;
+       __u8  reserved[3];
+};
+
+struct ib_ucm_req {
+       __u32 id;
+       __u32 qpn;
+       __u32 qp_type;
+       __u32 psn;
+       __be64 sid;
+       __u64 data;
+       __u64 primary_path;
+       __u64 alternate_path;
+       __u8  len;
+       __u8  peer_to_peer;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  remote_cm_response_timeout;
+       __u8  flow_control;
+       __u8  local_cm_response_timeout;
+       __u8  retry_count;
+       __u8  rnr_retry_count;
+       __u8  max_cm_retries;
+       __u8  srq;
+       __u8  reserved[5];
+};
+
+struct ib_ucm_rep {
+       __u64 uid;
+       __u64 data;
+       __u32 id;
+       __u32 qpn;
+       __u32 psn;
+       __u8  len;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  target_ack_delay;
+       __u8  failover_accepted;
+       __u8  flow_control;
+       __u8  rnr_retry_count;
+       __u8  srq;
+       __u8  reserved[4];
+};
+
+struct ib_ucm_info {
+       __u32 id;
+       __u32 status;
+       __u64 info;
+       __u64 data;
+       __u8  info_len;
+       __u8  data_len;
+       __u8  reserved[6];
+};
+
+struct ib_ucm_mra {
+       __u64 data;
+       __u32 id;
+       __u8  len;
+       __u8  timeout;
+       __u8  reserved[2];
+};
+
+struct ib_ucm_lap {
+       __u64 path;
+       __u64 data;
+       __u32 id;
+       __u8  len;
+       __u8  reserved[3];
+};
+
+struct ib_ucm_sidr_req {
+       __u32 id;
+       __u32 timeout;
+       __be64 sid;
+       __u64 data;
+       __u64 path;
+       __u16 reserved_pkey;
+       __u8  len;
+       __u8  max_cm_retries;
+       __u8  reserved[4];
+};
+
+struct ib_ucm_sidr_rep {
+       __u32 id;
+       __u32 qpn;
+       __u32 qkey;
+       __u32 status;
+       __u64 info;
+       __u64 data;
+       __u8  info_len;
+       __u8  data_len;
+       __u8  reserved[6];
+};
+/*
+ * event notification ABI structures.
+ */
+struct ib_ucm_event_get {
+       __u64 response;
+       __u64 data;
+       __u64 info;
+       __u8  data_len;
+       __u8  info_len;
+       __u8  reserved[6];
+};
+
+struct ib_ucm_req_event_resp {
+       struct ib_user_path_rec primary_path;
+       struct ib_user_path_rec alternate_path;
+       __be64                 remote_ca_guid;
+       __u32                  remote_qkey;
+       __u32                  remote_qpn;
+       __u32                  qp_type;
+       __u32                  starting_psn;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  local_cm_response_timeout;
+       __u8  flow_control;
+       __u8  remote_cm_response_timeout;
+       __u8  retry_count;
+       __u8  rnr_retry_count;
+       __u8  srq;
+       __u8  port;
+       __u8  reserved[7];
+};
+
+struct ib_ucm_rep_event_resp {
+       __be64 remote_ca_guid;
+       __u32 remote_qkey;
+       __u32 remote_qpn;
+       __u32 starting_psn;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  target_ack_delay;
+       __u8  failover_accepted;
+       __u8  flow_control;
+       __u8  rnr_retry_count;
+       __u8  srq;
+       __u8  reserved[5];
+};
+
+struct ib_ucm_rej_event_resp {
+       __u32 reason;
+       /* ari in ib_ucm_event_get info field. */
+};
+
+struct ib_ucm_mra_event_resp {
+       __u8  timeout;
+       __u8  reserved[3];
+};
+
+struct ib_ucm_lap_event_resp {
+       struct ib_user_path_rec path;
+};
+
+struct ib_ucm_apr_event_resp {
+       __u32 status;
+       /* apr info in ib_ucm_event_get info field. */
+};
+
+struct ib_ucm_sidr_req_event_resp {
+       __u16 pkey;
+       __u8  port;
+       __u8  reserved;
+};
+
+struct ib_ucm_sidr_rep_event_resp {
+       __u32 status;
+       __u32 qkey;
+       __u32 qpn;
+       /* info in ib_ucm_event_get info field. */
+};
+
+#define IB_UCM_PRES_DATA      0x01
+#define IB_UCM_PRES_INFO      0x02
+#define IB_UCM_PRES_PRIMARY   0x04
+#define IB_UCM_PRES_ALTERNATE 0x08
+
+struct ib_ucm_event_resp {
+       __u64 uid;
+       __u32 id;
+       __u32 event;
+       __u32 present;
+       __u32 reserved;
+       union {
+               struct ib_ucm_req_event_resp req_resp;
+               struct ib_ucm_rep_event_resp rep_resp;
+               struct ib_ucm_rej_event_resp rej_resp;
+               struct ib_ucm_mra_event_resp mra_resp;
+               struct ib_ucm_lap_event_resp lap_resp;
+               struct ib_ucm_apr_event_resp apr_resp;
+
+               struct ib_ucm_sidr_req_event_resp sidr_req_resp;
+               struct ib_ucm_sidr_rep_event_resp sidr_rep_resp;
+
+               __u32                             send_status;
+       } u;
+};
+
+#endif /* IB_USER_CM_H */
diff --git a/include/uapi/rdma/ib_user_mad.h b/include/uapi/rdma/ib_user_mad.h
new file mode 100644 (file)
index 0000000..d6fce1c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_MAD_H
+#define IB_USER_MAD_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IB_USER_MAD_ABI_VERSION        5
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ */
+
+/**
+ * ib_user_mad_hdr_old - Old version of MAD packet header without pkey_index
+ * @id - ID of agent MAD received with/to be sent with
+ * @status - 0 on successful receive, ETIMEDOUT if no response
+ *   received (transaction ID in data[] will be set to TID of original
+ *   request) (ignored on send)
+ * @timeout_ms - Milliseconds to wait for response (unset on receive)
+ * @retries - Number of automatic retries to attempt
+ * @qpn - Remote QP number received from/to be sent to
+ * @qkey - Remote Q_Key to be sent with (unset on receive)
+ * @lid - Remote lid received from/to be sent to
+ * @sl - Service level received with/to be sent with
+ * @path_bits - Local path bits received with/to be sent with
+ * @grh_present - If set, GRH was received/should be sent
+ * @gid_index - Local GID index to send with (unset on receive)
+ * @hop_limit - Hop limit in GRH
+ * @traffic_class - Traffic class in GRH
+ * @gid - Remote GID in GRH
+ * @flow_label - Flow label in GRH
+ */
+struct ib_user_mad_hdr_old {
+       __u32   id;
+       __u32   status;
+       __u32   timeout_ms;
+       __u32   retries;
+       __u32   length;
+       __be32  qpn;
+       __be32  qkey;
+       __be16  lid;
+       __u8    sl;
+       __u8    path_bits;
+       __u8    grh_present;
+       __u8    gid_index;
+       __u8    hop_limit;
+       __u8    traffic_class;
+       __u8    gid[16];
+       __be32  flow_label;
+};
+
+/**
+ * ib_user_mad_hdr - MAD packet header
+ *   This layout allows specifying/receiving the P_Key index.  To use
+ *   this capability, an application must call the
+ *   IB_USER_MAD_ENABLE_PKEY ioctl on the user MAD file handle before
+ *   any other actions with the file handle.
+ * @id - ID of agent MAD received with/to be sent with
+ * @status - 0 on successful receive, ETIMEDOUT if no response
+ *   received (transaction ID in data[] will be set to TID of original
+ *   request) (ignored on send)
+ * @timeout_ms - Milliseconds to wait for response (unset on receive)
+ * @retries - Number of automatic retries to attempt
+ * @qpn - Remote QP number received from/to be sent to
+ * @qkey - Remote Q_Key to be sent with (unset on receive)
+ * @lid - Remote lid received from/to be sent to
+ * @sl - Service level received with/to be sent with
+ * @path_bits - Local path bits received with/to be sent with
+ * @grh_present - If set, GRH was received/should be sent
+ * @gid_index - Local GID index to send with (unset on receive)
+ * @hop_limit - Hop limit in GRH
+ * @traffic_class - Traffic class in GRH
+ * @gid - Remote GID in GRH
+ * @flow_label - Flow label in GRH
+ * @pkey_index - P_Key index
+ */
+struct ib_user_mad_hdr {
+       __u32   id;
+       __u32   status;
+       __u32   timeout_ms;
+       __u32   retries;
+       __u32   length;
+       __be32  qpn;
+       __be32  qkey;
+       __be16  lid;
+       __u8    sl;
+       __u8    path_bits;
+       __u8    grh_present;
+       __u8    gid_index;
+       __u8    hop_limit;
+       __u8    traffic_class;
+       __u8    gid[16];
+       __be32  flow_label;
+       __u16   pkey_index;
+       __u8    reserved[6];
+};
+
+/**
+ * ib_user_mad - MAD packet
+ * @hdr - MAD packet header
+ * @data - Contents of MAD
+ *
+ */
+struct ib_user_mad {
+       struct ib_user_mad_hdr hdr;
+       __u64   data[0];
+};
+
+/*
+ * Earlier versions of this interface definition declared the
+ * method_mask[] member as an array of __u32 but treated it as a
+ * bitmap made up of longs in the kernel.  This ambiguity meant that
+ * 32-bit big-endian applications that can run on both 32-bit and
+ * 64-bit kernels had no consistent ABI to rely on, and 64-bit
+ * big-endian applications that treated method_mask as being made up
+ * of 32-bit words would have their bitmap misinterpreted.
+ *
+ * To clear up this confusion, we change the declaration of
+ * method_mask[] to use unsigned long and handle the conversion from
+ * 32-bit userspace to 64-bit kernel for big-endian systems in the
+ * compat_ioctl method.  Unfortunately, to keep the structure layout
+ * the same, we need the method_mask[] array to be aligned only to 4
+ * bytes even when long is 64 bits, which forces us into this ugly
+ * typedef.
+ */
+typedef unsigned long __attribute__((aligned(4))) packed_ulong;
+#define IB_USER_MAD_LONGS_PER_METHOD_MASK (128 / (8 * sizeof (long)))
+
+/**
+ * ib_user_mad_reg_req - MAD registration request
+ * @id - Set by the kernel; used to identify agent in future requests.
+ * @qpn - Queue pair number; must be 0 or 1.
+ * @method_mask - The caller will receive unsolicited MADs for any method
+ *   where @method_mask = 1.
+ * @mgmt_class - Indicates which management class of MADs should be receive
+ *   by the caller.  This field is only required if the user wishes to
+ *   receive unsolicited MADs, otherwise it should be 0.
+ * @mgmt_class_version - Indicates which version of MADs for the given
+ *   management class to receive.
+ * @oui: Indicates IEEE OUI when mgmt_class is a vendor class
+ *   in the range from 0x30 to 0x4f. Otherwise not used.
+ * @rmpp_version: If set, indicates the RMPP version used.
+ *
+ */
+struct ib_user_mad_reg_req {
+       __u32   id;
+       packed_ulong method_mask[IB_USER_MAD_LONGS_PER_METHOD_MASK];
+       __u8    qpn;
+       __u8    mgmt_class;
+       __u8    mgmt_class_version;
+       __u8    oui[3];
+       __u8    rmpp_version;
+};
+
+#define IB_IOCTL_MAGIC         0x1b
+
+#define IB_USER_MAD_REGISTER_AGENT     _IOWR(IB_IOCTL_MAGIC, 1, \
+                                             struct ib_user_mad_reg_req)
+
+#define IB_USER_MAD_UNREGISTER_AGENT   _IOW(IB_IOCTL_MAGIC, 2, __u32)
+
+#define IB_USER_MAD_ENABLE_PKEY                _IO(IB_IOCTL_MAGIC, 3)
+
+#endif /* IB_USER_MAD_H */
diff --git a/include/uapi/rdma/ib_user_sa.h b/include/uapi/rdma/ib_user_sa.h
new file mode 100644 (file)
index 0000000..cfc7c9b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_SA_H
+#define IB_USER_SA_H
+
+#include <linux/types.h>
+
+enum {
+       IB_PATH_GMP             = 1,
+       IB_PATH_PRIMARY         = (1<<1),
+       IB_PATH_ALTERNATE       = (1<<2),
+       IB_PATH_OUTBOUND        = (1<<3),
+       IB_PATH_INBOUND         = (1<<4),
+       IB_PATH_INBOUND_REVERSE = (1<<5),
+       IB_PATH_BIDIRECTIONAL   = IB_PATH_OUTBOUND | IB_PATH_INBOUND_REVERSE
+};
+
+struct ib_path_rec_data {
+       __u32   flags;
+       __u32   reserved;
+       __u32   path_rec[16];
+};
+
+struct ib_user_path_rec {
+       __u8    dgid[16];
+       __u8    sgid[16];
+       __be16  dlid;
+       __be16  slid;
+       __u32   raw_traffic;
+       __be32  flow_label;
+       __u32   reversible;
+       __u32   mtu;
+       __be16  pkey;
+       __u8    hop_limit;
+       __u8    traffic_class;
+       __u8    numb_path;
+       __u8    sl;
+       __u8    mtu_selector;
+       __u8    rate_selector;
+       __u8    rate;
+       __u8    packet_life_time_selector;
+       __u8    packet_life_time;
+       __u8    preference;
+};
+
+#endif /* IB_USER_SA_H */
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
new file mode 100644 (file)
index 0000000..81aba3a
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_VERBS_H
+#define IB_USER_VERBS_H
+
+#include <linux/types.h>
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IB_USER_VERBS_ABI_VERSION      6
+
+enum {
+       IB_USER_VERBS_CMD_GET_CONTEXT,
+       IB_USER_VERBS_CMD_QUERY_DEVICE,
+       IB_USER_VERBS_CMD_QUERY_PORT,
+       IB_USER_VERBS_CMD_ALLOC_PD,
+       IB_USER_VERBS_CMD_DEALLOC_PD,
+       IB_USER_VERBS_CMD_CREATE_AH,
+       IB_USER_VERBS_CMD_MODIFY_AH,
+       IB_USER_VERBS_CMD_QUERY_AH,
+       IB_USER_VERBS_CMD_DESTROY_AH,
+       IB_USER_VERBS_CMD_REG_MR,
+       IB_USER_VERBS_CMD_REG_SMR,
+       IB_USER_VERBS_CMD_REREG_MR,
+       IB_USER_VERBS_CMD_QUERY_MR,
+       IB_USER_VERBS_CMD_DEREG_MR,
+       IB_USER_VERBS_CMD_ALLOC_MW,
+       IB_USER_VERBS_CMD_BIND_MW,
+       IB_USER_VERBS_CMD_DEALLOC_MW,
+       IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
+       IB_USER_VERBS_CMD_CREATE_CQ,
+       IB_USER_VERBS_CMD_RESIZE_CQ,
+       IB_USER_VERBS_CMD_DESTROY_CQ,
+       IB_USER_VERBS_CMD_POLL_CQ,
+       IB_USER_VERBS_CMD_PEEK_CQ,
+       IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
+       IB_USER_VERBS_CMD_CREATE_QP,
+       IB_USER_VERBS_CMD_QUERY_QP,
+       IB_USER_VERBS_CMD_MODIFY_QP,
+       IB_USER_VERBS_CMD_DESTROY_QP,
+       IB_USER_VERBS_CMD_POST_SEND,
+       IB_USER_VERBS_CMD_POST_RECV,
+       IB_USER_VERBS_CMD_ATTACH_MCAST,
+       IB_USER_VERBS_CMD_DETACH_MCAST,
+       IB_USER_VERBS_CMD_CREATE_SRQ,
+       IB_USER_VERBS_CMD_MODIFY_SRQ,
+       IB_USER_VERBS_CMD_QUERY_SRQ,
+       IB_USER_VERBS_CMD_DESTROY_SRQ,
+       IB_USER_VERBS_CMD_POST_SRQ_RECV,
+       IB_USER_VERBS_CMD_OPEN_XRCD,
+       IB_USER_VERBS_CMD_CLOSE_XRCD,
+       IB_USER_VERBS_CMD_CREATE_XSRQ,
+       IB_USER_VERBS_CMD_OPEN_QP
+};
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ * Specifically:
+ *  - Do not use pointer types -- pass pointers in __u64 instead.
+ *  - Make sure that any structure larger than 4 bytes is padded to a
+ *    multiple of 8 bytes.  Otherwise the structure size will be
+ *    different between 32-bit and 64-bit architectures.
+ */
+
+struct ib_uverbs_async_event_desc {
+       __u64 element;
+       __u32 event_type;       /* enum ib_event_type */
+       __u32 reserved;
+};
+
+struct ib_uverbs_comp_event_desc {
+       __u64 cq_handle;
+};
+
+/*
+ * All commands from userspace should start with a __u32 command field
+ * followed by __u16 in_words and out_words fields (which give the
+ * length of the command block and response buffer if any in 32-bit
+ * words).  The kernel driver will read these fields first and read
+ * the rest of the command struct based on these value.
+ */
+
+struct ib_uverbs_cmd_hdr {
+       __u32 command;
+       __u16 in_words;
+       __u16 out_words;
+};
+
+struct ib_uverbs_get_context {
+       __u64 response;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_get_context_resp {
+       __u32 async_fd;
+       __u32 num_comp_vectors;
+};
+
+struct ib_uverbs_query_device {
+       __u64 response;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_device_resp {
+       __u64 fw_ver;
+       __be64 node_guid;
+       __be64 sys_image_guid;
+       __u64 max_mr_size;
+       __u64 page_size_cap;
+       __u32 vendor_id;
+       __u32 vendor_part_id;
+       __u32 hw_ver;
+       __u32 max_qp;
+       __u32 max_qp_wr;
+       __u32 device_cap_flags;
+       __u32 max_sge;
+       __u32 max_sge_rd;
+       __u32 max_cq;
+       __u32 max_cqe;
+       __u32 max_mr;
+       __u32 max_pd;
+       __u32 max_qp_rd_atom;
+       __u32 max_ee_rd_atom;
+       __u32 max_res_rd_atom;
+       __u32 max_qp_init_rd_atom;
+       __u32 max_ee_init_rd_atom;
+       __u32 atomic_cap;
+       __u32 max_ee;
+       __u32 max_rdd;
+       __u32 max_mw;
+       __u32 max_raw_ipv6_qp;
+       __u32 max_raw_ethy_qp;
+       __u32 max_mcast_grp;
+       __u32 max_mcast_qp_attach;
+       __u32 max_total_mcast_qp_attach;
+       __u32 max_ah;
+       __u32 max_fmr;
+       __u32 max_map_per_fmr;
+       __u32 max_srq;
+       __u32 max_srq_wr;
+       __u32 max_srq_sge;
+       __u16 max_pkeys;
+       __u8  local_ca_ack_delay;
+       __u8  phys_port_cnt;
+       __u8  reserved[4];
+};
+
+struct ib_uverbs_query_port {
+       __u64 response;
+       __u8  port_num;
+       __u8  reserved[7];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_port_resp {
+       __u32 port_cap_flags;
+       __u32 max_msg_sz;
+       __u32 bad_pkey_cntr;
+       __u32 qkey_viol_cntr;
+       __u32 gid_tbl_len;
+       __u16 pkey_tbl_len;
+       __u16 lid;
+       __u16 sm_lid;
+       __u8  state;
+       __u8  max_mtu;
+       __u8  active_mtu;
+       __u8  lmc;
+       __u8  max_vl_num;
+       __u8  sm_sl;
+       __u8  subnet_timeout;
+       __u8  init_type_reply;
+       __u8  active_width;
+       __u8  active_speed;
+       __u8  phys_state;
+       __u8  link_layer;
+       __u8  reserved[2];
+};
+
+struct ib_uverbs_alloc_pd {
+       __u64 response;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_alloc_pd_resp {
+       __u32 pd_handle;
+};
+
+struct ib_uverbs_dealloc_pd {
+       __u32 pd_handle;
+};
+
+struct ib_uverbs_open_xrcd {
+       __u64 response;
+       __u32 fd;
+       __u32 oflags;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_open_xrcd_resp {
+       __u32 xrcd_handle;
+};
+
+struct ib_uverbs_close_xrcd {
+       __u32 xrcd_handle;
+};
+
+struct ib_uverbs_reg_mr {
+       __u64 response;
+       __u64 start;
+       __u64 length;
+       __u64 hca_va;
+       __u32 pd_handle;
+       __u32 access_flags;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_reg_mr_resp {
+       __u32 mr_handle;
+       __u32 lkey;
+       __u32 rkey;
+};
+
+struct ib_uverbs_dereg_mr {
+       __u32 mr_handle;
+};
+
+struct ib_uverbs_create_comp_channel {
+       __u64 response;
+};
+
+struct ib_uverbs_create_comp_channel_resp {
+       __u32 fd;
+};
+
+struct ib_uverbs_create_cq {
+       __u64 response;
+       __u64 user_handle;
+       __u32 cqe;
+       __u32 comp_vector;
+       __s32 comp_channel;
+       __u32 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_cq_resp {
+       __u32 cq_handle;
+       __u32 cqe;
+};
+
+struct ib_uverbs_resize_cq {
+       __u64 response;
+       __u32 cq_handle;
+       __u32 cqe;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_resize_cq_resp {
+       __u32 cqe;
+       __u32 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_poll_cq {
+       __u64 response;
+       __u32 cq_handle;
+       __u32 ne;
+};
+
+struct ib_uverbs_wc {
+       __u64 wr_id;
+       __u32 status;
+       __u32 opcode;
+       __u32 vendor_err;
+       __u32 byte_len;
+       union {
+               __u32 imm_data;
+               __u32 invalidate_rkey;
+       } ex;
+       __u32 qp_num;
+       __u32 src_qp;
+       __u32 wc_flags;
+       __u16 pkey_index;
+       __u16 slid;
+       __u8 sl;
+       __u8 dlid_path_bits;
+       __u8 port_num;
+       __u8 reserved;
+};
+
+struct ib_uverbs_poll_cq_resp {
+       __u32 count;
+       __u32 reserved;
+       struct ib_uverbs_wc wc[0];
+};
+
+struct ib_uverbs_req_notify_cq {
+       __u32 cq_handle;
+       __u32 solicited_only;
+};
+
+struct ib_uverbs_destroy_cq {
+       __u64 response;
+       __u32 cq_handle;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_cq_resp {
+       __u32 comp_events_reported;
+       __u32 async_events_reported;
+};
+
+struct ib_uverbs_global_route {
+       __u8  dgid[16];
+       __u32 flow_label;
+       __u8  sgid_index;
+       __u8  hop_limit;
+       __u8  traffic_class;
+       __u8  reserved;
+};
+
+struct ib_uverbs_ah_attr {
+       struct ib_uverbs_global_route grh;
+       __u16 dlid;
+       __u8  sl;
+       __u8  src_path_bits;
+       __u8  static_rate;
+       __u8  is_global;
+       __u8  port_num;
+       __u8  reserved;
+};
+
+struct ib_uverbs_qp_attr {
+       __u32   qp_attr_mask;
+       __u32   qp_state;
+       __u32   cur_qp_state;
+       __u32   path_mtu;
+       __u32   path_mig_state;
+       __u32   qkey;
+       __u32   rq_psn;
+       __u32   sq_psn;
+       __u32   dest_qp_num;
+       __u32   qp_access_flags;
+
+       struct ib_uverbs_ah_attr ah_attr;
+       struct ib_uverbs_ah_attr alt_ah_attr;
+
+       /* ib_qp_cap */
+       __u32   max_send_wr;
+       __u32   max_recv_wr;
+       __u32   max_send_sge;
+       __u32   max_recv_sge;
+       __u32   max_inline_data;
+
+       __u16   pkey_index;
+       __u16   alt_pkey_index;
+       __u8    en_sqd_async_notify;
+       __u8    sq_draining;
+       __u8    max_rd_atomic;
+       __u8    max_dest_rd_atomic;
+       __u8    min_rnr_timer;
+       __u8    port_num;
+       __u8    timeout;
+       __u8    retry_cnt;
+       __u8    rnr_retry;
+       __u8    alt_port_num;
+       __u8    alt_timeout;
+       __u8    reserved[5];
+};
+
+struct ib_uverbs_create_qp {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 send_cq_handle;
+       __u32 recv_cq_handle;
+       __u32 srq_handle;
+       __u32 max_send_wr;
+       __u32 max_recv_wr;
+       __u32 max_send_sge;
+       __u32 max_recv_sge;
+       __u32 max_inline_data;
+       __u8  sq_sig_all;
+       __u8  qp_type;
+       __u8  is_srq;
+       __u8  reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_open_qp {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 qpn;
+       __u8  qp_type;
+       __u8  reserved[7];
+       __u64 driver_data[0];
+};
+
+/* also used for open response */
+struct ib_uverbs_create_qp_resp {
+       __u32 qp_handle;
+       __u32 qpn;
+       __u32 max_send_wr;
+       __u32 max_recv_wr;
+       __u32 max_send_sge;
+       __u32 max_recv_sge;
+       __u32 max_inline_data;
+       __u32 reserved;
+};
+
+/*
+ * This struct needs to remain a multiple of 8 bytes to keep the
+ * alignment of the modify QP parameters.
+ */
+struct ib_uverbs_qp_dest {
+       __u8  dgid[16];
+       __u32 flow_label;
+       __u16 dlid;
+       __u16 reserved;
+       __u8  sgid_index;
+       __u8  hop_limit;
+       __u8  traffic_class;
+       __u8  sl;
+       __u8  src_path_bits;
+       __u8  static_rate;
+       __u8  is_global;
+       __u8  port_num;
+};
+
+struct ib_uverbs_query_qp {
+       __u64 response;
+       __u32 qp_handle;
+       __u32 attr_mask;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_qp_resp {
+       struct ib_uverbs_qp_dest dest;
+       struct ib_uverbs_qp_dest alt_dest;
+       __u32 max_send_wr;
+       __u32 max_recv_wr;
+       __u32 max_send_sge;
+       __u32 max_recv_sge;
+       __u32 max_inline_data;
+       __u32 qkey;
+       __u32 rq_psn;
+       __u32 sq_psn;
+       __u32 dest_qp_num;
+       __u32 qp_access_flags;
+       __u16 pkey_index;
+       __u16 alt_pkey_index;
+       __u8  qp_state;
+       __u8  cur_qp_state;
+       __u8  path_mtu;
+       __u8  path_mig_state;
+       __u8  sq_draining;
+       __u8  max_rd_atomic;
+       __u8  max_dest_rd_atomic;
+       __u8  min_rnr_timer;
+       __u8  port_num;
+       __u8  timeout;
+       __u8  retry_cnt;
+       __u8  rnr_retry;
+       __u8  alt_port_num;
+       __u8  alt_timeout;
+       __u8  sq_sig_all;
+       __u8  reserved[5];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp {
+       struct ib_uverbs_qp_dest dest;
+       struct ib_uverbs_qp_dest alt_dest;
+       __u32 qp_handle;
+       __u32 attr_mask;
+       __u32 qkey;
+       __u32 rq_psn;
+       __u32 sq_psn;
+       __u32 dest_qp_num;
+       __u32 qp_access_flags;
+       __u16 pkey_index;
+       __u16 alt_pkey_index;
+       __u8  qp_state;
+       __u8  cur_qp_state;
+       __u8  path_mtu;
+       __u8  path_mig_state;
+       __u8  en_sqd_async_notify;
+       __u8  max_rd_atomic;
+       __u8  max_dest_rd_atomic;
+       __u8  min_rnr_timer;
+       __u8  port_num;
+       __u8  timeout;
+       __u8  retry_cnt;
+       __u8  rnr_retry;
+       __u8  alt_port_num;
+       __u8  alt_timeout;
+       __u8  reserved[2];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp_resp {
+};
+
+struct ib_uverbs_destroy_qp {
+       __u64 response;
+       __u32 qp_handle;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_qp_resp {
+       __u32 events_reported;
+};
+
+/*
+ * The ib_uverbs_sge structure isn't used anywhere, since we assume
+ * the ib_sge structure is packed the same way on 32-bit and 64-bit
+ * architectures in both kernel and user space.  It's just here to
+ * document the ABI.
+ */
+struct ib_uverbs_sge {
+       __u64 addr;
+       __u32 length;
+       __u32 lkey;
+};
+
+struct ib_uverbs_send_wr {
+       __u64 wr_id;
+       __u32 num_sge;
+       __u32 opcode;
+       __u32 send_flags;
+       union {
+               __u32 imm_data;
+               __u32 invalidate_rkey;
+       } ex;
+       union {
+               struct {
+                       __u64 remote_addr;
+                       __u32 rkey;
+                       __u32 reserved;
+               } rdma;
+               struct {
+                       __u64 remote_addr;
+                       __u64 compare_add;
+                       __u64 swap;
+                       __u32 rkey;
+                       __u32 reserved;
+               } atomic;
+               struct {
+                       __u32 ah;
+                       __u32 remote_qpn;
+                       __u32 remote_qkey;
+                       __u32 reserved;
+               } ud;
+       } wr;
+};
+
+struct ib_uverbs_post_send {
+       __u64 response;
+       __u32 qp_handle;
+       __u32 wr_count;
+       __u32 sge_count;
+       __u32 wqe_size;
+       struct ib_uverbs_send_wr send_wr[0];
+};
+
+struct ib_uverbs_post_send_resp {
+       __u32 bad_wr;
+};
+
+struct ib_uverbs_recv_wr {
+       __u64 wr_id;
+       __u32 num_sge;
+       __u32 reserved;
+};
+
+struct ib_uverbs_post_recv {
+       __u64 response;
+       __u32 qp_handle;
+       __u32 wr_count;
+       __u32 sge_count;
+       __u32 wqe_size;
+       struct ib_uverbs_recv_wr recv_wr[0];
+};
+
+struct ib_uverbs_post_recv_resp {
+       __u32 bad_wr;
+};
+
+struct ib_uverbs_post_srq_recv {
+       __u64 response;
+       __u32 srq_handle;
+       __u32 wr_count;
+       __u32 sge_count;
+       __u32 wqe_size;
+       struct ib_uverbs_recv_wr recv[0];
+};
+
+struct ib_uverbs_post_srq_recv_resp {
+       __u32 bad_wr;
+};
+
+struct ib_uverbs_create_ah {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 reserved;
+       struct ib_uverbs_ah_attr attr;
+};
+
+struct ib_uverbs_create_ah_resp {
+       __u32 ah_handle;
+};
+
+struct ib_uverbs_destroy_ah {
+       __u32 ah_handle;
+};
+
+struct ib_uverbs_attach_mcast {
+       __u8  gid[16];
+       __u32 qp_handle;
+       __u16 mlid;
+       __u16 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_detach_mcast {
+       __u8  gid[16];
+       __u32 qp_handle;
+       __u16 mlid;
+       __u16 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 max_wr;
+       __u32 max_sge;
+       __u32 srq_limit;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_xsrq {
+       __u64 response;
+       __u64 user_handle;
+       __u32 srq_type;
+       __u32 pd_handle;
+       __u32 max_wr;
+       __u32 max_sge;
+       __u32 srq_limit;
+       __u32 reserved;
+       __u32 xrcd_handle;
+       __u32 cq_handle;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq_resp {
+       __u32 srq_handle;
+       __u32 max_wr;
+       __u32 max_sge;
+       __u32 srqn;
+};
+
+struct ib_uverbs_modify_srq {
+       __u32 srq_handle;
+       __u32 attr_mask;
+       __u32 max_wr;
+       __u32 srq_limit;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_srq {
+       __u64 response;
+       __u32 srq_handle;
+       __u32 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_srq_resp {
+       __u32 max_wr;
+       __u32 max_sge;
+       __u32 srq_limit;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_srq {
+       __u64 response;
+       __u32 srq_handle;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_srq_resp {
+       __u32 events_reported;
+};
+
+#endif /* IB_USER_VERBS_H */
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
new file mode 100644 (file)
index 0000000..8297285
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _UAPI_RDMA_NETLINK_H
+#define _UAPI_RDMA_NETLINK_H
+
+#include <linux/types.h>
+
+enum {
+       RDMA_NL_RDMA_CM = 1
+};
+
+#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10)
+#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
+#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
+
+enum {
+       RDMA_NL_RDMA_CM_ID_STATS = 0,
+       RDMA_NL_RDMA_CM_NUM_OPS
+};
+
+enum {
+       RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
+       RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
+       RDMA_NL_RDMA_CM_NUM_ATTR,
+};
+
+struct rdma_cm_id_stats {
+       __u32   qp_num;
+       __u32   bound_dev_if;
+       __u32   port_space;
+       __s32   pid;
+       __u8    cm_state;
+       __u8    node_type;
+       __u8    port_num;
+       __u8    qp_type;
+};
+
+
+#endif /* _UAPI_RDMA_NETLINK_H */
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h
new file mode 100644 (file)
index 0000000..1ee9239
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RDMA_USER_CM_H
+#define RDMA_USER_CM_H
+
+#include <linux/types.h>
+#include <linux/in6.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_user_sa.h>
+
+#define RDMA_USER_CM_ABI_VERSION       4
+
+#define RDMA_MAX_PRIVATE_DATA          256
+
+enum {
+       RDMA_USER_CM_CMD_CREATE_ID,
+       RDMA_USER_CM_CMD_DESTROY_ID,
+       RDMA_USER_CM_CMD_BIND_ADDR,
+       RDMA_USER_CM_CMD_RESOLVE_ADDR,
+       RDMA_USER_CM_CMD_RESOLVE_ROUTE,
+       RDMA_USER_CM_CMD_QUERY_ROUTE,
+       RDMA_USER_CM_CMD_CONNECT,
+       RDMA_USER_CM_CMD_LISTEN,
+       RDMA_USER_CM_CMD_ACCEPT,
+       RDMA_USER_CM_CMD_REJECT,
+       RDMA_USER_CM_CMD_DISCONNECT,
+       RDMA_USER_CM_CMD_INIT_QP_ATTR,
+       RDMA_USER_CM_CMD_GET_EVENT,
+       RDMA_USER_CM_CMD_GET_OPTION,
+       RDMA_USER_CM_CMD_SET_OPTION,
+       RDMA_USER_CM_CMD_NOTIFY,
+       RDMA_USER_CM_CMD_JOIN_MCAST,
+       RDMA_USER_CM_CMD_LEAVE_MCAST,
+       RDMA_USER_CM_CMD_MIGRATE_ID
+};
+
+/*
+ * command ABI structures.
+ */
+struct rdma_ucm_cmd_hdr {
+       __u32 cmd;
+       __u16 in;
+       __u16 out;
+};
+
+struct rdma_ucm_create_id {
+       __u64 uid;
+       __u64 response;
+       __u16 ps;
+       __u8  qp_type;
+       __u8  reserved[5];
+};
+
+struct rdma_ucm_create_id_resp {
+       __u32 id;
+};
+
+struct rdma_ucm_destroy_id {
+       __u64 response;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct rdma_ucm_destroy_id_resp {
+       __u32 events_reported;
+};
+
+struct rdma_ucm_bind_addr {
+       __u64 response;
+       struct sockaddr_in6 addr;
+       __u32 id;
+};
+
+struct rdma_ucm_resolve_addr {
+       struct sockaddr_in6 src_addr;
+       struct sockaddr_in6 dst_addr;
+       __u32 id;
+       __u32 timeout_ms;
+};
+
+struct rdma_ucm_resolve_route {
+       __u32 id;
+       __u32 timeout_ms;
+};
+
+struct rdma_ucm_query_route {
+       __u64 response;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct rdma_ucm_query_route_resp {
+       __u64 node_guid;
+       struct ib_user_path_rec ib_route[2];
+       struct sockaddr_in6 src_addr;
+       struct sockaddr_in6 dst_addr;
+       __u32 num_paths;
+       __u8 port_num;
+       __u8 reserved[3];
+};
+
+struct rdma_ucm_conn_param {
+       __u32 qp_num;
+       __u32 reserved;
+       __u8  private_data[RDMA_MAX_PRIVATE_DATA];
+       __u8  private_data_len;
+       __u8  srq;
+       __u8  responder_resources;
+       __u8  initiator_depth;
+       __u8  flow_control;
+       __u8  retry_count;
+       __u8  rnr_retry_count;
+       __u8  valid;
+};
+
+struct rdma_ucm_ud_param {
+       __u32 qp_num;
+       __u32 qkey;
+       struct ib_uverbs_ah_attr ah_attr;
+       __u8  private_data[RDMA_MAX_PRIVATE_DATA];
+       __u8  private_data_len;
+       __u8  reserved[7];
+};
+
+struct rdma_ucm_connect {
+       struct rdma_ucm_conn_param conn_param;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct rdma_ucm_listen {
+       __u32 id;
+       __u32 backlog;
+};
+
+struct rdma_ucm_accept {
+       __u64 uid;
+       struct rdma_ucm_conn_param conn_param;
+       __u32 id;
+       __u32 reserved;
+};
+
+struct rdma_ucm_reject {
+       __u32 id;
+       __u8  private_data_len;
+       __u8  reserved[3];
+       __u8  private_data[RDMA_MAX_PRIVATE_DATA];
+};
+
+struct rdma_ucm_disconnect {
+       __u32 id;
+};
+
+struct rdma_ucm_init_qp_attr {
+       __u64 response;
+       __u32 id;
+       __u32 qp_state;
+};
+
+struct rdma_ucm_notify {
+       __u32 id;
+       __u32 event;
+};
+
+struct rdma_ucm_join_mcast {
+       __u64 response;         /* rdma_ucm_create_id_resp */
+       __u64 uid;
+       struct sockaddr_in6 addr;
+       __u32 id;
+};
+
+struct rdma_ucm_get_event {
+       __u64 response;
+};
+
+struct rdma_ucm_event_resp {
+       __u64 uid;
+       __u32 id;
+       __u32 event;
+       __u32 status;
+       union {
+               struct rdma_ucm_conn_param conn;
+               struct rdma_ucm_ud_param   ud;
+       } param;
+};
+
+/* Option levels */
+enum {
+       RDMA_OPTION_ID          = 0,
+       RDMA_OPTION_IB          = 1
+};
+
+/* Option details */
+enum {
+       RDMA_OPTION_ID_TOS       = 0,
+       RDMA_OPTION_ID_REUSEADDR = 1,
+       RDMA_OPTION_ID_AFONLY    = 2,
+       RDMA_OPTION_IB_PATH      = 1
+};
+
+struct rdma_ucm_set_option {
+       __u64 optval;
+       __u32 id;
+       __u32 level;
+       __u32 optname;
+       __u32 optlen;
+};
+
+struct rdma_ucm_migrate_id {
+       __u64 response;
+       __u32 id;
+       __u32 fd;
+};
+
+struct rdma_ucm_migrate_resp {
+       __u32 events_reported;
+};
+
+#endif /* RDMA_USER_CM_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..0f7d279ebde35fd1be21cc922def324eaacb240f 100644 (file)
@@ -1 +1,11 @@
 # UAPI Header export list
+header-y += asequencer.h
+header-y += asound.h
+header-y += asound_fm.h
+header-y += compress_offload.h
+header-y += compress_params.h
+header-y += emu10k1.h
+header-y += hdsp.h
+header-y += hdspm.h
+header-y += sb16_csp.h
+header-y += sfnt_info.h
diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h
new file mode 100644 (file)
index 0000000..09c8a00
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ *  Main header file for the ALSA sequencer
+ *  Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
+ *            (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_ASEQUENCER_H
+#define _UAPI__SOUND_ASEQUENCER_H
+
+
+/** version of the sequencer */
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
+
+/**
+ * definition of sequencer event types
+ */
+
+/** system messages
+ * event data type = #snd_seq_result
+ */
+#define SNDRV_SEQ_EVENT_SYSTEM         0
+#define SNDRV_SEQ_EVENT_RESULT         1
+
+/** note messages (channel specific)
+ * event data type = #snd_seq_ev_note
+ */
+#define SNDRV_SEQ_EVENT_NOTE           5
+#define SNDRV_SEQ_EVENT_NOTEON         6
+#define SNDRV_SEQ_EVENT_NOTEOFF                7
+#define SNDRV_SEQ_EVENT_KEYPRESS       8
+       
+/** control messages (channel specific)
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_CONTROLLER     10
+#define SNDRV_SEQ_EVENT_PGMCHANGE      11
+#define SNDRV_SEQ_EVENT_CHANPRESS      12
+#define SNDRV_SEQ_EVENT_PITCHBEND      13      /**< from -8192 to 8191 */
+#define SNDRV_SEQ_EVENT_CONTROL14      14      /**< 14 bit controller value */
+#define SNDRV_SEQ_EVENT_NONREGPARAM    15      /**< 14 bit NRPN address + 14 bit unsigned value */
+#define SNDRV_SEQ_EVENT_REGPARAM       16      /**< 14 bit RPN address + 14 bit unsigned value */
+
+/** synchronisation messages
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_SONGPOS                20      /* Song Position Pointer with LSB and MSB values */
+#define SNDRV_SEQ_EVENT_SONGSEL                21      /* Song Select with song ID number */
+#define SNDRV_SEQ_EVENT_QFRAME         22      /* midi time code quarter frame */
+#define SNDRV_SEQ_EVENT_TIMESIGN       23      /* SMF Time Signature event */
+#define SNDRV_SEQ_EVENT_KEYSIGN                24      /* SMF Key Signature event */
+               
+/** timer messages
+ * event data type = snd_seq_ev_queue_control
+ */
+#define SNDRV_SEQ_EVENT_START          30      /* midi Real Time Start message */
+#define SNDRV_SEQ_EVENT_CONTINUE       31      /* midi Real Time Continue message */
+#define SNDRV_SEQ_EVENT_STOP           32      /* midi Real Time Stop message */       
+#define        SNDRV_SEQ_EVENT_SETPOS_TICK     33      /* set tick queue position */
+#define SNDRV_SEQ_EVENT_SETPOS_TIME    34      /* set realtime queue position */
+#define SNDRV_SEQ_EVENT_TEMPO          35      /* (SMF) Tempo event */
+#define SNDRV_SEQ_EVENT_CLOCK          36      /* midi Real Time Clock message */
+#define SNDRV_SEQ_EVENT_TICK           37      /* midi Real Time Tick message */
+#define SNDRV_SEQ_EVENT_QUEUE_SKEW     38      /* skew queue tempo */
+
+/** others
+ * event data type = none
+ */
+#define SNDRV_SEQ_EVENT_TUNE_REQUEST   40      /* tune request */
+#define SNDRV_SEQ_EVENT_RESET          41      /* reset to power-on state */
+#define SNDRV_SEQ_EVENT_SENSING                42      /* "active sensing" event */
+
+/** echo back, kernel private messages
+ * event data type = any type
+ */
+#define SNDRV_SEQ_EVENT_ECHO           50      /* echo event */
+#define SNDRV_SEQ_EVENT_OSS            51      /* OSS raw event */
+
+/** system status messages (broadcast for subscribers)
+ * event data type = snd_seq_addr
+ */
+#define SNDRV_SEQ_EVENT_CLIENT_START   60      /* new client has connected */
+#define SNDRV_SEQ_EVENT_CLIENT_EXIT    61      /* client has left the system */
+#define SNDRV_SEQ_EVENT_CLIENT_CHANGE  62      /* client status/info has changed */
+#define SNDRV_SEQ_EVENT_PORT_START     63      /* new port was created */
+#define SNDRV_SEQ_EVENT_PORT_EXIT      64      /* port was deleted from system */
+#define SNDRV_SEQ_EVENT_PORT_CHANGE    65      /* port status/info has changed */
+
+/** port connection changes
+ * event data type = snd_seq_connect
+ */
+#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED        66      /* ports connected */
+#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67   /* ports disconnected */
+
+/* 70-89:  synthesizer events - obsoleted */
+
+/** user-defined events with fixed length
+ * event data type = any
+ */
+#define SNDRV_SEQ_EVENT_USR0           90
+#define SNDRV_SEQ_EVENT_USR1           91
+#define SNDRV_SEQ_EVENT_USR2           92
+#define SNDRV_SEQ_EVENT_USR3           93
+#define SNDRV_SEQ_EVENT_USR4           94
+#define SNDRV_SEQ_EVENT_USR5           95
+#define SNDRV_SEQ_EVENT_USR6           96
+#define SNDRV_SEQ_EVENT_USR7           97
+#define SNDRV_SEQ_EVENT_USR8           98
+#define SNDRV_SEQ_EVENT_USR9           99
+
+/* 100-118: instrument layer - obsoleted */
+/* 119-129: reserved */
+
+/* 130-139: variable length events
+ * event data type = snd_seq_ev_ext
+ * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
+ */
+#define SNDRV_SEQ_EVENT_SYSEX          130     /* system exclusive data (variable length) */
+#define SNDRV_SEQ_EVENT_BOUNCE         131     /* error event */
+/* 132-134: reserved */
+#define SNDRV_SEQ_EVENT_USR_VAR0       135
+#define SNDRV_SEQ_EVENT_USR_VAR1       136
+#define SNDRV_SEQ_EVENT_USR_VAR2       137
+#define SNDRV_SEQ_EVENT_USR_VAR3       138
+#define SNDRV_SEQ_EVENT_USR_VAR4       139
+
+/* 150-151: kernel events with quote - DO NOT use in user clients */
+#define SNDRV_SEQ_EVENT_KERNEL_ERROR   150
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE   151     /* obsolete */
+
+/* 152-191: reserved */
+
+/* 192-254: hardware specific events */
+
+/* 255: special event */
+#define SNDRV_SEQ_EVENT_NONE           255
+
+
+typedef unsigned char snd_seq_event_type_t;
+
+/** event address */
+struct snd_seq_addr {
+       unsigned char client;   /**< Client number:         0..255, 255 = broadcast to all clients */
+       unsigned char port;     /**< Port within client:    0..255, 255 = broadcast to all ports */
+};
+
+/** port connection */
+struct snd_seq_connect {
+       struct snd_seq_addr sender;
+       struct snd_seq_addr dest;
+};
+
+
+#define SNDRV_SEQ_ADDRESS_UNKNOWN      253     /* unknown source */
+#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS  254     /* send event to all subscribed ports */
+#define SNDRV_SEQ_ADDRESS_BROADCAST    255     /* send event to all queues/clients/ports/channels */
+#define SNDRV_SEQ_QUEUE_DIRECT         253     /* direct dispatch */
+
+       /* event mode flag - NOTE: only 8 bits available! */
+#define SNDRV_SEQ_TIME_STAMP_TICK      (0<<0) /* timestamp in clock ticks */
+#define SNDRV_SEQ_TIME_STAMP_REAL      (1<<0) /* timestamp in real time */
+#define SNDRV_SEQ_TIME_STAMP_MASK      (1<<0)
+
+#define SNDRV_SEQ_TIME_MODE_ABS                (0<<1)  /* absolute timestamp */
+#define SNDRV_SEQ_TIME_MODE_REL                (1<<1)  /* relative to current time */
+#define SNDRV_SEQ_TIME_MODE_MASK       (1<<1)
+
+#define SNDRV_SEQ_EVENT_LENGTH_FIXED   (0<<2)  /* fixed event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE        (1<<2)  /* variable event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARUSR  (2<<2)  /* variable event size - user memory space */
+#define SNDRV_SEQ_EVENT_LENGTH_MASK    (3<<2)
+
+#define SNDRV_SEQ_PRIORITY_NORMAL      (0<<4)  /* normal priority */
+#define SNDRV_SEQ_PRIORITY_HIGH                (1<<4)  /* event should be processed before others */
+#define SNDRV_SEQ_PRIORITY_MASK                (1<<4)
+
+
+       /* note event */
+struct snd_seq_ev_note {
+       unsigned char channel;
+       unsigned char note;
+       unsigned char velocity;
+       unsigned char off_velocity;     /* only for SNDRV_SEQ_EVENT_NOTE */
+       unsigned int duration;          /* only for SNDRV_SEQ_EVENT_NOTE */
+};
+
+       /* controller event */
+struct snd_seq_ev_ctrl {
+       unsigned char channel;
+       unsigned char unused1, unused2, unused3;        /* pad */
+       unsigned int param;
+       signed int value;
+};
+
+       /* generic set of bytes (12x8 bit) */
+struct snd_seq_ev_raw8 {
+       unsigned char d[12];    /* 8 bit value */
+};
+
+       /* generic set of integers (3x32 bit) */
+struct snd_seq_ev_raw32 {
+       unsigned int d[3];      /* 32 bit value */
+};
+
+       /* external stored data */
+struct snd_seq_ev_ext {
+       unsigned int len;       /* length of data */
+       void *ptr;              /* pointer to data (note: maybe 64-bit) */
+} __attribute__((packed));
+
+struct snd_seq_result {
+       int event;              /* processed event type */
+       int result;
+};
+
+
+struct snd_seq_real_time {
+       unsigned int tv_sec;    /* seconds */
+       unsigned int tv_nsec;   /* nanoseconds */
+};
+
+typedef unsigned int snd_seq_tick_time_t;      /* midi ticks */
+
+union snd_seq_timestamp {
+       snd_seq_tick_time_t tick;
+       struct snd_seq_real_time time;
+};
+
+struct snd_seq_queue_skew {
+       unsigned int value;
+       unsigned int base;
+};
+
+       /* queue timer control */
+struct snd_seq_ev_queue_control {
+       unsigned char queue;                    /* affected queue */
+       unsigned char pad[3];                   /* reserved */
+       union {
+               signed int value;               /* affected value (e.g. tempo) */
+               union snd_seq_timestamp time;   /* time */
+               unsigned int position;          /* sync position */
+               struct snd_seq_queue_skew skew;
+               unsigned int d32[2];
+               unsigned char d8[8];
+       } param;
+};
+
+       /* quoted event - inside the kernel only */
+struct snd_seq_ev_quote {
+       struct snd_seq_addr origin;             /* original sender */
+       unsigned short value;           /* optional data */
+       struct snd_seq_event *event;            /* quoted event */
+} __attribute__((packed));
+
+
+       /* sequencer event */
+struct snd_seq_event {
+       snd_seq_event_type_t type;      /* event type */
+       unsigned char flags;            /* event flags */
+       char tag;
+       
+       unsigned char queue;            /* schedule queue */
+       union snd_seq_timestamp time;   /* schedule time */
+
+
+       struct snd_seq_addr source;     /* source address */
+       struct snd_seq_addr dest;       /* destination address */
+
+       union {                         /* event data... */
+               struct snd_seq_ev_note note;
+               struct snd_seq_ev_ctrl control;
+               struct snd_seq_ev_raw8 raw8;
+               struct snd_seq_ev_raw32 raw32;
+               struct snd_seq_ev_ext ext;
+               struct snd_seq_ev_queue_control queue;
+               union snd_seq_timestamp time;
+               struct snd_seq_addr addr;
+               struct snd_seq_connect connect;
+               struct snd_seq_result result;
+               struct snd_seq_ev_quote quote;
+       } data;
+};
+
+
+/*
+ * bounce event - stored as variable size data
+ */
+struct snd_seq_event_bounce {
+       int err;
+       struct snd_seq_event event;
+       /* external data follows here. */
+};
+
+
+       /* system information */
+struct snd_seq_system_info {
+       int queues;                     /* maximum queues count */
+       int clients;                    /* maximum clients count */
+       int ports;                      /* maximum ports per client */
+       int channels;                   /* maximum channels per port */
+       int cur_clients;                /* current clients */
+       int cur_queues;                 /* current queues */
+       char reserved[24];
+};
+
+
+       /* system running information */
+struct snd_seq_running_info {
+       unsigned char client;           /* client id */
+       unsigned char big_endian;       /* 1 = big-endian */
+       unsigned char cpu_mode;         /* 4 = 32bit, 8 = 64bit */
+       unsigned char pad;              /* reserved */
+       unsigned char reserved[12];
+};
+
+
+       /* known client numbers */
+#define SNDRV_SEQ_CLIENT_SYSTEM                0
+       /* internal client numbers */
+#define SNDRV_SEQ_CLIENT_DUMMY         14      /* midi through */
+#define SNDRV_SEQ_CLIENT_OSS           15      /* oss sequencer emulator */
+
+
+       /* client types */
+typedef int __bitwise snd_seq_client_type_t;
+#define        NO_CLIENT       ((__force snd_seq_client_type_t) 0)
+#define        USER_CLIENT     ((__force snd_seq_client_type_t) 1)
+#define        KERNEL_CLIENT   ((__force snd_seq_client_type_t) 2)
+                        
+       /* event filter flags */
+#define SNDRV_SEQ_FILTER_BROADCAST     (1<<0)  /* accept broadcast messages */
+#define SNDRV_SEQ_FILTER_MULTICAST     (1<<1)  /* accept multicast messages */
+#define SNDRV_SEQ_FILTER_BOUNCE                (1<<2)  /* accept bounce event in error */
+#define SNDRV_SEQ_FILTER_USE_EVENT     (1<<31) /* use event filter */
+
+struct snd_seq_client_info {
+       int client;                     /* client number to inquire */
+       snd_seq_client_type_t type;     /* client type */
+       char name[64];                  /* client name */
+       unsigned int filter;            /* filter flags */
+       unsigned char multicast_filter[8]; /* multicast filter bitmap */
+       unsigned char event_filter[32]; /* event filter bitmap */
+       int num_ports;                  /* RO: number of ports */
+       int event_lost;                 /* number of lost events */
+       char reserved[64];              /* for future use */
+};
+
+
+/* client pool size */
+struct snd_seq_client_pool {
+       int client;                     /* client number to inquire */
+       int output_pool;                /* outgoing (write) pool size */
+       int input_pool;                 /* incoming (read) pool size */
+       int output_room;                /* minimum free pool size for select/blocking mode */
+       int output_free;                /* unused size */
+       int input_free;                 /* unused size */
+       char reserved[64];
+};
+
+
+/* Remove events by specified criteria */
+
+#define SNDRV_SEQ_REMOVE_INPUT         (1<<0)  /* Flush input queues */
+#define SNDRV_SEQ_REMOVE_OUTPUT                (1<<1)  /* Flush output queues */
+#define SNDRV_SEQ_REMOVE_DEST          (1<<2)  /* Restrict by destination q:client:port */
+#define SNDRV_SEQ_REMOVE_DEST_CHANNEL  (1<<3)  /* Restrict by channel */
+#define SNDRV_SEQ_REMOVE_TIME_BEFORE   (1<<4)  /* Restrict to before time */
+#define SNDRV_SEQ_REMOVE_TIME_AFTER    (1<<5)  /* Restrict to time or after */
+#define SNDRV_SEQ_REMOVE_TIME_TICK     (1<<6)  /* Time is in ticks */
+#define SNDRV_SEQ_REMOVE_EVENT_TYPE    (1<<7)  /* Restrict to event type */
+#define SNDRV_SEQ_REMOVE_IGNORE_OFF    (1<<8)  /* Do not flush off events */
+#define SNDRV_SEQ_REMOVE_TAG_MATCH     (1<<9)  /* Restrict to events with given tag */
+
+struct snd_seq_remove_events {
+       unsigned int  remove_mode;      /* Flags that determine what gets removed */
+
+       union snd_seq_timestamp time;
+
+       unsigned char queue;    /* Queue for REMOVE_DEST */
+       struct snd_seq_addr dest;       /* Address for REMOVE_DEST */
+       unsigned char channel;  /* Channel for REMOVE_DEST */
+
+       int  type;      /* For REMOVE_EVENT_TYPE */
+       char  tag;      /* Tag for REMOVE_TAG */
+
+       int  reserved[10];      /* To allow for future binary compatibility */
+
+};
+
+
+       /* known port numbers */
+#define SNDRV_SEQ_PORT_SYSTEM_TIMER    0
+#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
+
+       /* port capabilities (32 bits) */
+#define SNDRV_SEQ_PORT_CAP_READ                (1<<0)  /* readable from this port */
+#define SNDRV_SEQ_PORT_CAP_WRITE       (1<<1)  /* writable to this port */
+
+#define SNDRV_SEQ_PORT_CAP_SYNC_READ   (1<<2)
+#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE  (1<<3)
+
+#define SNDRV_SEQ_PORT_CAP_DUPLEX      (1<<4)
+
+#define SNDRV_SEQ_PORT_CAP_SUBS_READ   (1<<5)  /* allow read subscription */
+#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE  (1<<6)  /* allow write subscription */
+#define SNDRV_SEQ_PORT_CAP_NO_EXPORT   (1<<7)  /* routing not allowed */
+
+       /* port type */
+#define SNDRV_SEQ_PORT_TYPE_SPECIFIC   (1<<0)  /* hardware specific */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1)        /* generic MIDI device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM    (1<<2)  /* General MIDI compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GS    (1<<3)  /* GS compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_XG    (1<<4)  /* XG compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32  (1<<5)  /* MT-32 compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2   (1<<6)  /* General MIDI 2 compatible device */
+
+/* other standards...*/
+#define SNDRV_SEQ_PORT_TYPE_SYNTH      (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
+#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)      /* Sampling device (support sample download) */
+#define SNDRV_SEQ_PORT_TYPE_SAMPLE     (1<<12) /* Sampling device (sample can be downloaded at any time) */
+/*...*/
+#define SNDRV_SEQ_PORT_TYPE_HARDWARE   (1<<16) /* driver for a hardware device */
+#define SNDRV_SEQ_PORT_TYPE_SOFTWARE   (1<<17) /* implemented in software */
+#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER        (1<<18) /* generates sound */
+#define SNDRV_SEQ_PORT_TYPE_PORT       (1<<19) /* connects to other device(s) */
+#define SNDRV_SEQ_PORT_TYPE_APPLICATION        (1<<20) /* application (sequencer/editor) */
+
+/* misc. conditioning flags */
+#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT  (1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP   (1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL   (1<<2)
+
+struct snd_seq_port_info {
+       struct snd_seq_addr addr;       /* client/port numbers */
+       char name[64];                  /* port name */
+
+       unsigned int capability;        /* port capability bits */
+       unsigned int type;              /* port type bits */
+       int midi_channels;              /* channels per MIDI port */
+       int midi_voices;                /* voices per MIDI port */
+       int synth_voices;               /* voices per SYNTH port */
+
+       int read_use;                   /* R/O: subscribers for output (from this port) */
+       int write_use;                  /* R/O: subscribers for input (to this port) */
+
+       void *kernel;                   /* reserved for kernel use (must be NULL) */
+       unsigned int flags;             /* misc. conditioning */
+       unsigned char time_queue;       /* queue # for timestamping */
+       char reserved[59];              /* for future use */
+};
+
+
+/* queue flags */
+#define SNDRV_SEQ_QUEUE_FLG_SYNC       (1<<0)  /* sync enabled */
+
+/* queue information */
+struct snd_seq_queue_info {
+       int queue;              /* queue id */
+
+       /*
+        *  security settings, only owner of this queue can start/stop timer
+        *  etc. if the queue is locked for other clients
+        */
+       int owner;              /* client id for owner of the queue */
+       unsigned locked:1;      /* timing queue locked for other queues */
+       char name[64];          /* name of this queue */
+       unsigned int flags;     /* flags */
+       char reserved[60];      /* for future use */
+
+};
+
+/* queue info/status */
+struct snd_seq_queue_status {
+       int queue;                      /* queue id */
+       int events;                     /* read-only - queue size */
+       snd_seq_tick_time_t tick;       /* current tick */
+       struct snd_seq_real_time time;  /* current time */
+       int running;                    /* running state of queue */
+       int flags;                      /* various flags */
+       char reserved[64];              /* for the future */
+};
+
+
+/* queue tempo */
+struct snd_seq_queue_tempo {
+       int queue;                      /* sequencer queue */
+       unsigned int tempo;             /* current tempo, us/tick */
+       int ppq;                        /* time resolution, ticks/quarter */
+       unsigned int skew_value;        /* queue skew */
+       unsigned int skew_base;         /* queue skew base */
+       char reserved[24];              /* for the future */
+};
+
+
+/* sequencer timer sources */
+#define SNDRV_SEQ_TIMER_ALSA           0       /* ALSA timer */
+#define SNDRV_SEQ_TIMER_MIDI_CLOCK     1       /* Midi Clock (CLOCK event) */
+#define SNDRV_SEQ_TIMER_MIDI_TICK      2       /* Midi Timer Tick (TICK event) */
+
+/* queue timer info */
+struct snd_seq_queue_timer {
+       int queue;                      /* sequencer queue */
+       int type;                       /* source timer type */
+       union {
+               struct {
+                       struct snd_timer_id id; /* ALSA's timer ID */
+                       unsigned int resolution;        /* resolution in Hz */
+               } alsa;
+       } u;
+       char reserved[64];              /* for the future use */
+};
+
+
+struct snd_seq_queue_client {
+       int queue;              /* sequencer queue */
+       int client;             /* sequencer client */
+       int used;               /* queue is used with this client
+                                  (must be set for accepting events) */
+       /* per client watermarks */
+       char reserved[64];      /* for future use */
+};
+
+
+#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE  (1<<0)  /* exclusive connection */
+#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP  (1<<1)
+#define SNDRV_SEQ_PORT_SUBS_TIME_REAL  (1<<2)
+
+struct snd_seq_port_subscribe {
+       struct snd_seq_addr sender;     /* sender address */
+       struct snd_seq_addr dest;       /* destination address */
+       unsigned int voices;            /* number of voices to be allocated (0 = don't care) */
+       unsigned int flags;             /* modes */
+       unsigned char queue;            /* input time-stamp queue (optional) */
+       unsigned char pad[3];           /* reserved */
+       char reserved[64];
+};
+
+/* type of query subscription */
+#define SNDRV_SEQ_QUERY_SUBS_READ      0
+#define SNDRV_SEQ_QUERY_SUBS_WRITE     1
+
+struct snd_seq_query_subs {
+       struct snd_seq_addr root;       /* client/port id to be searched */
+       int type;               /* READ or WRITE */
+       int index;              /* 0..N-1 */
+       int num_subs;           /* R/O: number of subscriptions on this port */
+       struct snd_seq_addr addr;       /* R/O: result */
+       unsigned char queue;    /* R/O: result */
+       unsigned int flags;     /* R/O: result */
+       char reserved[64];      /* for future use */
+};
+
+
+/*
+ *  IOCTL commands
+ */
+
+#define SNDRV_SEQ_IOCTL_PVERSION       _IOR ('S', 0x00, int)
+#define SNDRV_SEQ_IOCTL_CLIENT_ID      _IOR ('S', 0x01, int)
+#define SNDRV_SEQ_IOCTL_SYSTEM_INFO    _IOWR('S', 0x02, struct snd_seq_system_info)
+#define SNDRV_SEQ_IOCTL_RUNNING_MODE   _IOWR('S', 0x03, struct snd_seq_running_info)
+
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO        _IOWR('S', 0x10, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO        _IOW ('S', 0x11, struct snd_seq_client_info)
+
+#define SNDRV_SEQ_IOCTL_CREATE_PORT    _IOWR('S', 0x20, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_DELETE_PORT    _IOW ('S', 0x21, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_PORT_INFO  _IOWR('S', 0x22, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_SET_PORT_INFO  _IOW ('S', 0x23, struct snd_seq_port_info)
+
+#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
+
+#define SNDRV_SEQ_IOCTL_CREATE_QUEUE   _IOWR('S', 0x32, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_DELETE_QUEUE   _IOW ('S', 0x33, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE        _IOWR('S', 0x36, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO        _IOWR('S', 0x41, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO        _IOW ('S', 0x42, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER        _IOWR('S', 0x43, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER        _IOW ('S', 0x44, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER        _IOWR('S', 0x45, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER        _IOW ('S', 0x46, struct snd_seq_queue_timer)
+/* XXX
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
+*/
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT       _IOWR('S', 0x49, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT       _IOW ('S', 0x4a, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL        _IOWR('S', 0x4b, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL        _IOW ('S', 0x4c, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS  _IOW ('S', 0x4e, struct snd_seq_remove_events)
+#define SNDRV_SEQ_IOCTL_QUERY_SUBS     _IOWR('S', 0x4f, struct snd_seq_query_subs)
+#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION       _IOWR('S', 0x50, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT      _IOWR('S', 0x51, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT        _IOWR('S', 0x52, struct snd_seq_port_info)
+
+#endif /* _UAPI__SOUND_ASEQUENCER_H */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
new file mode 100644 (file)
index 0000000..1774a5c
--- /dev/null
@@ -0,0 +1,971 @@
+/*
+ *  Advanced Linux Sound Architecture - ALSA - Driver
+ *  Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
+ *                             Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef _UAPI__SOUND_ASOUND_H
+#define _UAPI__SOUND_ASOUND_H
+
+#include <linux/types.h>
+
+
+/*
+ *  protocol version
+ */
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
+       (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
+        (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
+          SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+/****************************************************************************
+ *                                                                          *
+ *        Digital audio interface                                          *
+ *                                                                          *
+ ****************************************************************************/
+
+struct snd_aes_iec958 {
+       unsigned char status[24];       /* AES/IEC958 channel status bits */
+       unsigned char subcode[147];     /* AES/IEC958 subcode bits */
+       unsigned char pad;              /* nothing */
+       unsigned char dig_subframe[4];  /* AES/IEC958 subframe bits */
+};
+
+/****************************************************************************
+ *                                                                          *
+ *        CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort                    *
+ *                                                                          *
+ ****************************************************************************/
+
+struct snd_cea_861_aud_if {
+       unsigned char db1_ct_cc; /* coding type and channel count */
+       unsigned char db2_sf_ss; /* sample frequency and size */
+       unsigned char db3; /* not used, all zeros */
+       unsigned char db4_ca; /* channel allocation code */
+       unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+};
+
+/****************************************************************************
+ *                                                                          *
+ *      Section for driver hardware dependent interface - /dev/snd/hw?      *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SNDRV_HWDEP_VERSION            SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+       SNDRV_HWDEP_IFACE_OPL2 = 0,
+       SNDRV_HWDEP_IFACE_OPL3,
+       SNDRV_HWDEP_IFACE_OPL4,
+       SNDRV_HWDEP_IFACE_SB16CSP,      /* Creative Signal Processor */
+       SNDRV_HWDEP_IFACE_EMU10K1,      /* FX8010 processor in EMU10K1 chip */
+       SNDRV_HWDEP_IFACE_YSS225,       /* Yamaha FX processor */
+       SNDRV_HWDEP_IFACE_ICS2115,      /* Wavetable synth */
+       SNDRV_HWDEP_IFACE_SSCAPE,       /* Ensoniq SoundScape ISA card (MC68EC000) */
+       SNDRV_HWDEP_IFACE_VX,           /* Digigram VX cards */
+       SNDRV_HWDEP_IFACE_MIXART,       /* Digigram miXart cards */
+       SNDRV_HWDEP_IFACE_USX2Y,        /* Tascam US122, US224 & US428 usb */
+       SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */  
+       SNDRV_HWDEP_IFACE_BLUETOOTH,    /* Bluetooth audio */
+       SNDRV_HWDEP_IFACE_USX2Y_PCM,    /* Tascam US122, US224 & US428 rawusb pcm */
+       SNDRV_HWDEP_IFACE_PCXHR,        /* Digigram PCXHR */
+       SNDRV_HWDEP_IFACE_SB_RC,        /* SB Extigy/Audigy2NX remote control */
+       SNDRV_HWDEP_IFACE_HDA,          /* HD-audio */
+       SNDRV_HWDEP_IFACE_USB_STREAM,   /* direct access to usb stream */
+
+       /* Don't forget to change the following: */
+       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+       unsigned int device;            /* WR: device number */
+       int card;                       /* R: card number */
+       unsigned char id[64];           /* ID (user selectable) */
+       unsigned char name[80];         /* hwdep name */
+       int iface;                      /* hwdep interface */
+       unsigned char reserved[64];     /* reserved for future */
+};
+
+/* generic DSP loader */
+struct snd_hwdep_dsp_status {
+       unsigned int version;           /* R: driver-specific version */
+       unsigned char id[32];           /* R: driver-specific ID string */
+       unsigned int num_dsps;          /* R: number of DSP images to transfer */
+       unsigned int dsp_loaded;        /* R: bit flags indicating the loaded DSPs */
+       unsigned int chip_ready;        /* R: 1 = initialization finished */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+struct snd_hwdep_dsp_image {
+       unsigned int index;             /* W: DSP index */
+       unsigned char name[64];         /* W: ID (e.g. file name) */
+       unsigned char __user *image;    /* W: binary image */
+       size_t length;                  /* W: size of image in bytes */
+       unsigned long driver_data;      /* W: driver-specific data */
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION     _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO         _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS   _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD     _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+/*****************************************************************************
+ *                                                                           *
+ *             Digital Audio (PCM) interface - /dev/snd/pcm??                *
+ *                                                                           *
+ *****************************************************************************/
+
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 11)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+       SNDRV_PCM_CLASS_GENERIC = 0,    /* standard mono or stereo device */
+       SNDRV_PCM_CLASS_MULTI,          /* multichannel device */
+       SNDRV_PCM_CLASS_MODEM,          /* software modem class */
+       SNDRV_PCM_CLASS_DIGITIZER,      /* digitizer class */
+       /* Don't forget to change the following: */
+       SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+       SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
+       SNDRV_PCM_SUBCLASS_MULTI_MIX,   /* multichannel subdevices are mixed together */
+       /* Don't forget to change the following: */
+       SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+       SNDRV_PCM_STREAM_PLAYBACK = 0,
+       SNDRV_PCM_STREAM_CAPTURE,
+       SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define        SNDRV_PCM_ACCESS_MMAP_INTERLEAVED       ((__force snd_pcm_access_t) 0) /* interleaved mmap */
+#define        SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED    ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
+#define        SNDRV_PCM_ACCESS_MMAP_COMPLEX           ((__force snd_pcm_access_t) 2) /* complex mmap */
+#define        SNDRV_PCM_ACCESS_RW_INTERLEAVED         ((__force snd_pcm_access_t) 3) /* readi/writei */
+#define        SNDRV_PCM_ACCESS_RW_NONINTERLEAVED      ((__force snd_pcm_access_t) 4) /* readn/writen */
+#define        SNDRV_PCM_ACCESS_LAST           SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define        SNDRV_PCM_FORMAT_S8     ((__force snd_pcm_format_t) 0)
+#define        SNDRV_PCM_FORMAT_U8     ((__force snd_pcm_format_t) 1)
+#define        SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define        SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define        SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define        SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define        SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
+#define        SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define        SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define        SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define        SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define        SNDRV_PCM_FORMAT_FLOAT_LE       ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_FLOAT_BE       ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_FLOAT64_LE     ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_FLOAT64_BE     ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
+#define        SNDRV_PCM_FORMAT_MU_LAW         ((__force snd_pcm_format_t) 20)
+#define        SNDRV_PCM_FORMAT_A_LAW          ((__force snd_pcm_format_t) 21)
+#define        SNDRV_PCM_FORMAT_IMA_ADPCM      ((__force snd_pcm_format_t) 22)
+#define        SNDRV_PCM_FORMAT_MPEG           ((__force snd_pcm_format_t) 23)
+#define        SNDRV_PCM_FORMAT_GSM            ((__force snd_pcm_format_t) 24)
+#define        SNDRV_PCM_FORMAT_SPECIAL        ((__force snd_pcm_format_t) 31)
+#define        SNDRV_PCM_FORMAT_S24_3LE        ((__force snd_pcm_format_t) 32) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S24_3BE        ((__force snd_pcm_format_t) 33) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U24_3LE        ((__force snd_pcm_format_t) 34) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U24_3BE        ((__force snd_pcm_format_t) 35) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S20_3LE        ((__force snd_pcm_format_t) 36) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S20_3BE        ((__force snd_pcm_format_t) 37) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U20_3LE        ((__force snd_pcm_format_t) 38) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U20_3BE        ((__force snd_pcm_format_t) 39) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S18_3LE        ((__force snd_pcm_format_t) 40) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_S18_3BE        ((__force snd_pcm_format_t) 41) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U18_3LE        ((__force snd_pcm_format_t) 42) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_U18_3BE        ((__force snd_pcm_format_t) 43) /* in three bytes */
+#define        SNDRV_PCM_FORMAT_G723_24        ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
+#define        SNDRV_PCM_FORMAT_G723_24_1B     ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
+#define        SNDRV_PCM_FORMAT_G723_40        ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
+#define        SNDRV_PCM_FORMAT_G723_40_1B     ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
+#define        SNDRV_PCM_FORMAT_LAST           SNDRV_PCM_FORMAT_G723_40_1B
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_LE
+#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_LE
+#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_LE
+#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_LE
+#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_LE
+#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_LE
+#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_LE
+#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_LE
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_BE
+#define        SNDRV_PCM_FORMAT_U16            SNDRV_PCM_FORMAT_U16_BE
+#define        SNDRV_PCM_FORMAT_S24            SNDRV_PCM_FORMAT_S24_BE
+#define        SNDRV_PCM_FORMAT_U24            SNDRV_PCM_FORMAT_U24_BE
+#define        SNDRV_PCM_FORMAT_S32            SNDRV_PCM_FORMAT_S32_BE
+#define        SNDRV_PCM_FORMAT_U32            SNDRV_PCM_FORMAT_U32_BE
+#define        SNDRV_PCM_FORMAT_FLOAT          SNDRV_PCM_FORMAT_FLOAT_BE
+#define        SNDRV_PCM_FORMAT_FLOAT64        SNDRV_PCM_FORMAT_FLOAT64_BE
+#define        SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define        SNDRV_PCM_SUBFORMAT_STD         ((__force snd_pcm_subformat_t) 0)
+#define        SNDRV_PCM_SUBFORMAT_LAST        SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP            0x00000001      /* hardware supports mmap */
+#define SNDRV_PCM_INFO_MMAP_VALID      0x00000002      /* period data are valid during transfer */
+#define SNDRV_PCM_INFO_DOUBLE          0x00000004      /* Double buffering needed for PCM start/stop */
+#define SNDRV_PCM_INFO_BATCH           0x00000010      /* double buffering */
+#define SNDRV_PCM_INFO_INTERLEAVED     0x00000100      /* channels are interleaved */
+#define SNDRV_PCM_INFO_NONINTERLEAVED  0x00000200      /* channels are not interleaved */
+#define SNDRV_PCM_INFO_COMPLEX         0x00000400      /* complex frame organization (mmap only) */
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER  0x00010000      /* hardware transfer block of samples */
+#define SNDRV_PCM_INFO_OVERRANGE       0x00020000      /* hardware supports ADC (capture) overrange detection */
+#define SNDRV_PCM_INFO_RESUME          0x00040000      /* hardware supports stream resume after suspend */
+#define SNDRV_PCM_INFO_PAUSE           0x00080000      /* pause ioctl is supported */
+#define SNDRV_PCM_INFO_HALF_DUPLEX     0x00100000      /* only half duplex */
+#define SNDRV_PCM_INFO_JOINT_DUPLEX    0x00200000      /* playback and capture stream are somewhat correlated */
+#define SNDRV_PCM_INFO_SYNC_START      0x00400000      /* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP        0x00800000      /* period wakeup can be disabled */
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK   0x01000000      /* has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
+
+typedef int __bitwise snd_pcm_state_t;
+#define        SNDRV_PCM_STATE_OPEN            ((__force snd_pcm_state_t) 0) /* stream is open */
+#define        SNDRV_PCM_STATE_SETUP           ((__force snd_pcm_state_t) 1) /* stream has a setup */
+#define        SNDRV_PCM_STATE_PREPARED        ((__force snd_pcm_state_t) 2) /* stream is ready to start */
+#define        SNDRV_PCM_STATE_RUNNING         ((__force snd_pcm_state_t) 3) /* stream is running */
+#define        SNDRV_PCM_STATE_XRUN            ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
+#define        SNDRV_PCM_STATE_DRAINING        ((__force snd_pcm_state_t) 5) /* stream is draining */
+#define        SNDRV_PCM_STATE_PAUSED          ((__force snd_pcm_state_t) 6) /* stream is paused */
+#define        SNDRV_PCM_STATE_SUSPENDED       ((__force snd_pcm_state_t) 7) /* hardware is suspended */
+#define        SNDRV_PCM_STATE_DISCONNECTED    ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
+#define        SNDRV_PCM_STATE_LAST            SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+       SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+       SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+       SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+       unsigned char id[16];
+       unsigned short id16[8];
+       unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+       unsigned int device;            /* RO/WR (control): device number */
+       unsigned int subdevice;         /* RO/WR (control): subdevice number */
+       int stream;                     /* RO/WR (control): stream direction */
+       int card;                       /* R: card number */
+       unsigned char id[64];           /* ID (user selectable) */
+       unsigned char name[80];         /* name of this device */
+       unsigned char subname[32];      /* subdevice name */
+       int dev_class;                  /* SNDRV_PCM_CLASS_* */
+       int dev_subclass;               /* SNDRV_PCM_SUBCLASS_* */
+       unsigned int subdevices_count;
+       unsigned int subdevices_avail;
+       union snd_pcm_sync_id sync;     /* hardware synchronization ID */
+       unsigned char reserved[64];     /* reserved for future... */
+};
+
+typedef int snd_pcm_hw_param_t;
+#define        SNDRV_PCM_HW_PARAM_ACCESS       0       /* Access type */
+#define        SNDRV_PCM_HW_PARAM_FORMAT       1       /* Format */
+#define        SNDRV_PCM_HW_PARAM_SUBFORMAT    2       /* Subformat */
+#define        SNDRV_PCM_HW_PARAM_FIRST_MASK   SNDRV_PCM_HW_PARAM_ACCESS
+#define        SNDRV_PCM_HW_PARAM_LAST_MASK    SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define        SNDRV_PCM_HW_PARAM_SAMPLE_BITS  8       /* Bits per sample */
+#define        SNDRV_PCM_HW_PARAM_FRAME_BITS   9       /* Bits per frame */
+#define        SNDRV_PCM_HW_PARAM_CHANNELS     10      /* Channels */
+#define        SNDRV_PCM_HW_PARAM_RATE         11      /* Approx rate */
+#define        SNDRV_PCM_HW_PARAM_PERIOD_TIME  12      /* Approx distance between
+                                                * interrupts in us
+                                                */
+#define        SNDRV_PCM_HW_PARAM_PERIOD_SIZE  13      /* Approx frames between
+                                                * interrupts
+                                                */
+#define        SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14      /* Approx bytes between
+                                                * interrupts
+                                                */
+#define        SNDRV_PCM_HW_PARAM_PERIODS      15      /* Approx interrupts per
+                                                * buffer
+                                                */
+#define        SNDRV_PCM_HW_PARAM_BUFFER_TIME  16      /* Approx duration of buffer
+                                                * in us
+                                                */
+#define        SNDRV_PCM_HW_PARAM_BUFFER_SIZE  17      /* Size of buffer in frames */
+#define        SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18      /* Size of buffer in bytes */
+#define        SNDRV_PCM_HW_PARAM_TICK_TIME    19      /* Approx tick duration in us */
+#define        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL       SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define        SNDRV_PCM_HW_PARAM_LAST_INTERVAL        SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
+#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER      (1<<1)  /* export buffer */
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP   (1<<2)  /* disable period wakeups */
+
+struct snd_interval {
+       unsigned int min, max;
+       unsigned int openmin:1,
+                    openmax:1,
+                    integer:1,
+                    empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+       __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+       unsigned int flags;
+       struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - 
+                              SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+       struct snd_mask mres[5];        /* reserved masks */
+       struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+                                       SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+       struct snd_interval ires[9];    /* reserved intervals */
+       unsigned int rmask;             /* W: requested masks */
+       unsigned int cmask;             /* R: changed masks */
+       unsigned int info;              /* R: Info flags for returned setup */
+       unsigned int msbits;            /* R: used most significant bits */
+       unsigned int rate_num;          /* R: rate numerator */
+       unsigned int rate_den;          /* R: rate denominator */
+       snd_pcm_uframes_t fifo_size;    /* R: chip FIFO size in frames */
+       unsigned char reserved[64];     /* reserved for future */
+};
+
+enum {
+       SNDRV_PCM_TSTAMP_NONE = 0,
+       SNDRV_PCM_TSTAMP_ENABLE,
+       SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+       int tstamp_mode;                        /* timestamp mode */
+       unsigned int period_step;
+       unsigned int sleep_min;                 /* min ticks to sleep */
+       snd_pcm_uframes_t avail_min;            /* min avail frames for wakeup */
+       snd_pcm_uframes_t xfer_align;           /* obsolete: xfer size need to be a multiple */
+       snd_pcm_uframes_t start_threshold;      /* min hw_avail frames for automatic start */
+       snd_pcm_uframes_t stop_threshold;       /* min avail frames for automatic stop */
+       snd_pcm_uframes_t silence_threshold;    /* min distance from noise for silence filling */
+       snd_pcm_uframes_t silence_size;         /* silence block size */
+       snd_pcm_uframes_t boundary;             /* pointers wrap point */
+       unsigned char reserved[64];             /* reserved for future */
+};
+
+struct snd_pcm_channel_info {
+       unsigned int channel;
+       __kernel_off_t offset;          /* mmap offset */
+       unsigned int first;             /* offset to first sample in bits */
+       unsigned int step;              /* samples distance in bits */
+};
+
+struct snd_pcm_status {
+       snd_pcm_state_t state;          /* stream state */
+       struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
+       struct timespec tstamp;         /* reference timestamp */
+       snd_pcm_uframes_t appl_ptr;     /* appl ptr */
+       snd_pcm_uframes_t hw_ptr;       /* hw ptr */
+       snd_pcm_sframes_t delay;        /* current delay in frames */
+       snd_pcm_uframes_t avail;        /* number of frames available */
+       snd_pcm_uframes_t avail_max;    /* max frames available on hw since last status */
+       snd_pcm_uframes_t overrange;    /* count of ADC (capture) overrange detections from last status */
+       snd_pcm_state_t suspended_state; /* suspended stream state */
+       __u32 reserved_alignment;       /* must be filled with zero */
+       struct timespec audio_tstamp;   /* from sample counter or wall clock */
+       unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */
+};
+
+struct snd_pcm_mmap_status {
+       snd_pcm_state_t state;          /* RO: state - SNDRV_PCM_STATE_XXXX */
+       int pad1;                       /* Needed for 64 bit alignment */
+       snd_pcm_uframes_t hw_ptr;       /* RO: hw ptr (0...boundary-1) */
+       struct timespec tstamp;         /* Timestamp */
+       snd_pcm_state_t suspended_state; /* RO: suspended stream state */
+       struct timespec audio_tstamp;   /* from sample counter or wall clock */
+};
+
+struct snd_pcm_mmap_control {
+       snd_pcm_uframes_t appl_ptr;     /* RW: appl ptr (0...boundary-1) */
+       snd_pcm_uframes_t avail_min;    /* RW: min available frames for wakeup */
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC      (1<<0)  /* execute hwsync */
+#define SNDRV_PCM_SYNC_PTR_APPL                (1<<1)  /* get appl_ptr from driver (r/w op) */
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN   (1<<2)  /* get avail_min from driver */
+
+struct snd_pcm_sync_ptr {
+       unsigned int flags;
+       union {
+               struct snd_pcm_mmap_status status;
+               unsigned char reserved[64];
+       } s;
+       union {
+               struct snd_pcm_mmap_control control;
+               unsigned char reserved[64];
+       } c;
+};
+
+struct snd_xferi {
+       snd_pcm_sframes_t result;
+       void __user *buf;
+       snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+       snd_pcm_sframes_t result;
+       void __user * __user *bufs;
+       snd_pcm_uframes_t frames;
+};
+
+enum {
+       SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
+       SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,        /* posix_clock_monotonic equivalent */
+       SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+/* channel positions */
+enum {
+       SNDRV_CHMAP_UNKNOWN = 0,
+       SNDRV_CHMAP_NA,         /* N/A, silent */
+       SNDRV_CHMAP_MONO,       /* mono stream */
+       /* this follows the alsa-lib mixer channel value + 3 */
+       SNDRV_CHMAP_FL,         /* front left */
+       SNDRV_CHMAP_FR,         /* front right */
+       SNDRV_CHMAP_RL,         /* rear left */
+       SNDRV_CHMAP_RR,         /* rear right */
+       SNDRV_CHMAP_FC,         /* front center */
+       SNDRV_CHMAP_LFE,        /* LFE */
+       SNDRV_CHMAP_SL,         /* side left */
+       SNDRV_CHMAP_SR,         /* side right */
+       SNDRV_CHMAP_RC,         /* rear center */
+       /* new definitions */
+       SNDRV_CHMAP_FLC,        /* front left center */
+       SNDRV_CHMAP_FRC,        /* front right center */
+       SNDRV_CHMAP_RLC,        /* rear left center */
+       SNDRV_CHMAP_RRC,        /* rear right center */
+       SNDRV_CHMAP_FLW,        /* front left wide */
+       SNDRV_CHMAP_FRW,        /* front right wide */
+       SNDRV_CHMAP_FLH,        /* front left high */
+       SNDRV_CHMAP_FCH,        /* front center high */
+       SNDRV_CHMAP_FRH,        /* front right high */
+       SNDRV_CHMAP_TC,         /* top center */
+       SNDRV_CHMAP_TFL,        /* top front left */
+       SNDRV_CHMAP_TFR,        /* top front right */
+       SNDRV_CHMAP_TFC,        /* top front center */
+       SNDRV_CHMAP_TRL,        /* top rear left */
+       SNDRV_CHMAP_TRR,        /* top rear right */
+       SNDRV_CHMAP_TRC,        /* top rear center */
+       /* new definitions for UAC2 */
+       SNDRV_CHMAP_TFLC,       /* top front left center */
+       SNDRV_CHMAP_TFRC,       /* top front right center */
+       SNDRV_CHMAP_TSL,        /* top side left */
+       SNDRV_CHMAP_TSR,        /* top side right */
+       SNDRV_CHMAP_LLFE,       /* left LFE */
+       SNDRV_CHMAP_RLFE,       /* right LFE */
+       SNDRV_CHMAP_BC,         /* bottom center */
+       SNDRV_CHMAP_BLC,        /* bottom left center */
+       SNDRV_CHMAP_BRC,        /* bottom right center */
+       SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
+};
+
+#define SNDRV_CHMAP_POSITION_MASK      0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE      (0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC                (0x02 << 16)
+
+#define SNDRV_PCM_IOCTL_PVERSION       _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO           _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP         _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP                _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE      _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS      _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE                _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS      _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS         _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY          _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC         _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR       _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO   _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE                _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET          _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START          _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP           _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN          _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE          _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND         _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME         _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN           _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD                _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES  _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES   _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES  _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES   _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK           _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK         _IO('A', 0x61)
+
+/*****************************************************************************
+ *                                                                           *
+ *                            MIDI v1.0 interface                            *
+ *                                                                           *
+ *****************************************************************************/
+
+/*
+ *  Raw MIDI section - /dev/snd/midi??
+ */
+
+#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+       SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+       SNDRV_RAWMIDI_STREAM_INPUT,
+       SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT              0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT               0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX              0x00000004
+
+struct snd_rawmidi_info {
+       unsigned int device;            /* RO/WR (control): device number */
+       unsigned int subdevice;         /* RO/WR (control): subdevice number */
+       int stream;                     /* WR: stream */
+       int card;                       /* R: card number */
+       unsigned int flags;             /* SNDRV_RAWMIDI_INFO_XXXX */
+       unsigned char id[64];           /* ID (user selectable) */
+       unsigned char name[80];         /* name of device */
+       unsigned char subname[32];      /* name of active or selected subdevice */
+       unsigned int subdevices_count;
+       unsigned int subdevices_avail;
+       unsigned char reserved[64];     /* reserved for future use */
+};
+
+struct snd_rawmidi_params {
+       int stream;
+       size_t buffer_size;             /* queue size in bytes */
+       size_t avail_min;               /* minimum avail bytes for wakeup */
+       unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+struct snd_rawmidi_status {
+       int stream;
+       struct timespec tstamp;         /* Timestamp */
+       size_t avail;                   /* available bytes */
+       size_t xruns;                   /* count of overruns since last status (in bytes) */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION   _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO       _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS     _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS     _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP       _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN      _IOW('W', 0x31, int)
+
+/*
+ *  Timer section - /dev/snd/timer
+ */
+
+#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+       SNDRV_TIMER_CLASS_NONE = -1,
+       SNDRV_TIMER_CLASS_SLAVE = 0,
+       SNDRV_TIMER_CLASS_GLOBAL,
+       SNDRV_TIMER_CLASS_CARD,
+       SNDRV_TIMER_CLASS_PCM,
+       SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+/* slave timer classes */
+enum {
+       SNDRV_TIMER_SCLASS_NONE = 0,
+       SNDRV_TIMER_SCLASS_APPLICATION,
+       SNDRV_TIMER_SCLASS_SEQUENCER,           /* alias */
+       SNDRV_TIMER_SCLASS_OSS_SEQUENCER,       /* alias */
+       SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+/* global timers (device member) */
+#define SNDRV_TIMER_GLOBAL_SYSTEM      0
+#define SNDRV_TIMER_GLOBAL_RTC         1
+#define SNDRV_TIMER_GLOBAL_HPET                2
+#define SNDRV_TIMER_GLOBAL_HRTIMER     3
+
+/* info flags */
+#define SNDRV_TIMER_FLG_SLAVE          (1<<0)  /* cannot be controlled */
+
+struct snd_timer_id {
+       int dev_class;
+       int dev_sclass;
+       int card;
+       int device;
+       int subdevice;
+};
+
+struct snd_timer_ginfo {
+       struct snd_timer_id tid;        /* requested timer ID */
+       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
+       int card;                       /* card number */
+       unsigned char id[64];           /* timer identification */
+       unsigned char name[80];         /* timer name */
+       unsigned long reserved0;        /* reserved for future use */
+       unsigned long resolution;       /* average period resolution in ns */
+       unsigned long resolution_min;   /* minimal period resolution in ns */
+       unsigned long resolution_max;   /* maximal period resolution in ns */
+       unsigned int clients;           /* active timer clients */
+       unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+       struct snd_timer_id tid;        /* requested timer ID */
+       unsigned long period_num;       /* requested precise period duration (in seconds) - numerator */
+       unsigned long period_den;       /* requested precise period duration (in seconds) - denominator */
+       unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+       struct snd_timer_id tid;        /* requested timer ID */
+       unsigned long resolution;       /* current period resolution in ns */
+       unsigned long resolution_num;   /* precise current period resolution (in seconds) - numerator */
+       unsigned long resolution_den;   /* precise current period resolution (in seconds) - denominator */
+       unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+       struct snd_timer_id id; /* bind to timer ID */
+       unsigned char reserved[32];     /* reserved */
+};
+
+struct snd_timer_info {
+       unsigned int flags;             /* timer flags - SNDRV_TIMER_FLG_* */
+       int card;                       /* card number */
+       unsigned char id[64];           /* timer identificator */
+       unsigned char name[80];         /* timer name */
+       unsigned long reserved0;        /* reserved for future use */
+       unsigned long resolution;       /* average period resolution in ns */
+       unsigned char reserved[64];     /* reserved */
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO         (1<<0)  /* auto start, otherwise one-shot */
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE    (1<<1)  /* exclusive use, precise start/stop/pause/continue */
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT  (1<<2)  /* write early event to the poll queue */
+
+struct snd_timer_params {
+       unsigned int flags;             /* flags - SNDRV_MIXER_PSFLG_* */
+       unsigned int ticks;             /* requested resolution in ticks */
+       unsigned int queue_size;        /* total size of queue (32-1024) */
+       unsigned int reserved0;         /* reserved, was: failure locations */
+       unsigned int filter;            /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
+       unsigned char reserved[60];     /* reserved */
+};
+
+struct snd_timer_status {
+       struct timespec tstamp;         /* Timestamp - last update */
+       unsigned int resolution;        /* current period resolution in ns */
+       unsigned int lost;              /* counter of master tick lost */
+       unsigned int overrun;           /* count of read queue overruns */
+       unsigned int queue;             /* used queue size */
+       unsigned char reserved[64];     /* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION     _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE  _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD                _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO                _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS      _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS      _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT       _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO         _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS       _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS       _IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START                _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP         _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE     _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE                _IO('T', 0xa3)
+
+struct snd_timer_read {
+       unsigned int resolution;
+       unsigned int ticks;
+};
+
+enum {
+       SNDRV_TIMER_EVENT_RESOLUTION = 0,       /* val = resolution in ns */
+       SNDRV_TIMER_EVENT_TICK,                 /* val = ticks */
+       SNDRV_TIMER_EVENT_START,                /* val = resolution in ns */
+       SNDRV_TIMER_EVENT_STOP,                 /* val = 0 */
+       SNDRV_TIMER_EVENT_CONTINUE,             /* val = resolution in ns */
+       SNDRV_TIMER_EVENT_PAUSE,                /* val = 0 */
+       SNDRV_TIMER_EVENT_EARLY,                /* val = 0, early event */
+       SNDRV_TIMER_EVENT_SUSPEND,              /* val = 0 */
+       SNDRV_TIMER_EVENT_RESUME,               /* val = resolution in ns */
+       /* master timer events for slave timer instances */
+       SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+       SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+       SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+       SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+       SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+       SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+       int event;
+       struct timespec tstamp;
+       unsigned int val;
+};
+
+/****************************************************************************
+ *                                                                          *
+ *        Section for driver control interface - /dev/snd/control?          *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 7)
+
+struct snd_ctl_card_info {
+       int card;                       /* card number */
+       int pad;                        /* reserved for future (was type) */
+       unsigned char id[16];           /* ID of card (user selectable) */
+       unsigned char driver[16];       /* Driver name */
+       unsigned char name[32];         /* Short name of soundcard */
+       unsigned char longname[80];     /* name + info text about soundcard */
+       unsigned char reserved_[16];    /* reserved for future (was ID of mixer) */
+       unsigned char mixername[80];    /* visual mixer identification */
+       unsigned char components[128];  /* card components / fine identification, delimited with one space (AC97 etc..) */
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define        SNDRV_CTL_ELEM_TYPE_NONE        ((__force snd_ctl_elem_type_t) 0) /* invalid */
+#define        SNDRV_CTL_ELEM_TYPE_BOOLEAN     ((__force snd_ctl_elem_type_t) 1) /* boolean type */
+#define        SNDRV_CTL_ELEM_TYPE_INTEGER     ((__force snd_ctl_elem_type_t) 2) /* integer type */
+#define        SNDRV_CTL_ELEM_TYPE_ENUMERATED  ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
+#define        SNDRV_CTL_ELEM_TYPE_BYTES       ((__force snd_ctl_elem_type_t) 4) /* byte array */
+#define        SNDRV_CTL_ELEM_TYPE_IEC958      ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
+#define        SNDRV_CTL_ELEM_TYPE_INTEGER64   ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
+#define        SNDRV_CTL_ELEM_TYPE_LAST        SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define        SNDRV_CTL_ELEM_IFACE_CARD       ((__force snd_ctl_elem_iface_t) 0) /* global control */
+#define        SNDRV_CTL_ELEM_IFACE_HWDEP      ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
+#define        SNDRV_CTL_ELEM_IFACE_MIXER      ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
+#define        SNDRV_CTL_ELEM_IFACE_PCM        ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
+#define        SNDRV_CTL_ELEM_IFACE_RAWMIDI    ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
+#define        SNDRV_CTL_ELEM_IFACE_TIMER      ((__force snd_ctl_elem_iface_t) 5) /* timer device */
+#define        SNDRV_CTL_ELEM_IFACE_SEQUENCER  ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
+#define        SNDRV_CTL_ELEM_IFACE_LAST       SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ             (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE            (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE                (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE         (1<<2)  /* control value may be changed without a notification */
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP                (1<<3)  /* when was control changed */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ         (1<<4)  /* TLV read is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE                (1<<5)  /* TLV write is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE    (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND      (1<<6)  /* TLV command is possible */
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE         (1<<8)  /* control does actually nothing, but may be updated */
+#define SNDRV_CTL_ELEM_ACCESS_LOCK             (1<<9)  /* write lock */
+#define SNDRV_CTL_ELEM_ACCESS_OWNER            (1<<10) /* write lock owner */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK     (1<<28) /* kernel use a TLV callback */ 
+#define SNDRV_CTL_ELEM_ACCESS_USER             (1<<29) /* user space element */
+/* bits 30 and 31 are obsoleted (for indirect access) */
+
+/* for further details see the ACPI and PCI power management specification */
+#define SNDRV_CTL_POWER_D0             0x0000  /* full On */
+#define SNDRV_CTL_POWER_D1             0x0100  /* partial On */
+#define SNDRV_CTL_POWER_D2             0x0200  /* partial On */
+#define SNDRV_CTL_POWER_D3             0x0300  /* Off */
+#define SNDRV_CTL_POWER_D3hot          (SNDRV_CTL_POWER_D3|0x0000)     /* Off, with power */
+#define SNDRV_CTL_POWER_D3cold         (SNDRV_CTL_POWER_D3|0x0001)     /* Off, without power */
+
+struct snd_ctl_elem_id {
+       unsigned int numid;             /* numeric identifier, zero = invalid */
+       snd_ctl_elem_iface_t iface;     /* interface identifier */
+       unsigned int device;            /* device/client number */
+       unsigned int subdevice;         /* subdevice (substream) number */
+       unsigned char name[44];         /* ASCII name of item */
+       unsigned int index;             /* index of item */
+};
+
+struct snd_ctl_elem_list {
+       unsigned int offset;            /* W: first element ID to get */
+       unsigned int space;             /* W: count of element IDs to get */
+       unsigned int used;              /* R: count of element IDs set */
+       unsigned int count;             /* R: count of all elements */
+       struct snd_ctl_elem_id __user *pids; /* R: IDs */
+       unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+       struct snd_ctl_elem_id id;      /* W: element ID */
+       snd_ctl_elem_type_t type;       /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
+       unsigned int access;            /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
+       unsigned int count;             /* count of values */
+       __kernel_pid_t owner;           /* owner's PID of this control */
+       union {
+               struct {
+                       long min;               /* R: minimum value */
+                       long max;               /* R: maximum value */
+                       long step;              /* R: step (0 variable) */
+               } integer;
+               struct {
+                       long long min;          /* R: minimum value */
+                       long long max;          /* R: maximum value */
+                       long long step;         /* R: step (0 variable) */
+               } integer64;
+               struct {
+                       unsigned int items;     /* R: number of items */
+                       unsigned int item;      /* W: item number */
+                       char name[64];          /* R: value name */
+                       __u64 names_ptr;        /* W: names list (ELEM_ADD only) */
+                       unsigned int names_length;
+               } enumerated;
+               unsigned char reserved[128];
+       } value;
+       union {
+               unsigned short d[4];            /* dimensions */
+               unsigned short *d_ptr;          /* indirect - obsoleted */
+       } dimen;
+       unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+       struct snd_ctl_elem_id id;      /* W: element ID */
+       unsigned int indirect: 1;       /* W: indirect access - obsoleted */
+       union {
+               union {
+                       long value[128];
+                       long *value_ptr;        /* obsoleted */
+               } integer;
+               union {
+                       long long value[64];
+                       long long *value_ptr;   /* obsoleted */
+               } integer64;
+               union {
+                       unsigned int item[128];
+                       unsigned int *item_ptr; /* obsoleted */
+               } enumerated;
+               union {
+                       unsigned char data[512];
+                       unsigned char *data_ptr;        /* obsoleted */
+               } bytes;
+               struct snd_aes_iec958 iec958;
+       } value;                /* RO */
+       struct timespec tstamp;
+       unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+       unsigned int numid;     /* control element numeric identification */
+       unsigned int length;    /* in bytes aligned to 4 */
+       unsigned int tlv[0];    /* first TLV */
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION       _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO      _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST      _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO      _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ      _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE     _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK      _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK    _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD       _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE   _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE    _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ       _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE      _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND    _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO     _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE        _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO       _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO   _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER          _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE    _IOR('U', 0xd1, int)
+
+/*
+ *  Read interface.
+ */
+
+enum sndrv_ctl_event_type {
+       SNDRV_CTL_EVENT_ELEM = 0,
+       SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE     (1<<0)  /* element value was changed */
+#define SNDRV_CTL_EVENT_MASK_INFO      (1<<1)  /* element info was changed */
+#define SNDRV_CTL_EVENT_MASK_ADD       (1<<2)  /* element was added */
+#define SNDRV_CTL_EVENT_MASK_TLV       (1<<3)  /* element TLV tree was changed */
+#define SNDRV_CTL_EVENT_MASK_REMOVE    (~0U)   /* element was removed */
+
+struct snd_ctl_event {
+       int type;       /* event type - SNDRV_CTL_EVENT_* */
+       union {
+               struct {
+                       unsigned int mask;
+                       struct snd_ctl_elem_id id;
+               } elem;
+               unsigned char data8[60];
+       } data;
+};
+
+/*
+ *  Control names
+ */
+
+#define SNDRV_CTL_NAME_NONE                            ""
+#define SNDRV_CTL_NAME_PLAYBACK                                "Playback "
+#define SNDRV_CTL_NAME_CAPTURE                         "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE                     ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH                   "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME                   "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT                  "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK                     "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK                 "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK                 "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM               "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what)     "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/include/uapi/sound/asound_fm.h b/include/uapi/sound/asound_fm.h
new file mode 100644 (file)
index 0000000..c2a4b96
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __SOUND_ASOUND_FM_H
+#define __SOUND_ASOUND_FM_H
+
+/*
+ *  Advanced Linux Sound Architecture - ALSA
+ *
+ *  Interface file between ALSA driver & user space
+ *  Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
+ *                           4Front Technologies
+ *
+ *  Direct FM control
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define SNDRV_DM_FM_MODE_OPL2  0x00
+#define SNDRV_DM_FM_MODE_OPL3  0x01
+
+struct snd_dm_fm_info {
+       unsigned char fm_mode;          /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
+       unsigned char rhythm;           /* percussion mode flag */
+};
+
+/*
+ *  Data structure composing an FM "note" or sound event.
+ */
+
+struct snd_dm_fm_voice {
+       unsigned char op;               /* operator cell (0 or 1) */
+       unsigned char voice;            /* FM voice (0 to 17) */
+
+       unsigned char am;               /* amplitude modulation */
+       unsigned char vibrato;          /* vibrato effect */
+       unsigned char do_sustain;       /* sustain phase */
+       unsigned char kbd_scale;        /* keyboard scaling */
+       unsigned char harmonic;         /* 4 bits: harmonic and multiplier */
+       unsigned char scale_level;      /* 2 bits: decrease output freq rises */
+       unsigned char volume;           /* 6 bits: volume */
+
+       unsigned char attack;           /* 4 bits: attack rate */
+       unsigned char decay;            /* 4 bits: decay rate */
+       unsigned char sustain;          /* 4 bits: sustain level */
+       unsigned char release;          /* 4 bits: release rate */
+
+       unsigned char feedback;         /* 3 bits: feedback for op0 */
+       unsigned char connection;       /* 0 for serial, 1 for parallel */
+       unsigned char left;             /* stereo left */
+       unsigned char right;            /* stereo right */
+       unsigned char waveform;         /* 3 bits: waveform shape */
+};
+
+/*
+ *  This describes an FM note by its voice, octave, frequency number (10bit)
+ *  and key on/off.
+ */
+
+struct snd_dm_fm_note {
+       unsigned char voice;    /* 0-17 voice channel */
+       unsigned char octave;   /* 3 bits: what octave to play */
+       unsigned int fnum;      /* 10 bits: frequency number */
+       unsigned char key_on;   /* set for active, clear for silent */
+};
+
+/*
+ *  FM parameters that apply globally to all voices, and thus are not "notes"
+ */
+
+struct snd_dm_fm_params {
+       unsigned char am_depth;         /* amplitude modulation depth (1=hi) */
+       unsigned char vib_depth;        /* vibrato depth (1=hi) */
+       unsigned char kbd_split;        /* keyboard split */
+       unsigned char rhythm;           /* percussion mode select */
+
+       /* This block is the percussion instrument data */
+       unsigned char bass;
+       unsigned char snare;
+       unsigned char tomtom;
+       unsigned char cymbal;
+       unsigned char hihat;
+};
+
+/*
+ *  FM mode ioctl settings
+ */
+
+#define SNDRV_DM_FM_IOCTL_INFO         _IOR('H', 0x20, struct snd_dm_fm_info)
+#define SNDRV_DM_FM_IOCTL_RESET                _IO ('H', 0x21)
+#define SNDRV_DM_FM_IOCTL_PLAY_NOTE    _IOW('H', 0x22, struct snd_dm_fm_note)
+#define SNDRV_DM_FM_IOCTL_SET_VOICE    _IOW('H', 0x23, struct snd_dm_fm_voice)
+#define SNDRV_DM_FM_IOCTL_SET_PARAMS   _IOW('H', 0x24, struct snd_dm_fm_params)
+#define SNDRV_DM_FM_IOCTL_SET_MODE     _IOW('H', 0x25, int)
+/* for OPL3 only */
+#define SNDRV_DM_FM_IOCTL_SET_CONNECTION       _IOW('H', 0x26, int)
+/* SBI patch management */
+#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES        _IO ('H', 0x40)
+
+#define SNDRV_DM_FM_OSS_IOCTL_RESET            0x20
+#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE                0x21
+#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE                0x22
+#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS       0x23
+#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE         0x24
+#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL          0x25
+
+/*
+ * Patch Record - fixed size for write
+ */
+
+#define FM_KEY_SBI     "SBI\032"
+#define FM_KEY_2OP     "2OP\032"
+#define FM_KEY_4OP     "4OP\032"
+
+struct sbi_patch {
+       unsigned char prog;
+       unsigned char bank;
+       char key[4];
+       char name[25];
+       char extension[7];
+       unsigned char data[32];
+};
+
+#endif /* __SOUND_ASOUND_FM_H */
diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
new file mode 100644 (file)
index 0000000..05341a4
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:   Vinod Koul <vinod.koul@linux.intel.com>
+ *             Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+#include <sound/compress_params.h>
+
+
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+/**
+ * struct snd_compressed_buffer: compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+       __u32 fragment_size;
+       __u32 fragments;
+};
+
+/**
+ * struct snd_compr_params: compressed stream params
+ * @buffer: buffer description
+ * @codec: codec parameters
+ * @no_wake_mode: dont wake on fragment elapsed
+ */
+struct snd_compr_params {
+       struct snd_compressed_buffer buffer;
+       struct snd_codec codec;
+       __u8 no_wake_mode;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @byte_offset: Byte offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
+ * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
+ *     large steps and should only be used to monitor encoding/decoding
+ *     progress. It shall not be used for timing estimates.
+ * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
+ * output/input. This field should be used for A/V sync or time estimates.
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+       __u32 byte_offset;
+       __u32 copied_total;
+       snd_pcm_uframes_t pcm_frames;
+       snd_pcm_uframes_t pcm_io_frames;
+       __u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+       __u64 avail;
+       struct snd_compr_tstamp tstamp;
+};
+
+enum snd_compr_direction {
+       SND_COMPRESS_PLAYBACK = 0,
+       SND_COMPRESS_CAPTURE
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @direction: direction supported. Of type snd_compr_direction
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+       __u32 num_codecs;
+       __u32 direction;
+       __u32 min_fragment_size;
+       __u32 max_fragment_size;
+       __u32 min_fragments;
+       __u32 max_fragments;
+       __u32 codecs[MAX_NUM_CODECS];
+       __u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+       __u32 codec;
+       __u32 num_descriptors;
+       struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
+ */
+#define SNDRV_COMPRESS_IOCTL_VERSION   _IOR('C', 0x00, int)
+#define SNDRV_COMPRESS_GET_CAPS                _IOWR('C', 0x10, struct snd_compr_caps)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS  _IOWR('C', 0x11,\
+                                               struct snd_compr_codec_caps)
+#define SNDRV_COMPRESS_SET_PARAMS      _IOW('C', 0x12, struct snd_compr_params)
+#define SNDRV_COMPRESS_GET_PARAMS      _IOR('C', 0x13, struct snd_codec)
+#define SNDRV_COMPRESS_TSTAMP          _IOR('C', 0x20, struct snd_compr_tstamp)
+#define SNDRV_COMPRESS_AVAIL           _IOR('C', 0x21, struct snd_compr_avail)
+#define SNDRV_COMPRESS_PAUSE           _IO('C', 0x30)
+#define SNDRV_COMPRESS_RESUME          _IO('C', 0x31)
+#define SNDRV_COMPRESS_START           _IO('C', 0x32)
+#define SNDRV_COMPRESS_STOP            _IO('C', 0x33)
+#define SNDRV_COMPRESS_DRAIN           _IO('C', 0x34)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
new file mode 100644 (file)
index 0000000..602dc6c
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *  compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:   Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#ifndef __SND_COMPRESS_PARAMS_H
+#define __SND_COMPRESS_PARAMS_H
+
+#include <linux/types.h>
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+#define SND_AUDIOCODEC_MAX                   SND_AUDIOCODEC_G729
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED             ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM              ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1                     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3               ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2                     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC                     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC                     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3              ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD            ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP               ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST               ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO            ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC            ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2           ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND             ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+       __u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+       __s32 quality;
+       __u32 managed;
+       __u32 max_bit_rate;
+       __u32 min_bit_rate;
+       __u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+       __u32 quant_bits;
+       __u32 start_region;
+       __u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *     needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+       __u32 num;
+       __u32 gain;
+};
+
+struct snd_enc_generic {
+       __u32 bw;       /* encoder bandwidth */
+       __s32 reserved[15];
+};
+
+union snd_codec_options {
+       struct snd_enc_wma wma;
+       struct snd_enc_vorbis vorbis;
+       struct snd_enc_real real;
+       struct snd_enc_flac flac;
+       struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @min_buffer: Minimum buffer size handled by codec implementation
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+       __u32 max_ch;
+       __u32 sample_rates;
+       __u32 bit_rate[MAX_NUM_BITRATES];
+       __u32 num_bitrates;
+       __u32 rate_control;
+       __u32 profiles;
+       __u32 modes;
+       __u32 formats;
+       __u32 min_buffer;
+       __u32 reserved[15];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *             See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *             this field and the channelMode field, the channelMode field
+ *             overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *              May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *             decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *             See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *             Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+       __u32 id;
+       __u32 ch_in;
+       __u32 ch_out;
+       __u32 sample_rate;
+       __u32 bit_rate;
+       __u32 rate_control;
+       __u32 profile;
+       __u32 level;
+       __u32 ch_mode;
+       __u32 format;
+       __u32 align;
+       union snd_codec_options options;
+       __u32 reserved[3];
+};
+
+#endif
diff --git a/include/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h
new file mode 100644 (file)
index 0000000..d1bbaf7
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
+ *                  Creative Labs, Inc.
+ *  Definitions for EMU10K1 (SB Live!) chips
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_EMU10K1_H
+#define _UAPI__SOUND_EMU10K1_H
+
+#include <linux/types.h>
+
+
+
+/*
+ * ---- FX8010 ----
+ */
+
+#define EMU10K1_CARD_CREATIVE                  0x00000000
+#define EMU10K1_CARD_EMUAPS                    0x00000001
+
+#define EMU10K1_FX8010_PCM_COUNT               8
+
+/* instruction set */
+#define iMAC0   0x00   /* R = A + (X * Y >> 31)   ; saturation */
+#define iMAC1   0x01   /* R = A + (-X * Y >> 31)  ; saturation */
+#define iMAC2   0x02   /* R = A + (X * Y >> 31)   ; wraparound */
+#define iMAC3   0x03   /* R = A + (-X * Y >> 31)  ; wraparound */
+#define iMACINT0 0x04  /* R = A + X * Y           ; saturation */
+#define iMACINT1 0x05  /* R = A + X * Y           ; wraparound (31-bit) */
+#define iACC3   0x06   /* R = A + X + Y           ; saturation */
+#define iMACMV   0x07  /* R = A, acc += X * Y >> 31 */
+#define iANDXOR  0x08  /* R = (A & X) ^ Y */
+#define iTSTNEG  0x09  /* R = (A >= Y) ? X : ~X */
+#define iLIMITGE 0x0a  /* R = (A >= Y) ? X : Y */
+#define iLIMITLT 0x0b  /* R = (A < Y) ? X : Y */
+#define iLOG    0x0c   /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
+#define iEXP    0x0d   /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
+#define iINTERP  0x0e  /* R = A + (X * (Y - A) >> 31)  ; saturation */
+#define iSKIP    0x0f  /* R = A (cc_reg), X (count), Y (cc_test) */
+
+/* GPRs */
+#define FXBUS(x)       (0x00 + (x))    /* x = 0x00 - 0x0f */
+#define EXTIN(x)       (0x10 + (x))    /* x = 0x00 - 0x0f */
+#define EXTOUT(x)      (0x20 + (x))    /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x)      (0x30 + (x))    /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+                                       /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
+#define C_00000000     0x40
+#define C_00000001     0x41
+#define C_00000002     0x42
+#define C_00000003     0x43
+#define C_00000004     0x44
+#define C_00000008     0x45
+#define C_00000010     0x46
+#define C_00000020     0x47
+#define C_00000100     0x48
+#define C_00010000     0x49
+#define C_00080000     0x4a
+#define C_10000000     0x4b
+#define C_20000000     0x4c
+#define C_40000000     0x4d
+#define C_80000000     0x4e
+#define C_7fffffff     0x4f
+#define C_ffffffff     0x50
+#define C_fffffffe     0x51
+#define C_c0000000     0x52
+#define C_4f1bbcdc     0x53
+#define C_5a7ef9db     0x54
+#define C_00100000     0x55            /* ?? */
+#define GPR_ACCU       0x56            /* ACCUM, accumulator */
+#define GPR_COND       0x57            /* CCR, condition register */
+#define GPR_NOISE0     0x58            /* noise source */
+#define GPR_NOISE1     0x59            /* noise source */
+#define GPR_IRQ                0x5a            /* IRQ register */
+#define GPR_DBAC       0x5b            /* TRAM Delay Base Address Counter */
+#define GPR(x)         (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x)  (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x)  (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+
+#define A_ITRAM_DATA(x)        (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_DATA(x)        (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_ADDR(x)        (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+
+#define A_FXBUS(x)     (0x00 + (x))    /* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x)     (0x40 + (x))    /* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x)    (0x50 + (x))    /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x)    (0x60 + (x))    /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
+#define A_FXBUS2(x)    (0x80 + (x))    /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x) (0xa0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x) (0xb0 + (x))    /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
+#define A3_EMU32IN(x)  (0x160 + (x))   /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
+#define A3_EMU32OUT(x) (0x1E0 + (x))   /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
+#define A_GPR(x)       (A_FXGPREGBASE + (x))
+
+/* cc_reg constants */
+#define CC_REG_NORMALIZED C_00000001
+#define CC_REG_BORROW  C_00000002
+#define CC_REG_MINUS   C_00000004
+#define CC_REG_ZERO    C_00000008
+#define CC_REG_SATURATE        C_00000010
+#define CC_REG_NONZERO C_00000100
+
+/* FX buses */
+#define FXBUS_PCM_LEFT         0x00
+#define FXBUS_PCM_RIGHT                0x01
+#define FXBUS_PCM_LEFT_REAR    0x02
+#define FXBUS_PCM_RIGHT_REAR   0x03
+#define FXBUS_MIDI_LEFT                0x04
+#define FXBUS_MIDI_RIGHT       0x05
+#define FXBUS_PCM_CENTER       0x06
+#define FXBUS_PCM_LFE          0x07
+#define FXBUS_PCM_LEFT_FRONT   0x08
+#define FXBUS_PCM_RIGHT_FRONT  0x09
+#define FXBUS_MIDI_REVERB      0x0c
+#define FXBUS_MIDI_CHORUS      0x0d
+#define FXBUS_PCM_LEFT_SIDE    0x0e
+#define FXBUS_PCM_RIGHT_SIDE   0x0f
+#define FXBUS_PT_LEFT          0x14
+#define FXBUS_PT_RIGHT         0x15
+
+/* Inputs */
+#define EXTIN_AC97_L      0x00 /* AC'97 capture channel - left */
+#define EXTIN_AC97_R      0x01 /* AC'97 capture channel - right */
+#define EXTIN_SPDIF_CD_L   0x02        /* internal S/PDIF CD - onboard - left */
+#define EXTIN_SPDIF_CD_R   0x03        /* internal S/PDIF CD - onboard - right */
+#define EXTIN_ZOOM_L      0x04 /* Zoom Video I2S - left */
+#define EXTIN_ZOOM_R      0x05 /* Zoom Video I2S - right */
+#define EXTIN_TOSLINK_L           0x06 /* LiveDrive - TOSLink Optical - left */
+#define EXTIN_TOSLINK_R    0x07        /* LiveDrive - TOSLink Optical - right */
+#define EXTIN_LINE1_L     0x08 /* LiveDrive - Line/Mic 1 - left */
+#define EXTIN_LINE1_R     0x09 /* LiveDrive - Line/Mic 1 - right */
+#define EXTIN_COAX_SPDIF_L 0x0a        /* LiveDrive - Coaxial S/PDIF - left */
+#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
+#define EXTIN_LINE2_L     0x0c /* LiveDrive - Line/Mic 2 - left */
+#define EXTIN_LINE2_R     0x0d /* LiveDrive - Line/Mic 2 - right */
+
+/* Outputs */
+#define EXTOUT_AC97_L     0x00 /* AC'97 playback channel - left */
+#define EXTOUT_AC97_R     0x01 /* AC'97 playback channel - right */
+#define EXTOUT_TOSLINK_L   0x02        /* LiveDrive - TOSLink Optical - left */
+#define EXTOUT_TOSLINK_R   0x03        /* LiveDrive - TOSLink Optical - right */
+#define EXTOUT_AC97_CENTER 0x04        /* SB Live 5.1 - center */
+#define EXTOUT_AC97_LFE           0x05 /* SB Live 5.1 - LFE */
+#define EXTOUT_HEADPHONE_L 0x06        /* LiveDrive - Headphone - left */
+#define EXTOUT_HEADPHONE_R 0x07        /* LiveDrive - Headphone - right */
+#define EXTOUT_REAR_L     0x08 /* Rear channel - left */
+#define EXTOUT_REAR_R     0x09 /* Rear channel - right */
+#define EXTOUT_ADC_CAP_L   0x0a        /* ADC Capture buffer - left */
+#define EXTOUT_ADC_CAP_R   0x0b        /* ADC Capture buffer - right */
+#define EXTOUT_MIC_CAP    0x0c /* MIC Capture buffer */
+#define EXTOUT_AC97_REAR_L 0x0d        /* SB Live 5.1 (c) 2003 - Rear Left */
+#define EXTOUT_AC97_REAR_R 0x0e        /* SB Live 5.1 (c) 2003 - Rear Right */
+#define EXTOUT_ACENTER    0x11 /* Analog Center */
+#define EXTOUT_ALFE       0x12 /* Analog LFE */
+
+/* Audigy Inputs */
+#define A_EXTIN_AC97_L         0x00    /* AC'97 capture channel - left */
+#define A_EXTIN_AC97_R         0x01    /* AC'97 capture channel - right */
+#define A_EXTIN_SPDIF_CD_L     0x02    /* digital CD left */
+#define A_EXTIN_SPDIF_CD_R     0x03    /* digital CD left */
+#define A_EXTIN_OPT_SPDIF_L     0x04    /* audigy drive Optical SPDIF - left */
+#define A_EXTIN_OPT_SPDIF_R     0x05    /*                              right */ 
+#define A_EXTIN_LINE2_L                0x08    /* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R                0x09    /*                           right */
+#define A_EXTIN_ADC_L          0x0a    /* Philips ADC - left */
+#define A_EXTIN_ADC_R          0x0b    /*               right */
+#define A_EXTIN_AUX2_L         0x0c    /* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R         0x0d    /*                   - right */
+
+/* Audigiy Outputs */
+#define A_EXTOUT_FRONT_L       0x00    /* digital front left */
+#define A_EXTOUT_FRONT_R       0x01    /*               right */
+#define A_EXTOUT_CENTER                0x02    /* digital front center */
+#define A_EXTOUT_LFE           0x03    /* digital front lfe */
+#define A_EXTOUT_HEADPHONE_L   0x04    /* headphone audigy drive left */
+#define A_EXTOUT_HEADPHONE_R   0x05    /*                        right */
+#define A_EXTOUT_REAR_L                0x06    /* digital rear left */
+#define A_EXTOUT_REAR_R                0x07    /*              right */
+#define A_EXTOUT_AFRONT_L      0x08    /* analog front left */
+#define A_EXTOUT_AFRONT_R      0x09    /*              right */
+#define A_EXTOUT_ACENTER       0x0a    /* analog center */
+#define A_EXTOUT_ALFE          0x0b    /* analog LFE */
+#define A_EXTOUT_ASIDE_L       0x0c    /* analog side left  - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R       0x0d    /*             right - Audigy 2 ZS */
+#define A_EXTOUT_AREAR_L       0x0e    /* analog rear left */
+#define A_EXTOUT_AREAR_R       0x0f    /*             right */
+#define A_EXTOUT_AC97_L                0x10    /* AC97 left (front) */
+#define A_EXTOUT_AC97_R                0x11    /*      right */
+#define A_EXTOUT_ADC_CAP_L     0x16    /* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R     0x17    /*                    right */
+#define A_EXTOUT_MIC_CAP       0x18    /* Mic capture buffer */
+
+/* Audigy constants */
+#define A_C_00000000   0xc0
+#define A_C_00000001   0xc1
+#define A_C_00000002   0xc2
+#define A_C_00000003   0xc3
+#define A_C_00000004   0xc4
+#define A_C_00000008   0xc5
+#define A_C_00000010   0xc6
+#define A_C_00000020   0xc7
+#define A_C_00000100   0xc8
+#define A_C_00010000   0xc9
+#define A_C_00000800   0xca
+#define A_C_10000000   0xcb
+#define A_C_20000000   0xcc
+#define A_C_40000000   0xcd
+#define A_C_80000000   0xce
+#define A_C_7fffffff   0xcf
+#define A_C_ffffffff   0xd0
+#define A_C_fffffffe   0xd1
+#define A_C_c0000000   0xd2
+#define A_C_4f1bbcdc   0xd3
+#define A_C_5a7ef9db   0xd4
+#define A_C_00100000   0xd5
+#define A_GPR_ACCU     0xd6            /* ACCUM, accumulator */
+#define A_GPR_COND     0xd7            /* CCR, condition register */
+#define A_GPR_NOISE0   0xd8            /* noise source */
+#define A_GPR_NOISE1   0xd9            /* noise source */
+#define A_GPR_IRQ      0xda            /* IRQ register */
+#define A_GPR_DBAC     0xdb            /* TRAM Delay Base Address Counter - internal */
+#define A_GPR_DBACE    0xde            /* TRAM Delay Base Address Counter - external */
+
+/* definitions for debug register */
+#define EMU10K1_DBG_ZC                 0x80000000      /* zero tram counter */
+#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000      /* saturation control */
+#define EMU10K1_DBG_SATURATION_ADDR    0x01ff0000      /* saturation address */
+#define EMU10K1_DBG_SINGLE_STEP                0x00008000      /* single step mode */
+#define EMU10K1_DBG_STEP               0x00004000      /* start single step */
+#define EMU10K1_DBG_CONDITION_CODE     0x00003e00      /* condition code */
+#define EMU10K1_DBG_SINGLE_STEP_ADDR   0x000001ff      /* single step address */
+
+/* tank memory address line */
+#ifndef __KERNEL__
+#define TANKMEMADDRREG_ADDR_MASK 0x000fffff    /* 20 bit tank address field                    */
+#define TANKMEMADDRREG_CLEAR    0x00800000     /* Clear tank memory                            */
+#define TANKMEMADDRREG_ALIGN    0x00400000     /* Align read or write relative to tank access  */
+#define TANKMEMADDRREG_WRITE    0x00200000     /* Write to tank memory                         */
+#define TANKMEMADDRREG_READ     0x00100000     /* Read from tank memory                        */
+#endif
+
+struct snd_emu10k1_fx8010_info {
+       unsigned int internal_tram_size;        /* in samples */
+       unsigned int external_tram_size;        /* in samples */
+       char fxbus_names[16][32];               /* names of FXBUSes */
+       char extin_names[16][32];               /* names of external inputs */
+       char extout_names[32][32];              /* names of external outputs */
+       unsigned int gpr_controls;              /* count of GPR controls */
+};
+
+#define EMU10K1_GPR_TRANSLATION_NONE           0
+#define EMU10K1_GPR_TRANSLATION_TABLE100       1
+#define EMU10K1_GPR_TRANSLATION_BASS           2
+#define EMU10K1_GPR_TRANSLATION_TREBLE         3
+#define EMU10K1_GPR_TRANSLATION_ONOFF          4
+
+struct snd_emu10k1_fx8010_control_gpr {
+       struct snd_ctl_elem_id id;              /* full control ID definition */
+       unsigned int vcount;            /* visible count */
+       unsigned int count;             /* count of GPR (1..16) */
+       unsigned short gpr[32];         /* GPR number(s) */
+       unsigned int value[32];         /* initial values */
+       unsigned int min;               /* minimum range */
+       unsigned int max;               /* maximum range */
+       unsigned int translation;       /* translation type (EMU10K1_GPR_TRANSLATION*) */
+       const unsigned int *tlv;
+};
+
+/* old ABI without TLV support */
+struct snd_emu10k1_fx8010_control_old_gpr {
+       struct snd_ctl_elem_id id;
+       unsigned int vcount;
+       unsigned int count;
+       unsigned short gpr[32];
+       unsigned int value[32];
+       unsigned int min;
+       unsigned int max;
+       unsigned int translation;
+};
+
+struct snd_emu10k1_fx8010_code {
+       char name[128];
+
+       DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
+       __u32 __user *gpr_map;          /* initializers */
+
+       unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
+       struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
+
+       unsigned int gpr_del_control_count; /* count of GPR controls to remove */
+       struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
+
+       unsigned int gpr_list_control_count; /* count of GPR controls to list */
+       unsigned int gpr_list_control_total; /* total count of GPR controls */
+       struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
+
+       DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
+       __u32 __user *tram_data_map;      /* data initializers */
+       __u32 __user *tram_addr_map;      /* map initializers */
+
+       DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
+       __u32 __user *code;               /* one instruction - 64 bits */
+};
+
+struct snd_emu10k1_fx8010_tram {
+       unsigned int address;           /* 31.bit == 1 -> external TRAM */
+       unsigned int size;              /* size in samples (4 bytes) */
+       unsigned int *samples;          /* pointer to samples (20-bit) */
+                                       /* NULL->clear memory */
+};
+
+struct snd_emu10k1_fx8010_pcm_rec {
+       unsigned int substream;         /* substream number */
+       unsigned int res1;              /* reserved */
+       unsigned int channels;          /* 16-bit channels count, zero = remove this substream */
+       unsigned int tram_start;        /* ring buffer position in TRAM (in samples) */
+       unsigned int buffer_size;       /* count of buffered samples */
+       unsigned short gpr_size;                /* GPR containing size of ringbuffer in samples (host) */
+       unsigned short gpr_ptr;         /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+       unsigned short gpr_count;       /* GPR containing count of samples between two interrupts (host) */
+       unsigned short gpr_tmpcount;    /* GPR containing current count of samples to interrupt (host = set, FX8010) */
+       unsigned short gpr_trigger;     /* GPR containing trigger (activate) information (host) */
+       unsigned short gpr_running;     /* GPR containing info if PCM is running (FX8010) */
+       unsigned char pad;              /* reserved */
+       unsigned char etram[32];        /* external TRAM address & data (one per channel) */
+       unsigned int res2;              /* reserved */
+};
+
+#define SNDRV_EMU10K1_VERSION          SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+#define SNDRV_EMU10K1_IOCTL_INFO       _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
+#define SNDRV_EMU10K1_IOCTL_CODE_POKE  _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK  _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
+#define SNDRV_EMU10K1_IOCTL_TRAM_POKE  _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK  _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_PCM_POKE   _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PCM_PEEK   _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PVERSION   _IOR ('H', 0x40, int)
+#define SNDRV_EMU10K1_IOCTL_STOP       _IO  ('H', 0x80)
+#define SNDRV_EMU10K1_IOCTL_CONTINUE   _IO  ('H', 0x81)
+#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
+#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP        _IOW ('H', 0x83, int)
+#define SNDRV_EMU10K1_IOCTL_DBG_READ   _IOR ('H', 0x84, int)
+
+/* typedefs for compatibility to user-space */
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+
+#endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/uapi/sound/hdsp.h b/include/uapi/sound/hdsp.h
new file mode 100644 (file)
index 0000000..0909a38
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __SOUND_HDSP_H
+#define __SOUND_HDSP_H
+
+/*
+ *   Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
+ *    
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+#define HDSP_MATRIX_MIXER_SIZE 2048
+
+enum HDSP_IO_Type {
+       Digiface,
+       Multiface,
+       H9652,
+       H9632,
+       RPM,
+       Undefined,
+};
+
+struct hdsp_peak_rms {
+       __u32 input_peaks[26];
+       __u32 playback_peaks[26];
+       __u32 output_peaks[28];
+       __u64 input_rms[26];
+       __u64 playback_rms[26];
+       /* These are only used for H96xx cards */
+       __u64 output_rms[26];
+};
+
+#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
+
+struct hdsp_config_info {
+       unsigned char pref_sync_ref;
+       unsigned char wordclock_sync_check;
+       unsigned char spdif_sync_check;
+       unsigned char adatsync_sync_check;
+       unsigned char adat_sync_check[3];
+       unsigned char spdif_in;
+       unsigned char spdif_out;
+       unsigned char spdif_professional;
+       unsigned char spdif_emphasis;
+       unsigned char spdif_nonaudio;
+       unsigned int spdif_sample_rate;
+       unsigned int system_sample_rate;
+       unsigned int autosync_sample_rate;
+       unsigned char system_clock_mode;
+       unsigned char clock_source;
+       unsigned char autosync_ref;
+       unsigned char line_out;
+       unsigned char passthru; 
+       unsigned char da_gain;
+       unsigned char ad_gain;
+       unsigned char phone_gain;
+       unsigned char xlr_breakout_cable;
+       unsigned char analog_extension_board;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
+
+struct hdsp_firmware {
+       void __user *firmware_data;     /* 24413 x 4 bytes */
+};
+
+#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
+
+struct hdsp_version {
+       enum HDSP_IO_Type io_type;
+       unsigned short firmware_rev;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
+
+struct hdsp_mixer {
+       unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
+};
+
+#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
+
+struct hdsp_9632_aeb {
+       int aebi;
+       int aebo;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
+
+/* typedefs for compatibility to user-space */
+typedef enum HDSP_IO_Type HDSP_IO_Type;
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
+typedef struct hdsp_config_info hdsp_config_info_t;
+typedef struct hdsp_firmware hdsp_firmware_t;
+typedef struct hdsp_version hdsp_version_t;
+typedef struct hdsp_mixer hdsp_mixer_t;
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
+
+#endif /* __SOUND_HDSP_H */
diff --git a/include/uapi/sound/hdspm.h b/include/uapi/sound/hdspm.h
new file mode 100644 (file)
index 0000000..1f59ea2
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef __SOUND_HDSPM_H
+#define __SOUND_HDSPM_H
+/*
+ *   Copyright (C) 2003 Winfried Ritsch (IEM)
+ *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
+#define HDSPM_MAX_CHANNELS      64
+
+enum hdspm_io_type {
+       MADI,
+       MADIface,
+       AIO,
+       AES32,
+       RayDAT
+};
+
+enum hdspm_speed {
+       ss,
+       ds,
+       qs
+};
+
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
+
+struct hdspm_peak_rms {
+       uint32_t input_peaks[64];
+       uint32_t playback_peaks[64];
+       uint32_t output_peaks[64];
+
+       uint64_t input_rms[64];
+       uint64_t playback_rms[64];
+       uint64_t output_rms[64];
+
+       uint8_t speed; /* enum {ss, ds, qs} */
+       int status2;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
+       _IOR('H', 0x42, struct hdspm_peak_rms)
+
+/* ------------ CONFIG block IOCTL ---------------------- */
+
+struct hdspm_config {
+       unsigned char pref_sync_ref;
+       unsigned char wordclock_sync_check;
+       unsigned char madi_sync_check;
+       unsigned int system_sample_rate;
+       unsigned int autosync_sample_rate;
+       unsigned char system_clock_mode;
+       unsigned char clock_source;
+       unsigned char autosync_ref;
+       unsigned char line_out;
+       unsigned int passthru;
+       unsigned int analog_out;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
+       _IOR('H', 0x41, struct hdspm_config)
+
+/**
+ * If there's a TCO (TimeCode Option) board installed,
+ * there are further options and status data available.
+ * The hdspm_ltc structure contains the current SMPTE
+ * timecode and some status information and can be
+ * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
+ * hdspm_status struct.
+ **/
+
+enum hdspm_ltc_format {
+       format_invalid,
+       fps_24,
+       fps_25,
+       fps_2997,
+       fps_30
+};
+
+enum hdspm_ltc_frame {
+       frame_invalid,
+       drop_frame,
+       full_frame
+};
+
+enum hdspm_ltc_input_format {
+       ntsc,
+       pal,
+       no_video
+};
+
+struct hdspm_ltc {
+       unsigned int ltc;
+
+       enum hdspm_ltc_format format;
+       enum hdspm_ltc_frame frame;
+       enum hdspm_ltc_input_format input_format;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
+
+/**
+ * The status data reflects the device's current state
+ * as determined by the card's configuration and
+ * connection status.
+ **/
+
+enum hdspm_sync {
+       hdspm_sync_no_lock = 0,
+       hdspm_sync_lock = 1,
+       hdspm_sync_sync = 2
+};
+
+enum hdspm_madi_input {
+       hdspm_input_optical = 0,
+       hdspm_input_coax = 1
+};
+
+enum hdspm_madi_channel_format {
+       hdspm_format_ch_64 = 0,
+       hdspm_format_ch_56 = 1
+};
+
+enum hdspm_madi_frame_format {
+       hdspm_frame_48 = 0,
+       hdspm_frame_96 = 1
+};
+
+enum hdspm_syncsource {
+       syncsource_wc = 0,
+       syncsource_madi = 1,
+       syncsource_tco = 2,
+       syncsource_sync = 3,
+       syncsource_none = 4
+};
+
+struct hdspm_status {
+       uint8_t card_type; /* enum hdspm_io_type */
+       enum hdspm_syncsource autosync_source;
+
+       uint64_t card_clock;
+       uint32_t master_period;
+
+       union {
+               struct {
+                       uint8_t sync_wc; /* enum hdspm_sync */
+                       uint8_t sync_madi; /* enum hdspm_sync */
+                       uint8_t sync_tco; /* enum hdspm_sync */
+                       uint8_t sync_in; /* enum hdspm_sync */
+                       uint8_t madi_input; /* enum hdspm_madi_input */
+                       uint8_t channel_format; /* enum hdspm_madi_channel_format */
+                       uint8_t frame_format; /* enum hdspm_madi_frame_format */
+               } madi;
+       } card_specific;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_STATUS \
+       _IOR('H', 0x47, struct hdspm_status)
+
+/**
+ * Get information about the card and its add-ons.
+ **/
+
+#define HDSPM_ADDON_TCO 1
+
+struct hdspm_version {
+       uint8_t card_type; /* enum hdspm_io_type */
+       char cardname[20];
+       unsigned int serial;
+       unsigned short firmware_rev;
+       int addons;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
+
+/* ------------- get Matrix Mixer IOCTL --------------- */
+
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
+ * 32768 Bytes
+ */
+
+/* organisation is 64 channelfader in a continuous memory block */
+/* equivalent to hardware definition, maybe for future feature of mmap of
+ * them
+ */
+/* each of 64 outputs has 64 infader and 64 outfader:
+   Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
+
+#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
+
+struct hdspm_channelfader {
+       unsigned int in[HDSPM_MIXER_CHANNELS];
+       unsigned int pb[HDSPM_MIXER_CHANNELS];
+};
+
+struct hdspm_mixer {
+       struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
+};
+
+struct hdspm_mixer_ioctl {
+       struct hdspm_mixer *mixer;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
+
+/* typedefs for compatibility to user-space */
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
+typedef struct hdspm_config_info hdspm_config_info_t;
+typedef struct hdspm_version hdspm_version_t;
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
+typedef struct hdspm_mixer hdspm_mixer_t;
+
+
+#endif
diff --git a/include/uapi/sound/sb16_csp.h b/include/uapi/sound/sb16_csp.h
new file mode 100644 (file)
index 0000000..3b96907
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
+ *                        Takashi Iwai <tiwai@suse.de>
+ *
+ *  SB16ASP/AWE32 CSP control
+ *
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_SB16_CSP_H
+#define _UAPI__SOUND_SB16_CSP_H
+
+
+/* CSP modes */
+#define SNDRV_SB_CSP_MODE_NONE         0x00
+#define SNDRV_SB_CSP_MODE_DSP_READ     0x01    /* Record from DSP */
+#define SNDRV_SB_CSP_MODE_DSP_WRITE    0x02    /* Play to DSP */
+#define SNDRV_SB_CSP_MODE_QSOUND               0x04    /* QSound */
+
+/* CSP load flags */
+#define SNDRV_SB_CSP_LOAD_FROMUSER     0x01
+#define SNDRV_SB_CSP_LOAD_INITBLOCK    0x02
+
+/* CSP sample width */
+#define SNDRV_SB_CSP_SAMPLE_8BIT               0x01
+#define SNDRV_SB_CSP_SAMPLE_16BIT              0x02
+
+/* CSP channels */
+#define SNDRV_SB_CSP_MONO                      0x01
+#define SNDRV_SB_CSP_STEREO            0x02
+
+/* CSP rates */
+#define SNDRV_SB_CSP_RATE_8000         0x01
+#define SNDRV_SB_CSP_RATE_11025                0x02
+#define SNDRV_SB_CSP_RATE_22050                0x04
+#define SNDRV_SB_CSP_RATE_44100                0x08
+#define SNDRV_SB_CSP_RATE_ALL          0x0f
+
+/* CSP running state */
+#define SNDRV_SB_CSP_ST_IDLE           0x00
+#define SNDRV_SB_CSP_ST_LOADED         0x01
+#define SNDRV_SB_CSP_ST_RUNNING                0x02
+#define SNDRV_SB_CSP_ST_PAUSED         0x04
+#define SNDRV_SB_CSP_ST_AUTO           0x08
+#define SNDRV_SB_CSP_ST_QSOUND         0x10
+
+/* maximum QSound value (180 degrees right) */
+#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT  0x20
+
+/* maximum microcode RIFF file size */
+#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE   0x3000
+
+/* microcode header */
+struct snd_sb_csp_mc_header {
+       char codec_name[16];            /* id name of codec */
+       unsigned short func_req;        /* requested function */
+};
+
+/* microcode to be loaded */
+struct snd_sb_csp_microcode {
+       struct snd_sb_csp_mc_header info;
+       unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
+};
+
+/* start CSP with sample_width in mono/stereo */
+struct snd_sb_csp_start {
+       int sample_width;       /* sample width, look above */
+       int channels;           /* channels, look above */
+};
+
+/* CSP information */
+struct snd_sb_csp_info {
+       char codec_name[16];            /* id name of codec */
+       unsigned short func_nr;         /* function number */
+       unsigned int acc_format;        /* accepted PCM formats */
+       unsigned short acc_channels;    /* accepted channels */
+       unsigned short acc_width;       /* accepted sample width */
+       unsigned short acc_rates;       /* accepted sample rates */
+       unsigned short csp_mode;        /* CSP mode, see above */
+       unsigned short run_channels;    /* current channels  */
+       unsigned short run_width;       /* current sample width */
+       unsigned short version;         /* version id: 0x10 - 0x1f */
+       unsigned short state;           /* state bits */
+};
+
+/* HWDEP controls */
+/* get CSP information */
+#define SNDRV_SB_CSP_IOCTL_INFO                _IOR('H', 0x10, struct snd_sb_csp_info)
+/* load microcode to CSP */
+/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
+ * defined for some architectures like MIPS, and it leads to build errors.
+ * (x86 and co have 14-bit size, thus it's valid, though.)
+ * As a workaround for skipping the size-limit check, here we don't use the
+ * normal _IOW() macro but _IOC() with the manual argument.
+ */
+#define SNDRV_SB_CSP_IOCTL_LOAD_CODE   \
+       _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
+/* unload microcode from CSP */
+#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
+/* start CSP */
+#define SNDRV_SB_CSP_IOCTL_START               _IOW('H', 0x13, struct snd_sb_csp_start)
+/* stop CSP */
+#define SNDRV_SB_CSP_IOCTL_STOP                _IO('H', 0x14)
+/* pause CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_PAUSE               _IO('H', 0x15)
+/* restart CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_RESTART     _IO('H', 0x16)
+
+
+#endif /* _UAPI__SOUND_SB16_CSP_H */
diff --git a/include/uapi/sound/sfnt_info.h b/include/uapi/sound/sfnt_info.h
new file mode 100644 (file)
index 0000000..1bce7fd
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef __SOUND_SFNT_INFO_H
+#define __SOUND_SFNT_INFO_H
+
+/*
+ *  Patch record compatible with AWE driver on OSS
+ *
+ *  Copyright (C) 1999-2000 Takashi Iwai
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <sound/asound.h>
+
+/*
+ * patch information record
+ */
+
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_OSS_PATCHKEY(id) (0xfd00|id)
+#else
+#define SNDRV_OSS_PATCHKEY(id) ((id<<8)|0xfd)
+#endif
+
+/* patch interface header: 16 bytes */
+struct soundfont_patch_info {
+       unsigned short key;             /* use the key below */
+#define SNDRV_OSS_SOUNDFONT_PATCH              SNDRV_OSS_PATCHKEY(0x07)
+
+       short device_no;                /* synthesizer number */
+       unsigned short sf_id;           /* file id (should be zero) */
+       short optarg;                   /* optional argument */
+       int len;                        /* data length (without this header) */
+
+       short type;                     /* patch operation type */
+#define SNDRV_SFNT_LOAD_INFO           0       /* awe_voice_rec */
+#define SNDRV_SFNT_LOAD_DATA           1       /* awe_sample_info */
+#define SNDRV_SFNT_OPEN_PATCH  2       /* awe_open_parm */
+#define SNDRV_SFNT_CLOSE_PATCH 3       /* none */
+       /* 4 is obsolete */
+#define SNDRV_SFNT_REPLACE_DATA        5       /* awe_sample_info (optarg=#channels)*/
+#define SNDRV_SFNT_MAP_PRESET  6       /* awe_voice_map */
+       /* 7 is not used */
+#define SNDRV_SFNT_PROBE_DATA          8       /* optarg=sample */
+#define SNDRV_SFNT_REMOVE_INFO         9       /* optarg=(bank<<8)|instr */
+
+       short reserved;                 /* word alignment data */
+
+       /* the actual patch data begins after this */
+};
+
+
+/*
+ * open patch
+ */
+
+#define SNDRV_SFNT_PATCH_NAME_LEN      32
+
+struct soundfont_open_parm {
+       unsigned short type;            /* sample type */
+#define SNDRV_SFNT_PAT_TYPE_MISC       0
+#define SNDRV_SFNT_PAT_TYPE_GUS        6
+#define SNDRV_SFNT_PAT_TYPE_MAP        7
+#define SNDRV_SFNT_PAT_LOCKED  0x100   /* lock the samples */
+#define SNDRV_SFNT_PAT_SHARED  0x200   /* sample is shared */
+
+       short reserved;
+       char name[SNDRV_SFNT_PATCH_NAME_LEN];
+};
+
+
+/*
+ * raw voice information record
+ */
+
+/* wave table envelope & effect parameters to control EMU8000 */
+struct soundfont_voice_parm {
+       unsigned short moddelay;        /* modulation delay (0x8000) */
+       unsigned short modatkhld;       /* modulation attack & hold time (0x7f7f) */
+       unsigned short moddcysus;       /* modulation decay & sustain (0x7f7f) */
+       unsigned short modrelease;      /* modulation release time (0x807f) */
+       short modkeyhold, modkeydecay;  /* envelope change per key (not used) */
+       unsigned short voldelay;        /* volume delay (0x8000) */
+       unsigned short volatkhld;       /* volume attack & hold time (0x7f7f) */
+       unsigned short voldcysus;       /* volume decay & sustain (0x7f7f) */
+       unsigned short volrelease;      /* volume release time (0x807f) */
+       short volkeyhold, volkeydecay;  /* envelope change per key (not used) */
+       unsigned short lfo1delay;       /* LFO1 delay (0x8000) */
+       unsigned short lfo2delay;       /* LFO2 delay (0x8000) */
+       unsigned short pefe;            /* modulation pitch & cutoff (0x0000) */
+       unsigned short fmmod;           /* LFO1 pitch & cutoff (0x0000) */
+       unsigned short tremfrq;         /* LFO1 volume & freq (0x0000) */
+       unsigned short fm2frq2;         /* LFO2 pitch & freq (0x0000) */
+       unsigned char cutoff;           /* initial cutoff (0xff) */
+       unsigned char filterQ;          /* initial filter Q [0-15] (0x0) */
+       unsigned char chorus;           /* chorus send (0x00) */
+       unsigned char reverb;           /* reverb send (0x00) */
+       unsigned short reserved[4];     /* not used */
+};
+
+
+/* wave table parameters: 92 bytes */
+struct soundfont_voice_info {
+       unsigned short sf_id;           /* file id (should be zero) */
+       unsigned short sample;          /* sample id */
+       int start, end;                 /* sample offset correction */
+       int loopstart, loopend;         /* loop offset correction */
+       short rate_offset;              /* sample rate pitch offset */
+       unsigned short mode;            /* sample mode */
+#define SNDRV_SFNT_MODE_ROMSOUND               0x8000
+#define SNDRV_SFNT_MODE_STEREO         1
+#define SNDRV_SFNT_MODE_LOOPING                2
+#define SNDRV_SFNT_MODE_NORELEASE              4       /* obsolete */
+#define SNDRV_SFNT_MODE_INIT_PARM              8
+
+       short root;                     /* midi root key */
+       short tune;                     /* pitch tuning (in cents) */
+       unsigned char low, high;        /* key note range */
+       unsigned char vellow, velhigh;  /* velocity range */
+       signed char fixkey, fixvel;     /* fixed key, velocity */
+       signed char pan, fixpan;        /* panning, fixed panning */
+       short exclusiveClass;           /* exclusive class (0 = none) */
+       unsigned char amplitude;        /* sample volume (127 max) */
+       unsigned char attenuation;      /* attenuation (0.375dB) */
+       short scaleTuning;              /* pitch scale tuning(%), normally 100 */
+       struct soundfont_voice_parm parm;       /* voice envelope parameters */
+       unsigned short sample_mode;     /* sample mode_flag (set by driver) */
+};
+
+
+/* instrument info header: 4 bytes */
+struct soundfont_voice_rec_hdr {
+       unsigned char bank;             /* midi bank number */
+       unsigned char instr;            /* midi preset number */
+       char nvoices;                   /* number of voices */
+       char write_mode;                /* write mode; normally 0 */
+#define SNDRV_SFNT_WR_APPEND           0       /* append anyway */
+#define SNDRV_SFNT_WR_EXCLUSIVE                1       /* skip if already exists */
+#define SNDRV_SFNT_WR_REPLACE          2       /* replace if already exists */
+};
+
+
+/*
+ * sample wave information
+ */
+
+/* wave table sample header: 32 bytes */
+struct soundfont_sample_info {
+       unsigned short sf_id;           /* file id (should be zero) */
+       unsigned short sample;          /* sample id */
+       int start, end;                 /* start & end offset */
+       int loopstart, loopend;         /* loop start & end offset */
+       int size;                       /* size (0 = ROM) */
+       short dummy;                    /* not used */
+       unsigned short mode_flags;      /* mode flags */
+#define SNDRV_SFNT_SAMPLE_8BITS                1       /* wave data is 8bits */
+#define SNDRV_SFNT_SAMPLE_UNSIGNED     2       /* wave data is unsigned */
+#define SNDRV_SFNT_SAMPLE_NO_BLANK     4       /* no blank loop is attached */
+#define SNDRV_SFNT_SAMPLE_SINGLESHOT   8       /* single-shot w/o loop */
+#define SNDRV_SFNT_SAMPLE_BIDIR_LOOP   16      /* bidirectional looping */
+#define SNDRV_SFNT_SAMPLE_STEREO_LEFT  32      /* stereo left sound */
+#define SNDRV_SFNT_SAMPLE_STEREO_RIGHT 64      /* stereo right sound */
+#define SNDRV_SFNT_SAMPLE_REVERSE_LOOP 128     /* reverse looping */
+       unsigned int truesize;          /* used memory size (set by driver) */
+};
+
+
+/*
+ * voice preset mapping (aliasing)
+ */
+
+struct soundfont_voice_map {
+       int map_bank, map_instr, map_key;       /* key = -1 means all keys */
+       int src_bank, src_instr, src_key;
+};
+
+
+/*
+ * ioctls for hwdep
+ */
+
+#define SNDRV_EMUX_HWDEP_NAME  "Emux WaveTable"
+
+#define SNDRV_EMUX_VERSION     ((1 << 16) | (0 << 8) | 0)      /* 1.0.0 */
+
+struct snd_emux_misc_mode {
+       int port;       /* -1 = all */
+       int mode;
+       int value;
+       int value2;     /* reserved */
+};
+
+#define SNDRV_EMUX_IOCTL_VERSION       _IOR('H', 0x80, unsigned int)
+#define SNDRV_EMUX_IOCTL_LOAD_PATCH    _IOWR('H', 0x81, struct soundfont_patch_info)
+#define SNDRV_EMUX_IOCTL_RESET_SAMPLES _IO('H', 0x82)
+#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83)
+#define SNDRV_EMUX_IOCTL_MEM_AVAIL     _IOW('H', 0x84, int)
+#define SNDRV_EMUX_IOCTL_MISC_MODE     _IOWR('H', 0x84, struct snd_emux_misc_mode)
+
+#endif /* __SOUND_SFNT_INFO_H */
index 5a0e4f9efb53a31cb4c1ba74e0257a2881fcde3e..f88825928dd16ac24502054d4796ae7121930e23 100644 (file)
 #ifndef DA8XX_FB_H
 #define DA8XX_FB_H
 
-enum panel_type {
-       QVGA = 0
-};
-
 enum panel_shade {
        MONOCHROME = 0,
        COLOR_ACTIVE,
@@ -27,13 +23,6 @@ enum raster_load_mode {
        LOAD_PALETTE,
 };
 
-struct display_panel {
-       enum panel_type panel_type; /* QVGA */
-       int max_bpp;
-       int min_bpp;
-       enum panel_shade panel_shade;
-};
-
 struct da8xx_lcdc_platform_data {
        const char manu_name[10];
        void *controller_data;
@@ -42,7 +31,7 @@ struct da8xx_lcdc_platform_data {
 };
 
 struct lcd_ctrl_config {
-       const struct display_panel *p_disp_panel;
+       enum panel_shade panel_shade;
 
        /* AC Bias Pin Frequency */
        int ac_bias;
@@ -68,18 +57,9 @@ struct lcd_ctrl_config {
        /* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */
        unsigned char mono_8bit_mode;
 
-       /* Invert line clock */
-       unsigned char invert_line_clock;
-
-       /* Invert frame clock  */
-       unsigned char invert_frm_clock;
-
        /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
        unsigned char sync_edge;
 
-       /* Horizontal and Vertical Sync: Control: 0=ignore */
-       unsigned char sync_ctrl;
-
        /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
        unsigned char raster_order;
 
@@ -103,5 +83,8 @@ struct lcd_sync_arg {
 #define FBIPUT_HSYNC           _IOW('F', 9, int)
 #define FBIPUT_VSYNC           _IOW('F', 10, int)
 
+/* Proprietary FB_SYNC_ flags */
+#define FB_SYNC_CLK_INVERT 0x40000000
+
 #endif  /* ifndef DA8XX_FB_H */
 
index 88c829466fc1151c61edac08789939d0c00aba47..caefa093337d9da1d0ba440cdc98665d91bb1801 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
 
 #define DISPC_IRQ_FRAMEDONE            (1 << 0)
 #define DISPC_IRQ_VSYNC                        (1 << 1)
@@ -55,6 +56,7 @@
 
 struct omap_dss_device;
 struct omap_overlay_manager;
+struct dss_lcd_mgr_config;
 struct snd_aes_iec958;
 struct snd_cea_861_aud_if;
 
@@ -158,7 +160,6 @@ enum omap_display_caps {
 enum omap_dss_display_state {
        OMAP_DSS_DISPLAY_DISABLED = 0,
        OMAP_DSS_DISPLAY_ACTIVE,
-       OMAP_DSS_DISPLAY_SUSPENDED,
 };
 
 enum omap_dss_audio_state {
@@ -621,10 +622,6 @@ struct omap_dss_device {
        struct {
                struct omap_video_timings timings;
 
-               int acbi;       /* ac-bias pin transitions per interrupt */
-               /* Unit: line clocks */
-               int acb;        /* ac-bias pin frequency */
-
                enum omap_dss_dsi_pixel_format dsi_pix_fmt;
                enum omap_dss_dsi_mode dsi_mode;
                struct omap_dss_dsi_videomode_timings dsi_vm_timings;
@@ -686,8 +683,6 @@ struct omap_dss_driver {
 
        int (*enable)(struct omap_dss_device *display);
        void (*disable)(struct omap_dss_device *display);
-       int (*suspend)(struct omap_dss_device *display);
-       int (*resume)(struct omap_dss_device *display);
        int (*run_test)(struct omap_dss_device *display, int test);
 
        int (*update)(struct omap_dss_device *dssdev,
@@ -745,6 +740,8 @@ struct omap_dss_driver {
 
 };
 
+enum omapdss_version omapdss_get_version(void);
+
 int omap_dss_register_driver(struct omap_dss_driver *);
 void omap_dss_unregister_driver(struct omap_dss_driver *);
 
@@ -754,10 +751,19 @@ void omap_dss_put_device(struct omap_dss_device *dssdev);
 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
 struct omap_dss_device *omap_dss_find_device(void *data,
                int (*match)(struct omap_dss_device *dssdev, void *data));
+const char *omapdss_get_default_display_name(void);
 
 int omap_dss_start_device(struct omap_dss_device *dssdev);
 void omap_dss_stop_device(struct omap_dss_device *dssdev);
 
+int dss_feat_get_num_mgrs(void);
+int dss_feat_get_num_ovls(void);
+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);
+
+
+
 int omap_dss_get_num_overlay_managers(void);
 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
 
@@ -779,9 +785,43 @@ typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 
-int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
-               unsigned long timeout);
+u32 dispc_read_irqstatus(void);
+void dispc_clear_irqstatus(u32 mask);
+u32 dispc_read_irqenable(void);
+void dispc_write_irqenable(u32 mask);
+
+int dispc_request_irq(irq_handler_t handler, void *dev_id);
+void dispc_free_irq(void *dev_id);
+
+int dispc_runtime_get(void);
+void dispc_runtime_put(void);
+
+void dispc_mgr_enable(enum omap_channel channel, bool enable);
+bool dispc_mgr_is_enabled(enum omap_channel channel);
+u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
+bool dispc_mgr_go_busy(enum omap_channel channel);
+void dispc_mgr_go(enum omap_channel channel);
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+               const struct dss_lcd_mgr_config *config);
+void dispc_mgr_set_timings(enum omap_channel channel,
+               const struct omap_video_timings *timings);
+void dispc_mgr_setup(enum omap_channel channel,
+               const struct omap_overlay_manager_info *info);
+
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
+               const struct omap_overlay_info *oi,
+               const struct omap_video_timings *timings,
+               int *x_predecim, int *y_predecim);
+
+int dispc_ovl_enable(enum omap_plane plane, bool enable);
+bool dispc_ovl_enabled(enum omap_plane plane);
+void dispc_ovl_set_channel_out(enum omap_plane plane,
+               enum omap_channel channel);
+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);
 
 #define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
 #define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
@@ -840,4 +880,35 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
 void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
                struct rfbi_timings *timings);
 
+int omapdss_compat_init(void);
+void omapdss_compat_uninit(void);
+
+struct dss_mgr_ops {
+       void (*start_update)(struct omap_overlay_manager *mgr);
+       int (*enable)(struct omap_overlay_manager *mgr);
+       void (*disable)(struct omap_overlay_manager *mgr);
+       void (*set_timings)(struct omap_overlay_manager *mgr,
+                       const struct omap_video_timings *timings);
+       void (*set_lcd_config)(struct omap_overlay_manager *mgr,
+                       const struct dss_lcd_mgr_config *config);
+       int (*register_framedone_handler)(struct omap_overlay_manager *mgr,
+                       void (*handler)(void *), void *data);
+       void (*unregister_framedone_handler)(struct omap_overlay_manager *mgr,
+                       void (*handler)(void *), void *data);
+};
+
+int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops);
+void dss_uninstall_mgr_ops(void);
+
+void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+               const struct omap_video_timings *timings);
+void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+               const struct dss_lcd_mgr_config *config);
+int dss_mgr_enable(struct omap_overlay_manager *mgr);
+void dss_mgr_disable(struct omap_overlay_manager *mgr);
+void dss_mgr_start_update(struct omap_overlay_manager *mgr);
+int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data);
+void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data);
 #endif
index 7ae6c07f2ef8617b98d4cdefefc6929e675eb2de..e7554486a2b7e89bff91bfd2c96726fcbcad4a89 100644 (file)
 
 #define VIDCON0                                        (0x00)
 #define VIDCON0_INTERLACE                      (1 << 29)
-#define VIDCON0_VIDOUT_MASK                    (0x3 << 26)
+#define VIDCON0_VIDOUT_MASK                    (0x7 << 26)
 #define VIDCON0_VIDOUT_SHIFT                   (26)
 #define VIDCON0_VIDOUT_RGB                     (0x0 << 26)
 #define VIDCON0_VIDOUT_TV                      (0x1 << 26)
 #define VIDCON0_VIDOUT_I80_LDI0                        (0x2 << 26)
 #define VIDCON0_VIDOUT_I80_LDI1                        (0x3 << 26)
+#define VIDCON0_VIDOUT_WB_RGB                  (0x4 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI0             (0x6 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI1             (0x7 << 26)
 
 #define VIDCON0_L1_DATA_MASK                   (0x7 << 23)
 #define VIDCON0_L1_DATA_SHIFT                  (23)
@@ -77,6 +80,7 @@
 #define VIDCON1_LINECNT_MASK                   (0x7ff << 16)
 #define VIDCON1_LINECNT_SHIFT                  (16)
 #define VIDCON1_LINECNT_GET(_v)                        (((_v) >> 16) & 0x7ff)
+#define VIDCON1_FSTATUS_EVEN                   (1 << 15)
 #define VIDCON1_VSTATUS_MASK                   (0x3 << 13)
 #define VIDCON1_VSTATUS_SHIFT                  (13)
 #define VIDCON1_VSTATUS_VSYNC                  (0x0 << 13)
 
 /* VIDTCON0 */
 
+#define VIDTCON0                               (0x10)
 #define VIDTCON0_VBPDE_MASK                    (0xff << 24)
 #define VIDTCON0_VBPDE_SHIFT                   (24)
 #define VIDTCON0_VBPDE_LIMIT                   (0xff)
 
 /* VIDTCON1 */
 
+#define VIDTCON1                               (0x14)
 #define VIDTCON1_VFPDE_MASK                    (0xff << 24)
 #define VIDTCON1_VFPDE_SHIFT                   (24)
 #define VIDTCON1_VFPDE_LIMIT                   (0xff)
 #define VIDTCON1_HSPW_LIMIT                    (0xff)
 #define VIDTCON1_HSPW(_x)                      ((_x) << 0)
 
+#define VIDTCON2                               (0x18)
 #define VIDTCON2                               (0x18)
 #define VIDTCON2_LINEVAL_E(_x)                 ((((_x) & 0x800) >> 11) << 23)
 #define VIDTCON2_LINEVAL_MASK                  (0x7ff << 11)
 
 /* WINCONx */
 
-
+#define WINCON(_win)                           (0x20 + ((_win) * 4))
+#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_BITSWP                         (1 << 18)
 #define WINCONx_BYTSWP                         (1 << 17)
 #define WINCONx_HAWSWP                         (1 << 16)
 #define WINCONx_WSWP                           (1 << 15)
+#define WINCONx_YCbCr                          (1 << 13)
 #define WINCONx_BURSTLEN_MASK                  (0x3 << 9)
 #define WINCONx_BURSTLEN_SHIFT                 (9)
 #define WINCONx_BURSTLEN_16WORD                        (0x0 << 9)
 #define WINCONx_BURSTLEN_8WORD                 (0x1 << 9)
 #define WINCONx_BURSTLEN_4WORD                 (0x2 << 9)
-
 #define WINCONx_ENWIN                          (1 << 0)
+
 #define WINCON0_BPPMODE_MASK                   (0xf << 2)
 #define WINCON0_BPPMODE_SHIFT                  (2)
 #define WINCON0_BPPMODE_1BPP                   (0x0 << 2)
 #define WINCON0_BPPMODE_18BPP_666              (0x8 << 2)
 #define WINCON0_BPPMODE_24BPP_888              (0xb << 2)
 
+#define WINCON1_LOCALSEL_CAMIF                 (1 << 23)
 #define WINCON1_BLD_PIX                                (1 << 6)
-
-#define WINCON1_ALPHA_SEL                      (1 << 1)
 #define WINCON1_BPPMODE_MASK                   (0xf << 2)
 #define WINCON1_BPPMODE_SHIFT                  (2)
 #define WINCON1_BPPMODE_1BPP                   (0x0 << 2)
 #define WINCON1_BPPMODE_24BPP_A1887            (0xc << 2)
 #define WINCON1_BPPMODE_25BPP_A1888            (0xd << 2)
 #define WINCON1_BPPMODE_28BPP_A4888            (0xd << 2)
+#define WINCON1_ALPHA_SEL                      (1 << 1)
 
 /* S5PV210 */
 #define SHADOWCON                              (0x34)
 /* Local input channels (windows 0-2) */
 #define SHADOWCON_CHx_LOCAL_ENABLE(_win)       (1 << (5 + (_win)))
 
+/* VIDOSDx */
+
+#define VIDOSD_BASE                            (0x40)
 #define VIDOSDxA_TOPLEFT_X_E(_x)               ((((_x) & 0x800) >> 11) << 23)
 #define VIDOSDxA_TOPLEFT_X_MASK                        (0x7ff << 11)
 #define VIDOSDxA_TOPLEFT_X_SHIFT               (11)
 
 /* Interrupt controls and status */
 
+#define VIDINTCON0                             (0x130)
 #define VIDINTCON0_FIFOINTERVAL_MASK           (0x3f << 20)
 #define VIDINTCON0_FIFOINTERVAL_SHIFT          (20)
 #define VIDINTCON0_FIFOINTERVAL_LIMIT          (0x3f)
 #define VIDINTCON0_FIFIOSEL_SHIFT              (5)
 #define VIDINTCON0_FIFIOSEL_WINDOW0            (0x1 << 5)
 #define VIDINTCON0_FIFIOSEL_WINDOW1            (0x2 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW2            (0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3            (0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4            (0x40 << 5)
 
 #define VIDINTCON0_FIFOLEVEL_MASK              (0x7 << 2)
 #define VIDINTCON0_FIFOLEVEL_SHIFT             (2)
 #define WxKEYCON1_COLVAL_LIMIT                 (0xffffff)
 #define WxKEYCON1_COLVAL(_x)                   ((_x) << 0)
 
+/* Dithering control */
+#define DITHMODE                               (0x170)
+#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)
 
 /* Window blanking (MAP) */
-
+#define WINxMAP(_win)                          (0x180 + ((_win) * 4))
 #define WINxMAP_MAP                            (1 << 24)
 #define WINxMAP_MAP_COLOUR_MASK                        (0xffffff << 0)
 #define WINxMAP_MAP_COLOUR_SHIFT               (0)
 #define WINxMAP_MAP_COLOUR_LIMIT               (0xffffff)
 #define WINxMAP_MAP_COLOUR(_x)                 ((_x) << 0)
 
+/* Winodw palette control */
+#define WPALCON                                        (0x1A0)
 #define WPALCON_PAL_UPDATE                     (1 << 9)
+#define WPALCON_W4PAL_16BPP_A555               (1 << 8)
+#define WPALCON_W3PAL_16BPP_A555               (1 << 7)
+#define WPALCON_W2PAL_16BPP_A555               (1 << 6)
 #define WPALCON_W1PAL_MASK                     (0x7 << 3)
 #define WPALCON_W1PAL_SHIFT                    (3)
 #define WPALCON_W1PAL_25BPP_A888               (0x0 << 3)
 #define WPALCON_W1PAL_18BPP                    (0x4 << 3)
 #define WPALCON_W1PAL_16BPP_A555               (0x5 << 3)
 #define WPALCON_W1PAL_16BPP_565                        (0x6 << 3)
-
 #define WPALCON_W0PAL_MASK                     (0x7 << 0)
 #define WPALCON_W0PAL_SHIFT                    (0)
 #define WPALCON_W0PAL_25BPP_A888               (0x0 << 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
  *
index 06c67fbc4eee471f8871fd3892f87be5712c2e00..a01f197e6ac1560d1200b0f8d4e1b843b1891fd2 100644 (file)
@@ -25,8 +25,6 @@ enum sh_mipi_dsi_data_fmt {
        MIPI_YUV420,
 };
 
-struct sh_mobile_lcdc_chan_cfg;
-
 #define SH_MIPI_DSI_HSABM      (1 << 0)
 #define SH_MIPI_DSI_HBPBM      (1 << 1)
 #define SH_MIPI_DSI_HFPBM      (1 << 2)
@@ -47,7 +45,7 @@ struct sh_mobile_lcdc_chan_cfg;
 
 struct sh_mipi_dsi_info {
        enum sh_mipi_dsi_data_fmt       data_format;
-       struct sh_mobile_lcdc_chan_cfg  *lcd_chan;
+       int                             channel;
        int                             lane;
        unsigned long                   flags;
        u32                             clksrc;
index ff43ffc1aab29a111a9f7893ac08b93864d1be0f..2605fa8adb9c00c74c951ee1e307fd85914dc247 100644 (file)
@@ -163,7 +163,6 @@ struct sh_mobile_lcdc_bl_info {
        const char *name;
        int max_brightness;
        int (*set_brightness)(int brightness);
-       int (*get_brightness)(void);
 };
 
 struct sh_mobile_lcdc_overlay_cfg {
index 90712e2072d57ba6c6154549352266d253ab3615..b40a4315cb8b0724a7ff373570c5526800dceee5 100644 (file)
@@ -153,6 +153,14 @@ struct xen_machphys_mapping {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
 
+#define XENMAPSPACE_shared_info  0 /* shared info page */
+#define XENMAPSPACE_grant_table  1 /* grant table page */
+#define XENMAPSPACE_gmfn         2 /* GMFN */
+#define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
+                                   * XENMEM_add_to_physmap_range only.
+                                   */
+
 /*
  * Sets the GPFN at which a particular page appears in the specified guest's
  * pseudophysical address space.
@@ -167,8 +175,6 @@ struct xen_add_to_physmap {
     uint16_t    size;
 
     /* Source mapping space. */
-#define XENMAPSPACE_shared_info 0 /* shared info page */
-#define XENMAPSPACE_grant_table 1 /* grant table page */
     unsigned int space;
 
     /* Index into source mapping space. */
@@ -182,6 +188,24 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 /*** REMOVED ***/
 /*#define XENMEM_translate_gpfn_list  8*/
 
+#define XENMEM_add_to_physmap_range 23
+struct xen_add_to_physmap_range {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+    uint16_t space; /* => enum phys_map_space */
+
+    /* Number of pages to go through */
+    uint16_t size;
+    domid_t foreign_domid; /* IFF gmfn_foreign */
+
+    /* Indexes into space being mapped. */
+    GUEST_HANDLE(xen_ulong_t) idxs;
+
+    /* GPFN in domid where the source mapping page should appear. */
+    GUEST_HANDLE(xen_pfn_t) gpfns;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap_range);
+
 /*
  * Returns the pseudo-physical memory map as it was when the domain
  * was started (specified by XENMEM_set_memory_map).
@@ -217,4 +241,20 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_memory_map);
  * during a driver critical region.
  */
 extern spinlock_t xen_reservation_lock;
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap      15
+struct xen_remove_from_physmap {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+
+    /* GPFN of the current mapping of the page. */
+    xen_pfn_t gpfn;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap);
+
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
index 4755b5fac9c736b5fc010ae5d9a3e8c70838a232..5e36932ab40754181191c9966cfb735fdb58dbc1 100644 (file)
@@ -324,6 +324,22 @@ struct xenpf_cpu_ol {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol);
 
+/*
+ * CMD 58 and 59 are reserved for cpu hotadd and memory hotadd,
+ * which are already occupied at Xen hypervisor side.
+ */
+#define XENPF_core_parking     60
+struct xenpf_core_parking {
+       /* IN variables */
+#define XEN_CORE_PARKING_SET   1
+#define XEN_CORE_PARKING_GET   2
+       uint32_t type;
+       /* IN variables:  set cpu nums expected to be idled */
+       /* OUT variables: get cpu nums actually be idled */
+       uint32_t idle_nums;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_core_parking);
+
 struct xen_platform_op {
        uint32_t cmd;
        uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -341,6 +357,7 @@ struct xen_platform_op {
                struct xenpf_set_processor_pminfo set_pminfo;
                struct xenpf_pcpuinfo          pcpu_info;
                struct xenpf_cpu_ol            cpu_ol;
+               struct xenpf_core_parking      core_parking;
                uint8_t                        pad[128];
        } u;
 };
index 6a198e46ab6e1c50cdff7fe76d58b3a4afb43d43..d6fe062cad6b3128b25104107a1c0468d442295f 100644 (file)
@@ -2,6 +2,7 @@
 #define INCLUDE_XEN_OPS_H
 
 #include <linux/percpu.h>
+#include <asm/xen/interface.h>
 
 DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
 
@@ -26,7 +27,11 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
 struct vm_area_struct;
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
                               unsigned long addr,
-                              unsigned long mfn, int nr,
-                              pgprot_t prot, unsigned domid);
+                              xen_pfn_t mfn, int nr,
+                              pgprot_t prot, unsigned domid,
+                              struct page **pages);
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+                              int numpgs, struct page **pages);
 
+bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
 #endif /* INCLUDE_XEN_OPS_H */
index e33e09df3cbc61ad11736776ef4138010df1de8e..6af5470b806761bd477bbeb2b46269e85e22d2b0 100644 (file)
@@ -463,6 +463,10 @@ static void __init mm_init(void)
        percpu_init_late();
        pgtable_cache_init();
        vmalloc_init();
+#ifdef CONFIG_X86
+       if (efi_enabled)
+               efi_enter_virtual_mode();
+#endif
 }
 
 asmlinkage void __init start_kernel(void)
@@ -603,10 +607,6 @@ asmlinkage void __init start_kernel(void)
        calibrate_delay();
        pidmap_init();
        anon_vma_init();
-#ifdef CONFIG_X86
-       if (efi_enabled)
-               efi_enter_virtual_mode();
-#endif
        thread_info_cache_init();
        cred_init();
        fork_init(totalram_pages);
@@ -857,7 +857,7 @@ static void __init kernel_init_freeable(void)
        /*
         * init can allocate pages on any node
         */
-       set_mems_allowed(node_states[N_HIGH_MEMORY]);
+       set_mems_allowed(node_states[N_MEMORY]);
        /*
         * init can run on any cpu.
         */
index b017887d632f21a7743882705b59b9d99b0add9d..7bb63eea6eb85e4781eac7289e6f4a4edf6d3520 100644 (file)
@@ -302,10 +302,10 @@ static void guarantee_online_cpus(const struct cpuset *cs,
  * are online, with memory.  If none are online with memory, walk
  * up the cpuset hierarchy until we find one that does have some
  * online mems.  If we get all the way to the top and still haven't
- * found any online mems, return node_states[N_HIGH_MEMORY].
+ * found any online mems, return node_states[N_MEMORY].
  *
  * One way or another, we guarantee to return some non-empty subset
- * of node_states[N_HIGH_MEMORY].
+ * of node_states[N_MEMORY].
  *
  * Call with callback_mutex held.
  */
@@ -313,14 +313,14 @@ static void guarantee_online_cpus(const struct cpuset *cs,
 static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
 {
        while (cs && !nodes_intersects(cs->mems_allowed,
-                                       node_states[N_HIGH_MEMORY]))
+                                       node_states[N_MEMORY]))
                cs = cs->parent;
        if (cs)
                nodes_and(*pmask, cs->mems_allowed,
-                                       node_states[N_HIGH_MEMORY]);
+                                       node_states[N_MEMORY]);
        else
-               *pmask = node_states[N_HIGH_MEMORY];
-       BUG_ON(!nodes_intersects(*pmask, node_states[N_HIGH_MEMORY]));
+               *pmask = node_states[N_MEMORY];
+       BUG_ON(!nodes_intersects(*pmask, node_states[N_MEMORY]));
 }
 
 /*
@@ -1100,7 +1100,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
                return -ENOMEM;
 
        /*
-        * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
+        * top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
         * it's read-only
         */
        if (cs == &top_cpuset) {
@@ -1122,7 +1122,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
                        goto done;
 
                if (!nodes_subset(trialcs->mems_allowed,
-                               node_states[N_HIGH_MEMORY])) {
+                               node_states[N_MEMORY])) {
                        retval =  -EINVAL;
                        goto done;
                }
@@ -2026,7 +2026,7 @@ static struct cpuset *cpuset_next(struct list_head *queue)
  * before dropping down to the next.  It always processes a node before
  * any of its children.
  *
- * In the case of memory hot-unplug, it will remove nodes from N_HIGH_MEMORY
+ * In the case of memory hot-unplug, it will remove nodes from N_MEMORY
  * if all present pages from a node are offlined.
  */
 static void
@@ -2065,7 +2065,7 @@ scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
 
                        /* Continue past cpusets with all mems online */
                        if (nodes_subset(cp->mems_allowed,
-                                       node_states[N_HIGH_MEMORY]))
+                                       node_states[N_MEMORY]))
                                continue;
 
                        oldmems = cp->mems_allowed;
@@ -2073,7 +2073,7 @@ scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
                        /* Remove offline mems from this cpuset. */
                        mutex_lock(&callback_mutex);
                        nodes_and(cp->mems_allowed, cp->mems_allowed,
-                                               node_states[N_HIGH_MEMORY]);
+                                               node_states[N_MEMORY]);
                        mutex_unlock(&callback_mutex);
 
                        /* Move tasks from the empty cpuset to a parent */
@@ -2126,8 +2126,8 @@ void cpuset_update_active_cpus(bool cpu_online)
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
- * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
- * Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
+ * Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY].
+ * Call this routine anytime after node_states[N_MEMORY] changes.
  * See cpuset_update_active_cpus() for CPU hotplug handling.
  */
 static int cpuset_track_online_nodes(struct notifier_block *self,
@@ -2140,7 +2140,7 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
        case MEM_ONLINE:
                oldmems = top_cpuset.mems_allowed;
                mutex_lock(&callback_mutex);
-               top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+               top_cpuset.mems_allowed = node_states[N_MEMORY];
                mutex_unlock(&callback_mutex);
                update_tasks_nodemask(&top_cpuset, &oldmems, NULL);
                break;
@@ -2169,7 +2169,7 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
 void __init cpuset_init_smp(void)
 {
        cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
-       top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+       top_cpuset.mems_allowed = node_states[N_MEMORY];
 
        hotplug_memory_notifier(cpuset_track_online_nodes, 10);
 
@@ -2237,7 +2237,7 @@ void cpuset_init_current_mems_allowed(void)
  *
  * Description: Returns the nodemask_t mems_allowed of the cpuset
  * attached to the specified @tsk.  Guaranteed to return some non-empty
- * subset of node_states[N_HIGH_MEMORY], even if this means going outside the
+ * subset of node_states[N_MEMORY], even if this means going outside the
  * tasks cpuset.
  **/
 
index 29fb60caecb53125fa76e852609d38f4380cab4c..691dc2ef9baf241c121144799360a7e1237afcb5 100644 (file)
@@ -428,7 +428,7 @@ int kthreadd(void *unused)
        set_task_comm(tsk, "kthreadd");
        ignore_signals(tsk);
        set_cpus_allowed_ptr(tsk, cpu_all_mask);
-       set_mems_allowed(node_states[N_HIGH_MEMORY]);
+       set_mems_allowed(node_states[N_MEMORY]);
 
        current->flags |= PF_NOFREEZE;
 
index 89fe3d1b9efbc1f34351e5752dd730db3c5bbab4..072f4ee4eb893a5341942146775c2ce9fcc1dbc8 100644 (file)
@@ -171,7 +171,7 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd)
 {
        int cpu, num_cpus;
        unsigned int next_nr, next_index;
-       struct padata_parallel_queue *queue, *next_queue;
+       struct padata_parallel_queue *next_queue;
        struct padata_priv *padata;
        struct padata_list *reorder;
 
@@ -204,8 +204,7 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd)
                goto out;
        }
 
-       queue = per_cpu_ptr(pd->pqueue, smp_processor_id());
-       if (queue->cpu_index == next_queue->cpu_index) {
+       if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) {
                padata = ERR_PTR(-ENODATA);
                goto out;
        }
index aebd4f5aaf41ffaf59e4bf2a12d18600705d08e9..fd996c1ed9f891988607812abb95dc8820ab3751 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Generic pidhash and scalable, time-bounded PID allocator
  *
- * (C) 2002-2003 William Irwin, IBM
- * (C) 2004 William Irwin, Oracle
+ * (C) 2002-2003 Nadia Yvette Chambers, IBM
+ * (C) 2004 Nadia Yvette Chambers, Oracle
  * (C) 2002-2004 Ingo Molnar, Red Hat
  *
  * pid-structures are backing objects for tasks sharing a given ID to chain
index 76b8e77773eecb3120b87faa0a0b23e2b4cb8fd3..1f391819c42fe6d6539f5ba5e66e6f365b877f6d 100644 (file)
@@ -8,9 +8,10 @@
  *  Scheduler profiling support, Arjan van de Ven and Ingo Molnar,
  *     Red Hat, July 2004
  *  Consolidation of architecture support code for profiling,
- *     William Irwin, Oracle, July 2004
+ *     Nadia Yvette Chambers, Oracle, July 2004
  *  Amortized hit count accounting via per-cpu open-addressed hashtables
- *     to resolve timer interrupt livelocks, William Irwin, Oracle, 2004
+ *     to resolve timer interrupt livelocks, Nadia Yvette Chambers,
+ *     Oracle, 2004
  */
 
 #include <linux/export.h>
@@ -256,7 +257,7 @@ EXPORT_SYMBOL_GPL(unregister_timer_hook);
  * pagetable hash functions, but uses a full hashtable full of finite
  * collision chains, not just pairs of them.
  *
- * -- wli
+ * -- nyc
  */
 static void __profile_flip_buffers(void *unused)
 {
index ad581aa2369a2ed8f925c395b2b4eadd9d8640f2..3920d593e63c7d86acfcc07f1caa1443a065ffb1 100644 (file)
@@ -192,25 +192,3 @@ int res_counter_memparse_write_strategy(const char *buf,
        *res = PAGE_ALIGN(*res);
        return 0;
 }
-
-int res_counter_write(struct res_counter *counter, int member,
-                     const char *buf, write_strategy_fn write_strategy)
-{
-       char *end;
-       unsigned long flags;
-       unsigned long long tmp, *val;
-
-       if (write_strategy) {
-               if (write_strategy(buf, &tmp))
-                       return -EINVAL;
-       } else {
-               tmp = simple_strtoull(buf, &end, 10);
-               if (*end != '\0')
-                       return -EINVAL;
-       }
-       spin_lock_irqsave(&counter->lock, flags);
-       val = res_counter_member(counter, member);
-       *val = tmp;
-       spin_unlock_irqrestore(&counter->lock, flags);
-       return 0;
-}
index 6271b89f87acb4eb6ad834732256a62317d14566..0533496b6228cfde3afe20051006683da12e0ca5 100644 (file)
@@ -923,6 +923,13 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
                rq->skip_clock_update = 1;
 }
 
+static ATOMIC_NOTIFIER_HEAD(task_migration_notifier);
+
+void register_task_migration_notifier(struct notifier_block *n)
+{
+       atomic_notifier_chain_register(&task_migration_notifier, n);
+}
+
 #ifdef CONFIG_SMP
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
@@ -953,10 +960,18 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
        trace_sched_migrate_task(p, new_cpu);
 
        if (task_cpu(p) != new_cpu) {
+               struct task_migration_notifier tmn;
+
                if (p->sched_class->migrate_task_rq)
                        p->sched_class->migrate_task_rq(p, new_cpu);
                p->se.nr_migrations++;
                perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, NULL, 0);
+
+               tmn.task = p;
+               tmn.from_cpu = task_cpu(p);
+               tmn.to_cpu = new_cpu;
+
+               atomic_notifier_call_chain(&task_migration_notifier, 0, &tmn);
        }
 
        __set_task_cpu(p, new_cpu);
index 59e072b2db970b80eb2eac7b435d297305640e2a..756f9f9e85422759e4c391ac1e5404d93ee9a836 100644 (file)
@@ -1265,7 +1265,6 @@ static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq, int force_update)
        }
 
        __update_cfs_rq_tg_load_contrib(cfs_rq, force_update);
-       update_cfs_shares(cfs_rq);
 }
 
 static inline void update_rq_runnable_avg(struct rq *rq, int runnable)
@@ -1475,8 +1474,9 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
         * Update run-time statistics of the 'current'.
         */
        update_curr(cfs_rq);
-       account_entity_enqueue(cfs_rq, se);
        enqueue_entity_load_avg(cfs_rq, se, flags & ENQUEUE_WAKEUP);
+       account_entity_enqueue(cfs_rq, se);
+       update_cfs_shares(cfs_rq);
 
        if (flags & ENQUEUE_WAKEUP) {
                place_entity(cfs_rq, se, 0);
@@ -1549,6 +1549,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
         * Update run-time statistics of the 'current'.
         */
        update_curr(cfs_rq);
+       dequeue_entity_load_avg(cfs_rq, se, flags & DEQUEUE_SLEEP);
 
        update_stats_dequeue(cfs_rq, se);
        if (flags & DEQUEUE_SLEEP) {
@@ -1568,8 +1569,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 
        if (se != cfs_rq->curr)
                __dequeue_entity(cfs_rq, se);
+       se->on_rq = 0;
        account_entity_dequeue(cfs_rq, se);
-       dequeue_entity_load_avg(cfs_rq, se, flags & DEQUEUE_SLEEP);
 
        /*
         * Normalize the entity after updating the min_vruntime because the
@@ -1583,7 +1584,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
        return_cfs_rq_runtime(cfs_rq);
 
        update_min_vruntime(cfs_rq);
-       se->on_rq = 0;
+       update_cfs_shares(cfs_rq);
 }
 
 /*
@@ -2595,8 +2596,8 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
                if (cfs_rq_throttled(cfs_rq))
                        break;
 
+               update_cfs_shares(cfs_rq);
                update_entity_load_avg(se, 1);
-               update_cfs_rq_blocked_load(cfs_rq, 0);
        }
 
        if (!se) {
@@ -2656,8 +2657,8 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
                if (cfs_rq_throttled(cfs_rq))
                        break;
 
+               update_cfs_shares(cfs_rq);
                update_entity_load_avg(se, 1);
-               update_cfs_rq_blocked_load(cfs_rq, 0);
        }
 
        if (!se) {
@@ -5837,11 +5838,8 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
                se = tg->se[i];
                /* Propagate contribution to hierarchy */
                raw_spin_lock_irqsave(&rq->lock, flags);
-               for_each_sched_entity(se) {
+               for_each_sched_entity(se)
                        update_cfs_shares(group_cfs_rq(se));
-                       /* update contribution to parent */
-                       update_entity_load_avg(se, 1);
-               }
                raw_spin_unlock_irqrestore(&rq->lock, flags);
        }
 
index 4c7de02eacdce9875cefb7598d5047b95f235770..cbc6acb0db3fafbaa4830da34cdb22e538892764 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/time.h>
 #include <linux/tick.h>
 #include <linux/stop_machine.h>
+#include <linux/pvclock_gtod.h>
 
 
 static struct timekeeper timekeeper;
@@ -174,6 +175,54 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
        return nsec + arch_gettimeoffset();
 }
 
+static RAW_NOTIFIER_HEAD(pvclock_gtod_chain);
+
+static void update_pvclock_gtod(struct timekeeper *tk)
+{
+       raw_notifier_call_chain(&pvclock_gtod_chain, 0, tk);
+}
+
+/**
+ * pvclock_gtod_register_notifier - register a pvclock timedata update listener
+ *
+ * Must hold write on timekeeper.lock
+ */
+int pvclock_gtod_register_notifier(struct notifier_block *nb)
+{
+       struct timekeeper *tk = &timekeeper;
+       unsigned long flags;
+       int ret;
+
+       write_seqlock_irqsave(&tk->lock, flags);
+       ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb);
+       /* update timekeeping data */
+       update_pvclock_gtod(tk);
+       write_sequnlock_irqrestore(&tk->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pvclock_gtod_register_notifier);
+
+/**
+ * pvclock_gtod_unregister_notifier - unregister a pvclock
+ * timedata update listener
+ *
+ * Must hold write on timekeeper.lock
+ */
+int pvclock_gtod_unregister_notifier(struct notifier_block *nb)
+{
+       struct timekeeper *tk = &timekeeper;
+       unsigned long flags;
+       int ret;
+
+       write_seqlock_irqsave(&tk->lock, flags);
+       ret = raw_notifier_chain_unregister(&pvclock_gtod_chain, nb);
+       write_sequnlock_irqrestore(&tk->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier);
+
 /* must hold write on timekeeper.lock */
 static void timekeeping_update(struct timekeeper *tk, bool clearntp)
 {
@@ -182,6 +231,7 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp)
                ntp_clear();
        }
        update_vsyscall(tk);
+       update_pvclock_gtod(tk);
 }
 
 /**
index 7693aaf324c655d325b1739014c032aba76856b4..afd092de45b71c45a9b3be6b70ed8dc0db085a0a 100644 (file)
@@ -10,7 +10,7 @@
  * Based on code in the latency_tracer, that is:
  *
  *  Copyright (C) 2004-2006 Ingo Molnar
- *  Copyright (C) 2004 William Lee Irwin III
+ *  Copyright (C) 2004 Nadia Yvette Chambers
  */
 
 #include <linux/stop_machine.h>
index b69cc380322dbfe17983e582a9537d6e53e1ce7b..61e081b4ba1199c7c7da9f44c6b7f9fa9e87eeb2 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Based on code from the latency_tracer, that is:
  *  Copyright (C) 2004-2006 Ingo Molnar
- *  Copyright (C) 2004 William Lee Irwin III
+ *  Copyright (C) 2004 Nadia Yvette Chambers
  */
 #include <linux/ring_buffer.h>
 #include <generated/utsrelease.h>
index bb227e380cb574f9eb629b5ac162fcab8b34b1b3..8e3ad8082ab7074fde4ea9da403961afd2eadc45 100644 (file)
@@ -7,7 +7,7 @@
  * Based on code from the latency_tracer, that is:
  *
  *  Copyright (C) 2004-2006 Ingo Molnar
- *  Copyright (C) 2004 William Lee Irwin III
+ *  Copyright (C) 2004 Nadia Yvette Chambers
  */
 #include <linux/ring_buffer.h>
 #include <linux/debugfs.h>
index 5ffce7b0f33c71d5fae15d8ead377aded9d0fd88..713a2cac48816461c0c0a5b11d5a854ea5c4b3d3 100644 (file)
@@ -7,7 +7,7 @@
  * From code in the latency_tracer, that is:
  *
  *  Copyright (C) 2004-2006 Ingo Molnar
- *  Copyright (C) 2004 William Lee Irwin III
+ *  Copyright (C) 2004 Nadia Yvette Chambers
  */
 #include <linux/kallsyms.h>
 #include <linux/debugfs.h>
index bc64fc1375542415bb258f635226b76e056f1909..9fe45fcefca084b804b37d8a4f782fdafa87f1bb 100644 (file)
@@ -7,7 +7,7 @@
  * Based on code from the latency_tracer, that is:
  *
  *  Copyright (C) 2004-2006 Ingo Molnar
- *  Copyright (C) 2004 William Lee Irwin III
+ *  Copyright (C) 2004 Nadia Yvette Chambers
  */
 #include <linux/module.h>
 #include <linux/fs.h>
index 7fdd9eaca2c3a40ba08955b0cb9be5dd04e88f04..6698e0c04ead068279a7ed6a106a794b4ee1a8e6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Generic waiting primitives.
  *
- * (C) 2004 William Irwin, Oracle
+ * (C) 2004 Nadia Yvette Chambers, Oracle
  */
 #include <linux/init.h>
 #include <linux/export.h>
index 41faf0b8df1df9f2f5d9cb12eb01980526025ec4..e458782f3c52ac69f88d05d10233fd32b330a7fb 100644 (file)
@@ -1115,7 +1115,7 @@ config NOTIFIER_ERROR_INJECTION
        depends on DEBUG_KERNEL
        select DEBUG_FS
        help
-         This option provides the ability to inject artifical errors to
+         This option provides the ability to inject artificial errors to
          specified notifier chain callbacks. It is useful to test the error
          handling of notifier call chain failures.
 
@@ -1126,7 +1126,7 @@ config CPU_NOTIFIER_ERROR_INJECT
        depends on HOTPLUG_CPU && NOTIFIER_ERROR_INJECTION
        help
          This option provides a kernel module that can be used to test
-         the error handling of the cpu notifiers by injecting artifical
+         the error handling of the cpu notifiers by injecting artificial
          errors to CPU notifier chain callbacks.  It is controlled through
          debugfs interface under /sys/kernel/debug/notifier-error-inject/cpu
 
@@ -1150,7 +1150,7 @@ config PM_NOTIFIER_ERROR_INJECT
        depends on PM && NOTIFIER_ERROR_INJECTION
        default m if PM_DEBUG
        help
-         This option provides the ability to inject artifical errors to
+         This option provides the ability to inject artificial errors to
          PM notifier chain callbacks.  It is controlled through debugfs
          interface /sys/kernel/debug/notifier-error-inject/pm
 
@@ -1173,7 +1173,7 @@ config MEMORY_NOTIFIER_ERROR_INJECT
        tristate "Memory hotplug notifier error injection module"
        depends on MEMORY_HOTPLUG_SPARSE && NOTIFIER_ERROR_INJECTION
        help
-         This option provides the ability to inject artifical errors to
+         This option provides the ability to inject artificial errors to
          memory hotplug notifier chain callbacks.  It is controlled through
          debugfs interface under /sys/kernel/debug/notifier-error-inject/memory
 
@@ -1196,7 +1196,7 @@ config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT
        tristate "pSeries reconfig notifier error injection module"
        depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION
        help
-         This option provides the ability to inject artifical errors to
+         This option provides the ability to inject artificial errors to
          pSeries reconfig notifier chain callbacks.  It is controlled
          through debugfs interface under
          /sys/kernel/debug/notifier-error-inject/pSeries-reconfig/
index e3723c7527daa49c19b68c47b6c30136492a952f..e2152fa7ff4d9ddd970468f5cfe19f340284ff55 100644 (file)
@@ -12,7 +12,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
         idr.o int_sqrt.o extable.o \
         sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
         proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
-        is_single_threaded.o plist.o decompress.o kobject_uevent.o
+        is_single_threaded.o plist.o decompress.o kobject_uevent.o \
+        earlycpio.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
index 06fdfa1aeba712283c1e1d706424c1279abaf0ca..06f7e4fe8d2de4046a3139106058b9c831c9b789 100644 (file)
@@ -353,7 +353,7 @@ again:
 EXPORT_SYMBOL(bitmap_find_next_zero_area);
 
 /*
- * Bitmap printing & parsing functions: first version by Bill Irwin,
+ * Bitmap printing & parsing functions: first version by Nadia Yvette Chambers,
  * second version by Paul Jackson, third by Joe Korty.
  */
 
diff --git a/lib/earlycpio.c b/lib/earlycpio.c
new file mode 100644 (file)
index 0000000..8078ef4
--- /dev/null
@@ -0,0 +1,145 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2012 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available
+ *   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 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * earlycpio.c
+ *
+ * Find a specific cpio member; must precede any compressed content.
+ * This is used to locate data items in the initramfs used by the
+ * kernel itself during early boot (before the main initramfs is
+ * decompressed.)  It is the responsibility of the initramfs creator
+ * to ensure that these items are uncompressed at the head of the
+ * blob.  Depending on the boot loader or package tool that may be a
+ * separate file or part of the same file.
+ */
+
+#include <linux/earlycpio.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+enum cpio_fields {
+       C_MAGIC,
+       C_INO,
+       C_MODE,
+       C_UID,
+       C_GID,
+       C_NLINK,
+       C_MTIME,
+       C_FILESIZE,
+       C_MAJ,
+       C_MIN,
+       C_RMAJ,
+       C_RMIN,
+       C_NAMESIZE,
+       C_CHKSUM,
+       C_NFIELDS
+};
+
+/**
+ * cpio_data find_cpio_data - Search for files in an uncompressed cpio
+ * @path:   The directory to search for, including a slash at the end
+ * @data:   Pointer to the the cpio archive or a header inside
+ * @len:    Remaining length of the cpio based on data pointer
+ * @offset: When a matching file is found, this is the offset to the
+ *          beginning of the cpio. It can be used to iterate through
+ *          the cpio to find all files inside of a directory path
+ *
+ * @return: struct cpio_data containing the address, length and
+ *          filename (with the directory path cut off) of the found file.
+ *          If you search for a filename and not for files in a directory,
+ *          pass the absolute path of the filename in the cpio and make sure
+ *          the match returned an empty filename string.
+ */
+
+struct cpio_data __cpuinit find_cpio_data(const char *path, void *data,
+                                         size_t len,  long *offset)
+{
+       const size_t cpio_header_len = 8*C_NFIELDS - 2;
+       struct cpio_data cd = { NULL, 0, "" };
+       const char *p, *dptr, *nptr;
+       unsigned int ch[C_NFIELDS], *chp, v;
+       unsigned char c, x;
+       size_t mypathsize = strlen(path);
+       int i, j;
+
+       p = data;
+
+       while (len > cpio_header_len) {
+               if (!*p) {
+                       /* All cpio headers need to be 4-byte aligned */
+                       p += 4;
+                       len -= 4;
+                       continue;
+               }
+
+               j = 6;          /* The magic field is only 6 characters */
+               chp = ch;
+               for (i = C_NFIELDS; i; i--) {
+                       v = 0;
+                       while (j--) {
+                               v <<= 4;
+                               c = *p++;
+
+                               x = c - '0';
+                               if (x < 10) {
+                                       v += x;
+                                       continue;
+                               }
+
+                               x = (c | 0x20) - 'a';
+                               if (x < 6) {
+                                       v += x + 10;
+                                       continue;
+                               }
+
+                               goto quit; /* Invalid hexadecimal */
+                       }
+                       *chp++ = v;
+                       j = 8;  /* All other fields are 8 characters */
+               }
+
+               if ((ch[C_MAGIC] - 0x070701) > 1)
+                       goto quit; /* Invalid magic */
+
+               len -= cpio_header_len;
+
+               dptr = PTR_ALIGN(p + ch[C_NAMESIZE], 4);
+               nptr = PTR_ALIGN(dptr + ch[C_FILESIZE], 4);
+
+               if (nptr > p + len || dptr < p || nptr < dptr)
+                       goto quit; /* Buffer overrun */
+
+               if ((ch[C_MODE] & 0170000) == 0100000 &&
+                   ch[C_NAMESIZE] >= mypathsize &&
+                   !memcmp(p, path, mypathsize)) {
+                       *offset = (long)nptr - (long)data;
+                       if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
+                               pr_warn(
+                               "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
+                               p, MAX_CPIO_FILE_NAME);
+                       }
+                       strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
+
+                       cd.data = (void *)dptr;
+                       cd.size = ch[C_FILESIZE];
+                       return cd; /* Found it! */
+               }
+               len -= (nptr - p);
+               p = nptr;
+       }
+
+quit:
+       return cd;
+}
index e6651c5de14f4e42a0b6455e0d0b0859f06c2680..71259e052ce8c516fccf135ffa994354729a142a 100644 (file)
@@ -143,6 +143,14 @@ config NO_BOOTMEM
 config MEMORY_ISOLATION
        boolean
 
+config MOVABLE_NODE
+       boolean "Enable to assign a node which has only movable memory"
+       depends on HAVE_MEMBLOCK
+       depends on NO_BOOTMEM
+       depends on X86_64
+       depends on NUMA
+       depends on BROKEN
+
 # eventually, we can have this option just 'select SPARSEMEM'
 config MEMORY_HOTPLUG
        bool "Allow for memory hot-add"
index ecc45958ac0c5d3527b84f7eeddad3e51627f55f..1324cd74faec45dc2b0ba4f0b3fb0659640e9f25 100644 (file)
@@ -229,6 +229,22 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        return count;
 }
 
+static void reset_node_lowmem_managed_pages(pg_data_t *pgdat)
+{
+       struct zone *z;
+
+       /*
+        * In free_area_init_core(), highmem zone's managed_pages is set to
+        * present_pages, and bootmem allocator doesn't allocate from highmem
+        * zones. So there's no need to recalculate managed_pages because all
+        * highmem pages will be managed by the buddy system. Here highmem
+        * zone also includes highmem movable zone.
+        */
+       for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+               if (!is_highmem(z))
+                       z->managed_pages = 0;
+}
+
 /**
  * free_all_bootmem_node - release a node's free pages to the buddy allocator
  * @pgdat: node to be released
@@ -238,6 +254,7 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
        register_page_bootmem_info_node(pgdat);
+       reset_node_lowmem_managed_pages(pgdat);
        return free_all_bootmem_core(pgdat->bdata);
 }
 
@@ -250,6 +267,10 @@ unsigned long __init free_all_bootmem(void)
 {
        unsigned long total_pages = 0;
        bootmem_data_t *bdata;
+       struct pglist_data *pgdat;
+
+       for_each_online_pgdat(pgdat)
+               reset_node_lowmem_managed_pages(pgdat);
 
        list_for_each_entry(bdata, &bdata_list, list)
                total_pages += free_all_bootmem_core(bdata);
@@ -439,12 +460,6 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size,
        return mark_bootmem(start, end, 1, flags);
 }
 
-int __weak __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
-                                  int flags)
-{
-       return reserve_bootmem(phys, len, flags);
-}
-
 static unsigned long __init align_idx(struct bootmem_data *bdata,
                                      unsigned long idx, unsigned long step)
 {
@@ -575,27 +590,6 @@ find_block:
        return NULL;
 }
 
-static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata,
-                                       unsigned long size, unsigned long align,
-                                       unsigned long goal, unsigned long limit)
-{
-       if (WARN_ON_ONCE(slab_is_available()))
-               return kzalloc(size, GFP_NOWAIT);
-
-#ifdef CONFIG_HAVE_ARCH_BOOTMEM
-       {
-               bootmem_data_t *p_bdata;
-
-               p_bdata = bootmem_arch_preferred_node(bdata, size, align,
-                                                       goal, limit);
-               if (p_bdata)
-                       return alloc_bootmem_bdata(p_bdata, size, align,
-                                                       goal, limit);
-       }
-#endif
-       return NULL;
-}
-
 static void * __init alloc_bootmem_core(unsigned long size,
                                        unsigned long align,
                                        unsigned long goal,
@@ -604,9 +598,8 @@ static void * __init alloc_bootmem_core(unsigned long size,
        bootmem_data_t *bdata;
        void *region;
 
-       region = alloc_arch_preferred_bootmem(NULL, size, align, goal, limit);
-       if (region)
-               return region;
+       if (WARN_ON_ONCE(slab_is_available()))
+               return kzalloc(size, GFP_NOWAIT);
 
        list_for_each_entry(bdata, &bdata_list, list) {
                if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
@@ -704,11 +697,9 @@ void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
 {
        void *ptr;
 
+       if (WARN_ON_ONCE(slab_is_available()))
+               return kzalloc(size, GFP_NOWAIT);
 again:
-       ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size,
-                                          align, goal, limit);
-       if (ptr)
-               return ptr;
 
        /* do not panic in alloc_bootmem_bdata() */
        if (limit && goal + size > limit)
index d24dd2d7bad407140c4b0e6fe514a0cb187bbcc8..1297912182269c979a60296fca64a7a01e1e95ca 100644 (file)
@@ -215,60 +215,6 @@ static bool suitable_migration_target(struct page *page)
        return false;
 }
 
-static void compact_capture_page(struct compact_control *cc)
-{
-       unsigned long flags;
-       int mtype, mtype_low, mtype_high;
-
-       if (!cc->page || *cc->page)
-               return;
-
-       /*
-        * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
-        * regardless of the migratetype of the freelist is is captured from.
-        * This is fine because the order for a high-order MIGRATE_MOVABLE
-        * allocation is typically at least a pageblock size and overall
-        * fragmentation is not impaired. Other allocation types must
-        * capture pages from their own migratelist because otherwise they
-        * could pollute other pageblocks like MIGRATE_MOVABLE with
-        * difficult to move pages and making fragmentation worse overall.
-        */
-       if (cc->migratetype == MIGRATE_MOVABLE) {
-               mtype_low = 0;
-               mtype_high = MIGRATE_PCPTYPES;
-       } else {
-               mtype_low = cc->migratetype;
-               mtype_high = cc->migratetype + 1;
-       }
-
-       /* Speculatively examine the free lists without zone lock */
-       for (mtype = mtype_low; mtype < mtype_high; mtype++) {
-               int order;
-               for (order = cc->order; order < MAX_ORDER; order++) {
-                       struct page *page;
-                       struct free_area *area;
-                       area = &(cc->zone->free_area[order]);
-                       if (list_empty(&area->free_list[mtype]))
-                               continue;
-
-                       /* Take the lock and attempt capture of the page */
-                       if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
-                               return;
-                       if (!list_empty(&area->free_list[mtype])) {
-                               page = list_entry(area->free_list[mtype].next,
-                                                       struct page, lru);
-                               if (capture_free_page(page, cc->order, mtype)) {
-                                       spin_unlock_irqrestore(&cc->zone->lock,
-                                                                       flags);
-                                       *cc->page = page;
-                                       return;
-                               }
-                       }
-                       spin_unlock_irqrestore(&cc->zone->lock, flags);
-               }
-       }
-}
-
 /*
  * Isolate free pages onto a private freelist. Caller must hold zone->lock.
  * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
@@ -953,6 +899,60 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        return COMPACT_CONTINUE;
 }
 
+static void compact_capture_page(struct compact_control *cc)
+{
+       unsigned long flags;
+       int mtype, mtype_low, mtype_high;
+
+       if (!cc->page || *cc->page)
+               return;
+
+       /*
+        * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
+        * regardless of the migratetype of the freelist is is captured from.
+        * This is fine because the order for a high-order MIGRATE_MOVABLE
+        * allocation is typically at least a pageblock size and overall
+        * fragmentation is not impaired. Other allocation types must
+        * capture pages from their own migratelist because otherwise they
+        * could pollute other pageblocks like MIGRATE_MOVABLE with
+        * difficult to move pages and making fragmentation worse overall.
+        */
+       if (cc->migratetype == MIGRATE_MOVABLE) {
+               mtype_low = 0;
+               mtype_high = MIGRATE_PCPTYPES;
+       } else {
+               mtype_low = cc->migratetype;
+               mtype_high = cc->migratetype + 1;
+       }
+
+       /* Speculatively examine the free lists without zone lock */
+       for (mtype = mtype_low; mtype < mtype_high; mtype++) {
+               int order;
+               for (order = cc->order; order < MAX_ORDER; order++) {
+                       struct page *page;
+                       struct free_area *area;
+                       area = &(cc->zone->free_area[order]);
+                       if (list_empty(&area->free_list[mtype]))
+                               continue;
+
+                       /* Take the lock and attempt capture of the page */
+                       if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
+                               return;
+                       if (!list_empty(&area->free_list[mtype])) {
+                               page = list_entry(area->free_list[mtype].next,
+                                                       struct page, lru);
+                               if (capture_free_page(page, cc->order, mtype)) {
+                                       spin_unlock_irqrestore(&cc->zone->lock,
+                                                                       flags);
+                                       *cc->page = page;
+                                       return;
+                               }
+                       }
+                       spin_unlock_irqrestore(&cc->zone->lock, flags);
+               }
+       }
+}
+
 static int compact_zone(struct zone *zone, struct compact_control *cc)
 {
        int ret;
index 5f902e20e8c03eb70cd11d569e36a8697ed5d28a..827d9c81305115d4d3b0b4c22dfadf2fc20d2a10 100644 (file)
 #include <linux/mmu_notifier.h>
 #include <linux/rmap.h>
 #include <linux/swap.h>
+#include <linux/shrinker.h>
 #include <linux/mm_inline.h>
 #include <linux/kthread.h>
 #include <linux/khugepaged.h>
 #include <linux/freezer.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
+
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
 #include "internal.h"
@@ -37,7 +39,8 @@ unsigned long transparent_hugepage_flags __read_mostly =
        (1<<TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG)|
 #endif
        (1<<TRANSPARENT_HUGEPAGE_DEFRAG_FLAG)|
-       (1<<TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG);
+       (1<<TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG)|
+       (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
 
 /* default scan 8*512 pte (or vmas) every 30 second */
 static unsigned int khugepaged_pages_to_scan __read_mostly = HPAGE_PMD_NR*8;
@@ -159,6 +162,77 @@ static int start_khugepaged(void)
        return err;
 }
 
+static atomic_t huge_zero_refcount;
+static unsigned long huge_zero_pfn __read_mostly;
+
+static inline bool is_huge_zero_pfn(unsigned long pfn)
+{
+       unsigned long zero_pfn = ACCESS_ONCE(huge_zero_pfn);
+       return zero_pfn && pfn == zero_pfn;
+}
+
+static inline bool is_huge_zero_pmd(pmd_t pmd)
+{
+       return is_huge_zero_pfn(pmd_pfn(pmd));
+}
+
+static unsigned long get_huge_zero_page(void)
+{
+       struct page *zero_page;
+retry:
+       if (likely(atomic_inc_not_zero(&huge_zero_refcount)))
+               return ACCESS_ONCE(huge_zero_pfn);
+
+       zero_page = alloc_pages((GFP_TRANSHUGE | __GFP_ZERO) & ~__GFP_MOVABLE,
+                       HPAGE_PMD_ORDER);
+       if (!zero_page) {
+               count_vm_event(THP_ZERO_PAGE_ALLOC_FAILED);
+               return 0;
+       }
+       count_vm_event(THP_ZERO_PAGE_ALLOC);
+       preempt_disable();
+       if (cmpxchg(&huge_zero_pfn, 0, page_to_pfn(zero_page))) {
+               preempt_enable();
+               __free_page(zero_page);
+               goto retry;
+       }
+
+       /* We take additional reference here. It will be put back by shrinker */
+       atomic_set(&huge_zero_refcount, 2);
+       preempt_enable();
+       return ACCESS_ONCE(huge_zero_pfn);
+}
+
+static void put_huge_zero_page(void)
+{
+       /*
+        * Counter should never go to zero here. Only shrinker can put
+        * last reference.
+        */
+       BUG_ON(atomic_dec_and_test(&huge_zero_refcount));
+}
+
+static int shrink_huge_zero_page(struct shrinker *shrink,
+               struct shrink_control *sc)
+{
+       if (!sc->nr_to_scan)
+               /* we can free zero page only if last reference remains */
+               return atomic_read(&huge_zero_refcount) == 1 ? HPAGE_PMD_NR : 0;
+
+       if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) {
+               unsigned long zero_pfn = xchg(&huge_zero_pfn, 0);
+               BUG_ON(zero_pfn == 0);
+               __free_page(__pfn_to_page(zero_pfn));
+       }
+
+       return 0;
+}
+
+static struct shrinker huge_zero_page_shrinker = {
+       .shrink = shrink_huge_zero_page,
+       .seeks = DEFAULT_SEEKS,
+};
+
 #ifdef CONFIG_SYSFS
 
 static ssize_t double_flag_show(struct kobject *kobj,
@@ -284,6 +358,20 @@ static ssize_t defrag_store(struct kobject *kobj,
 static struct kobj_attribute defrag_attr =
        __ATTR(defrag, 0644, defrag_show, defrag_store);
 
+static ssize_t use_zero_page_show(struct kobject *kobj,
+               struct kobj_attribute *attr, char *buf)
+{
+       return single_flag_show(kobj, attr, buf,
+                               TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
+}
+static ssize_t use_zero_page_store(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       return single_flag_store(kobj, attr, buf, count,
+                                TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
+}
+static struct kobj_attribute use_zero_page_attr =
+       __ATTR(use_zero_page, 0644, use_zero_page_show, use_zero_page_store);
 #ifdef CONFIG_DEBUG_VM
 static ssize_t debug_cow_show(struct kobject *kobj,
                                struct kobj_attribute *attr, char *buf)
@@ -305,6 +393,7 @@ static struct kobj_attribute debug_cow_attr =
 static struct attribute *hugepage_attr[] = {
        &enabled_attr.attr,
        &defrag_attr.attr,
+       &use_zero_page_attr.attr,
 #ifdef CONFIG_DEBUG_VM
        &debug_cow_attr.attr,
 #endif
@@ -550,6 +639,8 @@ static int __init hugepage_init(void)
                goto out;
        }
 
+       register_shrinker(&huge_zero_page_shrinker);
+
        /*
         * By default disable transparent hugepages on smaller systems,
         * where the extra memory used could hurt more than TLB overhead
@@ -678,6 +769,22 @@ static inline struct page *alloc_hugepage(int defrag)
 }
 #endif
 
+static bool set_huge_zero_page(pgtable_t pgtable, struct mm_struct *mm,
+               struct vm_area_struct *vma, unsigned long haddr, pmd_t *pmd,
+               unsigned long zero_pfn)
+{
+       pmd_t entry;
+       if (!pmd_none(*pmd))
+               return false;
+       entry = pfn_pmd(zero_pfn, vma->vm_page_prot);
+       entry = pmd_wrprotect(entry);
+       entry = pmd_mkhuge(entry);
+       set_pmd_at(mm, haddr, pmd, entry);
+       pgtable_trans_huge_deposit(mm, pgtable);
+       mm->nr_ptes++;
+       return true;
+}
+
 int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
                               unsigned long address, pmd_t *pmd,
                               unsigned int flags)
@@ -691,6 +798,30 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        return VM_FAULT_OOM;
                if (unlikely(khugepaged_enter(vma)))
                        return VM_FAULT_OOM;
+               if (!(flags & FAULT_FLAG_WRITE) &&
+                               transparent_hugepage_use_zero_page()) {
+                       pgtable_t pgtable;
+                       unsigned long zero_pfn;
+                       bool set;
+                       pgtable = pte_alloc_one(mm, haddr);
+                       if (unlikely(!pgtable))
+                               return VM_FAULT_OOM;
+                       zero_pfn = get_huge_zero_page();
+                       if (unlikely(!zero_pfn)) {
+                               pte_free(mm, pgtable);
+                               count_vm_event(THP_FAULT_FALLBACK);
+                               goto out;
+                       }
+                       spin_lock(&mm->page_table_lock);
+                       set = set_huge_zero_page(pgtable, mm, vma, haddr, pmd,
+                                       zero_pfn);
+                       spin_unlock(&mm->page_table_lock);
+                       if (!set) {
+                               pte_free(mm, pgtable);
+                               put_huge_zero_page();
+                       }
+                       return 0;
+               }
                page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
                                          vma, haddr, numa_node_id(), 0);
                if (unlikely(!page)) {
@@ -755,6 +886,26 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                pte_free(dst_mm, pgtable);
                goto out_unlock;
        }
+       /*
+        * mm->page_table_lock is enough to be sure that huge zero pmd is not
+        * under splitting since we don't split the page itself, only pmd to
+        * a page table.
+        */
+       if (is_huge_zero_pmd(pmd)) {
+               unsigned long zero_pfn;
+               bool set;
+               /*
+                * get_huge_zero_page() will never allocate a new page here,
+                * since we already have a zero page to copy. It just takes a
+                * reference.
+                */
+               zero_pfn = get_huge_zero_page();
+               set = set_huge_zero_page(pgtable, dst_mm, vma, addr, dst_pmd,
+                               zero_pfn);
+               BUG_ON(!set); /* unexpected !pmd_none(dst_pmd) */
+               ret = 0;
+               goto out_unlock;
+       }
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(&src_mm->page_table_lock);
@@ -806,6 +957,80 @@ unlock:
        spin_unlock(&mm->page_table_lock);
 }
 
+static int do_huge_pmd_wp_zero_page_fallback(struct mm_struct *mm,
+               struct vm_area_struct *vma, unsigned long address,
+               pmd_t *pmd, pmd_t orig_pmd, unsigned long haddr)
+{
+       pgtable_t pgtable;
+       pmd_t _pmd;
+       struct page *page;
+       int i, ret = 0;
+       unsigned long mmun_start;       /* For mmu_notifiers */
+       unsigned long mmun_end;         /* For mmu_notifiers */
+
+       page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
+       if (!page) {
+               ret |= VM_FAULT_OOM;
+               goto out;
+       }
+
+       if (mem_cgroup_newpage_charge(page, mm, GFP_KERNEL)) {
+               put_page(page);
+               ret |= VM_FAULT_OOM;
+               goto out;
+       }
+
+       clear_user_highpage(page, address);
+       __SetPageUptodate(page);
+
+       mmun_start = haddr;
+       mmun_end   = haddr + HPAGE_PMD_SIZE;
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+
+       spin_lock(&mm->page_table_lock);
+       if (unlikely(!pmd_same(*pmd, orig_pmd)))
+               goto out_free_page;
+
+       pmdp_clear_flush(vma, haddr, pmd);
+       /* leave pmd empty until pte is filled */
+
+       pgtable = pgtable_trans_huge_withdraw(mm);
+       pmd_populate(mm, &_pmd, pgtable);
+
+       for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+               pte_t *pte, entry;
+               if (haddr == (address & PAGE_MASK)) {
+                       entry = mk_pte(page, vma->vm_page_prot);
+                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+                       page_add_new_anon_rmap(page, vma, haddr);
+               } else {
+                       entry = pfn_pte(my_zero_pfn(haddr), vma->vm_page_prot);
+                       entry = pte_mkspecial(entry);
+               }
+               pte = pte_offset_map(&_pmd, haddr);
+               VM_BUG_ON(!pte_none(*pte));
+               set_pte_at(mm, haddr, pte, entry);
+               pte_unmap(pte);
+       }
+       smp_wmb(); /* make pte visible before pmd */
+       pmd_populate(mm, pmd, pgtable);
+       spin_unlock(&mm->page_table_lock);
+       put_huge_zero_page();
+       inc_mm_counter(mm, MM_ANONPAGES);
+
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+
+       ret |= VM_FAULT_WRITE;
+out:
+       return ret;
+out_free_page:
+       spin_unlock(&mm->page_table_lock);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mem_cgroup_uncharge_page(page);
+       put_page(page);
+       goto out;
+}
+
 static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm,
                                        struct vm_area_struct *vma,
                                        unsigned long address,
@@ -912,19 +1137,21 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, pmd_t *pmd, pmd_t orig_pmd)
 {
        int ret = 0;
-       struct page *page, *new_page;
+       struct page *page = NULL, *new_page;
        unsigned long haddr;
        unsigned long mmun_start;       /* For mmu_notifiers */
        unsigned long mmun_end;         /* For mmu_notifiers */
 
        VM_BUG_ON(!vma->anon_vma);
+       haddr = address & HPAGE_PMD_MASK;
+       if (is_huge_zero_pmd(orig_pmd))
+               goto alloc;
        spin_lock(&mm->page_table_lock);
        if (unlikely(!pmd_same(*pmd, orig_pmd)))
                goto out_unlock;
 
        page = pmd_page(orig_pmd);
        VM_BUG_ON(!PageCompound(page) || !PageHead(page));
-       haddr = address & HPAGE_PMD_MASK;
        if (page_mapcount(page) == 1) {
                pmd_t entry;
                entry = pmd_mkyoung(orig_pmd);
@@ -936,7 +1163,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        }
        get_page(page);
        spin_unlock(&mm->page_table_lock);
-
+alloc:
        if (transparent_hugepage_enabled(vma) &&
            !transparent_hugepage_debug_cow())
                new_page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
@@ -946,24 +1173,34 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
        if (unlikely(!new_page)) {
                count_vm_event(THP_FAULT_FALLBACK);
-               ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
-                                                  pmd, orig_pmd, page, haddr);
-               if (ret & VM_FAULT_OOM)
-                       split_huge_page(page);
-               put_page(page);
+               if (is_huge_zero_pmd(orig_pmd)) {
+                       ret = do_huge_pmd_wp_zero_page_fallback(mm, vma,
+                                       address, pmd, orig_pmd, haddr);
+               } else {
+                       ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
+                                       pmd, orig_pmd, page, haddr);
+                       if (ret & VM_FAULT_OOM)
+                               split_huge_page(page);
+                       put_page(page);
+               }
                goto out;
        }
        count_vm_event(THP_FAULT_ALLOC);
 
        if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) {
                put_page(new_page);
-               split_huge_page(page);
-               put_page(page);
+               if (page) {
+                       split_huge_page(page);
+                       put_page(page);
+               }
                ret |= VM_FAULT_OOM;
                goto out;
        }
 
-       copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
+       if (is_huge_zero_pmd(orig_pmd))
+               clear_huge_page(new_page, haddr, HPAGE_PMD_NR);
+       else
+               copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
        __SetPageUptodate(new_page);
 
        mmun_start = haddr;
@@ -971,7 +1208,8 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
        spin_lock(&mm->page_table_lock);
-       put_page(page);
+       if (page)
+               put_page(page);
        if (unlikely(!pmd_same(*pmd, orig_pmd))) {
                spin_unlock(&mm->page_table_lock);
                mem_cgroup_uncharge_page(new_page);
@@ -979,14 +1217,19 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out_mn;
        } else {
                pmd_t entry;
-               VM_BUG_ON(!PageHead(page));
                entry = mk_huge_pmd(new_page, vma);
                pmdp_clear_flush(vma, haddr, pmd);
                page_add_new_anon_rmap(new_page, vma, haddr);
                set_pmd_at(mm, haddr, pmd, entry);
                update_mmu_cache_pmd(vma, address, pmd);
-               page_remove_rmap(page);
-               put_page(page);
+               if (is_huge_zero_pmd(orig_pmd)) {
+                       add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
+                       put_huge_zero_page();
+               } else {
+                       VM_BUG_ON(!PageHead(page));
+                       page_remove_rmap(page);
+                       put_page(page);
+               }
                ret |= VM_FAULT_WRITE;
        }
        spin_unlock(&mm->page_table_lock);
@@ -1055,15 +1298,21 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
                pmd_t orig_pmd;
                pgtable = pgtable_trans_huge_withdraw(tlb->mm);
                orig_pmd = pmdp_get_and_clear(tlb->mm, addr, pmd);
-               page = pmd_page(orig_pmd);
                tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
-               page_remove_rmap(page);
-               VM_BUG_ON(page_mapcount(page) < 0);
-               add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
-               VM_BUG_ON(!PageHead(page));
-               tlb->mm->nr_ptes--;
-               spin_unlock(&tlb->mm->page_table_lock);
-               tlb_remove_page(tlb, page);
+               if (is_huge_zero_pmd(orig_pmd)) {
+                       tlb->mm->nr_ptes--;
+                       spin_unlock(&tlb->mm->page_table_lock);
+                       put_huge_zero_page();
+               } else {
+                       page = pmd_page(orig_pmd);
+                       page_remove_rmap(page);
+                       VM_BUG_ON(page_mapcount(page) < 0);
+                       add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
+                       VM_BUG_ON(!PageHead(page));
+                       tlb->mm->nr_ptes--;
+                       spin_unlock(&tlb->mm->page_table_lock);
+                       tlb_remove_page(tlb, page);
+               }
                pte_free(tlb->mm, pgtable);
                ret = 1;
        }
@@ -1135,6 +1384,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                pmd_t entry;
                entry = pmdp_get_and_clear(mm, addr, pmd);
                entry = pmd_modify(entry, newprot);
+               BUG_ON(pmd_write(entry));
                set_pmd_at(mm, addr, pmd, entry);
                spin_unlock(&vma->vm_mm->page_table_lock);
                ret = 1;
@@ -1477,6 +1727,7 @@ int split_huge_page(struct page *page)
        struct anon_vma *anon_vma;
        int ret = 1;
 
+       BUG_ON(is_huge_zero_pfn(page_to_pfn(page)));
        BUG_ON(!PageAnon(page));
        anon_vma = page_lock_anon_vma(page);
        if (!anon_vma)
@@ -2336,19 +2587,65 @@ static int khugepaged(void *none)
        return 0;
 }
 
-void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd)
+static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
+               unsigned long haddr, pmd_t *pmd)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       pgtable_t pgtable;
+       pmd_t _pmd;
+       int i;
+
+       pmdp_clear_flush(vma, haddr, pmd);
+       /* leave pmd empty until pte is filled */
+
+       pgtable = pgtable_trans_huge_withdraw(mm);
+       pmd_populate(mm, &_pmd, pgtable);
+
+       for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+               pte_t *pte, entry;
+               entry = pfn_pte(my_zero_pfn(haddr), vma->vm_page_prot);
+               entry = pte_mkspecial(entry);
+               pte = pte_offset_map(&_pmd, haddr);
+               VM_BUG_ON(!pte_none(*pte));
+               set_pte_at(mm, haddr, pte, entry);
+               pte_unmap(pte);
+       }
+       smp_wmb(); /* make pte visible before pmd */
+       pmd_populate(mm, pmd, pgtable);
+       put_huge_zero_page();
+}
+
+void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address,
+               pmd_t *pmd)
 {
        struct page *page;
+       struct mm_struct *mm = vma->vm_mm;
+       unsigned long haddr = address & HPAGE_PMD_MASK;
+       unsigned long mmun_start;       /* For mmu_notifiers */
+       unsigned long mmun_end;         /* For mmu_notifiers */
+
+       BUG_ON(vma->vm_start > haddr || vma->vm_end < haddr + HPAGE_PMD_SIZE);
 
+       mmun_start = haddr;
+       mmun_end   = haddr + HPAGE_PMD_SIZE;
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        spin_lock(&mm->page_table_lock);
        if (unlikely(!pmd_trans_huge(*pmd))) {
                spin_unlock(&mm->page_table_lock);
+               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+               return;
+       }
+       if (is_huge_zero_pmd(*pmd)) {
+               __split_huge_zero_page_pmd(vma, haddr, pmd);
+               spin_unlock(&mm->page_table_lock);
+               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
                return;
        }
        page = pmd_page(*pmd);
        VM_BUG_ON(!page_count(page));
        get_page(page);
        spin_unlock(&mm->page_table_lock);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
        split_huge_page(page);
 
@@ -2356,6 +2653,16 @@ void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd)
        BUG_ON(pmd_trans_huge(*pmd));
 }
 
+void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
+               pmd_t *pmd)
+{
+       struct vm_area_struct *vma;
+
+       vma = find_vma(mm, address);
+       BUG_ON(vma == NULL);
+       split_huge_page_pmd(vma, address, pmd);
+}
+
 static void split_huge_page_address(struct mm_struct *mm,
                                    unsigned long address)
 {
@@ -2370,7 +2677,7 @@ static void split_huge_page_address(struct mm_struct *mm,
         * Caller holds the mmap_sem write mode, so a huge pmd cannot
         * materialize from under us.
         */
-       split_huge_page_pmd(mm, pmd);
+       split_huge_page_pmd_mm(mm, address, pmd);
 }
 
 void __vma_adjust_trans_huge(struct vm_area_struct *vma,
index 1ef2cd4ae3c98229ffe9a244985c4c49da3fbb00..88e7293b96bd74df334c6a15b88e55e2de53c446 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generic hugetlb support.
- * (C) William Irwin, April 2004
+ * (C) Nadia Yvette Chambers, April 2004
  */
 #include <linux/list.h>
 #include <linux/init.h>
@@ -1057,7 +1057,7 @@ static void return_unused_surplus_pages(struct hstate *h,
         * on-line nodes with memory and will handle the hstate accounting.
         */
        while (nr_pages--) {
-               if (!free_pool_huge_page(h, &node_states[N_HIGH_MEMORY], 1))
+               if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
                        break;
        }
 }
@@ -1180,14 +1180,14 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
 int __weak alloc_bootmem_huge_page(struct hstate *h)
 {
        struct huge_bootmem_page *m;
-       int nr_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
+       int nr_nodes = nodes_weight(node_states[N_MEMORY]);
 
        while (nr_nodes) {
                void *addr;
 
                addr = __alloc_bootmem_node_nopanic(
                                NODE_DATA(hstate_next_node_to_alloc(h,
-                                               &node_states[N_HIGH_MEMORY])),
+                                               &node_states[N_MEMORY])),
                                huge_page_size(h), huge_page_size(h), 0);
 
                if (addr) {
@@ -1259,7 +1259,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h)
                        if (!alloc_bootmem_huge_page(h))
                                break;
                } else if (!alloc_fresh_huge_page(h,
-                                        &node_states[N_HIGH_MEMORY]))
+                                        &node_states[N_MEMORY]))
                        break;
        }
        h->max_huge_pages = i;
@@ -1527,7 +1527,7 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
                if (!(obey_mempolicy &&
                                init_nodemask_of_mempolicy(nodes_allowed))) {
                        NODEMASK_FREE(nodes_allowed);
-                       nodes_allowed = &node_states[N_HIGH_MEMORY];
+                       nodes_allowed = &node_states[N_MEMORY];
                }
        } else if (nodes_allowed) {
                /*
@@ -1537,11 +1537,11 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
                count += h->nr_huge_pages - h->nr_huge_pages_node[nid];
                init_nodemask_of_node(nodes_allowed, nid);
        } else
-               nodes_allowed = &node_states[N_HIGH_MEMORY];
+               nodes_allowed = &node_states[N_MEMORY];
 
        h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed);
 
-       if (nodes_allowed != &node_states[N_HIGH_MEMORY])
+       if (nodes_allowed != &node_states[N_MEMORY])
                NODEMASK_FREE(nodes_allowed);
 
        return len;
@@ -1844,7 +1844,7 @@ static void hugetlb_register_all_nodes(void)
 {
        int nid;
 
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                struct node *node = node_devices[nid];
                if (node->dev.id == nid)
                        hugetlb_register_node(node);
@@ -1939,8 +1939,8 @@ void __init hugetlb_add_hstate(unsigned order)
        for (i = 0; i < MAX_NUMNODES; ++i)
                INIT_LIST_HEAD(&h->hugepage_freelists[i]);
        INIT_LIST_HEAD(&h->hugepage_activelist);
-       h->next_nid_to_alloc = first_node(node_states[N_HIGH_MEMORY]);
-       h->next_nid_to_free = first_node(node_states[N_HIGH_MEMORY]);
+       h->next_nid_to_alloc = first_node(node_states[N_MEMORY]);
+       h->next_nid_to_free = first_node(node_states[N_MEMORY]);
        snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB",
                                        huge_page_size(h)/1024);
        /*
@@ -2035,11 +2035,11 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
                if (!(obey_mempolicy &&
                               init_nodemask_of_mempolicy(nodes_allowed))) {
                        NODEMASK_FREE(nodes_allowed);
-                       nodes_allowed = &node_states[N_HIGH_MEMORY];
+                       nodes_allowed = &node_states[N_MEMORY];
                }
                h->max_huge_pages = set_max_huge_pages(h, tmp, nodes_allowed);
 
-               if (nodes_allowed != &node_states[N_HIGH_MEMORY])
+               if (nodes_allowed != &node_states[N_MEMORY])
                        NODEMASK_FREE(nodes_allowed);
        }
 out:
@@ -2386,8 +2386,10 @@ again:
                /*
                 * HWPoisoned hugepage is already unmapped and dropped reference
                 */
-               if (unlikely(is_hugetlb_entry_hwpoisoned(pte)))
+               if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
+                       pte_clear(mm, address, ptep);
                        continue;
+               }
 
                page = pte_page(pte);
                /*
@@ -3170,7 +3172,13 @@ int dequeue_hwpoisoned_huge_page(struct page *hpage)
 
        spin_lock(&hugetlb_lock);
        if (is_hugepage_on_freelist(hpage)) {
-               list_del(&hpage->lru);
+               /*
+                * Hwpoisoned hugepage isn't linked to activelist or freelist,
+                * but dangling hpage->lru can trigger list-debug warnings
+                * (this happens when we call unpoison_memory() on it),
+                * so let it point to itself with list_del_init().
+                */
+               list_del_init(&hpage->lru);
                set_page_refcounted(hpage);
                h->free_huge_pages--;
                h->free_huge_pages_node[nid]--;
index 12307b3838fb37c37bda30c913b7ef6ea0a39734..6c055929c8cc3250f895ca7e264fdeb0a8d4a934 100644 (file)
@@ -59,6 +59,8 @@
 #include <trace/events/vmscan.h>
 
 struct cgroup_subsys mem_cgroup_subsys __read_mostly;
+EXPORT_SYMBOL(mem_cgroup_subsys);
+
 #define MEM_CGROUP_RECLAIM_RETRIES     5
 static struct mem_cgroup *root_mem_cgroup __read_mostly;
 
@@ -800,7 +802,7 @@ static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,
        int nid;
        u64 total = 0;
 
-       for_each_node_state(nid, N_HIGH_MEMORY)
+       for_each_node_state(nid, N_MEMORY)
                total += mem_cgroup_node_nr_lru_pages(memcg, nid, lru_mask);
        return total;
 }
@@ -1015,13 +1017,10 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
             iter != NULL;                              \
             iter = mem_cgroup_iter(NULL, iter, NULL))
 
-void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
+void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 {
        struct mem_cgroup *memcg;
 
-       if (!mm)
-               return;
-
        rcu_read_lock();
        memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
        if (unlikely(!memcg))
@@ -1040,7 +1039,7 @@ void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 out:
        rcu_read_unlock();
 }
-EXPORT_SYMBOL(mem_cgroup_count_vm_event);
+EXPORT_SYMBOL(__mem_cgroup_count_vm_event);
 
 /**
  * mem_cgroup_zone_lruvec - get the lru list vector for a zone and memcg
@@ -1644,9 +1643,9 @@ static void mem_cgroup_may_update_nodemask(struct mem_cgroup *memcg)
                return;
 
        /* make a nodemask where this memcg uses memory from */
-       memcg->scan_nodes = node_states[N_HIGH_MEMORY];
+       memcg->scan_nodes = node_states[N_MEMORY];
 
-       for_each_node_mask(nid, node_states[N_HIGH_MEMORY]) {
+       for_each_node_mask(nid, node_states[N_MEMORY]) {
 
                if (!test_mem_cgroup_node_reclaimable(memcg, nid, false))
                        node_clear(nid, memcg->scan_nodes);
@@ -1717,7 +1716,7 @@ static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
        /*
         * Check rest of nodes.
         */
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                if (node_isset(nid, memcg->scan_nodes))
                        continue;
                if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
@@ -3776,7 +3775,7 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)
                lru_add_drain_all();
                drain_all_stock_sync(memcg);
                mem_cgroup_start_move(memcg);
-               for_each_node_state(node, N_HIGH_MEMORY) {
+               for_each_node_state(node, N_MEMORY) {
                        for (zid = 0; zid < MAX_NR_ZONES; zid++) {
                                enum lru_list lru;
                                for_each_lru(lru) {
@@ -4122,7 +4121,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
        seq_printf(m, "total=%lu", total_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL);
                seq_printf(m, " N%d=%lu", nid, node_nr);
        }
@@ -4130,7 +4129,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        file_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_FILE);
        seq_printf(m, "file=%lu", file_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
                                LRU_ALL_FILE);
                seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4139,7 +4138,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        anon_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_ANON);
        seq_printf(m, "anon=%lu", anon_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
                                LRU_ALL_ANON);
                seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4148,7 +4147,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        unevictable_nr = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
        seq_printf(m, "unevictable=%lu", unevictable_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
                                BIT(LRU_UNEVICTABLE));
                seq_printf(m, " N%d=%lu", nid, node_nr);
index 765377385632086e872058cb46fe7958dadd472f..db2e9e797a05fc67684ef735ff5623b7151ad478 100644 (file)
@@ -717,20 +717,6 @@ static inline bool is_cow_mapping(vm_flags_t flags)
        return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
 }
 
-#ifndef is_zero_pfn
-static inline int is_zero_pfn(unsigned long pfn)
-{
-       return pfn == zero_pfn;
-}
-#endif
-
-#ifndef my_zero_pfn
-static inline unsigned long my_zero_pfn(unsigned long addr)
-{
-       return zero_pfn;
-}
-#endif
-
 /*
  * vm_normal_page -- This function gets the "struct page" associated with a pte.
  *
@@ -1250,7 +1236,7 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb,
                                        BUG();
                                }
 #endif
-                               split_huge_page_pmd(vma->vm_mm, pmd);
+                               split_huge_page_pmd(vma, addr, pmd);
                        } else if (zap_huge_pmd(tlb, vma, pmd, addr))
                                goto next;
                        /* fall through */
@@ -1519,7 +1505,7 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
        }
        if (pmd_trans_huge(*pmd)) {
                if (flags & FOLL_SPLIT) {
-                       split_huge_page_pmd(mm, pmd);
+                       split_huge_page_pmd(vma, address, pmd);
                        goto split_fallthrough;
                }
                spin_lock(&mm->page_table_lock);
@@ -2794,13 +2780,8 @@ unlock:
 oom_free_new:
        page_cache_release(new_page);
 oom:
-       if (old_page) {
-               if (page_mkwrite) {
-                       unlock_page(old_page);
-                       page_cache_release(old_page);
-               }
+       if (old_page)
                page_cache_release(old_page);
-       }
        return VM_FAULT_OOM;
 
 unwritable_page:
index de9cb14ae753ee2cfe7854201aa1bfb3d2e1f480..518baa896e8375e25fce00ccbbe34709d9984e01 100644 (file)
@@ -106,6 +106,7 @@ static void get_page_bootmem(unsigned long info,  struct page *page,
 void __ref put_page_bootmem(struct page *page)
 {
        unsigned long type;
+       static DEFINE_MUTEX(ppb_lock);
 
        type = (unsigned long) page->lru.next;
        BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -115,7 +116,14 @@ void __ref put_page_bootmem(struct page *page)
                ClearPagePrivate(page);
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
+
+               /*
+                * Please refer to comment for __free_pages_bootmem()
+                * for why we serialize here.
+                */
+               mutex_lock(&ppb_lock);
                __free_pages_bootmem(page, 0);
+               mutex_unlock(&ppb_lock);
        }
 
 }
@@ -581,11 +589,19 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
        return 0;
 }
 
+#ifdef CONFIG_MOVABLE_NODE
+/* when CONFIG_MOVABLE_NODE, we allow online node don't have normal memory */
+static bool can_online_high_movable(struct zone *zone)
+{
+       return true;
+}
+#else /* #ifdef CONFIG_MOVABLE_NODE */
 /* ensure every online node has NORMAL memory */
 static bool can_online_high_movable(struct zone *zone)
 {
        return node_state(zone_to_nid(zone), N_NORMAL_MEMORY);
 }
+#endif /* #ifdef CONFIG_MOVABLE_NODE */
 
 /* check which state of node_states will be changed when online memory */
 static void node_states_check_changes_online(unsigned long nr_pages,
@@ -595,13 +611,15 @@ static void node_states_check_changes_online(unsigned long nr_pages,
        enum zone_type zone_last = ZONE_NORMAL;
 
        /*
-        * If we have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes
-        * which have 0...ZONE_NORMAL, set zone_last to ZONE_NORMAL.
+        * If we have HIGHMEM or movable node, node_states[N_NORMAL_MEMORY]
+        * contains nodes which have zones of 0...ZONE_NORMAL,
+        * set zone_last to ZONE_NORMAL.
         *
-        * If we don't have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes
-        * which have 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
+        * If we don't have HIGHMEM nor movable node,
+        * node_states[N_NORMAL_MEMORY] contains nodes which have zones of
+        * 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
         */
-       if (N_HIGH_MEMORY == N_NORMAL_MEMORY)
+       if (N_MEMORY == N_NORMAL_MEMORY)
                zone_last = ZONE_MOVABLE;
 
        /*
@@ -615,12 +633,34 @@ static void node_states_check_changes_online(unsigned long nr_pages,
        else
                arg->status_change_nid_normal = -1;
 
+#ifdef CONFIG_HIGHMEM
+       /*
+        * If we have movable node, node_states[N_HIGH_MEMORY]
+        * contains nodes which have zones of 0...ZONE_HIGHMEM,
+        * set zone_last to ZONE_HIGHMEM.
+        *
+        * If we don't have movable node, node_states[N_NORMAL_MEMORY]
+        * contains nodes which have zones of 0...ZONE_MOVABLE,
+        * set zone_last to ZONE_MOVABLE.
+        */
+       zone_last = ZONE_HIGHMEM;
+       if (N_MEMORY == N_HIGH_MEMORY)
+               zone_last = ZONE_MOVABLE;
+
+       if (zone_idx(zone) <= zone_last && !node_state(nid, N_HIGH_MEMORY))
+               arg->status_change_nid_high = nid;
+       else
+               arg->status_change_nid_high = -1;
+#else
+       arg->status_change_nid_high = arg->status_change_nid_normal;
+#endif
+
        /*
         * if the node don't have memory befor online, we will need to
-        * set the node to node_states[N_HIGH_MEMORY] after the memory
+        * set the node to node_states[N_MEMORY] after the memory
         * is online.
         */
-       if (!node_state(nid, N_HIGH_MEMORY))
+       if (!node_state(nid, N_MEMORY))
                arg->status_change_nid = nid;
        else
                arg->status_change_nid = -1;
@@ -631,7 +671,10 @@ static void node_states_set_node(int node, struct memory_notify *arg)
        if (arg->status_change_nid_normal >= 0)
                node_set_state(node, N_NORMAL_MEMORY);
 
-       node_set_state(node, N_HIGH_MEMORY);
+       if (arg->status_change_nid_high >= 0)
+               node_set_state(node, N_HIGH_MEMORY);
+
+       node_set_state(node, N_MEMORY);
 }
 
 
@@ -713,6 +756,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
                return ret;
        }
 
+       zone->managed_pages += onlined_pages;
        zone->present_pages += onlined_pages;
        zone->zone_pgdat->node_present_pages += onlined_pages;
        if (onlined_pages) {
@@ -1066,6 +1110,13 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
        return offlined;
 }
 
+#ifdef CONFIG_MOVABLE_NODE
+/* when CONFIG_MOVABLE_NODE, we allow online node don't have normal memory */
+static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
+{
+       return true;
+}
+#else /* #ifdef CONFIG_MOVABLE_NODE */
 /* ensure the node has NORMAL memory if it is still online */
 static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
 {
@@ -1089,6 +1140,7 @@ static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
         */
        return present_pages == 0;
 }
+#endif /* #ifdef CONFIG_MOVABLE_NODE */
 
 /* check which state of node_states will be changed when offline memory */
 static void node_states_check_changes_offline(unsigned long nr_pages,
@@ -1099,13 +1151,15 @@ static void node_states_check_changes_offline(unsigned long nr_pages,
        enum zone_type zt, zone_last = ZONE_NORMAL;
 
        /*
-        * If we have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes
-        * which have 0...ZONE_NORMAL, set zone_last to ZONE_NORMAL.
+        * If we have HIGHMEM or movable node, node_states[N_NORMAL_MEMORY]
+        * contains nodes which have zones of 0...ZONE_NORMAL,
+        * set zone_last to ZONE_NORMAL.
         *
-        * If we don't have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes
-        * which have 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
+        * If we don't have HIGHMEM nor movable node,
+        * node_states[N_NORMAL_MEMORY] contains nodes which have zones of
+        * 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
         */
-       if (N_HIGH_MEMORY == N_NORMAL_MEMORY)
+       if (N_MEMORY == N_NORMAL_MEMORY)
                zone_last = ZONE_MOVABLE;
 
        /*
@@ -1122,6 +1176,30 @@ static void node_states_check_changes_offline(unsigned long nr_pages,
        else
                arg->status_change_nid_normal = -1;
 
+#ifdef CONFIG_HIGHMEM
+       /*
+        * If we have movable node, node_states[N_HIGH_MEMORY]
+        * contains nodes which have zones of 0...ZONE_HIGHMEM,
+        * set zone_last to ZONE_HIGHMEM.
+        *
+        * If we don't have movable node, node_states[N_NORMAL_MEMORY]
+        * contains nodes which have zones of 0...ZONE_MOVABLE,
+        * set zone_last to ZONE_MOVABLE.
+        */
+       zone_last = ZONE_HIGHMEM;
+       if (N_MEMORY == N_HIGH_MEMORY)
+               zone_last = ZONE_MOVABLE;
+
+       for (; zt <= zone_last; zt++)
+               present_pages += pgdat->node_zones[zt].present_pages;
+       if (zone_idx(zone) <= zone_last && nr_pages >= present_pages)
+               arg->status_change_nid_high = zone_to_nid(zone);
+       else
+               arg->status_change_nid_high = -1;
+#else
+       arg->status_change_nid_high = arg->status_change_nid_normal;
+#endif
+
        /*
         * node_states[N_HIGH_MEMORY] contains nodes which have 0...ZONE_MOVABLE
         */
@@ -1146,9 +1224,13 @@ static void node_states_clear_node(int node, struct memory_notify *arg)
        if (arg->status_change_nid_normal >= 0)
                node_clear_state(node, N_NORMAL_MEMORY);
 
-       if ((N_HIGH_MEMORY != N_NORMAL_MEMORY) &&
-           (arg->status_change_nid >= 0))
+       if ((N_MEMORY != N_NORMAL_MEMORY) &&
+           (arg->status_change_nid_high >= 0))
                node_clear_state(node, N_HIGH_MEMORY);
+
+       if ((N_MEMORY != N_HIGH_MEMORY) &&
+           (arg->status_change_nid >= 0))
+               node_clear_state(node, N_MEMORY);
 }
 
 static int __ref __offline_pages(unsigned long start_pfn,
@@ -1230,10 +1312,10 @@ repeat:
                        goto repeat;
                }
        }
-       /* drain all zone's lru pagevec, this is asyncronous... */
+       /* drain all zone's lru pagevec, this is asynchronous... */
        lru_add_drain_all();
        yield();
-       /* drain pcp pages , this is synchrouns. */
+       /* drain pcp pages, this is synchronous. */
        drain_all_pages();
        /* check again */
        offlined_pages = check_pages_isolated(start_pfn, end_pfn);
@@ -1242,12 +1324,13 @@ repeat:
                goto failed_removal;
        }
        printk(KERN_INFO "Offlined Pages %ld\n", offlined_pages);
-       /* Ok, all of our target is islaoted.
+       /* Ok, all of our target is isolated.
           We cannot do rollback at this point. */
        offline_isolated_pages(start_pfn, end_pfn);
        /* reset pagetype flags and makes migrate type to be MOVABLE */
        undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
        /* removal success */
+       zone->managed_pages -= offlined_pages;
        zone->present_pages -= offlined_pages;
        zone->zone_pgdat->node_present_pages -= offlined_pages;
        totalram_pages -= offlined_pages;
index 05b28361a39b13b192aecd8545f73f6d607b2a2e..aaf54566cb6b6616b61a093f5c19ab4bdb7678ea 100644 (file)
@@ -212,9 +212,9 @@ static int mpol_set_nodemask(struct mempolicy *pol,
        /* if mode is MPOL_DEFAULT, pol is NULL. This is right. */
        if (pol == NULL)
                return 0;
-       /* Check N_HIGH_MEMORY */
+       /* Check N_MEMORY */
        nodes_and(nsc->mask1,
-                 cpuset_current_mems_allowed, node_states[N_HIGH_MEMORY]);
+                 cpuset_current_mems_allowed, node_states[N_MEMORY]);
 
        VM_BUG_ON(!nodes);
        if (pol->mode == MPOL_PREFERRED && nodes_empty(*nodes))
@@ -511,7 +511,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud,
        pmd = pmd_offset(pud, addr);
        do {
                next = pmd_addr_end(addr, end);
-               split_huge_page_pmd(vma->vm_mm, pmd);
+               split_huge_page_pmd(vma, addr, pmd);
                if (pmd_none_or_trans_huge_or_clear_bad(pmd))
                        continue;
                if (check_pte_range(vma, pmd, addr, next, nodes,
@@ -1388,7 +1388,7 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
                goto out_put;
        }
 
-       if (!nodes_subset(*new, node_states[N_HIGH_MEMORY])) {
+       if (!nodes_subset(*new, node_states[N_MEMORY])) {
                err = -EINVAL;
                goto out_put;
        }
@@ -2326,7 +2326,7 @@ void __init numa_policy_init(void)
         * fall back to the largest node if they're all smaller.
         */
        nodes_clear(interleave_nodes);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                unsigned long total_pages = node_present_pages(nid);
 
                /* Preserve the largest node */
@@ -2407,7 +2407,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                *nodelist++ = '\0';
                if (nodelist_parse(nodelist, nodes))
                        goto out;
-               if (!nodes_subset(nodes, node_states[N_HIGH_MEMORY]))
+               if (!nodes_subset(nodes, node_states[N_MEMORY]))
                        goto out;
        } else
                nodes_clear(nodes);
@@ -2441,7 +2441,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                 * Default to online nodes with memory if no nodelist
                 */
                if (!nodelist)
-                       nodes = node_states[N_HIGH_MEMORY];
+                       nodes = node_states[N_MEMORY];
                break;
        case MPOL_LOCAL:
                /*
index 3f675ca08279f27af98b4a046413be029cf082b8..cae02711181dd7ad0bde55e9eecfc0dd5bccaa83 100644 (file)
@@ -1238,7 +1238,7 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
                        if (node < 0 || node >= MAX_NUMNODES)
                                goto out_pm;
 
-                       if (!node_state(node, N_HIGH_MEMORY))
+                       if (!node_state(node, N_MEMORY))
                                goto out_pm;
 
                        err = -EACCES;
index f940062c8d4b7dd50a619663c49fde83b40e3f61..2b7d9e78a5693982a70f2b7f61d42afcad20ef01 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1488,7 +1488,11 @@ munmap_back:
                 *
                 * Answer: Yes, several device drivers can do it in their
                 *         f_op->mmap method. -DaveM
+                * Bug: If addr is changed, prev, rb_link, rb_parent should
+                *      be updated for vma_link()
                 */
+               WARN_ON_ONCE(addr != vma->vm_start);
+
                addr = vma->vm_start;
                pgoff = vma->vm_pgoff;
                vm_flags = vma->vm_flags;
@@ -2065,6 +2069,18 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
                if (vma->vm_pgoff + (size >> PAGE_SHIFT) >= vma->vm_pgoff) {
                        error = acct_stack_growth(vma, size, grow);
                        if (!error) {
+                               /*
+                                * vma_gap_update() doesn't support concurrent
+                                * updates, but we only hold a shared mmap_sem
+                                * lock here, so we need to protect against
+                                * concurrent vma expansions.
+                                * vma_lock_anon_vma() doesn't help here, as
+                                * we don't guarantee that all growable vmas
+                                * in a mm share the same root anon vma.
+                                * So, we reuse mm->page_table_lock to guard
+                                * against concurrent vma expansions.
+                                */
+                               spin_lock(&vma->vm_mm->page_table_lock);
                                anon_vma_interval_tree_pre_update_vma(vma);
                                vma->vm_end = address;
                                anon_vma_interval_tree_post_update_vma(vma);
@@ -2072,6 +2088,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
                                        vma_gap_update(vma->vm_next);
                                else
                                        vma->vm_mm->highest_vm_end = address;
+                               spin_unlock(&vma->vm_mm->page_table_lock);
+
                                perf_event_mmap(vma);
                        }
                }
@@ -2122,11 +2140,25 @@ int expand_downwards(struct vm_area_struct *vma,
                if (grow <= vma->vm_pgoff) {
                        error = acct_stack_growth(vma, size, grow);
                        if (!error) {
+                               /*
+                                * vma_gap_update() doesn't support concurrent
+                                * updates, but we only hold a shared mmap_sem
+                                * lock here, so we need to protect against
+                                * concurrent vma expansions.
+                                * vma_lock_anon_vma() doesn't help here, as
+                                * we don't guarantee that all growable vmas
+                                * in a mm share the same root anon vma.
+                                * So, we reuse mm->page_table_lock to guard
+                                * against concurrent vma expansions.
+                                */
+                               spin_lock(&vma->vm_mm->page_table_lock);
                                anon_vma_interval_tree_pre_update_vma(vma);
                                vma->vm_start = address;
                                vma->vm_pgoff -= grow;
                                anon_vma_interval_tree_post_update_vma(vma);
                                vma_gap_update(vma);
+                               spin_unlock(&vma->vm_mm->page_table_lock);
+
                                perf_event_mmap(vma);
                        }
                }
index a40992610ab6f6c0cbe96f9a9bd43a3fa973fd96..e8c3938db6faecf6f91c47db790a36271fa8d938 100644 (file)
@@ -90,7 +90,7 @@ static inline void change_pmd_range(struct vm_area_struct *vma, pud_t *pud,
                next = pmd_addr_end(addr, end);
                if (pmd_trans_huge(*pmd)) {
                        if (next - addr != HPAGE_PMD_SIZE)
-                               split_huge_page_pmd(vma->vm_mm, pmd);
+                               split_huge_page_pmd(vma, addr, pmd);
                        else if (change_huge_pmd(vma, pmd, addr, newprot))
                                continue;
                        /* fall through */
index 1b61c2d3307a800c9c958e5f949d81fb76515899..eabb24da6c9e1bf00ee64075626630331ca94039 100644 (file)
@@ -182,7 +182,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
                                need_flush = true;
                                continue;
                        } else if (!err) {
-                               split_huge_page_pmd(vma->vm_mm, old_pmd);
+                               split_huge_page_pmd(vma, old_addr, old_pmd);
                        }
                        VM_BUG_ON(pmd_trans_huge(*old_pmd));
                }
index bd82f6b314114dc937bea707a70072b299860a08..b8294fc03df869153378f47f41f0ecd595c10887 100644 (file)
@@ -137,6 +137,22 @@ unsigned long __init free_low_memory_core_early(int nodeid)
        return count;
 }
 
+static void reset_node_lowmem_managed_pages(pg_data_t *pgdat)
+{
+       struct zone *z;
+
+       /*
+        * In free_area_init_core(), highmem zone's managed_pages is set to
+        * present_pages, and bootmem allocator doesn't allocate from highmem
+        * zones. So there's no need to recalculate managed_pages because all
+        * highmem pages will be managed by the buddy system. Here highmem
+        * zone also includes highmem movable zone.
+        */
+       for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+               if (!is_highmem(z))
+                       z->managed_pages = 0;
+}
+
 /**
  * free_all_bootmem_node - release a node's free pages to the buddy allocator
  * @pgdat: node to be released
@@ -146,6 +162,7 @@ unsigned long __init free_low_memory_core_early(int nodeid)
 unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
        register_page_bootmem_info_node(pgdat);
+       reset_node_lowmem_managed_pages(pgdat);
 
        /* free_low_memory_core_early(MAX_NUMNODES) will be called later */
        return 0;
@@ -158,6 +175,11 @@ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
  */
 unsigned long __init free_all_bootmem(void)
 {
+       struct pglist_data *pgdat;
+
+       for_each_online_pgdat(pgdat)
+               reset_node_lowmem_managed_pages(pgdat);
+
        /*
         * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id
         *  because in some case like Node0 doesn't have RAM installed
index 18f1ae2b45de6d45f64cf13b4490b2da62dd2fb5..0399f146ae49900a92c52ea158823cef1ad18ff2 100644 (file)
@@ -215,7 +215,7 @@ static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
         * the page allocator means a mempolicy is in effect.  Cpuset policy
         * is enforced in get_page_from_freelist().
         */
-       if (nodemask && !nodes_subset(node_states[N_HIGH_MEMORY], *nodemask)) {
+       if (nodemask && !nodes_subset(node_states[N_MEMORY], *nodemask)) {
                *totalpages = total_swap_pages;
                for_each_node_mask(nid, *nodemask)
                        *totalpages += node_spanned_pages(nid);
@@ -591,43 +591,6 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
        spin_unlock(&zone_scan_lock);
 }
 
-/*
- * Try to acquire the oom killer lock for all system zones.  Returns zero if a
- * parallel oom killing is taking place, otherwise locks all zones and returns
- * non-zero.
- */
-static int try_set_system_oom(void)
-{
-       struct zone *zone;
-       int ret = 1;
-
-       spin_lock(&zone_scan_lock);
-       for_each_populated_zone(zone)
-               if (zone_is_oom_locked(zone)) {
-                       ret = 0;
-                       goto out;
-               }
-       for_each_populated_zone(zone)
-               zone_set_flag(zone, ZONE_OOM_LOCKED);
-out:
-       spin_unlock(&zone_scan_lock);
-       return ret;
-}
-
-/*
- * Clears ZONE_OOM_LOCKED for all system zones so that failed allocation
- * attempts or page faults may now recall the oom killer, if necessary.
- */
-static void clear_system_oom(void)
-{
-       struct zone *zone;
-
-       spin_lock(&zone_scan_lock);
-       for_each_populated_zone(zone)
-               zone_clear_flag(zone, ZONE_OOM_LOCKED);
-       spin_unlock(&zone_scan_lock);
-}
-
 /**
  * out_of_memory - kill the "best" process when we run out of memory
  * @zonelist: zonelist pointer
@@ -708,15 +671,16 @@ out:
 
 /*
  * The pagefault handler calls here because it is out of memory, so kill a
- * memory-hogging task.  If a populated zone has ZONE_OOM_LOCKED set, a parallel
- * oom killing is already in progress so do nothing.  If a task is found with
- * TIF_MEMDIE set, it has been killed so do nothing and allow it to exit.
+ * memory-hogging task.  If any populated zone has ZONE_OOM_LOCKED set, a
+ * parallel oom killing is already in progress so do nothing.
  */
 void pagefault_out_of_memory(void)
 {
-       if (try_set_system_oom()) {
+       struct zonelist *zonelist = node_zonelist(first_online_node,
+                                                 GFP_KERNEL);
+
+       if (try_set_zonelist_oom(zonelist, GFP_KERNEL)) {
                out_of_memory(NULL, 0, 0, NULL, false);
-               clear_system_oom();
+               clear_zonelist_oom(zonelist, GFP_KERNEL);
        }
-       schedule_timeout_killable(1);
 }
index 5a8d339d282a88cd0c5687596eca8023f93846ba..83637dfba110c8308570d7f75ec46bca7386dc3a 100644 (file)
@@ -89,6 +89,9 @@ nodemask_t node_states[NR_NODE_STATES] __read_mostly = {
        [N_NORMAL_MEMORY] = { { [0] = 1UL } },
 #ifdef CONFIG_HIGHMEM
        [N_HIGH_MEMORY] = { { [0] = 1UL } },
+#endif
+#ifdef CONFIG_MOVABLE_NODE
+       [N_MEMORY] = { { [0] = 1UL } },
 #endif
        [N_CPU] = { { [0] = 1UL } },
 #endif /* NUMA */
@@ -523,7 +526,7 @@ static inline int page_is_buddy(struct page *page, struct page *buddy,
  * If a block is freed, and its buddy is also free, then this
  * triggers coalescing into a block of larger size.
  *
- * -- wli
+ * -- nyc
  */
 
 static inline void __free_one_page(struct page *page,
@@ -732,6 +735,13 @@ static void __free_pages_ok(struct page *page, unsigned int order)
        local_irq_restore(flags);
 }
 
+/*
+ * Read access to zone->managed_pages is safe because it's unsigned long,
+ * but we still need to serialize writers. Currently all callers of
+ * __free_pages_bootmem() except put_page_bootmem() should only be used
+ * at boot time. So for shorter boot time, we shift the burden to
+ * put_page_bootmem() to serialize writers.
+ */
 void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
 {
        unsigned int nr_pages = 1 << order;
@@ -747,6 +757,7 @@ void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
                set_page_count(p, 0);
        }
 
+       page_zone(page)->managed_pages += 1 << order;
        set_page_refcounted(page);
        __free_pages(page, order);
 }
@@ -782,7 +793,7 @@ void __init init_cma_reserved_pageblock(struct page *page)
  * large block of memory acted on by a series of small allocations.
  * This behavior is a critical factor in sglist merging's success.
  *
- * -- wli
+ * -- nyc
  */
 static inline void expand(struct zone *zone, struct page *page,
        int low, int high, struct free_area *area,
@@ -1695,7 +1706,7 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
  *
  * If the zonelist cache is present in the passed in zonelist, then
  * returns a pointer to the allowed node mask (either the current
- * tasks mems_allowed, or node_states[N_HIGH_MEMORY].)
+ * tasks mems_allowed, or node_states[N_MEMORY].)
  *
  * If the zonelist cache is not available for this zonelist, does
  * nothing and returns NULL.
@@ -1724,7 +1735,7 @@ static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
 
        allowednodes = !in_interrupt() && (alloc_flags & ALLOC_CPUSET) ?
                                        &cpuset_current_mems_allowed :
-                                       &node_states[N_HIGH_MEMORY];
+                                       &node_states[N_MEMORY];
        return allowednodes;
 }
 
@@ -2981,6 +2992,7 @@ void show_free_areas(unsigned int filter)
                        " isolated(anon):%lukB"
                        " isolated(file):%lukB"
                        " present:%lukB"
+                       " managed:%lukB"
                        " mlocked:%lukB"
                        " dirty:%lukB"
                        " writeback:%lukB"
@@ -3010,6 +3022,7 @@ void show_free_areas(unsigned int filter)
                        K(zone_page_state(zone, NR_ISOLATED_ANON)),
                        K(zone_page_state(zone, NR_ISOLATED_FILE)),
                        K(zone->present_pages),
+                       K(zone->managed_pages),
                        K(zone_page_state(zone, NR_MLOCK)),
                        K(zone_page_state(zone, NR_FILE_DIRTY)),
                        K(zone_page_state(zone, NR_WRITEBACK)),
@@ -3238,7 +3251,7 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
                return node;
        }
 
-       for_each_node_state(n, N_HIGH_MEMORY) {
+       for_each_node_state(n, N_MEMORY) {
 
                /* Don't want a node to appear more than once */
                if (node_isset(n, *used_node_mask))
@@ -3380,7 +3393,7 @@ static int default_zonelist_order(void)
         * local memory, NODE_ORDER may be suitable.
          */
        average_size = total_size /
-                               (nodes_weight(node_states[N_HIGH_MEMORY]) + 1);
+                               (nodes_weight(node_states[N_MEMORY]) + 1);
        for_each_online_node(nid) {
                low_kmem_size = 0;
                total_size = 0;
@@ -4476,6 +4489,26 @@ void __init set_pageblock_order(void)
 
 #endif /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
 
+static unsigned long __paginginit calc_memmap_size(unsigned long spanned_pages,
+                                                  unsigned long present_pages)
+{
+       unsigned long pages = spanned_pages;
+
+       /*
+        * Provide a more accurate estimation if there are holes within
+        * the zone and SPARSEMEM is in use. If there are holes within the
+        * zone, each populated memory region may cost us one or two extra
+        * memmap pages due to alignment because memmap pages for each
+        * populated regions may not naturally algined on page boundary.
+        * So the (present_pages >> 4) heuristic is a tradeoff for that.
+        */
+       if (spanned_pages > present_pages + (present_pages >> 4) &&
+           IS_ENABLED(CONFIG_SPARSEMEM))
+               pages = present_pages;
+
+       return PAGE_ALIGN(pages * sizeof(struct page)) >> PAGE_SHIFT;
+}
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -4499,48 +4532,56 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
 
        for (j = 0; j < MAX_NR_ZONES; j++) {
                struct zone *zone = pgdat->node_zones + j;
-               unsigned long size, realsize, memmap_pages;
+               unsigned long size, realsize, freesize, memmap_pages;
 
                size = zone_spanned_pages_in_node(nid, j, zones_size);
-               realsize = size - zone_absent_pages_in_node(nid, j,
+               realsize = freesize = size - zone_absent_pages_in_node(nid, j,
                                                                zholes_size);
 
                /*
-                * Adjust realsize so that it accounts for how much memory
+                * Adjust freesize so that it accounts for how much memory
                 * is used by this zone for memmap. This affects the watermark
                 * and per-cpu initialisations
                 */
-               memmap_pages =
-                       PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
-               if (realsize >= memmap_pages) {
-                       realsize -= memmap_pages;
+               memmap_pages = calc_memmap_size(size, realsize);
+               if (freesize >= memmap_pages) {
+                       freesize -= memmap_pages;
                        if (memmap_pages)
                                printk(KERN_DEBUG
                                       "  %s zone: %lu pages used for memmap\n",
                                       zone_names[j], memmap_pages);
                } else
                        printk(KERN_WARNING
-                               "  %s zone: %lu pages exceeds realsize %lu\n",
-                               zone_names[j], memmap_pages, realsize);
+                               "  %s zone: %lu pages exceeds freesize %lu\n",
+                               zone_names[j], memmap_pages, freesize);
 
                /* Account for reserved pages */
-               if (j == 0 && realsize > dma_reserve) {
-                       realsize -= dma_reserve;
+               if (j == 0 && freesize > dma_reserve) {
+                       freesize -= dma_reserve;
                        printk(KERN_DEBUG "  %s zone: %lu pages reserved\n",
                                        zone_names[0], dma_reserve);
                }
 
                if (!is_highmem_idx(j))
-                       nr_kernel_pages += realsize;
-               nr_all_pages += realsize;
+                       nr_kernel_pages += freesize;
+               /* Charge for highmem memmap if there are enough kernel pages */
+               else if (nr_kernel_pages > memmap_pages * 2)
+                       nr_kernel_pages -= memmap_pages;
+               nr_all_pages += freesize;
 
                zone->spanned_pages = size;
-               zone->present_pages = realsize;
+               zone->present_pages = freesize;
+               /*
+                * Set an approximate value for lowmem here, it will be adjusted
+                * when the bootmem allocator frees pages into the buddy system.
+                * And all highmem pages will be managed by the buddy system.
+                */
+               zone->managed_pages = is_highmem_idx(j) ? realsize : freesize;
 #ifdef CONFIG_NUMA
                zone->node = nid;
-               zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio)
+               zone->min_unmapped_pages = (freesize*sysctl_min_unmapped_ratio)
                                                / 100;
-               zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100;
+               zone->min_slab_pages = (freesize * sysctl_min_slab_ratio) / 100;
 #endif
                zone->name = zone_names[j];
                spin_lock_init(&zone->lock);
@@ -4731,7 +4772,7 @@ unsigned long __init find_min_pfn_with_active_regions(void)
 /*
  * early_calculate_totalpages()
  * Sum pages in active regions for movable zone.
- * Populate N_HIGH_MEMORY for calculating usable_nodes.
+ * Populate N_MEMORY for calculating usable_nodes.
  */
 static unsigned long __init early_calculate_totalpages(void)
 {
@@ -4744,7 +4785,7 @@ static unsigned long __init early_calculate_totalpages(void)
 
                totalpages += pages;
                if (pages)
-                       node_set_state(nid, N_HIGH_MEMORY);
+                       node_set_state(nid, N_MEMORY);
        }
        return totalpages;
 }
@@ -4761,9 +4802,9 @@ static void __init find_zone_movable_pfns_for_nodes(void)
        unsigned long usable_startpfn;
        unsigned long kernelcore_node, kernelcore_remaining;
        /* save the state before borrow the nodemask */
-       nodemask_t saved_node_state = node_states[N_HIGH_MEMORY];
+       nodemask_t saved_node_state = node_states[N_MEMORY];
        unsigned long totalpages = early_calculate_totalpages();
-       int usable_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
+       int usable_nodes = nodes_weight(node_states[N_MEMORY]);
 
        /*
         * If movablecore was specified, calculate what size of
@@ -4798,7 +4839,7 @@ static void __init find_zone_movable_pfns_for_nodes(void)
 restart:
        /* Spread kernelcore memory as evenly as possible throughout nodes */
        kernelcore_node = required_kernelcore / usable_nodes;
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                unsigned long start_pfn, end_pfn;
 
                /*
@@ -4890,23 +4931,27 @@ restart:
 
 out:
        /* restore the node_state */
-       node_states[N_HIGH_MEMORY] = saved_node_state;
+       node_states[N_MEMORY] = saved_node_state;
 }
 
-/* Any regular memory on that node ? */
-static void __init check_for_regular_memory(pg_data_t *pgdat)
+/* Any regular or high memory on that node ? */
+static void check_for_memory(pg_data_t *pgdat, int nid)
 {
-#ifdef CONFIG_HIGHMEM
        enum zone_type zone_type;
 
-       for (zone_type = 0; zone_type <= ZONE_NORMAL; zone_type++) {
+       if (N_MEMORY == N_NORMAL_MEMORY)
+               return;
+
+       for (zone_type = 0; zone_type <= ZONE_MOVABLE - 1; zone_type++) {
                struct zone *zone = &pgdat->node_zones[zone_type];
                if (zone->present_pages) {
-                       node_set_state(zone_to_nid(zone), N_NORMAL_MEMORY);
+                       node_set_state(nid, N_HIGH_MEMORY);
+                       if (N_NORMAL_MEMORY != N_HIGH_MEMORY &&
+                           zone_type <= ZONE_NORMAL)
+                               node_set_state(nid, N_NORMAL_MEMORY);
                        break;
                }
        }
-#endif
 }
 
 /**
@@ -4989,8 +5034,8 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
 
                /* Any memory on that node */
                if (pgdat->node_present_pages)
-                       node_set_state(nid, N_HIGH_MEMORY);
-               check_for_regular_memory(pgdat);
+                       node_set_state(nid, N_MEMORY);
+               check_for_memory(pgdat, nid);
        }
 }
 
@@ -5727,7 +5772,7 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
        unsigned int tries = 0;
        int ret = 0;
 
-       migrate_prep_local();
+       migrate_prep();
 
        while (pfn < end || !list_empty(&cc->migratepages)) {
                if (fatal_signal_pending(current)) {
index 44db00e253ed35f7b4909ab7c151a6af145c0210..6d757e3a872ad52adea55aabecee1ec571c3970d 100644 (file)
@@ -274,7 +274,7 @@ void __init page_cgroup_init(void)
        if (mem_cgroup_disabled())
                return;
 
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                unsigned long start_pfn, end_pfn;
 
                start_pfn = node_start_pfn(nid);
index 6c118d012bb5a27be54ab331a4491e3ec421ac31..35aa294656cd812d2773fede0d51179a8b7ee09a 100644 (file)
@@ -58,7 +58,7 @@ again:
                if (!walk->pte_entry)
                        continue;
 
-               split_huge_page_pmd(walk->mm, pmd);
+               split_huge_page_pmd_mm(walk->mm, addr, pmd);
                if (pmd_none_or_trans_huge_or_clear_bad(pmd))
                        goto again;
                err = walk_pte_range(pmd, addr, next, walk);
index cf7e99a87c32865c4e6cf5b6ed4f48f7f05aa9e0..face808a489e7765ecbaa57041e4690b47c9d177 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1249,12 +1249,14 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
        update_hiwater_rss(mm);
 
        if (PageHWPoison(page) && !(flags & TTU_IGNORE_HWPOISON)) {
-               if (PageAnon(page))
-                       dec_mm_counter(mm, MM_ANONPAGES);
-               else
-                       dec_mm_counter(mm, MM_FILEPAGES);
+               if (!PageHuge(page)) {
+                       if (PageAnon(page))
+                               dec_mm_counter(mm, MM_ANONPAGES);
+                       else
+                               dec_mm_counter(mm, MM_FILEPAGES);
+               }
                set_pte_at(mm, address, pte,
-                               swp_entry_to_pte(make_hwpoison_entry(page)));
+                          swp_entry_to_pte(make_hwpoison_entry(page)));
        } else if (PageAnon(page)) {
                swp_entry_t entry = { .val = page_private(page) };
 
index 50c5b8f3a359b611a22e1e3715dd816880e4651e..03f9ba8fb8e543d96d2fad317a2a19126cf99222 100644 (file)
@@ -1715,6 +1715,96 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
        return error;
 }
 
+/*
+ * llseek SEEK_DATA or SEEK_HOLE through the radix_tree.
+ */
+static pgoff_t shmem_seek_hole_data(struct address_space *mapping,
+                                   pgoff_t index, pgoff_t end, int origin)
+{
+       struct page *page;
+       struct pagevec pvec;
+       pgoff_t indices[PAGEVEC_SIZE];
+       bool done = false;
+       int i;
+
+       pagevec_init(&pvec, 0);
+       pvec.nr = 1;            /* start small: we may be there already */
+       while (!done) {
+               pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
+                                       pvec.nr, pvec.pages, indices);
+               if (!pvec.nr) {
+                       if (origin == SEEK_DATA)
+                               index = end;
+                       break;
+               }
+               for (i = 0; i < pvec.nr; i++, index++) {
+                       if (index < indices[i]) {
+                               if (origin == SEEK_HOLE) {
+                                       done = true;
+                                       break;
+                               }
+                               index = indices[i];
+                       }
+                       page = pvec.pages[i];
+                       if (page && !radix_tree_exceptional_entry(page)) {
+                               if (!PageUptodate(page))
+                                       page = NULL;
+                       }
+                       if (index >= end ||
+                           (page && origin == SEEK_DATA) ||
+                           (!page && origin == SEEK_HOLE)) {
+                               done = true;
+                               break;
+                       }
+               }
+               shmem_deswap_pagevec(&pvec);
+               pagevec_release(&pvec);
+               pvec.nr = PAGEVEC_SIZE;
+               cond_resched();
+       }
+       return index;
+}
+
+static loff_t shmem_file_llseek(struct file *file, loff_t offset, int origin)
+{
+       struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
+       pgoff_t start, end;
+       loff_t new_offset;
+
+       if (origin != SEEK_DATA && origin != SEEK_HOLE)
+               return generic_file_llseek_size(file, offset, origin,
+                                       MAX_LFS_FILESIZE, i_size_read(inode));
+       mutex_lock(&inode->i_mutex);
+       /* We're holding i_mutex so we can access i_size directly */
+
+       if (offset < 0)
+               offset = -EINVAL;
+       else if (offset >= inode->i_size)
+               offset = -ENXIO;
+       else {
+               start = offset >> PAGE_CACHE_SHIFT;
+               end = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+               new_offset = shmem_seek_hole_data(mapping, start, end, origin);
+               new_offset <<= PAGE_CACHE_SHIFT;
+               if (new_offset > offset) {
+                       if (new_offset < inode->i_size)
+                               offset = new_offset;
+                       else if (origin == SEEK_DATA)
+                               offset = -ENXIO;
+                       else
+                               offset = inode->i_size;
+               }
+       }
+
+       if (offset >= 0 && offset != file->f_pos) {
+               file->f_pos = offset;
+               file->f_version = 0;
+       }
+       mutex_unlock(&inode->i_mutex);
+       return offset;
+}
+
 static long shmem_fallocate(struct file *file, int mode, loff_t offset,
                                                         loff_t len)
 {
@@ -2586,7 +2676,7 @@ static const struct address_space_operations shmem_aops = {
 static const struct file_operations shmem_file_operations = {
        .mmap           = shmem_mmap,
 #ifdef CONFIG_TMPFS
-       .llseek         = generic_file_llseek,
+       .llseek         = shmem_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .aio_read       = shmem_file_aio_read,
index dc3036cdcc6a60ac4e8bea6521279b2cff687bcb..c55e26b17d93de77dc069d7f30019f7391e0d93f 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -152,7 +152,7 @@ EXPORT_SYMBOL(__krealloc);
  *
  * The contents of the object pointed to are preserved up to the
  * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * behaves exactly like kmalloc().  If @new_size is 0 and @p is not a
  * %NULL pointer, the object pointed to is freed.
  */
 void *krealloc(const void *p, size_t new_size, gfp_t flags)
index 157bb116dec883f7a5075b2078f83a7022080820..7f3096137b8a4dc288ba509a98429a1b048bc55f 100644 (file)
@@ -3131,7 +3131,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
        int nid;
 
        if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
-               for_each_node_state(nid, N_HIGH_MEMORY) {
+               for_each_node_state(nid, N_MEMORY) {
                        pg_data_t *pgdat = NODE_DATA(nid);
                        const struct cpumask *mask;
 
@@ -3187,7 +3187,7 @@ static int __init kswapd_init(void)
        int nid;
 
        swap_setup();
-       for_each_node_state(nid, N_HIGH_MEMORY)
+       for_each_node_state(nid, N_MEMORY)
                kswapd_run(nid);
        hotcpu_notifier(cpu_callback, 0);
        return 0;
index c7370579111b872943c56bd694dc0bd02121092d..df14808f0a360ea38a30f3217d2fdd301de4d6b3 100644 (file)
@@ -801,6 +801,8 @@ const char * const vmstat_text[] = {
        "thp_collapse_alloc",
        "thp_collapse_alloc_failed",
        "thp_split",
+       "thp_zero_page_alloc",
+       "thp_zero_page_alloc_failed",
 #endif
 
 #endif /* CONFIG_VM_EVENTS_COUNTERS */
@@ -930,7 +932,7 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg)
        pg_data_t *pgdat = (pg_data_t *)arg;
 
        /* check memoryless node */
-       if (!node_state(pgdat->node_id, N_HIGH_MEMORY))
+       if (!node_state(pgdat->node_id, N_MEMORY))
                return 0;
 
        seq_printf(m, "Page block order: %d\n", pageblock_order);
@@ -992,14 +994,16 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
                   "\n        high     %lu"
                   "\n        scanned  %lu"
                   "\n        spanned  %lu"
-                  "\n        present  %lu",
+                  "\n        present  %lu"
+                  "\n        managed  %lu",
                   zone_page_state(zone, NR_FREE_PAGES),
                   min_wmark_pages(zone),
                   low_wmark_pages(zone),
                   high_wmark_pages(zone),
                   zone->pages_scanned,
                   zone->spanned_pages,
-                  zone->present_pages);
+                  zone->present_pages,
+                  zone->managed_pages);
 
        for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
                seq_printf(m, "\n    %-12s %lu", vmstat_text[i],
@@ -1292,7 +1296,7 @@ static int unusable_show(struct seq_file *m, void *arg)
        pg_data_t *pgdat = (pg_data_t *)arg;
 
        /* check memoryless node */
-       if (!node_state(pgdat->node_id, N_HIGH_MEMORY))
+       if (!node_state(pgdat->node_id, N_MEMORY))
                return 0;
 
        walk_zones_in_node(m, pgdat, unusable_show_print);
index 0c0028463fa3479f5448053772b14fe11360fa49..b2bcbe2dc328ba8473227035c39a7ff467ee5659 100644 (file)
@@ -945,6 +945,13 @@ static int hidp_setup_hid(struct hidp_session *session,
        hid->hid_get_raw_report = hidp_get_raw_report;
        hid->hid_output_raw_report = hidp_output_raw_report;
 
+       /* True if device is blacklisted in drivers/hid/hid-core.c */
+       if (hid_ignore(hid)) {
+               hid_destroy_device(session->hid);
+               session->hid = NULL;
+               return -ENODEV;
+       }
+
        return 0;
 
 fault:
@@ -1017,7 +1024,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 
        if (req->rd_size > 0) {
                err = hidp_setup_hid(session, req);
-               if (err)
+               if (err && err != -ENODEV)
                        goto purge;
        }
 
index 977c3ee02e65ac26131cad067c3c56fa0aeb8802..1093c89095d8526278b1b8335f8fb0fc0f56e23b 100644 (file)
@@ -622,7 +622,7 @@ out:
 struct net_bridge_port_group *br_multicast_new_port_group(
                        struct net_bridge_port *port,
                        struct br_ip *group,
-                       struct net_bridge_port_group *next)
+                       struct net_bridge_port_group __rcu *next)
 {
        struct net_bridge_port_group *p;
 
@@ -632,7 +632,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
 
        p->addr = *group;
        p->port = port;
-       p->next = next;
+       rcu_assign_pointer(p->next, next);
        hlist_add_head(&p->mglist, &port->mglist);
        setup_timer(&p->timer, br_multicast_port_group_expired,
                    (unsigned long)p);
@@ -1138,7 +1138,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                                  struct sk_buff *skb)
 {
        const struct ipv6hdr *ip6h = ipv6_hdr(skb);
-       struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb);
+       struct mld_msg *mld;
        struct net_bridge_mdb_entry *mp;
        struct mld2_query *mld2q;
        struct net_bridge_port_group *p;
@@ -1165,6 +1165,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                if (max_delay)
                        group = &mld->mld_mca;
        } else if (skb->len >= sizeof(*mld2q)) {
+               u16 mrc;
                if (!pskb_may_pull(skb, sizeof(*mld2q))) {
                        err = -EINVAL;
                        goto out;
@@ -1172,7 +1173,8 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                mld2q = (struct mld2_query *)icmp6_hdr(skb);
                if (!mld2q->mld2q_nsrcs)
                        group = &mld2q->mld2q_mca;
-               max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(mld2q->mld2q_mrc) : 1;
+               mrc = ntohs(mld2q->mld2q_mrc);
+               max_delay = mrc ? MLDV2_MRC(mrc) : 1;
        }
 
        if (!group)
index 3b6dd3180492109cd8203b6933e7d0af9a3c9c87..ae566902d2bf33be59d944c618b3a9f6a9e133ad 100644 (file)
@@ -397,7 +397,7 @@ static inline void can_rcvlist_sff_proc_show_one(struct seq_file *m,
        int i;
        int all_empty = 1;
 
-       /* check wether at least one list is non-empty */
+       /* check whether at least one list is non-empty */
        for (i = 0; i < 0x800; i++)
                if (!hlist_empty(&d->rx_sff[i])) {
                        all_empty = 0;
index baf28611b3345030d42ea73d40a14284648717bb..291f2ed7cc311649a72700d65098b6d70ba338b5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Plugable TCP congestion control support and newReno
  * congestion control.
- * Based on ideas from I/O scheduler suport and Web100.
+ * Based on ideas from I/O scheduler support and Web100.
  *
  * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
  */
index 4c02e6ab96e7d2990adcda4afa1dc8bac63e1b5c..f2a007b7bde34d38f5b9b7f49c41ce77b136d04c 100644 (file)
@@ -151,8 +151,8 @@ static inline int ndisc_opt_addr_space(struct net_device *dev)
 static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
                                  unsigned short addr_type)
 {
-       int space = NDISC_OPT_SPACE(data_len);
        int pad   = ndisc_addr_option_pad(addr_type);
+       int space = NDISC_OPT_SPACE(data_len + pad);
 
        opt[0] = type;
        opt[1] = space>>3;
index c6560cc7a9d6468b6b3239afc81baaecccc3957e..698dc7e6f309847373541748c3cc4a2f40b67f58 100644 (file)
@@ -634,7 +634,7 @@ static inline void drv_reset_tsf(struct ieee80211_local *local,
 
 static inline int drv_tx_last_beacon(struct ieee80211_local *local)
 {
-       int ret = 0; /* default unsuported op for less congestion */
+       int ret = 0; /* default unsupported op for less congestion */
 
        might_sleep();
 
index 703fb26aa48d288fa3de60a79f58b43b56c43f78..9e312695c81813b0f9e854df721cbf49bc029f79 100644 (file)
@@ -32,7 +32,7 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger)
        return NULL;
 }
 
-/* return EEXIST if the same logger is registred, 0 on success. */
+/* return EEXIST if the same logger is registered, 0 on success. */
 int nf_log_register(u_int8_t pf, struct nf_logger *logger)
 {
        const struct nf_logger *llog;
index 0fa1e92ceac8869f026a8bf2a61724ce102919fe..fea22eb41b8242a1fb80d22c6aa2ca6515d78d0e 100644 (file)
@@ -614,10 +614,6 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 
                if (msg->msg_namelen < sizeof(*addr)) {
                        release_sock(sk);
-
-                       pr_err("Invalid socket address length %d\n",
-                              msg->msg_namelen);
-
                        return -EINVAL;
                }
 
index a5c95274127990b34de5af72f82e9135cf73aa85..9b9be5279f5dac83f53b1027f10144fe91d6bf98 100644 (file)
@@ -676,7 +676,7 @@ static ssize_t rfkill_soft_store(struct device *dev,
        rfkill_set_block(rfkill, state);
        mutex_unlock(&rfkill_global_mutex);
 
-       return err ?: count;
+       return count;
 }
 
 static u8 user_state_from_blocked(unsigned long state)
@@ -721,7 +721,7 @@ static ssize_t rfkill_state_store(struct device *dev,
        rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
        mutex_unlock(&rfkill_global_mutex);
 
-       return err ?: count;
+       return count;
 }
 
 static ssize_t rfkill_claim_show(struct device *dev,
index 32ab55b18281e7e614b7226c5029c10356ca854c..17a001bac2cc3c81ab052c2b603b02091bd924e0 100644 (file)
@@ -163,7 +163,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
 
        list_add(&null_key->key_list, &ep->endpoint_shared_keys);
 
-       /* Allocate and initialize transorms arrays for suported HMACs. */
+       /* Allocate and initialize transorms arrays for supported HMACs. */
        err = sctp_auth_init_hmacs(ep, gfp);
        if (err)
                goto nomem_hmacs;
index ebcd1eedb1151d050d51c5a5043e720f4797a33a..618ec7e216cae9bb17038c07ff5d87a75c8f6208 100644 (file)
@@ -4000,7 +4000,7 @@ static sctp_ierror_t sctp_sf_authenticate(struct net *net,
        chunk->subh.auth_hdr = auth_hdr;
        skb_pull(chunk->skb, sizeof(struct sctp_authhdr));
 
-       /* Make sure that we suport the HMAC algorithm from the auth
+       /* Make sure that we support the HMAC algorithm from the auth
         * chunk.
         */
        if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id))
index 46e7aff80d1a8d1b2ea054d1febc0e8ce0404c35..28b7615678154180c16d950252dea460c2e8e29e 100755 (executable)
@@ -137,6 +137,8 @@ use strict;
 # should document the "Context:" of the function, e.g. whether the functions
 # can be called form interrupts. Unlike other sections you can end it with an
 # empty line.
+# A non-void function should have a "Return:" section describing the return
+# value(s).
 # Example-sections should contain the string EXAMPLE so that they are marked
 # appropriately in DocBook.
 #
@@ -315,6 +317,7 @@ my $section_default = "Description";        # default section
 my $section_intro = "Introduction";
 my $section = $section_default;
 my $section_context = "Context";
+my $section_return = "Return";
 
 my $undescribed = "-- undescribed --";
 
@@ -2038,6 +2041,28 @@ sub check_sections($$$$$$) {
        }
 }
 
+##
+# Checks the section describing the return value of a function.
+sub check_return_section {
+        my $file = shift;
+        my $declaration_name = shift;
+        my $return_type = shift;
+
+        # Ignore an empty return type (It's a macro)
+        # Ignore functions with a "void" return type. (But don't ignore "void *")
+        if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
+                return;
+        }
+
+        if (!defined($sections{$section_return}) ||
+            $sections{$section_return} eq "") {
+                print STDERR "Warning(${file}:$.): " .
+                        "No description found for return value of " .
+                        "'$declaration_name'\n";
+                ++$warnings;
+        }
+}
+
 ##
 # takes a function prototype and the name of the current file being
 # processed and spits out all the details stored in the global
@@ -2109,6 +2134,15 @@ sub dump_function($$) {
        my $prms = join " ", @parameterlist;
        check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
 
+        # This check emits a lot of warnings at the moment, because many
+        # functions don't have a 'Return' doc section. So until the number
+        # of warnings goes sufficiently down, the check is only performed in
+        # verbose mode.
+        # TODO: always perform the check.
+        if ($verbose) {
+                check_return_section($file, $declaration_name, $return_type);
+        }
+
     output_declaration($declaration_name,
                       'function',
                       {'function' => $declaration_name,
index a58f712605d83105b6d32e1b966436a454331a90..86468f385fc8ef1ac0422afb117114f8d81b6ba4 100644 (file)
@@ -358,8 +358,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
 
                switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
-                       if (ret)
-                               break;
                case -ENOKEY: /* negative key */
                        ret = key_ref;
                        break;
index 5119fdabcb98728a0d0520fd9a69c75a8fe11f6a..aa5d8034890b5f6d3fc7ede653862e17bf46b9db 100644 (file)
@@ -786,7 +786,7 @@ static int aaci_resume(struct amba_device *dev)
 #endif
 
 
-static struct ac97_pcm ac97_defs[] __devinitdata = {
+static struct ac97_pcm ac97_defs[] = {
        [0] = { /* Front PCM */
                .exclusive = 1,
                .r = {
@@ -832,7 +832,7 @@ static struct snd_ac97_bus_ops aaci_bus_ops = {
        .read   = aaci_ac97_read,
 };
 
-static int __devinit aaci_probe_ac97(struct aaci *aaci)
+static int aaci_probe_ac97(struct aaci *aaci)
 {
        struct snd_ac97_template ac97_template;
        struct snd_ac97_bus *ac97_bus;
@@ -893,7 +893,7 @@ static void aaci_free_card(struct snd_card *card)
                iounmap(aaci->base);
 }
 
-static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
+static struct aaci *aaci_init_card(struct amba_device *dev)
 {
        struct aaci *aaci;
        struct snd_card *card;
@@ -926,7 +926,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
        return aaci;
 }
 
-static int __devinit aaci_init_pcm(struct aaci *aaci)
+static int aaci_init_pcm(struct aaci *aaci)
 {
        struct snd_pcm *pcm;
        int ret;
@@ -948,7 +948,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
        return ret;
 }
 
-static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
+static unsigned int aaci_size_fifo(struct aaci *aaci)
 {
        struct aaci_runtime *aacirun = &aaci->playback;
        int i;
@@ -984,8 +984,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
        return i;
 }
 
-static int __devinit aaci_probe(struct amba_device *dev,
-       const struct amba_id *id)
+static int aaci_probe(struct amba_device *dev,
+                     const struct amba_id *id)
 {
        struct aaci *aaci;
        int ret, i;
@@ -1072,7 +1072,7 @@ static int __devinit aaci_probe(struct amba_device *dev,
        return ret;
 }
 
-static int __devexit aaci_remove(struct amba_device *dev)
+static int aaci_remove(struct amba_device *dev)
 {
        struct snd_card *card = amba_get_drvdata(dev);
 
@@ -1104,7 +1104,7 @@ static struct amba_driver aaci_driver = {
                .name   = DRIVER_NAME,
        },
        .probe          = aaci_probe,
-       .remove         = __devexit_p(aaci_remove),
+       .remove         = aaci_remove,
        .suspend        = aaci_suspend,
        .resume         = aaci_resume,
        .id_table       = aaci_ids,
index 48d7c0aa5073d43897b126fdbc743f84350f1783..6fc0ae90e5b1de99992b288d35035e2a0d061df2 100644 (file)
@@ -314,7 +314,7 @@ int pxa2xx_ac97_hw_resume(void)
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
 #endif
 
-int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
+int pxa2xx_ac97_hw_probe(struct platform_device *dev)
 {
        int ret;
        pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
index 4e1fda75c1c9fbc335b6b45fd34871e8ce0a1898..ec54be4efff09c48ec1ff7a5b09318a831ac563e 100644 (file)
@@ -163,7 +163,7 @@ static int pxa2xx_ac97_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume);
 #endif
 
-static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+static int pxa2xx_ac97_probe(struct platform_device *dev)
 {
        struct snd_card *card;
        struct snd_ac97_bus *ac97_bus;
@@ -224,7 +224,7 @@ err_dev:
        return ret;
 }
 
-static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
+static int pxa2xx_ac97_remove(struct platform_device *dev)
 {
        struct snd_card *card = platform_get_drvdata(dev);
 
@@ -239,7 +239,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
 
 static struct platform_driver pxa2xx_ac97_driver = {
        .probe          = pxa2xx_ac97_probe,
-       .remove         = __devexit_p(pxa2xx_ac97_remove),
+       .remove         = pxa2xx_ac97_remove,
        .driver         = {
                .name   = "pxa2xx-ac97",
                .owner  = THIS_MODULE,
index 277ebce23a452be6cb027590eb997c278971eba8..071ce1b5f2b40bb7b6d1558ee28f42fc1a99dd96 100644 (file)
@@ -309,7 +309,7 @@ static struct snd_pcm_ops atmel_abdac_ops = {
        .pointer        = atmel_abdac_pointer,
 };
 
-static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac)
+static int atmel_abdac_pcm_new(struct atmel_abdac *dac)
 {
        struct snd_pcm_hardware hw = atmel_abdac_hw;
        struct snd_pcm *pcm;
@@ -386,7 +386,7 @@ static int set_sample_rates(struct atmel_abdac *dac)
        return retval;
 }
 
-static int __devinit atmel_abdac_probe(struct platform_device *pdev)
+static int atmel_abdac_probe(struct platform_device *pdev)
 {
        struct snd_card         *card;
        struct atmel_abdac      *dac;
@@ -567,7 +567,7 @@ static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume
 #define ATMEL_ABDAC_PM_OPS     NULL
 #endif
 
-static int __devexit atmel_abdac_remove(struct platform_device *pdev)
+static int atmel_abdac_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
        struct atmel_abdac *dac = get_dac(card);
@@ -589,7 +589,7 @@ static int __devexit atmel_abdac_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver atmel_abdac_driver = {
-       .remove         = __devexit_p(atmel_abdac_remove),
+       .remove         = atmel_abdac_remove,
        .driver         = {
                .name   = "atmel_abdac",
                .owner  = THIS_MODULE,
index 9052aff37f6460fcdaba020f0b44d85484243c96..79d6bda58753a2c575969a5fea2c56008eb9daf6 100644 (file)
@@ -728,7 +728,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
        return retval;
 }
 
-static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
+static struct ac97_pcm at91_ac97_pcm_defs[] = {
        /* Playback */
        {
                .exclusive = 1,
@@ -756,7 +756,7 @@ static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
        },
 };
 
-static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
+static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
 {
        struct snd_pcm          *pcm;
        struct snd_pcm_hardware hw = atmel_ac97c_hw;
@@ -902,7 +902,7 @@ static void atmel_ac97c_reset(struct atmel_ac97c *chip)
        }
 }
 
-static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
+static int atmel_ac97c_probe(struct platform_device *pdev)
 {
        struct snd_card                 *card;
        struct atmel_ac97c              *chip;
@@ -1168,7 +1168,7 @@ static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume
 #define ATMEL_AC97C_PM_OPS     NULL
 #endif
 
-static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
+static int atmel_ac97c_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
        struct atmel_ac97c *chip = get_chip(card);
@@ -1205,7 +1205,7 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver atmel_ac97c_driver = {
-       .remove         = __devexit_p(atmel_ac97c_remove),
+       .remove         = atmel_ac97c_remove,
        .driver         = {
                .name   = "atmel_ac97c",
                .owner  = THIS_MODULE,
index 71cc3ddf5c156075be1bfbee065e9899af8f806d..727ac44d39f4a64f7ba203d8dd839caaa66c15ec 100644 (file)
@@ -199,12 +199,13 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
 snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
 {
        struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
-       int stream = snd_pcm_plug_stream(plug);
+       int stream;
 
        if (snd_BUG_ON(!plug))
                return -ENXIO;
        if (drv_frames == 0)
                return 0;
+       stream = snd_pcm_plug_stream(plug);
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                plugin = snd_pcm_plug_last(plug);
                while (plugin && drv_frames > 0) {
@@ -230,13 +231,14 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
 {
        struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
        snd_pcm_sframes_t frames;
-       int stream = snd_pcm_plug_stream(plug);
+       int stream;
        
        if (snd_BUG_ON(!plug))
                return -ENXIO;
        if (clt_frames == 0)
                return 0;
        frames = clt_frames;
+       stream = snd_pcm_plug_stream(plug);
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                plugin = snd_pcm_plug_first(plug);
                while (plugin && frames > 0) {
index 030102caeee96b8080d9af6f2c99217278ec5a86..61798f85d0301f51087312551a677167792eadf7 100644 (file)
@@ -981,8 +981,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
                       PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
        kfree(runtime->hw_constraints.rules);
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
-       if (runtime->hwptr_log)
-               kfree(runtime->hwptr_log);
+       kfree(runtime->hwptr_log);
 #endif
        kfree(runtime);
        substream->runtime = NULL;
index 91cdf9435feca986cf3be980412b7d21a9dddecd..af49721ba0e38310183adbe01dcb1f8acaa3d4ab 100644 (file)
@@ -190,7 +190,9 @@ struct snd_pcm_status32 {
        u32 avail_max;
        u32 overrange;
        s32 suspended_state;
-       unsigned char reserved[60];
+       u32 reserved_alignment;
+       struct compat_timespec audio_tstamp;
+       unsigned char reserved[56-sizeof(struct compat_timespec)];
 } __attribute__((packed));
 
 
@@ -205,17 +207,16 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
                return err;
 
        if (put_user(status.state, &src->state) ||
-           put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) ||
-           put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) ||
-           put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
-           put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+           compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
+           compat_put_timespec(&status.tstamp, &src->tstamp) ||
            put_user(status.appl_ptr, &src->appl_ptr) ||
            put_user(status.hw_ptr, &src->hw_ptr) ||
            put_user(status.delay, &src->delay) ||
            put_user(status.avail, &src->avail) ||
            put_user(status.avail_max, &src->avail_max) ||
            put_user(status.overrange, &src->overrange) ||
-           put_user(status.suspended_state, &src->suspended_state))
+           put_user(status.suspended_state, &src->suspended_state) ||
+           compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp))
                return -EFAULT;
 
        return err;
@@ -364,6 +365,7 @@ struct snd_pcm_mmap_status32 {
        u32 hw_ptr;
        struct compat_timespec tstamp;
        s32 suspended_state;
+       struct compat_timespec audio_tstamp;
 } __attribute__((packed));
 
 struct snd_pcm_mmap_control32 {
@@ -426,12 +428,14 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
        sstatus.hw_ptr = status->hw_ptr % boundary;
        sstatus.tstamp = status->tstamp;
        sstatus.suspended_state = status->suspended_state;
+       sstatus.audio_tstamp = status->audio_tstamp;
        snd_pcm_stream_unlock_irq(substream);
        if (put_user(sstatus.state, &src->s.status.state) ||
            put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
-           put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) ||
-           put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) ||
+           compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
            put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+           compat_put_timespec(&sstatus.audio_tstamp,
+                   &src->s.status.audio_tstamp) ||
            put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
            put_user(scontrol.avail_min, &src->c.control.avail_min))
                return -EFAULT;
index f42c10a43315afdbe3761e6ef86d4fe220387124..c4840ff75d00a97ebbe12e3820ab43dd743a785e 100644 (file)
@@ -316,6 +316,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        unsigned long jdelta;
        unsigned long curr_jiffies;
        struct timespec curr_tstamp;
+       struct timespec audio_tstamp;
+       int crossed_boundary = 0;
 
        old_hw_ptr = runtime->status->hw_ptr;
 
@@ -327,9 +329,14 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
         */
        pos = substream->ops->pointer(substream);
        curr_jiffies = jiffies;
-       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
                snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
 
+               if ((runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) &&
+                       (substream->ops->wall_clock))
+                       substream->ops->wall_clock(substream, &audio_tstamp);
+       }
+
        if (pos == SNDRV_PCM_POS_XRUN) {
                xrun(substream);
                return -EPIPE;
@@ -360,8 +367,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                        hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
                        if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
                                hw_base += runtime->buffer_size;
-                               if (hw_base >= runtime->boundary)
+                               if (hw_base >= runtime->boundary) {
                                        hw_base = 0;
+                                       crossed_boundary++;
+                               }
                                new_hw_ptr = hw_base + pos;
                                goto __delta;
                        }
@@ -371,8 +380,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        /* pointer crosses the end of the ring buffer */
        if (new_hw_ptr < old_hw_ptr) {
                hw_base += runtime->buffer_size;
-               if (hw_base >= runtime->boundary)
+               if (hw_base >= runtime->boundary) {
                        hw_base = 0;
+                       crossed_boundary++;
+               }
                new_hw_ptr = hw_base + pos;
        }
       __delta:
@@ -410,8 +421,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                while (hdelta > xrun_threshold) {
                        delta += runtime->buffer_size;
                        hw_base += runtime->buffer_size;
-                       if (hw_base >= runtime->boundary)
+                       if (hw_base >= runtime->boundary) {
                                hw_base = 0;
+                               crossed_boundary++;
+                       }
                        new_hw_ptr = hw_base + pos;
                        hdelta -= runtime->hw_ptr_buffer_jiffies;
                }
@@ -456,8 +469,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                /* the delta value is small or zero in most cases */
                while (delta > 0) {
                        new_hw_ptr += runtime->period_size;
-                       if (new_hw_ptr >= runtime->boundary)
+                       if (new_hw_ptr >= runtime->boundary) {
                                new_hw_ptr -= runtime->boundary;
+                               crossed_boundary--;
+                       }
                        delta--;
                }
                /* align hw_base to buffer_size */
@@ -507,9 +522,35 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        runtime->hw_ptr_base = hw_base;
        runtime->status->hw_ptr = new_hw_ptr;
        runtime->hw_ptr_jiffies = curr_jiffies;
-       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+       if (crossed_boundary) {
+               snd_BUG_ON(crossed_boundary != 1);
+               runtime->hw_ptr_wrap += runtime->boundary;
+       }
+       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
                runtime->status->tstamp = curr_tstamp;
 
+               if (!(runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)) {
+                       /*
+                        * no wall clock available, provide audio timestamp
+                        * derived from pointer position+delay
+                        */
+                       u64 audio_frames, audio_nsecs;
+
+                       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                               audio_frames = runtime->hw_ptr_wrap
+                                       + runtime->status->hw_ptr
+                                       - runtime->delay;
+                       else
+                               audio_frames = runtime->hw_ptr_wrap
+                                       + runtime->status->hw_ptr
+                                       + runtime->delay;
+                       audio_nsecs = div_u64(audio_frames * 1000000000LL,
+                                       runtime->rate);
+                       audio_tstamp = ns_to_timespec(audio_nsecs);
+               }
+               runtime->status->audio_tstamp = audio_tstamp;
+       }
+
        return snd_pcm_update_state(substream, runtime);
 }
 
@@ -1661,8 +1702,10 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
        if (snd_pcm_running(substream) &&
            snd_pcm_update_hw_ptr(substream) >= 0)
                runtime->status->hw_ptr %= runtime->buffer_size;
-       else
+       else {
                runtime->status->hw_ptr = 0;
+               runtime->hw_ptr_wrap = 0;
+       }
        snd_pcm_stream_unlock_irqrestore(substream, flags);
        return 0;
 }
index f9ddecf2f4cd7a17ebc0d5f0ba92405c03ab904a..09b4286c65f9d7d6e7ab8abed498ad2d7f96e737 100644 (file)
@@ -602,6 +602,8 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
                snd_pcm_update_hw_ptr(substream);
                if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
                        status->tstamp = runtime->status->tstamp;
+                       status->audio_tstamp =
+                               runtime->status->audio_tstamp;
                        goto _tstamp_end;
                }
        }
@@ -1998,7 +2000,7 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
        if (runtime->dma_bytes) {
                err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
                if (err < 0)
-                       return -EINVAL;
+                       return err;
        }
 
        if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
index 60e8fc1b344041d27086d4dfde7786b8d8ac85ec..040c60e1da28f346aa049737802a43ce853940d3 100644 (file)
@@ -66,7 +66,7 @@ struct ops_list {
        /* operators */
        struct snd_seq_dev_ops ops;
 
-       /* registred devices */
+       /* registered devices */
        struct list_head dev_list;      /* list of devices */
        int num_devices;        /* number of associated devices */
        int num_init_devices;   /* number of initialized devices */
index fe5ae09ffccba585392e786f26942265e0d90650..7d02c322ed9398179ea6bde8a0683a457630549e 100644 (file)
@@ -14,6 +14,7 @@ config SND_OPL4_LIB
 
 config SND_VX_LIB
        tristate
+       select FW_LOADER
        select SND_HWDEP
        select SND_PCM
 
@@ -35,7 +36,6 @@ config SND_PCSP
        tristate "PC-Speaker support (READ HELP!)"
        depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS
        depends on INPUT
-       depends on EXPERIMENTAL
        select SND_PCM
        help
          If you don't have a sound card in your computer, you can include a
index 0fe6d64ff840f02cdb17df4c27721f8e9a953cb5..3d822328d383211acf226daf6dce7c5252991c02 100644 (file)
@@ -120,7 +120,6 @@ struct loopback_pcm {
        unsigned int last_drift;
        unsigned long last_jiffies;
        struct timer_list timer;
-       spinlock_t timer_lock;
 };
 
 static struct platform_device *devices[SNDRV_CARDS];
@@ -166,12 +165,12 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
        return get_setup(dpcm)->rate_shift;
 }
 
+/* call in cable->lock */
 static void loopback_timer_start(struct loopback_pcm *dpcm)
 {
        unsigned long tick;
        unsigned int rate_shift = get_rate_shift(dpcm);
 
-       spin_lock(&dpcm->timer_lock);
        if (rate_shift != dpcm->pcm_rate_shift) {
                dpcm->pcm_rate_shift = rate_shift;
                dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -184,15 +183,13 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
        tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
        dpcm->timer.expires = jiffies + tick;
        add_timer(&dpcm->timer);
-       spin_unlock(&dpcm->timer_lock);
 }
 
+/* call in cable->lock */
 static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
 {
-       spin_lock(&dpcm->timer_lock);
        del_timer(&dpcm->timer);
        dpcm->timer.expires = 0;
-       spin_unlock(&dpcm->timer_lock);
 }
 
 #define CABLE_VALID_PLAYBACK   (1 << SNDRV_PCM_STREAM_PLAYBACK)
@@ -274,8 +271,8 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
                spin_lock(&cable->lock);        
                cable->running |= stream;
                cable->pause &= ~stream;
-               spin_unlock(&cable->lock);
                loopback_timer_start(dpcm);
+               spin_unlock(&cable->lock);
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        loopback_active_notify(dpcm);
                break;
@@ -283,23 +280,23 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
                spin_lock(&cable->lock);        
                cable->running &= ~stream;
                cable->pause &= ~stream;
-               spin_unlock(&cable->lock);
                loopback_timer_stop(dpcm);
+               spin_unlock(&cable->lock);
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        loopback_active_notify(dpcm);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                spin_lock(&cable->lock);        
                cable->pause |= stream;
-               spin_unlock(&cable->lock);
                loopback_timer_stop(dpcm);
+               spin_unlock(&cable->lock);
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                spin_lock(&cable->lock);
                dpcm->last_jiffies = jiffies;
                cable->pause &= ~stream;
-               spin_unlock(&cable->lock);
                loopback_timer_start(dpcm);
+               spin_unlock(&cable->lock);
                break;
        default:
                return -EINVAL;
@@ -477,6 +474,7 @@ static inline void bytepos_finish(struct loopback_pcm *dpcm,
        dpcm->buf_pos %= dpcm->pcm_buffer_size;
 }
 
+/* call in cable->lock */
 static unsigned int loopback_pos_update(struct loopback_cable *cable)
 {
        struct loopback_pcm *dpcm_play =
@@ -485,9 +483,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
                        cable->streams[SNDRV_PCM_STREAM_CAPTURE];
        unsigned long delta_play = 0, delta_capt = 0;
        unsigned int running, count1, count2;
-       unsigned long flags;
 
-       spin_lock_irqsave(&cable->lock, flags);
        running = cable->running ^ cable->pause;
        if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
                delta_play = jiffies - dpcm_play->last_jiffies;
@@ -529,32 +525,39 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
        bytepos_finish(dpcm_play, count1);
        bytepos_finish(dpcm_capt, count1);
  unlock:
-       spin_unlock_irqrestore(&cable->lock, flags);
        return running;
 }
 
 static void loopback_timer_function(unsigned long data)
 {
        struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
-       unsigned int running;
+       unsigned long flags;
 
-       running = loopback_pos_update(dpcm->cable);
-       if (running & (1 << dpcm->substream->stream)) {
+       spin_lock_irqsave(&dpcm->cable->lock, flags);
+       if (loopback_pos_update(dpcm->cable) & (1 << dpcm->substream->stream)) {
                loopback_timer_start(dpcm);
                if (dpcm->period_update_pending) {
                        dpcm->period_update_pending = 0;
+                       spin_unlock_irqrestore(&dpcm->cable->lock, flags);
+                       /* need to unlock before calling below */
                        snd_pcm_period_elapsed(dpcm->substream);
+                       return;
                }
        }
+       spin_unlock_irqrestore(&dpcm->cable->lock, flags);
 }
 
 static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct loopback_pcm *dpcm = runtime->private_data;
+       snd_pcm_uframes_t pos;
 
+       spin_lock(&dpcm->cable->lock);
        loopback_pos_update(dpcm->cable);
-       return bytes_to_frames(runtime, dpcm->buf_pos);
+       pos = dpcm->buf_pos;
+       spin_unlock(&dpcm->cable->lock);
+       return bytes_to_frames(runtime, pos);
 }
 
 static struct snd_pcm_hardware loopback_pcm_hardware =
@@ -672,7 +675,6 @@ static int loopback_open(struct snd_pcm_substream *substream)
        dpcm->substream = substream;
        setup_timer(&dpcm->timer, loopback_timer_function,
                    (unsigned long)dpcm);
-       spin_lock_init(&dpcm->timer_lock);
 
        cable = loopback->cables[substream->number][dev];
        if (!cable) {
@@ -772,8 +774,8 @@ static struct snd_pcm_ops loopback_capture_ops = {
        .mmap =         snd_pcm_lib_mmap_vmalloc,
 };
 
-static int __devinit loopback_pcm_new(struct loopback *loopback,
-                                     int device, int substreams)
+static int loopback_pcm_new(struct loopback *loopback,
+                           int device, int substreams)
 {
        struct snd_pcm *pcm;
        int err;
@@ -947,7 +949,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new loopback_controls[]  __devinitdata = {
+static struct snd_kcontrol_new loopback_controls[]  = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         "PCM Rate Shift 100000",
@@ -996,7 +998,7 @@ static struct snd_kcontrol_new loopback_controls[]  __devinitdata = {
 }
 };
 
-static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
+static int loopback_mixer_new(struct loopback *loopback, int notify)
 {
        struct snd_card *card = loopback->card;
        struct snd_pcm *pcm;
@@ -1109,7 +1111,7 @@ static void print_cable_info(struct snd_info_entry *entry,
        mutex_unlock(&loopback->cable_lock);
 }
 
-static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
+static int loopback_proc_new(struct loopback *loopback, int cidx)
 {
        char name[32];
        struct snd_info_entry *entry;
@@ -1130,7 +1132,7 @@ static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
 
 #endif
 
-static int __devinit loopback_probe(struct platform_device *devptr)
+static int loopback_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct loopback *loopback;
@@ -1175,7 +1177,7 @@ static int __devinit loopback_probe(struct platform_device *devptr)
        return err;
 }
 
-static int __devexit loopback_remove(struct platform_device *devptr)
+static int loopback_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -1213,7 +1215,7 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
 
 static struct platform_driver loopback_driver = {
        .probe          = loopback_probe,
-       .remove         = __devexit_p(loopback_remove),
+       .remove         = loopback_remove,
        .driver         = {
                .name   = SND_LOOPBACK_DRIVER,
                .owner  = THIS_MODULE,
index 54bb6644a598a8177e3fbec4220df2966abd6131..fd798f753609c81a64e6391132d73543cfbf1761 100644 (file)
@@ -134,6 +134,9 @@ struct snd_dummy {
        spinlock_t mixer_lock;
        int mixer_volume[MIXER_ADDR_LAST+1][2];
        int capture_source[MIXER_ADDR_LAST+1][2];
+       int iobox;
+       struct snd_kcontrol *cd_volume_ctl;
+       struct snd_kcontrol *cd_switch_ctl;
        const struct dummy_timer_ops *timer_ops;
 };
 
@@ -685,8 +688,8 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
        .page =         dummy_pcm_page,
 };
 
-static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
-                                       int substreams)
+static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
+                             int substreams)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_ops *ops;
@@ -817,6 +820,57 @@ static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
        return change;
 }
 
+static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *info)
+{
+       const char *const names[] = { "None", "CD Player" };
+
+       return snd_ctl_enum_info(info, 1, 2, names);
+}
+
+static int snd_dummy_iobox_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+
+       value->value.enumerated.item[0] = dummy->iobox;
+       return 0;
+}
+
+static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+       int changed;
+
+       if (value->value.enumerated.item[0] > 1)
+               return -EINVAL;
+
+       changed = value->value.enumerated.item[0] != dummy->iobox;
+       if (changed) {
+               dummy->iobox = value->value.enumerated.item[0];
+
+               if (dummy->iobox) {
+                       dummy->cd_volume_ctl->vd[0].access &=
+                               ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+                       dummy->cd_switch_ctl->vd[0].access &=
+                               ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+               } else {
+                       dummy->cd_volume_ctl->vd[0].access |=
+                               SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+                       dummy->cd_switch_ctl->vd[0].access |=
+                               SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+               }
+
+               snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,
+                              &dummy->cd_volume_ctl->id);
+               snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,
+                              &dummy->cd_switch_ctl->id);
+       }
+
+       return changed;
+}
+
 static struct snd_kcontrol_new snd_dummy_controls[] = {
 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
 DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
@@ -827,22 +881,37 @@ DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE),
 DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
 DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC),
 DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
-DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD)
+DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD),
+{
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name  = "External I/O Box",
+       .info  = snd_dummy_iobox_info,
+       .get   = snd_dummy_iobox_get,
+       .put   = snd_dummy_iobox_put,
+},
 };
 
-static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
+static int snd_card_dummy_new_mixer(struct snd_dummy *dummy)
 {
        struct snd_card *card = dummy->card;
+       struct snd_kcontrol *kcontrol;
        unsigned int idx;
        int err;
 
        spin_lock_init(&dummy->mixer_lock);
        strcpy(card->mixername, "Dummy Mixer");
+       dummy->iobox = 1;
 
        for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
-               err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy));
+               kcontrol = snd_ctl_new1(&snd_dummy_controls[idx], dummy);
+               err = snd_ctl_add(card, kcontrol);
                if (err < 0)
                        return err;
+               if (!strcmp(kcontrol->id.name, "CD Volume"))
+                       dummy->cd_volume_ctl = kcontrol;
+               else if (!strcmp(kcontrol->id.name, "CD Capture Switch"))
+                       dummy->cd_switch_ctl = kcontrol;
+
        }
        return 0;
 }
@@ -962,7 +1031,7 @@ static void dummy_proc_write(struct snd_info_entry *entry,
        }
 }
 
-static void __devinit dummy_proc_init(struct snd_dummy *chip)
+static void dummy_proc_init(struct snd_dummy *chip)
 {
        struct snd_info_entry *entry;
 
@@ -977,7 +1046,7 @@ static void __devinit dummy_proc_init(struct snd_dummy *chip)
 #define dummy_proc_init(x)
 #endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */
 
-static int __devinit snd_dummy_probe(struct platform_device *devptr)
+static int snd_dummy_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_dummy *dummy;
@@ -1057,7 +1126,7 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
        return err;
 }
 
-static int __devexit snd_dummy_remove(struct platform_device *devptr)
+static int snd_dummy_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -1093,7 +1162,7 @@ static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);
 
 static struct platform_driver snd_dummy_driver = {
        .probe          = snd_dummy_probe,
-       .remove         = __devexit_p(snd_dummy_remove),
+       .remove         = snd_dummy_remove,
        .driver         = {
                .name   = SND_DUMMY_DRIVER,
                .owner  = THIS_MODULE,
index 6c83b1aed288a8d8a7bb08bf142adf954218efe6..8125a7e95ee4dd0bf93dbd07291abb17dbcd1347 100644 (file)
@@ -1063,7 +1063,7 @@ snd_ml403_ac97cr_codec_write(struct snd_ac97 *ac97, unsigned short reg,
        return;
 }
 
-static int __devinit
+static int
 snd_ml403_ac97cr_chip_init(struct snd_ml403_ac97cr *ml403_ac97cr)
 {
        unsigned long end_time;
@@ -1108,7 +1108,7 @@ static int snd_ml403_ac97cr_dev_free(struct snd_device *snddev)
        return snd_ml403_ac97cr_free(ml403_ac97cr);
 }
 
-static int __devinit
+static int
 snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
                        struct snd_ml403_ac97cr **rml403_ac97cr)
 {
@@ -1204,7 +1204,7 @@ static void snd_ml403_ac97cr_mixer_free(struct snd_ac97 *ac97)
        PDEBUG(INIT_INFO, "mixer_free(): (done)\n");
 }
 
-static int __devinit
+static int
 snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
 {
        struct snd_ac97_bus *bus;
@@ -1237,7 +1237,7 @@ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
        return err;
 }
 
-static int __devinit
+static int
 snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
                     struct snd_pcm **rpcm)
 {
@@ -1268,7 +1268,7 @@ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
        return 0;
 }
 
-static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev)
+static int snd_ml403_ac97cr_probe(struct platform_device *pfdev)
 {
        struct snd_card *card;
        struct snd_ml403_ac97cr *ml403_ac97cr = NULL;
index bc03a2046c9c60e6f7f939df86537408e70bb04d..da1a29bfc85d7a21c91f8efb6f29edaae6fa0677 100644 (file)
@@ -100,7 +100,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
        return err;
 }
 
-static int __devinit snd_mpu401_probe(struct platform_device *devptr)
+static int snd_mpu401_probe(struct platform_device *devptr)
 {
        int dev = devptr->id;
        int err;
@@ -126,7 +126,7 @@ static int __devinit snd_mpu401_probe(struct platform_device *devptr)
        return 0;
 }
 
-static int __devexit snd_mpu401_remove(struct platform_device *devptr)
+static int snd_mpu401_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -137,7 +137,7 @@ static int __devexit snd_mpu401_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_mpu401_driver = {
        .probe          = snd_mpu401_probe,
-       .remove         = __devexit_p(snd_mpu401_remove),
+       .remove         = snd_mpu401_remove,
        .driver         = {
                .name   = SND_MPU401_DRIVER,
                .owner  = THIS_MODULE,
@@ -156,8 +156,8 @@ static struct pnp_device_id snd_mpu401_pnpids[] = {
 
 MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
 
-static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
-                                const struct pnp_device_id *id)
+static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
+                         const struct pnp_device_id *id)
 {
        if (!pnp_port_valid(device, 0) ||
            pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
@@ -182,8 +182,8 @@ static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
        return 0;
 }
 
-static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
-                                         const struct pnp_device_id *id)
+static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
+                               const struct pnp_device_id *id)
 {
        static int dev;
        struct snd_card *card;
@@ -211,7 +211,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
        return -ENODEV;
 }
 
-static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
+static void snd_mpu401_pnp_remove(struct pnp_dev *dev)
 {
        struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
 
@@ -223,7 +223,7 @@ static struct pnp_driver snd_mpu401_pnp_driver = {
        .name = "mpu401",
        .id_table = snd_mpu401_pnpids,
        .probe = snd_mpu401_pnp_probe,
-       .remove = __devexit_p(snd_mpu401_pnp_remove),
+       .remove = snd_mpu401_pnp_remove,
 };
 #else
 static struct pnp_driver snd_mpu401_pnp_driver;
index cad73af3860cd0f56fb82ee9da909a53627dcafc..9f1815b99a15235ec2923e39ed040998ee7a3448 100644 (file)
@@ -583,7 +583,7 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
 /*
  * get ISA resources
  */
-static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
+static int snd_mtpav_get_ISA(struct mtpav *mcard)
 {
        if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
                snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
@@ -619,8 +619,8 @@ static struct snd_rawmidi_ops snd_mtpav_input = {
  * get RAWMIDI resources
  */
 
-static void __devinit snd_mtpav_set_name(struct mtpav *chip,
-                                     struct snd_rawmidi_substream *substream)
+static void snd_mtpav_set_name(struct mtpav *chip,
+                              struct snd_rawmidi_substream *substream)
 {
        if (substream->number >= 0 && substream->number < chip->num_ports)
                sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
@@ -634,7 +634,7 @@ static void __devinit snd_mtpav_set_name(struct mtpav *chip,
                strcpy(substream->name, "MTP broadcast");
 }
 
-static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
+static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
 {
        int rval;
        struct snd_rawmidi *rawmidi;
@@ -691,7 +691,7 @@ static void snd_mtpav_free(struct snd_card *card)
 
 /*
  */
-static int __devinit snd_mtpav_probe(struct platform_device *dev)
+static int snd_mtpav_probe(struct platform_device *dev)
 {
        struct snd_card *card;
        int err;
@@ -746,7 +746,7 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev)
        return err;
 }
 
-static int __devexit snd_mtpav_remove(struct platform_device *devptr)
+static int snd_mtpav_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -757,7 +757,7 @@ static int __devexit snd_mtpav_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_mtpav_driver = {
        .probe          = snd_mtpav_probe,
-       .remove         = __devexit_p(snd_mtpav_remove),
+       .remove         = snd_mtpav_remove,
        .driver         = {
                .name   = SND_MTPAV_DRIVER,
                .owner  = THIS_MODULE,
index 2d5514b0a2909d3ad47fd9ab1b81d8c47e0b9917..4e0dd22ba08eddbd7aa744c12069d4417d4f7307 100644 (file)
@@ -83,9 +83,9 @@ static int snd_mts64_free(struct mts64 *mts)
        return 0;
 }
 
-static int __devinit snd_mts64_create(struct snd_card *card, 
-                                     struct pardevice *pardev, 
-                                     struct mts64 **rchip)
+static int snd_mts64_create(struct snd_card *card,
+                           struct pardevice *pardev,
+                           struct mts64 **rchip)
 {
        struct mts64 *mts;
 
@@ -214,7 +214,7 @@ static int mts64_device_ready(struct parport *p)
  *  0 init ok
  *  -EIO failure
  */
-static int __devinit mts64_device_init(struct parport *p)
+static int mts64_device_init(struct parport *p)
 {
        int i;
 
@@ -290,7 +290,7 @@ static u8 mts64_map_midi_input(u8 c)
  *  0       device found
  *  -ENODEV no device
  */
-static int __devinit mts64_probe(struct parport *p)
+static int mts64_probe(struct parport *p)
 {
        u8 c;
 
@@ -483,7 +483,7 @@ __out:
        return changed;
 }
 
-static struct snd_kcontrol_new mts64_ctl_smpte_switch __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Playback Switch",
        .index = 0,
@@ -556,7 +556,7 @@ static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl,
        return changed;
 }
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Hours",
        .index = 0,
@@ -567,7 +567,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = {
        .put  = snd_mts64_ctl_smpte_time_put
 };
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Minutes",
        .index = 0,
@@ -578,7 +578,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = {
        .put  = snd_mts64_ctl_smpte_time_put
 };
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Seconds",
        .index = 0,
@@ -589,7 +589,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = {
        .put  = snd_mts64_ctl_smpte_time_put
 };
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_frames __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Frames",
        .index = 0,
@@ -651,7 +651,7 @@ static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl,
        return changed;
 }
 
-static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = {
+static struct snd_kcontrol_new mts64_ctl_smpte_fps = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Fps",
        .index = 0,
@@ -663,11 +663,11 @@ static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = {
 };
 
 
-static int __devinit snd_mts64_ctl_create(struct snd_card *card, 
-                                         struct mts64 *mts) 
+static int snd_mts64_ctl_create(struct snd_card *card,
+                               struct mts64 *mts)
 {
        int err, i;
-       static struct snd_kcontrol_new *control[] __devinitdata = {
+       static struct snd_kcontrol_new *control[] = {
                &mts64_ctl_smpte_switch,
                &mts64_ctl_smpte_time_hours,
                &mts64_ctl_smpte_time_minutes,
@@ -774,7 +774,7 @@ static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {
 };
 
 /* Create and initialize the rawmidi component */
-static int __devinit snd_mts64_rawmidi_create(struct snd_card *card)
+static int snd_mts64_rawmidi_create(struct snd_card *card)
 {
        struct mts64 *mts = card->private_data;
        struct snd_rawmidi *rmidi;
@@ -860,7 +860,7 @@ __out:
        spin_unlock(&mts->lock);
 }
 
-static int __devinit snd_mts64_probe_port(struct parport *p)
+static int snd_mts64_probe_port(struct parport *p)
 {
        struct pardevice *pardev;
        int res;
@@ -884,7 +884,7 @@ static int __devinit snd_mts64_probe_port(struct parport *p)
        return res;
 }
 
-static void __devinit snd_mts64_attach(struct parport *p)
+static void snd_mts64_attach(struct parport *p)
 {
        struct platform_device *device;
 
@@ -940,7 +940,7 @@ static void snd_mts64_card_private_free(struct snd_card *card)
        snd_mts64_free(mts);
 }
 
-static int __devinit snd_mts64_probe(struct platform_device *pdev)
+static int snd_mts64_probe(struct platform_device *pdev)
 {
        struct pardevice *pardev;
        struct parport *p;
@@ -1025,7 +1025,7 @@ __err:
        return err;
 }
 
-static int __devexit snd_mts64_remove(struct platform_device *pdev)
+static int snd_mts64_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -1038,7 +1038,7 @@ static int __devexit snd_mts64_remove(struct platform_device *pdev)
 
 static struct platform_driver snd_mts64_driver = {
        .probe  = snd_mts64_probe,
-       .remove = __devexit_p(snd_mts64_remove),
+       .remove = snd_mts64_remove,
        .driver = {
                .name = PLATFORM_DRIVER,
                .owner  = THIS_MODULE,
index ef171295f6d46b3684667dfac434196f5a9ccd3f..7a5fdb9b0afcd000acc649042a38f182cc280f4e 100644 (file)
@@ -39,7 +39,7 @@ MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain.");
 
 struct snd_pcsp pcsp_chip;
 
-static int __devinit snd_pcsp_create(struct snd_card *card)
+static int snd_pcsp_create(struct snd_card *card)
 {
        static struct snd_device_ops ops = { };
        struct timespec tp;
@@ -93,7 +93,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card)
        return 0;
 }
 
-static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
+static int snd_card_pcsp_probe(int devnum, struct device *dev)
 {
        struct snd_card *card;
        int err;
@@ -142,7 +142,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
        return 0;
 }
 
-static int __devinit alsa_card_pcsp_init(struct device *dev)
+static int alsa_card_pcsp_init(struct device *dev)
 {
        int err;
 
@@ -161,12 +161,12 @@ static int __devinit alsa_card_pcsp_init(struct device *dev)
        return 0;
 }
 
-static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
+static void alsa_card_pcsp_exit(struct snd_pcsp *chip)
 {
        snd_card_free(chip->card);
 }
 
-static int __devinit pcsp_probe(struct platform_device *dev)
+static int pcsp_probe(struct platform_device *dev)
 {
        int err;
 
@@ -184,7 +184,7 @@ static int __devinit pcsp_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit pcsp_remove(struct platform_device *dev)
+static int pcsp_remove(struct platform_device *dev)
 {
        struct snd_pcsp *chip = platform_get_drvdata(dev);
        alsa_card_pcsp_exit(chip);
@@ -227,7 +227,7 @@ static struct platform_driver pcsp_platform_driver = {
                .pm     = PCSP_PM_OPS,
        },
        .probe          = pcsp_probe,
-       .remove         = __devexit_p(pcsp_remove),
+       .remove         = pcsp_remove,
        .shutdown       = pcsp_shutdown,
 };
 
index b5e2b54c2604ecb398e5fcaae6c5a873a2dc1cad..b874b0ad99cd2ba7cd8fea316c53ad225a2220d1 100644 (file)
@@ -77,7 +77,7 @@ static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
        return 0;
 }
 
-int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
+int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
 {
        int err;
 
index e66738c783338bc4b98d2bf7daded2e4d920dcef..d692749b8c9b00338526a4958839eafd3343fbf0 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef __PCSP_INPUT_H__
 #define __PCSP_INPUT_H__
 
-int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
+int pcspkr_input_init(struct input_dev **rdev, struct device *dev);
 int pcspkr_input_remove(struct input_dev *dev);
 void pcspkr_stop_sound(void);
 
index 434981dd4a611966b9c6f9d4e695ca23c58fb7a7..29ebaa4ec0fda8ff02bc36daa41f9e26927c1e66 100644 (file)
@@ -334,7 +334,7 @@ static struct snd_pcm_ops snd_pcsp_playback_ops = {
        .pointer = snd_pcsp_playback_pointer,
 };
 
-int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
+int snd_pcsp_new_pcm(struct snd_pcsp *chip)
 {
        int err;
 
index 6f633f4f3b96e83378db293a4dc6d3340261b507..f1e1defc09b1e70beaf32921a3e6124aeab06747 100644 (file)
@@ -119,17 +119,17 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
        .put =          pcsp_##ctl_type##_put, \
 }
 
-static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = {
+static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
        PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
        PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
 };
 
-static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = {
+static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
        PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
 };
 
-static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
-       struct snd_kcontrol_new *ctls, int num)
+static int snd_pcsp_ctls_add(struct snd_pcsp *chip,
+                            struct snd_kcontrol_new *ctls, int num)
 {
        int i, err;
        struct snd_card *card = chip->card;
@@ -141,7 +141,7 @@ static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
        return 0;
 }
 
-int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
+int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
 {
        int err;
        struct snd_card *card = chip->card;
index 8364855ed14fbfd7b3d2af81c7edd0914b6792fc..991018df7131d957341ed11e2c5bde91ea34d8cd 100644 (file)
@@ -96,9 +96,9 @@ static int portman_free(struct portman *pm)
        return 0;
 }
 
-static int __devinit portman_create(struct snd_card *card, 
-                                   struct pardevice *pardev, 
-                                   struct portman **rchip)
+static int portman_create(struct snd_card *card,
+                         struct pardevice *pardev,
+                         struct portman **rchip)
 {
        struct portman *pm;
 
@@ -561,7 +561,7 @@ static struct snd_rawmidi_ops snd_portman_midi_input = {
 };
 
 /* Create and initialize the rawmidi component */
-static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
+static int snd_portman_rawmidi_create(struct snd_card *card)
 {
        struct portman *pm = card->private_data;
        struct snd_rawmidi *rmidi;
@@ -648,7 +648,7 @@ static void snd_portman_interrupt(void *userdata)
        spin_unlock(&pm->reg_lock);
 }
 
-static int __devinit snd_portman_probe_port(struct parport *p)
+static int snd_portman_probe_port(struct parport *p)
 {
        struct pardevice *pardev;
        int res;
@@ -672,7 +672,7 @@ static int __devinit snd_portman_probe_port(struct parport *p)
        return res ? -EIO : 0;
 }
 
-static void __devinit snd_portman_attach(struct parport *p)
+static void snd_portman_attach(struct parport *p)
 {
        struct platform_device *device;
 
@@ -728,7 +728,7 @@ static void snd_portman_card_private_free(struct snd_card *card)
        portman_free(pm);
 }
 
-static int __devinit snd_portman_probe(struct platform_device *pdev)
+static int snd_portman_probe(struct platform_device *pdev)
 {
        struct pardevice *pardev;
        struct parport *p;
@@ -814,7 +814,7 @@ __err:
        return err;
 }
 
-static int __devexit snd_portman_remove(struct platform_device *pdev)
+static int snd_portman_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -827,7 +827,7 @@ static int __devexit snd_portman_remove(struct platform_device *pdev)
 
 static struct platform_driver snd_portman_driver = {
        .probe  = snd_portman_probe,
-       .remove = __devexit_p(snd_portman_remove),
+       .remove = snd_portman_remove,
        .driver = {
                .name = PLATFORM_DRIVER,
                .owner  = THIS_MODULE,
index 86700671d1ac12e8192f7400fb2d7fc8a25a66ef..7425dd8c1f095072d3163d98ccd5378594627886 100644 (file)
@@ -328,7 +328,7 @@ static void snd_uart16550_buffer_timer(unsigned long data)
  *  return 0 if found
  *  return negative error if not found
  */
-static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart)
+static int snd_uart16550_detect(struct snd_uart16550 *uart)
 {
        unsigned long io_base = uart->base;
        int ok;
@@ -783,14 +783,14 @@ static int snd_uart16550_dev_free(struct snd_device *device)
        return snd_uart16550_free(uart);
 }
 
-static int __devinit snd_uart16550_create(struct snd_card *card,
-                                      unsigned long iobase,
-                                      int irq,
-                                      unsigned int speed,
-                                      unsigned int base,
-                                      int adaptor,
-                                      int droponfull,
-                                      struct snd_uart16550 **ruart)
+static int snd_uart16550_create(struct snd_card *card,
+                               unsigned long iobase,
+                               int irq,
+                               unsigned int speed,
+                               unsigned int base,
+                               int adaptor,
+                               int droponfull,
+                               struct snd_uart16550 **ruart)
 {
        static struct snd_device_ops ops = {
                .dev_free =     snd_uart16550_dev_free,
@@ -863,7 +863,7 @@ static int __devinit snd_uart16550_create(struct snd_card *card,
        return 0;
 }
 
-static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
+static void snd_uart16550_substreams(struct snd_rawmidi_str *stream)
 {
        struct snd_rawmidi_substream *substream;
 
@@ -872,9 +872,9 @@ static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
        }
 }
 
-static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
-                                     int outs, int ins,
-                                     struct snd_rawmidi **rmidi)
+static int snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
+                              int outs, int ins,
+                              struct snd_rawmidi **rmidi)
 {
        struct snd_rawmidi *rrawmidi;
        int err;
@@ -899,7 +899,7 @@ static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
        return 0;
 }
 
-static int __devinit snd_serial_probe(struct platform_device *devptr)
+static int snd_serial_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_uart16550 *uart;
@@ -982,7 +982,7 @@ static int __devinit snd_serial_probe(struct platform_device *devptr)
        return err;
 }
 
-static int __devexit snd_serial_remove(struct platform_device *devptr)
+static int snd_serial_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -993,7 +993,7 @@ static int __devexit snd_serial_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_serial_driver = {
        .probe          = snd_serial_probe,
-       .remove         = __devexit_p( snd_serial_remove),
+       .remove         =  snd_serial_remove,
        .driver         = {
                .name   = SND_SERIAL_DRIVER,
                .owner  = THIS_MODULE,
index d7d514df90586439592a525db37e9930ef8fc7c3..cc4be88d73184a6e538a4eb961c3f47c182abdd0 100644 (file)
@@ -83,7 +83,7 @@ struct snd_card_virmidi {
 static struct platform_device *devices[SNDRV_CARDS];
 
 
-static int __devinit snd_virmidi_probe(struct platform_device *devptr)
+static int snd_virmidi_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_card_virmidi *vmidi;
@@ -129,7 +129,7 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
        return err;
 }
 
-static int __devexit snd_virmidi_remove(struct platform_device *devptr)
+static int snd_virmidi_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -140,7 +140,7 @@ static int __devexit snd_virmidi_remove(struct platform_device *devptr)
 
 static struct platform_driver snd_virmidi_driver = {
        .probe          = snd_virmidi_probe,
-       .remove         = __devexit_p(snd_virmidi_remove),
+       .remove         = snd_virmidi_remove,
        .driver         = {
                .name   = SND_VIRMIDI_DRIVER,
                .owner  = THIS_MODULE,
index 4a1fae99ac553e69bae361bce765ee39f82ebf97..3014b86362bdcaff723bc45b3567fb7d5fb02e83 100644 (file)
@@ -29,8 +29,6 @@
 #include <sound/hwdep.h>
 #include <sound/vx_core.h>
 
-#ifdef SND_VX_FW_LOADER
-
 MODULE_FIRMWARE("vx/bx_1_vxp.b56");
 MODULE_FIRMWARE("vx/bx_1_vp4.b56");
 MODULE_FIRMWARE("vx/x1_1_vx2.xlx");
@@ -119,142 +117,5 @@ void snd_vx_free_firmware(struct vx_core *chip)
 #endif
 }
 
-#else /* old style firmware loading */
-
-static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
-                              struct snd_hwdep_dsp_status *info)
-{
-       static char *type_ids[VX_TYPE_NUMS] = {
-               [VX_TYPE_BOARD] = "vxboard",
-               [VX_TYPE_V2] = "vx222",
-               [VX_TYPE_MIC] = "vx222",
-               [VX_TYPE_VXPOCKET] = "vxpocket",
-               [VX_TYPE_VXP440] = "vxp440",
-       };
-       struct vx_core *vx = hw->private_data;
-
-       if (snd_BUG_ON(!type_ids[vx->type]))
-               return -EINVAL;
-       strcpy(info->id, type_ids[vx->type]);
-       if (vx_is_pcmcia(vx))
-               info->num_dsps = 4;
-       else
-               info->num_dsps = 3;
-       if (vx->chip_status & VX_STAT_CHIP_INIT)
-               info->chip_ready = 1;
-       info->version = VX_DRIVER_VERSION;
-       return 0;
-}
-
-static void free_fw(const struct firmware *fw)
-{
-       if (fw) {
-               vfree(fw->data);
-               kfree(fw);
-       }
-}
-
-static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
-                            struct snd_hwdep_dsp_image *dsp)
-{
-       struct vx_core *vx = hw->private_data;
-       int index, err;
-       struct firmware *fw;
-
-       if (snd_BUG_ON(!vx->ops->load_dsp))
-               return -ENXIO;
-
-       fw = kmalloc(sizeof(*fw), GFP_KERNEL);
-       if (! fw) {
-               snd_printk(KERN_ERR "cannot allocate firmware\n");
-               return -ENOMEM;
-       }
-       fw->size = dsp->length;
-       fw->data = vmalloc(fw->size);
-       if (! fw->data) {
-               snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n",
-                          (int)fw->size);
-               kfree(fw);
-               return -ENOMEM;
-       }
-       if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) {
-               free_fw(fw);
-               return -EFAULT;
-       }
-
-       index = dsp->index;
-       if (! vx_is_pcmcia(vx))
-               index++;
-       err = vx->ops->load_dsp(vx, index, fw);
-       if (err < 0) {
-               free_fw(fw);
-               return err;
-       }
-#ifdef CONFIG_PM
-       vx->firmware[index] = fw;
-#else
-       free_fw(fw);
-#endif
-
-       if (index == 1)
-               vx->chip_status |= VX_STAT_XILINX_LOADED;
-       if (index < 3)
-               return 0;
-
-       /* ok, we reached to the last one */
-       /* create the devices if not built yet */
-       if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) {
-               if ((err = snd_vx_pcm_new(vx)) < 0)
-                       return err;
-
-               if ((err = snd_vx_mixer_new(vx)) < 0)
-                       return err;
-
-               if (vx->ops->add_controls)
-                       if ((err = vx->ops->add_controls(vx)) < 0)
-                               return err;
-
-               if ((err = snd_card_register(vx->card)) < 0)
-                       return err;
-
-               vx->chip_status |= VX_STAT_DEVICE_INIT;
-       }
-       vx->chip_status |= VX_STAT_CHIP_INIT;
-       return 0;
-}
-
-
-/* exported */
-int snd_vx_setup_firmware(struct vx_core *chip)
-{
-       int err;
-       struct snd_hwdep *hw;
-
-       if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
-               return err;
-
-       hw->iface = SNDRV_HWDEP_IFACE_VX;
-       hw->private_data = chip;
-       hw->ops.dsp_status = vx_hwdep_dsp_status;
-       hw->ops.dsp_load = vx_hwdep_dsp_load;
-       hw->exclusive = 1;
-       sprintf(hw->name, "VX Loader (%s)", chip->card->driver);
-       chip->hwdep = hw;
-
-       return snd_card_register(chip->card);
-}
-
-/* exported */
-void snd_vx_free_firmware(struct vx_core *chip)
-{
-#ifdef CONFIG_PM
-       int i;
-       for (i = 0; i < 4; i++)
-               free_fw(chip->firmware[i]);
-#endif
-}
-
-#endif /* SND_VX_FW_LOADER */
-
 EXPORT_SYMBOL(snd_vx_setup_firmware);
 EXPORT_SYMBOL(snd_vx_free_firmware);
index 26071489970bebcd8af0aa5f86bd626d01b8f42f..ea063e1f87221e982558ec892024e5bdb7793b89 100644 (file)
@@ -33,4 +33,17 @@ config SND_ISIGHT
          To compile this driver as a module, choose M here: the module
          will be called snd-isight.
 
+config SND_SCS1X
+       tristate "Stanton Control System 1 MIDI"
+       select SND_PCM
+       select SND_RAWMIDI
+       select SND_FIREWIRE_LIB
+       help
+         Say Y here to include support for the MIDI ports of the Stanton
+         SCS.1d/SCS.1m DJ controllers.  (SCS.1m audio is still handled
+         by FFADO.)
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-scs1x.
+
 endif # SND_FIREWIRE
index d71ed8935f76603e9a75217d2f34763a3ca03f82..460179df5bb526ee06f90fa7ffd03ef638024e3b 100644 (file)
@@ -2,7 +2,9 @@ snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
                         fcp.o cmp.o amdtp.o
 snd-firewire-speakers-objs := speakers.o
 snd-isight-objs := isight.o
+snd-scs1x-objs := scs1x.o
 
 obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
 obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
 obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
+obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o
diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c
new file mode 100644 (file)
index 0000000..844a555
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Stanton Control System 1 MIDI driver
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include "lib.h"
+
+#define OUI_STANTON    0x001260
+#define MODEL_SCS_1M   0x001000
+#define MODEL_SCS_1D   0x002000
+
+#define HSS1394_ADDRESS                        0xc007dedadadaULL
+#define HSS1394_MAX_PACKET_SIZE                64
+
+#define HSS1394_TAG_USER_DATA          0x00
+#define HSS1394_TAG_CHANGE_ADDRESS     0xf1
+
+struct scs {
+       struct snd_card *card;
+       struct fw_unit *unit;
+       struct fw_address_handler hss_handler;
+       struct fw_transaction transaction;
+       bool transaction_running;
+       bool output_idle;
+       u8 output_status;
+       u8 output_bytes;
+       bool output_escaped;
+       bool output_escape_high_nibble;
+       u8 input_escape_count;
+       struct snd_rawmidi_substream *output;
+       struct snd_rawmidi_substream *input;
+       struct tasklet_struct tasklet;
+       wait_queue_head_t idle_wait;
+       u8 *buffer;
+};
+
+static const u8 sysex_escape_prefix[] = {
+       0xf0,                   /* SysEx begin */
+       0x00, 0x01, 0x60,       /* Stanton DJ */
+       0x48, 0x53, 0x53,       /* "HSS" */
+};
+
+static int scs_output_open(struct snd_rawmidi_substream *stream)
+{
+       struct scs *scs = stream->rmidi->private_data;
+
+       scs->output_status = 0;
+       scs->output_bytes = 1;
+       scs->output_escaped = false;
+
+       return 0;
+}
+
+static int scs_output_close(struct snd_rawmidi_substream *stream)
+{
+       return 0;
+}
+
+static void scs_output_trigger(struct snd_rawmidi_substream *stream, int up)
+{
+       struct scs *scs = stream->rmidi->private_data;
+
+       ACCESS_ONCE(scs->output) = up ? stream : NULL;
+       if (up) {
+               scs->output_idle = false;
+               tasklet_schedule(&scs->tasklet);
+       }
+}
+
+static void scs_write_callback(struct fw_card *card, int rcode,
+                              void *data, size_t length, void *callback_data)
+{
+       struct scs *scs = callback_data;
+
+       if (rcode == RCODE_GENERATION) {
+               /* TODO: retry this packet */
+       }
+
+       scs->transaction_running = false;
+       tasklet_schedule(&scs->tasklet);
+}
+
+static bool is_valid_running_status(u8 status)
+{
+       return status >= 0x80 && status <= 0xef;
+}
+
+static bool is_one_byte_cmd(u8 status)
+{
+       return status == 0xf6 ||
+              status >= 0xf8;
+}
+
+static bool is_two_bytes_cmd(u8 status)
+{
+       return (status >= 0xc0 && status <= 0xdf) ||
+              status == 0xf1 ||
+              status == 0xf3;
+}
+
+static bool is_three_bytes_cmd(u8 status)
+{
+       return (status >= 0x80 && status <= 0xbf) ||
+              (status >= 0xe0 && status <= 0xef) ||
+              status == 0xf2;
+}
+
+static bool is_invalid_cmd(u8 status)
+{
+       return status == 0xf4 ||
+              status == 0xf5 ||
+              status == 0xf9 ||
+              status == 0xfd;
+}
+
+static void scs_output_tasklet(unsigned long data)
+{
+       struct scs *scs = (void *)data;
+       struct snd_rawmidi_substream *stream;
+       unsigned int i;
+       u8 byte;
+       struct fw_device *dev;
+       int generation;
+
+       if (scs->transaction_running)
+               return;
+
+       stream = ACCESS_ONCE(scs->output);
+       if (!stream) {
+               scs->output_idle = true;
+               wake_up(&scs->idle_wait);
+               return;
+       }
+
+       i = scs->output_bytes;
+       for (;;) {
+               if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
+                       scs->output_bytes = i;
+                       scs->output_idle = true;
+                       wake_up(&scs->idle_wait);
+                       return;
+               }
+               /*
+                * Convert from real MIDI to what I think the device expects (no
+                * running status, one command per packet, unescaped SysExs).
+                */
+               if (scs->output_escaped && byte < 0x80) {
+                       if (scs->output_escape_high_nibble) {
+                               if (i < HSS1394_MAX_PACKET_SIZE) {
+                                       scs->buffer[i] = byte << 4;
+                                       scs->output_escape_high_nibble = false;
+                               }
+                       } else {
+                               scs->buffer[i++] |= byte & 0x0f;
+                               scs->output_escape_high_nibble = true;
+                       }
+               } else if (byte < 0x80) {
+                       if (i == 1) {
+                               if (!is_valid_running_status(scs->output_status))
+                                       continue;
+                               scs->buffer[0] = HSS1394_TAG_USER_DATA;
+                               scs->buffer[i++] = scs->output_status;
+                       }
+                       scs->buffer[i++] = byte;
+                       if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
+                           (i == 4 && is_three_bytes_cmd(scs->output_status)))
+                               break;
+                       if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
+                           !memcmp(scs->buffer + 1, sysex_escape_prefix,
+                                   ARRAY_SIZE(sysex_escape_prefix))) {
+                               scs->output_escaped = true;
+                               scs->output_escape_high_nibble = true;
+                               i = 0;
+                       }
+                       if (i >= HSS1394_MAX_PACKET_SIZE)
+                               i = 1;
+               } else if (byte == 0xf7) {
+                       if (scs->output_escaped) {
+                               if (i >= 1 && scs->output_escape_high_nibble &&
+                                   scs->buffer[0] != HSS1394_TAG_CHANGE_ADDRESS)
+                                       break;
+                       } else {
+                               if (i > 1 && scs->output_status == 0xf0) {
+                                       scs->buffer[i++] = 0xf7;
+                                       break;
+                               }
+                       }
+                       i = 1;
+                       scs->output_escaped = false;
+               } else if (!is_invalid_cmd(byte) &&
+                          byte < 0xf8) {
+                       i = 1;
+                       scs->buffer[0] = HSS1394_TAG_USER_DATA;
+                       scs->buffer[i++] = byte;
+                       scs->output_status = byte;
+                       scs->output_escaped = false;
+                       if (is_one_byte_cmd(byte))
+                               break;
+               }
+       }
+       scs->output_bytes = 1;
+       scs->output_escaped = false;
+
+       scs->transaction_running = true;
+       dev = fw_parent_device(scs->unit);
+       generation = dev->generation;
+       smp_rmb(); /* node_id vs. generation */
+       fw_send_request(dev->card, &scs->transaction, TCODE_WRITE_BLOCK_REQUEST,
+                       dev->node_id, generation, dev->max_speed,
+                       HSS1394_ADDRESS, scs->buffer, i,
+                       scs_write_callback, scs);
+}
+
+static void scs_output_drain(struct snd_rawmidi_substream *stream)
+{
+       struct scs *scs = stream->rmidi->private_data;
+
+       wait_event(scs->idle_wait, scs->output_idle);
+}
+
+static struct snd_rawmidi_ops output_ops = {
+       .open    = scs_output_open,
+       .close   = scs_output_close,
+       .trigger = scs_output_trigger,
+       .drain   = scs_output_drain,
+};
+
+static int scs_input_open(struct snd_rawmidi_substream *stream)
+{
+       struct scs *scs = stream->rmidi->private_data;
+
+       scs->input_escape_count = 0;
+
+       return 0;
+}
+
+static int scs_input_close(struct snd_rawmidi_substream *stream)
+{
+       return 0;
+}
+
+static void scs_input_trigger(struct snd_rawmidi_substream *stream, int up)
+{
+       struct scs *scs = stream->rmidi->private_data;
+
+       ACCESS_ONCE(scs->input) = up ? stream : NULL;
+}
+
+static void scs_input_escaped_byte(struct snd_rawmidi_substream *stream,
+                                  u8 byte)
+{
+       u8 nibbles[2];
+
+       nibbles[0] = byte >> 4;
+       nibbles[1] = byte & 0x0f;
+       snd_rawmidi_receive(stream, nibbles, 2);
+}
+
+static void scs_input_midi_byte(struct scs *scs,
+                               struct snd_rawmidi_substream *stream,
+                               u8 byte)
+{
+       if (scs->input_escape_count > 0) {
+               scs_input_escaped_byte(stream, byte);
+               scs->input_escape_count--;
+               if (scs->input_escape_count == 0)
+                       snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
+       } else if (byte == 0xf9) {
+               snd_rawmidi_receive(stream, sysex_escape_prefix,
+                                   ARRAY_SIZE(sysex_escape_prefix));
+               scs_input_escaped_byte(stream, 0x00);
+               scs_input_escaped_byte(stream, 0xf9);
+               scs->input_escape_count = 3;
+       } else {
+               snd_rawmidi_receive(stream, &byte, 1);
+       }
+}
+
+static void scs_input_packet(struct scs *scs,
+                            struct snd_rawmidi_substream *stream,
+                            const u8 *data, unsigned int bytes)
+{
+       unsigned int i;
+
+       if (data[0] == HSS1394_TAG_USER_DATA) {
+               for (i = 1; i < bytes; ++i)
+                       scs_input_midi_byte(scs, stream, data[i]);
+       } else {
+               snd_rawmidi_receive(stream, sysex_escape_prefix,
+                                   ARRAY_SIZE(sysex_escape_prefix));
+               for (i = 0; i < bytes; ++i)
+                       scs_input_escaped_byte(stream, data[i]);
+               snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
+       }
+}
+
+static struct snd_rawmidi_ops input_ops = {
+       .open    = scs_input_open,
+       .close   = scs_input_close,
+       .trigger = scs_input_trigger,
+};
+
+static int scs_create_midi(struct scs *scs)
+{
+       struct snd_rawmidi *rmidi;
+       int err;
+
+       err = snd_rawmidi_new(scs->card, "SCS.1x", 0, 1, 1, &rmidi);
+       if (err < 0)
+               return err;
+       snprintf(rmidi->name, sizeof(rmidi->name),
+                "%s MIDI", scs->card->shortname);
+       rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                           SNDRV_RAWMIDI_INFO_INPUT |
+                           SNDRV_RAWMIDI_INFO_DUPLEX;
+       rmidi->private_data = scs;
+       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &output_ops);
+       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &input_ops);
+
+       return 0;
+}
+
+static void handle_hss(struct fw_card *card, struct fw_request *request,
+                      int tcode, int destination, int source, int generation,
+                      unsigned long long offset, void *data, size_t length,
+                      void *callback_data)
+{
+       struct scs *scs = callback_data;
+       struct snd_rawmidi_substream *stream;
+
+       if (offset != scs->hss_handler.offset) {
+               fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+               return;
+       }
+       if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
+           tcode != TCODE_WRITE_BLOCK_REQUEST) {
+               fw_send_response(card, request, RCODE_TYPE_ERROR);
+               return;
+       }
+
+       if (length >= 1) {
+               stream = ACCESS_ONCE(scs->input);
+               if (stream)
+                       scs_input_packet(scs, stream, data, length);
+       }
+
+       fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+static int scs_init_hss_address(struct scs *scs)
+{
+       __be64 data;
+       int err;
+
+       data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
+                          scs->hss_handler.offset);
+       err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
+                                HSS1394_ADDRESS, &data, 8);
+       if (err < 0)
+               dev_err(&scs->unit->device, "HSS1394 communication failed\n");
+
+       return err;
+}
+
+static void scs_card_free(struct snd_card *card)
+{
+       struct scs *scs = card->private_data;
+
+       fw_core_remove_address_handler(&scs->hss_handler);
+       kfree(scs->buffer);
+}
+
+static int scs_probe(struct device *unit_dev)
+{
+       struct fw_unit *unit = fw_unit(unit_dev);
+       struct fw_device *fw_dev = fw_parent_device(unit);
+       struct snd_card *card;
+       struct scs *scs;
+       int err;
+
+       err = snd_card_create(-16, NULL, THIS_MODULE, sizeof(*scs), &card);
+       if (err < 0)
+               return err;
+       snd_card_set_dev(card, unit_dev);
+
+       scs = card->private_data;
+       scs->card = card;
+       scs->unit = unit;
+       tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs);
+       init_waitqueue_head(&scs->idle_wait);
+       scs->output_idle = true;
+
+       scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL);
+       if (!scs->buffer)
+               goto err_card;
+
+       scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
+       scs->hss_handler.address_callback = handle_hss;
+       scs->hss_handler.callback_data = scs;
+       err = fw_core_add_address_handler(&scs->hss_handler,
+                                         &fw_high_memory_region);
+       if (err < 0)
+               goto err_buffer;
+
+       card->private_free = scs_card_free;
+
+       strcpy(card->driver, "SCS.1x");
+       strcpy(card->shortname, "SCS.1x");
+       fw_csr_string(unit->directory, CSR_MODEL,
+                     card->shortname, sizeof(card->shortname));
+       snprintf(card->longname, sizeof(card->longname),
+                "Stanton DJ %s (GUID %08x%08x) at %s, S%d",
+                card->shortname, fw_dev->config_rom[3], fw_dev->config_rom[4],
+                dev_name(&unit->device), 100 << fw_dev->max_speed);
+       strcpy(card->mixername, card->shortname);
+
+       err = scs_init_hss_address(scs);
+       if (err < 0)
+               goto err_card;
+
+       err = scs_create_midi(scs);
+       if (err < 0)
+               goto err_card;
+
+       err = snd_card_register(card);
+       if (err < 0)
+               goto err_card;
+
+       dev_set_drvdata(unit_dev, scs);
+
+       return 0;
+
+err_buffer:
+       kfree(scs->buffer);
+err_card:
+       snd_card_free(card);
+       return err;
+}
+
+static int scs_remove(struct device *dev)
+{
+       struct scs *scs = dev_get_drvdata(dev);
+
+       snd_card_disconnect(scs->card);
+
+       ACCESS_ONCE(scs->output) = NULL;
+       ACCESS_ONCE(scs->input) = NULL;
+
+       wait_event(scs->idle_wait, scs->output_idle);
+
+       tasklet_kill(&scs->tasklet);
+
+       snd_card_free_when_closed(scs->card);
+
+       return 0;
+}
+
+static void scs_update(struct fw_unit *unit)
+{
+       struct scs *scs = dev_get_drvdata(&unit->device);
+       __be64 data;
+
+       data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
+                          scs->hss_handler.offset);
+       snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
+                          HSS1394_ADDRESS, &data, 8);
+}
+
+static const struct ieee1394_device_id scs_id_table[] = {
+       {
+               .match_flags = IEEE1394_MATCH_VENDOR_ID |
+                              IEEE1394_MATCH_MODEL_ID,
+               .vendor_id   = OUI_STANTON,
+               .model_id    = MODEL_SCS_1M,
+       },
+       {
+               .match_flags = IEEE1394_MATCH_VENDOR_ID |
+                              IEEE1394_MATCH_MODEL_ID,
+               .vendor_id   = OUI_STANTON,
+               .model_id    = MODEL_SCS_1D,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(ieee1394, scs_id_table);
+
+MODULE_DESCRIPTION("SCS.1x MIDI driver");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL v2");
+
+static struct fw_driver scs_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = KBUILD_MODNAME,
+               .bus    = &fw_bus_type,
+               .probe  = scs_probe,
+               .remove = scs_remove,
+       },
+       .update   = scs_update,
+       .id_table = scs_id_table,
+};
+
+static int __init alsa_scs1x_init(void)
+{
+       return driver_register(&scs_driver.driver);
+}
+
+static void __exit alsa_scs1x_exit(void)
+{
+       driver_unregister(&scs_driver.driver);
+}
+
+module_init(alsa_scs1x_init);
+module_exit(alsa_scs1x_exit);
index 297244e658d9158663239d9744fee44aec00ab6a..d6846557f27089f11741a7f4e50dc22148eb6a88 100644 (file)
@@ -663,7 +663,7 @@ static void fwspk_card_free(struct snd_card *card)
        mutex_destroy(&fwspk->mutex);
 }
 
-static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
+static const struct device_info *fwspk_detect(struct fw_device *dev)
 {
        static const struct device_info griffin_firewave = {
                .driver_name = "FireWave",
@@ -699,7 +699,7 @@ static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
        return NULL;
 }
 
-static int __devinit fwspk_probe(struct device *unit_dev)
+static int fwspk_probe(struct device *unit_dev)
 {
        struct fw_unit *unit = fw_unit(unit_dev);
        struct fw_device *fw_dev = fw_parent_device(unit);
@@ -770,7 +770,7 @@ error:
        return err;
 }
 
-static int __devexit fwspk_remove(struct device *dev)
+static int fwspk_remove(struct device *dev)
 {
        struct fwspk *fwspk = dev_get_drvdata(dev);
 
@@ -834,7 +834,7 @@ static struct fw_driver fwspk_driver = {
                .name   = KBUILD_MODNAME,
                .bus    = &fw_bus_type,
                .probe  = fwspk_probe,
-               .remove = __devexit_p(fwspk_remove),
+               .remove = fwspk_remove,
        },
        .update   = fwspk_bus_reset,
        .id_table = fwspk_id_table,
index a38d9643e9d8319dc38c4e3379d83d13a27e250c..affa13480659e4b302606b182ae5e4dc6d72de6f 100644 (file)
@@ -425,7 +425,7 @@ config SND_WAVEFRONT
 
 config SND_MSND_PINNACLE
        tristate "Turtle Beach MultiSound Pinnacle/Fiji driver"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        select FW_LOADER
        select SND_MPU401_UART
        select SND_PCM
@@ -438,7 +438,7 @@ config SND_MSND_PINNACLE
 
 config SND_MSND_CLASSIC
        tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        select FW_LOADER
        select SND_MPU401_UART
        select SND_PCM
index 2c2f829c3fd7b91ca38a2323272bdfab9421d217..26ce26a5884d7254e6b61ca0f6fd1df2acba545c 100644 (file)
@@ -94,8 +94,8 @@ MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids);
 #define        DRIVER_NAME     "snd-card-ad1816a"
 
 
-static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
-                                         const struct pnp_card_device_id *id)
+static int snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
+                               const struct pnp_card_device_id *id)
 {
        struct pnp_dev *pdev;
        int err;
@@ -135,8 +135,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
        return 0;
 }
 
-static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
-                                           const struct pnp_card_device_id *pid)
+static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
+                                 const struct pnp_card_device_id *pid)
 {
        int error;
        struct snd_card *card;
@@ -217,10 +217,10 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
        return 0;
 }
 
-static unsigned int __devinitdata ad1816a_devices;
+static unsigned int ad1816a_devices;
 
-static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
-                                           const struct pnp_card_device_id *id)
+static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
+                                 const struct pnp_card_device_id *id)
 {
        static int dev;
        int res;
@@ -238,7 +238,7 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
         return -ENODEV;
 }
 
-static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard)
+static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -270,7 +270,7 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
        .name           = "ad1816a",
        .id_table       = snd_ad1816a_pnpids,
        .probe          = snd_ad1816a_pnp_detect,
-       .remove         = __devexit_p(snd_ad1816a_pnp_remove),
+       .remove         = snd_ad1816a_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_ad1816a_pnp_suspend,
        .resume         = snd_ad1816a_pnp_resume,
index db64df6023e0fc3cf8dc53ff6f1b6e7349efb7fa..f0fd98e695e323bdcf1525ba0c038b0f2c358496 100644 (file)
@@ -537,7 +537,7 @@ void snd_ad1816a_resume(struct snd_ad1816a *chip)
 }
 #endif
 
-static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip)
+static int snd_ad1816a_probe(struct snd_ad1816a *chip)
 {
        unsigned long flags;
 
@@ -583,7 +583,7 @@ static int snd_ad1816a_dev_free(struct snd_device *device)
        return snd_ad1816a_free(chip);
 }
 
-static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
+static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
 {
        switch (chip->hardware) {
        case AD1816A_HW_AD1816A: return "AD1816A";
@@ -596,9 +596,9 @@ static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
        }
 }
 
-int __devinit snd_ad1816a_create(struct snd_card *card,
-                                unsigned long port, int irq, int dma1, int dma2,
-                                struct snd_ad1816a *chip)
+int snd_ad1816a_create(struct snd_card *card,
+                      unsigned long port, int irq, int dma1, int dma2,
+                      struct snd_ad1816a *chip)
 {
         static struct snd_device_ops ops = {
                .dev_free =     snd_ad1816a_dev_free,
@@ -675,7 +675,7 @@ static struct snd_pcm_ops snd_ad1816a_capture_ops = {
        .pointer =      snd_ad1816a_capture_pointer,
 };
 
-int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
+int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
 {
        int error;
        struct snd_pcm *pcm;
@@ -702,7 +702,8 @@ int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_p
        return 0;
 }
 
-int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer)
+int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
+                     struct snd_timer **rtimer)
 {
        struct snd_timer *timer;
        struct snd_timer_id tid;
@@ -923,7 +924,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 
-static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ad1816a_controls[] = {
 AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
 AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1,
                   db_scale_5bit),
@@ -969,7 +970,7 @@ AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1),
 AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0),
 };
                                         
-int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip)
+int snd_ad1816a_mixer(struct snd_ad1816a *chip)
 {
        struct snd_card *card;
        unsigned int idx;
index 2af77faefbb1734fc5822b3753fbf1c8b046eee3..c214ecf45400a1c7de02aacaf0d68b6495ae719e 100644 (file)
@@ -64,7 +64,7 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
 module_param_array(thinkpad, bool, NULL, 0444);
 MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
 
-static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
+static int snd_ad1848_match(struct device *dev, unsigned int n)
 {
        if (!enable[n])
                return 0;
@@ -84,7 +84,7 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
        return 1;
 }
 
-static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
+static int snd_ad1848_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_wss *chip;
@@ -132,7 +132,7 @@ out:        snd_card_free(card);
        return error;
 }
 
-static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
+static int snd_ad1848_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -164,7 +164,7 @@ static int snd_ad1848_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_ad1848_driver = {
        .match          = snd_ad1848_match,
        .probe          = snd_ad1848_probe,
-       .remove         = __devexit_p(snd_ad1848_remove),
+       .remove         = snd_ad1848_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_ad1848_suspend,
        .resume         = snd_ad1848_resume,
index 4d50c69f3290969f416333754a7798a91d9df1aa..d26545543732dab8b0805a97dbbcb9f40ba22b28 100644 (file)
@@ -30,7 +30,7 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 
-static int __devinit snd_adlib_match(struct device *dev, unsigned int n)
+static int snd_adlib_match(struct device *dev, unsigned int n)
 {
        if (!enable[n])
                return 0;
@@ -47,7 +47,7 @@ static void snd_adlib_free(struct snd_card *card)
        release_and_free_resource(card->private_data);
 }
 
-static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
+static int snd_adlib_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_opl3 *opl3;
@@ -98,7 +98,7 @@ out:  snd_card_free(card);
        return error;
 }
 
-static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
+static int snd_adlib_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -108,7 +108,7 @@ static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
 static struct isa_driver snd_adlib_driver = {
        .match          = snd_adlib_match,
        .probe          = snd_adlib_probe,
-       .remove         = __devexit_p(snd_adlib_remove),
+       .remove         = snd_adlib_remove,
 
        .driver         = {
                .name   = DEV_NAME
index f7cdaf51512d05d26ca93baf8ce2627375a8af43..10f08a18fe3ba7b9bd7789a343f40575a4a4cf43 100644 (file)
@@ -117,9 +117,9 @@ static struct pnp_card_device_id snd_als100_pnpids[] = {
 
 MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
 
-static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
-                                        struct pnp_card_link *card,
-                                        const struct pnp_card_device_id *id)
+static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
+                              struct pnp_card_link *card,
+                              const struct pnp_card_device_id *id)
 {
        struct pnp_dev *pdev;
        int err;
@@ -183,9 +183,9 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
        return 0;
 }
 
-static int __devinit snd_card_als100_probe(int dev,
-                                       struct pnp_card_link *pcard,
-                                       const struct pnp_card_device_id *pid)
+static int snd_card_als100_probe(int dev,
+                                struct pnp_card_link *pcard,
+                                const struct pnp_card_device_id *pid)
 {
        int error;
        struct snd_sb *chip;
@@ -286,10 +286,10 @@ static int __devinit snd_card_als100_probe(int dev,
        return 0;
 }
 
-static unsigned int __devinitdata als100_devices;
+static unsigned int als100_devices;
 
-static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
-                                          const struct pnp_card_device_id *id)
+static int snd_als100_pnp_detect(struct pnp_card_link *card,
+                                const struct pnp_card_device_id *id)
 {
        static int dev;
        int res;
@@ -307,7 +307,7 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
        return -ENODEV;
 }
 
-static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
+static void snd_als100_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -344,7 +344,7 @@ static struct pnp_card_driver als100_pnpc_driver = {
        .name           = "als100",
         .id_table       = snd_als100_pnpids,
         .probe          = snd_als100_pnp_detect,
-        .remove         = __devexit_p(snd_als100_pnp_remove),
+       .remove         = snd_als100_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_als100_pnp_suspend,
        .resume         = snd_als100_pnp_resume,
index 6a2c78ef1d8fdf46d41bd90aed88d7b688f32a2e..db301ff94ec2ec43611beb6a86c495fc6e475fa6 100644 (file)
@@ -99,9 +99,9 @@ MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
 
 #define        DRIVER_NAME     "snd-card-azt2320"
 
-static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
-                                         struct pnp_card_link *card,
-                                         const struct pnp_card_device_id *id)
+static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
+                               struct pnp_card_link *card,
+                               const struct pnp_card_device_id *id)
 {
        struct pnp_dev *pdev;
        int err;
@@ -147,7 +147,7 @@ static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acar
 }
 
 /* same of snd_sbdsp_command by Jaroslav Kysela */
-static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val)
+static int snd_card_azt2320_command(unsigned long port, unsigned char val)
 {
        int i;
        unsigned long limit;
@@ -161,7 +161,7 @@ static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char
        return -EBUSY;
 }
 
-static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
+static int snd_card_azt2320_enable_wss(unsigned long port)
 {
        int error;
 
@@ -174,9 +174,9 @@ static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
        return 0;
 }
 
-static int __devinit snd_card_azt2320_probe(int dev,
-                                           struct pnp_card_link *pcard,
-                                           const struct pnp_card_device_id *pid)
+static int snd_card_azt2320_probe(int dev,
+                                 struct pnp_card_link *pcard,
+                                 const struct pnp_card_device_id *pid)
 {
        int error;
        struct snd_card *card;
@@ -264,10 +264,10 @@ static int __devinit snd_card_azt2320_probe(int dev,
        return 0;
 }
 
-static unsigned int __devinitdata azt2320_devices;
+static unsigned int azt2320_devices;
 
-static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
-                                           const struct pnp_card_device_id *id)
+static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
+                                 const struct pnp_card_device_id *id)
 {
        static int dev;
        int res;
@@ -285,7 +285,7 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
         return -ENODEV;
 }
 
-static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard)
+static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -320,7 +320,7 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
        .name           = "azt2320",
        .id_table       = snd_azt2320_pnpids,
        .probe          = snd_azt2320_pnp_detect,
-       .remove         = __devexit_p(snd_azt2320_pnp_remove),
+       .remove         = snd_azt2320_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_azt2320_pnp_suspend,
        .resume         = snd_azt2320_pnp_resume,
index bde60139bb95e0ff49348bec3f869242e3c591e3..a7369fe19a6f045fdf5098ed93660f07997489c2 100644 (file)
@@ -140,7 +140,7 @@ static void snd_cmi8328_cfg_restore(u16 port, u8 cfg[])
        snd_cmi8328_cfg_write(port, CFG3, cfg[2]);
 }
 
-static int __devinit snd_cmi8328_mixer(struct snd_wss *chip)
+static int snd_cmi8328_mixer(struct snd_wss *chip)
 {
        struct snd_card *card;
        struct snd_ctl_elem_id id1, id2;
@@ -212,7 +212,7 @@ int array_find_l(long array[], long item)
        return -1;
 }
 
-static int __devinit snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
+static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
 {
        struct snd_card *card;
        struct snd_opl3 *opl3;
@@ -401,7 +401,7 @@ error:
        return err;
 }
 
-static int __devexit snd_cmi8328_remove(struct device *pdev, unsigned int dev)
+static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
 {
        struct snd_card *card = dev_get_drvdata(pdev);
        struct snd_cmi8328 *cmi = card->private_data;
@@ -459,7 +459,7 @@ static int snd_cmi8328_resume(struct device *pdev, unsigned int n)
 
 static struct isa_driver snd_cmi8328_driver = {
        .probe          = snd_cmi8328_probe,
-       .remove         = __devexit_p(snd_cmi8328_remove),
+       .remove         = snd_cmi8328_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8328_suspend,
        .resume         = snd_cmi8328_resume,
index 7bd5e337ee93b6b205fc9202c8ee94f03abb2fab..c707c52268ab44aed2d1165079e889c6470de344 100644 (file)
@@ -193,7 +193,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
 #endif
 
 
-static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmi8330_controls[] = {
 WSS_DOUBLE("Master Playback Volume", 0,
                CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
 WSS_SINGLE("Loud Playback Switch", 0,
@@ -249,7 +249,7 @@ WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
 };
 
 #ifdef ENABLE_SB_MIXER
-static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = {
+static struct sbmix_elem cmi8330_sb_mixers[] = {
 SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
 SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
 SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
@@ -267,7 +267,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6
 SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
 };
 
-static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
+static unsigned char cmi8330_sb_init_values[][2] = {
        { SB_DSP4_MASTER_DEV + 0, 0 },
        { SB_DSP4_MASTER_DEV + 1, 0 },
        { SB_DSP4_PCM_DEV + 0, 0 },
@@ -281,7 +281,7 @@ static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
 };
 
 
-static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
+static int cmi8330_add_sb_mixers(struct snd_sb *chip)
 {
        int idx, err;
        unsigned long flags;
@@ -306,7 +306,7 @@ static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
 }
 #endif
 
-static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
+static int snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
 {
        unsigned int idx;
        int err;
@@ -329,9 +329,9 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330
 }
 
 #ifdef CONFIG_PNP
-static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
-                                    struct pnp_card_link *card,
-                                    const struct pnp_card_device_id *id)
+static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
+                          struct pnp_card_link *card,
+                          const struct pnp_card_device_id *id)
 {
        struct pnp_dev *pdev;
        int err;
@@ -437,7 +437,7 @@ static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream)
        return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream);
 }
 
-static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
+static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
 {
        struct snd_pcm *pcm;
        const struct snd_pcm_ops *ops;
@@ -532,7 +532,7 @@ static int snd_cmi8330_card_new(int dev, struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
+static int snd_cmi8330_probe(struct snd_card *card, int dev)
 {
        struct snd_cmi8330 *acard;
        int i, err;
@@ -613,8 +613,8 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
        return snd_card_register(card);
 }
 
-static int __devinit snd_cmi8330_isa_match(struct device *pdev,
-                                          unsigned int dev)
+static int snd_cmi8330_isa_match(struct device *pdev,
+                                unsigned int dev)
 {
        if (!enable[dev] || is_isapnp_selected(dev))
                return 0;
@@ -629,8 +629,8 @@ static int __devinit snd_cmi8330_isa_match(struct device *pdev,
        return 1;
 }
 
-static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
-                                          unsigned int dev)
+static int snd_cmi8330_isa_probe(struct device *pdev,
+                                unsigned int dev)
 {
        struct snd_card *card;
        int err;
@@ -647,8 +647,8 @@ static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int __devexit snd_cmi8330_isa_remove(struct device *devptr,
-                                           unsigned int dev)
+static int snd_cmi8330_isa_remove(struct device *devptr,
+                                 unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -673,7 +673,7 @@ static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_cmi8330_driver = {
        .match          = snd_cmi8330_isa_match,
        .probe          = snd_cmi8330_isa_probe,
-       .remove         = __devexit_p(snd_cmi8330_isa_remove),
+       .remove         = snd_cmi8330_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_isa_suspend,
        .resume         = snd_cmi8330_isa_resume,
@@ -685,8 +685,8 @@ static struct isa_driver snd_cmi8330_driver = {
 
 
 #ifdef CONFIG_PNP
-static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
-                                           const struct pnp_card_device_id *pid)
+static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
+                                 const struct pnp_card_device_id *pid)
 {
        static int dev;
        struct snd_card *card;
@@ -717,7 +717,7 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard)
+static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -740,7 +740,7 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
        .name = "cmi8330",
        .id_table = snd_cmi8330_pnpids,
        .probe = snd_cmi8330_pnp_detect,
-       .remove = __devexit_p(snd_cmi8330_pnp_remove),
+       .remove = snd_cmi8330_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cmi8330_pnp_suspend,
        .resume         = snd_cmi8330_pnp_resume,
index 99dda45e82f5a33c0130db4ca36dc1c7bfdecb1a..aa7a5d86e480412b1bb2da2411847e5d574d0880 100644 (file)
@@ -68,7 +68,7 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
 
-static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
+static int snd_cs4231_match(struct device *dev, unsigned int n)
 {
        if (!enable[n])
                return 0;
@@ -88,7 +88,7 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
        return 1;
 }
 
-static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
+static int snd_cs4231_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_wss *chip;
@@ -148,7 +148,7 @@ out:        snd_card_free(card);
        return error;
 }
 
-static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
+static int snd_cs4231_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -180,7 +180,7 @@ static int snd_cs4231_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_cs4231_driver = {
        .match          = snd_cs4231_match,
        .probe          = snd_cs4231_probe,
-       .remove         = __devexit_p(snd_cs4231_remove),
+       .remove         = snd_cs4231_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs4231_suspend,
        .resume         = snd_cs4231_resume,
index 740c51a1ed7bfbd5a508147990e67dcd30b46c15..252e9fb37db34bc862627255e129f1f36f50ed86 100644 (file)
@@ -251,7 +251,7 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
 MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids);
 
 /* WSS initialization */
-static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
+static int snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
 {
        if (pnp_activate_dev(pdev) < 0) {
                printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n");
@@ -272,7 +272,7 @@ static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
 }
 
 /* CTRL initialization */
-static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
+static int snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
 {
        if (pnp_activate_dev(pdev) < 0) {
                printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n");
@@ -284,7 +284,7 @@ static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
 }
 
 /* MPU initialization */
-static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
+static int snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
 {
        if (pnp_activate_dev(pdev) < 0) {
                printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n");
@@ -303,9 +303,9 @@ static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
        return 0;
 }
 
-static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
-                                        struct pnp_dev *pdev,
-                                        struct pnp_dev *cdev)
+static int snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
+                              struct pnp_dev *pdev,
+                              struct pnp_dev *cdev)
 {
        acard->wss = pdev;
        if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0)
@@ -317,9 +317,9 @@ static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
        return 0;
 }
 
-static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
-                                         struct pnp_card_link *card,
-                                         const struct pnp_card_device_id *id)
+static int snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
+                               struct pnp_card_link *card,
+                               const struct pnp_card_device_id *id)
 {
        acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
        if (acard->wss == NULL)
@@ -378,7 +378,7 @@ static int snd_cs423x_card_new(int dev, struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
+static int snd_cs423x_probe(struct snd_card *card, int dev)
 {
        struct snd_card_cs4236 *acard;
        struct snd_pcm *pcm;
@@ -456,8 +456,8 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
        return snd_card_register(card);
 }
 
-static int __devinit snd_cs423x_isa_match(struct device *pdev,
-                                         unsigned int dev)
+static int snd_cs423x_isa_match(struct device *pdev,
+                               unsigned int dev)
 {
        if (!enable[dev] || is_isapnp_selected(dev))
                return 0;
@@ -481,8 +481,8 @@ static int __devinit snd_cs423x_isa_match(struct device *pdev,
        return 1;
 }
 
-static int __devinit snd_cs423x_isa_probe(struct device *pdev,
-                                         unsigned int dev)
+static int snd_cs423x_isa_probe(struct device *pdev,
+                               unsigned int dev)
 {
        struct snd_card *card;
        int err;
@@ -500,8 +500,8 @@ static int __devinit snd_cs423x_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int __devexit snd_cs423x_isa_remove(struct device *pdev,
-                                          unsigned int dev)
+static int snd_cs423x_isa_remove(struct device *pdev,
+                                unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
@@ -540,7 +540,7 @@ static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver cs423x_isa_driver = {
        .match          = snd_cs423x_isa_match,
        .probe          = snd_cs423x_isa_probe,
-       .remove         = __devexit_p(snd_cs423x_isa_remove),
+       .remove         = snd_cs423x_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_isa_suspend,
        .resume         = snd_cs423x_isa_resume,
@@ -552,8 +552,8 @@ static struct isa_driver cs423x_isa_driver = {
 
 
 #ifdef CONFIG_PNP
-static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
-                                              const struct pnp_device_id *id)
+static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
+                                    const struct pnp_device_id *id)
 {
        static int dev;
        int err;
@@ -597,7 +597,7 @@ static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
        return 0;
 }
 
-static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev)
+static void snd_cs423x_pnp_remove(struct pnp_dev *pdev)
 {
        snd_card_free(pnp_get_drvdata(pdev));
        pnp_set_drvdata(pdev, NULL);
@@ -619,15 +619,15 @@ static struct pnp_driver cs423x_pnp_driver = {
        .name = "cs423x-pnpbios",
        .id_table = snd_cs423x_pnpbiosids,
        .probe = snd_cs423x_pnpbios_detect,
-       .remove = __devexit_p(snd_cs423x_pnp_remove),
+       .remove = snd_cs423x_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_pnp_suspend,
        .resume         = snd_cs423x_pnp_resume,
 #endif
 };
 
-static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
-                                           const struct pnp_card_device_id *pid)
+static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
+                                 const struct pnp_card_device_id *pid)
 {
        static int dev;
        struct snd_card *card;
@@ -659,7 +659,7 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard)
+static void snd_cs423x_pnpc_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -682,7 +682,7 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
        .name = CS423X_ISAPNP_DRIVER,
        .id_table = snd_cs423x_pnpids,
        .probe = snd_cs423x_pnpc_detect,
-       .remove = __devexit_p(snd_cs423x_pnpc_remove),
+       .remove = snd_cs423x_pnpc_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_cs423x_pnpc_suspend,
        .resume         = snd_cs423x_pnpc_resume,
index b036e60f62d14b02ec672aaa43f37e866fc1098b..102874a703d4cc8c53e98db88728215ef60cbec6 100644 (file)
@@ -90,13 +90,13 @@ MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
 #define is_isapnp_selected(dev)                0
 #endif
 
-static int __devinit snd_es1688_match(struct device *dev, unsigned int n)
+static int snd_es1688_match(struct device *dev, unsigned int n)
 {
        return enable[n] && !is_isapnp_selected(n);
 }
 
-static int __devinit snd_es1688_legacy_create(struct snd_card *card,
-                                       struct device *dev, unsigned int n)
+static int snd_es1688_legacy_create(struct snd_card *card,
+                                   struct device *dev, unsigned int n)
 {
        struct snd_es1688 *chip = card->private_data;
        static long possible_ports[] = {0x220, 0x240, 0x260};
@@ -134,7 +134,7 @@ static int __devinit snd_es1688_legacy_create(struct snd_card *card,
        return error;
 }
 
-static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
+static int snd_es1688_probe(struct snd_card *card, unsigned int n)
 {
        struct snd_es1688 *chip = card->private_data;
        struct snd_opl3 *opl3;
@@ -182,7 +182,7 @@ static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
        return snd_card_register(card);
 }
 
-static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n)
+static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        int error;
@@ -210,7 +210,7 @@ out:
        return error;
 }
 
-static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
+static int snd_es1688_isa_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -220,7 +220,7 @@ static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
 static struct isa_driver snd_es1688_driver = {
        .match          = snd_es1688_match,
        .probe          = snd_es1688_isa_probe,
-       .remove         = __devexit_p(snd_es1688_isa_remove),
+       .remove         = snd_es1688_isa_remove,
 #if 0  /* FIXME */
        .suspend        = snd_es1688_suspend,
        .resume         = snd_es1688_resume,
@@ -233,9 +233,9 @@ static struct isa_driver snd_es1688_driver = {
 static int snd_es968_pnp_is_probed;
 
 #ifdef CONFIG_PNP
-static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
-                                       struct pnp_card_link *pcard,
-                                       const struct pnp_card_device_id *pid)
+static int snd_card_es968_pnp(struct snd_card *card, unsigned int n,
+                             struct pnp_card_link *pcard,
+                             const struct pnp_card_device_id *pid)
 {
        struct snd_es1688 *chip = card->private_data;
        struct pnp_dev *pdev;
@@ -258,8 +258,8 @@ static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
                                 mpu_irq[n], dma8[n], ES1688_HW_AUTO);
 }
 
-static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
-                                         const struct pnp_card_device_id *pid)
+static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
+                               const struct pnp_card_device_id *pid)
 {
        struct snd_card *card;
        static unsigned int dev;
@@ -295,7 +295,7 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
+static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -338,7 +338,7 @@ static struct pnp_card_driver es968_pnpc_driver = {
        .name           = DEV_NAME " PnP",
        .id_table       = snd_es968_pnpids,
        .probe          = snd_es968_pnp_detect,
-       .remove         = __devexit_p(snd_es968_pnp_remove),
+       .remove         = snd_es968_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_es968_pnp_suspend,
        .resume         = snd_es968_pnp_resume,
index c20baafd9b7cfc0acfb02a943078da333ef294da..24380efe31a11099417f3422838f5854249cf286 100644 (file)
@@ -348,7 +348,7 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch
 }
 
 
-static int __devinit snd_es18xx_reset(struct snd_es18xx *chip)
+static int snd_es18xx_reset(struct snd_es18xx *chip)
 {
        int i;
         outb(0x03, chip->port + 0x06);
@@ -1363,7 +1363,7 @@ static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
 ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
 };
 
-static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
+static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
 {
        int data;
 
@@ -1372,8 +1372,8 @@ static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned ch
        return data;
 }
 
-static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip, 
-                                             unsigned char reg, unsigned char data)
+static void snd_es18xx_config_write(struct snd_es18xx *chip,
+                                   unsigned char reg, unsigned char data)
 {
        /* No need for spinlocks, this function is used only in
           otherwise protected init code */
@@ -1384,9 +1384,9 @@ static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
 #endif
 }
 
-static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
-                                          unsigned long mpu_port,
-                                          unsigned long fm_port)
+static int snd_es18xx_initialize(struct snd_es18xx *chip,
+                                unsigned long mpu_port,
+                                unsigned long fm_port)
 {
        int mask = 0;
 
@@ -1549,7 +1549,7 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
         return 0;
 }
 
-static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
+static int snd_es18xx_identify(struct snd_es18xx *chip)
 {
        int hi,lo;
 
@@ -1618,9 +1618,9 @@ static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
        return 0;
 }
 
-static int __devinit snd_es18xx_probe(struct snd_es18xx *chip,
-                                       unsigned long mpu_port,
-                                       unsigned long fm_port)
+static int snd_es18xx_probe(struct snd_es18xx *chip,
+                           unsigned long mpu_port,
+                           unsigned long fm_port)
 {
        if (snd_es18xx_identify(chip) < 0) {
                snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
@@ -1680,8 +1680,8 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
        .pointer =      snd_es18xx_capture_pointer,
 };
 
-static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
-                                   struct snd_pcm **rpcm)
+static int snd_es18xx_pcm(struct snd_card *card, int device,
+                         struct snd_pcm **rpcm)
 {
        struct snd_es18xx *chip = card->private_data;
         struct snd_pcm *pcm;
@@ -1777,11 +1777,11 @@ static int snd_es18xx_dev_free(struct snd_device *device)
        return snd_es18xx_free(device->card);
 }
 
-static int __devinit snd_es18xx_new_device(struct snd_card *card,
-                                          unsigned long port,
-                                          unsigned long mpu_port,
-                                          unsigned long fm_port,
-                                          int irq, int dma1, int dma2)
+static int snd_es18xx_new_device(struct snd_card *card,
+                                unsigned long port,
+                                unsigned long mpu_port,
+                                unsigned long fm_port,
+                                int irq, int dma1, int dma2)
 {
        struct snd_es18xx *chip = card->private_data;
        static struct snd_device_ops ops = {
@@ -1839,7 +1839,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
         return 0;
 }
 
-static int __devinit snd_es18xx_mixer(struct snd_card *card)
+static int snd_es18xx_mixer(struct snd_card *card)
 {
        struct snd_es18xx *chip = card->private_data;
        int err;
@@ -2016,7 +2016,7 @@ static struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
 MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids);
 
 /* PnP main device initialization */
-static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
+static int snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
 {
        if (pnp_activate_dev(pdev) < 0) {
                snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
@@ -2043,8 +2043,8 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
        return 0;
 }
 
-static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
-                                       struct pnp_dev *pdev)
+static int snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
+                             struct pnp_dev *pdev)
 {
        chip->dev = pdev;
        if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
@@ -2073,9 +2073,9 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
 
 MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
 
-static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
-                                       struct pnp_card_link *card,
-                                       const struct pnp_card_device_id *id)
+static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
+                              struct pnp_card_link *card,
+                              const struct pnp_card_device_id *id)
 {
        chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
        if (chip->dev == NULL)
@@ -2111,7 +2111,7 @@ static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
                               sizeof(struct snd_es18xx), cardp);
 }
 
-static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
+static int snd_audiodrive_probe(struct snd_card *card, int dev)
 {
        struct snd_es18xx *chip = card->private_data;
        struct snd_opl3 *opl3;
@@ -2169,12 +2169,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
        return snd_card_register(card);
 }
 
-static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
+static int snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
 {
        return enable[dev] && !is_isapnp_selected(dev);
 }
 
-static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
+static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
 {
        struct snd_card *card;
        int err;
@@ -2191,7 +2191,7 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
        return 0;
 }
 
-static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
+static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
 {
        int err;
        static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
@@ -2231,8 +2231,8 @@ static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static int __devexit snd_es18xx_isa_remove(struct device *devptr,
-                                          unsigned int dev)
+static int snd_es18xx_isa_remove(struct device *devptr,
+                                unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -2257,7 +2257,7 @@ static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_es18xx_isa_driver = {
        .match          = snd_es18xx_isa_match,
        .probe          = snd_es18xx_isa_probe,
-       .remove         = __devexit_p(snd_es18xx_isa_remove),
+       .remove         = snd_es18xx_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_es18xx_isa_suspend,
        .resume         = snd_es18xx_isa_resume,
@@ -2269,8 +2269,8 @@ static struct isa_driver snd_es18xx_isa_driver = {
 
 
 #ifdef CONFIG_PNP
-static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
-                                           const struct pnp_device_id *id)
+static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
+                                    const struct pnp_device_id *id)
 {
        static int dev;
        int err;
@@ -2302,7 +2302,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
        return 0;
 }
 
-static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev)
+static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev)
 {
        snd_card_free(pnp_get_drvdata(pdev));
        pnp_set_drvdata(pdev, NULL);
@@ -2323,15 +2323,15 @@ static struct pnp_driver es18xx_pnp_driver = {
        .name = "es18xx-pnpbios",
        .id_table = snd_audiodrive_pnpbiosids,
        .probe = snd_audiodrive_pnp_detect,
-       .remove = __devexit_p(snd_audiodrive_pnp_remove),
+       .remove = snd_audiodrive_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_audiodrive_pnp_suspend,
        .resume = snd_audiodrive_pnp_resume,
 #endif
 };
 
-static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
-                                              const struct pnp_card_device_id *pid)
+static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
+                                     const struct pnp_card_device_id *pid)
 {
        static int dev;
        struct snd_card *card;
@@ -2363,7 +2363,7 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard)
+static void snd_audiodrive_pnpc_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -2387,7 +2387,7 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
        .name = "es18xx",
        .id_table = snd_audiodrive_pnpids,
        .probe = snd_audiodrive_pnpc_detect,
-       .remove = __devexit_p(snd_audiodrive_pnpc_remove),
+       .remove = snd_audiodrive_pnpc_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_audiodrive_pnpc_suspend,
        .resume         = snd_audiodrive_pnpc_resume,
index 55e20782858d75baec9b48cf119e7740ed99134f..672184e3221a6e2765accc287c8e7b47596ff235 100644 (file)
@@ -84,7 +84,7 @@ MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
 
 #define DSP_COMMAND_GET_VERSION        0xe1
 
-static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
+static int dsp_get_byte(void __iomem *port, u8 *val)
 {
        int loops = 1000;
 
@@ -97,7 +97,7 @@ static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
        return 0;
 }
 
-static int __devinit dsp_reset(void __iomem *port)
+static int dsp_reset(void __iomem *port)
 {
        u8 val;
 
@@ -111,7 +111,7 @@ static int __devinit dsp_reset(void __iomem *port)
        return 0;
 }
 
-static int __devinit dsp_command(void __iomem *port, u8 cmd)
+static int dsp_command(void __iomem *port, u8 cmd)
 {
        int loops = 1000;
 
@@ -124,7 +124,7 @@ static int __devinit dsp_command(void __iomem *port, u8 cmd)
        return 0;
 }
 
-static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
+static int dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
 {
        int err;
 
@@ -161,7 +161,7 @@ static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
 
 #define WSS_SIGNATURE          4
 
-static int __devinit wss_detect(void __iomem *wss_port)
+static int wss_detect(void __iomem *wss_port)
 {
        if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
                return -ENODEV;
@@ -204,7 +204,7 @@ struct snd_galaxy {
 static u32 config[SNDRV_CARDS];
 static u8 wss_config[SNDRV_CARDS];
 
-static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
+static int snd_galaxy_match(struct device *dev, unsigned int n)
 {
        if (!enable[n])
                return 0;
@@ -379,7 +379,7 @@ fm:
        return 1;
 }
 
-static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
+static int galaxy_init(struct snd_galaxy *galaxy, u8 *type)
 {
        u8 major;
        u8 minor;
@@ -411,7 +411,7 @@ static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
        return 0;
 }
 
-static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
+static int galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
 {
        int err;
 
@@ -449,7 +449,7 @@ static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
        msleep(10);
 }
 
-static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
+static void galaxy_config(struct snd_galaxy *galaxy, u32 config)
 {
        int i;
 
@@ -461,7 +461,7 @@ static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
        galaxy_set_config(galaxy, config);
 }
 
-static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
+static int galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
 {
        int err;
 
@@ -498,7 +498,7 @@ static void snd_galaxy_free(struct snd_card *card)
        }
 }
 
-static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
+static int snd_galaxy_probe(struct device *dev, unsigned int n)
 {
        struct snd_galaxy *galaxy;
        struct snd_wss *chip;
@@ -620,7 +620,7 @@ error:
        return err;
 }
 
-static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
+static int snd_galaxy_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -630,7 +630,7 @@ static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
 static struct isa_driver snd_galaxy_driver = {
        .match          = snd_galaxy_match,
        .probe          = snd_galaxy_probe,
-       .remove         = __devexit_p(snd_galaxy_remove),
+       .remove         = snd_galaxy_remove,
 
        .driver         = {
                .name   = DEV_NAME
index bf63336716130a438c1c61e4020b8714dfe15c06..16bca4e96c08a01d5af759c95626b7bcbcc53065 100644 (file)
@@ -73,13 +73,14 @@ MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
 module_param_array(pcm_channels, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
 
-static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n)
+static int snd_gusclassic_match(struct device *dev, unsigned int n)
 {
        return enable[n];
 }
 
-static int __devinit snd_gusclassic_create(struct snd_card *card,
-               struct device *dev, unsigned int n, struct snd_gus_card **rgus)
+static int snd_gusclassic_create(struct snd_card *card,
+                                struct device *dev, unsigned int n,
+                                struct snd_gus_card **rgus)
 {
        static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
        static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
@@ -123,7 +124,7 @@ static int __devinit snd_gusclassic_create(struct snd_card *card,
        return error;
 }
 
-static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
+static int snd_gusclassic_detect(struct snd_gus_card *gus)
 {
        unsigned char d;
 
@@ -142,7 +143,7 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
        return 0;
 }
 
-static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n)
+static int snd_gusclassic_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_gus_card *gus;
@@ -211,7 +212,7 @@ out:        snd_card_free(card);
        return error;
 }
 
-static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
+static int snd_gusclassic_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -221,7 +222,7 @@ static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
 static struct isa_driver snd_gusclassic_driver = {
        .match          = snd_gusclassic_match,
        .probe          = snd_gusclassic_probe,
-       .remove         = __devexit_p(snd_gusclassic_remove),
+       .remove         = snd_gusclassic_remove,
 #if 0  /* FIXME */
        .suspend        = snd_gusclassic_suspend,
        .remove         = snd_gusclassic_remove,
index bc10cc26e5f94361594f76aaa8856b6347ccb133..0b9c2426b49f05608a3e0c099a9efdad20157cdf 100644 (file)
@@ -89,13 +89,14 @@ MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
 module_param_array(pcm_channels, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
 
-static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n)
+static int snd_gusextreme_match(struct device *dev, unsigned int n)
 {
        return enable[n];
 }
 
-static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
-               struct snd_es1688 *chip, struct device *dev, unsigned int n)
+static int snd_gusextreme_es1688_create(struct snd_card *card,
+                                       struct snd_es1688 *chip,
+                                       struct device *dev, unsigned int n)
 {
        static long possible_ports[] = {0x220, 0x240, 0x260};
        static int possible_irqs[] = {5, 9, 10, 7, -1};
@@ -132,8 +133,9 @@ static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
        return error;
 }
 
-static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
-               struct device *dev, unsigned int n, struct snd_gus_card **rgus)
+static int snd_gusextreme_gus_card_create(struct snd_card *card,
+                                         struct device *dev, unsigned int n,
+                                         struct snd_gus_card **rgus)
 {
        static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
        static int possible_dmas[] = {5, 6, 7, 3, 1, -1};
@@ -156,8 +158,8 @@ static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
                        0, channels[n], pcm_channels[n], 0, rgus);
 }
 
-static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
-       struct snd_es1688 *es1688)
+static int snd_gusextreme_detect(struct snd_gus_card *gus,
+                                struct snd_es1688 *es1688)
 {
        unsigned long flags;
        unsigned char d;
@@ -206,7 +208,7 @@ static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
        return 0;
 }
 
-static int __devinit snd_gusextreme_mixer(struct snd_card *card)
+static int snd_gusextreme_mixer(struct snd_card *card)
 {
        struct snd_ctl_elem_id id1, id2;
        int error;
@@ -232,7 +234,7 @@ static int __devinit snd_gusextreme_mixer(struct snd_card *card)
        return 0;
 }
 
-static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
+static int snd_gusextreme_probe(struct device *dev, unsigned int n)
 {
        struct snd_card *card;
        struct snd_gus_card *gus;
@@ -339,7 +341,7 @@ out:        snd_card_free(card);
        return error;
 }
 
-static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
+static int snd_gusextreme_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
        dev_set_drvdata(dev, NULL);
@@ -349,7 +351,7 @@ static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
 static struct isa_driver snd_gusextreme_driver = {
        .match          = snd_gusextreme_match,
        .probe          = snd_gusextreme_probe,
-       .remove         = __devexit_p(snd_gusextreme_remove),
+       .remove         = snd_gusextreme_remove,
 #if 0  /* FIXME */
        .suspend        = snd_gusextreme_suspend,
        .resume         = snd_gusextreme_resume,
index 41c3f448745ff14f197b1c5715fed49b12ebb386..c309a5d0e7e12e0eba6a3fc8a4d1414aebf5408c 100644 (file)
@@ -82,7 +82,7 @@ struct snd_gusmax {
 
 #define PFX    "gusmax: "
 
-static int __devinit snd_gusmax_detect(struct snd_gus_card * gus)
+static int snd_gusmax_detect(struct snd_gus_card *gus)
 {
        unsigned char d;
 
@@ -124,8 +124,8 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
        return IRQ_RETVAL(handled);
 }
 
-static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
-                                     struct snd_gus_card * gus)
+static void snd_gusmax_init(int dev, struct snd_card *card,
+                           struct snd_gus_card *gus)
 {
        gus->equal_irq = 1;
        gus->codec_flag = 1;
@@ -140,7 +140,7 @@ static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
        outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
 }
 
-static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
+static int snd_gusmax_mixer(struct snd_wss *chip)
 {
        struct snd_card *card = chip->card;
        struct snd_ctl_elem_id id1, id2;
@@ -199,12 +199,12 @@ static void snd_gusmax_free(struct snd_card *card)
                free_irq(maxcard->irq, (void *)maxcard);
 }
 
-static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev)
+static int snd_gusmax_match(struct device *pdev, unsigned int dev)
 {
        return enable[dev];
 }
 
-static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
+static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
 {
        static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
        static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
@@ -354,7 +354,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
        return err;
 }
 
-static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
+static int snd_gusmax_remove(struct device *devptr, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -366,7 +366,7 @@ static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_gusmax_driver = {
        .match          = snd_gusmax_match,
        .probe          = snd_gusmax_probe,
-       .remove         = __devexit_p(snd_gusmax_remove),
+       .remove         = snd_gusmax_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
index 3fc8b66fd167fc98bbdd42c29b889920f5c104ce..78bc5744e89a0cb66a34628916632186c8dd3029 100644 (file)
@@ -207,9 +207,9 @@ static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = {
        .getdata  = snd_interwave_i2c_getdataline,
 };
 
-static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
-                                             struct snd_gus_card * gus, int dev,
-                                             struct snd_i2c_bus **rbus)
+static int snd_interwave_detect_stb(struct snd_interwave *iwcard,
+                                   struct snd_gus_card *gus, int dev,
+                                   struct snd_i2c_bus **rbus)
 {
        unsigned long port;
        struct snd_i2c_bus *bus;
@@ -249,11 +249,11 @@ static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
 }
 #endif
 
-static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
-                                         struct snd_gus_card * gus,
-                                         int dev
+static int snd_interwave_detect(struct snd_interwave *iwcard,
+                               struct snd_gus_card *gus,
+                               int dev
 #ifdef SNDRV_STB
-                                         , struct snd_i2c_bus **rbus
+                               , struct snd_i2c_bus **rbus
 #endif
                                          )
 {
@@ -318,7 +318,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id)
        return IRQ_RETVAL(handled);
 }
 
-static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
+static void snd_interwave_reset(struct snd_gus_card *gus)
 {
        snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00);
        udelay(160);
@@ -326,7 +326,7 @@ static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
        udelay(160);
 }
 
-static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes)
+static void snd_interwave_bank_sizes(struct snd_gus_card *gus, int *sizes)
 {
        unsigned int idx;
        unsigned int local;
@@ -377,7 +377,7 @@ struct rom_hdr {
        /* 511 */ unsigned char csum;
 };
 
-static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
+static void snd_interwave_detect_memory(struct snd_gus_card *gus)
 {
        static unsigned int lmc[13] =
        {
@@ -475,7 +475,7 @@ static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
                snd_interwave_reset(gus);
 }
 
-static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus)
+static void snd_interwave_init(int dev, struct snd_gus_card *gus)
 {
        unsigned long flags;
 
@@ -508,7 +508,7 @@ WSS_DOUBLE("Mic Playback Volume", 0,
                CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
 };
 
-static int __devinit snd_interwave_mixer(struct snd_wss *chip)
+static int snd_interwave_mixer(struct snd_wss *chip)
 {
        struct snd_card *card = chip->card;
        struct snd_ctl_elem_id id1, id2;
@@ -558,9 +558,9 @@ static int __devinit snd_interwave_mixer(struct snd_wss *chip)
 
 #ifdef CONFIG_PNP
 
-static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
-                                      struct pnp_card_link *card,
-                                      const struct pnp_card_device_id *id)
+static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
+                            struct pnp_card_link *card,
+                            const struct pnp_card_device_id *id)
 {
        struct pnp_dev *pdev;
        int err;
@@ -644,7 +644,7 @@ static int snd_interwave_card_new(int dev, struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
+static int snd_interwave_probe(struct snd_card *card, int dev)
 {
        int xirq, xdma1, xdma2;
        struct snd_interwave *iwcard = card->private_data;
@@ -775,7 +775,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
        return 0;
 }
 
-static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
+static int snd_interwave_isa_probe1(int dev, struct device *devptr)
 {
        struct snd_card *card;
        int err;
@@ -793,8 +793,8 @@ static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
        return 0;
 }
 
-static int __devinit snd_interwave_isa_match(struct device *pdev,
-                                            unsigned int dev)
+static int snd_interwave_isa_match(struct device *pdev,
+                                  unsigned int dev)
 {
        if (!enable[dev])
                return 0;
@@ -805,8 +805,8 @@ static int __devinit snd_interwave_isa_match(struct device *pdev,
        return 1;
 }
 
-static int __devinit snd_interwave_isa_probe(struct device *pdev,
-                                            unsigned int dev)
+static int snd_interwave_isa_probe(struct device *pdev,
+                                  unsigned int dev)
 {
        int err;
        static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
@@ -846,7 +846,7 @@ static int __devinit snd_interwave_isa_probe(struct device *pdev,
        }
 }
 
-static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
+static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -856,7 +856,7 @@ static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned in
 static struct isa_driver snd_interwave_driver = {
        .match          = snd_interwave_isa_match,
        .probe          = snd_interwave_isa_probe,
-       .remove         = __devexit_p(snd_interwave_isa_remove),
+       .remove         = snd_interwave_isa_remove,
        /* FIXME: suspend,resume */
        .driver         = {
                .name   = INTERWAVE_DRIVER
@@ -864,8 +864,8 @@ static struct isa_driver snd_interwave_driver = {
 };
 
 #ifdef CONFIG_PNP
-static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
-                                             const struct pnp_card_device_id *pid)
+static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
+                                   const struct pnp_card_device_id *pid)
 {
        static int dev;
        struct snd_card *card;
@@ -896,7 +896,7 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard)
+static void snd_interwave_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -907,7 +907,7 @@ static struct pnp_card_driver interwave_pnpc_driver = {
        .name = INTERWAVE_PNP_DRIVER,
        .id_table = snd_interwave_pnpids,
        .probe = snd_interwave_pnp_detect,
-       .remove = __devexit_p(snd_interwave_pnp_remove),
+       .remove = snd_interwave_pnp_remove,
        /* FIXME: suspend,resume */
 };
 
index a168ba3313ac3449063edb1aacfc6654338a43b8..dbac3a42347b7db65a2394daeebf4a6a86529f41 100644 (file)
@@ -303,6 +303,6 @@ int snd_msndmidi_new(struct snd_card *card, int device);
 void snd_msndmidi_input_read(void *mpu);
 
 void snd_msndmix_setup(struct snd_msnd *chip);
-int __devinit snd_msndmix_new(struct snd_card *card);
+int snd_msndmix_new(struct snd_card *card);
 int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc);
 #endif /* __MSND_H */
index 29cc8e162b0276bc380132ca78c2fae07293b798..ddabb406b14cbacfe660678fe72326fab49bc15c 100644 (file)
@@ -78,7 +78,7 @@
 #  define LOGNAME                      "snd_msnd_pinnacle"
 #endif
 
-static void __devinit set_default_audio_parameters(struct snd_msnd *chip)
+static void set_default_audio_parameters(struct snd_msnd *chip)
 {
        chip->play_sample_size = DEFSAMPLESIZE;
        chip->play_sample_rate = DEFSAMPLERATE;
@@ -213,7 +213,7 @@ static int snd_msnd_reset_dsp(long io, unsigned char *info)
        return -EIO;
 }
 
-static int __devinit snd_msnd_probe(struct snd_card *card)
+static int snd_msnd_probe(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
        unsigned char info;
@@ -497,7 +497,7 @@ static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
        return snd_msnd_send_dsp_cmd(chip, cmd);
 }
 
-static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
+static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
 {
        snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate);
        writew(srate, chip->SMA + SMA_wCalFreqAtoD);
@@ -535,7 +535,7 @@ static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
 static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
 
-static int __devinit snd_msnd_attach(struct snd_card *card)
+static int snd_msnd_attach(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
        int err;
@@ -634,7 +634,7 @@ err_release_region:
 }
 
 
-static void __devexit snd_msnd_unload(struct snd_card *card)
+static void snd_msnd_unload(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
 
@@ -649,7 +649,7 @@ static void __devexit snd_msnd_unload(struct snd_card *card)
 
 /* Pinnacle/Fiji Logical Device Configuration */
 
-static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
+static int snd_msnd_write_cfg(int cfg, int reg, int value)
 {
        outb(reg, cfg);
        outb(value, cfg + 1);
@@ -660,7 +660,7 @@ static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
        return 0;
 }
 
-static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
+static int snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
 {
        if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
                return -EIO;
@@ -671,7 +671,7 @@ static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
        return 0;
 }
 
-static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
+static int snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
 {
        if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
                return -EIO;
@@ -682,7 +682,7 @@ static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
        return 0;
 }
 
-static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
+static int snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
 {
        if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
                return -EIO;
@@ -693,7 +693,7 @@ static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
        return 0;
 }
 
-static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
+static int snd_msnd_write_cfg_mem(int cfg, int num, int mem)
 {
        u16 wmem;
 
@@ -711,7 +711,7 @@ static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
        return 0;
 }
 
-static int __devinit snd_msnd_activate_logical(int cfg, int num)
+static int snd_msnd_activate_logical(int cfg, int num)
 {
        if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
                return -EIO;
@@ -720,8 +720,8 @@ static int __devinit snd_msnd_activate_logical(int cfg, int num)
        return 0;
 }
 
-static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
-                                               u16 io1, u16 irq, int mem)
+static int snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
+                                     u16 io1, u16 irq, int mem)
 {
        if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
                return -EIO;
@@ -738,7 +738,7 @@ static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
        return 0;
 }
 
-static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg)
+static int snd_msnd_pinnacle_cfg_reset(int cfg)
 {
        int i;
 
@@ -818,7 +818,7 @@ module_param_array(joystick_io, long, NULL, S_IRUGO);
 #endif
 
 
-static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
+static int snd_msnd_isa_match(struct device *pdev, unsigned int i)
 {
        if (io[i] == SNDRV_AUTO_PORT)
                return 0;
@@ -888,7 +888,7 @@ static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
        return 1;
 }
 
-static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
+static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
 {
        int err;
        struct snd_card *card;
@@ -1061,7 +1061,7 @@ cfg_error:
 #endif
 }
 
-static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
 {
        snd_msnd_unload(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
@@ -1073,7 +1073,7 @@ static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
 static struct isa_driver snd_msnd_driver = {
        .match          = snd_msnd_isa_match,
        .probe          = snd_msnd_isa_probe,
-       .remove         = __devexit_p(snd_msnd_isa_remove),
+       .remove         = snd_msnd_isa_remove,
        /* FIXME: suspend, resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1081,8 +1081,8 @@ static struct isa_driver snd_msnd_driver = {
 };
 
 #ifdef CONFIG_PNP
-static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard,
-                                        const struct pnp_card_device_id *pid)
+static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
+                              const struct pnp_card_device_id *pid)
 {
        static int idx;
        struct pnp_dev *pnp_dev;
@@ -1185,7 +1185,7 @@ _release_card:
        return ret;
 }
 
-static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard)
+static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_msnd_unload(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -1207,7 +1207,7 @@ static struct pnp_card_driver msnd_pnpc_driver = {
        .name = "msnd_pinnacle",
        .id_table = msnd_pnpids,
        .probe = snd_msnd_pnp_detect,
-       .remove = __devexit_p(snd_msnd_pnp_remove),
+       .remove = snd_msnd_pnp_remove,
 };
 #endif /* CONFIG_PNP */
 
index 1de59d4414260a6c6a20b9454c112eb99d0f08e4..031dc69b7470a0b9d6f3bce39284a6c94474a9e9 100644 (file)
@@ -302,7 +302,7 @@ DUMMY_VOLUME("Monitor",     0, MSND_MIXER_IMIX),
 };
 
 
-int __devinit snd_msndmix_new(struct snd_card *card)
+int snd_msndmix_new(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
        unsigned int idx;
index f6cc0b917ef03bfe5d38f619e1b3341a42cacf39..075777a6cf0b3d165ff27d537eb48a9573d6b1f4 100644 (file)
@@ -221,7 +221,7 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
        spin_unlock_irqrestore(&chip->reg_lock, flags);
 }
 
-static int __devinit snd_opl3sa2_detect(struct snd_card *card)
+static int snd_opl3sa2_detect(struct snd_card *card)
 {
        struct snd_opl3sa2 *chip = card->private_data;
        unsigned long port;
@@ -496,7 +496,7 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
        chip->master_volume = NULL;
 }
 
-static int __devinit snd_opl3sa2_mixer(struct snd_card *card)
+static int snd_opl3sa2_mixer(struct snd_card *card)
 {
        struct snd_opl3sa2 *chip = card->private_data;
        struct snd_ctl_elem_id id1, id2;
@@ -596,8 +596,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PNP
-static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
-                                    struct pnp_dev *pdev)
+static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
+                          struct pnp_dev *pdev)
 {
        if (pnp_activate_dev(pdev) < 0) {
                snd_printk(KERN_ERR "PnP configure failure (out of resources?)\n");
@@ -647,7 +647,7 @@ static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
+static int snd_opl3sa2_probe(struct snd_card *card, int dev)
 {
        int xirq, xdma1, xdma2;
        struct snd_opl3sa2 *chip;
@@ -721,8 +721,8 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
 }
 
 #ifdef CONFIG_PNP
-static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
-                                           const struct pnp_device_id *id)
+static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
+                                 const struct pnp_device_id *id)
 {
        static int dev;
        int err;
@@ -754,7 +754,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
        return 0;
 }
 
-static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev)
+static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev)
 {
        snd_card_free(pnp_get_drvdata(pdev));
        pnp_set_drvdata(pdev, NULL);
@@ -775,15 +775,15 @@ static struct pnp_driver opl3sa2_pnp_driver = {
        .name = "snd-opl3sa2-pnpbios",
        .id_table = snd_opl3sa2_pnpbiosids,
        .probe = snd_opl3sa2_pnp_detect,
-       .remove = __devexit_p(snd_opl3sa2_pnp_remove),
+       .remove = snd_opl3sa2_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_opl3sa2_pnp_suspend,
        .resume = snd_opl3sa2_pnp_resume,
 #endif
 };
 
-static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
-                                            const struct pnp_card_device_id *id)
+static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
+                                  const struct pnp_card_device_id *id)
 {
        static int dev;
        struct pnp_dev *pdev;
@@ -820,7 +820,7 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard)
+static void snd_opl3sa2_pnp_cremove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -842,7 +842,7 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
        .name = "snd-opl3sa2-cpnp",
        .id_table = snd_opl3sa2_pnpids,
        .probe = snd_opl3sa2_pnp_cdetect,
-       .remove = __devexit_p(snd_opl3sa2_pnp_cremove),
+       .remove = snd_opl3sa2_pnp_cremove,
 #ifdef CONFIG_PM
        .suspend = snd_opl3sa2_pnp_csuspend,
        .resume = snd_opl3sa2_pnp_cresume,
@@ -850,8 +850,8 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
 };
 #endif /* CONFIG_PNP */
 
-static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
-                                          unsigned int dev)
+static int snd_opl3sa2_isa_match(struct device *pdev,
+                                unsigned int dev)
 {
        if (!enable[dev])
                return 0;
@@ -878,8 +878,8 @@ static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
        return 1;
 }
 
-static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
-                                          unsigned int dev)
+static int snd_opl3sa2_isa_probe(struct device *pdev,
+                                unsigned int dev)
 {
        struct snd_card *card;
        int err;
@@ -896,8 +896,8 @@ static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int __devexit snd_opl3sa2_isa_remove(struct device *devptr,
-                                           unsigned int dev)
+static int snd_opl3sa2_isa_remove(struct device *devptr,
+                                 unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -922,7 +922,7 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_opl3sa2_isa_driver = {
        .match          = snd_opl3sa2_isa_match,
        .probe          = snd_opl3sa2_isa_probe,
-       .remove         = __devexit_p(snd_opl3sa2_isa_remove),
+       .remove         = snd_opl3sa2_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opl3sa2_isa_suspend,
        .resume         = snd_opl3sa2_isa_resume,
index 4a7ff4e8985ba2fe3b71ac7b57a191e694063ae2..c3da1df9371df1c4c5cce4c6c00001906d270395 100644 (file)
@@ -587,7 +587,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_controls[] = {
 MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
 MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
 MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
@@ -599,7 +599,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
 
 /* Equalizer with seven bands (only PCM20) 
    from -12dB up to +12dB on each band */
-static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_eq_controls[] = {
 MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
 MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
 MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
@@ -609,15 +609,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
 MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
 };
 
-static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_radio_control[] = {
 MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
 };
 
-static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_line_control[] = {
 MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
 };
 
-static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_preamp_control[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Mic Boost",
@@ -627,7 +627,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
        .put = snd_miro_put_preamp,
 }};
 
-static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_amp_control[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Line Boost",
@@ -637,7 +637,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
        .put = snd_miro_put_amp,
 }};
 
-static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
+static struct snd_kcontrol_new snd_miro_capture_control[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "PCM Capture Switch",
@@ -647,7 +647,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
        .put = snd_miro_put_capture,
 }};
 
-static unsigned char aci_init_values[][2] __devinitdata = {
+static unsigned char aci_init_values[][2] = {
        { ACI_SET_MUTE, 0x00 },
        { ACI_SET_POWERAMP, 0x00 },
        { ACI_SET_PREAMP, 0x00 },
@@ -670,7 +670,7 @@ static unsigned char aci_init_values[][2] __devinitdata = {
        { ACI_SET_MASTER + 1, 0x20 },
 };
 
-static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
+static int snd_set_aci_init_values(struct snd_miro *miro)
 {
        int idx, error;
        struct snd_miro_aci *aci = miro->aci;
@@ -713,8 +713,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
        return 0;
 }
 
-static int __devinit snd_miro_mixer(struct snd_card *card,
-                                   struct snd_miro *miro)
+static int snd_miro_mixer(struct snd_card *card,
+                         struct snd_miro *miro)
 {
        unsigned int idx;
        int err;
@@ -771,8 +771,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_miro_init(struct snd_miro *chip,
-                                  unsigned short hardware)
+static int snd_miro_init(struct snd_miro *chip,
+                        unsigned short hardware)
 {
        static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 
@@ -989,8 +989,8 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
        snd_iprintf(buffer, "  preamp  : 0x%x\n", aci->aci_preamp);
 }
 
-static void __devinit snd_miro_proc_init(struct snd_card *card,
-                                        struct snd_miro *miro)
+static void snd_miro_proc_init(struct snd_card *card,
+                              struct snd_miro *miro)
 {
        struct snd_info_entry *entry;
 
@@ -1002,7 +1002,7 @@ static void __devinit snd_miro_proc_init(struct snd_card *card,
  *  Init
  */
 
-static int __devinit snd_miro_configure(struct snd_miro *chip)
+static int snd_miro_configure(struct snd_miro *chip)
 {
        unsigned char wss_base_bits;
        unsigned char irq_bits;
@@ -1162,7 +1162,7 @@ __skip_mpu:
        return 0;
 }
 
-static int __devinit snd_miro_opti_check(struct snd_miro *chip)
+static int snd_miro_opti_check(struct snd_miro *chip)
 {
        unsigned char value;
 
@@ -1182,8 +1182,8 @@ static int __devinit snd_miro_opti_check(struct snd_miro *chip)
        return -ENODEV;
 }
 
-static int __devinit snd_card_miro_detect(struct snd_card *card,
-                                         struct snd_miro *chip)
+static int snd_card_miro_detect(struct snd_card *card,
+                               struct snd_miro *chip)
 {
        int i, err;
 
@@ -1200,8 +1200,8 @@ static int __devinit snd_card_miro_detect(struct snd_card *card,
        return -ENODEV;
 }
 
-static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
-                                             struct snd_miro *miro)
+static int snd_card_miro_aci_detect(struct snd_card *card,
+                                   struct snd_miro *miro)
 {
        unsigned char regval;
        int i;
@@ -1265,7 +1265,7 @@ static void snd_card_miro_free(struct snd_card *card)
        release_and_free_resource(miro->res_mc_base);
 }
 
-static int __devinit snd_miro_probe(struct snd_card *card)
+static int snd_miro_probe(struct snd_card *card)
 {
        int error;
        struct snd_miro *miro = card->private_data;
@@ -1386,7 +1386,7 @@ static int __devinit snd_miro_probe(struct snd_card *card)
        return snd_card_register(card);
 }
 
-static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
+static int snd_miro_isa_match(struct device *devptr, unsigned int n)
 {
 #ifdef CONFIG_PNP
        if (snd_miro_pnp_is_probed)
@@ -1397,7 +1397,7 @@ static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
        return 1;
 }
 
-static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
+static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
 {
        static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
        static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
@@ -1491,8 +1491,8 @@ static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
        return 0;
 }
 
-static int __devexit snd_miro_isa_remove(struct device *devptr,
-                                        unsigned int dev)
+static int snd_miro_isa_remove(struct device *devptr,
+                              unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -1504,7 +1504,7 @@ static int __devexit snd_miro_isa_remove(struct device *devptr,
 static struct isa_driver snd_miro_driver = {
        .match          = snd_miro_isa_match,
        .probe          = snd_miro_isa_probe,
-       .remove         = __devexit_p(snd_miro_isa_remove),
+       .remove         = snd_miro_isa_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1513,9 +1513,9 @@ static struct isa_driver snd_miro_driver = {
 
 #ifdef CONFIG_PNP
 
-static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
-                                       struct pnp_card_link *card,
-                                       const struct pnp_card_device_id *pid)
+static int snd_card_miro_pnp(struct snd_miro *chip,
+                            struct pnp_card_link *card,
+                            const struct pnp_card_device_id *pid)
 {
        struct pnp_dev *pdev;
        int err;
@@ -1574,8 +1574,8 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
        return 0;
 }
 
-static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
-                                       const struct pnp_card_device_id *pid)
+static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
+                             const struct pnp_card_device_id *pid)
 {
        struct snd_card *card;
        int err;
@@ -1624,7 +1624,7 @@ static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard)
+static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -1636,7 +1636,7 @@ static struct pnp_card_driver miro_pnpc_driver = {
        .name           = "miro",
        .id_table       = snd_miro_pnpids,
        .probe          = snd_miro_pnp_probe,
-       .remove         = __devexit_p(snd_miro_pnp_remove),
+       .remove         = snd_miro_pnp_remove,
 };
 #endif
 
index 2899c9fd1ceb4c12a34d01d714ec1bd3d4e74767..b41ed8661b237abd41676cf2bed810686028e046 100644 (file)
@@ -186,8 +186,8 @@ static char * snd_opti9xx_names[] = {
        "82C930",       "82C931",       "82C933"
 };
 
-static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
-                                     unsigned short hardware)
+static int snd_opti9xx_init(struct snd_opti9xx *chip,
+                           unsigned short hardware)
 {
        static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 
@@ -593,7 +593,7 @@ WSS_DOUBLE_TLV("Aux Playback Volume", 0,
                db_scale_4bit_12db_max),
 };
 
-static int __devinit snd_opti93x_mixer(struct snd_wss *chip)
+static int snd_opti93x_mixer(struct snd_wss *chip)
 {
        struct snd_card *card;
        unsigned int idx;
@@ -666,7 +666,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 
 #endif /* OPTi93X */
 
-static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
+static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
 {
        unsigned char value;
 #ifdef OPTi93X
@@ -707,8 +707,8 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
        return -ENODEV;
 }
 
-static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
-                                            struct snd_opti9xx *chip)
+static int snd_card_opti9xx_detect(struct snd_card *card,
+                                  struct snd_opti9xx *chip)
 {
        int i, err;
 
@@ -732,9 +732,9 @@ static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
 }
 
 #ifdef CONFIG_PNP
-static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
-                                         struct pnp_card_link *card,
-                                         const struct pnp_card_device_id *pid)
+static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
+                               struct pnp_card_link *card,
+                               const struct pnp_card_device_id *pid)
 {
        struct pnp_dev *pdev;
        int err;
@@ -817,7 +817,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
        }
 }
 
-static int __devinit snd_opti9xx_probe(struct snd_card *card)
+static int snd_opti9xx_probe(struct snd_card *card)
 {
        static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
        int error;
@@ -952,8 +952,8 @@ static int snd_opti9xx_card_new(struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit snd_opti9xx_isa_match(struct device *devptr,
-                                          unsigned int dev)
+static int snd_opti9xx_isa_match(struct device *devptr,
+                                unsigned int dev)
 {
 #ifdef CONFIG_PNP
        if (snd_opti9xx_pnp_is_probed)
@@ -964,8 +964,8 @@ static int __devinit snd_opti9xx_isa_match(struct device *devptr,
        return 1;
 }
 
-static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
-                                          unsigned int dev)
+static int snd_opti9xx_isa_probe(struct device *devptr,
+                                unsigned int dev)
 {
        struct snd_card *card;
        int error;
@@ -1031,8 +1031,8 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
        return 0;
 }
 
-static int __devexit snd_opti9xx_isa_remove(struct device *devptr,
-                                           unsigned int dev)
+static int snd_opti9xx_isa_remove(struct device *devptr,
+                                 unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -1083,7 +1083,7 @@ static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_opti9xx_driver = {
        .match          = snd_opti9xx_isa_match,
        .probe          = snd_opti9xx_isa_probe,
-       .remove         = __devexit_p(snd_opti9xx_isa_remove),
+       .remove         = snd_opti9xx_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opti9xx_isa_suspend,
        .resume         = snd_opti9xx_isa_resume,
@@ -1094,8 +1094,8 @@ static struct isa_driver snd_opti9xx_driver = {
 };
 
 #ifdef CONFIG_PNP
-static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
-                                          const struct pnp_card_device_id *pid)
+static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
+                                const struct pnp_card_device_id *pid)
 {
        struct snd_card *card;
        int error, hw;
@@ -1146,7 +1146,7 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
+static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -1171,7 +1171,7 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
        .name           = "opti9xx",
        .id_table       = snd_opti9xx_pnpids,
        .probe          = snd_opti9xx_pnp_probe,
-       .remove         = __devexit_p(snd_opti9xx_pnp_remove),
+       .remove         = snd_opti9xx_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_opti9xx_pnp_suspend,
        .resume         = snd_opti9xx_pnp_resume,
index 2aae6a0efbcd3a2a05e40f896fc0374be7e3eb3b..45fcdff611f919263d335875144ee67dc78585bf 100644 (file)
@@ -131,7 +131,7 @@ snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
 
 /*
  */
-static void __devinit
+static void
 snd_emu8000_read_wait(struct snd_emu8000 *emu)
 {
        while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
@@ -143,7 +143,7 @@ snd_emu8000_read_wait(struct snd_emu8000 *emu)
 
 /*
  */
-static void __devinit
+static void
 snd_emu8000_write_wait(struct snd_emu8000 *emu)
 {
        while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
@@ -156,7 +156,7 @@ snd_emu8000_write_wait(struct snd_emu8000 *emu)
 /*
  * detect a card at the given port
  */
-static int __devinit
+static int
 snd_emu8000_detect(struct snd_emu8000 *emu)
 {
        /* Initialise */
@@ -182,7 +182,7 @@ snd_emu8000_detect(struct snd_emu8000 *emu)
 /*
  * intiailize audio channels
  */
-static void __devinit
+static void
 init_audio(struct snd_emu8000 *emu)
 {
        int ch;
@@ -223,7 +223,7 @@ init_audio(struct snd_emu8000 *emu)
 /*
  * initialize DMA address
  */
-static void __devinit
+static void
 init_dma(struct snd_emu8000 *emu)
 {
        EMU8000_SMALR_WRITE(emu, 0);
@@ -235,7 +235,7 @@ init_dma(struct snd_emu8000 *emu)
 /*
  * initialization arrays; from ADIP
  */
-static unsigned short init1[128] /*__devinitdata*/ = {
+static unsigned short init1[128] = {
        0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
        0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
        0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
@@ -257,7 +257,7 @@ static unsigned short init1[128] /*__devinitdata*/ = {
        0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
 };
 
-static unsigned short init2[128] /*__devinitdata*/ = {
+static unsigned short init2[128] = {
        0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
        0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
        0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
@@ -279,7 +279,7 @@ static unsigned short init2[128] /*__devinitdata*/ = {
        0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
 };
 
-static unsigned short init3[128] /*__devinitdata*/ = {
+static unsigned short init3[128] = {
        0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
        0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
        0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
@@ -301,7 +301,7 @@ static unsigned short init3[128] /*__devinitdata*/ = {
        0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
 };
 
-static unsigned short init4[128] /*__devinitdata*/ = {
+static unsigned short init4[128] = {
        0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
        0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
        0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
@@ -327,7 +327,7 @@ static unsigned short init4[128] /*__devinitdata*/ = {
  * Taken from the oss driver, not obvious from the doc how this
  * is meant to work
  */
-static void __devinit
+static void
 send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
 {
        int i;
@@ -349,7 +349,7 @@ send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
  * Send initialization arrays to start up, this just follows the
  * initialisation sequence in the adip.
  */
-static void __devinit
+static void
 init_arrays(struct snd_emu8000 *emu)
 {
        send_array(emu, init1, ARRAY_SIZE(init1)/4);
@@ -375,7 +375,7 @@ init_arrays(struct snd_emu8000 *emu)
  * seems that the only way to do this is to use the one channel and keep
  * reallocating between read and write.
  */
-static void __devinit
+static void
 size_dram(struct snd_emu8000 *emu)
 {
        int i, size, detected_size;
@@ -512,7 +512,7 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu)
 /*
  * The main initialization routine.
  */
-static void __devinit
+static void
 snd_emu8000_init_hw(struct snd_emu8000 *emu)
 {
        int i;
@@ -1031,7 +1031,7 @@ static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
 /*
  * create and attach mixer elements for WaveTable treble/bass controls
  */
-static int __devinit
+static int
 snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
 {
        int i, err = 0;
@@ -1082,7 +1082,7 @@ static int snd_emu8000_dev_free(struct snd_device *device)
 /*
  * initialize and register emu8000 synth device.
  */
-int __devinit
+int
 snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
                struct snd_seq_device **awe_ret)
 {
index 410758c68090397d2747af150f5b2f8cbc07c9e2..4961da4e627c24878c5cf0537cf70ffd90c8b221 100644 (file)
@@ -78,8 +78,8 @@ static irqreturn_t jazz16_interrupt(int irq, void *chip)
        return snd_sb8dsp_interrupt(chip);
 }
 
-static int __devinit jazz16_configure_ports(unsigned long port,
-                                           unsigned long mpu_port, int idx)
+static int jazz16_configure_ports(unsigned long port,
+                                 unsigned long mpu_port, int idx)
 {
        unsigned char val;
 
@@ -99,8 +99,8 @@ static int __devinit jazz16_configure_ports(unsigned long port,
        return 0;
 }
 
-static int __devinit jazz16_detect_board(unsigned long port,
-                                        unsigned long mpu_port)
+static int jazz16_detect_board(unsigned long port,
+                              unsigned long mpu_port)
 {
        int err;
        int val;
@@ -156,7 +156,7 @@ err_unmap:
        return err;
 }
 
-static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
+static int jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
 {
        static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
                                                 0, 2, 5, 0, 0, 0, 0, 6 };
@@ -183,7 +183,7 @@ static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
        return 0;
 }
 
-static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
+static int snd_jazz16_match(struct device *devptr, unsigned int dev)
 {
        if (!enable[dev])
                return 0;
@@ -218,7 +218,7 @@ static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
        return 1;
 }
 
-static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
+static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
 {
        struct snd_card *card;
        struct snd_card_jazz16 *jazz16;
@@ -341,7 +341,7 @@ err_free:
        return err;
 }
 
-static int __devexit snd_jazz16_remove(struct device *devptr, unsigned int dev)
+static int snd_jazz16_remove(struct device *devptr, unsigned int dev)
 {
        struct snd_card *card = dev_get_drvdata(devptr);
 
@@ -380,7 +380,7 @@ static int snd_jazz16_resume(struct device *pdev, unsigned int n)
 static struct isa_driver snd_jazz16_driver = {
        .match          = snd_jazz16_match,
        .probe          = snd_jazz16_probe,
-       .remove         = __devexit_p(snd_jazz16_remove),
+       .remove         = snd_jazz16_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_jazz16_suspend,
        .resume         = snd_jazz16_resume,
index 39b8eca152137434e32cba0b0e60bf6ecba444b2..50dbec454f9872df065c54667d77e6ac1753f635 100644 (file)
@@ -250,9 +250,9 @@ MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids);
 
 #ifdef CONFIG_PNP
 
-static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
-                                      struct pnp_card_link *card,
-                                      const struct pnp_card_device_id *id)
+static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
+                            struct pnp_card_link *card,
+                            const struct pnp_card_device_id *id)
 {
        struct pnp_dev *pdev;
        int err;
@@ -337,7 +337,7 @@ static int snd_sb16_card_new(int dev, struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
+static int snd_sb16_probe(struct snd_card *card, int dev)
 {
        int xirq, xdma8, xdma16;
        struct snd_sb *chip;
@@ -487,7 +487,7 @@ static int snd_sb16_resume(struct snd_card *card)
 }
 #endif
 
-static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
+static int snd_sb16_isa_probe1(int dev, struct device *pdev)
 {
        struct snd_card_sb16 *acard;
        struct snd_card *card;
@@ -517,12 +517,12 @@ static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
 }
 
 
-static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev)
+static int snd_sb16_isa_match(struct device *pdev, unsigned int dev)
 {
        return enable[dev] && !is_isapnp_selected(dev);
 }
 
-static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
+static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
 {
        int err;
        static int possible_irqs[] = {5, 9, 10, 7, -1};
@@ -563,7 +563,7 @@ static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
+static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
@@ -592,7 +592,7 @@ static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_sb16_isa_driver = {
        .match          = snd_sb16_isa_match,
        .probe          = snd_sb16_isa_probe,
-       .remove         = __devexit_p(snd_sb16_isa_remove),
+       .remove         = snd_sb16_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_sb16_isa_suspend,
        .resume         = snd_sb16_isa_resume,
@@ -604,8 +604,8 @@ static struct isa_driver snd_sb16_isa_driver = {
 
 
 #ifdef CONFIG_PNP
-static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
-                                        const struct pnp_card_device_id *pid)
+static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
+                              const struct pnp_card_device_id *pid)
 {
        static int dev;
        struct snd_card *card;
@@ -631,7 +631,7 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
        return -ENODEV;
 }
 
-static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard)
+static void snd_sb16_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -657,7 +657,7 @@ static struct pnp_card_driver sb16_pnpc_driver = {
 #endif
        .id_table = snd_sb16_pnpids,
        .probe = snd_sb16_pnp_detect,
-       .remove = __devexit_p(snd_sb16_pnp_remove),
+       .remove = snd_sb16_pnp_remove,
 #ifdef CONFIG_PM
        .suspend = snd_sb16_pnp_suspend,
        .resume = snd_sb16_pnp_resume,
index ab5cebea52e17156f542d5e87006dd490adbdd20..237d964ff8a6bcd49a955ff266f19494d6fa3cec 100644 (file)
@@ -79,7 +79,7 @@ static void snd_sb8_free(struct snd_card *card)
        release_and_free_resource(acard->fm_res);
 }
 
-static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
+static int snd_sb8_match(struct device *pdev, unsigned int dev)
 {
        if (!enable[dev])
                return 0;
@@ -94,7 +94,7 @@ static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
        return 1;
 }
 
-static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
+static int snd_sb8_probe(struct device *pdev, unsigned int dev)
 {
        struct snd_sb *chip;
        struct snd_card *card;
@@ -205,7 +205,7 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
        return err;
 }
 
-static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev)
+static int snd_sb8_remove(struct device *pdev, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
@@ -244,7 +244,7 @@ static int snd_sb8_resume(struct device *dev, unsigned int n)
 static struct isa_driver snd_sb8_driver = {
        .match          = snd_sb8_match,
        .probe          = snd_sb8_probe,
-       .remove         = __devexit_p(snd_sb8_remove),
+       .remove         = snd_sb8_remove,
 #ifdef CONFIG_PM
        .suspend        = snd_sb8_suspend,
        .resume         = snd_sb8_resume,
index d97d0f381817f633364e5041a6b3fb41e1828c9d..5376ebff845ec4a091dfc38349b7d6c337633bad 100644 (file)
@@ -121,7 +121,7 @@ MODULE_PARM_DESC(joystick, "Enable gameport.");
 /*
  * sc6000_irq_to_softcfg - Decode irq number into cfg code.
  */
-static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
+static unsigned char sc6000_irq_to_softcfg(int irq)
 {
        unsigned char val = 0;
 
@@ -150,7 +150,7 @@ static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
 /*
  * sc6000_dma_to_softcfg - Decode dma number into cfg code.
  */
-static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
+static unsigned char sc6000_dma_to_softcfg(int dma)
 {
        unsigned char val = 0;
 
@@ -173,7 +173,7 @@ static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
 /*
  * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code.
  */
-static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
+static unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
 {
        unsigned char val = 0;
 
@@ -242,8 +242,8 @@ static int sc6000_write(char __iomem *vport, int cmd)
        return -EIO;
 }
 
-static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
-                                          char *data, int data_len)
+static int sc6000_dsp_get_answer(char __iomem *vport, int command,
+                                char *data, int data_len)
 {
        int len = 0;
 
@@ -269,7 +269,7 @@ static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
        return len ? len : -EIO;
 }
 
-static int __devinit sc6000_dsp_reset(char __iomem *vport)
+static int sc6000_dsp_reset(char __iomem *vport)
 {
        iowrite8(1, vport + DSP_RESET);
        udelay(10);
@@ -281,7 +281,7 @@ static int __devinit sc6000_dsp_reset(char __iomem *vport)
 }
 
 /* detection and initialization */
-static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
+static int sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
 {
        if (sc6000_write(vport, COMMAND_6C) < 0) {
                snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C);
@@ -345,8 +345,8 @@ static int sc6000_setup_board(char __iomem *vport, int config)
        return 0;
 }
 
-static int __devinit sc6000_init_mss(char __iomem *vport, int config,
-                                    char __iomem *vmss_port, int mss_config)
+static int sc6000_init_mss(char __iomem *vport, int config,
+                          char __iomem *vmss_port, int mss_config)
 {
        if (sc6000_write(vport, DSP_INIT_MSS)) {
                snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n",
@@ -364,9 +364,9 @@ static int __devinit sc6000_init_mss(char __iomem *vport, int config,
        return 0;
 }
 
-static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
-                                          long xport, long xmpu,
-                                          long xmss_port, int joystick)
+static void sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
+                                long xport, long xmpu,
+                                long xmss_port, int joystick)
 {
        cfg[0] = 0;
        cfg[1] = 0;
@@ -386,8 +386,8 @@ static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
        snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]);
 }
 
-static int __devinit sc6000_init_board(char __iomem *vport,
-                                       char __iomem *vmss_port, int dev)
+static int sc6000_init_board(char __iomem *vport,
+                            char __iomem *vmss_port, int dev)
 {
        char answer[15];
        char version[2];
@@ -467,7 +467,7 @@ static int __devinit sc6000_init_board(char __iomem *vport,
        return 0;
 }
 
-static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
+static int snd_sc6000_mixer(struct snd_wss *chip)
 {
        struct snd_card *card = chip->card;
        struct snd_ctl_elem_id id1, id2;
@@ -502,7 +502,7 @@ static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
        return 0;
 }
 
-static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
+static int snd_sc6000_match(struct device *devptr, unsigned int dev)
 {
        if (!enable[dev])
                return 0;
@@ -545,7 +545,7 @@ static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
        return 1;
 }
 
-static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
+static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
 {
        static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
        static int possible_dmas[] = { 1, 3, 0, -1 };
@@ -687,7 +687,7 @@ err_exit:
        return err;
 }
 
-static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
+static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
 {
        struct snd_card *card = dev_get_drvdata(devptr);
        char __iomem **vport = card->private_data;
@@ -706,7 +706,7 @@ static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_sc6000_driver = {
        .match          = snd_sc6000_match,
        .probe          = snd_sc6000_probe,
-       .remove         = __devexit_p(snd_sc6000_remove),
+       .remove         = snd_sc6000_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DRV_NAME,
index 8490f59709bbf5721786bf89da622caac9f8cdc8..42a009720b29c2e89201e923b6160c4f3ed52136 100644 (file)
@@ -683,7 +683,7 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
  * These IRQs are encoded as bit patterns so that they can be
  * written to the control registers.
  */
-static unsigned __devinit get_irq_config(int sscape_type, int irq)
+static unsigned get_irq_config(int sscape_type, int irq)
 {
        static const int valid_irq[] = { 9, 5, 7, 10 };
        static const int old_irq[] = { 9, 7, 5, 15 };
@@ -706,7 +706,7 @@ static unsigned __devinit get_irq_config(int sscape_type, int irq)
  * Perform certain arcane port-checks to see whether there
  * is a SoundScape board lurking behind the given ports.
  */
-static int __devinit detect_sscape(struct soundscape *s, long wss_io)
+static int detect_sscape(struct soundscape *s, long wss_io)
 {
        unsigned long flags;
        unsigned d;
@@ -817,8 +817,8 @@ static int mpu401_open(struct snd_mpu401 *mpu)
 /*
  * Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
  */
-static int __devinit create_mpu401(struct snd_card *card, int devnum,
-                                  unsigned long port, int irq)
+static int create_mpu401(struct snd_card *card, int devnum,
+                        unsigned long port, int irq)
 {
        struct soundscape *sscape = get_card_soundscape(card);
        struct snd_rawmidi *rawmidi;
@@ -845,8 +845,8 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum,
  * try to support at least some of the extra bits by overriding
  * some of the CS4231 callback.
  */
-static int __devinit create_ad1845(struct snd_card *card, unsigned port,
-                                  int irq, int dma1, int dma2)
+static int create_ad1845(struct snd_card *card, unsigned port,
+                        int irq, int dma1, int dma2)
 {
        register struct soundscape *sscape = get_card_soundscape(card);
        struct snd_wss *chip;
@@ -937,7 +937,7 @@ _error:
  * Create an ALSA soundcard entry for the SoundScape, using
  * the given list of port, IRQ and DMA resources.
  */
-static int __devinit create_sscape(int dev, struct snd_card *card)
+static int create_sscape(int dev, struct snd_card *card)
 {
        struct soundscape *sscape = get_card_soundscape(card);
        unsigned dma_cfg;
@@ -1143,7 +1143,7 @@ _release_region:
 }
 
 
-static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
+static int snd_sscape_match(struct device *pdev, unsigned int i)
 {
        /*
         * Make sure we were given ALL of the other parameters.
@@ -1163,7 +1163,7 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
        return 1;
 }
 
-static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
+static int snd_sscape_probe(struct device *pdev, unsigned int dev)
 {
        struct snd_card *card;
        struct soundscape *sscape;
@@ -1197,7 +1197,7 @@ _release_card:
        return ret;
 }
 
-static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
+static int snd_sscape_remove(struct device *devptr, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -1209,7 +1209,7 @@ static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
 static struct isa_driver snd_sscape_driver = {
        .match          = snd_sscape_match,
        .probe          = snd_sscape_probe,
-       .remove         = __devexit_p(snd_sscape_remove),
+       .remove         = snd_sscape_remove,
        /* FIXME: suspend/resume */
        .driver         = {
                .name   = DEV_NAME
@@ -1217,7 +1217,7 @@ static struct isa_driver snd_sscape_driver = {
 };
 
 #ifdef CONFIG_PNP
-static inline int __devinit get_next_autoindex(int i)
+static inline int get_next_autoindex(int i)
 {
        while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT)
                ++i;
@@ -1225,8 +1225,8 @@ static inline int __devinit get_next_autoindex(int i)
 }
 
 
-static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
-                                      const struct pnp_card_device_id *pid)
+static int sscape_pnp_detect(struct pnp_card_link *pcard,
+                            const struct pnp_card_device_id *pid)
 {
        static int idx = 0;
        struct pnp_dev *dev;
@@ -1310,7 +1310,7 @@ _release_card:
        return ret;
 }
 
-static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard)
+static void sscape_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -1321,7 +1321,7 @@ static struct pnp_card_driver sscape_pnpc_driver = {
        .name = "sscape",
        .id_table = sscape_pnpids,
        .probe = sscape_pnp_detect,
-       .remove = __devexit_p(sscape_pnp_remove),
+       .remove = sscape_pnp_remove,
 };
 
 #endif /* CONFIG_PNP */
index e0a73271cb91aff3191d4e32753ac17d91715ca1..fe5dd982bd2384a6e14fa837292f4f381b092352 100644 (file)
@@ -98,7 +98,7 @@ static struct pnp_card_device_id snd_wavefront_pnpids[] = {
 
 MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids);
 
-static int __devinit
+static int
 snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card,
                   const struct pnp_card_device_id *id)
 {
@@ -231,10 +231,9 @@ static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static struct snd_hwdep * __devinit
-snd_wavefront_new_synth (struct snd_card *card,
-                        int hw_dev,
-                        snd_wavefront_card_t *acard)
+static struct snd_hwdep *snd_wavefront_new_synth(struct snd_card *card,
+                                                int hw_dev,
+                                                snd_wavefront_card_t *acard)
 {
        struct snd_hwdep *wavefront_synth;
 
@@ -257,11 +256,10 @@ snd_wavefront_new_synth (struct snd_card *card,
        return wavefront_synth;
 }
 
-static struct snd_hwdep * __devinit
-snd_wavefront_new_fx (struct snd_card *card,
-                     int hw_dev,
-                     snd_wavefront_card_t *acard,
-                     unsigned long port)
+static struct snd_hwdep *snd_wavefront_new_fx(struct snd_card *card,
+                                             int hw_dev,
+                                             snd_wavefront_card_t *acard,
+                                             unsigned long port)
 
 {
        struct snd_hwdep *fx_processor;
@@ -284,12 +282,11 @@ snd_wavefront_new_fx (struct snd_card *card,
 static snd_wavefront_mpu_id internal_id = internal_mpu;
 static snd_wavefront_mpu_id external_id = external_mpu;
 
-static struct snd_rawmidi *__devinit
-snd_wavefront_new_midi (struct snd_card *card,
-                       int midi_dev,
-                       snd_wavefront_card_t *acard,
-                       unsigned long port,
-                       snd_wavefront_mpu_id mpu)
+static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card,
+                                                 int midi_dev,
+                                                 snd_wavefront_card_t *acard,
+                                                 unsigned long port,
+                                                 snd_wavefront_mpu_id mpu)
 
 {
        struct snd_rawmidi *rmidi;
@@ -361,7 +358,7 @@ static int snd_wavefront_card_new(int dev, struct snd_card **cardp)
        return 0;
 }
 
-static int __devinit
+static int
 snd_wavefront_probe (struct snd_card *card, int dev)
 {
        snd_wavefront_card_t *acard = card->private_data;
@@ -541,8 +538,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
        return snd_card_register(card);
 }      
 
-static int __devinit snd_wavefront_isa_match(struct device *pdev,
-                                            unsigned int dev)
+static int snd_wavefront_isa_match(struct device *pdev,
+                                  unsigned int dev)
 {
        if (!enable[dev])
                return 0;
@@ -561,8 +558,8 @@ static int __devinit snd_wavefront_isa_match(struct device *pdev,
        return 1;
 }
 
-static int __devinit snd_wavefront_isa_probe(struct device *pdev,
-                                            unsigned int dev)
+static int snd_wavefront_isa_probe(struct device *pdev,
+                                  unsigned int dev)
 {
        struct snd_card *card;
        int err;
@@ -580,8 +577,8 @@ static int __devinit snd_wavefront_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int __devexit snd_wavefront_isa_remove(struct device *devptr,
-                                             unsigned int dev)
+static int snd_wavefront_isa_remove(struct device *devptr,
+                                   unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
        dev_set_drvdata(devptr, NULL);
@@ -593,7 +590,7 @@ static int __devexit snd_wavefront_isa_remove(struct device *devptr,
 static struct isa_driver snd_wavefront_driver = {
        .match          = snd_wavefront_isa_match,
        .probe          = snd_wavefront_isa_probe,
-       .remove         = __devexit_p(snd_wavefront_isa_remove),
+       .remove         = snd_wavefront_isa_remove,
        /* FIXME: suspend, resume */
        .driver         = {
                .name   = DEV_NAME
@@ -602,8 +599,8 @@ static struct isa_driver snd_wavefront_driver = {
 
 
 #ifdef CONFIG_PNP
-static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
-                                       const struct pnp_card_device_id *pid)
+static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
+                                   const struct pnp_card_device_id *pid)
 {
        static int dev;
        struct snd_card *card;
@@ -637,7 +634,7 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
        return 0;
 }
 
-static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard)
+static void snd_wavefront_pnp_remove(struct pnp_card_link *pcard)
 {
        snd_card_free(pnp_get_card_drvdata(pcard));
        pnp_set_card_drvdata(pcard, NULL);
@@ -648,7 +645,7 @@ static struct pnp_card_driver wavefront_pnpc_driver = {
        .name           = "wavefront",
        .id_table       = snd_wavefront_pnpids,
        .probe          = snd_wavefront_pnp_detect,
-       .remove         = __devexit_p(snd_wavefront_pnp_remove),
+       .remove         = snd_wavefront_pnp_remove,
        /* FIXME: suspend,resume */
 };
 
index e51e0906050b59ff09f25b450d397031ff34d921..b77883c7ee762f5ff86891754f31a536627e3be7 100644 (file)
@@ -240,7 +240,7 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
    that outputs it.
 */
 
-int __devinit
+int
 snd_wavefront_fx_start (snd_wavefront_t *dev)
 {
        unsigned int i;
index 65329f3abc302f91b76c2f139e87e1862cfa6cbd..7dc9916822977d1eb739fba86a57caeae7a87b0e 100644 (file)
@@ -481,7 +481,7 @@ snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
        spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
 }
 
-int __devinit
+int
 snd_wavefront_midi_start (snd_wavefront_card_t *card)
 
 {
index b1bf8d4e6494f4561ea2e11a407f4663f5882f98..a2f87f9488ee163e336350c3c1b7cdebb48dca24 100644 (file)
@@ -1739,7 +1739,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
 7 Unused
 */
 
-static int __devinit
+static int
 snd_wavefront_interrupt_bits (int irq)
 
 {
@@ -1767,7 +1767,7 @@ snd_wavefront_interrupt_bits (int irq)
        return bits;
 }
 
-static void __devinit
+static void
 wavefront_should_cause_interrupt (snd_wavefront_t *dev, 
                                  int val, int port, unsigned long timeout)
 
@@ -1786,7 +1786,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
        }
 }
 
-static int __devinit
+static int
 wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
 
 {
@@ -1937,7 +1937,7 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
        return (1);
 }
 
-static int __devinit
+static int
 wavefront_download_firmware (snd_wavefront_t *dev, char *path)
 
 {
@@ -2010,7 +2010,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
 }
 
 
-static int __devinit
+static int
 wavefront_do_reset (snd_wavefront_t *dev)
 
 {
@@ -2099,7 +2099,7 @@ wavefront_do_reset (snd_wavefront_t *dev)
        return 1;
 }
 
-int __devinit
+int
 snd_wavefront_start (snd_wavefront_t *dev)
 
 {
@@ -2141,7 +2141,7 @@ snd_wavefront_start (snd_wavefront_t *dev)
        return (0);
 }
 
-int __devinit
+int
 snd_wavefront_detect (snd_wavefront_card_t *card)
 
 {
index 3f3ec0bec0671675de52887586f9f672f06d4431..224f54be15a61002ef17630acff78a191a501039 100644 (file)
@@ -439,7 +439,7 @@ static struct snd_pcm_ops snd_card_au1000_capture_ops = {
        .pointer                = snd_au1000_pointer,
 };
 
-static int __devinit
+static int
 snd_au1000_pcm_new(struct snd_au1000 *au1000)
 {
        struct snd_pcm *pcm;
@@ -552,7 +552,7 @@ get the interrupt driven case to work efficiently */
        spin_unlock(&au1000->ac97_lock);
 }
 
-static int __devinit
+static int
 snd_au1000_ac97_new(struct snd_au1000 *au1000)
 {
        int err;
index 5f88d1f09ffeef01f3fd9d0cc1a5746972ec1e90..7420c59444ab41c442cb774be05f869019c5fc86 100644 (file)
@@ -260,7 +260,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
        return old != new;
 }
 
-static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
+static struct snd_kcontrol_new hal2_ctrl_headphone = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Headphone Playback Volume",
        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -270,7 +270,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
        .put            = hal2_gain_put,
 };
 
-static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
+static struct snd_kcontrol_new hal2_ctrl_mic = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Mic Capture Volume",
        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -280,7 +280,7 @@ static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
        .put            = hal2_gain_put,
 };
 
-static int __devinit hal2_mixer_create(struct snd_hal2 *hal2)
+static int hal2_mixer_create(struct snd_hal2 *hal2)
 {
        int err;
 
@@ -733,7 +733,7 @@ static struct snd_pcm_ops hal2_capture_ops = {
        .ack =         hal2_capture_ack,
 };
 
-static int __devinit hal2_pcm_create(struct snd_hal2 *hal2)
+static int hal2_pcm_create(struct snd_hal2 *hal2)
 {
        struct snd_pcm *pcm;
        int err;
@@ -874,7 +874,7 @@ static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip)
        return 0;
 }
 
-static int __devinit hal2_probe(struct platform_device *pdev)
+static int hal2_probe(struct platform_device *pdev)
 {
        struct snd_card *card;
        struct snd_hal2 *chip;
@@ -917,7 +917,7 @@ static int __devinit hal2_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit hal2_remove(struct platform_device *pdev)
+static int hal2_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -928,7 +928,7 @@ static int __devexit hal2_remove(struct platform_device *pdev)
 
 static struct platform_driver hal2_driver = {
        .probe  = hal2_probe,
-       .remove = __devexit_p(hal2_remove),
+       .remove = hal2_remove,
        .driver = {
                .name   = "sgihal2",
                .owner  = THIS_MODULE,
index ceaa593ea4ef632d9f8ad4a6333ded19c0602684..01a03efdc8b042059668e24274ac25799af63029 100644 (file)
@@ -237,7 +237,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
 }
 
 /* dac1/pcm0 mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "PCM Playback Volume",
        .index          = 0,
@@ -249,7 +249,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
 };
 
 /* dac2/pcm1 mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "PCM Playback Volume",
        .index          = 1,
@@ -261,7 +261,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
 };
 
 /* record level mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Capture Volume",
        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -272,7 +272,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
 };
 
 /* record level source control */
-static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Capture Source",
        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -282,7 +282,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
 };
 
 /* line mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_line = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Line Playback Volume",
        .index          = 0,
@@ -294,7 +294,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
 };
 
 /* cd mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Line Playback Volume",
        .index          = 1,
@@ -306,7 +306,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
 };
 
 /* mic mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
+static struct snd_kcontrol_new sgio2audio_ctrl_mic = {
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name           = "Mic Playback Volume",
        .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -317,7 +317,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
 };
 
 
-static int __devinit snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
+static int snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
 {
        int err;
 
@@ -726,7 +726,7 @@ static struct snd_pcm_ops snd_sgio2audio_capture_ops = {
  */
 
 /* create a pcm device */
-static int __devinit snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
+static int snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -834,8 +834,8 @@ static struct snd_device_ops ops = {
        .dev_free = snd_sgio2audio_dev_free,
 };
 
-static int __devinit snd_sgio2audio_create(struct snd_card *card,
-                                          struct snd_sgio2audio **rchip)
+static int snd_sgio2audio_create(struct snd_card *card,
+                                struct snd_sgio2audio **rchip)
 {
        struct snd_sgio2audio *chip;
        int i, err;
@@ -914,7 +914,7 @@ static int __devinit snd_sgio2audio_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
+static int snd_sgio2audio_probe(struct platform_device *pdev)
 {
        struct snd_card *card;
        struct snd_sgio2audio *chip;
@@ -958,7 +958,7 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
+static int snd_sgio2audio_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
@@ -969,7 +969,7 @@ static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
 
 static struct platform_driver sgio2audio_driver = {
        .probe  = snd_sgio2audio_probe,
-       .remove = __devexit_p(snd_sgio2audio_remove),
+       .remove = snd_sgio2audio_remove,
        .driver = {
                .name   = "sgio2audio",
                .owner  = THIS_MODULE,
index 98d23bdcaf21bd0208e82bc82d53ee569b56600e..4918b7145b736ef16982bd72131f2b773c23dd79 100644 (file)
@@ -2864,7 +2864,7 @@ static struct {
        {NULL}
 };
 
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
        {       ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
         {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
index 52d06a334e8f1a20ca43da9cc7dd8a347680b646..2a44cc10645924820972e8a1cf90e00ac5881ab7 100644 (file)
@@ -43,7 +43,7 @@
  *     not real hardware.
  */
 
-static u8 __devinit mixer_read(unsigned long io, u8 reg)
+static u8 mixer_read(unsigned long io, u8 reg)
 {
        outb(reg, io + 4);
        udelay(20);
@@ -52,7 +52,7 @@ static u8 __devinit mixer_read(unsigned long io, u8 reg)
        return reg;
 }
 
-static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct address_info *hw_config;
        unsigned long base;
@@ -183,7 +183,7 @@ err_out_free:
        return 1;
 }
 
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
 {
        struct address_info *hw_config = pci_get_drvdata(pdev);
        sb_dsp_unload(hw_config, 0);
@@ -210,7 +210,7 @@ static struct pci_driver kahlua_driver = {
        .name           = "kahlua",
        .id_table       = id_tbl,
        .probe          = probe_one,
-       .remove         = __devexit_p(remove_one),
+       .remove         = remove_one,
 };
 
 
@@ -220,7 +220,7 @@ static int __init kahlua_init_module(void)
        return pci_register_driver(&kahlua_driver);
 }
 
-static void __devexit kahlua_cleanup_module(void)
+static void kahlua_cleanup_module(void)
 {
        pci_unregister_driver(&kahlua_driver);
 }
index b2b3c014221afd4d6b2079c6a3627f64fcfe9480..048439a16000ef08a8ead209285240224ac2683b 100644 (file)
@@ -442,7 +442,7 @@ static int sb201_audio_set_speed(int dev, int speed)
 {
        sb_devc *devc = audio_devs[dev]->devc;
        int tmp;
-       int s = speed * devc->channels;
+       int s;
 
        if (speed > 0)
        {
@@ -452,6 +452,7 @@ static int sb201_audio_set_speed(int dev, int speed)
                        speed = 44100;
                if (devc->opened & OPEN_READ && speed > 15000)
                        speed = 15000;
+               s = speed * devc->channels;
                devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;
                tmp = 256 - devc->tconst;
                speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
index f47f9e226b0823c35970fcbed96096e18042d15f..0e66ba48d453fd9e81e431623320d8e86f3ad758 100644 (file)
@@ -856,7 +856,7 @@ static struct snd_kcontrol_new snd_harmony_controls[] = {
                       HARMONY_GAIN_HE_SHIFT, 1, 0),
 };
 
-static void __devinit
+static void
 snd_harmony_mixer_reset(struct snd_harmony *h)
 {
        harmony_mute(h);
@@ -865,7 +865,7 @@ snd_harmony_mixer_reset(struct snd_harmony *h)
        harmony_unmute(h);
 }
 
-static int __devinit
+static int
 snd_harmony_mixer_init(struct snd_harmony *h)
 {
        struct snd_card *card;
@@ -915,7 +915,7 @@ snd_harmony_dev_free(struct snd_device *dev)
        return snd_harmony_free(h);
 }
 
-static int __devinit
+static int
 snd_harmony_create(struct snd_card *card, 
                   struct parisc_device *padev, 
                   struct snd_harmony **rchip)
@@ -972,7 +972,7 @@ free_and_ret:
        return err;
 }
 
-static int __devinit
+static int
 snd_harmony_probe(struct parisc_device *padev)
 {
        int err;
@@ -1012,7 +1012,7 @@ free_and_ret:
        return err;
 }
 
-static int __devexit
+static int
 snd_harmony_remove(struct parisc_device *padev)
 {
        snd_card_free(parisc_get_drvdata(padev));
@@ -1024,7 +1024,7 @@ static struct parisc_driver snd_harmony_driver = {
        .name = "harmony",
        .id_table = snd_harmony_devtable,
        .probe = snd_harmony_probe,
-       .remove = __devexit_p(snd_harmony_remove),
+       .remove = snd_harmony_remove,
 };
 
 static int __init 
index f99fa251228623a161c6bcaed0d2622f5bf132bf..947cfb4eb30cbd6ed7722bcfa7037bd0f2735f05 100644 (file)
@@ -572,6 +572,7 @@ source "sound/pci/hda/Kconfig"
 
 config SND_HDSP
        tristate "RME Hammerfall DSP Audio"
+       select FW_LOADER
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
@@ -630,7 +631,7 @@ config SND_ICE1724
          AudioTrak Prodigy 192, 7.1 (HIFI/LT/XT), HD2; Hercules
          Fortissimo IV; ESI Juli@; Pontis MS300; EGO-SYS WaveTerminal
          192M; Albatron K8X800 Pro II; Chaintech ZNF3-150/250, 9CJS,
-         AV-710; Shuttle SN25P.
+         AV-710; Shuttle SN25P; Philips PSC724 Ultimate Edge.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-ice1724.
@@ -707,6 +708,7 @@ config SND_MAESTRO3_INPUT
 
 config SND_MIXART
        tristate "Digigram miXart"
+       select FW_LOADER
        select SND_HWDEP
        select SND_PCM
        help
@@ -727,6 +729,7 @@ config SND_NM256
 
 config SND_PCXHR
        tristate "Digigram PCXHR"
+       select FW_LOADER
        select SND_PCM
        select SND_HWDEP
        help
index e672ff4df2da15969f29a3882e541bd3ae441b7c..ad8a31173939d80a6738656579a2a88bd793ac86 100644 (file)
@@ -624,7 +624,7 @@ snd_ad1889_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit
+static int
 snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm)
 {
        int err;
@@ -747,7 +747,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
        snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
 }
 
-static void __devinit
+static void
 snd_ad1889_proc_init(struct snd_ad1889 *chip)
 {
        struct snd_info_entry *entry;
@@ -767,7 +767,7 @@ static struct ac97_quirk ac97_quirks[] = {
        { } /* terminator */
 };
 
-static void __devinit
+static void
 snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
 {
        u16 reg;
@@ -805,7 +805,7 @@ snd_ad1889_ac97_free(struct snd_ac97 *ac97)
        chip->ac97 = NULL;
 }
 
-static int __devinit
+static int
 snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
 {
        int err;
@@ -878,7 +878,7 @@ snd_ad1889_dev_free(struct snd_device *device)
        return snd_ad1889_free(chip);
 }
 
-static int __devinit
+static int
 snd_ad1889_init(struct snd_ad1889 *chip) 
 {
        ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
@@ -892,7 +892,7 @@ snd_ad1889_init(struct snd_ad1889 *chip)
        return 0;
 }
 
-static int __devinit
+static int
 snd_ad1889_create(struct snd_card *card,
                  struct pci_dev *pci,
                  struct snd_ad1889 **rchip)
@@ -978,7 +978,7 @@ free_and_ret:
        return err;
 }
 
-static int __devinit
+static int
 snd_ad1889_probe(struct pci_dev *pci,
                 const struct pci_device_id *pci_id)
 {
@@ -1042,7 +1042,7 @@ free_and_ret:
        return err;
 }
 
-static void __devexit
+static void
 snd_ad1889_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
@@ -1059,7 +1059,7 @@ static struct pci_driver ad1889_pci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ad1889_ids,
        .probe = snd_ad1889_probe,
-       .remove = __devexit_p(snd_ad1889_remove),
+       .remove = snd_ad1889_remove,
 };
 
 module_pci_driver(ad1889_pci_driver);
index cadf7b962e3001956db1f9035a1da0e4d7dd228b..3bf0dc53360ab5fd2a550477feb05a4584df1046 100644 (file)
@@ -274,7 +274,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
 
-static struct snd_kcontrol_new snd_ak4531_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ak4531_controls[] = {
 
 AK4531_DOUBLE_TLV("Master Playback Switch", 0,
                  AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
@@ -383,9 +383,9 @@ static u8 snd_ak4531_initial_map[0x19 + 1] = {
        0x01            /* 19: Mic Amp Setup */
 };
 
-int __devinit snd_ak4531_mixer(struct snd_card *card,
-                              struct snd_ak4531 *_ak4531,
-                              struct snd_ak4531 **rak4531)
+int snd_ak4531_mixer(struct snd_card *card,
+                    struct snd_ak4531 *_ak4531,
+                    struct snd_ak4531 **rak4531)
 {
        unsigned int idx;
        int err;
@@ -483,7 +483,7 @@ static void snd_ak4531_proc_read(struct snd_info_entry *entry,
                    ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
 }
 
-static void __devinit
+static void
 snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
 {
        struct snd_info_entry *entry;
index c7e3c533316eeb72e0873353478354caa7594aab..136a393b70abc98dcbe5f0fee9d9c0247b51b375 100644 (file)
@@ -1678,8 +1678,8 @@ static void snd_ali_pcm_free(struct snd_pcm *pcm)
 }
 
 
-static int __devinit snd_ali_pcm(struct snd_ali * codec, int device,
-                                struct ali_pcm_description *desc)
+static int snd_ali_pcm(struct snd_ali *codec, int device,
+                      struct ali_pcm_description *desc)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1727,7 +1727,7 @@ static struct ali_pcm_description ali_pcms[] = {
        }
 };
 
-static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
+static int snd_ali_build_pcms(struct snd_ali *codec)
 {
        int i, err;
        for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) {
@@ -1832,7 +1832,7 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {
        /* spdif aplayback switch */
        /* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
        ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
@@ -1842,7 +1842,7 @@ static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
        ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
 };
 
-static int __devinit snd_ali_mixer(struct snd_ali * codec)
+static int snd_ali_mixer(struct snd_ali *codec)
 {
        struct snd_ac97_template ac97;
        unsigned int idx;
@@ -2079,14 +2079,14 @@ static void snd_ali_proc_read(struct snd_info_entry *entry,
                snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
 }
 
-static void __devinit snd_ali_proc_init(struct snd_ali *codec)
+static void snd_ali_proc_init(struct snd_ali *codec)
 {
        struct snd_info_entry *entry;
        if (!snd_card_proc_new(codec->card, "ali5451", &entry))
                snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
 }
 
-static int __devinit snd_ali_resources(struct snd_ali *codec)
+static int snd_ali_resources(struct snd_ali *codec)
 {
        int err;
 
@@ -2112,11 +2112,11 @@ static int snd_ali_dev_free(struct snd_device *device)
        return 0;
 }
 
-static int __devinit snd_ali_create(struct snd_card *card,
-                                   struct pci_dev *pci,
-                                   int pcm_streams,
-                                   int spdif_support,
-                                   struct snd_ali ** r_ali)
+static int snd_ali_create(struct snd_card *card,
+                         struct pci_dev *pci,
+                         int pcm_streams,
+                         int spdif_support,
+                         struct snd_ali **r_ali)
 {
        struct snd_ali *codec;
        int i, err;
@@ -2246,8 +2246,8 @@ static int __devinit snd_ali_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_ali_probe(struct pci_dev *pci,
-                                  const struct pci_device_id *pci_id)
+static int snd_ali_probe(struct pci_dev *pci,
+                        const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct snd_ali *codec;
@@ -2295,7 +2295,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_ali_remove(struct pci_dev *pci)
+static void snd_ali_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2305,7 +2305,7 @@ static struct pci_driver ali5451_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ali_ids,
        .probe = snd_ali_probe,
-       .remove = __devexit_p(snd_ali_remove),
+       .remove = snd_ali_remove,
        .driver = {
                .pm = ALI_PM_OPS,
        },
index 5af3cb6b0c18d36345aadfefee3d509404bbba80..864c4310366b4da41ad891ce829d0e2fc0a10300 100644 (file)
@@ -278,7 +278,7 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void __devexit snd_als300_remove(struct pci_dev *pci)
+static void snd_als300_remove(struct pci_dev *pci)
 {
        snd_als300_dbgcallenter();
        snd_card_free(pci_get_drvdata(pci));
@@ -622,7 +622,7 @@ static struct snd_pcm_ops snd_als300_capture_ops = {
        .pointer =      snd_als300_pointer,
 };
 
-static int __devinit snd_als300_new_pcm(struct snd_als300 *chip)
+static int snd_als300_new_pcm(struct snd_als300 *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -683,9 +683,9 @@ static void snd_als300_init(struct snd_als300 *chip)
        snd_als300_dbgcallleave();
 }
 
-static int __devinit snd_als300_create(struct snd_card *card,
-                                      struct pci_dev *pci, int chip_type,
-                                      struct snd_als300 **rchip)
+static int snd_als300_create(struct snd_card *card,
+                            struct pci_dev *pci, int chip_type,
+                            struct snd_als300 **rchip)
 {
        struct snd_als300 *chip;
        void *irq_handler;
@@ -815,7 +815,7 @@ static SIMPLE_DEV_PM_OPS(snd_als300_pm, snd_als300_suspend, snd_als300_resume);
 #define SND_ALS300_PM_OPS      NULL
 #endif
 
-static int __devinit snd_als300_probe(struct pci_dev *pci,
+static int snd_als300_probe(struct pci_dev *pci,
                              const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -867,7 +867,7 @@ static struct pci_driver als300_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_als300_ids,
        .probe = snd_als300_probe,
-       .remove = __devexit_p(snd_als300_remove),
+       .remove = snd_als300_remove,
        .driver = {
                .pm = SND_ALS300_PM_OPS,
        },
index feb2a143683079df95f47384f0b52c9621a0a03b..61efda2a4d949f56d4ace3b82daf1fe37dc4660b 100644 (file)
@@ -694,7 +694,7 @@ static struct snd_pcm_ops snd_als4000_capture_ops = {
        .pointer =      snd_als4000_capture_pointer
 };
 
-static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device)
+static int snd_als4000_pcm(struct snd_sb *chip, int device)
 {
        struct snd_pcm *pcm;
        int err;
@@ -770,7 +770,7 @@ static void snd_als4000_configure(struct snd_sb *chip)
 }
 
 #ifdef SUPPORT_JOYSTICK
-static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
+static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
 {
        struct gameport *gp;
        struct resource *r;
@@ -847,8 +847,8 @@ static void snd_card_als4000_free( struct snd_card *card )
        pci_disable_device(acard->pci);
 }
 
-static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
-                                         const struct pci_device_id *pci_id)
+static int snd_card_als4000_probe(struct pci_dev *pci,
+                                 const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -981,7 +981,7 @@ out:
        return err;
 }
 
-static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
+static void snd_card_als4000_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1046,7 +1046,7 @@ static struct pci_driver als4000_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_als4000_ids,
        .probe = snd_card_als4000_probe,
-       .remove = __devexit_p(snd_card_als4000_remove),
+       .remove = snd_card_als4000_remove,
        .driver = {
                .pm = SND_ALS4000_PM_OPS,
        },
index eedc017c1cd8f7f65f537ddca7c445c6e3b14111..3536b076b529ab8c25edf1292a62e713e841b800 100644 (file)
@@ -1235,8 +1235,7 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
        .pointer = snd_card_asihpi_capture_pointer,
 };
 
-static int __devinit snd_card_asihpi_pcm_new(
-               struct snd_card_asihpi *asihpi, int device)
+static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1497,8 +1496,8 @@ static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
+                                struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -1593,8 +1592,8 @@ static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0);
 
-static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
+                               struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -1715,8 +1714,8 @@ static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
+                                   struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -1753,8 +1752,8 @@ static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
+                                   struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -1996,8 +1995,8 @@ static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,
 }
 
 /* Tuner control group initializer  */
-static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
+                               struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -2100,8 +2099,8 @@ static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl, int subidx)
+static int snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
+                               struct hpi_control *hpi_ctl, int subidx)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -2214,8 +2213,8 @@ static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static int  __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int  snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
+                              struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -2303,8 +2302,8 @@ static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
+                               struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -2471,8 +2470,8 @@ static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
-                                       struct hpi_control *hpi_ctl)
+static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
+                                     struct hpi_control *hpi_ctl)
 {
        struct snd_card *card = asihpi->card;
        struct snd_kcontrol_new snd_control;
@@ -2548,7 +2547,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
    Mixer
  ------------------------------------------------------------*/
 
-static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
+static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 {
        struct snd_card *card = asihpi->card;
        unsigned int idx = 0;
@@ -2722,7 +2721,7 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
        }
 }
 
-static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
+static void snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
 {
        struct snd_info_entry *entry;
 
@@ -2764,8 +2763,8 @@ static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,
 /* results in /dev/snd/hwC#D0 file for each card with index #
    also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
 */
-static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
-       int device, struct snd_hwdep **rhwdep)
+static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
+                             int device, struct snd_hwdep **rhwdep)
 {
        struct snd_hwdep *hw;
        int err;
@@ -2789,8 +2788,8 @@ static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
 /*------------------------------------------------------------
    CARD
  ------------------------------------------------------------*/
-static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
-                                      const struct pci_device_id *pci_id)
+static int snd_asihpi_probe(struct pci_dev *pci_dev,
+                           const struct pci_device_id *pci_id)
 {
        int err;
        struct hpi_adapter *hpi;
@@ -2944,7 +2943,7 @@ __nodev:
 
 }
 
-static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
+static void snd_asihpi_remove(struct pci_dev *pci_dev)
 {
        struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
        snd_card_free(hpi->snd_card);
@@ -2967,7 +2966,7 @@ static struct pci_driver driver = {
        .name = KBUILD_MODNAME,
        .id_table = asihpi_pci_tbl,
        .probe = snd_asihpi_probe,
-       .remove = __devexit_p(snd_asihpi_remove),
+       .remove = snd_asihpi_remove,
 #ifdef CONFIG_PM_SLEEP
 /*     .suspend = snd_asihpi_suspend,
        .resume = snd_asihpi_resume, */
index 456a758f04f6112ee7c75bf2a9c842cc711b70c3..ac9163770013a8adeab493ff4585f70899afd6c0 100644 (file)
@@ -49,14 +49,12 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
        err = request_firmware(&firmware, fw_name, &dev->dev);
 
        if (err || !firmware) {
-               dev_printk(KERN_ERR, &dev->dev,
-                       "%d, request_firmware failed for  %s\n", err,
-                       fw_name);
+               dev_err(&dev->dev, "%d, request_firmware failed for %s\n",
+                       err, fw_name);
                goto error1;
        }
        if (firmware->size < sizeof(header)) {
-               dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n",
-                       fw_name);
+               dev_err(&dev->dev, "Header size too small %s\n", fw_name);
                goto error2;
        }
        memcpy(&header, firmware->data, sizeof(header));
@@ -64,7 +62,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
        if ((header.type != 0x45444F43) ||      /* "CODE" */
                (header.adapter != adapter)
                || (header.size != firmware->size)) {
-               dev_printk(KERN_ERR, &dev->dev,
+               dev_err(&dev->dev,
                        "Invalid firmware header size %d != file %zd\n",
                        header.size, firmware->size);
                goto error2;
@@ -72,17 +70,15 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
 
        if ((header.version >> 9) != (HPI_VER >> 9)) {
                /* Consider even and subsequent odd minor versions to be compatible */
-               dev_printk(KERN_ERR, &dev->dev,
-                       "Incompatible firmware version "
-                       "DSP image %X != Driver %X\n", header.version,
-                       HPI_VER);
+               dev_err(&dev->dev, "Incompatible firmware version DSP image %X != Driver %X\n",
+                       header.version, HPI_VER);
                goto error2;
        }
 
        if (header.version != HPI_VER) {
-               dev_printk(KERN_INFO, &dev->dev,
-                       "Firmware: release version mismatch  DSP image %X != Driver %X\n",
-                       header.version, HPI_VER);
+               dev_info(&dev->dev,
+                        "Firmware: release version mismatch  DSP image %X != Driver %X\n",
+                        header.version, HPI_VER);
        }
 
        HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
index 60915620556289dd4701ea6434b797e485d1f7b4..ef5019fe51930a7cedda5bc32949633d950dd878 100644 (file)
@@ -307,8 +307,8 @@ out:
        return err;
 }
 
-int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
-       const struct pci_device_id *pci_id)
+int asihpi_adapter_probe(struct pci_dev *pci_dev,
+                        const struct pci_device_id *pci_id)
 {
        int idx, nm;
        int adapter_index;
@@ -326,7 +326,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
                pci_dev->subsystem_device, pci_dev->devfn);
 
        if (pci_enable_device(pci_dev) < 0) {
-               dev_printk(KERN_ERR, &pci_dev->dev,
+               dev_err(&pci_dev->dev,
                        "pci_enable_device failed, disabling device\n");
                return -EIO;
        }
@@ -398,9 +398,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
        mutex_init(&adapters[adapter_index].mutex);
        pci_set_drvdata(pci_dev, &adapters[adapter_index]);
 
-       dev_printk(KERN_INFO, &pci_dev->dev,
-               "probe succeeded for ASI%04X HPI index %d\n",
-               adapter.adapter->type, adapter_index);
+       dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n",
+                adapter.adapter->type, adapter_index);
 
        return 0;
 
@@ -421,7 +420,7 @@ err:
        return -ENODEV;
 }
 
-void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
+void asihpi_adapter_remove(struct pci_dev *pci_dev)
 {
        int idx;
        struct hpi_message hm;
@@ -448,11 +447,11 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
 
        pci_set_drvdata(pci_dev, NULL);
        if (1)
-               dev_printk(KERN_INFO, &pci_dev->dev,
-                       "remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n",
-                       pci_dev->vendor, pci_dev->device,
-                       pci_dev->subsystem_vendor, pci_dev->subsystem_device,
-                       pci_dev->devfn, pa->adapter->index);
+               dev_info(&pci_dev->dev,
+                        "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n",
+                        pci_dev->vendor, pci_dev->device,
+                        pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+                        pci_dev->devfn, pa->adapter->index);
 
        memset(pa, 0, sizeof(*pa));
 }
index 2614aff672e2c8ccea387a96bbe7e97604b2ebb4..0d767e10ac48f07a9cb03e15995f3a7fcf85223f 100644 (file)
@@ -19,9 +19,9 @@
 Linux HPI ioctl, and shared module init functions
 *******************************************************************************/
 
-int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
-       const struct pci_device_id *pci_id);
-void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev);
+int asihpi_adapter_probe(struct pci_dev *pci_dev,
+                        const struct pci_device_id *pci_id);
+void asihpi_adapter_remove(struct pci_dev *pci_dev);
 void __init asihpi_init(void);
 void __exit asihpi_exit(void);
 
index 368df8b0853e218ca48b92553ccd653d8b406195..a67743183aaf2b77a6aeaae5a9b8e5089e0672dc 100644 (file)
@@ -296,7 +296,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = {
 
 MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
 
-static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
+static struct snd_pci_quirk atiixp_quirks[] = {
        SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0),
        SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
        { } /* terminator */
@@ -561,7 +561,7 @@ static int snd_atiixp_aclink_down(struct atiixp *chip)
             ATI_REG_ISR_CODEC2_NOT_READY)
 #define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
 
-static int __devinit ac97_probing_bugs(struct pci_dev *pci)
+static int ac97_probing_bugs(struct pci_dev *pci)
 {
        const struct snd_pci_quirk *q;
 
@@ -575,7 +575,7 @@ static int __devinit ac97_probing_bugs(struct pci_dev *pci)
        return -1;
 }
 
-static int __devinit snd_atiixp_codec_detect(struct atiixp *chip)
+static int snd_atiixp_codec_detect(struct atiixp *chip)
 {
        int timeout;
 
@@ -1183,7 +1183,7 @@ static struct snd_pcm_ops snd_atiixp_spdif_ops = {
        .pointer =      snd_atiixp_pcm_pointer,
 };
 
-static struct ac97_pcm atiixp_pcm_defs[] __devinitdata = {
+static struct ac97_pcm atiixp_pcm_defs[] = {
        /* front PCM */
        {
                .exclusive = 1,
@@ -1247,7 +1247,7 @@ static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = {
 };
        
 
-static int __devinit snd_atiixp_pcm_new(struct atiixp *chip)
+static int snd_atiixp_pcm_new(struct atiixp *chip)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_chmap *chmap;
@@ -1390,7 +1390,7 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
  * ac97 mixer section
  */
 
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
+static struct ac97_quirk ac97_quirks[] = {
        {
                .subvendor = 0x103c,
                .subdevice = 0x006b,
@@ -1412,8 +1412,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
        { } /* terminator */
 };
 
-static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
-                                         const char *quirk_override)
+static int snd_atiixp_mixer_new(struct atiixp *chip, int clock,
+                               const char *quirk_override)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
@@ -1560,7 +1560,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
 }
 
-static void __devinit snd_atiixp_proc_init(struct atiixp *chip)
+static void snd_atiixp_proc_init(struct atiixp *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1602,9 +1602,9 @@ static int snd_atiixp_dev_free(struct snd_device *device)
 /*
  * constructor for chip instance
  */
-static int __devinit snd_atiixp_create(struct snd_card *card,
-                                     struct pci_dev *pci,
-                                     struct atiixp **r_chip)
+static int snd_atiixp_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            struct atiixp **r_chip)
 {
        static struct snd_device_ops ops = {
                .dev_free =     snd_atiixp_dev_free,
@@ -1661,8 +1661,8 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
 }
 
 
-static int __devinit snd_atiixp_probe(struct pci_dev *pci,
-                                    const struct pci_device_id *pci_id)
+static int snd_atiixp_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct atiixp *chip;
@@ -1710,7 +1710,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_atiixp_remove(struct pci_dev *pci)
+static void snd_atiixp_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1720,7 +1720,7 @@ static struct pci_driver atiixp_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_atiixp_ids,
        .probe = snd_atiixp_probe,
-       .remove = __devexit_p(snd_atiixp_remove),
+       .remove = snd_atiixp_remove,
        .driver = {
                .pm = SND_ATIIXP_PM_OPS,
        },
index 6fc03d9f2cff451c2b3db77a525c64cd984c6b92..d0bec7ba3b0d8f3eb610807525e071ed53c4e220 100644 (file)
@@ -988,7 +988,7 @@ static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
        .flush_dma = atiixp_in_flush_dma,
 };
 
-static int __devinit snd_atiixp_pcm_new(struct atiixp_modem *chip)
+static int snd_atiixp_pcm_new(struct atiixp_modem *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1061,7 +1061,7 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
  * ac97 mixer section
  */
 
-static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
+static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
@@ -1186,7 +1186,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
 }
 
-static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip)
+static void snd_atiixp_proc_init(struct atiixp_modem *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1228,9 +1228,9 @@ static int snd_atiixp_dev_free(struct snd_device *device)
 /*
  * constructor for chip instance
  */
-static int __devinit snd_atiixp_create(struct snd_card *card,
-                                      struct pci_dev *pci,
-                                      struct atiixp_modem **r_chip)
+static int snd_atiixp_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            struct atiixp_modem **r_chip)
 {
        static struct snd_device_ops ops = {
                .dev_free =     snd_atiixp_dev_free,
@@ -1287,8 +1287,8 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
 }
 
 
-static int __devinit snd_atiixp_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_atiixp_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct atiixp_modem *chip;
@@ -1331,7 +1331,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_atiixp_remove(struct pci_dev *pci)
+static void snd_atiixp_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1341,7 +1341,7 @@ static struct pci_driver atiixp_modem_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_atiixp_ids,
        .probe = snd_atiixp_probe,
-       .remove = __devexit_p(snd_atiixp_remove),
+       .remove = snd_atiixp_remove,
        .driver = {
                .pm = SND_ATIIXP_PM_OPS,
        },
index ffc376f9f4e46f03d61aa808c48423d93e70748e..b157e1fadd8fb3b014575cefe8e3f317bc3747f3 100644 (file)
@@ -78,7 +78,7 @@ static void vortex_fix_agp_bridge(struct pci_dev *via)
        }
 }
 
-static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
+static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
 {
        struct pci_dev *via = NULL;
 
@@ -137,7 +137,7 @@ static int snd_vortex_dev_free(struct snd_device *device)
 
 // chip-specific constructor
 // (see "Management of Cards and Components")
-static int __devinit
+static int
 snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
 {
        vortex_t *chip;
@@ -234,7 +234,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
 }
 
 // constructor -- see "Constructor" sub-section
-static int __devinit
+static int
 snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -368,7 +368,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 }
 
 // destructor -- see "Destructor" sub-section
-static void __devexit snd_vortex_remove(struct pci_dev *pci)
+static void snd_vortex_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -379,7 +379,7 @@ static struct pci_driver vortex_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vortex_ids,
        .probe = snd_vortex_probe,
-       .remove = __devexit_p(snd_vortex_remove),
+       .remove = snd_vortex_remove,
 };
 
 module_pci_driver(vortex_driver);
index 9ae8b3b17651d84bfaed89c015da17e3290640db..aad831acbb170f282e1287863037ff81095b14d2 100644 (file)
@@ -594,7 +594,7 @@ static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode)
 static int vortex_a3d_register_controls(vortex_t * vortex);
 static void vortex_a3d_unregister_controls(vortex_t * vortex);
 /* A3D base support init/shudown */
-static void __devinit vortex_Vort3D_enable(vortex_t * v)
+static void vortex_Vort3D_enable(vortex_t *v)
 {
        int i;
 
@@ -845,7 +845,7 @@ snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_a3d_kcontrol = {
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "Playback PCM advanced processing",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -855,7 +855,7 @@ static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
 };
 
 /* Control (un)registration. */
-static int __devinit vortex_a3d_register_controls(vortex_t * vortex)
+static int vortex_a3d_register_controls(vortex_t *vortex)
 {
        struct snd_kcontrol *kcontrol;
        int err, i;
index 525f881f04096bd25cec390d0a2a26443a93aa0c..ae59dbaa53d919dcdc12de63f24cd1cddbebe3d9 100644 (file)
@@ -2461,7 +2461,12 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
 #ifndef CHIP_AU8810
                for (i = 0; i < NR_WT; i++) {
                        if (vortex->dma_wt[i].fifo_status == FIFO_START) {
-                               if (vortex_wtdma_bufshift(vortex, i)) ;
+                               /* FIXME: we ignore the return value from
+                                * vortex_wtdma_bufshift() below as the delta
+                                * calculation seems not working for wavetable
+                                * by some reason
+                                */
+                               vortex_wtdma_bufshift(vortex, i);
                                spin_unlock(&vortex->lock);
                                snd_pcm_period_elapsed(vortex->dma_wt[i].
                                                       substream);
@@ -2675,7 +2680,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
 
 /* Initialization */
 
-static int __devinit vortex_core_init(vortex_t * vortex)
+static int vortex_core_init(vortex_t *vortex)
 {
 
        printk(KERN_INFO "Vortex: init.... ");
index 278ed8189fca9123d7360180fdb9e4b475f4b197..e7220533ecfc79a46f9ab05f3d54d083216dc16d 100644 (file)
@@ -757,7 +757,7 @@ snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
        return 1;               /* Allways changes */
 }
 
-static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "EQ Enable",
        .index = 0,
@@ -815,7 +815,7 @@ snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucon
        return changed;
 }
 
-static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_eq_kcontrol = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "                        .",
        .index = 0,
@@ -854,7 +854,7 @@ snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u
        return 0;
 }
 
-static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_levels_kcontrol = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "EQ Peaks",
        .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -863,7 +863,7 @@ static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
 };
 
 /* EQ band gain labels. */
-static char *EqBandLabels[10] __devinitdata = {
+static char *EqBandLabels[10] = {
        "EQ0 31Hz\0",
        "EQ1 63Hz\0",
        "EQ2 125Hz\0",
@@ -877,7 +877,7 @@ static char *EqBandLabels[10] __devinitdata = {
 };
 
 /* ALSA driver entry points. Init and exit. */
-static int __devinit vortex_eq_init(vortex_t * vortex)
+static int vortex_eq_init(vortex_t *vortex)
 {
        struct snd_kcontrol *kcontrol;
        int err, i;
index 30a456700d899bb88cbc643d3d5ea782a2f3d684..280f86de223086ab1b26d2639e12334ab2dceb37 100644 (file)
@@ -92,7 +92,7 @@ static int vortex_game_open(struct gameport *gameport, int mode)
        return 0;
 }
 
-static int __devinit vortex_gameport_register(vortex_t * vortex)
+static int vortex_gameport_register(vortex_t *vortex)
 {
        struct gameport *gp;
 
index fa13efbebdaffc8c7fb5b938838dcac8ea6ce660..a58298cfe7e04f03ce681b4d73540ef688929b9d 100644 (file)
@@ -19,7 +19,7 @@ static int remove_ctl(struct snd_card *card, const char *name)
        return snd_ctl_remove_id(card, &id);
 }
 
-static int __devinit snd_vortex_mixer(vortex_t * vortex)
+static int snd_vortex_mixer(vortex_t *vortex)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
index e6c6a0febb752ab75c951a16dd08e1be01a2dd2a..29e5945eef60dea7af07e4cea22202d68526b616 100644 (file)
@@ -41,7 +41,7 @@
 #define MPU401_ENTER_UART      0x3f
 #define MPU401_ACK                 0xfe
 
-static int __devinit snd_vortex_midi(vortex_t * vortex)
+static int snd_vortex_midi(vortex_t *vortex)
 {
        struct snd_rawmidi *rmidi;
        int temp, mode;
index b2405020284c6476814b8039a27cb416d64bf668..a4184bb277617fbc3e87bae54b8e1b26c5c722e9 100644 (file)
@@ -516,7 +516,7 @@ static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
 }
 
 /* spdif controls */
-static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {
        {
                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -598,7 +598,7 @@ static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
 
-static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
+static struct snd_kcontrol_new snd_vortex_pcm_vol = {
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "PCM Playback Volume",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -611,7 +611,7 @@ static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
 };
 
 /* create a pcm device */
-static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
+static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
 {
        struct snd_pcm *pcm;
        struct snd_kcontrol *kctl;
index 0f804741825f7ef9db7f18f5bb0bd358188bf3c6..08e9a4702cbc4cafcd34a9d52c2219da0c6ca441 100644 (file)
@@ -113,11 +113,11 @@ struct aw2 {
  * FUNCTION DECLARATIONS
  ********************************/
 static int snd_aw2_dev_free(struct snd_device *device);
-static int __devinit snd_aw2_create(struct snd_card *card,
-                                   struct pci_dev *pci, struct aw2 **rchip);
-static int __devinit snd_aw2_probe(struct pci_dev *pci,
-                                  const struct pci_device_id *pci_id);
-static void __devexit snd_aw2_remove(struct pci_dev *pci);
+static int snd_aw2_create(struct snd_card *card,
+                         struct pci_dev *pci, struct aw2 **rchip);
+static int snd_aw2_probe(struct pci_dev *pci,
+                        const struct pci_device_id *pci_id);
+static void snd_aw2_remove(struct pci_dev *pci);
 static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
@@ -135,7 +135,7 @@ static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
                                                      *substream);
 static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
                                                     *substream);
-static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
+static int snd_aw2_new_pcm(struct aw2 *chip);
 
 static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
                                               struct snd_ctl_elem_info *uinfo);
@@ -173,7 +173,7 @@ static struct pci_driver aw2_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_aw2_ids,
        .probe = snd_aw2_probe,
-       .remove = __devexit_p(snd_aw2_remove),
+       .remove = snd_aw2_remove,
 };
 
 module_pci_driver(aw2_driver);
@@ -202,7 +202,7 @@ static struct snd_pcm_ops snd_aw2_capture_ops = {
        .pointer = snd_aw2_pcm_pointer_capture,
 };
 
-static struct snd_kcontrol_new aw2_control __devinitdata = {
+static struct snd_kcontrol_new aw2_control = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "PCM Capture Route",
        .index = 0,
@@ -242,8 +242,8 @@ static int snd_aw2_dev_free(struct snd_device *device)
 }
 
 /* chip-specific constructor */
-static int __devinit snd_aw2_create(struct snd_card *card,
-                                   struct pci_dev *pci, struct aw2 **rchip)
+static int snd_aw2_create(struct snd_card *card,
+                         struct pci_dev *pci, struct aw2 **rchip)
 {
        struct aw2 *chip;
        int err;
@@ -332,8 +332,8 @@ static int __devinit snd_aw2_create(struct snd_card *card,
 }
 
 /* constructor */
-static int __devinit snd_aw2_probe(struct pci_dev *pci,
-                                  const struct pci_device_id *pci_id)
+static int snd_aw2_probe(struct pci_dev *pci,
+                        const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -389,7 +389,7 @@ static int __devinit snd_aw2_probe(struct pci_dev *pci,
 }
 
 /* destructor */
-static void __devexit snd_aw2_remove(struct pci_dev *pci)
+static void snd_aw2_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -591,7 +591,7 @@ static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
 }
 
 /* create a pcm device */
-static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
+static int snd_aw2_new_pcm(struct aw2 *chip)
 {
        struct snd_pcm *pcm_playback_ana;
        struct snd_pcm *pcm_playback_num;
index c03b66b784a377ef22135d81de415995c9c163d7..1204a0fa336889c0bc92600496520e2b07961b20 100644 (file)
@@ -817,7 +817,7 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
                snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write");
 }
 
-static int __devinit
+static int
 snd_azf3328_mixer_new(struct snd_azf3328 *chip)
 {
        struct snd_ac97_bus *bus;
@@ -1171,7 +1171,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
        return (nreg != oreg);
 }
 
-static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
        AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
        AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
        AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
@@ -1229,7 +1229,7 @@ static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
 #endif
 };
 
-static u16 __devinitdata snd_azf3328_init_values[][2] = {
+static u16 snd_azf3328_init_values[][2] = {
         { IDX_MIXER_PLAY_MASTER,       MIXER_MUTE_MASK|0x1f1f },
         { IDX_MIXER_MODEMOUT,          MIXER_MUTE_MASK|0x1f1f },
        { IDX_MIXER_BASSTREBLE,         0x0000 },
@@ -1245,7 +1245,7 @@ static u16 __devinitdata snd_azf3328_init_values[][2] = {
         { IDX_MIXER_REC_VOLUME,                MIXER_MUTE_MASK|0x0707 },
 };
 
-static int __devinit
+static int
 snd_azf3328_mixer_new(struct snd_azf3328 *chip)
 {
        struct snd_card *card;
@@ -1899,7 +1899,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
        return 0;
 }
 
-static int __devinit
+static int
 snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
 {
        struct gameport *gp;
@@ -2212,7 +2212,7 @@ static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
        .pointer =      snd_azf3328_pcm_pointer
 };
 
-static int __devinit
+static int
 snd_azf3328_pcm(struct snd_azf3328 *chip)
 {
 enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */
@@ -2344,7 +2344,7 @@ static struct snd_timer_hardware snd_azf3328_timer_hw = {
        .precise_resolution = snd_azf3328_timer_precise_resolution,
 };
 
-static int __devinit
+static int
 snd_azf3328_timer(struct snd_azf3328 *chip, int device)
 {
        struct snd_timer *timer = NULL;
@@ -2489,7 +2489,7 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
 #endif /* DEBUG_MISC */
 }
 
-static int __devinit
+static int
 snd_azf3328_create(struct snd_card *card,
                   struct pci_dev *pci,
                   unsigned long device_type,
@@ -2615,7 +2615,7 @@ out:
        return err;
 }
 
-static int __devinit
+static int
 snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -2720,7 +2720,7 @@ out:
        return err;
 }
 
-static void __devexit
+static void
 snd_azf3328_remove(struct pci_dev *pci)
 {
        snd_azf3328_dbgcallenter();
@@ -2872,7 +2872,7 @@ static struct pci_driver azf3328_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_azf3328_ids,
        .probe = snd_azf3328_probe,
-       .remove = __devexit_p(snd_azf3328_remove),
+       .remove = snd_azf3328_remove,
        .driver = {
                .pm = SND_AZF3328_PM_OPS,
        },
index b6a95eeca095fe922d8418c4fd05ee5bcc7fe337..cdd100dae85559d0619e474ded3f198519327bd4 100644 (file)
@@ -164,7 +164,7 @@ struct snd_bt87x_board {
        unsigned no_digital:1;  /* No digital input */
 };
 
-static __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = {
+static struct snd_bt87x_board snd_bt87x_boards[] = {
        [SND_BT87X_BOARD_UNKNOWN] = {
                .dig_rate = 32000, /* just a guess */
        },
@@ -696,7 +696,7 @@ static int snd_bt87x_dev_free(struct snd_device *device)
        return snd_bt87x_free(chip);
 }
 
-static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
+static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
 {
        int err;
        struct snd_pcm *pcm;
@@ -714,9 +714,9 @@ static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *nam
                                                        ALIGN(255 * 4092, 1024));
 }
 
-static int __devinit snd_bt87x_create(struct snd_card *card,
-                                     struct pci_dev *pci,
-                                     struct snd_bt87x **rchip)
+static int snd_bt87x_create(struct snd_card *card,
+                           struct pci_dev *pci,
+                           struct snd_bt87x **rchip)
 {
        struct snd_bt87x *chip;
        int err;
@@ -822,7 +822,7 @@ MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
  * (DVB cards use the audio function to transfer MPEG data) */
 static struct {
        unsigned short subvendor, subdevice;
-} blacklist[] __devinitdata = {
+} blacklist[] = {
        {0x0071, 0x0101}, /* Nebula Electronics DigiTV */
        {0x11bd, 0x001c}, /* Pinnacle PCTV Sat */
        {0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */
@@ -837,7 +837,7 @@ static struct {
 };
 
 /* return the id of the card, or a negative value if it's blacklisted */
-static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
+static int snd_bt87x_detect_card(struct pci_dev *pci)
 {
        int i;
        const struct pci_device_id *supported;
@@ -862,8 +862,8 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
        return SND_BT87X_BOARD_UNKNOWN;
 }
 
-static int __devinit snd_bt87x_probe(struct pci_dev *pci,
-                                    const struct pci_device_id *pci_id)
+static int snd_bt87x_probe(struct pci_dev *pci,
+                          const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -948,7 +948,7 @@ _error:
        return err;
 }
 
-static void __devexit snd_bt87x_remove(struct pci_dev *pci)
+static void snd_bt87x_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -966,7 +966,7 @@ static struct pci_driver bt87x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_bt87x_ids,
        .probe = snd_bt87x_probe,
-       .remove = __devexit_p(snd_bt87x_remove),
+       .remove = snd_bt87x_remove,
 };
 
 module_pci_driver(bt87x_driver);
index 65c55910566b24eb5dda03445a0e50f0f848bfe5..1610a5705970790973d0eecdd6b34d36c1d4506b 100644 (file)
@@ -1352,7 +1352,7 @@ static const struct snd_pcm_chmap_elem side_map[] = {
        { }
 };
 
-static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
+static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_substream *substream;
@@ -1650,7 +1650,7 @@ static void ca0106_stop_chip(struct snd_ca0106 *chip)
         */
 }
 
-static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
+static int snd_ca0106_create(int dev, struct snd_card *card,
                                         struct pci_dev *pci,
                                         struct snd_ca0106 **rchip)
 {
@@ -1777,7 +1777,7 @@ static int ca0106_dev_id_port(void *dev_id)
        return ((struct snd_ca0106 *)dev_id)->port;
 }
 
-static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
+static int snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
 {
        struct snd_ca_midi *midi;
        char *name;
@@ -1828,7 +1828,7 @@ static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int chann
 }
 
 
-static int __devinit snd_ca0106_probe(struct pci_dev *pci,
+static int snd_ca0106_probe(struct pci_dev *pci,
                                        const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -1893,7 +1893,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_ca0106_remove(struct pci_dev *pci)
+static void snd_ca0106_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1971,7 +1971,7 @@ static struct pci_driver ca0106_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ca0106_ids,
        .probe = snd_ca0106_probe,
-       .remove = __devexit_p(snd_ca0106_remove),
+       .remove = snd_ca0106_remove,
        .driver = {
                .pm = SND_CA0106_PM_OPS,
        },
index 68eacf7002d6ee87b848818b06a6997236d00426..27de0de900183e17cc0ef8d0c55bfa2f81cc8c0b 100644 (file)
@@ -325,7 +325,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
         return change;
 }
 
-static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
+static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Shared Mic/Line in Capture Switch",
@@ -334,7 +334,7 @@ static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
        .put =          snd_ca0106_capture_mic_line_in_put
 };
 
-static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
+static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Shared Line in/Side out Capture Switch",
@@ -588,7 +588,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol,
        .private_value = ((chid) << 8) | (reg)                  \
 }
 
-static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
        CA_VOLUME("Analog Front Playback Volume",
                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
         CA_VOLUME("Analog Rear Playback Volume",
@@ -669,7 +669,7 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
         I2C_VOLUME("Phone Capture Volume", 0),
         I2C_VOLUME("Mic Capture Volume", 1),
         I2C_VOLUME("Line in Capture Volume", 2),
@@ -691,7 +691,7 @@ static const int spi_dmute_bit[] = {
        SPI_DMUTE4_BIT,
 };
 
-static struct snd_kcontrol_new __devinit
+static struct snd_kcontrol_new
 snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
                              int channel_id)
 {
@@ -735,7 +735,7 @@ snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
        return spi_switch;
 }
 
-static int __devinit remove_ctl(struct snd_card *card, const char *name)
+static int remove_ctl(struct snd_card *card, const char *name)
 {
        struct snd_ctl_elem_id id;
        memset(&id, 0, sizeof(id));
@@ -744,7 +744,7 @@ static int __devinit remove_ctl(struct snd_card *card, const char *name)
        return snd_ctl_remove_id(card, &id);
 }
 
-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
 {
        struct snd_ctl_elem_id sid;
        memset(&sid, 0, sizeof(sid));
@@ -754,7 +754,7 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char
        return snd_ctl_find_id(card, &sid);
 }
 
-static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
+static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
 {
        struct snd_kcontrol *kctl = ctl_find(card, src);
        if (kctl) {
@@ -774,10 +774,10 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
                }                                                       \
        } while (0)
 
-static __devinitdata
+static
 DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
 
-static char *slave_vols[] __devinitdata = {
+static char *slave_vols[] = {
        "Analog Front Playback Volume",
         "Analog Rear Playback Volume",
        "Analog Center/LFE Playback Volume",
@@ -790,7 +790,7 @@ static char *slave_vols[] __devinitdata = {
        NULL
 };
 
-static char *slave_sws[] __devinitdata = {
+static char *slave_sws[] = {
        "Analog Front Playback Switch",
        "Analog Rear Playback Switch",
        "Analog Center/LFE Playback Switch",
@@ -799,7 +799,7 @@ static char *slave_sws[] __devinitdata = {
        NULL
 };
 
-static void __devinit add_slaves(struct snd_card *card,
+static void add_slaves(struct snd_card *card,
                                 struct snd_kcontrol *master, char **list)
 {
        for (; *list; list++) {
@@ -809,7 +809,7 @@ static void __devinit add_slaves(struct snd_card *card,
        }
 }
 
-int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
+int snd_ca0106_mixer(struct snd_ca0106 *emu)
 {
        int err;
         struct snd_card *card = emu->card;
index c694464b11689136eff0b2afe028d10be789ebf5..4f9c2821bb31188ec2ff9ca9d55999b64bc1a5c7 100644 (file)
@@ -424,7 +424,7 @@ static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry,
         }
 }
 
-int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu)
+int snd_ca0106_proc_init(struct snd_ca0106 *emu)
 {
        struct snd_info_entry *entry;
        
index c7885117da334c3da81b41a582f1126f4e4f7489..8bbdf265d11d240ab6798b8b6d67a65a693a8d2d 100644 (file)
@@ -286,7 +286,7 @@ static void ca_rmidi_free(struct snd_rawmidi *rmidi)
        ca_midi_free(rmidi->private_data);
 }
 
-int __devinit ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
+int ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
 {
        struct snd_rawmidi *rmidi;
        int err;
index 22122ff26e34aacabf963c731f645aabb5678158..c617435db6e6532a1caad658a4cb7773bc252d2a 100644 (file)
@@ -1045,7 +1045,7 @@ static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_cmipci_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_default =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1072,7 +1072,7 @@ static int snd_cmipci_spdif_mask_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_cmipci_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_mask =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1119,7 +1119,7 @@ static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_cmipci_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_stream =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1897,7 +1897,7 @@ static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
 /*
  */
 
-static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
+static int snd_cmipci_pcm_new(struct cmipci *cm, int device)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1920,7 +1920,7 @@ static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
        return 0;
 }
 
-static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
+static int snd_cmipci_pcm2_new(struct cmipci *cm, int device)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1942,7 +1942,7 @@ static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
        return 0;
 }
 
-static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
+static int snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
 {
        struct snd_pcm *pcm;
        int err;
@@ -2290,7 +2290,7 @@ static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol,
 }
 
 
-static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_mixers[] = {
        CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
        CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
        CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31),
@@ -2601,7 +2601,7 @@ static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol,
 }
 
 /* both for CM8338/8738 */
-static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_mixer_switches[] = {
        DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
        {
                .name = "Line-In Mode",
@@ -2613,11 +2613,11 @@ static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
 };
 
 /* for non-multichannel chips */
-static struct snd_kcontrol_new snd_cmipci_nomulti_switch __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_nomulti_switch =
 DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac);
 
 /* only for CM8738 */
-static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] = {
 #if 0 /* controlled in pcm device */
        DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in),
        DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out),
@@ -2639,14 +2639,14 @@ static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata =
 };
 
 /* only for model 033/037 */
-static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] = {
        DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out),
        DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
        DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1),
 };
 
 /* only for model 039 or later */
-static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] = {
        DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
        DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
        {
@@ -2659,11 +2659,11 @@ static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata =
 };
 
 /* card control switches */
-static struct snd_kcontrol_new snd_cmipci_modem_switch __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_modem_switch =
 DEFINE_CARD_SWITCH("Modem", modem);
 
 
-static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
+static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
 {
        struct snd_card *card;
        struct snd_kcontrol_new *sw;
@@ -2791,7 +2791,7 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "\n");
 }
 
-static void __devinit snd_cmipci_proc_init(struct cmipci *cm)
+static void snd_cmipci_proc_init(struct cmipci *cm)
 {
        struct snd_info_entry *entry;
 
@@ -2817,7 +2817,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_cmipci_ids) = {
  * check chip version and capabilities
  * driver name is modified according to the chip model
  */
-static void __devinit query_chip(struct cmipci *cm)
+static void query_chip(struct cmipci *cm)
 {
        unsigned int detect;
 
@@ -2866,7 +2866,7 @@ static void __devinit query_chip(struct cmipci *cm)
 }
 
 #ifdef SUPPORT_JOYSTICK
-static int __devinit snd_cmipci_create_gameport(struct cmipci *cm, int dev)
+static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
 {
        static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
        struct gameport *gp;
@@ -2959,7 +2959,7 @@ static int snd_cmipci_dev_free(struct snd_device *device)
        return snd_cmipci_free(cm);
 }
 
-static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
+static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
 {
        long iosynth;
        unsigned int val;
@@ -3012,8 +3012,8 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
        return 0;
 }
 
-static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
-                                      int dev, struct cmipci **rcmipci)
+static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
+                            int dev, struct cmipci **rcmipci)
 {
        struct cmipci *cm;
        int err;
@@ -3265,8 +3265,8 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
 
 MODULE_DEVICE_TABLE(pci, snd_cmipci_ids);
 
-static int __devinit snd_cmipci_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_cmipci_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -3314,7 +3314,7 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci,
 
 }
 
-static void __devexit snd_cmipci_remove(struct pci_dev *pci)
+static void snd_cmipci_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -3415,7 +3415,7 @@ static struct pci_driver cmipci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cmipci_ids,
        .probe = snd_cmipci_probe,
-       .remove = __devexit_p(snd_cmipci_remove),
+       .remove = snd_cmipci_remove,
        .driver = {
                .pm = SND_CMIPCI_PM_OPS,
        },
index 8e86ec0031fcce10cdec54d3bbb6d03d310daa8f..6a86950699415527261c4d938bbe7cfaca328010 100644 (file)
@@ -969,8 +969,8 @@ static struct snd_pcm_ops snd_cs4281_capture_ops = {
        .pointer =      snd_cs4281_pointer,
 };
 
-static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device,
-                                   struct snd_pcm ** rpcm)
+static int snd_cs4281_pcm(struct cs4281 *chip, int device,
+                         struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1093,7 +1093,7 @@ static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97)
                chip->ac97 = NULL;
 }
 
-static int __devinit snd_cs4281_mixer(struct cs4281 * chip)
+static int snd_cs4281_mixer(struct cs4281 *chip)
 {
        struct snd_card *card = chip->card;
        struct snd_ac97_template ac97;
@@ -1171,7 +1171,7 @@ static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {
        .read = snd_cs4281_BA1_read,
 };
 
-static void __devinit snd_cs4281_proc_init(struct cs4281 * chip)
+static void snd_cs4281_proc_init(struct cs4281 *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1259,7 +1259,7 @@ static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
        return 0;
 }
 
-static int __devinit snd_cs4281_create_gameport(struct cs4281 *chip)
+static int snd_cs4281_create_gameport(struct cs4281 *chip)
 {
        struct gameport *gp;
 
@@ -1335,10 +1335,10 @@ static int snd_cs4281_dev_free(struct snd_device *device)
 
 static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
 
-static int __devinit snd_cs4281_create(struct snd_card *card,
-                                      struct pci_dev *pci,
-                                      struct cs4281 ** rchip,
-                                      int dual_codec)
+static int snd_cs4281_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            struct cs4281 **rchip,
+                            int dual_codec)
 {
        struct cs4281 *chip;
        unsigned int tmp;
@@ -1779,8 +1779,8 @@ static struct snd_rawmidi_ops snd_cs4281_midi_input =
        .trigger =      snd_cs4281_midi_input_trigger,
 };
 
-static int __devinit snd_cs4281_midi(struct cs4281 * chip, int device,
-                                    struct snd_rawmidi **rrawmidi)
+static int snd_cs4281_midi(struct cs4281 *chip, int device,
+                          struct snd_rawmidi **rrawmidi)
 {
        struct snd_rawmidi *rmidi;
        int err;
@@ -1901,8 +1901,8 @@ static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd,
        spin_unlock_irqrestore(&opl3->reg_lock, flags);
 }
 
-static int __devinit snd_cs4281_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_cs4281_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -1968,7 +1968,7 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_cs4281_remove(struct pci_dev *pci)
+static void snd_cs4281_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2095,7 +2095,7 @@ static struct pci_driver cs4281_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs4281_ids,
        .probe = snd_cs4281_probe,
-       .remove = __devexit_p(snd_cs4281_remove),
+       .remove = snd_cs4281_remove,
        .driver = {
                .pm = CS4281_PM_OPS,
        },
index 575bed0836ffa242856ab5db73f8cbe2d80288da..6b0d8b50a305d4a632f6702a7a445c2febdc3733 100644 (file)
@@ -73,8 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_cs46xx_ids) = {
 
 MODULE_DEVICE_TABLE(pci, snd_cs46xx_ids);
 
-static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
-                                          const struct pci_device_id *pci_id)
+static int snd_card_cs46xx_probe(struct pci_dev *pci,
+                                const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -155,7 +155,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
+static void snd_card_cs46xx_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -165,7 +165,7 @@ static struct pci_driver cs46xx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs46xx_ids,
        .probe = snd_card_cs46xx_probe,
-       .remove = __devexit_p(snd_card_cs46xx_remove),
+       .remove = snd_card_cs46xx_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_cs46xx_pm,
index a2bb8c91ebe6041c61b2789d0ef97b073ac518b1..1b66efd9b728e153506106cf3917b17c73ec87b3 100644 (file)
@@ -1590,7 +1590,7 @@ static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
 #define MAX_PLAYBACK_CHANNELS  1
 #endif
 
-int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1621,7 +1621,8 @@ int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm
 
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device,
+                       struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1650,7 +1651,8 @@ int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct sn
        return 0;
 }
 
-int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device,
+                             struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1679,7 +1681,8 @@ int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, str
        return 0;
 }
 
-int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
+int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device,
+                         struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -2092,7 +2095,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
 
 
-static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cs46xx_controls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "DAC Volume",
@@ -2278,7 +2281,7 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
 }
 #endif
 
-static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
+static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
 {
        int idx, err;
        struct snd_ac97_template ac97;
@@ -2311,7 +2314,7 @@ static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
        return -ENXIO;
 }
 
-int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
+int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
 {
        struct snd_card *card = chip->card;
        struct snd_ctl_elem_id id;
@@ -2531,7 +2534,7 @@ static struct snd_rawmidi_ops snd_cs46xx_midi_input =
        .trigger =      snd_cs46xx_midi_input_trigger,
 };
 
-int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
+int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
 {
        struct snd_rawmidi *rmidi;
        int err;
@@ -2613,7 +2616,7 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
        return 0;
 }
 
-int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip)
+int snd_cs46xx_gameport(struct snd_cs46xx *chip)
 {
        struct gameport *gp;
 
@@ -2649,7 +2652,7 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
        }
 }
 #else
-int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
+int snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
 static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
 #endif /* CONFIG_GAMEPORT */
 
@@ -2674,7 +2677,7 @@ static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
        .read = snd_cs46xx_io_read,
 };
 
-static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
+static int snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
 {
        struct snd_info_entry *entry;
        int idx;
@@ -3061,7 +3064,7 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
        snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt enable */
 }
 
-int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
+int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
 {      
        unsigned int tmp;
        /*
@@ -3477,7 +3480,7 @@ struct cs_card_type
        void (*mixer_init)(struct snd_cs46xx *);
 };
 
-static struct cs_card_type __devinitdata cards[] = {
+static struct cs_card_type cards[] = {
        {
                .vendor = 0x1489,
                .id = 0x7001,
@@ -3717,10 +3720,10 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
 /*
  */
 
-int __devinit snd_cs46xx_create(struct snd_card *card,
-                     struct pci_dev * pci,
+int snd_cs46xx_create(struct snd_card *card,
+                     struct pci_dev *pci,
                      int external_amp, int thinkpad,
-                     struct snd_cs46xx ** rchip)
+                     struct snd_cs46xx **rchip)
 {
        struct snd_cs46xx *chip;
        int err, idx;
index d1cca2831575973dac041b49d066afa404b89f0d..dace827b45d1390401b2f8ae7a0a1fa78cfc0cb8 100644 (file)
@@ -88,13 +88,13 @@ static int snd_cs5530_dev_free(struct snd_device *device)
        return snd_cs5530_free(chip);
 }
 
-static void __devexit snd_cs5530_remove(struct pci_dev *pci)
+static void snd_cs5530_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
 }
 
-static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
+static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
 {
        outb(reg, io + 4);
        udelay(20);
@@ -103,9 +103,9 @@ static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
        return reg;
 }
 
-static int __devinit snd_cs5530_create(struct snd_card *card,
-                                      struct pci_dev *pci,
-                                      struct snd_cs5530 **rchip)
+static int snd_cs5530_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            struct snd_cs5530 **rchip)
 {
        struct snd_cs5530 *chip;
        unsigned long sb_base;
@@ -250,8 +250,8 @@ static int __devinit snd_cs5530_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_cs5530_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_cs5530_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -294,7 +294,7 @@ static struct pci_driver cs5530_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs5530_ids,
        .probe = snd_cs5530_probe,
-       .remove = __devexit_p(snd_cs5530_remove),
+       .remove = snd_cs5530_remove,
 };
 
 module_pci_driver(cs5530_driver);
index 4915efa551fca122434cc926adcf92721b58018f..7e4b13e2d12aa84d89e7532f23a9b5053f8c1b2c 100644 (file)
@@ -43,7 +43,7 @@ static char *ac97_quirk;
 module_param(ac97_quirk, charp, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds.");
 
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
+static struct ac97_quirk ac97_quirks[] = {
 #if 0 /* Not yet confirmed if all 5536 boards are HP only */
        {
                .subvendor = PCI_VENDOR_ID_AMD, 
@@ -144,7 +144,7 @@ static unsigned short snd_cs5535audio_ac97_codec_read(struct snd_ac97 *ac97,
        return snd_cs5535audio_codec_read(cs5535au, reg);
 }
 
-static int __devinit snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
+static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
 {
        struct snd_card *card = cs5535au->card;
        struct snd_ac97_bus *pbus;
@@ -270,9 +270,9 @@ static int snd_cs5535audio_dev_free(struct snd_device *device)
        return snd_cs5535audio_free(cs5535au);
 }
 
-static int __devinit snd_cs5535audio_create(struct snd_card *card,
-                                           struct pci_dev *pci,
-                                           struct cs5535audio **rcs5535au)
+static int snd_cs5535audio_create(struct snd_card *card,
+                                 struct pci_dev *pci,
+                                 struct cs5535audio **rcs5535au)
 {
        struct cs5535audio *cs5535au;
 
@@ -338,8 +338,8 @@ pcifail:
        return err;
 }
 
-static int __devinit snd_cs5535audio_probe(struct pci_dev *pci,
-                                          const struct pci_device_id *pci_id)
+static int snd_cs5535audio_probe(struct pci_dev *pci,
+                                const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -387,7 +387,7 @@ probefail_out:
        return err;
 }
 
-static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
+static void snd_cs5535audio_remove(struct pci_dev *pci)
 {
        olpc_quirks_cleanup();
        snd_card_free(pci_get_drvdata(pci));
@@ -398,7 +398,7 @@ static struct pci_driver cs5535audio_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_cs5535audio_ids,
        .probe = snd_cs5535audio_probe,
-       .remove = __devexit_p(snd_cs5535audio_remove),
+       .remove = snd_cs5535audio_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_cs5535audio_pm,
index bb3cc641130c68ef6d9ce2c51f070abfc1de9e3f..0579daa6221571581d7c869aa7248c86529d7b3a 100644 (file)
@@ -97,10 +97,10 @@ struct cs5535audio {
 extern const struct dev_pm_ops snd_cs5535audio_pm;
 
 #ifdef CONFIG_OLPC
-void __devinit olpc_prequirks(struct snd_card *card,
-               struct snd_ac97_template *ac97);
-int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
-void __devexit olpc_quirks_cleanup(void);
+void olpc_prequirks(struct snd_card *card,
+                   struct snd_ac97_template *ac97);
+int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
+void olpc_quirks_cleanup(void);
 void olpc_analog_input(struct snd_ac97 *ac97, int on);
 void olpc_mic_bias(struct snd_ac97 *ac97, int on);
 
@@ -133,7 +133,7 @@ static inline void olpc_capture_open(struct snd_ac97 *ac97) { }
 static inline void olpc_capture_close(struct snd_ac97 *ac97) { }
 #endif
 
-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
+int snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
 
 #endif /* __SOUND_CS5535AUDIO_H */
 
index 50da49be9ae5be7e18a5fc65be87bcfa4b0dabb1..da1cb9c4c76c2e24b46a477a93d6ff1d926d39a3 100644 (file)
@@ -114,7 +114,7 @@ static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
        return 1;
 }
 
-static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
+static struct snd_kcontrol_new olpc_cs5535audio_ctls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "DC Mode Enable",
@@ -133,8 +133,8 @@ static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
 },
 };
 
-void __devinit olpc_prequirks(struct snd_card *card,
-               struct snd_ac97_template *ac97)
+void olpc_prequirks(struct snd_card *card,
+                   struct snd_ac97_template *ac97)
 {
        if (!machine_is_olpc())
                return;
@@ -144,7 +144,7 @@ void __devinit olpc_prequirks(struct snd_card *card,
                ac97->scaps |= AC97_SCAP_INV_EAPD;
 }
 
-int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
+int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
 {
        struct snd_ctl_elem_id elem;
        int i, err;
@@ -185,7 +185,7 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
        return 0;
 }
 
-void __devexit olpc_quirks_cleanup(void)
+void olpc_quirks_cleanup(void)
 {
        gpio_free(OLPC_GPIO_MIC_AC);
 }
index dbf94b189e7576b6e8a3194c5612b0397e6060ee..9ab01a7047cfe3230bbf41c3944c1ab260887c02 100644 (file)
@@ -422,7 +422,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
         .read_dma_pntr = cs5535audio_capture_read_dma_pntr,
 };
 
-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
+int snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
 {
        struct snd_pcm *pcm;
        int err;
index a2f997a9977a7218e1085b9ee75857ab45f9ee44..b5fa583a239a5c978a1af60defe47a61886aeab0 100644 (file)
@@ -38,7 +38,7 @@
                            | (0x10 << 16) \
                            | ((IEC958_AES3_CON_FS_48000) << 24))
 
-static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
+static struct snd_pci_quirk subsys_20k1_list[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
@@ -48,7 +48,7 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
        { } /* terminator */
 };
 
-static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = {
+static struct snd_pci_quirk subsys_20k2_list[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,
                      "SB0760", CTSB0760),
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270,
@@ -1249,7 +1249,7 @@ static int atc_dev_free(struct snd_device *dev)
        return ct_atc_destroy(atc);
 }
 
-static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
+static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)
 {
        const struct snd_pci_quirk *p;
        const struct snd_pci_quirk *list;
@@ -1296,7 +1296,7 @@ static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
        return 0;
 }
 
-int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
+int ct_atc_create_alsa_devs(struct ct_atc *atc)
 {
        enum CTALSADEVS i;
        int err;
@@ -1319,7 +1319,7 @@ int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
        return 0;
 }
 
-static int __devinit atc_create_hw_devs(struct ct_atc *atc)
+static int atc_create_hw_devs(struct ct_atc *atc)
 {
        struct hw *hw;
        struct card_conf info = {0};
@@ -1614,7 +1614,7 @@ static int atc_resume(struct ct_atc *atc)
 }
 #endif
 
-static struct ct_atc atc_preset __devinitdata = {
+static struct ct_atc atc_preset = {
        .map_audio_buffer = ct_map_audio_buffer,
        .unmap_audio_buffer = ct_unmap_audio_buffer,
        .pcm_playback_prepare = atc_pcm_playback_prepare,
@@ -1665,10 +1665,10 @@ static struct ct_atc atc_preset __devinitdata = {
  *  Returns 0 if succeeds, or negative error code if fails.
  */
 
-int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
-                           unsigned int rsr, unsigned int msr,
-                           int chip_type, unsigned int ssid,
-                           struct ct_atc **ratc)
+int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+                 unsigned int rsr, unsigned int msr,
+                 int chip_type, unsigned int ssid,
+                 struct ct_atc **ratc)
 {
        struct ct_atc *atc;
        static struct snd_device_ops ops = {
index 69b51f9d345eda48eff3fa2b85790b70990e188d..5f11ca22fcdefaca7706cb7a81256d16c5894d2e 100644 (file)
@@ -152,9 +152,9 @@ struct ct_atc {
 };
 
 
-int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
-                           unsigned int rsr, unsigned int msr, int chip_type,
-                           unsigned int subsysid, struct ct_atc **ratc);
-int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc);
+int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+                 unsigned int rsr, unsigned int msr, int chip_type,
+                 unsigned int subsysid, struct ct_atc **ratc);
+int ct_atc_create_alsa_devs(struct ct_atc *atc);
 
 #endif /* CTATC_H */
index 8e64f4862e8517dff5731f55f2fcceaea4642856..110b8ace6d8a46f24cec3225682eb4952e8c6ef1 100644 (file)
@@ -20,8 +20,8 @@
 #include "cthw20k2.h"
 #include <linux/bug.h>
 
-int __devinit create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
-                           enum CTCARDS model, struct hw **rhw)
+int create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
+                 enum CTCARDS model, struct hw **rhw)
 {
        int err;
 
index 4507f7088b24c1b69dba253a2968d3bfdc95d7da..6ac40beb49dabea2b54e3de48a9eb721cfc3a5ae 100644 (file)
@@ -2171,7 +2171,7 @@ static void hw_write_pci(struct hw *hw, u32 reg, u32 data)
                &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
 }
 
-static struct hw ct20k1_preset __devinitdata = {
+static struct hw ct20k1_preset = {
        .irq = -1,
 
        .card_init = hw_card_init,
@@ -2275,7 +2275,7 @@ static struct hw ct20k1_preset __devinitdata = {
        .get_wc = get_wc,
 };
 
-int __devinit create_20k1_hw_obj(struct hw **rhw)
+int create_20k1_hw_obj(struct hw **rhw)
 {
        struct hw20k1 *hw20k1;
 
index b9c9349058bcc9178242fc5680849eb6f074c07c..b1438861d38ade68112572dbec342240a24d9e34 100644 (file)
@@ -2237,7 +2237,7 @@ static void hw_write_20kx(struct hw *hw, u32 reg, u32 data)
        writel(data, (void *)(hw->mem_base + reg));
 }
 
-static struct hw ct20k2_preset __devinitdata = {
+static struct hw ct20k2_preset = {
        .irq = -1,
 
        .card_init = hw_card_init,
@@ -2345,7 +2345,7 @@ static struct hw ct20k2_preset __devinitdata = {
        .get_wc = get_wc,
 };
 
-int __devinit create_20k2_hw_obj(struct hw **rhw)
+int create_20k2_hw_obj(struct hw **rhw)
 {
        struct hw20k2 *hw20k2;
 
index 07c07d752fd8978fa040363b10329078c14a0fcf..d01ffcb2b2f5f823033869f24faf1a12b7cc70df 100644 (file)
@@ -56,7 +56,7 @@ static DEFINE_PCI_DEVICE_TABLE(ct_pci_dev_ids) = {
 };
 MODULE_DEVICE_TABLE(pci, ct_pci_dev_ids);
 
-static int __devinit
+static int
 ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -119,7 +119,7 @@ error:
        return err;
 }
 
-static void __devexit ct_card_remove(struct pci_dev *pci)
+static void ct_card_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -152,7 +152,7 @@ static struct pci_driver ct_driver = {
        .name = KBUILD_MODNAME,
        .id_table = ct_pci_dev_ids,
        .probe = ct_card_probe,
-       .remove = __devexit_p(ct_card_remove),
+       .remove = ct_card_remove,
        .driver = {
                .pm = CT_CARD_PM_OPS,
        },
index abb0b86c41c942286c2897727e60ab466323d93f..760cbff532105f3bf56485082a43f0e6177fbad9 100644 (file)
@@ -907,7 +907,7 @@ static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
 
 
 /*<--snd_echo_probe() */
-static int __devinit snd_echo_new_pcm(struct echoaudio *chip)
+static int snd_echo_new_pcm(struct echoaudio *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1050,7 +1050,7 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
 
 #ifdef ECHOCARD_HAS_LINE_OUT_GAIN
 /* On the Mia this one controls the line-out volume */
-static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
+static struct snd_kcontrol_new snd_echo_line_output_gain = {
        .name = "Line Playback Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1061,7 +1061,7 @@ static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
        .tlv = {.p = db_scale_output_gain},
 };
 #else
-static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
+static struct snd_kcontrol_new snd_echo_pcm_output_gain = {
        .name = "PCM Playback Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1131,7 +1131,7 @@ static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0);
 
-static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
+static struct snd_kcontrol_new snd_echo_line_input_gain = {
        .name = "Line Capture Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1195,7 +1195,7 @@ static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = {
+static struct snd_kcontrol_new snd_echo_output_nominal_level = {
        .name = "Line Playback Switch (-10dBV)",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = snd_echo_output_nominal_info,
@@ -1261,7 +1261,7 @@ static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = {
+static struct snd_kcontrol_new snd_echo_intput_nominal_level = {
        .name = "Line Capture Switch (-10dBV)",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = snd_echo_input_nominal_info,
@@ -1327,7 +1327,7 @@ static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
+static struct snd_kcontrol_new snd_echo_monitor_mixer = {
        .name = "Monitor Mixer Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1395,7 +1395,7 @@ static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
+static struct snd_kcontrol_new snd_echo_vmixer = {
        .name = "VMixer Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
@@ -1490,7 +1490,7 @@ static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_digital_mode_switch = {
        .name = "Digital mode Switch",
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .info = snd_echo_digital_mode_info,
@@ -1547,7 +1547,7 @@ static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_spdif_mode_switch = {
        .name = "S/PDIF mode Switch",
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .info = snd_echo_spdif_mode_info,
@@ -1626,7 +1626,7 @@ static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_clock_source_switch = {
        .name = "Sample Clock Source",
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .info = snd_echo_clock_source_info,
@@ -1669,7 +1669,7 @@ static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_phantom_power_switch = {
        .name = "Phantom power Switch",
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .info = snd_echo_phantom_power_info,
@@ -1712,7 +1712,7 @@ static int snd_echo_automute_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_automute_switch = {
        .name = "Digital Capture Switch (automute)",
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .info = snd_echo_automute_info,
@@ -1739,7 +1739,7 @@ static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
-static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = {
+static struct snd_kcontrol_new snd_echo_vumeters_switch = {
        .name = "VU-meters Switch",
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .access = SNDRV_CTL_ELEM_ACCESS_WRITE,
@@ -1780,7 +1780,7 @@ static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
+static struct snd_kcontrol_new snd_echo_vumeters = {
        .name = "VU-meters",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READ |
@@ -1836,7 +1836,7 @@ static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = {
+static struct snd_kcontrol_new snd_echo_channels_info = {
        .name = "Channels info",
        .iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
        .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -1940,9 +1940,9 @@ static int snd_echo_dev_free(struct snd_device *device)
 
 
 /* <--snd_echo_probe() */
-static __devinit int snd_echo_create(struct snd_card *card,
-                                    struct pci_dev *pci,
-                                    struct echoaudio **rchip)
+static int snd_echo_create(struct snd_card *card,
+                          struct pci_dev *pci,
+                          struct echoaudio **rchip)
 {
        struct echoaudio *chip;
        int err;
@@ -2040,8 +2040,8 @@ static __devinit int snd_echo_create(struct snd_card *card,
 
 
 /* constructor */
-static int __devinit snd_echo_probe(struct pci_dev *pci,
-                                   const struct pci_device_id *pci_id)
+static int snd_echo_probe(struct pci_dev *pci,
+                         const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -2316,7 +2316,7 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume);
 #endif /* CONFIG_PM_SLEEP */
 
 
-static void __devexit snd_echo_remove(struct pci_dev *pci)
+static void snd_echo_remove(struct pci_dev *pci)
 {
        struct echoaudio *chip;
 
@@ -2337,7 +2337,7 @@ static struct pci_driver echo_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_echo_ids,
        .probe = snd_echo_probe,
-       .remove = __devexit_p(snd_echo_remove),
+       .remove = snd_echo_remove,
        .driver = {
                .pm = SND_ECHO_PM_OPS,
        },
index e158369f5faaa117d23d71878293a27d6a428f86..b86b88da81cd92eb793610c6802ba12c2c13b277 100644 (file)
@@ -475,8 +475,8 @@ static int enable_midi_input(struct echoaudio *chip, char enable);
 static void snd_echo_midi_output_trigger(
                        struct snd_rawmidi_substream *substream, int up);
 static int midi_service_irq(struct echoaudio *chip);
-static int __devinit snd_echo_midi_create(struct snd_card *card,
-                                         struct echoaudio *chip);
+static int snd_echo_midi_create(struct snd_card *card,
+                               struct echoaudio *chip);
 #endif
 
 
index a953d142cb4b41144090cf6f0d66b3ddf382fc67..abfd51c2530ed9172cba8e98fef3714ad4e6b690 100644 (file)
@@ -307,8 +307,8 @@ static struct snd_rawmidi_ops snd_echo_midi_output = {
 
 
 /* <--snd_echo_probe() */
-static int __devinit snd_echo_midi_create(struct snd_card *card,
-                                         struct echoaudio *chip)
+static int snd_echo_midi_create(struct snd_card *card,
+                               struct echoaudio *chip)
 {
        int err;
 
index b7c1875ba90ec2ad06518a1af310fd62d3f357cb..8c5010f7889cbd57192cfaa03d77972f7522aded 100644 (file)
@@ -99,8 +99,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1_ids) = {
 
 MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids);
 
-static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
-                                           const struct pci_device_id *pci_id)
+static int snd_card_emu10k1_probe(struct pci_dev *pci,
+                                 const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -199,7 +199,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
+static void snd_card_emu10k1_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -215,6 +215,8 @@ static int snd_emu10k1_suspend(struct device *dev)
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 
+       emu->suspend = 1;
+
        snd_pcm_suspend_all(emu->pcm);
        snd_pcm_suspend_all(emu->pcm_mic);
        snd_pcm_suspend_all(emu->pcm_efx);
@@ -260,6 +262,8 @@ static int snd_emu10k1_resume(struct device *dev)
        if (emu->card_capabilities->ca0151_chip)
                snd_p16v_resume(emu);
 
+       emu->suspend = 0;
+
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
@@ -274,7 +278,7 @@ static struct pci_driver emu10k1_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_emu10k1_ids,
        .probe = snd_card_emu10k1_probe,
-       .remove = __devexit_p(snd_card_emu10k1_remove),
+       .remove = snd_card_emu10k1_remove,
        .driver = {
                .pm = SND_EMU10K1_PM_OPS,
        },
index c21adb6ef1d5d5b642c375febb1274e40b0cc9df..a7c296a36a177dc5d861216ee129a666c3aa563e 100644 (file)
@@ -657,22 +657,17 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
        return 0;
 }
 
-static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu)
 {
-       int err;
        int n, i;
        int reg;
        int value;
        unsigned int write_post;
        unsigned long flags;
-       const struct firmware *fw_entry;
+       const struct firmware *fw_entry = emu->firmware;
 
-       err = request_firmware(&fw_entry, filename, &emu->pci->dev);
-       if (err != 0) {
-               snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err);
-               return err;
-       }
-       snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size);
+       if (!fw_entry)
+               return -EIO;
 
        /* The FPGA is a Xilinx Spartan IIE XC2S50E */
        /* GPIO7 -> FPGA PGMN
@@ -705,7 +700,6 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filena
        write_post = inl(emu->port + A_IOCFG);
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 
-       release_firmware(fw_entry);
        return 0;
 }
 
@@ -720,6 +714,10 @@ static int emu1010_firmware_thread(void *data)
                msleep_interruptible(1000);
                if (kthread_should_stop())
                        break;
+#ifdef CONFIG_PM_SLEEP
+               if (emu->suspend)
+                       continue;
+#endif
                snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
                snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
                if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
@@ -727,22 +725,9 @@ static int emu1010_firmware_thread(void *data)
                        /* Return to Audio Dock programming mode */
                        snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
                        snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
-                       if (emu->card_capabilities->emu_model ==
-                           EMU_MODEL_EMU1010) {
-                               err = snd_emu1010_load_firmware(emu, DOCK_FILENAME);
-                               if (err != 0)
-                                       continue;
-                       } else if (emu->card_capabilities->emu_model ==
-                                  EMU_MODEL_EMU1010B) {
-                               err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
-                               if (err != 0)
-                                       continue;
-                       } else if (emu->card_capabilities->emu_model ==
-                                  EMU_MODEL_EMU1616) {
-                               err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
-                               if (err != 0)
-                                       continue;
-                       }
+                       err = snd_emu1010_load_firmware(emu);
+                       if (err != 0)
+                               continue;
 
                        snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
                        snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg);
@@ -807,7 +792,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        unsigned int i;
        u32 tmp, tmp2, reg;
        int err;
-       const char *filename = NULL;
 
        snd_printk(KERN_INFO "emu1010: Special config.\n");
        /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
@@ -849,31 +833,33 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
                return -ENODEV;
        }
        snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg);
-       switch (emu->card_capabilities->emu_model) {
-       case EMU_MODEL_EMU1010:
-               filename = HANA_FILENAME;
-               break;
-       case EMU_MODEL_EMU1010B:
-               filename = EMU1010B_FILENAME;
-               break;
-       case EMU_MODEL_EMU1616:
-               filename = EMU1010_NOTEBOOK_FILENAME;
-               break;
-       case EMU_MODEL_EMU0404:
-               filename = EMU0404_FILENAME;
-               break;
-       default:
-               filename = NULL;
-               return -ENODEV;
-               break;
-       }
-       snd_printk(KERN_INFO "emu1010: filename %s testing\n", filename);
-       err = snd_emu1010_load_firmware(emu, filename);
-       if (err != 0) {
-               snd_printk(
-                       KERN_INFO "emu1010: Loading Firmware file %s failed\n",
-                       filename);
-               return err;
+
+       if (!emu->firmware) {
+               const char *filename;
+               switch (emu->card_capabilities->emu_model) {
+               case EMU_MODEL_EMU1010:
+                       filename = HANA_FILENAME;
+                       break;
+               case EMU_MODEL_EMU1010B:
+                       filename = EMU1010B_FILENAME;
+                       break;
+               case EMU_MODEL_EMU1616:
+                       filename = EMU1010_NOTEBOOK_FILENAME;
+                       break;
+               case EMU_MODEL_EMU0404:
+                       filename = EMU0404_FILENAME;
+                       break;
+               default:
+                       return -ENODEV;
+               }
+
+               err = request_firmware(&emu->firmware, filename, &emu->pci->dev);
+               if (err != 0) {
+                       snd_printk(KERN_ERR "emu1010: firmware: %s not found. Err = %d\n", filename, err);
+                       return err;
+               }
+               snd_printk(KERN_INFO "emu1010: firmware file = %s, size = 0x%zx\n",
+                          filename, emu->firmware->size);
        }
 
        /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
@@ -1259,6 +1245,8 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
        }
        if (emu->emu1010.firmware_thread)
                kthread_stop(emu->emu1010.firmware_thread);
+       if (emu->firmware)
+               release_firmware(emu->firmware);
        if (emu->irq >= 0)
                free_irq(emu->irq, emu);
        /* remove reserved page */
@@ -1738,7 +1726,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
        { } /* terminator */
 };
 
-int __devinit snd_emu10k1_create(struct snd_card *card,
+int snd_emu10k1_create(struct snd_card *card,
                       struct pci_dev *pci,
                       unsigned short extin_mask,
                       unsigned short extout_mask,
@@ -2025,7 +2013,7 @@ static unsigned char saved_regs_audigy[] = {
        0xff /* end */
 };
 
-static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
+static int alloc_pm_buffer(struct snd_emu10k1 *emu)
 {
        int size;
 
index e10f027bde03a660899e1a440538c2a661d150e9..662a45876a8b3d9b6e1008173216b32c705776bf 100644 (file)
@@ -123,7 +123,7 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
        offset += size;
        data += size;
 
-#if 0 /* not suppported yet */
+#if 0 /* not supported yet */
        /* handle reverse (or bidirectional) loop */
        if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
                /* copy loop in reverse */
index 556fd6f456e36809af61c5156a062db67f3de386..cdff11d48ebd5b4316584552ca7191e4ee7aee97 100644 (file)
@@ -842,7 +842,7 @@ static const struct snd_pcm_chmap_elem clfe_map[] = {
        { }
 };
 
-static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
+static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        const struct snd_pcm_chmap_elem *map = NULL;
@@ -902,9 +902,9 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s
        return 0;
 }
 
-static int __devinit snd_emu10k1x_create(struct snd_card *card,
-                                        struct pci_dev *pci,
-                                        struct emu10k1x **rchip)
+static int snd_emu10k1x_create(struct snd_card *card,
+                              struct pci_dev *pci,
+                              struct emu10k1x **rchip)
 {
        struct emu10k1x *chip;
        int err;
@@ -1066,7 +1066,7 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
        }
 }
 
-static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu)
+static int snd_emu10k1x_proc_init(struct emu10k1x *emu)
 {
        struct snd_info_entry *entry;
        
@@ -1115,7 +1115,7 @@ static int snd_emu10k1x_shared_spdif_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_emu10k1x_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_emu10k1x_shared_spdif =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Analog/Digital Output Jack",
@@ -1194,7 +1194,7 @@ static struct snd_kcontrol_new snd_emu10k1x_spdif_control =
        .put =          snd_emu10k1x_spdif_put
 };
 
-static int __devinit snd_emu10k1x_mixer(struct emu10k1x *emu)
+static int snd_emu10k1x_mixer(struct emu10k1x *emu)
 {
        int err;
        struct snd_kcontrol *kctl;
@@ -1507,8 +1507,9 @@ static void snd_emu10k1x_midi_free(struct snd_rawmidi *rmidi)
        midi->rmidi = NULL;
 }
 
-static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
-                                       struct emu10k1x_midi *midi, int device, char *name)
+static int emu10k1x_midi_init(struct emu10k1x *emu,
+                             struct emu10k1x_midi *midi, int device,
+                             char *name)
 {
        struct snd_rawmidi *rmidi;
        int err;
@@ -1531,7 +1532,7 @@ static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
        return 0;
 }
 
-static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
+static int snd_emu10k1x_midi(struct emu10k1x *emu)
 {
        struct emu10k1x_midi *midi = &emu->midi;
        int err;
@@ -1548,8 +1549,8 @@ static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
        return 0;
 }
 
-static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_emu10k1x_probe(struct pci_dev *pci,
+                             const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -1619,7 +1620,7 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_emu10k1x_remove(struct pci_dev *pci)
+static void snd_emu10k1x_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1637,7 +1638,7 @@ static struct pci_driver emu10k1x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_emu10k1x_ids,
        .probe = snd_emu10k1x_probe,
-       .remove = __devexit_p(snd_emu10k1x_remove),
+       .remove = snd_emu10k1x_remove,
 };
 
 module_pci_driver(emu10k1x_driver);
index 52419959178c6fcad09855b67b417537b70e226a..0275209ca82e33bb4fd0c69569c31e08993a87d2 100644 (file)
@@ -1073,7 +1073,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
 #define SND_EMU10K1_PLAYBACK_CHANNELS  8
 #define SND_EMU10K1_CAPTURE_CHANNELS   4
 
-static void __devinit
+static void
 snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                              const char *name, int gpr, int defval)
 {
@@ -1094,7 +1094,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
        }
 }
 
-static void __devinit
+static void
 snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                                const char *name, int gpr, int defval)
 {
@@ -1116,7 +1116,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
        }
 }
 
-static void __devinit
+static void
 snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                                    const char *name, int gpr, int defval)
 {
@@ -1129,7 +1129,7 @@ snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
        ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
 }
 
-static void __devinit
+static void
 snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                                      const char *name, int gpr, int defval)
 {
@@ -1168,7 +1168,7 @@ static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
  * initial DSP configuration for Audigy
  */
 
-static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
+static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
 {
        int err, i, z, gpr, nctl;
        int bit_shifter16;
@@ -1757,14 +1757,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 
 /* when volume = max, then copy only to avoid volume modification */
 /* with iMAC0 (negative values) */
-static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
 {
        OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
        OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
        OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
        OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
 }
-static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
 {
        OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
        OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
@@ -1772,7 +1772,7 @@ static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *pt
        OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
        OP(icode, ptr, iMAC0, dst, dst, src, vol);
 }
-static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
 {
        OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
        OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
@@ -1803,7 +1803,7 @@ static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *pt
                _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
 
 
-static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
 {
        int err, i, z, gpr, tmp, playback, capture;
        u32 ptr;
@@ -2373,7 +2373,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
        return err;
 }
 
-int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+int snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
 {
        spin_lock_init(&emu->fx8010.irq_lock);
        INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
@@ -2626,7 +2626,8 @@ static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file)
        return 0;
 }
 
-int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep)
+int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device,
+                          struct snd_hwdep **rhwdep)
 {
        struct snd_hwdep *hw;
        int err;
@@ -2647,7 +2648,7 @@ int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct
 }
 
 #ifdef CONFIG_PM_SLEEP
-int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
+int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
 {
        int len;
 
index 9d890a5aec5afd5ad9aded994fe247b71644684e..f6c3da0d377d19e5a2b0822e07a1c66cd8b7199b 100644 (file)
@@ -510,7 +510,7 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
        EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
@@ -539,7 +539,7 @@ static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
 
 
 /* 1616(m) cardbus */
-static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
        EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
@@ -571,7 +571,7 @@ static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = {
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
        EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
        EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
        EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
@@ -639,7 +639,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
        EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
        EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
        EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
@@ -687,7 +687,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
+static struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
        EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
        EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
        EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
@@ -989,7 +989,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
+static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
        I2C_VOLUME("Mic Capture Volume", 0),
        I2C_VOLUME("Line Capture Volume", 0)
 };
@@ -1621,7 +1621,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_emu10k1_shared_spdif =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "SB Live Analog/Digital Output Jack",
@@ -1630,7 +1630,7 @@ static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
        .put =          snd_emu10k1_shared_spdif_put
 };
 
-static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_audigy_shared_spdif =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Audigy Analog/Digital Output Jack",
@@ -1668,7 +1668,7 @@ static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
        return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
 }
 
-static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata =
+static struct snd_kcontrol_new snd_audigy_capture_boost =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Analog Capture Boost",
@@ -1716,8 +1716,8 @@ static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
        return -ENOENT;
 }
 
-int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
-                               int pcm_device, int multi_device)
+int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
+                     int pcm_device, int multi_device)
 {
        int err, pcm;
        struct snd_kcontrol *kctl;
index bab564824efe11ebdf1160e81b568254c3a7fd1c..1ec91246dfee5cdff16bf2b68c939d3a90848efc 100644 (file)
@@ -326,7 +326,7 @@ static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
        midi->rmidi = NULL;
 }
 
-static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
+static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
 {
        struct snd_rawmidi *rmidi;
        int err;
@@ -349,7 +349,7 @@ static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10
        return 0;
 }
 
-int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
+int snd_emu10k1_midi(struct snd_emu10k1 *emu)
 {
        struct snd_emu10k1_midi *midi = &emu->midi;
        int err;
@@ -366,7 +366,7 @@ int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
        return 0;
 }
 
-int __devinit snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
+int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
 {
        struct snd_emu10k1_midi *midi;
        int err;
index 0e6664fa6cd997fe7b64137bd420523beef0444e..748a286277eb28e9ef43a13c1622bd83b6b9bc9d 100644 (file)
@@ -1391,7 +1391,7 @@ static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
        .page =                 snd_pcm_sgbuf_ops_page,
 };
 
-int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_substream *substream;
@@ -1426,7 +1426,8 @@ int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_p
        return 0;
 }
 
-int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device,
+                         struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_substream *substream;
@@ -1469,7 +1470,8 @@ static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
        .pointer =              snd_emu10k1_capture_pointer,
 };
 
-int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device,
+                       struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1810,7 +1812,8 @@ static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
        .ack =                  snd_emu10k1_fx8010_playback_transfer,
 };
 
-int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device,
+                       struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        struct snd_kcontrol *kctl;
index bc38dd4d071f54cdad06664554d47df099638265..2ca9f2e93139e125925c096f3e6163c3e2cd1c87 100644 (file)
@@ -577,7 +577,7 @@ static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = {
        .read = snd_emu10k1_fx8010_read,
 };
 
-int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
+int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
 {
        struct snd_info_entry *entry;
 #ifdef CONFIG_SND_DEBUG
index 88cec6b7dd41244643a6df7b3b7d80e4fb5776ab..7e2025cd6d9cc07a3696cb4f1e038c8b5e3e6ef6 100644 (file)
@@ -637,7 +637,7 @@ int snd_p16v_free(struct snd_emu10k1 *chip)
        return 0;
 }
 
-int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
+int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_substream *substream;
@@ -854,7 +854,7 @@ static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
        .private_value = ((xreg) | ((xhl) << 8)) \
 }
 
-static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
+static struct snd_kcontrol_new p16v_mixer_controls[] = {
        P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
        P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
        P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
@@ -880,7 +880,7 @@ static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
 };
 
 
-int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
+int snd_p16v_mixer(struct snd_emu10k1 *emu)
 {
        int i, err;
         struct snd_card *card = emu->card;
@@ -897,7 +897,7 @@ int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
 
 #define NUM_CHS        1       /* up to 4, but only first channel is used */
 
-int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
+int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
 {
        emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80);
        if (! emu->p16v_saved)
index 72321e946cccf6661810559c66a4f3cf69c30ba5..b69a7f8a216ce1177cda7b27a78c99ef5c3ab7a0 100644 (file)
@@ -75,7 +75,7 @@ static struct snd_timer_hardware snd_emu10k1_timer_hw = {
        .precise_resolution = snd_emu10k1_timer_precise_resolution,
 };
 
-int __devinit snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
+int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
 {
        struct snd_timer *timer = NULL;
        struct snd_timer_id tid;
index 5674cc316530bc3ab0a1b009e7d51b22ff0e3c1f..db2dc835171d2a6bf9ee8d4468ca6e54911b06c2 100644 (file)
@@ -1268,8 +1268,8 @@ static const struct snd_pcm_chmap_elem surround_map[] = {
        { }
 };
 
-static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
-                                    struct snd_pcm ** rpcm)
+static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device,
+                          struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1310,8 +1310,8 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
        return 0;
 }
 
-static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device,
-                                     struct snd_pcm ** rpcm)
+static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device,
+                           struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1484,7 +1484,7 @@ static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,
 
 
 /* spdif controls */
-static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_es1371_mixer_spdif[] = {
        ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
        {
                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1546,7 +1546,7 @@ static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ens1373_rear __devinitdata =
+static struct snd_kcontrol_new snd_ens1373_rear =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "AC97 2ch->4ch Copy Switch",
@@ -1591,7 +1591,7 @@ static int snd_es1373_line_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_ens1373_line __devinitdata =
+static struct snd_kcontrol_new snd_ens1373_line =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Line In->Rear Out Switch",
@@ -1625,7 +1625,7 @@ static int es1371_quirk_lookup(struct ensoniq *ensoniq,
        return 0;
 }
 
-static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
+static struct es1371_quirk es1371_spdif_present[] = {
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1634,14 +1634,14 @@ static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
        { .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
 };
 
-static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = {
+static struct snd_pci_quirk ens1373_line_quirk[] = {
        SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
        SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
        { } /* end */
 };
 
-static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
-                                           int has_spdif, int has_line)
+static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
+                                 int has_spdif, int has_line)
 {
        struct snd_card *card = ensoniq->card;
        struct snd_ac97_bus *pbus;
@@ -1749,7 +1749,7 @@ static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol,
  * ENS1370 mixer
  */
 
-static struct snd_kcontrol_new snd_es1370_controls[2] __devinitdata = {
+static struct snd_kcontrol_new snd_es1370_controls[2] = {
 ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0),
 ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)
 };
@@ -1762,7 +1762,7 @@ static void snd_ensoniq_mixer_free_ak4531(struct snd_ak4531 *ak4531)
        ensoniq->u.es1370.ak4531 = NULL;
 }
 
-static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
+static int snd_ensoniq_1370_mixer(struct ensoniq *ensoniq)
 {
        struct snd_card *card = ensoniq->card;
        struct snd_ak4531 ak4531;
@@ -1796,7 +1796,7 @@ static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
 #ifdef SUPPORT_JOYSTICK
 
 #ifdef CHIP1371
-static int __devinit snd_ensoniq_get_joystick_port(int dev)
+static int snd_ensoniq_get_joystick_port(int dev)
 {
        switch (joystick_port[dev]) {
        case 0: /* disabled */
@@ -1819,7 +1819,7 @@ static inline int snd_ensoniq_get_joystick_port(int dev)
 }
 #endif
 
-static int __devinit snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
+static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
 {
        struct gameport *gp;
        int io_port;
@@ -1913,7 +1913,7 @@ static void snd_ensoniq_proc_read(struct snd_info_entry *entry,
 #endif
 }
 
-static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq)
+static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
 {
        struct snd_info_entry *entry;
 
@@ -1960,7 +1960,7 @@ static int snd_ensoniq_dev_free(struct snd_device *device)
 }
 
 #ifdef CHIP1371
-static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = {
+static struct snd_pci_quirk es1371_amplifier_hack[] = {
        SND_PCI_QUIRK_ID(0x107b, 0x2150),       /* Gateway Solo 2150 */
        SND_PCI_QUIRK_ID(0x13bd, 0x100c),       /* EV1938 on Mebius PC-MJ100V */
        SND_PCI_QUIRK_ID(0x1102, 0x5938),       /* Targa Xtender300 */
@@ -2106,9 +2106,9 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume
 #define SND_ENSONIQ_PM_OPS     NULL
 #endif /* CONFIG_PM_SLEEP */
 
-static int __devinit snd_ensoniq_create(struct snd_card *card,
-                                    struct pci_dev *pci,
-                                    struct ensoniq ** rensoniq)
+static int snd_ensoniq_create(struct snd_card *card,
+                             struct pci_dev *pci,
+                             struct ensoniq **rensoniq)
 {
        struct ensoniq *ensoniq;
        int err;
@@ -2361,8 +2361,8 @@ static struct snd_rawmidi_ops snd_ensoniq_midi_input =
        .trigger =      snd_ensoniq_midi_input_trigger,
 };
 
-static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device,
-                                     struct snd_rawmidi **rrawmidi)
+static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device,
+                           struct snd_rawmidi **rrawmidi)
 {
        struct snd_rawmidi *rmidi;
        int err;
@@ -2422,8 +2422,8 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit snd_audiopci_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_audiopci_probe(struct pci_dev *pci,
+                             const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -2494,7 +2494,7 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_audiopci_remove(struct pci_dev *pci)
+static void snd_audiopci_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2504,7 +2504,7 @@ static struct pci_driver ens137x_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_audiopci_ids,
        .probe = snd_audiopci_probe,
-       .remove = __devexit_p(snd_audiopci_remove),
+       .remove = snd_audiopci_remove,
        .driver = {
                .pm = SND_ENSONIQ_PM_OPS,
        },
index 394c5d413530cd66fb5b1c1718d55f6b523ece13..8423403954abfae68b01ab7a96e93f0e025d1628 100644 (file)
@@ -1027,7 +1027,7 @@ static struct snd_pcm_ops snd_es1938_capture_ops = {
        .copy =         snd_es1938_capture_copy,
 };
 
-static int __devinit snd_es1938_new_pcm(struct es1938 *chip, int device)
+static int snd_es1938_new_pcm(struct es1938 *chip, int device)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1539,7 +1539,7 @@ static SIMPLE_DEV_PM_OPS(es1938_pm, es1938_suspend, es1938_resume);
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef SUPPORT_JOYSTICK
-static int __devinit snd_es1938_create_gameport(struct es1938 *chip)
+static int snd_es1938_create_gameport(struct es1938 *chip)
 {
        struct gameport *gp;
 
@@ -1594,9 +1594,9 @@ static int snd_es1938_dev_free(struct snd_device *device)
        return snd_es1938_free(chip);
 }
 
-static int __devinit snd_es1938_create(struct snd_card *card,
-                                   struct pci_dev * pci,
-                                   struct es1938 ** rchip)
+static int snd_es1938_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            struct es1938 **rchip)
 {
        struct es1938 *chip;
        int err;
@@ -1754,7 +1754,7 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id)
 
 #define ES1938_DMA_SIZE 64
 
-static int __devinit snd_es1938_mixer(struct es1938 *chip)
+static int snd_es1938_mixer(struct es1938 *chip)
 {
        struct snd_card *card;
        unsigned int idx;
@@ -1792,8 +1792,8 @@ static int __devinit snd_es1938_mixer(struct es1938 *chip)
 }
        
 
-static int __devinit snd_es1938_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_es1938_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -1878,7 +1878,7 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_es1938_remove(struct pci_dev *pci)
+static void snd_es1938_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1888,7 +1888,7 @@ static struct pci_driver es1938_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_es1938_ids,
        .probe = snd_es1938_probe,
-       .remove = __devexit_p(snd_es1938_remove),
+       .remove = snd_es1938_remove,
        .driver = {
                .pm = ES1938_PM_OPS,
        },
index 7266020c16cb3a489a22418fd3b1f32e3dbd9fdb..a1f32b5ae0d1b4131a7ba7b9a8d2366bfd959e3d 100644 (file)
@@ -1429,7 +1429,7 @@ static void snd_es1968_free_dmabuf(struct es1968 *chip)
        }
 }
 
-static int __devinit
+static int
 snd_es1968_init_dmabuf(struct es1968 *chip)
 {
        int err;
@@ -1704,7 +1704,7 @@ static struct snd_pcm_ops snd_es1968_capture_ops = {
  */
 #define CLOCK_MEASURE_BUFSIZE  16768   /* enough large for a single shot */
 
-static void __devinit es1968_measure_clock(struct es1968 *chip)
+static void es1968_measure_clock(struct es1968 *chip)
 {
        int i, apu;
        unsigned int pa, offset, t;
@@ -1806,7 +1806,7 @@ static void snd_es1968_pcm_free(struct snd_pcm *pcm)
        esm->pcm = NULL;
 }
 
-static int __devinit
+static int
 snd_es1968_pcm(struct es1968 *chip, int device)
 {
        struct snd_pcm *pcm;
@@ -2016,7 +2016,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
  *  Mixer stuff
  */
 
-static int __devinit
+static int
 snd_es1968_mixer(struct es1968 *chip)
 {
        struct snd_ac97_bus *pbus;
@@ -2291,7 +2291,7 @@ static void snd_es1968_chip_init(struct es1968 *chip)
        outb(0x88, iobase+0x1f);
 
        /* it appears some maestros (dell 7500) only work if these are set,
-          regardless of wether we use the assp or not. */
+          regardless of whether we use the assp or not. */
 
        outb(0, iobase + ASSP_CONTROL_B);
        outb(3, iobase + ASSP_CONTROL_A);       /* M: Reserved bits... */
@@ -2465,7 +2465,7 @@ static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume);
 
 #ifdef SUPPORT_JOYSTICK
 #define JOYSTICK_ADDR  0x200
-static int __devinit snd_es1968_create_gameport(struct es1968 *chip, int dev)
+static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
 {
        struct gameport *gp;
        struct resource *r;
@@ -2516,7 +2516,7 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
 #endif
 
 #ifdef CONFIG_SND_ES1968_INPUT
-static int __devinit snd_es1968_input_register(struct es1968 *chip)
+static int snd_es1968_input_register(struct es1968 *chip)
 {
        struct input_dev *input_dev;
        int err;
@@ -2653,7 +2653,7 @@ struct ess_device_list {
        unsigned short vendor;  /* subsystem vendor id */
 };
 
-static struct ess_device_list pm_whitelist[] __devinitdata = {
+static struct ess_device_list pm_whitelist[] = {
        { TYPE_MAESTRO2E, 0x0e11 },     /* Compaq Armada */
        { TYPE_MAESTRO2E, 0x1028 },
        { TYPE_MAESTRO2E, 0x103c },
@@ -2664,19 +2664,19 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
        { TYPE_MAESTRO2, 0x125d },      /* a PCI card, e.g. SF64-PCE2 */
 };
 
-static struct ess_device_list mpu_blacklist[] __devinitdata = {
+static struct ess_device_list mpu_blacklist[] = {
        { TYPE_MAESTRO2, 0x125d },
 };
 
-static int __devinit snd_es1968_create(struct snd_card *card,
-                                      struct pci_dev *pci,
-                                      int total_bufsize,
-                                      int play_streams,
-                                      int capt_streams,
-                                      int chip_type,
-                                      int do_pm,
-                                      int radio_nr,
-                                      struct es1968 **chip_ret)
+static int snd_es1968_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            int total_bufsize,
+                            int play_streams,
+                            int capt_streams,
+                            int chip_type,
+                            int do_pm,
+                            int radio_nr,
+                            struct es1968 **chip_ret)
 {
        static struct snd_device_ops ops = {
                .dev_free =     snd_es1968_dev_free,
@@ -2795,8 +2795,8 @@ static int __devinit snd_es1968_create(struct snd_card *card,
 
 /*
  */
-static int __devinit snd_es1968_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_es1968_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -2906,7 +2906,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_es1968_remove(struct pci_dev *pci)
+static void snd_es1968_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2916,7 +2916,7 @@ static struct pci_driver es1968_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_es1968_ids,
        .probe = snd_es1968_probe,
-       .remove = __devexit_p(snd_es1968_remove),
+       .remove = snd_es1968_remove,
        .driver = {
                .pm = ES1968_PM_OPS,
        },
index c5806f89be1ed8b23e0ad5e0ace6344815bb13f2..4f07fda5adf2cc534d2e52a4c2577ea666c2bd39 100644 (file)
@@ -689,7 +689,7 @@ static struct snd_pcm_ops snd_fm801_capture_ops = {
        .pointer =      snd_fm801_capture_pointer,
 };
 
-static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm ** rpcm)
+static int snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -984,7 +984,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
 
 #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
 
-static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_fm801_controls[] = {
 FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1,
                 db_scale_dsp),
 FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1),
@@ -1005,7 +1005,7 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1),
 
 #define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi)
 
-static struct snd_kcontrol_new snd_fm801_controls_multi[] __devinitdata = {
+static struct snd_kcontrol_new snd_fm801_controls_multi[] = {
 FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0),
 FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0),
 FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0),
@@ -1030,7 +1030,7 @@ static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
        }
 }
 
-static int __devinit snd_fm801_mixer(struct fm801 *chip)
+static int snd_fm801_mixer(struct fm801 *chip)
 {
        struct snd_ac97_template ac97;
        unsigned int i;
@@ -1191,11 +1191,11 @@ static int snd_fm801_dev_free(struct snd_device *device)
        return snd_fm801_free(chip);
 }
 
-static int __devinit snd_fm801_create(struct snd_card *card,
-                                     struct pci_dev * pci,
-                                     int tea575x_tuner,
-                                     int radio_nr,
-                                     struct fm801 ** rchip)
+static int snd_fm801_create(struct snd_card *card,
+                           struct pci_dev *pci,
+                           int tea575x_tuner,
+                           int radio_nr,
+                           struct fm801 **rchip)
 {
        struct fm801 *chip;
        int err;
@@ -1296,8 +1296,8 @@ static int __devinit snd_fm801_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
-                                         const struct pci_device_id *pci_id)
+static int snd_card_fm801_probe(struct pci_dev *pci,
+                               const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -1367,7 +1367,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
+static void snd_card_fm801_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1439,7 +1439,7 @@ static struct pci_driver fm801_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_fm801_ids,
        .probe = snd_card_fm801_probe,
-       .remove = __devexit_p(snd_card_fm801_remove),
+       .remove = snd_card_fm801_remove,
        .driver = {
                .pm = SND_FM801_PM_OPS,
        },
index 7105c3de1bca98ff5a975d15d2ba35fc19876d98..6eeb8897624b3b25a3e341e765256a4c8964f973 100644 (file)
@@ -37,8 +37,8 @@ config SND_HDA_HWDEP
          with codecs for debugging purposes.
 
 config SND_HDA_RECONFIG
-       bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)"
-       depends on SND_HDA_HWDEP && EXPERIMENTAL
+       bool "Allow dynamic codec reconfiguration"
+       depends on SND_HDA_HWDEP
        help
          Say Y here to enable the HD-audio codec re-configuration feature.
          This adds the sysfs interfaces to allow user to clear the whole
@@ -72,7 +72,6 @@ config SND_HDA_INPUT_JACK
 
 config SND_HDA_PATCH_LOADER
        bool "Support initialization patch loading for HD-audio"
-       depends on EXPERIMENTAL
        select FW_LOADER
        select SND_HDA_HWDEP
        select SND_HDA_RECONFIG
index bd4149f1aaf45f1f1300563c4aa469d483c2530f..24a251497a1f8ae537aa65de4731fcf1371e8af6 100644 (file)
@@ -8,6 +8,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
 
 # for trace-points
 CFLAGS_hda_codec.o := -I$(src)
+CFLAGS_hda_intel.o := -I$(src)
 
 snd-hda-codec-realtek-objs :=  patch_realtek.o
 snd-hda-codec-cmedia-objs :=   patch_cmedia.o
index 4ec6dc88b7f802a27adcc46ab580630e5c37fda8..7da883a464e327f7880c2974cdb5130770eca75e 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/sort.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
@@ -30,29 +31,30 @@ static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
        return 0;
 }
 
+/* a pair of input pin and its sequence */
+struct auto_out_pin {
+       hda_nid_t pin;
+       short seq;
+};
+
+static int compare_seq(const void *ap, const void *bp)
+{
+       const struct auto_out_pin *a = ap;
+       const struct auto_out_pin *b = bp;
+       return (int)(a->seq - b->seq);
+}
 
 /*
  * Sort an associated group of pins according to their sequence numbers.
+ * then store it to a pin array.
  */
-static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
+static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list,
                                  int num_pins)
 {
-       int i, j;
-       short seq;
-       hda_nid_t nid;
-
-       for (i = 0; i < num_pins; i++) {
-               for (j = i + 1; j < num_pins; j++) {
-                       if (sequences[i] > sequences[j]) {
-                               seq = sequences[i];
-                               sequences[i] = sequences[j];
-                               sequences[j] = seq;
-                               nid = pins[i];
-                               pins[i] = pins[j];
-                               pins[j] = nid;
-                       }
-               }
-       }
+       int i;
+       sort(list, num_pins, sizeof(list[0]), compare_seq, NULL);
+       for (i = 0; i < num_pins; i++)
+               pins[i] = list[i].pin;
 }
 
 
@@ -67,21 +69,11 @@ static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
        }
 }
 
-/* sort inputs in the order of AUTO_PIN_* type */
-static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
+static int compare_input_type(const void *ap, const void *bp)
 {
-       int i, j;
-
-       for (i = 0; i < cfg->num_inputs; i++) {
-               for (j = i + 1; j < cfg->num_inputs; j++) {
-                       if (cfg->inputs[i].type > cfg->inputs[j].type) {
-                               struct auto_pin_cfg_item tmp;
-                               tmp = cfg->inputs[i];
-                               cfg->inputs[i] = cfg->inputs[j];
-                               cfg->inputs[j] = tmp;
-                       }
-               }
-       }
+       const struct auto_pin_cfg_item *a = ap;
+       const struct auto_pin_cfg_item *b = bp;
+       return (int)(a->type - b->type);
 }
 
 /* Reorder the surround channels
@@ -129,16 +121,16 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 {
        hda_nid_t nid, end_nid;
        short seq, assoc_line_out;
-       short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
-       short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
-       short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
+       struct auto_out_pin line_out[ARRAY_SIZE(cfg->line_out_pins)];
+       struct auto_out_pin speaker_out[ARRAY_SIZE(cfg->speaker_pins)];
+       struct auto_out_pin hp_out[ARRAY_SIZE(cfg->hp_pins)];
        int i;
 
        memset(cfg, 0, sizeof(*cfg));
 
-       memset(sequences_line_out, 0, sizeof(sequences_line_out));
-       memset(sequences_speaker, 0, sizeof(sequences_speaker));
-       memset(sequences_hp, 0, sizeof(sequences_hp));
+       memset(line_out, 0, sizeof(line_out));
+       memset(speaker_out, 0, sizeof(speaker_out));
+       memset(hp_out, 0, sizeof(hp_out));
        assoc_line_out = 0;
 
        end_nid = codec->start_nid + codec->num_nodes;
@@ -184,8 +176,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
                                continue;
                        if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
                                continue;
-                       cfg->line_out_pins[cfg->line_outs] = nid;
-                       sequences_line_out[cfg->line_outs] = seq;
+                       line_out[cfg->line_outs].pin = nid;
+                       line_out[cfg->line_outs].seq = seq;
                        cfg->line_outs++;
                        break;
                case AC_JACK_SPEAKER:
@@ -193,8 +185,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
                        assoc = get_defcfg_association(def_conf);
                        if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
                                continue;
-                       cfg->speaker_pins[cfg->speaker_outs] = nid;
-                       sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;
+                       speaker_out[cfg->speaker_outs].pin = nid;
+                       speaker_out[cfg->speaker_outs].seq = (assoc << 4) | seq;
                        cfg->speaker_outs++;
                        break;
                case AC_JACK_HP_OUT:
@@ -202,8 +194,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
                        assoc = get_defcfg_association(def_conf);
                        if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
                                continue;
-                       cfg->hp_pins[cfg->hp_outs] = nid;
-                       sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
+                       hp_out[cfg->hp_outs].pin = nid;
+                       hp_out[cfg->hp_outs].seq = (assoc << 4) | seq;
                        cfg->hp_outs++;
                        break;
                case AC_JACK_MIC_IN:
@@ -248,34 +240,28 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
                int i = 0;
                while (i < cfg->hp_outs) {
                        /* The real HPs should have the sequence 0x0f */
-                       if ((sequences_hp[i] & 0x0f) == 0x0f) {
+                       if ((hp_out[i].seq & 0x0f) == 0x0f) {
                                i++;
                                continue;
                        }
                        /* Move it to the line-out table */
-                       cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
-                       sequences_line_out[cfg->line_outs] = sequences_hp[i];
-                       cfg->line_outs++;
+                       line_out[cfg->line_outs++] = hp_out[i];
                        cfg->hp_outs--;
-                       memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
-                               sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
-                       memmove(sequences_hp + i, sequences_hp + i + 1,
-                               sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
+                       memmove(hp_out + i, hp_out + i + 1,
+                               sizeof(hp_out[0]) * (cfg->hp_outs - i));
                }
-               memset(cfg->hp_pins + cfg->hp_outs, 0,
-                      sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
+               memset(hp_out + cfg->hp_outs, 0,
+                      sizeof(hp_out[0]) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
                if (!cfg->hp_outs)
                        cfg->line_out_type = AUTO_PIN_HP_OUT;
 
        }
 
        /* sort by sequence */
-       sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
-                             cfg->line_outs);
-       sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
+       sort_pins_by_sequence(cfg->line_out_pins, line_out, cfg->line_outs);
+       sort_pins_by_sequence(cfg->speaker_pins, speaker_out,
                              cfg->speaker_outs);
-       sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
-                             cfg->hp_outs);
+       sort_pins_by_sequence(cfg->hp_pins, hp_out, cfg->hp_outs);
 
        /*
         * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
@@ -304,7 +290,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
        reorder_outputs(cfg->hp_outs, cfg->hp_pins);
        reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
 
-       sort_autocfg_input_pins(cfg);
+       /* sort inputs in the order of AUTO_PIN_* type */
+       sort(cfg->inputs, cfg->num_inputs, sizeof(cfg->inputs[0]),
+            compare_input_type, NULL);
 
        /*
         * debug prints of the parsed results
index d010de12335e16525df3219cbe33647262316f7e..8353c77536ac51c0e9ed13ff6fb94732c9e80469 100644 (file)
@@ -738,7 +738,7 @@ static int snd_hda_bus_dev_register(struct snd_device *device)
  *
  * Returns 0 if successful, or a negative error code.
  */
-int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
+int snd_hda_bus_new(struct snd_card *card,
                              const struct hda_bus_template *temp,
                              struct hda_bus **busp)
 {
@@ -908,7 +908,7 @@ static int get_codec_name(struct hda_codec *codec)
 /*
  * look for an AFG and MFG nodes
  */
-static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
+static void setup_fg_nodes(struct hda_codec *codec)
 {
        int i, total_nodes, function_id;
        hda_nid_t nid;
@@ -993,19 +993,6 @@ static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
        return NULL;
 }
 
-/* write a config value for the given NID */
-static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
-                      unsigned int cfg)
-{
-       int i;
-       for (i = 0; i < 4; i++) {
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
-                                   cfg & 0xff);
-               cfg >>= 8;
-       }
-}
-
 /* set the current pin config value for the given NID.
  * the value is cached, and read via snd_hda_codec_get_pincfg()
  */
@@ -1013,12 +1000,10 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
                       hda_nid_t nid, unsigned int cfg)
 {
        struct hda_pincfg *pin;
-       unsigned int oldcfg;
 
        if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
                return -EINVAL;
 
-       oldcfg = snd_hda_codec_get_pincfg(codec, nid);
        pin = look_up_pincfg(codec, list, nid);
        if (!pin) {
                pin = snd_array_new(list);
@@ -1027,13 +1012,6 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
                pin->nid = nid;
        }
        pin->cfg = cfg;
-
-       /* change only when needed; e.g. if the pincfg is already present
-        * in user_pins[], don't write it
-        */
-       cfg = snd_hda_codec_get_pincfg(codec, nid);
-       if (oldcfg != cfg)
-               set_pincfg(codec, nid, cfg);
        return 0;
 }
 
@@ -1082,17 +1060,6 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
 
-/* restore all current pin configs */
-static void restore_pincfgs(struct hda_codec *codec)
-{
-       int i;
-       for (i = 0; i < codec->init_pins.used; i++) {
-               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
-               set_pincfg(codec, pin->nid,
-                          snd_hda_codec_get_pincfg(codec, pin->nid));
-       }
-}
-
 /**
  * snd_hda_shutup_pins - Shut up all pins
  * @codec: the HDA codec
@@ -1137,21 +1104,30 @@ static void restore_shutup_pins(struct hda_codec *codec)
 }
 #endif
 
+static void hda_jackpoll_work(struct work_struct *work)
+{
+       struct hda_codec *codec =
+               container_of(work, struct hda_codec, jackpoll_work.work);
+       if (!codec->jackpoll_interval)
+               return;
+
+       snd_hda_jack_set_dirty_all(codec);
+       snd_hda_jack_poll_all(codec);
+       queue_delayed_work(codec->bus->workq, &codec->jackpoll_work,
+                          codec->jackpoll_interval);
+}
+
 static void init_hda_cache(struct hda_cache_rec *cache,
                           unsigned int record_size);
 static void free_hda_cache(struct hda_cache_rec *cache);
 
-/* restore the initial pin cfgs and release all pincfg lists */
-static void restore_init_pincfgs(struct hda_codec *codec)
+/* release all pincfg lists */
+static void free_init_pincfgs(struct hda_codec *codec)
 {
-       /* first free driver_pins and user_pins, then call restore_pincfg
-        * so that only the values in init_pins are restored
-        */
        snd_array_free(&codec->driver_pins);
 #ifdef CONFIG_SND_HDA_HWDEP
        snd_array_free(&codec->user_pins);
 #endif
-       restore_pincfgs(codec);
        snd_array_free(&codec->init_pins);
 }
 
@@ -1192,8 +1168,9 @@ static void snd_hda_codec_free(struct hda_codec *codec)
 {
        if (!codec)
                return;
+       cancel_delayed_work_sync(&codec->jackpoll_work);
        snd_hda_jack_tbl_clear(codec);
-       restore_init_pincfgs(codec);
+       free_init_pincfgs(codec);
 #ifdef CONFIG_PM
        cancel_delayed_work(&codec->power_work);
        flush_workqueue(codec->bus->workq);
@@ -1235,7 +1212,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
  *
  * Returns 0 if successful, or a negative error code.
  */
-int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
+int snd_hda_codec_new(struct hda_bus *bus,
                                unsigned int codec_addr,
                                struct hda_codec **codecp)
 {
@@ -1275,6 +1252,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
        snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
        snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
        snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
+       snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
+       INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
 
 #ifdef CONFIG_PM
        spin_lock_init(&codec->power_lock);
@@ -1588,7 +1567,7 @@ static void hda_cleanup_all_streams(struct hda_codec *codec)
 #define INFO_AMP_VOL(ch)       (1 << (1 + (ch)))
 
 /* initialize the hash table */
-static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
+static void init_hda_cache(struct hda_cache_rec *cache,
                                     unsigned int record_size)
 {
        memset(cache, 0, sizeof(*cache));
@@ -2153,12 +2132,12 @@ EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
 
 /* find a mixer control element with the given name */
 static struct snd_kcontrol *
-_snd_hda_find_mixer_ctl(struct hda_codec *codec,
-                       const char *name, int idx)
+find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx)
 {
        struct snd_ctl_elem_id id;
        memset(&id, 0, sizeof(id));
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       id.device = dev;
        id.index = idx;
        if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
                return NULL;
@@ -2176,15 +2155,16 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec,
 struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
                                            const char *name)
 {
-       return _snd_hda_find_mixer_ctl(codec, name, 0);
+       return find_mixer_ctl(codec, name, 0, 0);
 }
 EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
 
-static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name)
+static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
+                                   int dev)
 {
        int idx;
        for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
-               if (!_snd_hda_find_mixer_ctl(codec, name, idx))
+               if (!find_mixer_ctl(codec, name, dev, idx))
                        return idx;
        }
        return -EBUSY;
@@ -2351,7 +2331,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
                return -EBUSY;
 
        /* OK, let it free */
-
+       cancel_delayed_work_sync(&codec->jackpoll_work);
 #ifdef CONFIG_PM
        cancel_delayed_work_sync(&codec->power_work);
        codec->power_on = 0;
@@ -2380,7 +2360,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
        /* free only driver_pins so that init_pins + user_pins are restored */
        snd_array_free(&codec->driver_pins);
-       restore_pincfgs(codec);
        snd_array_free(&codec->cvt_setups);
        snd_array_free(&codec->spdif_out);
        codec->num_pcms = 0;
@@ -3135,26 +3114,48 @@ static struct snd_kcontrol_new dig_mixes[] = {
 };
 
 /**
- * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+ * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls
  * @codec: the HDA codec
- * @nid: audio out widget NID
- *
- * Creates controls related with the SPDIF output.
- * Called from each patch supporting the SPDIF out.
+ * @associated_nid: NID that new ctls associated with
+ * @cvt_nid: converter NID
+ * @type: HDA_PCM_TYPE_*
+ * Creates controls related with the digital output.
+ * Called from each patch supporting the digital out.
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
-                                 hda_nid_t associated_nid,
-                                 hda_nid_t cvt_nid)
+int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
+                               hda_nid_t associated_nid,
+                               hda_nid_t cvt_nid,
+                               int type)
 {
        int err;
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_new *dig_mix;
-       int idx;
+       int idx, dev = 0;
+       const int spdif_pcm_dev = 1;
        struct hda_spdif_out *spdif;
 
-       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
+       if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
+           type == HDA_PCM_TYPE_SPDIF) {
+               dev = spdif_pcm_dev;
+       } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
+                  type == HDA_PCM_TYPE_HDMI) {
+               for (idx = 0; idx < codec->spdif_out.used; idx++) {
+                       spdif = snd_array_elem(&codec->spdif_out, idx);
+                       for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+                               kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx);
+                               if (!kctl)
+                                       break;
+                               kctl->id.device = spdif_pcm_dev;
+                       }
+               }
+               codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
+       }
+       if (!codec->primary_dig_out_type)
+               codec->primary_dig_out_type = type;
+
+       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev);
        if (idx < 0) {
                printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
                return -EBUSY;
@@ -3164,6 +3165,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
                kctl = snd_ctl_new1(dig_mix, codec);
                if (!kctl)
                        return -ENOMEM;
+               kctl->id.device = dev;
                kctl->id.index = idx;
                kctl->private_value = codec->spdif_out.used - 1;
                err = snd_hda_ctl_add(codec, associated_nid, kctl);
@@ -3176,7 +3178,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
        spdif->status = convert_to_spdif_status(spdif->ctls);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
+EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
 
 /* get the hda_spdif_out entry from the given NID
  * call within spdif_mutex lock
@@ -3351,7 +3353,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
        struct snd_kcontrol_new *dig_mix;
        int idx;
 
-       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
+       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
        if (idx < 0) {
                printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
                return -EBUSY;
@@ -3650,10 +3652,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
         */
        hda_keep_power_on(codec);
        hda_set_power_state(codec, AC_PWRST_D0);
-       restore_pincfgs(codec); /* restore all current pin configs */
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
-       snd_hda_jack_set_dirty_all(codec);
        if (codec->patch_ops.resume)
                codec->patch_ops.resume(codec);
        else {
@@ -3662,7 +3662,13 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_amp(codec);
                snd_hda_codec_resume_cache(codec);
        }
-       snd_hda_jack_report_sync(codec);
+
+       if (codec->jackpoll_interval)
+               hda_jackpoll_work(&codec->jackpoll_work.work);
+       else {
+               snd_hda_jack_set_dirty_all(codec);
+               snd_hda_jack_report_sync(codec);
+       }
 
        codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
@@ -3678,7 +3684,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
  *
  * Returns 0 if successful, otherwise a negative error code.
  */
-int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
+int snd_hda_build_controls(struct hda_bus *bus)
 {
        struct hda_codec *codec;
 
@@ -3712,13 +3718,14 @@ static int add_std_chmaps(struct hda_codec *codec)
                        struct hda_pcm_stream *hinfo =
                                &codec->pcm_info[i].stream[str];
                        struct snd_pcm_chmap *chmap;
+                       const struct snd_pcm_chmap_elem *elem;
 
                        if (codec->pcm_info[i].own_chmap)
                                continue;
                        if (!pcm || !hinfo->substreams)
                                continue;
-                       err = snd_pcm_add_chmap_ctls(pcm, str,
-                                                    snd_pcm_std_chmaps,
+                       elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
+                       err = snd_pcm_add_chmap_ctls(pcm, str, elem,
                                                     hinfo->channels_max,
                                                     0, &chmap);
                        if (err < 0)
@@ -3729,6 +3736,19 @@ static int add_std_chmaps(struct hda_codec *codec)
        return 0;
 }
 
+/* default channel maps for 2.1 speakers;
+ * since HD-audio supports only stereo, odd number channels are omitted
+ */
+const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = {
+       { .channels = 2,
+         .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+       { .channels = 4,
+         .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+                  SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } },
+       { }
+};
+EXPORT_SYMBOL_GPL(snd_pcm_2_1_chmaps);
+
 int snd_hda_codec_build_controls(struct hda_codec *codec)
 {
        int err = 0;
@@ -3746,7 +3766,10 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
        if (err < 0)
                return err;
 
-       snd_hda_jack_report_sync(codec); /* call at the last init point */
+       if (codec->jackpoll_interval)
+               hda_jackpoll_work(&codec->jackpoll_work.work);
+       else
+               snd_hda_jack_report_sync(codec); /* call at the last init point */
        return 0;
 }
 
@@ -4458,7 +4481,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
                                addr = codec->addr;
                        else if (!idx && !knew->index) {
                                idx = find_empty_mixer_ctl_idx(codec,
-                                                              knew->name);
+                                                              knew->name, 0);
                                if (idx <= 0)
                                        return err;
                        } else
@@ -4770,6 +4793,34 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
 EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
 
 
+/*
+ * process kcontrol info callback of a simple string enum array
+ * when @num_items is 0 or @texts is NULL, assume a boolean enum array
+ */
+int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_info *uinfo,
+                            int num_items, const char * const *texts)
+{
+       static const char * const texts_default[] = {
+               "Disabled", "Enabled"
+       };
+
+       if (!texts || !num_items) {
+               num_items = 2;
+               texts = texts_default;
+       }
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = num_items;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info);
+
 /*
  * Multi-channel / digital-out PCM helper functions
  */
@@ -4778,10 +4829,20 @@ EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
 static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
                                 unsigned int stream_tag, unsigned int format)
 {
-       struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(codec, nid);
-
-       /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
-       if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
+       struct hda_spdif_out *spdif;
+       unsigned int curr_fmt;
+       bool reset;
+
+       spdif = snd_hda_spdif_out_of_nid(codec, nid);
+       curr_fmt = snd_hda_codec_read(codec, nid, 0,
+                                     AC_VERB_GET_STREAM_FORMAT, 0);
+       reset = codec->spdif_status_reset &&
+               (spdif->ctls & AC_DIG1_ENABLE) &&
+               curr_fmt != format;
+
+       /* turn off SPDIF if needed; otherwise the IEC958 bits won't be
+          updated */
+       if (reset)
                set_dig_out_convert(codec, nid,
                                    spdif->ctls & ~AC_DIG1_ENABLE & 0xff,
                                    -1);
@@ -4793,7 +4854,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
                                                   format);
        }
        /* turn on again (if needed) */
-       if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
+       if (reset)
                set_dig_out_convert(codec, nid,
                                    spdif->ctls & 0xff, -1);
 }
@@ -5137,6 +5198,7 @@ int snd_hda_suspend(struct hda_bus *bus)
        struct hda_codec *codec;
 
        list_for_each_entry(codec, &bus->codec_list, list) {
+               cancel_delayed_work_sync(&codec->jackpoll_work);
                if (hda_codec_is_power_on(codec))
                        hda_call_codec_suspend(codec, false);
        }
index 4f4e545c0f4b2ded6029d21851b3443973ea7d23..8665540e55aa7cd1cce19a1cdb405dbcd2ffbbfa 100644 (file)
@@ -757,6 +757,7 @@ struct hda_pcm_stream {
        u32 rates;      /* supported rates */
        u64 formats;    /* supported formats (SNDRV_PCM_FMTBIT_) */
        unsigned int maxbps;    /* supported max. bit per sample */
+       const struct snd_pcm_chmap_elem *chmap; /* chmap to override */
        struct hda_pcm_ops ops;
 };
 
@@ -836,6 +837,7 @@ struct hda_codec {
        struct mutex hash_mutex;
        struct snd_array spdif_out;
        unsigned int spdif_in_enable;   /* SPDIF input enable? */
+       int primary_dig_out_type;       /* primary digital out PCM type */
        const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
        struct snd_array init_pins;     /* initial (BIOS) pin configurations */
        struct snd_array driver_pins;   /* pin configs set by codec parser */
@@ -885,6 +887,8 @@ struct hda_codec {
 
        /* jack detection */
        struct snd_array jacktbl;
+       unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */
+       struct delayed_work jackpoll_work;
 
 #ifdef CONFIG_SND_HDA_INPUT_JACK
        /* jack detection */
@@ -1024,6 +1028,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
                                unsigned int format);
 
+extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[];
+
 /*
  * Misc
  */
index 1af86d40eb2396b7dde509052beb8b0180bd0f8e..a5c9411bb3670f7a095e7bc70b8ad0b90a27d4ae 100644 (file)
@@ -125,7 +125,7 @@ static void hwdep_free(struct snd_hwdep *hwdep)
        clear_hwdep_elements(hwdep->private_data);
 }
 
-int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
+int snd_hda_create_hwdep(struct hda_codec *codec)
 {
        char hwname[16];
        struct snd_hwdep *hwdep;
index f9d870e554d98d2fabe8791e904d7a393c8925e6..0f3d3db0df71a3110d48643ab0dd214ca0897cd3 100644 (file)
 #include <linux/reboot.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/completion.h>
+
 #ifdef CONFIG_X86
 /* for snoop control */
 #include <asm/pgtable.h>
@@ -68,6 +72,7 @@ static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_only[SNDRV_CARDS];
+static int jackpoll_ms[SNDRV_CARDS];
 static bool single_cmd;
 static int enable_msi = -1;
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
@@ -95,6 +100,8 @@ module_param_array(probe_mask, int, NULL, 0444);
 MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
 module_param_array(probe_only, int, NULL, 0444);
 MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
+module_param_array(jackpoll_ms, int, NULL, 0444);
+MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
 module_param(single_cmd, bool, 0444);
 MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
                 "(for debugging only).");
@@ -185,7 +192,7 @@ MODULE_DESCRIPTION("Intel HDA driver");
 #ifdef CONFIG_SND_VERBOSE_PRINTK
 #define SFX    /* nop */
 #else
-#define SFX    "hda-intel: "
+#define SFX    "hda-intel "
 #endif
 
 #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO)
@@ -416,6 +423,9 @@ struct azx_dev {
        unsigned int insufficient :1;
        unsigned int wc_marked:1;
        unsigned int no_period_wakeup:1;
+
+       struct timecounter  azx_tc;
+       struct cyclecounter azx_cc;
 };
 
 /* CORB/RIRB */
@@ -460,6 +470,7 @@ struct azx {
        /* locks */
        spinlock_t reg_lock;
        struct mutex open_mutex;
+       struct completion probe_wait;
 
        /* streams (x num_streams) */
        struct azx_dev *azx_dev;
@@ -518,6 +529,9 @@ struct azx {
        struct list_head list;
 };
 
+#define CREATE_TRACE_POINTS
+#include "hda_intel_trace.h"
+
 /* driver types */
 enum {
        AZX_DRIVER_ICH,
@@ -589,15 +603,7 @@ enum {
 #define use_vga_switcheroo(chip)       0
 #endif
 
-#if defined(SUPPORT_VGA_SWITCHEROO) || defined(CONFIG_SND_HDA_PATCH_LOADER)
-#define DELAYED_INIT_MARK
-#define DELAYED_INITDATA_MARK
-#else
-#define DELAYED_INIT_MARK      __devinit
-#define DELAYED_INITDATA_MARK  __devinitdata
-#endif
-
-static char *driver_short_names[] DELAYED_INITDATA_MARK = {
+static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
        [AZX_DRIVER_PCH] = "HDA Intel PCH",
        [AZX_DRIVER_SCH] = "HDA Intel MID",
@@ -703,7 +709,7 @@ static int azx_alloc_cmd_io(struct azx *chip)
                                  snd_dma_pci_data(chip->pci),
                                  PAGE_SIZE, &chip->rb);
        if (err < 0) {
-               snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
+               snd_printk(KERN_ERR SFX "%s: cannot allocate CORB/RIRB\n", pci_name(chip->pci));
                return err;
        }
        mark_pages_wc(chip, &chip->rb, true);
@@ -793,7 +799,12 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
        spin_lock_irq(&chip->reg_lock);
 
        /* add command to corb */
-       wp = azx_readb(chip, CORBWP);
+       wp = azx_readw(chip, CORBWP);
+       if (wp == 0xffff) {
+               /* something wrong, controller likely turned to D3 */
+               spin_unlock_irq(&chip->reg_lock);
+               return -1;
+       }
        wp++;
        wp %= ICH6_MAX_CORB_ENTRIES;
 
@@ -815,7 +826,12 @@ static void azx_update_rirb(struct azx *chip)
        unsigned int addr;
        u32 res, res_ex;
 
-       wp = azx_readb(chip, RIRBWP);
+       wp = azx_readw(chip, RIRBWP);
+       if (wp == 0xffff) {
+               /* something wrong, controller likely turned to D3 */
+               return;
+       }
+
        if (wp == chip->rirb.wp)
                return;
        chip->rirb.wp = wp;
@@ -835,8 +851,9 @@ static void azx_update_rirb(struct azx *chip)
                        smp_wmb();
                        chip->rirb.cmds[addr]--;
                } else
-                       snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
+                       snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, "
                                   "last cmd=%#08x\n",
+                                  pci_name(chip->pci),
                                   res, res_ex,
                                   chip->last_cmd[addr]);
        }
@@ -879,9 +896,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
        }
 
        if (!chip->polling_mode && chip->poll_count < 2) {
-               snd_printdd(SFX "azx_get_response timeout, "
+               snd_printdd(SFX "%s: azx_get_response timeout, "
                           "polling the codec once: last cmd=0x%08x\n",
-                          chip->last_cmd[addr]);
+                          pci_name(chip->pci), chip->last_cmd[addr]);
                do_poll = 1;
                chip->poll_count++;
                goto again;
@@ -889,17 +906,17 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
 
 
        if (!chip->polling_mode) {
-               snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
+               snd_printk(KERN_WARNING SFX "%s: azx_get_response timeout, "
                           "switching to polling mode: last cmd=0x%08x\n",
-                          chip->last_cmd[addr]);
+                          pci_name(chip->pci), chip->last_cmd[addr]);
                chip->polling_mode = 1;
                goto again;
        }
 
        if (chip->msi) {
-               snd_printk(KERN_WARNING SFX "No response from codec, "
+               snd_printk(KERN_WARNING SFX "%s: No response from codec, "
                           "disabling MSI: last cmd=0x%08x\n",
-                          chip->last_cmd[addr]);
+                          pci_name(chip->pci), chip->last_cmd[addr]);
                free_irq(chip->irq, chip);
                chip->irq = -1;
                pci_disable_msi(chip->pci);
@@ -965,8 +982,8 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
                udelay(1);
        }
        if (printk_ratelimit())
-               snd_printd(SFX "get_response timeout: IRS=0x%x\n",
-                          azx_readw(chip, IRS));
+               snd_printd(SFX "%s: get_response timeout: IRS=0x%x\n",
+                          pci_name(chip->pci), azx_readw(chip, IRS));
        chip->rirb.res[addr] = -1;
        return -EIO;
 }
@@ -993,8 +1010,8 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
                udelay(1);
        }
        if (printk_ratelimit())
-               snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n",
-                          azx_readw(chip, IRS), val);
+               snd_printd(SFX "%s: send_cmd timeout: IRS=0x%x, val=0x%x\n",
+                          pci_name(chip->pci), azx_readw(chip, IRS), val);
        return -EIO;
 }
 
@@ -1047,7 +1064,7 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up);
 /* reset codec link */
 static int azx_reset(struct azx *chip, int full_reset)
 {
-       int count;
+       unsigned long timeout;
 
        if (!full_reset)
                goto __skip;
@@ -1058,29 +1075,31 @@ static int azx_reset(struct azx *chip, int full_reset)
        /* reset controller */
        azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
 
-       count = 50;
-       while (azx_readb(chip, GCTL) && --count)
-               msleep(1);
+       timeout = jiffies + msecs_to_jiffies(100);
+       while (azx_readb(chip, GCTL) &&
+                       time_before(jiffies, timeout))
+               usleep_range(500, 1000);
 
        /* delay for >= 100us for codec PLL to settle per spec
         * Rev 0.9 section 5.5.1
         */
-       msleep(1);
+       usleep_range(500, 1000);
 
        /* Bring controller out of reset */
        azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
 
-       count = 50;
-       while (!azx_readb(chip, GCTL) && --count)
-               msleep(1);
+       timeout = jiffies + msecs_to_jiffies(100);
+       while (!azx_readb(chip, GCTL) &&
+                       time_before(jiffies, timeout))
+               usleep_range(500, 1000);
 
        /* Brent Chartrand said to wait >= 540us for codecs to initialize */
-       msleep(1);
+       usleep_range(1000, 1200);
 
       __skip:
        /* check to see if controller is ready */
        if (!azx_readb(chip, GCTL)) {
-               snd_printd(SFX "azx_reset: controller not ready!\n");
+               snd_printd(SFX "%s: azx_reset: controller not ready!\n", pci_name(chip->pci));
                return -EBUSY;
        }
 
@@ -1092,7 +1111,7 @@ static int azx_reset(struct azx *chip, int full_reset)
        /* detect codecs */
        if (!chip->codec_mask) {
                chip->codec_mask = azx_readw(chip, STATESTS);
-               snd_printdd(SFX "codec_mask = 0x%x\n", chip->codec_mask);
+               snd_printdd(SFX "%s: codec_mask = 0x%x\n", pci_name(chip->pci), chip->codec_mask);
        }
 
        return 0;
@@ -1236,7 +1255,7 @@ static void azx_init_pci(struct azx *chip)
         * The PCI register TCSEL is defined in the Intel manuals.
         */
        if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
-               snd_printdd(SFX "Clearing TCSEL\n");
+               snd_printdd(SFX "%s: Clearing TCSEL\n", pci_name(chip->pci));
                update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
        }
 
@@ -1244,7 +1263,7 @@ static void azx_init_pci(struct azx *chip)
         * we need to enable snoop.
         */
        if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) {
-               snd_printdd(SFX "Setting ATI snoop: %d\n", azx_snoop(chip));
+               snd_printdd(SFX "%s: Setting ATI snoop: %d\n", pci_name(chip->pci), azx_snoop(chip));
                update_pci_byte(chip->pci,
                                ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07,
                                azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0);
@@ -1252,7 +1271,7 @@ static void azx_init_pci(struct azx *chip)
 
        /* For NVIDIA HDA, enable snoop */
        if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) {
-               snd_printdd(SFX "Setting Nvidia snoop: %d\n", azx_snoop(chip));
+               snd_printdd(SFX "%s: Setting Nvidia snoop: %d\n", pci_name(chip->pci), azx_snoop(chip));
                update_pci_byte(chip->pci,
                                NVIDIA_HDA_TRANSREG_ADDR,
                                0x0f, NVIDIA_HDA_ENABLE_COHBITS);
@@ -1277,8 +1296,8 @@ static void azx_init_pci(struct azx *chip)
                        pci_read_config_word(chip->pci,
                                INTEL_SCH_HDA_DEVC, &snoop);
                }
-               snd_printdd(SFX "SCH snoop: %s\n",
-                               (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
+               snd_printdd(SFX "%s: SCH snoop: %s\n",
+                               pci_name(chip->pci), (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
                                ? "Disabled" : "Enabled");
         }
 }
@@ -1438,8 +1457,8 @@ static int azx_setup_periods(struct azx *chip,
                                pos_align;
                pos_adj = frames_to_bytes(runtime, pos_adj);
                if (pos_adj >= period_bytes) {
-                       snd_printk(KERN_WARNING SFX "Too big adjustment %d\n",
-                                  bdl_pos_adj[chip->dev_index]);
+                       snd_printk(KERN_WARNING SFX "%s: Too big adjustment %d\n",
+                                  pci_name(chip->pci), bdl_pos_adj[chip->dev_index]);
                        pos_adj = 0;
                } else {
                        ofs = setup_bdle(chip, substream, azx_dev,
@@ -1463,8 +1482,8 @@ static int azx_setup_periods(struct azx *chip,
        return 0;
 
  error:
-       snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n",
-                  azx_dev->bufsize, period_bytes);
+       snd_printk(KERN_ERR SFX "%s: Too many BDL entries: buffer=%d, period=%d\n",
+                  pci_name(chip->pci), azx_dev->bufsize, period_bytes);
        return -EINVAL;
 }
 
@@ -1561,7 +1580,7 @@ static int probe_codec(struct azx *chip, int addr)
        mutex_unlock(&chip->bus->cmd_mutex);
        if (res == -1)
                return -EIO;
-       snd_printdd(SFX "codec #%d probed OK\n", addr);
+       snd_printdd(SFX "%s: codec #%d probed OK\n", pci_name(chip->pci), addr);
        return 0;
 }
 
@@ -1588,17 +1607,33 @@ static void azx_bus_reset(struct hda_bus *bus)
        bus->in_reset = 0;
 }
 
+static int get_jackpoll_interval(struct azx *chip)
+{
+       int i = jackpoll_ms[chip->dev_index];
+       unsigned int j;
+       if (i == 0)
+               return 0;
+       if (i < 50 || i > 60000)
+               j = 0;
+       else
+               j = msecs_to_jiffies(i);
+       if (j == 0)
+               snd_printk(KERN_WARNING SFX
+                          "jackpoll_ms value out of range: %d\n", i);
+       return j;
+}
+
 /*
  * Codec initialization
  */
 
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
-static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] DELAYED_INITDATA_MARK = {
+static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
        [AZX_DRIVER_NVIDIA] = 8,
        [AZX_DRIVER_TERA] = 1,
 };
 
-static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *model)
+static int azx_codec_create(struct azx *chip, const char *model)
 {
        struct hda_bus_template bus_temp;
        int c, codecs, err;
@@ -1622,7 +1657,7 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
                return err;
 
        if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
-               snd_printd(SFX "Enable delay in RIRB handling\n");
+               snd_printd(SFX "%s: Enable delay in RIRB handling\n", pci_name(chip->pci));
                chip->bus->needs_damn_long_delay = 1;
        }
 
@@ -1639,8 +1674,8 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
                                 * that don't exist
                                 */
                                snd_printk(KERN_WARNING SFX
-                                          "Codec #%d probe error; "
-                                          "disabling it...\n", c);
+                                          "%s: Codec #%d probe error; "
+                                          "disabling it...\n", pci_name(chip->pci), c);
                                chip->codec_mask &= ~(1 << c);
                                /* More badly, accessing to a non-existing
                                 * codec often screws up the controller chip,
@@ -1660,7 +1695,8 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
         * access works around the stall.  Grrr...
         */
        if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) {
-               snd_printd(SFX "Enable sync_write for stable communication\n");
+               snd_printd(SFX "%s: Enable sync_write for stable communication\n",
+                       pci_name(chip->pci));
                chip->bus->sync_write = 1;
                chip->bus->allow_bus_reset = 1;
        }
@@ -1672,19 +1708,20 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
                        err = snd_hda_codec_new(chip->bus, c, &codec);
                        if (err < 0)
                                continue;
+                       codec->jackpoll_interval = get_jackpoll_interval(chip);
                        codec->beep_mode = chip->beep_mode;
                        codecs++;
                }
        }
        if (!codecs) {
-               snd_printk(KERN_ERR SFX "no codecs initialized\n");
+               snd_printk(KERN_ERR SFX "%s: no codecs initialized\n", pci_name(chip->pci));
                return -ENXIO;
        }
        return 0;
 }
 
 /* configure each codec instance */
-static int __devinit azx_codec_configure(struct azx *chip)
+static int azx_codec_configure(struct azx *chip)
 {
        struct hda_codec *codec;
        list_for_each_entry(codec, &chip->bus->codec_list, list) {
@@ -1734,6 +1771,64 @@ static inline void azx_release_device(struct azx_dev *azx_dev)
        azx_dev->opened = 0;
 }
 
+static cycle_t azx_cc_read(const struct cyclecounter *cc)
+{
+       struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc);
+       struct snd_pcm_substream *substream = azx_dev->substream;
+       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+       struct azx *chip = apcm->chip;
+
+       return azx_readl(chip, WALLCLK);
+}
+
+static void azx_timecounter_init(struct snd_pcm_substream *substream,
+                               bool force, cycle_t last)
+{
+       struct azx_dev *azx_dev = get_azx_dev(substream);
+       struct timecounter *tc = &azx_dev->azx_tc;
+       struct cyclecounter *cc = &azx_dev->azx_cc;
+       u64 nsec;
+
+       cc->read = azx_cc_read;
+       cc->mask = CLOCKSOURCE_MASK(32);
+
+       /*
+        * Converting from 24 MHz to ns means applying a 125/3 factor.
+        * To avoid any saturation issues in intermediate operations,
+        * the 125 factor is applied first. The division is applied
+        * last after reading the timecounter value.
+        * Applying the 1/3 factor as part of the multiplication
+        * requires at least 20 bits for a decent precision, however
+        * overflows occur after about 4 hours or less, not a option.
+        */
+
+       cc->mult = 125; /* saturation after 195 years */
+       cc->shift = 0;
+
+       nsec = 0; /* audio time is elapsed time since trigger */
+       timecounter_init(tc, cc, nsec);
+       if (force)
+               /*
+                * force timecounter to use predefined value,
+                * used for synchronized starts
+                */
+               tc->cycle_last = last;
+}
+
+static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
+                               struct timespec *ts)
+{
+       struct azx_dev *azx_dev = get_azx_dev(substream);
+       u64 nsec;
+
+       nsec = timecounter_read(&azx_dev->azx_tc);
+       nsec = div_u64(nsec, 3); /* can be optimized */
+
+       *ts = ns_to_timespec(nsec);
+
+       return 0;
+}
+
 static struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP |
                                 SNDRV_PCM_INFO_INTERLEAVED |
@@ -1743,6 +1838,7 @@ static struct snd_pcm_hardware azx_pcm_hw = {
                                 /* SNDRV_PCM_INFO_RESUME |*/
                                 SNDRV_PCM_INFO_PAUSE |
                                 SNDRV_PCM_INFO_SYNC_START |
+                                SNDRV_PCM_INFO_HAS_WALL_CLOCK |
                                 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
        .rates =                SNDRV_PCM_RATE_48000,
@@ -1782,6 +1878,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        runtime->hw.rates = hinfo->rates;
        snd_pcm_limit_hw_rates(runtime);
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+       /* avoid wrap-around with wall-clock */
+       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
+                               20,
+                               178000000);
+
        if (chip->align_buffer_size)
                /* constrain buffer sizes to be multiple of 128
                   bytes. This is more efficient in terms of memory
@@ -1821,6 +1923,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                mutex_unlock(&chip->open_mutex);
                return -EINVAL;
        }
+
+       /* disable WALLCLOCK timestamps for capture streams
+          until we figure out how to handle digital inputs */
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK;
+
        spin_lock_irqsave(&chip->reg_lock, flags);
        azx_dev->substream = substream;
        azx_dev->running = 0;
@@ -1916,16 +2024,16 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                                                ctls);
        if (!format_val) {
                snd_printk(KERN_ERR SFX
-                          "invalid format_val, rate=%d, ch=%d, format=%d\n",
-                          runtime->rate, runtime->channels, runtime->format);
+                          "%s: invalid format_val, rate=%d, ch=%d, format=%d\n",
+                          pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format);
                return -EINVAL;
        }
 
        bufsize = snd_pcm_lib_buffer_bytes(substream);
        period_bytes = snd_pcm_lib_period_bytes(substream);
 
-       snd_printdd(SFX "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
-                   bufsize, format_val);
+       snd_printdd(SFX "%s: azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
+                   pci_name(chip->pci), bufsize, format_val);
 
        if (bufsize != azx_dev->bufsize ||
            period_bytes != azx_dev->period_bytes ||
@@ -1967,6 +2075,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        int rstart = 0, start, nsync = 0, sbits = 0;
        int nwait, timeout;
 
+       azx_dev = get_azx_dev(substream);
+       trace_azx_pcm_trigger(chip, azx_dev, cmd);
+
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                rstart = 1;
@@ -2057,6 +2168,22 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                        azx_readl(chip, OLD_SSYNC) & ~sbits);
        else
                azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits);
+       if (start) {
+               azx_timecounter_init(substream, 0, 0);
+               if (nsync > 1) {
+                       cycle_t cycle_last;
+
+                       /* same start cycle for master and group */
+                       azx_dev = get_azx_dev(substream);
+                       cycle_last = azx_dev->azx_tc.cycle_last;
+
+                       snd_pcm_group_for_each_entry(s, substream) {
+                               if (s->pcm->card != substream->pcm->card)
+                                       continue;
+                               azx_timecounter_init(s, 1, cycle_last);
+                       }
+               }
+       }
        spin_unlock(&chip->reg_lock);
        return 0;
 }
@@ -2123,6 +2250,7 @@ static unsigned int azx_get_position(struct azx *chip,
 {
        unsigned int pos;
        int stream = azx_dev->substream->stream;
+       int delay = 0;
 
        switch (chip->position_fix[stream]) {
        case POS_FIX_LPIB:
@@ -2156,7 +2284,6 @@ static unsigned int azx_get_position(struct azx *chip,
            chip->position_fix[stream] == POS_FIX_POSBUF &&
            (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
                unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
-               int delay;
                if (stream == SNDRV_PCM_STREAM_PLAYBACK)
                        delay = pos - lpib_pos;
                else
@@ -2165,15 +2292,16 @@ static unsigned int azx_get_position(struct azx *chip,
                        delay += azx_dev->bufsize;
                if (delay >= azx_dev->period_bytes) {
                        snd_printk(KERN_WARNING SFX
-                                  "Unstable LPIB (%d >= %d); "
+                                  "%s: Unstable LPIB (%d >= %d); "
                                   "disabling LPIB delay counting\n",
-                                  delay, azx_dev->period_bytes);
+                                  pci_name(chip->pci), delay, azx_dev->period_bytes);
                        delay = 0;
                        chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
                }
                azx_dev->substream->runtime->delay =
                        bytes_to_frames(azx_dev->substream->runtime, delay);
        }
+       trace_azx_get_position(chip, azx_dev, pos, delay);
        return pos;
 }
 
@@ -2199,13 +2327,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 {
        u32 wallclk;
        unsigned int pos;
-       int stream;
 
        wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk;
        if (wallclk < (azx_dev->period_wallclk * 2) / 3)
                return -1;      /* bogus (too early) interrupt */
 
-       stream = azx_dev->substream->stream;
        pos = azx_get_position(chip, azx_dev, true);
 
        if (WARN_ONCE(!azx_dev->period_bytes,
@@ -2296,6 +2422,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
        .prepare = azx_pcm_prepare,
        .trigger = azx_pcm_trigger,
        .pointer = azx_pcm_pointer,
+       .wall_clock =  azx_get_wallclock_tstamp,
        .mmap = azx_pcm_mmap,
        .page = snd_pcm_sgbuf_ops_page,
 };
@@ -2324,7 +2451,8 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
 
        list_for_each_entry(apcm, &chip->pcm_list, list) {
                if (apcm->pcm->device == pcm_dev) {
-                       snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);
+                       snd_printk(KERN_ERR SFX "%s: PCM %d already exists\n",
+                                  pci_name(chip->pci), pcm_dev);
                        return -EBUSY;
                }
        }
@@ -2365,7 +2493,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
 /*
  * mixer creation - all stuff is implemented in hda module
  */
-static int __devinit azx_mixer_create(struct azx *chip)
+static int azx_mixer_create(struct azx *chip)
 {
        return snd_hda_build_controls(chip->bus);
 }
@@ -2374,7 +2502,7 @@ static int __devinit azx_mixer_create(struct azx *chip)
 /*
  * initialize SD streams
  */
-static int __devinit azx_init_stream(struct azx *chip)
+static int azx_init_stream(struct azx *chip)
 {
        int i;
 
@@ -2502,6 +2630,9 @@ static int azx_suspend(struct device *dev)
        struct azx *chip = card->private_data;
        struct azx_pcm *p;
 
+       if (chip->disabled)
+               return 0;
+
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
        azx_clear_irq_pending(chip);
        list_for_each_entry(p, &chip->pcm_list, list)
@@ -2527,6 +2658,9 @@ static int azx_resume(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
+       if (chip->disabled)
+               return 0;
+
        pci_set_power_state(pci, PCI_D0);
        pci_restore_state(pci);
        if (pci_enable_device(pci) < 0) {
@@ -2557,10 +2691,6 @@ static int azx_runtime_suspend(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (!power_save_controller ||
-           !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
-               return -EAGAIN;
-
        azx_stop_chip(chip);
        azx_clear_irq_pending(chip);
        return 0;
@@ -2575,12 +2705,25 @@ static int azx_runtime_resume(struct device *dev)
        azx_init_chip(chip, 1);
        return 0;
 }
+
+static int azx_runtime_idle(struct device *dev)
+{
+       struct snd_card *card = dev_get_drvdata(dev);
+       struct azx *chip = card->private_data;
+
+       if (!power_save_controller ||
+           !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+               return -EBUSY;
+
+       return 0;
+}
+
 #endif /* CONFIG_PM_RUNTIME */
 
 #ifdef CONFIG_PM
 static const struct dev_pm_ops azx_pm = {
        SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
-       SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, NULL)
+       SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
 };
 
 #define AZX_PM_OPS     &azx_pm
@@ -2612,11 +2755,11 @@ static void azx_notifier_unregister(struct azx *chip)
                unregister_reboot_notifier(&chip->reboot_notifier);
 }
 
-static int DELAYED_INIT_MARK azx_first_init(struct azx *chip);
-static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip);
+static int azx_first_init(struct azx *chip);
+static int azx_probe_continue(struct azx *chip);
 
 #ifdef SUPPORT_VGA_SWITCHEROO
-static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci);
+static struct pci_dev *get_bound_vga(struct pci_dev *pci);
 
 static void azx_vs_set_state(struct pci_dev *pci,
                             enum vga_switcheroo_state state)
@@ -2625,6 +2768,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
        struct azx *chip = card->private_data;
        bool disabled;
 
+       wait_for_completion(&chip->probe_wait);
        if (chip->init_failed)
                return;
 
@@ -2648,15 +2792,14 @@ static void azx_vs_set_state(struct pci_dev *pci,
                }
        } else {
                snd_printk(KERN_INFO SFX
-                          "%s %s via VGA-switcheroo\n",
-                          disabled ? "Disabling" : "Enabling",
-                          pci_name(chip->pci));
+                          "%s: %s via VGA-switcheroo\n", pci_name(chip->pci),
+                          disabled ? "Disabling" : "Enabling");
                if (disabled) {
                        azx_suspend(&pci->dev);
                        chip->disabled = true;
                        if (snd_hda_lock_devices(chip->bus))
-                               snd_printk(KERN_WARNING SFX
-                                          "Cannot lock devices!\n");
+                               snd_printk(KERN_WARNING SFX "%s: Cannot lock devices!\n",
+                                          pci_name(chip->pci));
                } else {
                        snd_hda_unlock_devices(chip->bus);
                        chip->disabled = false;
@@ -2670,6 +2813,7 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
        struct snd_card *card = pci_get_drvdata(pci);
        struct azx *chip = card->private_data;
 
+       wait_for_completion(&chip->probe_wait);
        if (chip->init_failed)
                return false;
        if (chip->disabled || !chip->bus)
@@ -2680,7 +2824,7 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
        return true;
 }
 
-static void __devinit init_vga_switcheroo(struct azx *chip)
+static void init_vga_switcheroo(struct azx *chip)
 {
        struct pci_dev *p = get_bound_vga(chip->pci);
        if (p) {
@@ -2697,7 +2841,7 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
        .can_switch = azx_vs_can_switch,
 };
 
-static int __devinit register_vga_switcheroo(struct azx *chip)
+static int register_vga_switcheroo(struct azx *chip)
 {
        int err;
 
@@ -2731,6 +2875,9 @@ static int azx_free(struct azx *chip)
 
        azx_notifier_unregister(chip);
 
+       chip->init_failed = 1; /* to be sure */
+       complete(&chip->probe_wait);
+
        if (use_vga_switcheroo(chip)) {
                if (chip->disabled && chip->bus)
                        snd_hda_unlock_devices(chip->bus);
@@ -2789,7 +2936,7 @@ static int azx_dev_free(struct snd_device *device)
 /*
  * Check of disabled HDMI controller by vga-switcheroo
  */
-static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci)
+static struct pci_dev *get_bound_vga(struct pci_dev *pci)
 {
        struct pci_dev *p;
 
@@ -2812,7 +2959,7 @@ static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci)
        return NULL;
 }
 
-static bool __devinit check_hdmi_disabled(struct pci_dev *pci)
+static bool check_hdmi_disabled(struct pci_dev *pci)
 {
        bool vga_inactive = false;
        struct pci_dev *p = get_bound_vga(pci);
@@ -2829,7 +2976,7 @@ static bool __devinit check_hdmi_disabled(struct pci_dev *pci)
 /*
  * white/black-listing for position_fix
  */
-static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+static struct snd_pci_quirk position_fix_list[] = {
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
@@ -2847,7 +2994,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        {}
 };
 
-static int __devinit check_position_fix(struct azx *chip, int fix)
+static int check_position_fix(struct azx *chip, int fix)
 {
        const struct snd_pci_quirk *q;
 
@@ -2871,11 +3018,11 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
 
        /* Check VIA/ATI HD Audio Controller exist */
        if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) {
-               snd_printd(SFX "Using VIACOMBO position fix\n");
+               snd_printd(SFX "%s: Using VIACOMBO position fix\n", pci_name(chip->pci));
                return POS_FIX_VIACOMBO;
        }
        if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
-               snd_printd(SFX "Using LPIB position fix\n");
+               snd_printd(SFX "%s: Using LPIB position fix\n", pci_name(chip->pci));
                return POS_FIX_LPIB;
        }
        return POS_FIX_AUTO;
@@ -2884,7 +3031,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
 /*
  * black-lists for probe_mask
  */
-static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
+static struct snd_pci_quirk probe_mask_list[] = {
        /* Thinkpad often breaks the controller communication when accessing
         * to the non-working (or non-existing) modem codec slot.
         */
@@ -2905,7 +3052,7 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
 
 #define AZX_FORCE_CODEC_MASK   0x100
 
-static void __devinit check_probe_mask(struct azx *chip, int dev)
+static void check_probe_mask(struct azx *chip, int dev)
 {
        const struct snd_pci_quirk *q;
 
@@ -2933,7 +3080,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
 /*
  * white/black-list for enable_msi
  */
-static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+static struct snd_pci_quirk msi_black_list[] = {
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
@@ -2942,7 +3089,7 @@ static struct snd_pci_quirk msi_black_list[] __devinitdata = {
        {}
 };
 
-static void __devinit check_msi(struct azx *chip)
+static void check_msi(struct azx *chip)
 {
        const struct snd_pci_quirk *q;
 
@@ -2968,7 +3115,7 @@ static void __devinit check_msi(struct azx *chip)
 }
 
 /* check the snoop mode availability */
-static void __devinit azx_check_snoop_available(struct azx *chip)
+static void azx_check_snoop_available(struct azx *chip)
 {
        bool snoop = chip->snoop;
 
@@ -2991,8 +3138,8 @@ static void __devinit azx_check_snoop_available(struct azx *chip)
        }
 
        if (snoop != chip->snoop) {
-               snd_printk(KERN_INFO SFX "Force to %s mode\n",
-                          snoop ? "snoop" : "non-snoop");
+               snd_printk(KERN_INFO SFX "%s: Force to %s mode\n",
+                          pci_name(chip->pci), snoop ? "snoop" : "non-snoop");
                chip->snoop = snoop;
        }
 }
@@ -3000,9 +3147,9 @@ static void __devinit azx_check_snoop_available(struct azx *chip)
 /*
  * constructor
  */
-static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
-                               int dev, unsigned int driver_caps,
-                               struct azx **rchip)
+static int azx_create(struct snd_card *card, struct pci_dev *pci,
+                     int dev, unsigned int driver_caps,
+                     struct azx **rchip)
 {
        static struct snd_device_ops ops = {
                .dev_free = azx_dev_free,
@@ -3018,7 +3165,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (!chip) {
-               snd_printk(KERN_ERR SFX "cannot allocate chip\n");
+               snd_printk(KERN_ERR SFX "%s: Cannot allocate chip\n", pci_name(pci));
                pci_disable_device(pci);
                return -ENOMEM;
        }
@@ -3036,6 +3183,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        INIT_LIST_HEAD(&chip->pcm_list);
        INIT_LIST_HEAD(&chip->list);
        init_vga_switcheroo(chip);
+       init_completion(&chip->probe_wait);
 
        chip->position_fix[0] = chip->position_fix[1] =
                check_position_fix(chip, position_fix[dev]);
@@ -3063,29 +3211,10 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                }
        }
 
-       if (check_hdmi_disabled(pci)) {
-               snd_printk(KERN_INFO SFX "VGA controller for %s is disabled\n",
-                          pci_name(pci));
-               if (use_vga_switcheroo(chip)) {
-                       snd_printk(KERN_INFO SFX "Delaying initialization\n");
-                       chip->disabled = true;
-                       goto ok;
-               }
-               kfree(chip);
-               pci_disable_device(pci);
-               return -ENXIO;
-       }
-
-       err = azx_first_init(chip);
-       if (err < 0) {
-               azx_free(chip);
-               return err;
-       }
-
- ok:
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0) {
-               snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
+               snd_printk(KERN_ERR SFX "%s: Error creating device [card]!\n",
+                  pci_name(chip->pci));
                azx_free(chip);
                return err;
        }
@@ -3094,7 +3223,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        return 0;
 }
 
-static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
+static int azx_first_init(struct azx *chip)
 {
        int dev = chip->dev_index;
        struct pci_dev *pci = chip->pci;
@@ -3120,7 +3249,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
        chip->addr = pci_resource_start(pci, 0);
        chip->remap_addr = pci_ioremap_bar(pci, 0);
        if (chip->remap_addr == NULL) {
-               snd_printk(KERN_ERR SFX "ioremap error\n");
+               snd_printk(KERN_ERR SFX "%s: ioremap error\n", pci_name(chip->pci));
                return -ENXIO;
        }
 
@@ -3135,7 +3264,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
        synchronize_irq(chip->irq);
 
        gcap = azx_readw(chip, GCAP);
-       snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
+       snd_printdd(SFX "%s: chipset global capabilities = 0x%x\n", pci_name(chip->pci), gcap);
 
        /* disable SB600 64bit support for safety */
        if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
@@ -3152,7 +3281,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
 
        /* disable 64bit DMA address on some devices */
        if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
-               snd_printd(SFX "Disabling 64bit DMA\n");
+               snd_printd(SFX "%s: Disabling 64bit DMA\n", pci_name(chip->pci));
                gcap &= ~ICH6_GCAP_64OK;
        }
 
@@ -3207,7 +3336,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
        chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
                                GFP_KERNEL);
        if (!chip->azx_dev) {
-               snd_printk(KERN_ERR SFX "cannot malloc azx_dev\n");
+               snd_printk(KERN_ERR SFX "%s: cannot malloc azx_dev\n", pci_name(chip->pci));
                return -ENOMEM;
        }
 
@@ -3217,7 +3346,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
                                          snd_dma_pci_data(chip->pci),
                                          BDL_SIZE, &chip->azx_dev[i].bdl);
                if (err < 0) {
-                       snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+                       snd_printk(KERN_ERR SFX "%s: cannot allocate BDL\n", pci_name(chip->pci));
                        return -ENOMEM;
                }
                mark_pages_wc(chip, &chip->azx_dev[i].bdl, true);
@@ -3227,7 +3356,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
                                  snd_dma_pci_data(chip->pci),
                                  chip->num_streams * 8, &chip->posbuf);
        if (err < 0) {
-               snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+               snd_printk(KERN_ERR SFX "%s: cannot allocate posbuf\n", pci_name(chip->pci));
                return -ENOMEM;
        }
        mark_pages_wc(chip, &chip->posbuf, true);
@@ -3245,7 +3374,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip)
 
        /* codec detection */
        if (!chip->codec_mask) {
-               snd_printk(KERN_ERR SFX "no codecs found!\n");
+               snd_printk(KERN_ERR SFX "%s: no codecs found!\n", pci_name(chip->pci));
                return -ENODEV;
        }
 
@@ -3281,7 +3410,8 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
        struct pci_dev *pci = chip->pci;
 
        if (!fw) {
-               snd_printk(KERN_ERR SFX "Cannot load firmware, aborting\n");
+               snd_printk(KERN_ERR SFX "%s: Cannot load firmware, aborting\n",
+                          pci_name(chip->pci));
                goto error;
        }
 
@@ -3299,8 +3429,8 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
 }
 #endif
 
-static int __devinit azx_probe(struct pci_dev *pci,
-                              const struct pci_device_id *pci_id)
+static int azx_probe(struct pci_dev *pci,
+                    const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -3317,7 +3447,7 @@ static int __devinit azx_probe(struct pci_dev *pci,
 
        err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
        if (err < 0) {
-               snd_printk(KERN_ERR SFX "Error creating card!\n");
+               snd_printk(KERN_ERR "hda-intel: Error creating card!\n");
                return err;
        }
 
@@ -3327,12 +3457,34 @@ static int __devinit azx_probe(struct pci_dev *pci,
        if (err < 0)
                goto out_free;
        card->private_data = chip;
+
+       pci_set_drvdata(pci, card);
+
+       err = register_vga_switcheroo(chip);
+       if (err < 0) {
+               snd_printk(KERN_ERR SFX
+                          "%s: Error registering VGA-switcheroo client\n", pci_name(pci));
+               goto out_free;
+       }
+
+       if (check_hdmi_disabled(pci)) {
+               snd_printk(KERN_INFO SFX "%s: VGA controller is disabled\n",
+                          pci_name(pci));
+               snd_printk(KERN_INFO SFX "%s: Delaying initialization\n", pci_name(pci));
+               chip->disabled = true;
+       }
+
        probe_now = !chip->disabled;
+       if (probe_now) {
+               err = azx_first_init(chip);
+               if (err < 0)
+                       goto out_free;
+       }
 
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
        if (patch[dev] && *patch[dev]) {
-               snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n",
-                          patch[dev]);
+               snd_printk(KERN_ERR SFX "%s: Applying patch firmware '%s'\n",
+                          pci_name(pci), patch[dev]);
                err = request_firmware_nowait(THIS_MODULE, true, patch[dev],
                                              &pci->dev, GFP_KERNEL, card,
                                              azx_firmware_cb);
@@ -3348,27 +3500,20 @@ static int __devinit azx_probe(struct pci_dev *pci,
                        goto out_free;
        }
 
-       pci_set_drvdata(pci, card);
-
        if (pci_dev_run_wake(pci))
                pm_runtime_put_noidle(&pci->dev);
 
-       err = register_vga_switcheroo(chip);
-       if (err < 0) {
-               snd_printk(KERN_ERR SFX
-                          "Error registering VGA-switcheroo client\n");
-               goto out_free;
-       }
-
        dev++;
+       complete(&chip->probe_wait);
        return 0;
 
 out_free:
        snd_card_free(card);
+       pci_set_drvdata(pci, NULL);
        return err;
 }
 
-static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
+static int azx_probe_continue(struct azx *chip)
 {
        int dev = chip->dev_index;
        int err;
@@ -3387,8 +3532,10 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
                                         chip->fw->data);
                if (err < 0)
                        goto out_free;
+#ifndef CONFIG_PM
                release_firmware(chip->fw); /* no longer needed */
                chip->fw = NULL;
+#endif
        }
 #endif
        if ((probe_only[dev] & 1) == 0) {
@@ -3423,7 +3570,7 @@ out_free:
        return err;
 }
 
-static void __devexit azx_remove(struct pci_dev *pci)
+static void azx_remove(struct pci_dev *pci)
 {
        struct snd_card *card = pci_get_drvdata(pci);
 
@@ -3610,7 +3757,7 @@ static struct pci_driver azx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = azx_ids,
        .probe = azx_probe,
-       .remove = __devexit_p(azx_remove),
+       .remove = azx_remove,
        .driver = {
                .pm = AZX_PM_OPS,
        },
diff --git a/sound/pci/hda/hda_intel_trace.h b/sound/pci/hda/hda_intel_trace.h
new file mode 100644 (file)
index 0000000..7b5e4c2
--- /dev/null
@@ -0,0 +1,62 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hda_intel
+#define TRACE_INCLUDE_FILE hda_intel_trace
+
+#if !defined(_TRACE_HDA_INTEL_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HDA_INTEL_H
+
+#include <linux/tracepoint.h>
+
+struct azx;
+struct azx_dev;
+
+TRACE_EVENT(azx_pcm_trigger,
+
+       TP_PROTO(struct azx *chip, struct azx_dev *dev, int cmd),
+
+       TP_ARGS(chip, dev, cmd),
+
+       TP_STRUCT__entry(
+               __field( int, card )
+               __field( int, idx )
+               __field( int, cmd )
+       ),
+
+       TP_fast_assign(
+               __entry->card = (chip)->card->number;
+               __entry->idx = (dev)->index;
+               __entry->cmd = cmd;
+       ),
+
+       TP_printk("[%d:%d] cmd=%d", __entry->card, __entry->idx, __entry->cmd)
+);
+
+TRACE_EVENT(azx_get_position,
+
+    TP_PROTO(struct azx *chip, struct azx_dev *dev, unsigned int pos, unsigned int delay),
+
+           TP_ARGS(chip, dev, pos, delay),
+
+       TP_STRUCT__entry(
+               __field( int, card )
+               __field( int, idx )
+               __field( unsigned int, pos )
+               __field( unsigned int, delay )
+       ),
+
+       TP_fast_assign(
+               __entry->card = (chip)->card->number;
+               __entry->idx = (dev)->index;
+               __entry->pos = pos;
+               __entry->delay = delay;
+       ),
+
+       TP_printk("[%d:%d] pos=%u, delay=%u", __entry->card, __entry->idx, __entry->pos, __entry->delay)
+);
+
+#endif /* _TRACE_HDA_INTEL_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
index 5c690cb873d469af2b419476fb790e893c2433a2..6e9f57bbe6673d3c01371783428287956f8814eb 100644 (file)
@@ -95,7 +95,6 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
        struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
        if (jack)
                return jack;
-       snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
        jack = snd_array_new(&codec->jacktbl);
        if (!jack)
                return NULL;
@@ -122,6 +121,8 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec)
        snd_array_free(&codec->jacktbl);
 }
 
+#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
+
 /* update the cached value and notification flag if needed */
 static void jack_detect_update(struct hda_codec *codec,
                               struct hda_jack_tbl *jack)
@@ -134,7 +135,21 @@ static void jack_detect_update(struct hda_codec *codec,
        else
                jack->pin_sense = read_pin_sense(codec, jack->nid);
 
+       /* A gating jack indicates the jack is invalid if gating is unplugged */
+       if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack))
+               jack->pin_sense &= ~AC_PINSENSE_PRESENCE;
+
        jack->jack_dirty = 0;
+
+       /* If a jack is gated by this one update it. */
+       if (jack->gated_jack) {
+               struct hda_jack_tbl *gated =
+                       snd_hda_jack_tbl_get(codec, jack->gated_jack);
+               if (gated) {
+                       gated->jack_dirty = 1;
+                       jack_detect_update(codec, gated);
+               }
+       }
 }
 
 /**
@@ -173,8 +188,6 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
 }
 EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
 
-#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
-
 /**
  * snd_hda_jack_detect - query pin Presence Detect status
  * @codec: the CODEC to sense
@@ -206,6 +219,8 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
                jack->action = action;
        if (cb)
                jack->callback = cb;
+       if (codec->jackpoll_interval > 0)
+               return 0; /* No unsol if we're polling instead */
        return snd_hda_codec_write_cache(codec, nid, 0,
                                         AC_VERB_SET_UNSOLICITED_ENABLE,
                                         AC_USRSP_EN | jack->tag);
@@ -219,17 +234,47 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
 
+/**
+ * snd_hda_jack_set_gating_jack - Set gating jack.
+ *
+ * Indicates the gated jack is only valid when the gating jack is plugged.
+ */
+int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
+                                hda_nid_t gating_nid)
+{
+       struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, gated_nid);
+       struct hda_jack_tbl *gating = snd_hda_jack_tbl_get(codec, gating_nid);
+
+       if (!gated || !gating)
+               return -EINVAL;
+
+       gated->gating_jack = gating_nid;
+       gating->gated_jack = gated_nid;
+
+       return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_set_gating_jack);
+
 /**
  * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
  */
 void snd_hda_jack_report_sync(struct hda_codec *codec)
 {
-       struct hda_jack_tbl *jack = codec->jacktbl.list;
+       struct hda_jack_tbl *jack;
        int i, state;
 
+       /* update all jacks at first */
+       jack = codec->jacktbl.list;
        for (i = 0; i < codec->jacktbl.used; i++, jack++)
-               if (jack->nid) {
+               if (jack->nid)
                        jack_detect_update(codec, jack);
+
+       /* report the updated jacks; it's done after updating all jacks
+        * to make sure that all gating jacks properly have been set
+        */
+       jack = codec->jacktbl.list;
+       for (i = 0; i < codec->jacktbl.used; i++, jack++)
+               if (jack->nid) {
                        if (!jack->kctl)
                                continue;
                        state = get_jack_plug_state(jack->pin_sense);
@@ -422,6 +467,19 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
 
+static void call_jack_callback(struct hda_codec *codec,
+                              struct hda_jack_tbl *jack)
+{
+       if (jack->callback)
+               jack->callback(codec, jack);
+       if (jack->gated_jack) {
+               struct hda_jack_tbl *gated =
+                       snd_hda_jack_tbl_get(codec, jack->gated_jack);
+               if (gated && gated->callback)
+                       gated->callback(codec, gated);
+       }
+}
+
 void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
 {
        struct hda_jack_tbl *event;
@@ -432,10 +490,29 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
                return;
        event->jack_dirty = 1;
 
-       if (event->callback)
-               event->callback(codec, event);
-
+       call_jack_callback(codec, event);
        snd_hda_jack_report_sync(codec);
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event);
 
+void snd_hda_jack_poll_all(struct hda_codec *codec)
+{
+       struct hda_jack_tbl *jack = codec->jacktbl.list;
+       int i, changes = 0;
+
+       for (i = 0; i < codec->jacktbl.used; i++, jack++) {
+               unsigned int old_sense;
+               if (!jack->nid || !jack->jack_dirty || jack->phantom_jack)
+                       continue;
+               old_sense = get_jack_plug_state(jack->pin_sense);
+               jack_detect_update(codec, jack);
+               if (old_sense == get_jack_plug_state(jack->pin_sense))
+                       continue;
+               changes = 1;
+               call_jack_callback(codec, jack);
+       }
+       if (changes)
+               snd_hda_jack_report_sync(codec);
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_poll_all);
+
index af8dd4724da544c85a2b4df431262952dbb39c4a..ec12abd452631d12b9915e0c75a4c45fdbc07c95 100644 (file)
@@ -28,6 +28,8 @@ struct hda_jack_tbl {
        unsigned int jack_detect:1;     /* capable of jack-detection? */
        unsigned int jack_dirty:1;      /* needs to update? */
        unsigned int phantom_jack:1;    /* a fixed, always present port? */
+       hda_nid_t gating_jack;          /* valid when gating jack plugged */
+       hda_nid_t gated_jack;           /* gated is dependent on this jack */
        struct snd_kcontrol *kctl;      /* assigned kctl for jack-detection */
 #ifdef CONFIG_SND_HDA_INPUT_JACK
        int type;
@@ -69,6 +71,8 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
                                        unsigned char action,
                                        hda_jack_callback cb);
 
+int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
+                                hda_nid_t gating_nid);
 
 u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
 int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
@@ -84,4 +88,6 @@ void snd_hda_jack_report_sync(struct hda_codec *codec);
 
 void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res);
 
+void snd_hda_jack_poll_all(struct hda_codec *codec);
+
 #endif /* __SOUND_HDA_JACK_H */
index 09dbdc37f781592b45c8e8c03a80b0f133195996..4b40a5e7a8f54270cd9fe1df53d67bdca7c338e9 100644 (file)
@@ -240,9 +240,11 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 /*
  * SPDIF I/O
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
-                                 hda_nid_t associated_nid,
-                                 hda_nid_t cvt_nid);
+int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
+                               hda_nid_t associated_nid,
+                               hda_nid_t cvt_nid, int type);
+#define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \
+       snd_hda_create_dig_out_ctls(codec, anid, cnid, HDA_PCM_TYPE_SPDIF)
 int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
 
 /*
@@ -598,6 +600,15 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
 #define get_amp_offset(kc)     (((kc)->private_value >> 23) & 0x3f)
 #define get_amp_min_mute(kc)   (((kc)->private_value >> 29) & 0x1)
 
+/*
+ * enum control helper
+ */
+int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_info *uinfo,
+                            int num_entries, const char * const *texts);
+#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
+       snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL)
+
 /*
  * CEA Short Audio Descriptor data
  */
index 1eeba738666634329d17a76149618c1c6f3e8c26..89fc5030ec792b97204f5d296571d7280669bfc3 100644 (file)
@@ -636,7 +636,6 @@ static void ad198x_free(struct hda_codec *codec)
        if (!spec)
                return;
 
-       ad198x_shutup(codec);
        ad198x_free_kctls(codec);
        kfree(spec);
        snd_hda_detach_beep_device(codec);
@@ -1247,16 +1246,27 @@ static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
        return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
 }
 
-static int patch_ad1986a(struct hda_codec *codec)
+static int alloc_ad_spec(struct hda_codec *codec)
 {
        struct ad198x_spec *spec;
-       int err, board_config;
 
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
+       if (!spec)
                return -ENOMEM;
-
        codec->spec = spec;
+       snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+       return 0;
+}
+
+static int patch_ad1986a(struct hda_codec *codec)
+{
+       struct ad198x_spec *spec;
+       int err, board_config;
+
+       err = alloc_ad_spec(codec);
+       if (err < 0)
+               return err;
+       spec = codec->spec;
 
        err = snd_hda_attach_beep_device(codec, 0x19);
        if (err < 0) {
@@ -1549,11 +1559,10 @@ static int patch_ad1983(struct hda_codec *codec)
        struct ad198x_spec *spec;
        int err;
 
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
+       err = alloc_ad_spec(codec);
+       if (err < 0)
+               return err;
+       spec = codec->spec;
 
        err = snd_hda_attach_beep_device(codec, 0x10);
        if (err < 0) {
@@ -1955,11 +1964,10 @@ static int patch_ad1981(struct hda_codec *codec)
        struct ad198x_spec *spec;
        int err, board_config;
 
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
+       err = alloc_ad_spec(codec);
+       if (err < 0)
                return -ENOMEM;
-
-       codec->spec = spec;
+       spec = codec->spec;
 
        err = snd_hda_attach_beep_device(codec, 0x10);
        if (err < 0) {
@@ -2837,7 +2845,6 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
 {
        struct snd_kcontrol_new *knew;
 
-       snd_array_init(&spec->kctls, sizeof(*knew), 32);
        knew = snd_array_new(&spec->kctls);
        if (!knew)
                return -ENOMEM;
@@ -3255,11 +3262,10 @@ static int patch_ad1988(struct hda_codec *codec)
        struct ad198x_spec *spec;
        int err, board_config;
 
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
+       err = alloc_ad_spec(codec);
+       if (err < 0)
+               return err;
+       spec = codec->spec;
 
        if (is_rev2(codec))
                snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
@@ -3575,11 +3581,10 @@ static int patch_ad1884(struct hda_codec *codec)
        struct ad198x_spec *spec;
        int err;
 
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
+       err = alloc_ad_spec(codec);
+       if (err < 0)
+               return err;
+       spec = codec->spec;
 
        err = snd_hda_attach_beep_device(codec, 0x10);
        if (err < 0) {
@@ -4575,11 +4580,10 @@ static int patch_ad1884a(struct hda_codec *codec)
        struct ad198x_spec *spec;
        int err, board_config;
 
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
+       err = alloc_ad_spec(codec);
+       if (err < 0)
+               return err;
+       spec = codec->spec;
 
        err = snd_hda_attach_beep_device(codec, 0x10);
        if (err < 0) {
@@ -4988,11 +4992,10 @@ static int patch_ad1882(struct hda_codec *codec)
        struct ad198x_spec *spec;
        int err, board_config;
 
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
+       err = alloc_ad_spec(codec);
+       if (err < 0)
+               return err;
+       spec = codec->spec;
 
        err = snd_hda_attach_beep_device(codec, 0x10);
        if (err < 0) {
index 3bcb671723583ed852ec97aa844d2736ffd4b330..a2537b2f87240ae20f2d75d5d3cb7a0ebdc81510 100644 (file)
@@ -68,6 +68,7 @@ struct cs_spec {
 
        unsigned int hp_detect:1;
        unsigned int mic_detect:1;
+       unsigned int speaker_2_1:1;
        /* CS421x */
        unsigned int spdif_detect:1;
        unsigned int sense_b:1;
@@ -84,7 +85,7 @@ enum {
        CS420X_GPIO_13,
        CS420X_GPIO_23,
        CS420X_MBP101,
-       CS420X_MBP101_COEF,
+       CS420X_MBP81,
        CS420X_AUTO,
        /* aliases */
        CS420X_IMAC27_122 = CS420X_GPIO_23,
@@ -343,6 +344,9 @@ static int cs_build_pcms(struct hda_codec *codec)
        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dac_nid[0];
        info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
                spec->multiout.max_channels;
+       if (spec->speaker_2_1)
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+                       snd_pcm_2_1_chmaps;
        info->stream[SNDRV_PCM_STREAM_CAPTURE] = cs_pcm_analog_capture;
        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
                spec->adc_nid[spec->cur_input];
@@ -443,6 +447,9 @@ static int parse_output(struct hda_codec *codec)
        spec->multiout.dac_nids = spec->dac_nid;
        spec->multiout.max_channels = i * 2;
 
+       if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && i == 2)
+               spec->speaker_2_1 = 1; /* assume 2.1 speakers */
+
        /* add HP and speakers */
        extra_nids = 0;
        for (i = 0; i < cfg->hp_outs; i++) {
@@ -633,7 +640,9 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
                index = idx;
                break;
        case AUTO_PIN_SPEAKER_OUT:
-               if (num_ctls > 1)
+               if (spec->speaker_2_1)
+                       name = idx ? "Bass Speaker" : "Speaker";
+               else if (num_ctls > 1)
                        name = speakers[idx];
                else
                        name = "Speaker";
@@ -874,8 +883,9 @@ static int build_digital_output(struct hda_codec *codec)
        if (!spec->multiout.dig_out_nid)
                return 0;
 
-       err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid,
-                                           spec->multiout.dig_out_nid);
+       err = snd_hda_create_dig_out_ctls(codec, spec->multiout.dig_out_nid,
+                                         spec->multiout.dig_out_nid,
+                                         spec->pcm_rec[1].pcm_type);
        if (err < 0)
                return err;
        err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
@@ -1079,9 +1089,6 @@ static void init_input(struct hda_codec *codec)
                if (spec->mic_detect)
                        cs_automic(codec, NULL);
 
-               coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
-               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
-
                coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
                        coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
@@ -1111,6 +1118,9 @@ static const struct hda_verb cs_coef_init_verbs[] = {
          | 0x1000 /* Enable DACs High Pass Filter */
          | 0x0400 /* Disable Coefficient Auto increment */
          )},
+       /* ADC1/2 - Digital and Analog Soft Ramp */
+       {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
+       {0x11, AC_VERB_SET_PROC_COEF, 0x000a},
        /* Beep */
        {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
        {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
@@ -1167,14 +1177,6 @@ static const struct hda_verb cs_errata_init_verbs[] = {
        {} /* terminator */
 };
 
-static const struct hda_verb mbp101_init_verbs[] = {
-       {0x11, AC_VERB_SET_COEF_INDEX, 0x0002},
-       {0x11, AC_VERB_SET_PROC_COEF, 0x100a},
-       {0x11, AC_VERB_SET_COEF_INDEX, 0x0004},
-       {0x11, AC_VERB_SET_PROC_COEF, 0x000f},
-       {}
-};
-
 /* SPDIF setup */
 static void init_digital(struct hda_codec *codec)
 {
@@ -1199,6 +1201,8 @@ static int cs_init(struct hda_codec *codec)
 
        snd_hda_sequence_write(codec, cs_coef_init_verbs);
 
+       snd_hda_gen_apply_verbs(codec);
+
        if (spec->gpio_mask) {
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
                                    spec->gpio_mask);
@@ -1291,6 +1295,7 @@ static const struct hda_model_fixup cs420x_models[] = {
        { .id = CS420X_IMAC27_122, .name = "imac27_122" },
        { .id = CS420X_APPLE, .name = "apple" },
        { .id = CS420X_MBP101, .name = "mbp101" },
+       { .id = CS420X_MBP81, .name = "mbp81" },
        {}
 };
 
@@ -1303,6 +1308,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
        /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
 
        /* codec SSID */
+       SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
        SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
        SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
        SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
@@ -1413,11 +1419,16 @@ static const struct hda_fixup cs420x_fixups[] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = mbp101_pincfgs,
                .chained = true,
-               .chain_id = CS420X_MBP101_COEF,
+               .chain_id = CS420X_GPIO_13,
        },
-       [CS420X_MBP101_COEF] = {
+       [CS420X_MBP81] = {
                .type = HDA_FIXUP_VERBS,
-               .v.verbs = mbp101_init_verbs,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* internal mic ADC2: right only, single ended */
+                       {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
+                       {0x11, AC_VERB_SET_PROC_COEF, 0x102a},
+                       {}
+               },
                .chained = true,
                .chain_id = CS420X_GPIO_13,
        },
index 03b1dc317ff0341122d48a0535e41963b2834157..60890bfecc196600ffa15ab5979c06aef8891f9b 100644 (file)
@@ -337,6 +337,8 @@ static const struct hda_pcm_stream cx5051_pcm_analog_capture = {
        },
 };
 
+static bool is_2_1_speaker(struct conexant_spec *spec);
+
 static int conexant_build_pcms(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
@@ -351,6 +353,9 @@ static int conexant_build_pcms(struct hda_codec *codec)
                spec->multiout.max_channels;
        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
                spec->multiout.dac_nids[0];
+       if (is_2_1_speaker(spec))
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+                       snd_pcm_2_1_chmaps;
        if (spec->capture_stream)
                info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream;
        else {
@@ -472,7 +477,7 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = {
 #endif
 
 static const char * const slave_pfxs[] = {
-       "Headphone", "Speaker", "Front", "Surround", "CLFE",
+       "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE",
        NULL
 };
 
@@ -3430,28 +3435,13 @@ static int cx_automute_mode_info(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct conexant_spec *spec = codec->spec;
-       static const char * const texts2[] = {
-               "Disabled", "Enabled"
-       };
        static const char * const texts3[] = {
                "Disabled", "Speaker Only", "Line Out+Speaker"
        };
-       const char * const *texts;
 
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = 1;
-       if (spec->automute_hp_lo) {
-               uinfo->value.enumerated.items = 3;
-               texts = texts3;
-       } else {
-               uinfo->value.enumerated.items = 2;
-               texts = texts2;
-       }
-       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-       strcpy(uinfo->value.enumerated.name,
-              texts[uinfo->value.enumerated.item]);
-       return 0;
+       if (spec->automute_hp_lo)
+               return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
+       return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
 }
 
 static int cx_automute_mode_get(struct snd_kcontrol *kcontrol,
@@ -4116,11 +4106,26 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
        return 0;
 }
 
+static bool is_2_1_speaker(struct conexant_spec *spec)
+{
+       int i, type, num_spk = 0;
+
+       for (i = 0; i < spec->dac_info_filled; i++) {
+               type = spec->dac_info[i].type;
+               if (type == AUTO_PIN_LINE_OUT)
+                       type = spec->autocfg.line_out_type;
+               if (type == AUTO_PIN_SPEAKER_OUT)
+                       num_spk++;
+       }
+       return (num_spk == 2 && spec->autocfg.line_out_type != AUTO_PIN_LINE_OUT);
+}
+
 static int cx_auto_build_output_controls(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
        int i, err;
        int num_line = 0, num_hp = 0, num_spk = 0;
+       bool speaker_2_1;
        static const char * const texts[3] = { "Front", "Surround", "CLFE" };
 
        if (spec->dac_info_filled == 1)
@@ -4128,6 +4133,8 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
                                         spec->dac_info[0].pin,
                                         "Master", 0);
 
+       speaker_2_1 = is_2_1_speaker(spec);
+
        for (i = 0; i < spec->dac_info_filled; i++) {
                const char *label;
                int idx, type;
@@ -4146,8 +4153,13 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
                        idx = num_hp++;
                        break;
                case AUTO_PIN_SPEAKER_OUT:
-                       label = "Speaker";
-                       idx = num_spk++;
+                       if (speaker_2_1) {
+                               label = num_spk++ ? "Bass Speaker" : "Speaker";
+                               idx = 0;
+                       } else {
+                               label = "Speaker";
+                               idx = num_spk++;
+                       }
                        break;
                }
                err = try_add_pb_volume(codec, dac,
@@ -4405,7 +4417,10 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
 enum {
        CXT_PINCFG_LENOVO_X200,
        CXT_PINCFG_LENOVO_TP410,
+       CXT_PINCFG_LEMOTE_A1004,
+       CXT_PINCFG_LEMOTE_A1205,
        CXT_FIXUP_STEREO_DMIC,
+       CXT_FIXUP_INC_MIC_BOOST,
 };
 
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
@@ -4415,6 +4430,19 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
        spec->fixup_stereo_dmic = 1;
 }
 
+static void cxt5066_increase_mic_boost(struct hda_codec *codec,
+                                  const struct hda_fixup *fix, int action)
+{
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+
+       snd_hda_override_amp_caps(codec, 0x17, HDA_OUTPUT,
+                                 (0x3 << AC_AMPCAP_OFFSET_SHIFT) |
+                                 (0x4 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+                                 (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+                                 (0 << AC_AMPCAP_MUTE_SHIFT));
+}
+
 /* ThinkPad X200 & co with cxt5051 */
 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
        { 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -4432,6 +4460,18 @@ static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
        {}
 };
 
+/* Lemote A1004/A1205 with cxt5066 */
+static const struct hda_pintbl cxt_pincfg_lemote[] = {
+       { 0x1a, 0x90a10020 }, /* Internal mic */
+       { 0x1b, 0x03a11020 }, /* External mic */
+       { 0x1d, 0x400101f0 }, /* Not used */
+       { 0x1e, 0x40a701f0 }, /* Not used */
+       { 0x20, 0x404501f0 }, /* Not used */
+       { 0x22, 0x404401f0 }, /* Not used */
+       { 0x23, 0x40a701f0 }, /* Not used */
+       {}
+};
+
 static const struct hda_fixup cxt_fixups[] = {
        [CXT_PINCFG_LENOVO_X200] = {
                .type = HDA_FIXUP_PINS,
@@ -4441,10 +4481,24 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = cxt_pincfg_lenovo_tp410,
        },
+       [CXT_PINCFG_LEMOTE_A1004] = {
+               .type = HDA_FIXUP_PINS,
+               .chained = true,
+               .chain_id = CXT_FIXUP_INC_MIC_BOOST,
+               .v.pins = cxt_pincfg_lemote,
+       },
+       [CXT_PINCFG_LEMOTE_A1205] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = cxt_pincfg_lemote,
+       },
        [CXT_FIXUP_STEREO_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_stereo_dmic,
        },
+       [CXT_FIXUP_INC_MIC_BOOST] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cxt5066_increase_mic_boost,
+       },
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4453,6 +4507,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
 };
 
 static const struct snd_pci_quirk cxt5066_fixups[] = {
+       SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
@@ -4461,6 +4516,8 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
+       SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
        {}
 };
 
index 71555cc54db1686519b8bd20f168d4fe5babbcad..0fcfa6f406b8ac8738ba466954cfe7a6bc6faf87 100644 (file)
@@ -1193,12 +1193,11 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
        struct hdmi_spec_per_pin *per_pin;
        int err;
 
-       caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP);
+       caps = snd_hda_query_pin_caps(codec, pin_nid);
        if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
                return 0;
 
-       config = snd_hda_codec_read(codec, pin_nid, 0,
-                               AC_VERB_GET_CONFIG_DEFAULT, 0);
+       config = snd_hda_codec_get_pincfg(codec, pin_nid);
        if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
                return 0;
 
@@ -1272,7 +1271,7 @@ static int hdmi_parse_codec(struct hda_codec *codec)
                unsigned int caps;
                unsigned int type;
 
-               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+               caps = get_wcaps(codec, nid);
                type = get_wcaps_type(caps);
 
                if (!(caps & AC_WCAP_DIGITAL))
@@ -1288,13 +1287,17 @@ static int hdmi_parse_codec(struct hda_codec *codec)
                }
        }
 
+#ifdef CONFIG_PM
+       /* We're seeing some problems with unsolicited hot plug events on
+        * PantherPoint after S3, if this is not enabled */
+       if (codec->vendor_id == 0x80862806)
+               codec->bus->power_keep_link_on = 1;
        /*
         * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
         * can be lost and presence sense verb will become inaccurate if the
         * HDA link is powered off at hot plug or hw initialization time.
         */
-#ifdef CONFIG_PM
-       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+       else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
              AC_PWRST_EPSS))
                codec->bus->power_keep_link_on = 1;
 #endif
@@ -1589,9 +1592,10 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
                if (err < 0)
                        return err;
 
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   per_pin->pin_nid,
-                                                   per_pin->mux_nids[0]);
+               err = snd_hda_create_dig_out_ctls(codec,
+                                                 per_pin->pin_nid,
+                                                 per_pin->mux_nids[0],
+                                                 HDA_PCM_TYPE_HDMI);
                if (err < 0)
                        return err;
                snd_hda_spdif_ctls_unassign(codec, pin_idx);
index ad68d223f8af9e7dc43d24af303aab1eec64ca3d..7743775f6abb34b3babf5a1bf44c3b1f5ef308cc 100644 (file)
@@ -153,8 +153,8 @@ struct alc_spec {
        const struct hda_channel_mode *channel_mode;
        int num_channel_mode;
        int need_dac_fix;
-       int const_channel_count;
-       int ext_channel_count;
+       int const_channel_count;        /* min. channel count (for speakers) */
+       int ext_channel_count;          /* current channel count for multi-io */
 
        /* PCM information */
        struct hda_pcm pcm_rec[3];      /* used in alc_build_pcms() */
@@ -815,28 +815,13 @@ static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct alc_spec *spec = codec->spec;
-       static const char * const texts2[] = {
-               "Disabled", "Enabled"
-       };
        static const char * const texts3[] = {
                "Disabled", "Speaker Only", "Line Out+Speaker"
        };
-       const char * const *texts;
 
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = 1;
-       if (spec->automute_speaker_possible && spec->automute_lo_possible) {
-               uinfo->value.enumerated.items = 3;
-               texts = texts3;
-       } else {
-               uinfo->value.enumerated.items = 2;
-               texts = texts2;
-       }
-       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-       strcpy(uinfo->value.enumerated.name,
-              texts[uinfo->value.enumerated.item]);
-       return 0;
+       if (spec->automute_speaker_possible && spec->automute_lo_possible)
+               return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
+       return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
 }
 
 static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
@@ -903,23 +888,25 @@ static const struct snd_kcontrol_new alc_automute_mode_enum = {
        .put = alc_automute_mode_put,
 };
 
-static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+static struct snd_kcontrol_new *
+alc_kcontrol_new(struct alc_spec *spec, const char *name,
+                const struct snd_kcontrol_new *temp)
 {
-       snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
-       return snd_array_new(&spec->kctls);
+       struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
+       if (!knew)
+               return NULL;
+       *knew = *temp;
+       knew->name = kstrdup(name, GFP_KERNEL);
+       if (!knew->name)
+               return NULL;
+       return knew;
 }
 
 static int alc_add_automute_mode_enum(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       struct snd_kcontrol_new *knew;
 
-       knew = alc_kcontrol_new(spec);
-       if (!knew)
-               return -ENOMEM;
-       *knew = alc_automute_mode_enum;
-       knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
-       if (!knew->name)
+       if (!alc_kcontrol_new(spec, "Auto-Mute Mode", &alc_automute_mode_enum))
                return -ENOMEM;
        return 0;
 }
@@ -928,12 +915,12 @@ static int alc_add_automute_mode_enum(struct hda_codec *codec)
  * Check the availability of HP/line-out auto-mute;
  * Set up appropriately if really supported
  */
-static void alc_init_automute(struct hda_codec *codec)
+static int alc_init_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
        int present = 0;
-       int i;
+       int i, err;
 
        if (cfg->hp_pins[0])
                present++;
@@ -942,7 +929,7 @@ static void alc_init_automute(struct hda_codec *codec)
        if (cfg->speaker_pins[0])
                present++;
        if (present < 2) /* need two different output types */
-               return;
+               return 0;
 
        if (!cfg->speaker_pins[0] &&
            cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
@@ -992,9 +979,13 @@ static void alc_init_automute(struct hda_codec *codec)
        spec->automute_lo = spec->automute_lo_possible;
        spec->automute_speaker = spec->automute_speaker_possible;
 
-       if (spec->automute_speaker_possible || spec->automute_lo_possible)
+       if (spec->automute_speaker_possible || spec->automute_lo_possible) {
                /* create a control for automute mode */
-               alc_add_automute_mode_enum(codec);
+               err = alc_add_automute_mode_enum(codec);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
 }
 
 /* return the position of NID in the list, or -1 if not found */
@@ -1094,7 +1085,7 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec)
  * Check the availability of auto-mic switch;
  * Set up if really supported
  */
-static void alc_init_auto_mic(struct hda_codec *codec)
+static int alc_init_auto_mic(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -1102,7 +1093,7 @@ static void alc_init_auto_mic(struct hda_codec *codec)
        int i;
 
        if (spec->shared_mic_hp)
-               return; /* no auto-mic for the shared I/O */
+               return 0; /* no auto-mic for the shared I/O */
 
        spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
 
@@ -1114,25 +1105,25 @@ static void alc_init_auto_mic(struct hda_codec *codec)
                switch (snd_hda_get_input_pin_attr(defcfg)) {
                case INPUT_PIN_ATTR_INT:
                        if (fixed)
-                               return; /* already occupied */
+                               return 0; /* already occupied */
                        if (cfg->inputs[i].type != AUTO_PIN_MIC)
-                               return; /* invalid type */
+                               return 0; /* invalid type */
                        fixed = nid;
                        break;
                case INPUT_PIN_ATTR_UNUSED:
-                       return; /* invalid entry */
+                       return 0; /* invalid entry */
                case INPUT_PIN_ATTR_DOCK:
                        if (dock)
-                               return; /* already occupied */
+                               return 0; /* already occupied */
                        if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
-                               return; /* invalid type */
+                               return 0; /* invalid type */
                        dock = nid;
                        break;
                default:
                        if (ext)
-                               return; /* already occupied */
+                               return 0; /* already occupied */
                        if (cfg->inputs[i].type != AUTO_PIN_MIC)
-                               return; /* invalid type */
+                               return 0; /* invalid type */
                        ext = nid;
                        break;
                }
@@ -1142,11 +1133,11 @@ static void alc_init_auto_mic(struct hda_codec *codec)
                dock = 0;
        }
        if (!ext || !fixed)
-               return;
+               return 0;
        if (!is_jack_detectable(codec, ext))
-               return; /* no unsol support */
+               return 0; /* no unsol support */
        if (dock && !is_jack_detectable(codec, dock))
-               return; /* no unsol support */
+               return 0; /* no unsol support */
 
        /* check imux indices */
        spec->ext_mic_pin = ext;
@@ -1155,17 +1146,26 @@ static void alc_init_auto_mic(struct hda_codec *codec)
 
        spec->auto_mic = 1;
        if (!alc_auto_mic_check_imux(codec))
-               return;
+               return 0;
 
        snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
                    ext, fixed, dock);
+
+       return 0;
 }
 
 /* check the availabilities of auto-mute and auto-mic switches */
-static void alc_auto_check_switches(struct hda_codec *codec)
+static int alc_auto_check_switches(struct hda_codec *codec)
 {
-       alc_init_automute(codec);
-       alc_init_auto_mic(codec);
+       int err;
+
+       err = alc_init_automute(codec);
+       if (err < 0)
+               return err;
+       err = alc_init_auto_mic(codec);
+       if (err < 0)
+               return err;
+       return 0;
 }
 
 /*
@@ -1757,12 +1757,9 @@ static const struct snd_kcontrol_new alc_inv_dmic_sw = {
 static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid)
 {
        struct alc_spec *spec = codec->spec;
-       struct snd_kcontrol_new *knew = alc_kcontrol_new(spec);
-       if (!knew)
-               return -ENOMEM;
-       *knew = alc_inv_dmic_sw;
-       knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL);
-       if (!knew->name)
+
+       if (!alc_kcontrol_new(spec, "Inverted Internal Mic Capture Switch",
+                             &alc_inv_dmic_sw))
                return -ENOMEM;
        spec->inv_dmic_fixup = 1;
        spec->inv_dmic_muted = 0;
@@ -1836,9 +1833,10 @@ static int __alc_build_controls(struct hda_codec *codec)
                        return err;
        }
        if (spec->multiout.dig_out_nid) {
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   spec->multiout.dig_out_nid,
-                                                   spec->multiout.dig_out_nid);
+               err = snd_hda_create_dig_out_ctls(codec,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->pcm_rec[1].pcm_type);
                if (err < 0)
                        return err;
                if (!spec->no_analog) {
@@ -2259,6 +2257,10 @@ static int alc_build_pcms(struct hda_codec *codec)
                info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
                info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
                        spec->multiout.max_channels;
+               if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
+                   spec->autocfg.line_outs == 2)
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+                               snd_pcm_2_1_chmaps;
        }
        if (spec->adc_nids) {
                p = spec->stream_analog_capture;
@@ -2399,7 +2401,6 @@ static void alc_free(struct hda_codec *codec)
        if (!spec)
                return;
 
-       alc_shutup(codec);
        alc_free_kctls(codec);
        alc_free_bind_ctls(codec);
        snd_hda_gen_free(&spec->gen);
@@ -2534,13 +2535,9 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
 {
        struct snd_kcontrol_new *knew;
 
-       knew = alc_kcontrol_new(spec);
+       knew = alc_kcontrol_new(spec, name, &alc_control_templates[type]);
        if (!knew)
                return -ENOMEM;
-       *knew = alc_control_templates[type];
-       knew->name = kstrdup(name, GFP_KERNEL);
-       if (!knew->name)
-               return -ENOMEM;
        knew->index = cidx;
        if (get_amp_nid_(val))
                knew->subdevice = HDA_SUBDEV_AMP_FLAG;
@@ -3601,7 +3598,6 @@ static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
 {
        struct alc_spec *spec = codec->spec;
        struct hda_bind_ctls **ctlp, *ctl;
-       snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
        ctlp = snd_array_new(&spec->bind_ctls);
        if (!ctlp)
                return NULL;
@@ -3965,8 +3961,9 @@ static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
        spec->ext_channel_count = (ch + 1) * 2;
        for (i = 0; i < spec->multi_ios; i++)
                alc_set_multi_io(codec, i, i < ch);
-       spec->multiout.max_channels = spec->ext_channel_count;
-       if (spec->need_dac_fix && !spec->const_channel_count)
+       spec->multiout.max_channels = max(spec->ext_channel_count,
+                                         spec->const_channel_count);
+       if (spec->need_dac_fix)
                spec->multiout.num_dacs = spec->multiout.max_channels / 2;
        return 1;
 }
@@ -3984,14 +3981,8 @@ static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
 
        if (spec->multi_ios > 0) {
-               struct snd_kcontrol_new *knew;
-
-               knew = alc_kcontrol_new(spec);
-               if (!knew)
-                       return -ENOMEM;
-               *knew = alc_auto_channel_mode_enum;
-               knew->name = kstrdup("Channel Mode", GFP_KERNEL);
-               if (!knew->name)
+               if (!alc_kcontrol_new(spec, "Channel Mode",
+                                     &alc_auto_channel_mode_enum))
                        return -ENOMEM;
        }
        return 0;
@@ -4334,7 +4325,17 @@ static int alc_parse_auto_config(struct hda_codec *codec,
        if (err < 0)
                return err;
 
-       spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+       /* check the multiple speaker pins */
+       if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+               spec->const_channel_count = cfg->line_outs * 2;
+       else
+               spec->const_channel_count = cfg->speaker_outs * 2;
+
+       if (spec->multi_ios > 0)
+               spec->multiout.max_channels = max(spec->ext_channel_count,
+                                                 spec->const_channel_count);
+       else
+               spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
  dig_only:
        alc_auto_parse_digital(codec);
@@ -4346,7 +4347,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
                alc_ssid_check(codec, ssid_nids);
 
        if (!spec->no_analog) {
-               alc_auto_check_switches(codec);
+               err = alc_auto_check_switches(codec);
+               if (err < 0)
+                       return err;
                err = alc_auto_add_mic_boost(codec);
                if (err < 0)
                        return err;
@@ -4372,6 +4375,8 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
        codec->spec = spec;
        spec->mixer_nid = mixer_nid;
        snd_hda_gen_init(&spec->gen);
+       snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+       snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8);
 
        err = alc_codec_rename_from_preset(codec);
        if (err < 0) {
@@ -6009,6 +6014,16 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec,
        }
 }
 
+static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
+                                   const struct alc_fixup *fix,
+                                   int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action == ALC_FIXUP_ACT_PROBE)
+               snd_hda_jack_set_gating_jack(codec, spec->ext_mic_pin,
+                                            spec->autocfg.hp_pins[0]);
+}
 
 enum {
        ALC269_FIXUP_SONY_VAIO,
@@ -6031,6 +6046,8 @@ enum {
        ALC269_FIXUP_INV_DMIC,
        ALC269_FIXUP_LENOVO_DOCK,
        ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
+       ALC271_FIXUP_AMIC_MIC2,
+       ALC271_FIXUP_HP_GATE_MIC_JACK,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -6175,6 +6192,22 @@ static const struct alc_fixup alc269_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
        },
+       [ALC271_FIXUP_AMIC_MIC2] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x14, 0x99130110 }, /* speaker */
+                       { 0x19, 0x01a19c20 }, /* mic */
+                       { 0x1b, 0x99a7012f }, /* int-mic */
+                       { 0x21, 0x0121401f }, /* HP out */
+                       { }
+               },
+       },
+       [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc271_hp_gate_mic_jack,
+               .chained = true,
+               .chain_id = ALC271_FIXUP_AMIC_MIC2,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6195,6 +6228,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
index 9ba8af05617080f8081a5a69d68bcaec81cfb847..df13c0f84899773e7b40f3b25a23ffe60943fcb6 100644 (file)
@@ -1081,7 +1081,7 @@ static struct snd_kcontrol_new stac_smux_mixer = {
 
 static const char * const slave_pfxs[] = {
        "Front", "Surround", "Center", "LFE", "Side",
-       "Headphone", "Speaker", "IEC958", "PCM",
+       "Headphone", "Speaker", "Bass Speaker", "IEC958", "PCM",
        NULL
 };
 
@@ -1136,9 +1136,10 @@ static int stac92xx_build_controls(struct hda_codec *codec)
        }
 
        if (spec->multiout.dig_out_nid) {
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   spec->multiout.dig_out_nid,
-                                                   spec->multiout.dig_out_nid);
+               err = snd_hda_create_dig_out_ctls(codec,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->multiout.dig_out_nid,
+                                                 spec->autocfg.dig_out_type[0]);
                if (err < 0)
                        return err;
                err = snd_hda_create_spdif_share_sw(codec,
@@ -2515,6 +2516,11 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
                spec->multiout.dac_nids[0];
+       if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
+           spec->autocfg.line_outs == 2)
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+                       snd_pcm_2_1_chmaps;
+
        info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
        info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
        info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs;
@@ -2805,7 +2811,6 @@ stac_control_new(struct sigmatel_spec *spec,
 {
        struct snd_kcontrol_new *knew;
 
-       snd_array_init(&spec->kctls, sizeof(*knew), 32);
        knew = snd_array_new(&spec->kctls);
        if (!knew)
                return NULL;
@@ -3268,9 +3273,9 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
                                idx = i;
                                break;
                        case AUTO_PIN_SPEAKER_OUT:
-                               if (num_outs <= 1) {
-                                       name = "Speaker";
-                                       idx = i;
+                               if (num_outs <= 2) {
+                                       name = i ? "Bass Speaker" : "Speaker";
+                                       idx = 0;
                                        break;
                                }
                                /* Fall through in case of multi speaker outs */
@@ -4569,8 +4574,6 @@ static void stac92xx_free(struct hda_codec *codec)
        if (! spec)
                return;
 
-       stac92xx_shutup(codec);
-
        kfree(spec);
        snd_hda_detach_beep_device(codec);
 }
@@ -5155,20 +5158,34 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
        .reboot_notify = stac92xx_shutup,
 };
 
+static int alloc_stac_spec(struct hda_codec *codec, int num_pins,
+                          const hda_nid_t *pin_nids)
+{
+       struct sigmatel_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       codec->spec = spec;
+       codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */
+       spec->num_pins = num_pins;
+       spec->pin_nids = pin_nids;
+       snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+       return 0;
+}
+
 static int patch_stac9200(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec;
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac9200_pin_nids),
+                             stac9200_pin_nids);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 1;
-       spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
-       spec->pin_nids = stac9200_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
                                                        stac9200_models,
                                                        stac9200_cfg_tbl);
@@ -5224,15 +5241,13 @@ static int patch_stac925x(struct hda_codec *codec)
        struct sigmatel_spec *spec;
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac925x_pin_nids),
+                             stac925x_pin_nids);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 1;
-       spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
-       spec->pin_nids = stac925x_pin_nids;
 
        /* Check first for codec ID */
        spec->board_config = snd_hda_check_board_codec_sid_config(codec,
@@ -5307,19 +5322,17 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec;
        hda_nid_t conn[STAC92HD73_DAC_COUNT + 2];
-       int err = 0;
+       int err;
        int num_dacs;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac92hd73xx_pin_nids),
+                             stac92hd73xx_pin_nids);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 0;
        codec->slave_dig_outs = stac92hd73xx_slave_dig_outs;
-       spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids);
-       spec->pin_nids = stac92hd73xx_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec,
                                                        STAC_92HD73XX_MODELS,
                                                        stac92hd73xx_models,
@@ -5596,9 +5609,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        int default_polarity = -1; /* no default cfg */
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, 0, NULL); /* pins filled later */
+       if (err < 0)
+               return err;
 
        if (hp_bnb2011_with_dock(codec)) {
                snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f);
@@ -5606,11 +5619,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        }
 
        codec->epss = 0; /* longer delay needed for D3 */
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
-
        stac92hd8x_fill_auto_spec(codec);
 
+       spec = codec->spec;
        spec->linear_tone_beep = 0;
        codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
        spec->digbeep_nid = 0x21;
@@ -5779,21 +5790,19 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
        struct sigmatel_spec *spec;
        const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
        unsigned int pin_cfg;
-       int err = 0;
+       int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, STAC92HD71BXX_NUM_PINS,
+                             stac92hd71bxx_pin_nids_4port);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 0;
        codec->patch_ops = stac92xx_patch_ops;
-       spec->num_pins = STAC92HD71BXX_NUM_PINS;
        switch (codec->vendor_id) {
        case 0x111d76b6:
        case 0x111d76b7:
-               spec->pin_nids = stac92hd71bxx_pin_nids_4port;
                break;
        case 0x111d7603:
        case 0x111d7608:
@@ -6024,15 +6033,13 @@ static int patch_stac922x(struct hda_codec *codec)
        struct sigmatel_spec *spec;
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac922x_pin_nids),
+                             stac922x_pin_nids);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 1;
-       spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
-       spec->pin_nids = stac922x_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
                                                        stac922x_models,
                                                        stac922x_cfg_tbl);
@@ -6129,16 +6136,14 @@ static int patch_stac927x(struct hda_codec *codec)
        struct sigmatel_spec *spec;
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac927x_pin_nids),
+                             stac927x_pin_nids);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 1;
        codec->slave_dig_outs = stac927x_slave_dig_outs;
-       spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
-       spec->pin_nids = stac927x_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
                                                        stac927x_models,
                                                        stac927x_cfg_tbl);
@@ -6265,15 +6270,13 @@ static int patch_stac9205(struct hda_codec *codec)
        struct sigmatel_spec *spec;
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac9205_pin_nids),
+                             stac9205_pin_nids);
+       if (err < 0)
+               return err;
 
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       spec = codec->spec;
        spec->linear_tone_beep = 1;
-       spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
-       spec->pin_nids = stac9205_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
                                                        stac9205_models,
                                                        stac9205_cfg_tbl);
@@ -6421,14 +6424,13 @@ static int patch_stac9872(struct hda_codec *codec)
        struct sigmatel_spec *spec;
        int err;
 
-       spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-       codec->no_trigger_sense = 1;
-       codec->spec = spec;
+       err = alloc_stac_spec(codec, ARRAY_SIZE(stac9872_pin_nids),
+                             stac9872_pin_nids);
+       if (err < 0)
+               return err;
+
+       spec = codec->spec;
        spec->linear_tone_beep = 1;
-       spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
-       spec->pin_nids = stac9872_pin_nids;
 
        spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
                                                        stac9872_models,
index 019e1a00414a460cb7a43c8c6bf142ecc2f01d38..09bb64996d72ee3dba0335fa07b2cb3bf44fa2a9 100644 (file)
@@ -76,6 +76,8 @@ enum VIA_HDA_CODEC {
        VT2002P,
        VT1812,
        VT1802,
+       VT1705CF,
+       VT1808,
        CODEC_TYPES,
 };
 
@@ -220,6 +222,7 @@ struct via_spec {
        int vt1708_hp_present;
 
        void (*set_widgets_power_state)(struct hda_codec *codec);
+       unsigned int dac_stream_tag[4];
 
        struct hda_loopback_check loopback;
        int num_loopbacks;
@@ -241,6 +244,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
        if (spec == NULL)
                return NULL;
 
+       snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
        mutex_init(&spec->config_mutex);
        codec->spec = spec;
        spec->codec = codec;
@@ -295,6 +299,10 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
                codec_type = VT1708S;
        else if ((dev_id & 0xfff) == 0x446)
                codec_type = VT1802;
+       else if (dev_id == 0x4760)
+               codec_type = VT1705CF;
+       else if (dev_id == 0x4761 || dev_id == 0x4762)
+               codec_type = VT1808;
        else
                codec_type = UNKNOWN;
        return codec_type;
@@ -387,7 +395,6 @@ static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec,
 {
        struct snd_kcontrol_new *knew;
 
-       snd_array_init(&spec->kctls, sizeof(*knew), 32);
        knew = snd_array_new(&spec->kctls);
        if (!knew)
                return NULL;
@@ -711,6 +718,28 @@ static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
 }
 
+static void update_conv_power_state(struct hda_codec *codec, hda_nid_t nid,
+                              unsigned int parm, unsigned int index)
+{
+       struct via_spec *spec = codec->spec;
+       unsigned int format;
+       if (snd_hda_codec_read(codec, nid, 0,
+                              AC_VERB_GET_POWER_STATE, 0) == parm)
+               return;
+       format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
+       if (format && (spec->dac_stream_tag[index] != format))
+               spec->dac_stream_tag[index] = format;
+
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+       if (parm == AC_PWRST_D0) {
+               format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
+               if (!format && (spec->dac_stream_tag[index] != format))
+                       snd_hda_codec_write(codec, nid, 0,
+                                                 AC_VERB_SET_CHANNEL_STREAMID,
+                                                 spec->dac_stream_tag[index]);
+       }
+}
+
 static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
                                unsigned int *affected_parm)
 {
@@ -739,18 +768,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
 static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
                                  struct snd_ctl_elem_info *uinfo)
 {
-       static const char * const texts[] = {
-               "Disabled", "Enabled"
-       };
-
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = 1;
-       uinfo->value.enumerated.items = 2;
-       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-       strcpy(uinfo->value.enumerated.name,
-              texts[uinfo->value.enumerated.item]);
-       return 0;
+       return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
 }
 
 static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
@@ -1096,6 +1114,11 @@ static void __analog_low_current_mode(struct hda_codec *codec, bool force)
                verb = 0xf93;
                parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
                break;
+       case VT1705CF:
+       case VT1808:
+               verb = 0xf82;
+               parm = enable ? 0x00 : 0xe0;  /* 0x00: 4/40x, 0xe0: 1x */
+               break;
        default:
                return;         /* other codecs are not supported */
        }
@@ -1454,7 +1477,7 @@ static const struct hda_pcm_stream via_pcm_digital_capture = {
  */
 static const char * const via_slave_pfxs[] = {
        "Front", "Surround", "Center", "LFE", "Side",
-       "Headphone", "Speaker",
+       "Headphone", "Speaker", "Bass Speaker",
        NULL,
 };
 
@@ -1555,6 +1578,10 @@ static int via_build_pcms(struct hda_codec *codec)
                                spec->multiout.dac_nids[0];
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
                                spec->multiout.max_channels;
+                       if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT
+                           && spec->autocfg.line_outs == 2)
+                               info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
+                                       snd_pcm_2_1_chmaps;
                }
 
                if (!spec->stream_analog_capture) {
@@ -1934,7 +1961,7 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec)
        struct auto_pin_cfg *cfg = &spec->autocfg;
        struct nid_path *path;
        static const char * const chname[4] = {
-               "Front", "Surround", "C/LFE", "Side"
+               "Front", "Surround", NULL /* "CLFE" */, "Side"
        };
        int i, idx, err;
        int old_line_outs;
@@ -1969,8 +1996,8 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec)
                } else {
                        const char *pfx = chname[i];
                        if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
-                           cfg->line_outs == 1)
-                               pfx = "Speaker";
+                           cfg->line_outs <= 2)
+                               pfx = i ? "Bass Speaker" : "Speaker";
                        err = create_ch_ctls(codec, pfx, 3, true, path);
                        if (err < 0)
                                return err;
@@ -3824,6 +3851,125 @@ static int patch_vt1812(struct hda_codec *codec)
        return 0;
 }
 
+/* patch for vt3476 */
+
+static const struct hda_verb vt3476_init_verbs[] = {
+       /* Enable DMic 8/16/32K */
+       {0x1, 0xF7B, 0x30},
+       /* Enable Boost Volume backdoor */
+       {0x1, 0xFB9, 0x20},
+       /* Enable AOW-MW9 path */
+       {0x1, 0xFB8, 0x10},
+       { }
+};
+
+static void set_widgets_power_state_vt3476(struct hda_codec *codec)
+{
+       struct via_spec *spec = codec->spec;
+       int imux_is_smixer;
+       unsigned int parm, parm2;
+       /* MUX10 (1eh) = stereo mixer */
+       imux_is_smixer =
+       snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 4;
+       /* inputs */
+       /* PW 5/6/7 (29h/2ah/2bh) */
+       parm = AC_PWRST_D3;
+       set_pin_power_state(codec, 0x29, &parm);
+       set_pin_power_state(codec, 0x2a, &parm);
+       set_pin_power_state(codec, 0x2b, &parm);
+       if (imux_is_smixer)
+               parm = AC_PWRST_D0;
+       /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
+       update_power_state(codec, 0x1e, parm);
+       update_power_state(codec, 0x1f, parm);
+       update_power_state(codec, 0x10, parm);
+       update_power_state(codec, 0x11, parm);
+
+       /* outputs */
+       /* PW3 (27h), MW3(37h), AOW3 (bh) */
+       if (spec->codec_type == VT1705CF) {
+               parm = AC_PWRST_D3;
+               update_power_state(codec, 0x27, parm);
+               update_power_state(codec, 0x37, parm);
+       }       else {
+               parm = AC_PWRST_D3;
+               set_pin_power_state(codec, 0x27, &parm);
+               update_power_state(codec, 0x37, parm);
+       }
+
+       /* PW2 (26h), MW2(36h), AOW2 (ah) */
+       parm = AC_PWRST_D3;
+       set_pin_power_state(codec, 0x26, &parm);
+       update_power_state(codec, 0x36, parm);
+       if (spec->smart51_enabled) {
+               /* PW7(2bh), MW7(3bh), MUX7(1Bh) */
+               set_pin_power_state(codec, 0x2b, &parm);
+               update_power_state(codec, 0x3b, parm);
+               update_power_state(codec, 0x1b, parm);
+       }
+       update_conv_power_state(codec, 0xa, parm, 2);
+
+       /* PW1 (25h), MW1(35h), AOW1 (9h) */
+       parm = AC_PWRST_D3;
+       set_pin_power_state(codec, 0x25, &parm);
+       update_power_state(codec, 0x35, parm);
+       if (spec->smart51_enabled) {
+               /* PW6(2ah), MW6(3ah), MUX6(1ah) */
+               set_pin_power_state(codec, 0x2a, &parm);
+               update_power_state(codec, 0x3a, parm);
+               update_power_state(codec, 0x1a, parm);
+       }
+       update_conv_power_state(codec, 0x9, parm, 1);
+
+       /* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
+       parm = AC_PWRST_D3;
+       set_pin_power_state(codec, 0x28, &parm);
+       update_power_state(codec, 0x38, parm);
+       update_power_state(codec, 0x18, parm);
+       if (spec->hp_independent_mode)
+               update_conv_power_state(codec, 0xb, parm, 3);
+       parm2 = parm; /* for pin 0x0b */
+
+       /* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
+       parm = AC_PWRST_D3;
+       set_pin_power_state(codec, 0x24, &parm);
+       update_power_state(codec, 0x34, parm);
+       if (!spec->hp_independent_mode && parm2 != AC_PWRST_D3)
+               parm = parm2;
+       update_conv_power_state(codec, 0x8, parm, 0);
+       /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
+       update_power_state(codec, 0x3f, imux_is_smixer ? AC_PWRST_D0 : parm);
+}
+
+static int patch_vt3476(struct hda_codec *codec)
+{
+       struct via_spec *spec;
+       int err;
+
+       /* create a codec specific record */
+       spec = via_new_spec(codec);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       spec->aa_mix_nid = 0x3f;
+       add_secret_dac_path(codec);
+
+       /* automatic parse from the BIOS config */
+       err = via_parse_auto_config(codec);
+       if (err < 0) {
+               via_free(codec);
+               return err;
+       }
+
+       spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
+
+       codec->patch_ops = via_patch_ops;
+
+       spec->set_widgets_power_state = set_widgets_power_state_vt3476;
+
+       return 0;
+}
+
 /*
  * patch entries
  */
@@ -3917,6 +4063,12 @@ static const struct hda_codec_preset snd_hda_preset_via[] = {
                .patch = patch_vt2002P},
        { .id = 0x11068446, .name = "VT1802",
                .patch = patch_vt2002P},
+       { .id = 0x11064760, .name = "VT1705CF",
+               .patch = patch_vt3476},
+       { .id = 0x11064761, .name = "VT1708SCE",
+               .patch = patch_vt3476},
+       { .id = 0x11064762, .name = "VT1808",
+               .patch = patch_vt3476},
        {} /* terminator */
 };
 
index f7ce33f00ea5eae767e4e14732a6de8077bec841..7e50c1324556df83e7dbb2f3cd8a7a11ed5eb7f4 100644 (file)
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o psc724.o wm8766.o wm8776.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
index e525da2673be3c5a4b12de44eb7c81e6ccadfcdd..2f9b934678673e077657436b49127cc15d5b7045 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -38,7 +37,7 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
        snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
 }
 
-static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
+static int snd_vt1724_amp_init(struct snd_ice1712 *ice)
 {
        static const unsigned short wm_inits[] = {
                WM_ATTEN_L,     0x0000, /* 0 db */
@@ -66,7 +65,7 @@ static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
+static int snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
 {
        if (ice->ac97)
                /* we use pins 39 and 41 of the VT1616 for left and right
@@ -78,7 +77,7 @@ static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_amp_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_AV710,
                .name = "Chaintech AV-710",
index 20bcddea2eab19320d25299180368a815bc4f90f..55902ec40344d824b17d56d37d047f79281ba294 100644 (file)
@@ -46,7 +46,6 @@
  *                    on mixer switch and other coll stuff.
  */
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -203,7 +202,8 @@ static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_info *uinfo)
 {
-       char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
+       static const char * const texts[3] =
+               {"Internal Aux", "Wavetable", "Rear Line-In"};
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -1433,7 +1433,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
  * mixers
  */
 
-static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new aureon_dac_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -1548,7 +1548,7 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
        }
 };
 
-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "PCM Playback Switch",
@@ -1614,7 +1614,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
        }
 };
 
-static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new ac97_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "AC97 Playback Switch",
@@ -1719,7 +1719,7 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
        }
 };
 
-static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new universe_ac97_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "AC97 Playback Switch",
@@ -1851,7 +1851,7 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
 
 };
 
-static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
+static struct snd_kcontrol_new cs8415_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
@@ -1896,7 +1896,7 @@ static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
        }
 };
 
-static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
+static int aureon_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int i, counts;
        int err;
@@ -2124,7 +2124,7 @@ static int aureon_resume(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
-static int __devinit aureon_init(struct snd_ice1712 *ice)
+static int aureon_init(struct snd_ice1712 *ice)
 {
        struct aureon_spec *spec;
        int i, err;
@@ -2174,7 +2174,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char aureon51_eeprom[] __devinitdata = {
+static unsigned char aureon51_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
@@ -2190,7 +2190,7 @@ static unsigned char aureon51_eeprom[] __devinitdata = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char aureon71_eeprom[] __devinitdata = {
+static unsigned char aureon71_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
@@ -2207,7 +2207,7 @@ static unsigned char aureon71_eeprom[] __devinitdata = {
 };
 #define prodigy71_eeprom aureon71_eeprom
 
-static unsigned char aureon71_universe_eeprom[] __devinitdata = {
+static unsigned char aureon71_universe_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, spdif-in/ADC,
                                         * 4DACs
                                         */
@@ -2225,7 +2225,7 @@ static unsigned char aureon71_universe_eeprom[] __devinitdata = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char prodigy71lt_eeprom[] __devinitdata = {
+static unsigned char prodigy71lt_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
@@ -2243,7 +2243,7 @@ static unsigned char prodigy71lt_eeprom[] __devinitdata = {
 #define prodigy71xt_eeprom prodigy71lt_eeprom
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
                .name = "Terratec Aureon 5.1-Sky",
index 20c6b079d0dfc33cfc4620006bbbe944e39e91b6..9e28cc12969b3632357ae4f198634da499864903 100644 (file)
@@ -22,7 +22,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -432,7 +431,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status =
 {
        .access =       (SNDRV_CTL_ELEM_ACCESS_READ),
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -445,7 +444,7 @@ static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devini
  * initialize the chips on M-Audio cards
  */
 
-static struct snd_akm4xxx akm_audiophile __devinitdata = {
+static struct snd_akm4xxx akm_audiophile = {
        .type = SND_AK4528,
        .num_adcs = 2,
        .num_dacs = 2,
@@ -454,7 +453,7 @@ static struct snd_akm4xxx akm_audiophile __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_audiophile_priv = {
        .caddr = 2,
        .cif = 0,
        .data_mask = ICE1712_DELTA_AP_DOUT,
@@ -466,7 +465,7 @@ static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_delta410 __devinitdata = {
+static struct snd_akm4xxx akm_delta410 = {
        .type = SND_AK4529,
        .num_adcs = 2,
        .num_dacs = 8,
@@ -475,7 +474,7 @@ static struct snd_akm4xxx akm_delta410 __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta410_priv = {
        .caddr = 0,
        .cif = 0,
        .data_mask = ICE1712_DELTA_AP_DOUT,
@@ -487,7 +486,7 @@ static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
+static struct snd_akm4xxx akm_delta1010lt = {
        .type = SND_AK4524,
        .num_adcs = 8,
        .num_dacs = 8,
@@ -497,7 +496,7 @@ static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta1010lt_priv = {
        .caddr = 2,
        .cif = 0, /* the default level of the CIF pin from AK4524 */
        .data_mask = ICE1712_DELTA_1010LT_DOUT,
@@ -509,7 +508,7 @@ static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_delta66e __devinitdata = {
+static struct snd_akm4xxx akm_delta66e = {
        .type = SND_AK4524,
        .num_adcs = 4,
        .num_dacs = 4,
@@ -519,7 +518,7 @@ static struct snd_akm4xxx akm_delta66e __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta66e_priv = {
        .caddr = 2,
        .cif = 0, /* the default level of the CIF pin from AK4524 */
        .data_mask = ICE1712_DELTA_66E_DOUT,
@@ -532,7 +531,7 @@ static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = {
 };
 
 
-static struct snd_akm4xxx akm_delta44 __devinitdata = {
+static struct snd_akm4xxx akm_delta44 = {
        .type = SND_AK4524,
        .num_adcs = 4,
        .num_dacs = 4,
@@ -542,7 +541,7 @@ static struct snd_akm4xxx akm_delta44 __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta44_priv = {
        .caddr = 2,
        .cif = 0, /* the default level of the CIF pin from AK4524 */
        .data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA,
@@ -554,7 +553,7 @@ static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_vx442 __devinitdata = {
+static struct snd_akm4xxx akm_vx442 = {
        .type = SND_AK4524,
        .num_adcs = 4,
        .num_dacs = 4,
@@ -564,7 +563,7 @@ static struct snd_akm4xxx akm_vx442 __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_vx442_priv = {
        .caddr = 2,
        .cif = 0,
        .data_mask = ICE1712_VX442_DOUT,
@@ -576,7 +575,7 @@ static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+static int snd_ice1712_delta_init(struct snd_ice1712 *ice)
 {
        int err;
        struct snd_akm4xxx *ak;
@@ -617,7 +616,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
                ice->num_total_dacs = 4;        /* two AK4324 codecs */
                break;
        case ICE1712_SUBDEVICE_VX442:
-       case ICE1712_SUBDEVICE_DELTA66E:        /* omni not suported yet */
+       case ICE1712_SUBDEVICE_DELTA66E:        /* omni not supported yet */
                ice->num_total_dacs = 4;
                ice->num_total_adcs = 4;
                break;
@@ -714,19 +713,19 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
  * additional controls for M-Audio cards
  */
 
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
-static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
 
 
-static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+static int snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
 {
        int err;
 
@@ -802,7 +801,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_delta_cards[] = {
        {
                .subvendor = ICE1712_SUBDEVICE_DELTA1010,
                .name = "M Audio Delta 1010",
index 6fe35b8120400ddb8c073f9166879b9821984a33..bc2e7011c55d7fa184b63197f82ea7d6fab00a95 100644 (file)
@@ -22,7 +22,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -344,7 +343,7 @@ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate)
 
 /*
  */
-static struct snd_akm4xxx akm_ews88mt __devinitdata = {
+static struct snd_akm4xxx akm_ews88mt = {
        .num_adcs = 8,
        .num_dacs = 8,
        .type = SND_AK4524,
@@ -354,7 +353,7 @@ static struct snd_akm4xxx akm_ews88mt __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ews88mt_priv = {
        .caddr = 2,
        .cif = 1, /* CIF high */
        .data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -366,7 +365,7 @@ static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
+static struct snd_akm4xxx akm_ewx2496 = {
        .num_adcs = 2,
        .num_dacs = 2,
        .type = SND_AK4524,
@@ -375,7 +374,7 @@ static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ewx2496_priv = {
        .caddr = 2,
        .cif = 1, /* CIF high */
        .data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -387,7 +386,7 @@ static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_6fire __devinitdata = {
+static struct snd_akm4xxx akm_6fire = {
        .num_adcs = 6,
        .num_dacs = 6,
        .type = SND_AK4524,
@@ -396,7 +395,7 @@ static struct snd_akm4xxx akm_6fire __devinitdata = {
        }
 };
 
-static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_6fire_priv = {
        .caddr = 2,
        .cif = 1, /* CIF high */
        .data_mask = ICE1712_6FIRE_SERIAL_DATA,
@@ -420,7 +419,7 @@ static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
 
 static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data);
 
-static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+static int snd_ice1712_ews_init(struct snd_ice1712 *ice)
 {
        int err;
        struct snd_akm4xxx *ak;
@@ -576,7 +575,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
 /* i/o sensitivity - this callback is shared among other devices, too */
 static int snd_ice1712_ewx_io_sense_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){
 
-       static char *texts[2] = {
+       static const char * const texts[2] = {
                "+4dBu", "-10dBV",
        };
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -616,7 +615,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn
        return val != nval;
 }
 
-static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Input Sensitivity Switch",
@@ -724,7 +723,7 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st
        return ndata != data;
 }
 
-static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Input Sensitivity Switch",
        .info = snd_ice1712_ewx_io_sense_info,
@@ -733,7 +732,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
        .count = 8,
 };
 
-static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Output Sensitivity Switch",
        .info = snd_ice1712_ewx_io_sense_info,
@@ -811,7 +810,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct
   .private_value = xshift | (xinvert << 8),\
 }
 
-static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] = {
        EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
        EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
        EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -899,7 +898,7 @@ static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct s
 
 static int snd_ice1712_6fire_select_input_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[4] = {
+       static const char * const texts[4] = {
                "Internal", "Front Input", "Rear Input", "Wave Table"
        };
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -948,7 +947,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str
   .private_value = xshift | (xinvert << 8),\
 }
 
-static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_6fire_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Analog Input Select",
@@ -964,7 +963,7 @@ static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
 };
 
 
-static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+static int snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int idx;
        int err;
@@ -1030,7 +1029,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_ews_cards[] = {
        {
                .subvendor = ICE1712_SUBDEVICE_EWX2496,
                .name = "TerraTec EWX24/96",
index 6914189073a4d11ad81194e5cb7ad91c0a59e7da..59e37c581691e4e2b9072791956c4fee2ea09771 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -40,7 +39,7 @@ struct hoontech_spec {
        unsigned short boxconfig[4];
 };
 
-static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
+static void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
 {
        byte |= ICE1712_STDSP24_CLOCK_BIT;
        udelay(100);
@@ -53,7 +52,7 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, un
        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
 }
 
-static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
 {
        struct hoontech_spec *spec = ice->spec;
        mutex_lock(&ice->gpio_mutex);
@@ -62,7 +61,7 @@ static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int ac
        mutex_unlock(&ice->gpio_mutex);
 }
 
-static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
 {
        struct hoontech_spec *spec = ice->spec;
        mutex_lock(&ice->gpio_mutex);
@@ -71,7 +70,7 @@ static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int acti
        mutex_unlock(&ice->gpio_mutex);
 }
 
-static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
 {
        struct hoontech_spec *spec = ice->spec;
        mutex_lock(&ice->gpio_mutex);
@@ -80,7 +79,7 @@ static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int act
        mutex_unlock(&ice->gpio_mutex);
 }
 
-static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
+static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
 {
        struct hoontech_spec *spec = ice->spec;
 
@@ -130,7 +129,7 @@ static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, i
        mutex_unlock(&ice->gpio_mutex);
 }
 
-static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
+static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
 {
        struct hoontech_spec *spec = ice->spec;
 
@@ -158,7 +157,7 @@ static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int
        mutex_unlock(&ice->gpio_mutex);
 }
 
-static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
+static void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
 {
        struct hoontech_spec *spec = ice->spec;
        mutex_lock(&ice->gpio_mutex);
@@ -167,7 +166,7 @@ static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int act
        mutex_unlock(&ice->gpio_mutex);
 }
 
-static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+static int snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
 {
        struct hoontech_spec *spec;
        int box, chn;
@@ -267,10 +266,10 @@ static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
        snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
 }
 
-static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
+static int snd_ice1712_value_init(struct snd_ice1712 *ice)
 {
        /* Hoontech STDSP24 with modified hardware */
-       static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
+       static struct snd_akm4xxx akm_stdsp24_mv = {
                .num_adcs = 2,
                .num_dacs = 2,
                .type = SND_AK4524,
@@ -279,7 +278,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
                }
        };
 
-       static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
+       static struct snd_ak4xxx_private akm_stdsp24_mv_priv = {
                .caddr = 2,
                .cif = 1, /* CIF high */
                .data_mask = ICE1712_STDSP24_SERIAL_DATA,
@@ -317,7 +316,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
+static int snd_ice1712_ez8_init(struct snd_ice1712 *ice)
 {
        ice->gpio.write_mask = ice->eeprom.gpiomask;
        ice->gpio.direction = ice->eeprom.gpiodir;
@@ -329,7 +328,7 @@ static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] = {
        {
                .subvendor = ICE1712_SUBDEVICE_STDSP24,
                .name = "Hoontech SoundTrack Audio DSP24",
index 5be2e120a14e25a03744b873e690f765eecb9545..2ffdc35d5ffdca6ba5e1d1587feae59e6d08beaa 100644 (file)
@@ -47,7 +47,6 @@
  */
 
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -280,7 +279,7 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru
        return val != nval;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Digital Mixer To AC97",
        .info = snd_ice1712_digmix_route_ac97_info,
@@ -388,7 +387,7 @@ static void setup_cs8427(struct snd_ice1712 *ice, int rate)
 /*
  * create and initialize callbacks for cs8427 interface
  */
-int __devinit snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
+int snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
 {
        int err;
 
@@ -879,7 +878,7 @@ static struct snd_pcm_ops snd_ice1712_capture_ops = {
        .pointer =      snd_ice1712_capture_pointer,
 };
 
-static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -909,7 +908,7 @@ static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct
        return 0;
 }
 
-static int __devinit snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1254,7 +1253,7 @@ static struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
        .pointer =      snd_ice1712_capture_pro_pointer,
 };
 
-static int __devinit snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1388,7 +1387,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc
 
 static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
 
-static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Multi Playback Switch",
@@ -1412,7 +1411,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata
        },
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "H/W Multi Capture Switch",
        .info = snd_ice1712_pro_mixer_switch_info,
@@ -1421,7 +1420,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinit
        .private_value = 10,
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, SWITCH),
        .info = snd_ice1712_pro_mixer_switch_info,
@@ -1431,7 +1430,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitd
        .count = 2,
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
                   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -1443,7 +1442,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinit
        .tlv = { .p = db_scale_playback }
 };
 
-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, VOLUME),
        .info = snd_ice1712_pro_mixer_volume_info,
@@ -1453,7 +1452,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitd
        .count = 2,
 };
 
-static int __devinit snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
+static int snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
 {
        struct snd_card *card = ice->card;
        unsigned int idx;
@@ -1512,7 +1511,7 @@ static void snd_ice1712_mixer_free_ac97(struct snd_ac97 *ac97)
        ice->ac97 = NULL;
 }
 
-static int __devinit snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
+static int snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
 {
        int err, bus_num = 0;
        struct snd_ac97_template ac97;
@@ -1611,7 +1610,7 @@ static void snd_ice1712_proc_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "  GPIO_DIRECTION   : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION));
 }
 
-static void __devinit snd_ice1712_proc_init(struct snd_ice1712 *ice)
+static void snd_ice1712_proc_init(struct snd_ice1712 *ice)
 {
        struct snd_info_entry *entry;
 
@@ -1640,7 +1639,7 @@ static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_eeprom = {
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .name = "ICE1712 EEPROM",
        .access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1676,7 +1675,7 @@ static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_default =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
@@ -1727,7 +1726,7 @@ static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskc =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1736,7 +1735,7 @@ static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
        .get =          snd_ice1712_spdif_maskc_get,
 };
 
-static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskp =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1763,7 +1762,7 @@ static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_stream =
 {
        .access =       (SNDRV_CTL_ELEM_ACCESS_READWRITE |
                         SNDRV_CTL_ELEM_ACCESS_INACTIVE),
@@ -1894,7 +1893,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Internal Clock",
        .info = snd_ice1712_pro_internal_clock_info,
@@ -1965,7 +1964,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont
        return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Internal Clock Default",
        .info = snd_ice1712_pro_internal_clock_default_info,
@@ -1996,7 +1995,7 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_locking = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Rate Locking",
        .info = snd_ice1712_pro_rate_locking_info,
@@ -2027,7 +2026,7 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_reset = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Rate Reset",
        .info = snd_ice1712_pro_rate_reset_info,
@@ -2194,7 +2193,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "H/W Playback Route",
        .info = snd_ice1712_pro_route_info,
@@ -2202,7 +2201,7 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata
        .put = snd_ice1712_pro_route_analog_put,
 };
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route",
        .info = snd_ice1712_pro_route_info,
@@ -2244,7 +2243,7 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Volume Rate",
        .info = snd_ice1712_pro_volume_rate_info,
@@ -2277,7 +2276,7 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak = {
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "Multi Track Peak",
        .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2292,16 +2291,16 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
 /*
  * list of available boards
  */
-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static struct snd_ice1712_card_info *card_tables[] = {
        snd_ice1712_hoontech_cards,
        snd_ice1712_delta_cards,
        snd_ice1712_ews_cards,
        NULL,
 };
 
-static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
-                                                unsigned char dev,
-                                                unsigned char addr)
+static unsigned char snd_ice1712_read_i2c(struct snd_ice1712 *ice,
+                                         unsigned char dev,
+                                         unsigned char addr)
 {
        long t = 0x10000;
 
@@ -2311,8 +2310,8 @@ static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
        return inb(ICEREG(ice, I2C_DATA));
 }
 
-static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
-                                            const char *modelname)
+static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
+                                  const char *modelname)
 {
        int dev = 0xa0;         /* EEPROM device address */
        unsigned int i, size;
@@ -2386,7 +2385,7 @@ static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
 
 
 
-static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
+static int snd_ice1712_chip_init(struct snd_ice1712 *ice)
 {
        outb(ICE1712_RESET | ICE1712_NATIVE, ICEREG(ice, CONTROL));
        udelay(200);
@@ -2433,7 +2432,7 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
+int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
 {
        int err;
        struct snd_kcontrol *kctl;
@@ -2461,7 +2460,7 @@ int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
 }
 
 
-static int __devinit snd_ice1712_build_controls(struct snd_ice1712 *ice)
+static int snd_ice1712_build_controls(struct snd_ice1712 *ice)
 {
        int err;
 
@@ -2531,13 +2530,13 @@ static int snd_ice1712_dev_free(struct snd_device *device)
        return snd_ice1712_free(ice);
 }
 
-static int __devinit snd_ice1712_create(struct snd_card *card,
-                                       struct pci_dev *pci,
-                                       const char *modelname,
-                                       int omni,
-                                       int cs8427_timeout,
-                                       int dxr_enable,
-                                       struct snd_ice1712 **r_ice1712)
+static int snd_ice1712_create(struct snd_card *card,
+                             struct pci_dev *pci,
+                             const char *modelname,
+                             int omni,
+                             int cs8427_timeout,
+                             int dxr_enable,
+                             struct snd_ice1712 **r_ice1712)
 {
        struct snd_ice1712 *ice;
        int err;
@@ -2651,10 +2650,10 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
  *
  */
 
-static struct snd_ice1712_card_info no_matched __devinitdata;
+static struct snd_ice1712_card_info no_matched;
 
-static int __devinit snd_ice1712_probe(struct pci_dev *pci,
-                                      const struct pci_device_id *pci_id)
+static int snd_ice1712_probe(struct pci_dev *pci,
+                            const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -2686,6 +2685,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
        for (tbl = card_tables; *tbl; tbl++) {
                for (c = *tbl; c->subvendor; c++) {
                        if (c->subvendor == ice->eeprom.subvendor) {
+                               ice->card_info = c;
                                strcpy(card->shortname, c->name);
                                if (c->driver) /* specific driver? */
                                        strcpy(card->driver, c->driver);
@@ -2797,9 +2797,14 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_ice1712_remove(struct pci_dev *pci)
+static void snd_ice1712_remove(struct pci_dev *pci)
 {
-       snd_card_free(pci_get_drvdata(pci));
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (ice->card_info && ice->card_info->chip_exit)
+               ice->card_info->chip_exit(ice);
+       snd_card_free(card);
        pci_set_drvdata(pci, NULL);
 }
 
@@ -2807,7 +2812,7 @@ static struct pci_driver ice1712_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ice1712_ids,
        .probe = snd_ice1712_probe,
-       .remove = __devexit_p(snd_ice1712_remove),
+       .remove = snd_ice1712_remove,
 };
 
 module_pci_driver(ice1712_driver);
index d0e7d87f09f0ed4947462630906ec02249e583c6..b209fc30b334b455c7a83701f1f5b398de4881e4 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/io.h>
 #include <sound/control.h>
 #include <sound/ac97_codec.h>
 #include <sound/rawmidi.h>
@@ -288,6 +289,7 @@ struct snd_ice1712_spdif {
        } ops;
 };
 
+struct snd_ice1712_card_info;
 
 struct snd_ice1712 {
        unsigned long conp_dma_size;
@@ -324,6 +326,7 @@ struct snd_ice1712 {
        struct snd_info_entry *proc_entry;
 
        struct snd_ice1712_eeprom eeprom;
+       struct snd_ice1712_card_info *card_info;
 
        unsigned int pro_volumes[20];
        unsigned int omni:1;            /* Delta Omni I/O */
@@ -381,7 +384,7 @@ struct snd_ice1712 {
        unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
        int (*set_spdif_clock)(struct snd_ice1712 *ice, int type);
        int (*get_spdif_master_type)(struct snd_ice1712 *ice);
-       char **ext_clock_names;
+       const char * const *ext_clock_names;
        int ext_clock_count;
        void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *);
 #ifdef CONFIG_PM_SLEEP
@@ -513,10 +516,11 @@ static inline u8 snd_ice1712_read(struct snd_ice1712 *ice, u8 addr)
 
 struct snd_ice1712_card_info {
        unsigned int subvendor;
-       char *name;
-       char *model;
-       char *driver;
+       const char *name;
+       const char *model;
+       const char *driver;
        int (*chip_init)(struct snd_ice1712 *);
+       void (*chip_exit)(struct snd_ice1712 *);
        int (*build_controls)(struct snd_ice1712 *);
        unsigned int no_mpu401:1;
        unsigned int mpu401_1_info_flags;
index 245d874891ba25c2d993ea9de44536e0ab27ae6e..ce70e7f113e0545f90e70edfd363271b9455dc58 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -54,6 +53,7 @@
 #include "wtm.h"
 #include "se.h"
 #include "quartet.h"
+#include "psc724.h"
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -106,7 +106,7 @@ static int PRO_RATE_LOCKED;
 static int PRO_RATE_RESET = 1;
 static unsigned int PRO_RATE_DEFAULT = 44100;
 
-static char *ext_clock_names[1] = { "IEC958 In" };
+static const char * const ext_clock_names[1] = { "IEC958 In" };
 
 /*
  *  Basic I/O
@@ -1135,7 +1135,7 @@ static struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
        .pointer =      snd_vt1724_pcm_pointer,
 };
 
-static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
+static int snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
 {
        struct snd_pcm *pcm;
        int capt, err;
@@ -1315,7 +1315,7 @@ static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
 };
 
 
-static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
+static int snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
 {
        char *name;
        struct snd_pcm *pcm;
@@ -1449,7 +1449,7 @@ static struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
 };
 
 
-static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
+static int snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
 {
        struct snd_pcm *pcm;
        int play;
@@ -1484,7 +1484,7 @@ static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
  *  Mixer section
  */
 
-static int __devinit snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
+static int snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
 {
        int err;
 
@@ -1570,7 +1570,7 @@ static void snd_vt1724_proc_read(struct snd_info_entry *entry,
                            idx, inb(ice->profi_port+idx));
 }
 
-static void __devinit snd_vt1724_proc_init(struct snd_ice1712 *ice)
+static void snd_vt1724_proc_init(struct snd_ice1712 *ice)
 {
        struct snd_info_entry *entry;
 
@@ -1599,7 +1599,7 @@ static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_eeprom = {
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .name = "ICE1724 EEPROM",
        .access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1712,7 +1712,7 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol,
        return val != old;
 }
 
-static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_default =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
@@ -1744,7 +1744,7 @@ static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskc =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1753,7 +1753,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
        .get =          snd_vt1724_spdif_maskc_get,
 };
 
-static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskp =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1790,7 +1790,7 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol,
        return old != val;
 }
 
-static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_switch =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        /* FIXME: the following conflict with IEC958 Playback Route */
@@ -1965,7 +1965,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
        return old_rate != new_rate;
 }
 
-static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_internal_clock = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Internal Clock",
        .info = snd_vt1724_pro_internal_clock_info,
@@ -1996,7 +1996,7 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_locking = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Rate Locking",
        .info = snd_vt1724_pro_rate_locking_info,
@@ -2027,7 +2027,7 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_reset = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Multi Track Rate Reset",
        .info = snd_vt1724_pro_rate_reset_info,
@@ -2042,7 +2042,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
 static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol,
                                     struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[] = {
+       static const char * const texts[] = {
                "PCM Out", /* 0 */
                "H/W In 0", "H/W In 1", /* 1-2 */
                "IEC958 In L", "IEC958 In R", /* 3-4 */
@@ -2149,7 +2149,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
                                         digital_route_shift(idx));
 }
 
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "H/W Playback Route",
@@ -2158,7 +2158,7 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
        .put = snd_vt1724_pro_route_analog_put,
 };
 
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route",
        .info = snd_vt1724_pro_route_info,
@@ -2194,7 +2194,7 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "Multi Track Peak",
        .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2206,13 +2206,13 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
  *
  */
 
-static struct snd_ice1712_card_info no_matched __devinitdata;
+static struct snd_ice1712_card_info no_matched;
 
 
 /*
   ooAoo cards with no controls
 */
-static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
+static unsigned char ooaoo_sq210_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x4c,  /* 49MHz crystal, no mpu401, no ADC,
                                           1xDACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -2232,7 +2232,7 @@ static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
 };
 
 
-struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
+static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] = {
        {
                .name = "ooAoo SQ210a",
                .model = "sq210a",
@@ -2242,7 +2242,7 @@ struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
        { } /* terminator */
 };
 
-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static struct snd_ice1712_card_info *card_tables[] = {
        snd_vt1724_revo_cards,
        snd_vt1724_amp_cards,
        snd_vt1724_aureon_cards,
@@ -2257,6 +2257,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
        snd_vt1724_se_cards,
        snd_vt1724_qtet_cards,
        snd_vt1724_ooaoo_cards,
+       snd_vt1724_psc724_cards,
        NULL,
 };
 
@@ -2306,8 +2307,8 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice,
        mutex_unlock(&ice->i2c_mutex);
 }
 
-static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
-                                           const char *modelname)
+static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
+                                 const char *modelname)
 {
        const int dev = 0xa0;           /* EEPROM device address */
        unsigned int i, size;
@@ -2348,6 +2349,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
                                ice->eeprom.subvendor = c->subvendor;
                        } else if (c->subvendor != ice->eeprom.subvendor)
                                continue;
+                       ice->card_info = c;
                        if (!c->eeprom_size || !c->eeprom_data)
                                goto found;
                        /* if the EEPROM is given by the driver, use it */
@@ -2360,6 +2362,10 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
        }
        printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n",
               ice->eeprom.subvendor);
+#ifdef CONFIG_PM_SLEEP
+       /* assume AC97-only card which can suspend without additional code */
+       ice->pm_suspend_enabled = 1;
+#endif
 
  found:
        ice->eeprom.size = snd_vt1724_read_i2c(ice, dev, 0x04);
@@ -2371,7 +2377,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
                return -EIO;
        }
        ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05);
-       if (ice->eeprom.version != 2)
+       if (ice->eeprom.version != 1 && ice->eeprom.version != 2)
                printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n",
                       ice->eeprom.version);
        size = ice->eeprom.size - 6;
@@ -2424,7 +2430,7 @@ static int snd_vt1724_chip_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
+static int snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
 {
        int err;
        struct snd_kcontrol *kctl;
@@ -2466,7 +2472,7 @@ static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
 }
 
 
-static int __devinit snd_vt1724_build_controls(struct snd_ice1712 *ice)
+static int snd_vt1724_build_controls(struct snd_ice1712 *ice)
 {
        int err;
 
@@ -2526,10 +2532,10 @@ static int snd_vt1724_dev_free(struct snd_device *device)
        return snd_vt1724_free(ice);
 }
 
-static int __devinit snd_vt1724_create(struct snd_card *card,
-                                      struct pci_dev *pci,
-                                      const char *modelname,
-                                      struct snd_ice1712 **r_ice1712)
+static int snd_vt1724_create(struct snd_card *card,
+                            struct pci_dev *pci,
+                            const char *modelname,
+                            struct snd_ice1712 **r_ice1712)
 {
        struct snd_ice1712 *ice;
        int err;
@@ -2616,8 +2622,8 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
  *
  */
 
-static int __devinit snd_vt1724_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_vt1724_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -2786,9 +2792,14 @@ __found:
        return 0;
 }
 
-static void __devexit snd_vt1724_remove(struct pci_dev *pci)
+static void snd_vt1724_remove(struct pci_dev *pci)
 {
-       snd_card_free(pci_get_drvdata(pci));
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (ice->card_info && ice->card_info->chip_exit)
+               ice->card_info->chip_exit(ice);
+       snd_card_free(card);
        pci_set_drvdata(pci, NULL);
 }
 
@@ -2889,7 +2900,7 @@ static struct pci_driver vt1724_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vt1724_ids,
        .probe = snd_vt1724_probe,
-       .remove = __devexit_p(snd_vt1724_remove),
+       .remove = snd_vt1724_remove,
        .driver = {
                .pm = SND_VT1724_PM_OPS,
        },
index 14fd536b6452d6e5dda1ec01f12929a89c4cd7c0..8855933e710d7fe54e60ddffe6e509558f9b4589 100644 (file)
@@ -23,7 +23,6 @@
  *
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -283,7 +282,7 @@ static const struct snd_akm4xxx_dac_channel juli_dac[] = {
 };
 
 
-static struct snd_akm4xxx akm_juli_dac __devinitdata = {
+static struct snd_akm4xxx akm_juli_dac = {
        .type = SND_AK4358,
        .num_dacs = 8,  /* DAC1 - analog out
                           DAC2 - analog in monitor
@@ -358,7 +357,7 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
+static struct snd_kcontrol_new juli_mute_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -412,7 +411,7 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
        },
 };
 
-static char *slave_vols[] __devinitdata = {
+static char *slave_vols[] = {
        PCM_VOLUME,
        MONITOR_AN_IN_VOLUME,
        MONITOR_DIG_IN_VOLUME,
@@ -420,11 +419,11 @@ static char *slave_vols[] __devinitdata = {
        NULL
 };
 
-static __devinitdata
+static
 DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
 
-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
-               const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card,
+                                    const char *name)
 {
        struct snd_ctl_elem_id sid;
        memset(&sid, 0, sizeof(sid));
@@ -434,8 +433,9 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
        return snd_ctl_find_id(card, &sid);
 }
 
-static void __devinit add_slaves(struct snd_card *card,
-                                struct snd_kcontrol *master, char **list)
+static void add_slaves(struct snd_card *card,
+                      struct snd_kcontrol *master,
+                      char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -447,7 +447,7 @@ static void __devinit add_slaves(struct snd_card *card,
        }
 }
 
-static int __devinit juli_add_controls(struct snd_ice1712 *ice)
+static int juli_add_controls(struct snd_ice1712 *ice)
 {
        struct juli_spec *spec = ice->spec;
        int err;
@@ -579,7 +579,7 @@ static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
        }
 }
 
-static int __devinit juli_init(struct snd_ice1712 *ice)
+static int juli_init(struct snd_ice1712 *ice)
 {
        static const unsigned char ak4114_init_vals[] = {
                /* AK4117_REG_PWRDN */  AK4114_RST | AK4114_PWN |
@@ -667,7 +667,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char juli_eeprom[] __devinitdata = {
+static unsigned char juli_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, 1xADC, 1xDACs,
                                           SPDIF in */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -686,7 +686,7 @@ static unsigned char juli_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_juli_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_JULI,
                .name = "ESI Juli@",
index 726fd4b92e19e8d564adef229c9c5201a0785963..63aa39f06f02be728081d77c8b5c7d7a32ccdbd4 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
@@ -358,7 +357,7 @@ static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
 static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[] = { "Line", "Mic" };
+       static const char * const texts[] = { "Line", "Mic" };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -407,7 +406,7 @@ static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
 static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[] = {
+       static const char * const texts[] = {
                "PCM Out", /* 0 */
                "Input 1", "Input 2", "Input 3", "Input 4"
        };
@@ -455,7 +454,7 @@ static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
  * controls to be added
  */
 
-static struct snd_kcontrol_new maya_controls[] __devinitdata = {
+static struct snd_kcontrol_new maya_controls[] = {
        {
                .name = "Crossmix Playback Volume",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -545,7 +544,7 @@ static struct snd_kcontrol_new maya_controls[] __devinitdata = {
        },
 };
 
-static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
+static int maya44_add_controls(struct snd_ice1712 *ice)
 {
        int err, i;
 
@@ -562,8 +561,8 @@ static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
 /*
  * initialize a wm8776 chip
  */
-static void __devinit wm8776_init(struct snd_ice1712 *ice,
-                                 struct snd_wm8776 *wm, unsigned int addr)
+static void wm8776_init(struct snd_ice1712 *ice,
+                       struct snd_wm8776 *wm, unsigned int addr)
 {
        static const unsigned short inits_wm8776[] = {
                0x02, 0x100, /* R2: headphone L+R muted + update */
@@ -693,14 +692,14 @@ static struct snd_pcm_hw_constraint_list dac_rates = {
 /*
  * chip addresses on I2C bus
  */
-static unsigned char wm8776_addr[2] __devinitdata = {
+static unsigned char wm8776_addr[2] = {
        0x34, 0x36, /* codec 0 & 1 */
 };
 
 /*
  * initialize the chip
  */
-static int __devinit maya44_init(struct snd_ice1712 *ice)
+static int maya44_init(struct snd_ice1712 *ice)
 {
        int i;
        struct snd_maya44 *chip;
@@ -743,7 +742,7 @@ static int __devinit maya44_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char maya44_eeprom[] __devinitdata = {
+static unsigned char maya44_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x45,
                /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
        [ICE_EEP2_ACLINK]      = 0x80,
@@ -765,7 +764,7 @@ static unsigned char maya44_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_maya44_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_MAYA44,
                .name = "ESI Maya44",
index de29be8c96574e8bd89eacf81b9aee5eb8a51518..0011e04f36a23bc08dbeb8fbc2af4ead158ed69d 100644 (file)
@@ -42,7 +42,6 @@
  *   Digital receiver: CS8414-CS (supported in this release)
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -103,13 +102,13 @@ static const unsigned char wm_vol[256] = {
 #define WM_VOL_MAX     (sizeof(wm_vol) - 1)
 #define WM_VOL_MUTE    0x8000
 
-static struct snd_akm4xxx akm_phase22 __devinitdata = {
+static struct snd_akm4xxx akm_phase22 = {
        .type = SND_AK4524,
        .num_dacs = 2,
        .num_adcs = 2,
 };
 
-static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_phase22_priv = {
        .caddr =        2,
        .cif =          1,
        .data_mask =    1 << 4,
@@ -121,7 +120,7 @@ static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
        .mask_flags =   0,
 };
 
-static int __devinit phase22_init(struct snd_ice1712 *ice)
+static int phase22_init(struct snd_ice1712 *ice)
 {
        struct snd_akm4xxx *ak;
        int err;
@@ -158,7 +157,7 @@ static int __devinit phase22_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
+static int phase22_add_controls(struct snd_ice1712 *ice)
 {
        int err = 0;
 
@@ -172,7 +171,7 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
        return 0;
 }
 
-static unsigned char phase22_eeprom[] __devinitdata = {
+static unsigned char phase22_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x28,  /* clock 512, mpu 401,
                                        spdif-in/1xADC, 1xDACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -189,7 +188,7 @@ static unsigned char phase22_eeprom[] __devinitdata = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char phase28_eeprom[] __devinitdata = {
+static unsigned char phase28_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401,
                                        spdif-in/1xADC, 4xDACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -379,7 +378,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static int __devinit phase28_init(struct snd_ice1712 *ice)
+static int phase28_init(struct snd_ice1712 *ice)
 {
        static const unsigned short wm_inits_phase28[] = {
                /* These come first to reduce init pop noise */
@@ -722,7 +721,7 @@ static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
 static int phase28_oversampling_info(struct snd_kcontrol *k,
                                        struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[2] = { "128x", "64x" };
+       static const char * const texts[2] = { "128x", "64x"    };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -770,7 +769,7 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 
-static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new phase28_dac_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -885,7 +884,7 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        }
 };
 
-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "PCM Playback Switch",
@@ -919,7 +918,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
        }
 };
 
-static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
+static int phase28_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int i, counts;
        int err;
@@ -943,7 +942,7 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
        return 0;
 }
 
-struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_phase_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_PHASE22,
                .name = "Terratec PHASE 22",
index 92c1160d7ab52c52811609008ce9cfc6fbd54c18..5555eb4b2400696e640422aba6a231f0a47e43a0 100644 (file)
@@ -21,7 +21,6 @@
  *
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -550,7 +549,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
  * mixers
  */
 
-static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
+static struct snd_kcontrol_new pontis_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -697,7 +696,7 @@ static void cs_proc_init(struct snd_ice1712 *ice)
 }
 
 
-static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
+static int pontis_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int i;
        int err;
@@ -718,7 +717,7 @@ static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
-static int __devinit pontis_init(struct snd_ice1712 *ice)
+static int pontis_init(struct snd_ice1712 *ice)
 {
        static const unsigned short wm_inits[] = {
                /* These come first to reduce init pop noise */
@@ -805,7 +804,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char pontis_eeprom[] __devinitdata = {
+static unsigned char pontis_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x08,  /* clock 256, mpu401, spdif-in/ADC, 1DAC */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xf8,  /* vol, 96k, 24bit, 192k */
@@ -822,7 +821,7 @@ static unsigned char pontis_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1720_pontis_cards[] = {
        {
                .subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
                .name = "Pontis MS300",
index e36ddb94c382932a4e5c9b35095678d3b9c90ea5..e610339f7601416c972364192011e4f176819727 100644 (file)
@@ -54,7 +54,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -283,7 +282,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
 static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[2] = { "Line In", "Mic" };
+       static const char * const texts[2] = { "Line In", "Mic" };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -369,7 +368,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
  * mixers
  */
 
-static struct snd_kcontrol_new stac_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -562,7 +561,7 @@ static unsigned char prodigy192_ak4114_read(void *private_data,
 static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[2] = { "Toslink", "Coax" };
+       static const char * const texts[2] = { "Toslink", "Coax" };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
@@ -607,7 +606,7 @@ static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
+static struct snd_kcontrol_new ak4114_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "MIODIO IEC958 Capture Input",
@@ -672,7 +671,7 @@ static void stac9460_proc_init(struct snd_ice1712 *ice)
 }
 
 
-static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
+static int prodigy192_add_controls(struct snd_ice1712 *ice)
 {
        struct prodigy192_spec *spec = ice->spec;
        unsigned int i;
@@ -728,7 +727,7 @@ static int prodigy192_miodio_exists(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
-static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+static int prodigy192_init(struct snd_ice1712 *ice)
 {
        static const unsigned short stac_inits_prodigy[] = {
                STAC946X_RESET, 0,
@@ -784,7 +783,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char prodigy71_eeprom[] __devinitdata = {
+static unsigned char prodigy71_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x6a,  /* 49MHz crystal, mpu401,
                                         * spdif-in+ 1 stereo ADC,
                                         * 3 stereo DACs
@@ -808,7 +807,7 @@ static unsigned char prodigy71_eeprom[] __devinitdata = {
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
                .name = "Audiotrak Prodigy 192",
index 7bf093c51ce5a5569f6cec1a1f9e53a88763236f..2261d1e4915004281d3fcce7b29e243faff41689 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -299,7 +298,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
-static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
+static struct snd_kcontrol_new prodigy_hd2_controls[] = {
     {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -782,7 +781,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol,
  * mixers
  */
 
-static struct snd_kcontrol_new prodigy_hifi_controls[] __devinitdata = {
+static struct snd_kcontrol_new prodigy_hifi_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -939,7 +938,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
        }
 }
 
-static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice)
+static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int i;
        int err;
@@ -956,7 +955,7 @@ static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice)
+static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int i;
        int err;
@@ -977,7 +976,7 @@ static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
-static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice)
+static int prodigy_hifi_init(struct snd_ice1712 *ice)
 {
        static unsigned short wm_inits[] = {
                /* These come first to reduce init pop noise */
@@ -1115,7 +1114,7 @@ static int prodigy_hd2_resume(struct snd_ice1712 *ice)
 }
 #endif
 
-static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
+static int prodigy_hd2_init(struct snd_ice1712 *ice)
 {
        struct prodigy_hifi_spec *spec;
 
@@ -1152,7 +1151,7 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
 }
 
 
-static unsigned char prodigy71hifi_eeprom[] __devinitdata = {
+static unsigned char prodigy71hifi_eeprom[] = {
        0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
        0x80,   /* ACLINK: I2S */
        0xfc,   /* I2S: vol, 96k, 24bit, 192k */
@@ -1168,7 +1167,7 @@ static unsigned char prodigy71hifi_eeprom[] __devinitdata = {
        0x00,   /* GPIO_STATE2 */
 };
 
-static unsigned char prodigyhd2_eeprom[] __devinitdata = {
+static unsigned char prodigyhd2_eeprom[] = {
        0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
        0x80,   /* ACLINK: I2S */
        0xfc,   /* I2S: vol, 96k, 24bit, 192k */
@@ -1184,7 +1183,7 @@ static unsigned char prodigyhd2_eeprom[] __devinitdata = {
        0x00,   /* GPIO_STATE2 */
 };
 
-static unsigned char fortissimo4_eeprom[] __devinitdata = {
+static unsigned char fortissimo4_eeprom[] = {
        0x43,   /* SYSCONF: clock 512, ADC, 4DACs */    
        0x80,   /* ACLINK: I2S */
        0xfc,   /* I2S: vol, 96k, 24bit, 192k */
@@ -1201,7 +1200,7 @@ static unsigned char fortissimo4_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,
                .name = "Audiotrak Prodigy 7.1 HiFi",
diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c
new file mode 100644 (file)
index 0000000..302ac6d
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for Philips PSC724 Ultimate Edge
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "psc724.h"
+#include "wm8766.h"
+#include "wm8776.h"
+
+struct psc724_spec {
+       struct snd_wm8766 wm8766;
+       struct snd_wm8776 wm8776;
+       bool mute_all, jack_detect;
+       struct snd_ice1712 *ice;
+       struct delayed_work hp_work;
+       bool hp_connected;
+};
+
+/****************************************************************************/
+/*  PHILIPS PSC724 ULTIMATE EDGE                                            */
+/****************************************************************************/
+/*
+ *  VT1722 (Envy24GT) - 6 outputs, 4 inputs (only 2 used), 24-bit/96kHz
+ *
+ *  system configuration ICE_EEP2_SYSCONF=0x42
+ *    XIN1 49.152MHz
+ *    no MPU401
+ *    one stereo ADC, no S/PDIF receiver
+ *    three stereo DACs (FRONT, REAR, CENTER+LFE)
+ *
+ *  AC-Link configuration ICE_EEP2_ACLINK=0x80
+ *    use I2S, not AC97
+ *
+ *  I2S converters feature ICE_EEP2_I2S=0x30
+ *    I2S codec has no volume/mute control feature (bug!)
+ *    I2S codec does not support 96KHz or 192KHz (bug!)
+ *    I2S codec 24bits
+ *
+ *  S/PDIF configuration ICE_EEP2_SPDIF=0xc1
+ *    Enable integrated S/PDIF transmitter
+ *    internal S/PDIF out implemented
+ *    No S/PDIF input
+ *    External S/PDIF out implemented
+ *
+ *
+ * ** connected chips **
+ *
+ *  WM8776
+ *     2-channel DAC used for main output and stereo ADC (with 10-channel MUX)
+ *     AIN1: LINE IN, AIN2: CD/VIDEO, AIN3: AUX, AIN4: Front MIC, AIN5: Rear MIC
+ *     Controlled by I2C using VT1722 I2C interface:
+ *          MODE (pin16) -- GND
+ *          CE   (pin17) -- GND  I2C mode (address=0x34)
+ *          DI   (pin18) -- SDA  (VT1722 pin70)
+ *          CL   (pin19) -- SCLK (VT1722 pin71)
+ *
+ *  WM8766
+ *      6-channel DAC used for rear & center/LFE outputs (only 4 channels used)
+ *      Controlled by SPI using VT1722 GPIO pins:
+ *          MODE   (pin 1) -- GPIO19 (VT1722 pin99)
+ *          ML/I2S (pin11) -- GPIO18 (VT1722 pin98)
+ *          MC/IWL (pin12) -- GPIO17 (VT1722 pin97)
+ *          MD/DM  (pin13) -- GPIO16 (VT1722 pin96)
+ *          MUTE   (pin14) -- GPIO20 (VT1722 pin101)
+ *
+ *  GPIO14 is used as input for headphone jack detection (1 = connected)
+ *  GPIO22 is used as MUTE ALL output, grounding all 6 channels
+ *
+ * ** output pins and device names **
+ *
+ *   5.1ch name -- output connector color -- device (-D option)
+ *
+ *      FRONT 2ch                  -- green  -- plughw:0,0
+ *      CENTER(Lch) SUBWOOFER(Rch) -- orange -- plughw:0,2,0
+ *      REAR 2ch                   -- black  -- plughw:0,2,1
+ */
+
+/* codec access low-level functions */
+
+#define GPIO_HP_JACK   (1 << 14)
+#define GPIO_MUTE_SUR  (1 << 20)
+#define GPIO_MUTE_ALL  (1 << 22)
+
+#define JACK_INTERVAL  1000
+
+#define PSC724_SPI_DELAY 1
+
+#define PSC724_SPI_DATA        (1 << 16)
+#define PSC724_SPI_CLK (1 << 17)
+#define PSC724_SPI_LOAD        (1 << 18)
+#define PSC724_SPI_MASK        (PSC724_SPI_DATA | PSC724_SPI_CLK | PSC724_SPI_LOAD)
+
+static void psc724_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
+{
+       struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8766);
+       struct snd_ice1712 *ice = spec->ice;
+       u32 st, bits;
+       int i;
+
+       snd_ice1712_save_gpio_status(ice);
+
+       st = ((addr & 0x7f) << 9) | (data & 0x1ff);
+       snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | PSC724_SPI_MASK);
+       snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~PSC724_SPI_MASK);
+       bits = snd_ice1712_gpio_read(ice) & ~PSC724_SPI_MASK;
+       snd_ice1712_gpio_write(ice, bits);
+
+       for (i = 0; i < 16; i++) {
+               udelay(PSC724_SPI_DELAY);
+               bits &= ~PSC724_SPI_CLK;
+               /* MSB first */
+               st <<= 1;
+               if (st & 0x10000)
+                       bits |= PSC724_SPI_DATA;
+               else
+                       bits &= ~PSC724_SPI_DATA;
+               snd_ice1712_gpio_write(ice, bits);
+               /* CLOCK high */
+               udelay(PSC724_SPI_DELAY);
+               bits |= PSC724_SPI_CLK;
+               snd_ice1712_gpio_write(ice, bits);
+       }
+       /* LOAD high */
+       udelay(PSC724_SPI_DELAY);
+       bits |= PSC724_SPI_LOAD;
+       snd_ice1712_gpio_write(ice, bits);
+       /* LOAD low, DATA and CLOCK high */
+       udelay(PSC724_SPI_DELAY);
+       bits |= (PSC724_SPI_DATA | PSC724_SPI_CLK);
+       snd_ice1712_gpio_write(ice, bits);
+
+       snd_ice1712_restore_gpio_status(ice);
+}
+
+static void psc724_wm8776_write(struct snd_wm8776 *wm, u8 addr, u8 data)
+{
+       struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8776);
+
+       snd_vt1724_write_i2c(spec->ice, 0x34, addr, data);
+}
+
+/* mute all */
+
+static void psc724_set_master_switch(struct snd_ice1712 *ice, bool on)
+{
+       unsigned int bits = snd_ice1712_gpio_read(ice);
+       struct psc724_spec *spec = ice->spec;
+
+       spec->mute_all = !on;
+       if (on)
+               bits &= ~(GPIO_MUTE_ALL | GPIO_MUTE_SUR);
+       else
+               bits |= GPIO_MUTE_ALL | GPIO_MUTE_SUR;
+       snd_ice1712_gpio_write(ice, bits);
+}
+
+static bool psc724_get_master_switch(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       return !spec->mute_all;
+}
+
+/* jack detection */
+
+static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected)
+{
+       struct psc724_spec *spec = ice->spec;
+       struct snd_ctl_elem_id elem_id;
+       struct snd_kcontrol *kctl;
+       u16 power = spec->wm8776.regs[WM8776_REG_PWRDOWN] & ~WM8776_PWR_HPPD;
+
+       psc724_set_master_switch(ice, !hp_connected);
+       if (!hp_connected)
+               power |= WM8776_PWR_HPPD;
+       snd_wm8776_set_power(&spec->wm8776, power);
+       spec->hp_connected = hp_connected;
+       /* notify about master speaker mute change */
+       memset(&elem_id, 0, sizeof(elem_id));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strncpy(elem_id.name, "Master Speakers Playback Switch",
+                                               sizeof(elem_id.name));
+       kctl = snd_ctl_find_id(ice->card, &elem_id);
+       snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+       /* and headphone mute change */
+       strncpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
+                                               sizeof(elem_id.name));
+       kctl = snd_ctl_find_id(ice->card, &elem_id);
+       snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+}
+
+static void psc724_update_hp_jack_state(struct work_struct *work)
+{
+       struct psc724_spec *spec = container_of(work, struct psc724_spec,
+                                               hp_work.work);
+       struct snd_ice1712 *ice = spec->ice;
+       bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK;
+
+       schedule_delayed_work(&spec->hp_work, msecs_to_jiffies(JACK_INTERVAL));
+       if (hp_connected == spec->hp_connected)
+               return;
+       psc724_set_jack_state(ice, hp_connected);
+}
+
+static void psc724_set_jack_detection(struct snd_ice1712 *ice, bool on)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       if (spec->jack_detect == on)
+               return;
+
+       spec->jack_detect = on;
+       if (on) {
+               bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK;
+               psc724_set_jack_state(ice, hp_connected);
+               schedule_delayed_work(&spec->hp_work,
+                                       msecs_to_jiffies(JACK_INTERVAL));
+       } else
+               cancel_delayed_work_sync(&spec->hp_work);
+}
+
+static bool psc724_get_jack_detection(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       return spec->jack_detect;
+}
+
+/* mixer controls */
+
+struct psc724_control {
+       const char *name;
+       void (*set)(struct snd_ice1712 *ice, bool on);
+       bool (*get)(struct snd_ice1712 *ice);
+};
+
+static const struct psc724_control psc724_cont[] = {
+       {
+               .name = "Master Speakers Playback Switch",
+               .set = psc724_set_master_switch,
+               .get = psc724_get_master_switch,
+       },
+       {
+               .name = "Headphone Jack Detection Playback Switch",
+               .set = psc724_set_jack_detection,
+               .get = psc724_get_jack_detection,
+       },
+};
+
+static int psc724_ctl_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       ucontrol->value.integer.value[0] = psc724_cont[n].get(ice);
+
+       return 0;
+}
+
+static int psc724_ctl_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       psc724_cont[n].set(ice, ucontrol->value.integer.value[0]);
+
+       return 0;
+}
+
+static const char *front_volume        = "Front Playback Volume";
+static const char *front_switch        = "Front Playback Switch";
+static const char *front_zc    = "Front Zero Cross Detect Playback Switch";
+static const char *front_izd   = "Front Infinite Zero Detect Playback Switch";
+static const char *front_phase = "Front Phase Invert Playback Switch";
+static const char *front_deemph        = "Front Deemphasis Playback Switch";
+static const char *ain1_switch = "Line Capture Switch";
+static const char *ain2_switch = "CD Capture Switch";
+static const char *ain3_switch = "AUX Capture Switch";
+static const char *ain4_switch = "Front Mic Capture Switch";
+static const char *ain5_switch = "Rear Mic Capture Switch";
+static const char *rear_volume = "Surround Playback Volume";
+static const char *clfe_volume = "CLFE Playback Volume";
+static const char *rear_switch = "Surround Playback Switch";
+static const char *clfe_switch = "CLFE Playback Switch";
+static const char *rear_phase  = "Surround Phase Invert Playback Switch";
+static const char *clfe_phase  = "CLFE Phase Invert Playback Switch";
+static const char *rear_deemph = "Surround Deemphasis Playback Switch";
+static const char *clfe_deemph = "CLFE Deemphasis Playback Switch";
+static const char *rear_clfe_izd = "Rear Infinite Zero Detect Playback Switch";
+static const char *rear_clfe_zc        = "Rear Zero Cross Detect Playback Switch";
+
+static int psc724_add_controls(struct snd_ice1712 *ice)
+{
+       struct snd_kcontrol_new cont;
+       struct snd_kcontrol *ctl;
+       int err, i;
+       struct psc724_spec *spec = ice->spec;
+
+       spec->wm8776.ctl[WM8776_CTL_DAC_VOL].name = front_volume;
+       spec->wm8776.ctl[WM8776_CTL_DAC_SW].name = front_switch;
+       spec->wm8776.ctl[WM8776_CTL_DAC_ZC_SW].name = front_zc;
+       spec->wm8776.ctl[WM8776_CTL_AUX_SW].name = NULL;
+       spec->wm8776.ctl[WM8776_CTL_DAC_IZD_SW].name = front_izd;
+       spec->wm8776.ctl[WM8776_CTL_PHASE_SW].name = front_phase;
+       spec->wm8776.ctl[WM8776_CTL_DEEMPH_SW].name = front_deemph;
+       spec->wm8776.ctl[WM8776_CTL_INPUT1_SW].name = ain1_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT2_SW].name = ain2_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT3_SW].name = ain3_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT4_SW].name = ain4_switch;
+       spec->wm8776.ctl[WM8776_CTL_INPUT5_SW].name = ain5_switch;
+       snd_wm8776_build_controls(&spec->wm8776);
+       spec->wm8766.ctl[WM8766_CTL_CH1_VOL].name = rear_volume;
+       spec->wm8766.ctl[WM8766_CTL_CH2_VOL].name = clfe_volume;
+       spec->wm8766.ctl[WM8766_CTL_CH3_VOL].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_CH1_SW].name = rear_switch;
+       spec->wm8766.ctl[WM8766_CTL_CH2_SW].name = clfe_switch;
+       spec->wm8766.ctl[WM8766_CTL_CH3_SW].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_PHASE1_SW].name = rear_phase;
+       spec->wm8766.ctl[WM8766_CTL_PHASE2_SW].name = clfe_phase;
+       spec->wm8766.ctl[WM8766_CTL_PHASE3_SW].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_DEEMPH1_SW].name = rear_deemph;
+       spec->wm8766.ctl[WM8766_CTL_DEEMPH2_SW].name = clfe_deemph;
+       spec->wm8766.ctl[WM8766_CTL_DEEMPH3_SW].name = NULL;
+       spec->wm8766.ctl[WM8766_CTL_IZD_SW].name = rear_clfe_izd;
+       spec->wm8766.ctl[WM8766_CTL_ZC_SW].name = rear_clfe_zc;
+       snd_wm8766_build_controls(&spec->wm8766);
+
+       memset(&cont, 0, sizeof(cont));
+       cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       for (i = 0; i < ARRAY_SIZE(psc724_cont); i++) {
+               cont.private_value = i;
+               cont.name = psc724_cont[i].name;
+               cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+               cont.info = snd_ctl_boolean_mono_info;
+               cont.get = psc724_ctl_get;
+               cont.put = psc724_ctl_put;
+               ctl = snd_ctl_new1(&cont, ice);
+               if (!ctl)
+                       return -ENOMEM;
+               err = snd_ctl_add(ice->card, ctl);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+static void psc724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+       struct psc724_spec *spec = ice->spec;
+       /* restore codec volume settings after rate change (PMCLK stop) */
+       snd_wm8776_volume_restore(&spec->wm8776);
+       snd_wm8766_volume_restore(&spec->wm8766);
+}
+
+/* power management */
+
+#ifdef CONFIG_PM_SLEEP
+static int psc724_resume(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       snd_wm8776_resume(&spec->wm8776);
+       snd_wm8766_resume(&spec->wm8766);
+
+       return 0;
+}
+#endif
+
+/* init */
+
+static int psc724_init(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       ice->spec = spec;
+       spec->ice = ice;
+
+       ice->num_total_dacs = 6;
+       ice->num_total_adcs = 2;
+       spec->wm8776.ops.write = psc724_wm8776_write;
+       spec->wm8776.card = ice->card;
+       snd_wm8776_init(&spec->wm8776);
+       spec->wm8766.ops.write = psc724_wm8766_write;
+       spec->wm8766.card = ice->card;
+#ifdef CONFIG_PM_SLEEP
+       ice->pm_resume = psc724_resume;
+       ice->pm_suspend_enabled = 1;
+#endif
+       snd_wm8766_init(&spec->wm8766);
+       snd_wm8766_set_if(&spec->wm8766,
+                       WM8766_IF_FMT_I2S | WM8766_IF_IWL_24BIT);
+       ice->gpio.set_pro_rate = psc724_set_pro_rate;
+       INIT_DELAYED_WORK(&spec->hp_work, psc724_update_hp_jack_state);
+       psc724_set_jack_detection(ice, true);
+       return 0;
+}
+
+static void psc724_exit(struct snd_ice1712 *ice)
+{
+       struct psc724_spec *spec = ice->spec;
+
+       cancel_delayed_work_sync(&spec->hp_work);
+}
+
+/* PSC724 has buggy EEPROM (no 96&192kHz, all FFh GPIOs), so override it here */
+static unsigned char psc724_eeprom[] = {
+       [ICE_EEP2_SYSCONF]      = 0x42, /* 49.152MHz, 1 ADC, 3 DACs */
+       [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
+       [ICE_EEP2_I2S]          = 0xf0, /* I2S volume, 96kHz, 24bit */
+       [ICE_EEP2_SPDIF]        = 0xc1, /* spdif out-en, out-int, no input */
+       /* GPIO outputs */
+       [ICE_EEP2_GPIO_DIR2]    = 0x5f, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */
+       /* GPIO write enable */
+       [ICE_EEP2_GPIO_MASK]    = 0xff, /* read-only */
+       [ICE_EEP2_GPIO_MASK1]   = 0xff, /* read-only */
+       [ICE_EEP2_GPIO_MASK2]   = 0xa0, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */
+       /* GPIO initial state */
+       [ICE_EEP2_GPIO_STATE2]  = 0x20, /* unmuted, all WM8766 pins low */
+};
+
+struct snd_ice1712_card_info snd_vt1724_psc724_cards[] = {
+       {
+               .subvendor = VT1724_SUBDEVICE_PSC724,
+               .name = "Philips PSC724 Ultimate Edge",
+               .model = "psc724",
+               .chip_init = psc724_init,
+               .chip_exit = psc724_exit,
+               .build_controls = psc724_add_controls,
+               .eeprom_size = sizeof(psc724_eeprom),
+               .eeprom_data = psc724_eeprom,
+       },
+       {} /*terminator*/
+};
diff --git a/sound/pci/ice1712/psc724.h b/sound/pci/ice1712/psc724.h
new file mode 100644 (file)
index 0000000..858e5fd
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __SOUND_PSC724_H
+#define __SOUND_PSC724_H
+
+/* ID */
+#define PSC724_DEVICE_DESC     \
+               "{Philips,PSC724 Ultimate Edge},"
+
+#define VT1724_SUBDEVICE_PSC724                0xab170619
+
+/* entry struct */
+extern struct snd_ice1712_card_info snd_vt1724_psc724_cards[];
+
+#endif /* __SOUND_PSC724_H */
index 1948632787e6be6e97e4cac092695b89d55bfa32..975e0357bd5a047bdf54faa4970e76a42694bd89 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -47,7 +46,7 @@ struct qtet_kcontrol_private {
        unsigned int bit;
        void (*set_register)(struct snd_ice1712 *ice, unsigned int val);
        unsigned int (*get_register)(struct snd_ice1712 *ice);
-       unsigned char *texts[2];
+       unsigned char * const texts[2];
 };
 
 enum {
@@ -63,7 +62,7 @@ enum {
        OUT34_MON12,
 };
 
-static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
+static const char * const ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS",
        "Word Clock 256xFS"};
 
 /* chip address on I2C bus */
@@ -387,7 +386,7 @@ static const struct snd_akm4xxx_adc_channel qtet_adc[] = {
        AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2),
 };
 
-static struct snd_akm4xxx akm_qtet_dac __devinitdata = {
+static struct snd_akm4xxx akm_qtet_dac = {
        .type = SND_AK4620,
        .num_dacs = 4,  /* DAC1 - Output 12
        */
@@ -551,7 +550,8 @@ static int qtet_mute_put(struct snd_kcontrol *kcontrol,
 static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_info *uinfo)
 {
-       static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"};
+       static const char * const texts[3] =
+               {"Line In 1/2", "Mic", "Mic + Low-cut"};
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
        uinfo->value.enumerated.items = ARRAY_SIZE(texts);
@@ -758,7 +758,7 @@ static int qtet_sw_put(struct snd_kcontrol *kcontrol,
        .put = qtet_sw_put,\
        .private_value = xpriv }
 
-static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
+static struct snd_kcontrol_new qtet_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -795,17 +795,17 @@ static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
        QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12),
 };
 
-static char *slave_vols[] __devinitdata = {
+static char *slave_vols[] = {
        PCM_12_PLAYBACK_VOLUME,
        PCM_34_PLAYBACK_VOLUME,
        NULL
 };
 
-static __devinitdata
+static
 DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1);
 
-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
-               const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card,
+                                    const char *name)
 {
        struct snd_ctl_elem_id sid;
        memset(&sid, 0, sizeof(sid));
@@ -815,8 +815,8 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
        return snd_ctl_find_id(card, &sid);
 }
 
-static void __devinit add_slaves(struct snd_card *card,
-               struct snd_kcontrol *master, char **list)
+static void add_slaves(struct snd_card *card,
+                      struct snd_kcontrol *master, char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -825,7 +825,7 @@ static void __devinit add_slaves(struct snd_card *card,
        }
 }
 
-static int __devinit qtet_add_controls(struct snd_ice1712 *ice)
+static int qtet_add_controls(struct snd_ice1712 *ice)
 {
        struct qtet_spec *spec = ice->spec;
        int err, i;
@@ -1007,7 +1007,7 @@ static void qtet_spdif_in_open(struct snd_ice1712 *ice,
 /*
  * initialize the chip
  */
-static int __devinit qtet_init(struct snd_ice1712 *ice)
+static int qtet_init(struct snd_ice1712 *ice)
 {
        static const unsigned char ak4113_init_vals[] = {
                /* AK4113_REG_PWRDN */  AK4113_RST | AK4113_PWN |
@@ -1095,7 +1095,7 @@ static int __devinit qtet_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static unsigned char qtet_eeprom[] __devinitdata = {
+static unsigned char qtet_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x28,  /* clock 256(24MHz), mpu401, 1xADC,
                                           1xDACs, SPDIF in */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -1116,7 +1116,7 @@ static unsigned char qtet_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_qtet_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_QTET,
                .name = "Infrasonic Quartet",
index b508bb360b97d1499eea3902cade76ff83f4b3f1..7641080a9b5d33bc853821a135eeca9bd62ab84d 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -235,7 +234,7 @@ static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
        },
 };
 
-static struct snd_akm4xxx akm_revo_front __devinitdata = {
+static struct snd_akm4xxx akm_revo_front = {
        .type = SND_AK4381,
        .num_dacs = 2,
        .ops = {
@@ -244,7 +243,7 @@ static struct snd_akm4xxx akm_revo_front __devinitdata = {
        .dac_info = revo71_front,
 };
 
-static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo_front_priv = {
        .caddr = 1,
        .cif = 0,
        .data_mask = VT1724_REVO_CDOUT,
@@ -256,7 +255,7 @@ static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_revo_surround __devinitdata = {
+static struct snd_akm4xxx akm_revo_surround = {
        .type = SND_AK4355,
        .idx_offset = 1,
        .num_dacs = 6,
@@ -266,7 +265,7 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = {
        .dac_info = revo71_surround,
 };
 
-static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo_surround_priv = {
        .caddr = 3,
        .cif = 0,
        .data_mask = VT1724_REVO_CDOUT,
@@ -278,7 +277,7 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_revo51 __devinitdata = {
+static struct snd_akm4xxx akm_revo51 = {
        .type = SND_AK4358,
        .num_dacs = 8,
        .ops = {
@@ -287,7 +286,7 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = {
        .dac_info = revo51_dac,
 };
 
-static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo51_priv = {
        .caddr = 2,
        .cif = 0,
        .data_mask = VT1724_REVO_CDOUT,
@@ -299,13 +298,13 @@ static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
        .mask_flags = 0,
 };
 
-static struct snd_akm4xxx akm_revo51_adc __devinitdata = {
+static struct snd_akm4xxx akm_revo51_adc = {
        .type = SND_AK5365,
        .num_adcs = 2,
        .adc_info = revo51_adc,
 };
 
-static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo51_adc_priv = {
        .caddr = 2,
        .cif = 0,
        .data_mask = VT1724_REVO_CDOUT,
@@ -346,7 +345,7 @@ static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
        AK_DAC("PCM Playback Volume", 2)
 };
 
-static struct snd_akm4xxx akm_ap192 __devinitdata = {
+static struct snd_akm4xxx akm_ap192 = {
        .type = SND_AK4358,
        .num_dacs = 2,
        .ops = {
@@ -355,7 +354,7 @@ static struct snd_akm4xxx akm_ap192 __devinitdata = {
        .dac_info = ap192_dac,
 };
 
-static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ap192_priv = {
        .caddr = 2,
        .cif = 0,
        .data_mask = VT1724_REVO_CDOUT,
@@ -468,7 +467,7 @@ static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
        return data;
 }
 
-static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
+static int ap192_ak4114_init(struct snd_ice1712 *ice)
 {
        static const unsigned char ak4114_init_vals[] = {
                AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
@@ -496,7 +495,7 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
        return 0; /* error ignored; it's no fatal error */
 }
 
-static int __devinit revo_init(struct snd_ice1712 *ice)
+static int revo_init(struct snd_ice1712 *ice)
 {
        struct snd_akm4xxx *ak;
        int err;
@@ -574,7 +573,7 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
 }
 
 
-static int __devinit revo_add_controls(struct snd_ice1712 *ice)
+static int revo_add_controls(struct snd_ice1712 *ice)
 {
        struct revo51_spec *spec;
        int err;
@@ -607,7 +606,7 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
 }
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_revo_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_REVOLUTION71,
                .name = "M Audio Revolution-7.1",
index 69673b95869da9bfd855aa4aa05acdf24f4c6835..ffd894bb4507b2ea919b18f980c09007f6a8f8bf 100644 (file)
@@ -22,7 +22,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -114,7 +113,7 @@ struct se_spec {
 /*  WM8740 interface                                                        */
 /****************************************************************************/
 
-static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
+static void se200pci_WM8740_init(struct snd_ice1712 *ice)
 {
        /* nothing to do */
 }
@@ -196,7 +195,7 @@ static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
        }
 }
 
-static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
+static void se200pci_WM8766_init(struct snd_ice1712 *ice)
 {
        se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
        udelay(10);
@@ -253,7 +252,7 @@ static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
        se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
 }
 
-static const char *se200pci_sel[] = {
+static const char * const se200pci_sel[] = {
        "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
 };
 
@@ -278,7 +277,7 @@ static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
                se200pci_WM8776_write(ice, 0x16, 0x001);
 }
 
-static const char *se200pci_agc[] = {
+static const char * const se200pci_agc[] = {
        "Off", "LimiterMode", "ALCMode", NULL
 };
 
@@ -300,10 +299,10 @@ static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
        }
 }
 
-static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice)
+static void se200pci_WM8776_init(struct snd_ice1712 *ice)
 {
        int i;
-       static unsigned short __devinitdata default_values[] = {
+       static unsigned short default_values[] = {
                0x100, 0x100, 0x100,
                0x100, 0x100, 0x100,
                0x000, 0x090, 0x000, 0x000,
@@ -352,7 +351,7 @@ static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
 }
 
 struct se200pci_control {
-       char *name;
+       const char *name;
        enum {
                WM8766,
                WM8776in,
@@ -363,7 +362,7 @@ struct se200pci_control {
        } target;
        enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
        int ch;
-       const char **member;
+       const char * const *member;
        const char *comment;
 };
 
@@ -421,7 +420,7 @@ static const struct se200pci_control se200pci_cont[] = {
 
 static int se200pci_get_enum_count(int n)
 {
-       const char **member;
+       const char * const *member;
        int c;
 
        member = se200pci_cont[n].member;
@@ -600,7 +599,7 @@ static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
 static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
 static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
 
-static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
+static int se200pci_add_controls(struct snd_ice1712 *ice)
 {
        int i;
        struct snd_kcontrol_new cont;
@@ -678,7 +677,7 @@ static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
 /*  probe/initialize/setup                                                  */
 /****************************************************************************/
 
-static int __devinit se_init(struct snd_ice1712 *ice)
+static int se_init(struct snd_ice1712 *ice)
 {
        struct se_spec *spec;
 
@@ -706,7 +705,7 @@ static int __devinit se_init(struct snd_ice1712 *ice)
        return -ENOENT;
 }
 
-static int __devinit se_add_controls(struct snd_ice1712 *ice)
+static int se_add_controls(struct snd_ice1712 *ice)
 {
        int err;
 
@@ -723,7 +722,7 @@ static int __devinit se_add_controls(struct snd_ice1712 *ice)
 /*  entry point                                                             */
 /****************************************************************************/
 
-static unsigned char se200pci_eeprom[] __devinitdata = {
+static unsigned char se200pci_eeprom[] = {
        [ICE_EEP2_SYSCONF]      = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
        [ICE_EEP2_I2S]          = 0x78, /* 96k-ok, 24bit, 192k-ok */
@@ -742,7 +741,7 @@ static unsigned char se200pci_eeprom[] __devinitdata = {
        [ICE_EEP2_GPIO_STATE2]  = 0x07, /* WM8766 ML/MC/MD */
 };
 
-static unsigned char se90pci_eeprom[] __devinitdata = {
+static unsigned char se90pci_eeprom[] = {
        [ICE_EEP2_SYSCONF]      = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
        [ICE_EEP2_I2S]          = 0x78, /* 96k-ok, 24bit, 192k-ok */
@@ -751,7 +750,7 @@ static unsigned char se90pci_eeprom[] __devinitdata = {
        /* ALL GPIO bits are in input mode */
 };
 
-struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_SE200PCI,
                .name = "ONKYO SE200PCI",
index 4c551e147c089d8186db424d6bc630ddeead58b1..5dbb867e642cbfb955a89f4a7ea8cb3f8fefe48c 100644 (file)
@@ -21,7 +21,6 @@
  *
  */      
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -32,7 +31,7 @@
 #include "vt1720_mobo.h"
 
 
-static int __devinit k8x800_init(struct snd_ice1712 *ice)
+static int k8x800_init(struct snd_ice1712 *ice)
 {
        ice->vt1720 = 1;
 
@@ -46,7 +45,7 @@ static int __devinit k8x800_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
+static int k8x800_add_controls(struct snd_ice1712 *ice)
 {
        /* FIXME: needs some quirks for VT1616? */
        return 0;
@@ -54,7 +53,7 @@ static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
 
 /* EEPROM image */
 
-static unsigned char k8x800_eeprom[] __devinitdata = {
+static unsigned char k8x800_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x01,  /* clock 256, 1ADC, 2DACs */
        [ICE_EEP2_ACLINK]      = 0x02,  /* ACLINK, packed */
        [ICE_EEP2_I2S]         = 0x00,  /* - */
@@ -70,7 +69,7 @@ static unsigned char k8x800_eeprom[] __devinitdata = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,  /* - */
 };
 
-static unsigned char sn25p_eeprom[] __devinitdata = {
+static unsigned char sn25p_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x01,  /* clock 256, 1ADC, 2DACs */
        [ICE_EEP2_ACLINK]      = 0x02,  /* ACLINK, packed */
        [ICE_EEP2_I2S]         = 0x00,  /* - */
@@ -88,7 +87,7 @@ static unsigned char sn25p_eeprom[] __devinitdata = {
 
 
 /* entry point */
-struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1720_mobo_cards[] = {
        {
                .subvendor = VT1720_SUBDEVICE_K8X800,
                .name = "Albatron K8X800 Pro II",
diff --git a/sound/pci/ice1712/wm8766.c b/sound/pci/ice1712/wm8766.c
new file mode 100644 (file)
index 0000000..8072ade
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8766 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include "wm8766.h"
+
+/* low-level access */
+
+static void snd_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
+{
+       if (addr < WM8766_REG_RESET)
+               wm->regs[addr] = data;
+       wm->ops.write(wm, addr, data);
+}
+
+/* mixer controls */
+
+static const DECLARE_TLV_DB_SCALE(wm8766_tlv, -12750, 50, 1);
+
+static struct snd_wm8766_ctl snd_wm8766_default_ctl[WM8766_CTL_COUNT] = {
+       [WM8766_CTL_CH1_VOL] = {
+               .name = "Channel 1 Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8766_tlv,
+               .reg1 = WM8766_REG_DACL1,
+               .reg2 = WM8766_REG_DACR1,
+               .mask1 = WM8766_VOL_MASK,
+               .mask2 = WM8766_VOL_MASK,
+               .max = 0xff,
+               .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+       },
+       [WM8766_CTL_CH2_VOL] = {
+               .name = "Channel 2 Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8766_tlv,
+               .reg1 = WM8766_REG_DACL2,
+               .reg2 = WM8766_REG_DACR2,
+               .mask1 = WM8766_VOL_MASK,
+               .mask2 = WM8766_VOL_MASK,
+               .max = 0xff,
+               .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+       },
+       [WM8766_CTL_CH3_VOL] = {
+               .name = "Channel 3 Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8766_tlv,
+               .reg1 = WM8766_REG_DACL3,
+               .reg2 = WM8766_REG_DACR3,
+               .mask1 = WM8766_VOL_MASK,
+               .mask2 = WM8766_VOL_MASK,
+               .max = 0xff,
+               .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE,
+       },
+       [WM8766_CTL_CH1_SW] = {
+               .name = "Channel 1 Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_MUTE1,
+               .flags = WM8766_FLAG_INVERT,
+       },
+       [WM8766_CTL_CH2_SW] = {
+               .name = "Channel 2 Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_MUTE2,
+               .flags = WM8766_FLAG_INVERT,
+       },
+       [WM8766_CTL_CH3_SW] = {
+               .name = "Channel 3 Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_MUTE3,
+               .flags = WM8766_FLAG_INVERT,
+       },
+       [WM8766_CTL_PHASE1_SW] = {
+               .name = "Channel 1 Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_IFCTRL,
+               .mask1 = WM8766_PHASE_INVERT1,
+       },
+       [WM8766_CTL_PHASE2_SW] = {
+               .name = "Channel 2 Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_IFCTRL,
+               .mask1 = WM8766_PHASE_INVERT2,
+       },
+       [WM8766_CTL_PHASE3_SW] = {
+               .name = "Channel 3 Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_IFCTRL,
+               .mask1 = WM8766_PHASE_INVERT3,
+       },
+       [WM8766_CTL_DEEMPH1_SW] = {
+               .name = "Channel 1 Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_DEEMP1,
+       },
+       [WM8766_CTL_DEEMPH2_SW] = {
+               .name = "Channel 2 Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_DEEMP2,
+       },
+       [WM8766_CTL_DEEMPH3_SW] = {
+               .name = "Channel 3 Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_DEEMP3,
+       },
+       [WM8766_CTL_IZD_SW] = {
+               .name = "Infinite Zero Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL1,
+               .mask1 = WM8766_DAC_IZD,
+       },
+       [WM8766_CTL_ZC_SW] = {
+               .name = "Zero Cross Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8766_REG_DACCTRL2,
+               .mask1 = WM8766_DAC2_ZCD,
+               .flags = WM8766_FLAG_INVERT,
+       },
+};
+
+/* exported functions */
+
+void snd_wm8766_init(struct snd_wm8766 *wm)
+{
+       int i;
+       static const u16 default_values[] = {
+               0x000, 0x100,
+               0x120, 0x000,
+               0x000, 0x100, 0x000, 0x100, 0x000,
+               0x000, 0x080,
+       };
+
+       memcpy(wm->ctl, snd_wm8766_default_ctl, sizeof(wm->ctl));
+
+       snd_wm8766_write(wm, WM8766_REG_RESET, 0x00); /* reset */
+       udelay(10);
+       /* load defaults */
+       for (i = 0; i < ARRAY_SIZE(default_values); i++)
+               snd_wm8766_write(wm, i, default_values[i]);
+}
+
+void snd_wm8766_resume(struct snd_wm8766 *wm)
+{
+       int i;
+
+       for (i = 0; i < WM8766_REG_COUNT; i++)
+               snd_wm8766_write(wm, i, wm->regs[i]);
+}
+
+void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac)
+{
+       u16 val = wm->regs[WM8766_REG_IFCTRL] & ~WM8766_IF_MASK;
+
+       dac &= WM8766_IF_MASK;
+       snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac);
+}
+
+void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode)
+{
+       u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_MSTR_MASK;
+
+       mode &= WM8766_DAC3_MSTR_MASK;
+       snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | mode);
+}
+
+void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power)
+{
+       u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_POWER_MASK;
+
+       power &= WM8766_DAC3_POWER_MASK;
+       snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | power);
+}
+
+void snd_wm8766_volume_restore(struct snd_wm8766 *wm)
+{
+       u16 val = wm->regs[WM8766_REG_DACR1];
+       /* restore volume after MCLK stopped */
+       snd_wm8766_write(wm, WM8766_REG_DACR1, val | WM8766_VOL_UPDATE);
+}
+
+/* mixer callbacks */
+
+static int snd_wm8766_volume_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = (wm->ctl[n].flags & WM8766_FLAG_STEREO) ? 2 : 1;
+       uinfo->value.integer.min = wm->ctl[n].min;
+       uinfo->value.integer.max = wm->ctl[n].max;
+
+       return 0;
+}
+
+static int snd_wm8766_enum_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max,
+                                               wm->ctl[n].enum_names);
+}
+
+static int snd_wm8766_ctl_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val1, val2;
+
+       if (wm->ctl[n].get)
+               wm->ctl[n].get(wm, &val1, &val2);
+       else {
+               val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1;
+               val1 >>= __ffs(wm->ctl[n].mask1);
+               if (wm->ctl[n].flags & WM8766_FLAG_STEREO) {
+                       val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
+                       val2 >>= __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
+                               val2 &= ~WM8766_VOL_UPDATE;
+               }
+       }
+       if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
+               val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
+               val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+       }
+       ucontrol->value.integer.value[0] = val1;
+       if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
+               ucontrol->value.integer.value[1] = val2;
+
+       return 0;
+}
+
+static int snd_wm8766_ctl_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val, regval1, regval2;
+
+       /* this also works for enum because value is an union */
+       regval1 = ucontrol->value.integer.value[0];
+       regval2 = ucontrol->value.integer.value[1];
+       if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
+               regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
+               regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
+       }
+       if (wm->ctl[n].set)
+               wm->ctl[n].set(wm, regval1, regval2);
+       else {
+               val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
+               val |= regval1 << __ffs(wm->ctl[n].mask1);
+               /* both stereo controls in one register */
+               if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
+                               wm->ctl[n].reg1 == wm->ctl[n].reg2) {
+                       val &= ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+               }
+               snd_wm8766_write(wm, wm->ctl[n].reg1, val);
+               /* stereo controls in different registers */
+               if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
+                               wm->ctl[n].reg1 != wm->ctl[n].reg2) {
+                       val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
+                               val |= WM8766_VOL_UPDATE;
+                       snd_wm8766_write(wm, wm->ctl[n].reg2, val);
+               }
+       }
+
+       return 0;
+}
+
+static int snd_wm8766_add_control(struct snd_wm8766 *wm, int num)
+{
+       struct snd_kcontrol_new cont;
+       struct snd_kcontrol *ctl;
+
+       memset(&cont, 0, sizeof(cont));
+       cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       cont.private_value = num;
+       cont.name = wm->ctl[num].name;
+       cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+       if (wm->ctl[num].flags & WM8766_FLAG_LIM ||
+           wm->ctl[num].flags & WM8766_FLAG_ALC)
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       cont.tlv.p = NULL;
+       cont.get = snd_wm8766_ctl_get;
+       cont.put = snd_wm8766_ctl_put;
+
+       switch (wm->ctl[num].type) {
+       case SNDRV_CTL_ELEM_TYPE_INTEGER:
+               cont.info = snd_wm8766_volume_info;
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               cont.tlv.p = wm->ctl[num].tlv;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+               wm->ctl[num].max = 1;
+               if (wm->ctl[num].flags & WM8766_FLAG_STEREO)
+                       cont.info = snd_ctl_boolean_stereo_info;
+               else
+                       cont.info = snd_ctl_boolean_mono_info;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+               cont.info = snd_wm8766_enum_info;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ctl = snd_ctl_new1(&cont, wm);
+       if (!ctl)
+               return -ENOMEM;
+       wm->ctl[num].kctl = ctl;
+
+       return snd_ctl_add(wm->card, ctl);
+}
+
+int snd_wm8766_build_controls(struct snd_wm8766 *wm)
+{
+       int err, i;
+
+       for (i = 0; i < WM8766_CTL_COUNT; i++)
+               if (wm->ctl[i].name) {
+                       err = snd_wm8766_add_control(wm, i);
+                       if (err < 0)
+                               return err;
+               }
+
+       return 0;
+}
diff --git a/sound/pci/ice1712/wm8766.h b/sound/pci/ice1712/wm8766.h
new file mode 100644 (file)
index 0000000..c119f84
--- /dev/null
@@ -0,0 +1,163 @@
+#ifndef __SOUND_WM8766_H
+#define __SOUND_WM8766_H
+
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8766 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define WM8766_REG_DACL1       0x00
+#define WM8766_REG_DACR1       0x01
+#define WM8766_VOL_MASK                        0x1ff           /* incl. update bit */
+#define WM8766_VOL_UPDATE              (1 << 8)        /* update volume */
+#define WM8766_REG_DACCTRL1    0x02
+#define WM8766_DAC_MUTEALL             (1 << 0)
+#define WM8766_DAC_DEEMPALL            (1 << 1)
+#define WM8766_DAC_PDWN                        (1 << 2)
+#define WM8766_DAC_ATC                 (1 << 3)
+#define WM8766_DAC_IZD                 (1 << 4)
+#define WM8766_DAC_PL_MASK             0x1e0
+#define WM8766_DAC_PL_LL               (1 << 5)        /* L chan: L signal */
+#define WM8766_DAC_PL_LR               (2 << 5)        /* L chan: R signal */
+#define WM8766_DAC_PL_LB               (3 << 5)        /* L chan: both */
+#define WM8766_DAC_PL_RL               (1 << 7)        /* R chan: L signal */
+#define WM8766_DAC_PL_RR               (2 << 7)        /* R chan: R signal */
+#define WM8766_DAC_PL_RB               (3 << 7)        /* R chan: both */
+#define WM8766_REG_IFCTRL      0x03
+#define WM8766_IF_FMT_RIGHTJ           (0 << 0)
+#define WM8766_IF_FMT_LEFTJ            (1 << 0)
+#define WM8766_IF_FMT_I2S              (2 << 0)
+#define WM8766_IF_FMT_DSP              (3 << 0)
+#define WM8766_IF_DSP_LATE             (1 << 2)        /* in DSP mode */
+#define WM8766_IF_LRC_INVERTED         (1 << 2)        /* in other modes */
+#define WM8766_IF_BCLK_INVERTED                (1 << 3)
+#define WM8766_IF_IWL_16BIT            (0 << 4)
+#define WM8766_IF_IWL_20BIT            (1 << 4)
+#define WM8766_IF_IWL_24BIT            (2 << 4)
+#define WM8766_IF_IWL_32BIT            (3 << 4)
+#define WM8766_IF_MASK                 0x3f
+#define WM8766_PHASE_INVERT1           (1 << 6)
+#define WM8766_PHASE_INVERT2           (1 << 7)
+#define WM8766_PHASE_INVERT3           (1 << 8)
+#define WM8766_REG_DACL2       0x04
+#define WM8766_REG_DACR2       0x05
+#define WM8766_REG_DACL3       0x06
+#define WM8766_REG_DACR3       0x07
+#define WM8766_REG_MASTDA      0x08
+#define WM8766_REG_DACCTRL2    0x09
+#define WM8766_DAC2_ZCD                        (1 << 0)
+#define WM8766_DAC2_ZFLAG_ALL          (0 << 1)
+#define WM8766_DAC2_ZFLAG_1            (1 << 1)
+#define WM8766_DAC2_ZFLAG_2            (2 << 1)
+#define WM8766_DAC2_ZFLAG_3            (3 << 1)
+#define WM8766_DAC2_MUTE1              (1 << 3)
+#define WM8766_DAC2_MUTE2              (1 << 4)
+#define WM8766_DAC2_MUTE3              (1 << 5)
+#define WM8766_DAC2_DEEMP1             (1 << 6)
+#define WM8766_DAC2_DEEMP2             (1 << 7)
+#define WM8766_DAC2_DEEMP3             (1 << 8)
+#define WM8766_REG_DACCTRL3    0x0a
+#define WM8766_DAC3_DACPD1             (1 << 1)
+#define WM8766_DAC3_DACPD2             (1 << 2)
+#define WM8766_DAC3_DACPD3             (1 << 3)
+#define WM8766_DAC3_PWRDNALL           (1 << 4)
+#define WM8766_DAC3_POWER_MASK         0x1e
+#define WM8766_DAC3_MASTER             (1 << 5)
+#define WM8766_DAC3_DAC128FS           (0 << 6)
+#define WM8766_DAC3_DAC192FS           (1 << 6)
+#define WM8766_DAC3_DAC256FS           (2 << 6)
+#define WM8766_DAC3_DAC384FS           (3 << 6)
+#define WM8766_DAC3_DAC512FS           (4 << 6)
+#define WM8766_DAC3_DAC768FS           (5 << 6)
+#define WM8766_DAC3_MSTR_MASK          0x1e0
+#define WM8766_REG_MUTE1       0x0c
+#define WM8766_MUTE1_MPD               (1 << 6)
+#define WM8766_REG_MUTE2       0x0f
+#define WM8766_MUTE2_MPD               (1 << 5)
+#define WM8766_REG_RESET       0x1f
+
+#define WM8766_REG_COUNT       0x10    /* don't cache the RESET register */
+
+struct snd_wm8766;
+
+struct snd_wm8766_ops {
+       void (*write)(struct snd_wm8766 *wm, u16 addr, u16 data);
+};
+
+enum snd_wm8766_ctl_id {
+       WM8766_CTL_CH1_VOL,
+       WM8766_CTL_CH2_VOL,
+       WM8766_CTL_CH3_VOL,
+       WM8766_CTL_CH1_SW,
+       WM8766_CTL_CH2_SW,
+       WM8766_CTL_CH3_SW,
+       WM8766_CTL_PHASE1_SW,
+       WM8766_CTL_PHASE2_SW,
+       WM8766_CTL_PHASE3_SW,
+       WM8766_CTL_DEEMPH1_SW,
+       WM8766_CTL_DEEMPH2_SW,
+       WM8766_CTL_DEEMPH3_SW,
+       WM8766_CTL_IZD_SW,
+       WM8766_CTL_ZC_SW,
+
+       WM8766_CTL_COUNT,
+};
+
+#define WM8766_ENUM_MAX                16
+
+#define WM8766_FLAG_STEREO     (1 << 0)
+#define WM8766_FLAG_VOL_UPDATE (1 << 1)
+#define WM8766_FLAG_INVERT     (1 << 2)
+#define WM8766_FLAG_LIM                (1 << 3)
+#define WM8766_FLAG_ALC                (1 << 4)
+
+struct snd_wm8766_ctl {
+       struct snd_kcontrol *kctl;
+       const char *name;
+       snd_ctl_elem_type_t type;
+       const char *const enum_names[WM8766_ENUM_MAX];
+       const unsigned int *tlv;
+       u16 reg1, reg2, mask1, mask2, min, max, flags;
+       void (*set)(struct snd_wm8766 *wm, u16 ch1, u16 ch2);
+       void (*get)(struct snd_wm8766 *wm, u16 *ch1, u16 *ch2);
+};
+
+enum snd_wm8766_agc_mode { WM8766_AGC_OFF, WM8766_AGC_LIM, WM8766_AGC_ALC };
+
+struct snd_wm8766 {
+       struct snd_card *card;
+       struct snd_wm8766_ctl ctl[WM8766_CTL_COUNT];
+       enum snd_wm8766_agc_mode agc_mode;
+       struct snd_wm8766_ops ops;
+       u16 regs[WM8766_REG_COUNT];     /* 9-bit registers */
+};
+
+
+
+void snd_wm8766_init(struct snd_wm8766 *wm);
+void snd_wm8766_resume(struct snd_wm8766 *wm);
+void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac);
+void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode);
+void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power);
+void snd_wm8766_volume_restore(struct snd_wm8766 *wm);
+int snd_wm8766_build_controls(struct snd_wm8766 *wm);
+
+#endif /* __SOUND_WM8766_H */
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c
new file mode 100644 (file)
index 0000000..a3c05fe
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8776 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include "wm8776.h"
+
+/* low-level access */
+
+static void snd_wm8776_write(struct snd_wm8776 *wm, u16 addr, u16 data)
+{
+       u8 bus_addr = addr << 1 | data >> 8;    /* addr + 9th data bit */
+       u8 bus_data = data & 0xff;              /* remaining 8 data bits */
+
+       if (addr < WM8776_REG_RESET)
+               wm->regs[addr] = data;
+       wm->ops.write(wm, bus_addr, bus_data);
+}
+
+/* register-level functions */
+
+static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm,
+                                   const char *ctl_name,
+                                   bool active)
+{
+       struct snd_card *card = wm->card;
+       struct snd_kcontrol *kctl;
+       struct snd_kcontrol_volatile *vd;
+       struct snd_ctl_elem_id elem_id;
+       unsigned int index_offset;
+
+       memset(&elem_id, 0, sizeof(elem_id));
+       strncpy(elem_id.name, ctl_name, sizeof(elem_id.name));
+       elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       kctl = snd_ctl_find_id(card, &elem_id);
+       if (!kctl)
+               return;
+       index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
+       vd = &kctl->vd[index_offset];
+       if (active)
+               vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       else
+               vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
+}
+
+static void snd_wm8776_update_agc_ctl(struct snd_wm8776 *wm)
+{
+       int i, flags_on = 0, flags_off = 0;
+
+       switch (wm->agc_mode) {
+       case WM8776_AGC_OFF:
+               flags_off = WM8776_FLAG_LIM | WM8776_FLAG_ALC;
+               break;
+       case WM8776_AGC_LIM:
+               flags_off = WM8776_FLAG_ALC;
+               flags_on = WM8776_FLAG_LIM;
+               break;
+       case WM8776_AGC_ALC_R:
+       case WM8776_AGC_ALC_L:
+       case WM8776_AGC_ALC_STEREO:
+               flags_off = WM8776_FLAG_LIM;
+               flags_on = WM8776_FLAG_ALC;
+               break;
+       }
+
+       for (i = 0; i < WM8776_CTL_COUNT; i++)
+               if (wm->ctl[i].flags & flags_off)
+                       snd_wm8776_activate_ctl(wm, wm->ctl[i].name, false);
+               else if (wm->ctl[i].flags & flags_on)
+                       snd_wm8776_activate_ctl(wm, wm->ctl[i].name, true);
+}
+
+static void snd_wm8776_set_agc(struct snd_wm8776 *wm, u16 agc, u16 nothing)
+{
+       u16 alc1 = wm->regs[WM8776_REG_ALCCTRL1] & ~WM8776_ALC1_LCT_MASK;
+       u16 alc2 = wm->regs[WM8776_REG_ALCCTRL2] & ~WM8776_ALC2_LCEN;
+
+       switch (agc) {
+       case 0: /* Off */
+               wm->agc_mode = WM8776_AGC_OFF;
+               break;
+       case 1: /* Limiter */
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_LIM;
+               break;
+       case 2: /* ALC Right */
+               alc1 |= WM8776_ALC1_LCSEL_ALCR;
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_ALC_R;
+               break;
+       case 3: /* ALC Left */
+               alc1 |= WM8776_ALC1_LCSEL_ALCL;
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_ALC_L;
+               break;
+       case 4: /* ALC Stereo */
+               alc1 |= WM8776_ALC1_LCSEL_ALCSTEREO;
+               alc2 |= WM8776_ALC2_LCEN;
+               wm->agc_mode = WM8776_AGC_ALC_STEREO;
+               break;
+       }
+       snd_wm8776_write(wm, WM8776_REG_ALCCTRL1, alc1);
+       snd_wm8776_write(wm, WM8776_REG_ALCCTRL2, alc2);
+       snd_wm8776_update_agc_ctl(wm);
+}
+
+static void snd_wm8776_get_agc(struct snd_wm8776 *wm, u16 *mode, u16 *nothing)
+{
+       *mode = wm->agc_mode;
+}
+
+/* mixer controls */
+
+static const DECLARE_TLV_DB_SCALE(wm8776_hp_tlv, -7400, 100, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_dac_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_adc_tlv, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(wm8776_lct_tlv, -1600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_tlv, 0, 400, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_ngth_tlv, -7800, 600, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_tlv, -2100, 400, 0);
+
+static struct snd_wm8776_ctl snd_wm8776_default_ctl[WM8776_CTL_COUNT] = {
+       [WM8776_CTL_DAC_VOL] = {
+               .name = "Master Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_dac_tlv,
+               .reg1 = WM8776_REG_DACLVOL,
+               .reg2 = WM8776_REG_DACRVOL,
+               .mask1 = WM8776_DACVOL_MASK,
+               .mask2 = WM8776_DACVOL_MASK,
+               .max = 0xff,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+       },
+       [WM8776_CTL_DAC_SW] = {
+               .name = "Master Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL1,
+               .reg2 = WM8776_REG_DACCTRL1,
+               .mask1 = WM8776_DAC_PL_LL,
+               .mask2 = WM8776_DAC_PL_RR,
+               .flags = WM8776_FLAG_STEREO,
+       },
+       [WM8776_CTL_DAC_ZC_SW] = {
+               .name = "Master Zero Cross Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL1,
+               .mask1 = WM8776_DAC_DZCEN,
+       },
+       [WM8776_CTL_HP_VOL] = {
+               .name = "Headphone Playback Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_hp_tlv,
+               .reg1 = WM8776_REG_HPLVOL,
+               .reg2 = WM8776_REG_HPRVOL,
+               .mask1 = WM8776_HPVOL_MASK,
+               .mask2 = WM8776_HPVOL_MASK,
+               .min = 0x2f,
+               .max = 0x7f,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+       },
+       [WM8776_CTL_HP_SW] = {
+               .name = "Headphone Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_PWRDOWN,
+               .mask1 = WM8776_PWR_HPPD,
+               .flags = WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_HP_ZC_SW] = {
+               .name = "Headphone Zero Cross Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_HPLVOL,
+               .reg2 = WM8776_REG_HPRVOL,
+               .mask1 = WM8776_VOL_HPZCEN,
+               .mask2 = WM8776_VOL_HPZCEN,
+               .flags = WM8776_FLAG_STEREO,
+       },
+       [WM8776_CTL_AUX_SW] = {
+               .name = "AUX Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_OUTMUX,
+               .mask1 = WM8776_OUTMUX_AUX,
+       },
+       [WM8776_CTL_BYPASS_SW] = {
+               .name = "Bypass Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_OUTMUX,
+               .mask1 = WM8776_OUTMUX_BYPASS,
+       },
+       [WM8776_CTL_DAC_IZD_SW] = {
+               .name = "Infinite Zero Detect Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL1,
+               .mask1 = WM8776_DAC_IZD,
+       },
+       [WM8776_CTL_PHASE_SW] = {
+               .name = "Phase Invert Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_PHASESWAP,
+               .reg2 = WM8776_REG_PHASESWAP,
+               .mask1 = WM8776_PHASE_INVERTL,
+               .mask2 = WM8776_PHASE_INVERTR,
+               .flags = WM8776_FLAG_STEREO,
+       },
+       [WM8776_CTL_DEEMPH_SW] = {
+               .name = "Deemphasis Playback Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_DACCTRL2,
+               .mask1 = WM8776_DAC2_DEEMPH,
+       },
+       [WM8776_CTL_ADC_VOL] = {
+               .name = "Input Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_adc_tlv,
+               .reg1 = WM8776_REG_ADCLVOL,
+               .reg2 = WM8776_REG_ADCRVOL,
+               .mask1 = WM8776_ADC_GAIN_MASK,
+               .mask2 = WM8776_ADC_GAIN_MASK,
+               .max = 0xff,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE,
+       },
+       [WM8776_CTL_ADC_SW] = {
+               .name = "Input Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .reg2 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUTEL,
+               .mask2 = WM8776_ADC_MUTER,
+               .flags = WM8776_FLAG_STEREO | WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_INPUT1_SW] = {
+               .name = "AIN1 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN1,
+       },
+       [WM8776_CTL_INPUT2_SW] = {
+               .name = "AIN2 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN2,
+       },
+       [WM8776_CTL_INPUT3_SW] = {
+               .name = "AIN3 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN3,
+       },
+       [WM8776_CTL_INPUT4_SW] = {
+               .name = "AIN4 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN4,
+       },
+       [WM8776_CTL_INPUT5_SW] = {
+               .name = "AIN5 Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_ADCMUX,
+               .mask1 = WM8776_ADC_MUX_AIN5,
+       },
+       [WM8776_CTL_AGC_SEL] = {
+               .name = "AGC Select Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "Off", "Limiter", "ALC Right", "ALC Left",
+                               "ALC Stereo" },
+               .max = 5,       /* .enum_names item count */
+               .set = snd_wm8776_set_agc,
+               .get = snd_wm8776_get_agc,
+       },
+       [WM8776_CTL_LIM_THR] = {
+               .name = "Limiter Threshold Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_lct_tlv,
+               .reg1 = WM8776_REG_ALCCTRL1,
+               .mask1 = WM8776_ALC1_LCT_MASK,
+               .max = 15,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_ATK] = {
+               .name = "Limiter Attack Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "0.25 ms", "0.5 ms", "1 ms", "2 ms", "4 ms",
+                       "8 ms", "16 ms", "32 ms", "64 ms", "128 ms", "256 ms" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_ATK_MASK,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_DCY] = {
+               .name = "Limiter Decay Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
+                       "19.2 ms", "38.4 ms", "76.8 ms", "154 ms", "307 ms",
+                       "614 ms", "1.23 s" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_DCY_MASK,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_TRANWIN] = {
+               .name = "Limiter Transient Window Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "0 us", "62.5 us", "125 us", "250 us", "500 us",
+                       "1 ms", "2 ms", "4 ms" },
+               .max = 8,       /* .enum_names item count */
+               .reg1 = WM8776_REG_LIMITER,
+               .mask1 = WM8776_LIM_TRANWIN_MASK,
+               .flags = WM8776_FLAG_LIM,
+       },
+       [WM8776_CTL_LIM_MAXATTN] = {
+               .name = "Limiter Maximum Attenuation Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_maxatten_lim_tlv,
+               .reg1 = WM8776_REG_LIMITER,
+               .mask1 = WM8776_LIM_MAXATTEN_MASK,
+               .min = 3,
+               .max = 12,
+               .flags = WM8776_FLAG_LIM | WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_ALC_TGT] = {
+               .name = "ALC Target Level Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_lct_tlv,
+               .reg1 = WM8776_REG_ALCCTRL1,
+               .mask1 = WM8776_ALC1_LCT_MASK,
+               .max = 15,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_ATK] = {
+               .name = "ALC Attack Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
+                       "134 ms", "269 ms", "538 ms", "1.08 s", "2.15 s",
+                       "4.3 s", "8.6 s" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_ATK_MASK,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_DCY] = {
+               .name = "ALC Decay Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "33.5 ms", "67.0 ms", "134 ms", "268 ms",
+                       "536 ms", "1.07 s", "2.14 s", "4.29 s", "8.58 s",
+                       "17.2 s", "34.3 s" },
+               .max = 11,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL3,
+               .mask1 = WM8776_ALC3_DCY_MASK,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_MAXGAIN] = {
+               .name = "ALC Maximum Gain Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_maxgain_tlv,
+               .reg1 = WM8776_REG_ALCCTRL1,
+               .mask1 = WM8776_ALC1_MAXGAIN_MASK,
+               .min = 1,
+               .max = 7,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_ALC_MAXATTN] = {
+               .name = "ALC Maximum Attenuation Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_maxatten_alc_tlv,
+               .reg1 = WM8776_REG_LIMITER,
+               .mask1 = WM8776_LIM_MAXATTEN_MASK,
+               .min = 10,
+               .max = 15,
+               .flags = WM8776_FLAG_ALC | WM8776_FLAG_INVERT,
+       },
+       [WM8776_CTL_ALC_HLD] = {
+               .name = "ALC Hold Time Capture Enum",
+               .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
+               .enum_names = { "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
+                       "21.3 ms", "42.7 ms", "85.3 ms", "171 ms", "341 ms",
+                       "683 ms", "1.37 s", "2.73 s", "5.46 s", "10.9 s",
+                       "21.8 s", "43.7 s" },
+               .max = 16,      /* .enum_names item count */
+               .reg1 = WM8776_REG_ALCCTRL2,
+               .mask1 = WM8776_ALC2_HOLD_MASK,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_NGT_SW] = {
+               .name = "Noise Gate Capture Switch",
+               .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
+               .reg1 = WM8776_REG_NOISEGATE,
+               .mask1 = WM8776_NGAT_ENABLE,
+               .flags = WM8776_FLAG_ALC,
+       },
+       [WM8776_CTL_NGT_THR] = {
+               .name = "Noise Gate Threshold Capture Volume",
+               .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
+               .tlv = wm8776_ngth_tlv,
+               .reg1 = WM8776_REG_NOISEGATE,
+               .mask1 = WM8776_NGAT_THR_MASK,
+               .max = 7,
+               .flags = WM8776_FLAG_ALC,
+       },
+};
+
+/* exported functions */
+
+void snd_wm8776_init(struct snd_wm8776 *wm)
+{
+       int i;
+       static const u16 default_values[] = {
+               0x000, 0x100, 0x000,
+               0x000, 0x100, 0x000,
+               0x000, 0x090, 0x000, 0x000,
+               0x022, 0x022, 0x022,
+               0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
+               0x032, 0x000, 0x0a6, 0x001, 0x001
+       };
+
+       memcpy(wm->ctl, snd_wm8776_default_ctl, sizeof(wm->ctl));
+
+       snd_wm8776_write(wm, WM8776_REG_RESET, 0x00); /* reset */
+       udelay(10);
+       /* load defaults */
+       for (i = 0; i < ARRAY_SIZE(default_values); i++)
+               snd_wm8776_write(wm, i, default_values[i]);
+}
+
+void snd_wm8776_resume(struct snd_wm8776 *wm)
+{
+       int i;
+
+       for (i = 0; i < WM8776_REG_COUNT; i++)
+               snd_wm8776_write(wm, i, wm->regs[i]);
+}
+
+void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac)
+{
+       snd_wm8776_write(wm, WM8776_REG_DACIFCTRL, dac);
+}
+
+void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc)
+{
+       snd_wm8776_write(wm, WM8776_REG_ADCIFCTRL, adc);
+}
+
+void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode)
+{
+       snd_wm8776_write(wm, WM8776_REG_MSTRCTRL, mode);
+}
+
+void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power)
+{
+       snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power);
+}
+
+void snd_wm8776_volume_restore(struct snd_wm8776 *wm)
+{
+       u16 val = wm->regs[WM8776_REG_DACRVOL];
+       /* restore volume after MCLK stopped */
+       snd_wm8776_write(wm, WM8776_REG_DACRVOL, val | WM8776_VOL_UPDATE);
+}
+
+/* mixer callbacks */
+
+static int snd_wm8776_volume_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = (wm->ctl[n].flags & WM8776_FLAG_STEREO) ? 2 : 1;
+       uinfo->value.integer.min = wm->ctl[n].min;
+       uinfo->value.integer.max = wm->ctl[n].max;
+
+       return 0;
+}
+
+static int snd_wm8776_enum_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+
+       return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max,
+                                               wm->ctl[n].enum_names);
+}
+
+static int snd_wm8776_ctl_get(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val1, val2;
+
+       if (wm->ctl[n].get)
+               wm->ctl[n].get(wm, &val1, &val2);
+       else {
+               val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1;
+               val1 >>= __ffs(wm->ctl[n].mask1);
+               if (wm->ctl[n].flags & WM8776_FLAG_STEREO) {
+                       val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
+                       val2 >>= __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE)
+                               val2 &= ~WM8776_VOL_UPDATE;
+               }
+       }
+       if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
+               val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
+               val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+       }
+       ucontrol->value.integer.value[0] = val1;
+       if (wm->ctl[n].flags & WM8776_FLAG_STEREO)
+               ucontrol->value.integer.value[1] = val2;
+
+       return 0;
+}
+
+static int snd_wm8776_ctl_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol);
+       int n = kcontrol->private_value;
+       u16 val, regval1, regval2;
+
+       /* this also works for enum because value is an union */
+       regval1 = ucontrol->value.integer.value[0];
+       regval2 = ucontrol->value.integer.value[1];
+       if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
+               regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
+               regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
+       }
+       if (wm->ctl[n].set)
+               wm->ctl[n].set(wm, regval1, regval2);
+       else {
+               val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
+               val |= regval1 << __ffs(wm->ctl[n].mask1);
+               /* both stereo controls in one register */
+               if (wm->ctl[n].flags & WM8776_FLAG_STEREO &&
+                               wm->ctl[n].reg1 == wm->ctl[n].reg2) {
+                       val &= ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+               }
+               snd_wm8776_write(wm, wm->ctl[n].reg1, val);
+               /* stereo controls in different registers */
+               if (wm->ctl[n].flags & WM8776_FLAG_STEREO &&
+                               wm->ctl[n].reg1 != wm->ctl[n].reg2) {
+                       val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
+                       val |= regval2 << __ffs(wm->ctl[n].mask2);
+                       if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE)
+                               val |= WM8776_VOL_UPDATE;
+                       snd_wm8776_write(wm, wm->ctl[n].reg2, val);
+               }
+       }
+
+       return 0;
+}
+
+static int snd_wm8776_add_control(struct snd_wm8776 *wm, int num)
+{
+       struct snd_kcontrol_new cont;
+       struct snd_kcontrol *ctl;
+
+       memset(&cont, 0, sizeof(cont));
+       cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       cont.private_value = num;
+       cont.name = wm->ctl[num].name;
+       cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+       if (wm->ctl[num].flags & WM8776_FLAG_LIM ||
+           wm->ctl[num].flags & WM8776_FLAG_ALC)
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       cont.tlv.p = NULL;
+       cont.get = snd_wm8776_ctl_get;
+       cont.put = snd_wm8776_ctl_put;
+
+       switch (wm->ctl[num].type) {
+       case SNDRV_CTL_ELEM_TYPE_INTEGER:
+               cont.info = snd_wm8776_volume_info;
+               cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               cont.tlv.p = wm->ctl[num].tlv;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+               wm->ctl[num].max = 1;
+               if (wm->ctl[num].flags & WM8776_FLAG_STEREO)
+                       cont.info = snd_ctl_boolean_stereo_info;
+               else
+                       cont.info = snd_ctl_boolean_mono_info;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+               cont.info = snd_wm8776_enum_info;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ctl = snd_ctl_new1(&cont, wm);
+       if (!ctl)
+               return -ENOMEM;
+
+       return snd_ctl_add(wm->card, ctl);
+}
+
+int snd_wm8776_build_controls(struct snd_wm8776 *wm)
+{
+       int err, i;
+
+       for (i = 0; i < WM8776_CTL_COUNT; i++)
+               if (wm->ctl[i].name) {
+                       err = snd_wm8776_add_control(wm, i);
+                       if (err < 0)
+                               return err;
+               }
+
+       return 0;
+}
diff --git a/sound/pci/ice1712/wm8776.h b/sound/pci/ice1712/wm8776.h
new file mode 100644 (file)
index 0000000..93a2d69
--- /dev/null
@@ -0,0 +1,226 @@
+#ifndef __SOUND_WM8776_H
+#define __SOUND_WM8776_H
+
+/*
+ *   ALSA driver for ICEnsemble VT17xx
+ *
+ *   Lowlevel functions for WM8776 codec
+ *
+ *     Copyright (c) 2012 Ondrej Zary <linux@rainbow-software.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define WM8776_REG_HPLVOL      0x00
+#define WM8776_REG_HPRVOL      0x01
+#define WM8776_REG_HPMASTER    0x02
+#define WM8776_HPVOL_MASK              0x17f           /* incl. update bit */
+#define WM8776_VOL_HPZCEN              (1 << 7)        /* zero cross detect */
+#define WM8776_VOL_UPDATE              (1 << 8)        /* update volume */
+#define WM8776_REG_DACLVOL     0x03
+#define WM8776_REG_DACRVOL     0x04
+#define WM8776_REG_DACMASTER   0x05
+#define WM8776_DACVOL_MASK             0x1ff           /* incl. update bit */
+#define WM8776_REG_PHASESWAP   0x06
+#define WM8776_PHASE_INVERTL           (1 << 0)
+#define WM8776_PHASE_INVERTR           (1 << 1)
+#define WM8776_REG_DACCTRL1    0x07
+#define WM8776_DAC_DZCEN               (1 << 0)
+#define WM8776_DAC_ATC                 (1 << 1)
+#define WM8776_DAC_IZD                 (1 << 2)
+#define WM8776_DAC_TOD                 (1 << 3)
+#define WM8776_DAC_PL_MASK             0xf0
+#define WM8776_DAC_PL_LL               (1 << 4)        /* L chan: L signal */
+#define WM8776_DAC_PL_LR               (2 << 4)        /* L chan: R signal */
+#define WM8776_DAC_PL_LB               (3 << 4)        /* L chan: both */
+#define WM8776_DAC_PL_RL               (1 << 6)        /* R chan: L signal */
+#define WM8776_DAC_PL_RR               (2 << 6)        /* R chan: R signal */
+#define WM8776_DAC_PL_RB               (3 << 6)        /* R chan: both */
+#define WM8776_REG_DACMUTE     0x08
+#define WM8776_DACMUTE                 (1 << 0)
+#define WM8776_REG_DACCTRL2    0x09
+#define WM8776_DAC2_DEEMPH             (1 << 0)
+#define WM8776_DAC2_ZFLAG_DISABLE      (0 << 1)
+#define WM8776_DAC2_ZFLAG_OWN          (1 << 1)
+#define WM8776_DAC2_ZFLAG_BOTH         (2 << 1)
+#define WM8776_DAC2_ZFLAG_EITHER       (3 << 1)
+#define WM8776_REG_DACIFCTRL   0x0a
+#define WM8776_FMT_RIGHTJ              (0 << 0)
+#define WM8776_FMT_LEFTJ               (1 << 0)
+#define WM8776_FMT_I2S                 (2 << 0)
+#define WM8776_FMT_DSP                 (3 << 0)
+#define WM8776_FMT_DSP_LATE            (1 << 2)        /* in DSP mode */
+#define WM8776_FMT_LRC_INVERTED                (1 << 2)        /* in other modes */
+#define WM8776_FMT_BCLK_INVERTED       (1 << 3)
+#define WM8776_FMT_16BIT               (0 << 4)
+#define WM8776_FMT_20BIT               (1 << 4)
+#define WM8776_FMT_24BIT               (2 << 4)
+#define WM8776_FMT_32BIT               (3 << 4)
+#define WM8776_REG_ADCIFCTRL   0x0b
+#define WM8776_FMT_ADCMCLK_INVERTED    (1 << 6)
+#define WM8776_FMT_ADCHPD              (1 << 8)
+#define WM8776_REG_MSTRCTRL    0x0c
+#define WM8776_IF_ADC256FS             (2 << 0)
+#define WM8776_IF_ADC384FS             (3 << 0)
+#define WM8776_IF_ADC512FS             (4 << 0)
+#define WM8776_IF_ADC768FS             (5 << 0)
+#define WM8776_IF_OVERSAMP64           (1 << 3)
+#define WM8776_IF_DAC128FS             (0 << 4)
+#define WM8776_IF_DAC192FS             (1 << 4)
+#define WM8776_IF_DAC256FS             (2 << 4)
+#define WM8776_IF_DAC384FS             (3 << 4)
+#define WM8776_IF_DAC512FS             (4 << 4)
+#define WM8776_IF_DAC768FS             (5 << 4)
+#define WM8776_IF_DAC_MASTER           (1 << 7)
+#define WM8776_IF_ADC_MASTER           (1 << 8)
+#define WM8776_REG_PWRDOWN     0x0d
+#define WM8776_PWR_PDWN                        (1 << 0)
+#define WM8776_PWR_ADCPD               (1 << 1)
+#define WM8776_PWR_DACPD               (1 << 2)
+#define WM8776_PWR_HPPD                        (1 << 3)
+#define WM8776_PWR_AINPD               (1 << 6)
+#define WM8776_REG_ADCLVOL     0x0e
+#define WM8776_REG_ADCRVOL     0x0f
+#define WM8776_ADC_GAIN_MASK           0xff
+#define WM8776_ADC_ZCEN                        (1 << 8)
+#define WM8776_REG_ALCCTRL1    0x10
+#define WM8776_ALC1_LCT_MASK           0x0f    /* 0=-16dB, 1=-15dB..15=-1dB */
+#define WM8776_ALC1_MAXGAIN_MASK       0x70    /* 0,1=0dB, 2=+4dB...7=+24dB */
+#define WM8776_ALC1_LCSEL_MASK         0x180
+#define WM8776_ALC1_LCSEL_LIMITER      (0 << 7)
+#define WM8776_ALC1_LCSEL_ALCR         (1 << 7)
+#define WM8776_ALC1_LCSEL_ALCL         (2 << 7)
+#define WM8776_ALC1_LCSEL_ALCSTEREO    (3 << 7)
+#define WM8776_REG_ALCCTRL2    0x11
+#define WM8776_ALC2_HOLD_MASK          0x0f    /*0=0ms, 1=2.67ms, 2=5.33ms.. */
+#define WM8776_ALC2_ZCEN               (1 << 7)
+#define WM8776_ALC2_LCEN               (1 << 8)
+#define WM8776_REG_ALCCTRL3    0x12
+#define WM8776_ALC3_ATK_MASK           0x0f
+#define WM8776_ALC3_DCY_MASK           0xf0
+#define WM8776_ALC3_FDECAY             (1 << 8)
+#define WM8776_REG_NOISEGATE   0x13
+#define WM8776_NGAT_ENABLE             (1 << 0)
+#define WM8776_NGAT_THR_MASK           0x1c    /*0=-78dB, 1=-72dB...7=-36dB */
+#define WM8776_REG_LIMITER     0x14
+#define WM8776_LIM_MAXATTEN_MASK       0x0f
+#define WM8776_LIM_TRANWIN_MASK                0x70    /*0=0us, 1=62.5us, 2=125us.. */
+#define WM8776_REG_ADCMUX      0x15
+#define WM8776_ADC_MUX_AIN1            (1 << 0)
+#define WM8776_ADC_MUX_AIN2            (1 << 1)
+#define WM8776_ADC_MUX_AIN3            (1 << 2)
+#define WM8776_ADC_MUX_AIN4            (1 << 3)
+#define WM8776_ADC_MUX_AIN5            (1 << 4)
+#define WM8776_ADC_MUTER               (1 << 6)
+#define WM8776_ADC_MUTEL               (1 << 7)
+#define WM8776_ADC_LRBOTH              (1 << 8)
+#define WM8776_REG_OUTMUX      0x16
+#define WM8776_OUTMUX_DAC              (1 << 0)
+#define WM8776_OUTMUX_AUX              (1 << 1)
+#define WM8776_OUTMUX_BYPASS           (1 << 2)
+#define WM8776_REG_RESET       0x17
+
+#define WM8776_REG_COUNT       0x17    /* don't cache the RESET register */
+
+struct snd_wm8776;
+
+struct snd_wm8776_ops {
+       void (*write)(struct snd_wm8776 *wm, u8 addr, u8 data);
+};
+
+enum snd_wm8776_ctl_id {
+       WM8776_CTL_DAC_VOL,
+       WM8776_CTL_DAC_SW,
+       WM8776_CTL_DAC_ZC_SW,
+       WM8776_CTL_HP_VOL,
+       WM8776_CTL_HP_SW,
+       WM8776_CTL_HP_ZC_SW,
+       WM8776_CTL_AUX_SW,
+       WM8776_CTL_BYPASS_SW,
+       WM8776_CTL_DAC_IZD_SW,
+       WM8776_CTL_PHASE_SW,
+       WM8776_CTL_DEEMPH_SW,
+       WM8776_CTL_ADC_VOL,
+       WM8776_CTL_ADC_SW,
+       WM8776_CTL_INPUT1_SW,
+       WM8776_CTL_INPUT2_SW,
+       WM8776_CTL_INPUT3_SW,
+       WM8776_CTL_INPUT4_SW,
+       WM8776_CTL_INPUT5_SW,
+       WM8776_CTL_AGC_SEL,
+       WM8776_CTL_LIM_THR,
+       WM8776_CTL_LIM_ATK,
+       WM8776_CTL_LIM_DCY,
+       WM8776_CTL_LIM_TRANWIN,
+       WM8776_CTL_LIM_MAXATTN,
+       WM8776_CTL_ALC_TGT,
+       WM8776_CTL_ALC_ATK,
+       WM8776_CTL_ALC_DCY,
+       WM8776_CTL_ALC_MAXGAIN,
+       WM8776_CTL_ALC_MAXATTN,
+       WM8776_CTL_ALC_HLD,
+       WM8776_CTL_NGT_SW,
+       WM8776_CTL_NGT_THR,
+
+       WM8776_CTL_COUNT,
+};
+
+#define WM8776_ENUM_MAX                16
+
+#define WM8776_FLAG_STEREO     (1 << 0)
+#define WM8776_FLAG_VOL_UPDATE (1 << 1)
+#define WM8776_FLAG_INVERT     (1 << 2)
+#define WM8776_FLAG_LIM                (1 << 3)
+#define WM8776_FLAG_ALC                (1 << 4)
+
+struct snd_wm8776_ctl {
+       const char *name;
+       snd_ctl_elem_type_t type;
+       const char *const enum_names[WM8776_ENUM_MAX];
+       const unsigned int *tlv;
+       u16 reg1, reg2, mask1, mask2, min, max, flags;
+       void (*set)(struct snd_wm8776 *wm, u16 ch1, u16 ch2);
+       void (*get)(struct snd_wm8776 *wm, u16 *ch1, u16 *ch2);
+};
+
+enum snd_wm8776_agc_mode {
+       WM8776_AGC_OFF,
+       WM8776_AGC_LIM,
+       WM8776_AGC_ALC_R,
+       WM8776_AGC_ALC_L,
+       WM8776_AGC_ALC_STEREO
+};
+
+struct snd_wm8776 {
+       struct snd_card *card;
+       struct snd_wm8776_ctl ctl[WM8776_CTL_COUNT];
+       enum snd_wm8776_agc_mode agc_mode;
+       struct snd_wm8776_ops ops;
+       u16 regs[WM8776_REG_COUNT];     /* 9-bit registers */
+};
+
+
+
+void snd_wm8776_init(struct snd_wm8776 *wm);
+void snd_wm8776_resume(struct snd_wm8776 *wm);
+void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac);
+void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc);
+void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode);
+void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power);
+void snd_wm8776_volume_restore(struct snd_wm8776 *wm);
+int snd_wm8776_build_controls(struct snd_wm8776 *wm);
+
+#endif /* __SOUND_WM8776_H */
index e618f789026ea7dc4ff2ddddf4fc46a3e1328a39..bcf30a387b87640f2f42202b1189af0fde49066e 100644 (file)
@@ -25,7 +25,6 @@
 
 
 
-#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -384,7 +383,7 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
 /*
  * Control tabs
  */
-static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac9640_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -448,7 +447,7 @@ static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
 
 
 /*INIT*/
-static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
+static int wtm_add_controls(struct snd_ice1712 *ice)
 {
        unsigned int i;
        int err;
@@ -462,7 +461,7 @@ static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
        return 0;
 }
 
-static int __devinit wtm_init(struct snd_ice1712 *ice)
+static int wtm_init(struct snd_ice1712 *ice)
 {
        static unsigned short stac_inits_prodigy[] = {
                STAC946X_RESET, 0,
@@ -485,7 +484,7 @@ static int __devinit wtm_init(struct snd_ice1712 *ice)
 }
 
 
-static unsigned char wtm_eeprom[] __devinitdata = {
+static unsigned char wtm_eeprom[] = {
        0x47,   /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
        0x80,   /* ACLINK : I2S */
        0xf8,   /* I2S: vol; 96k, 24bit, 192k */
@@ -503,7 +502,7 @@ static unsigned char wtm_eeprom[] __devinitdata = {
 
 
 /*entry point*/
-struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
        {
                .subvendor = VT1724_SUBDEVICE_WTM,
                .name = "ESI Waveterminal 192M",
index ea4b706c8d635925c248bfb497a021361d990a27..3b9be752f3e2f8cdd5c9c248c1569a94446a49e9 100644 (file)
@@ -592,8 +592,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
        return res;
 }
 
-static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip,
-                                                  unsigned int codec)
+static void snd_intel8x0_codec_read_test(struct intel8x0 *chip,
+                                        unsigned int codec)
 {
        unsigned int tmp;
 
@@ -1507,8 +1507,8 @@ struct ich_pcm_table {
        int ac97_idx;
 };
 
-static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
-                                      struct ich_pcm_table *rec)
+static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
+                            struct ich_pcm_table *rec)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1564,7 +1564,7 @@ static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
        return 0;
 }
 
-static struct ich_pcm_table intel_pcms[] __devinitdata = {
+static struct ich_pcm_table intel_pcms[] = {
        {
                .playback_ops = &snd_intel8x0_playback_ops,
                .capture_ops = &snd_intel8x0_capture_ops,
@@ -1601,7 +1601,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
        },
 };
 
-static struct ich_pcm_table nforce_pcms[] __devinitdata = {
+static struct ich_pcm_table nforce_pcms[] = {
        {
                .playback_ops = &snd_intel8x0_playback_ops,
                .capture_ops = &snd_intel8x0_capture_ops,
@@ -1624,7 +1624,7 @@ static struct ich_pcm_table nforce_pcms[] __devinitdata = {
        },
 };
 
-static struct ich_pcm_table ali_pcms[] __devinitdata = {
+static struct ich_pcm_table ali_pcms[] = {
        {
                .playback_ops = &snd_intel8x0_ali_playback_ops,
                .capture_ops = &snd_intel8x0_ali_capture_ops,
@@ -1656,7 +1656,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = {
 #endif
 };
 
-static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip)
+static int snd_intel8x0_pcm(struct intel8x0 *chip)
 {
        int i, tblsize, device, err;
        struct ich_pcm_table *tbl, *rec;
@@ -1719,7 +1719,7 @@ static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
        chip->ac97[ac97->num] = NULL;
 }
 
-static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
+static struct ac97_pcm ac97_pcm_defs[] = {
        /* front PCM */
        {
                .exclusive = 1,
@@ -1789,7 +1789,7 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
        },
 };
 
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
+static struct ac97_quirk ac97_quirks[] = {
         {
                .subvendor = 0x0e11,
                .subdevice = 0x000e,
@@ -2196,8 +2196,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
        { } /* terminator */
 };
 
-static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
-                                       const char *quirk_override)
+static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
+                             const char *quirk_override)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
@@ -2765,7 +2765,7 @@ static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume);
 
 #define INTEL8X0_TESTBUF_SIZE  32768   /* enough large for one shot */
 
-static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
+static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
 {
        struct snd_pcm_substream *subs;
        struct ichdev *ichdev;
@@ -2883,7 +2883,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
        snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
 }
 
-static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
+static struct snd_pci_quirk intel8x0_clock_list[] = {
        SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
        SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
        SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000),
@@ -2892,7 +2892,7 @@ static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
        { }     /* terminator */
 };
 
-static int __devinit intel8x0_in_clock_list(struct intel8x0 *chip)
+static int intel8x0_in_clock_list(struct intel8x0 *chip)
 {
        struct pci_dev *pci = chip->pci;
        const struct snd_pci_quirk *wl;
@@ -2941,7 +2941,7 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
                        chip->ac97_sdin[2]);
 }
 
-static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip)
+static void snd_intel8x0_proc_init(struct intel8x0 *chip)
 {
        struct snd_info_entry *entry;
 
@@ -2970,7 +2970,7 @@ static unsigned int sis_codec_bits[3] = {
        ICH_PCR, ICH_SCR, ICH_SIS_TCR
 };
 
-static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
+static int snd_intel8x0_inside_vm(struct pci_dev *pci)
 {
        int result  = inside_vm;
        char *msg   = NULL;
@@ -3009,10 +3009,10 @@ fini:
        return result;
 }
 
-static int __devinit snd_intel8x0_create(struct snd_card *card,
-                                        struct pci_dev *pci,
-                                        unsigned long device_type,
-                                        struct intel8x0 ** r_intel8x0)
+static int snd_intel8x0_create(struct snd_card *card,
+                              struct pci_dev *pci,
+                              unsigned long device_type,
+                              struct intel8x0 **r_intel8x0)
 {
        struct intel8x0 *chip;
        int err;
@@ -3227,7 +3227,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
 static struct shortname_table {
        unsigned int id;
        const char *s;
-} shortnames[] __devinitdata = {
+} shortnames[] = {
        { PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
        { PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
        { PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
@@ -3253,13 +3253,13 @@ static struct shortname_table {
        { 0, NULL },
 };
 
-static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = {
+static struct snd_pci_quirk spdif_aclink_defaults[] = {
        SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
        { } /* end */
 };
 
 /* look up white/black list for SPDIF over ac-link */
-static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
+static int check_default_spdif_aclink(struct pci_dev *pci)
 {
        const struct snd_pci_quirk *w;
 
@@ -3276,8 +3276,8 @@ static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
        return 0;
 }
 
-static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_intel8x0_probe(struct pci_dev *pci,
+                             const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct intel8x0 *chip;
@@ -3359,7 +3359,7 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
+static void snd_intel8x0_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -3369,7 +3369,7 @@ static struct pci_driver intel8x0_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_intel8x0_ids,
        .probe = snd_intel8x0_probe,
-       .remove = __devexit_p(snd_intel8x0_remove),
+       .remove = snd_intel8x0_remove,
        .driver = {
                .pm = INTEL8X0_PM_OPS,
        },
index 4d551736531eebe546e4620768907e6775840ab2..fea09e8ea608d0078fa84e8fa81e73e40a33802c 100644 (file)
@@ -710,8 +710,8 @@ struct ich_pcm_table {
        int ac97_idx;
 };
 
-static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
-                                      struct ich_pcm_table *rec)
+static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
+                             struct ich_pcm_table *rec)
 {
        struct snd_pcm *pcm;
        int err;
@@ -749,7 +749,7 @@ static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
        return 0;
 }
 
-static struct ich_pcm_table intel_pcms[] __devinitdata = {
+static struct ich_pcm_table intel_pcms[] = {
        {
                .suffix = "Modem",
                .playback_ops = &snd_intel8x0m_playback_ops,
@@ -759,7 +759,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
        },
 };
 
-static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip)
+static int snd_intel8x0m_pcm(struct intel8x0m *chip)
 {
        int i, tblsize, device, err;
        struct ich_pcm_table *tbl, *rec;
@@ -819,7 +819,7 @@ static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97)
 }
 
 
-static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
+static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
@@ -1090,7 +1090,7 @@ static void snd_intel8x0m_proc_read(struct snd_info_entry * entry,
                        (tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : "");
 }
 
-static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
+static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1113,10 +1113,10 @@ struct ich_reg_info {
        unsigned int offset;
 };
 
-static int __devinit snd_intel8x0m_create(struct snd_card *card,
-                                        struct pci_dev *pci,
-                                        unsigned long device_type,
-                                        struct intel8x0m **r_intel8x0m)
+static int snd_intel8x0m_create(struct snd_card *card,
+                               struct pci_dev *pci,
+                               unsigned long device_type,
+                               struct intel8x0m **r_intel8x0m)
 {
        struct intel8x0m *chip;
        int err;
@@ -1252,7 +1252,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 static struct shortname_table {
        unsigned int id;
        const char *s;
-} shortnames[] __devinitdata = {
+} shortnames[] = {
        { PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },
        { PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },
        { PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },
@@ -1275,8 +1275,8 @@ static struct shortname_table {
        { 0 },
 };
 
-static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_intel8x0m_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct intel8x0m *chip;
@@ -1325,7 +1325,7 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
+static void snd_intel8x0m_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1335,7 +1335,7 @@ static struct pci_driver intel8x0m_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_intel8x0m_ids,
        .probe = snd_intel8x0m_probe,
-       .remove = __devexit_p(snd_intel8x0m_remove),
+       .remove = snd_intel8x0m_remove,
        .driver = {
                .pm = INTEL8X0M_PM_OPS,
        },
index 8a67ce95f2468395a65474f8a7de194241570c35..43b4228d9afe41812a25d4d9ea81e2b028016410 100644 (file)
@@ -2083,7 +2083,7 @@ static void snd_korg1212_proc_read(struct snd_info_entry *entry,
         snd_iprintf(buffer, "    Error count: %ld\n", korg1212->totalerrorcnt);
 }
 
-static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
+static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
 {
        struct snd_info_entry *entry;
 
@@ -2154,8 +2154,8 @@ static int snd_korg1212_dev_free(struct snd_device *device)
        return snd_korg1212_free(korg1212);
 }
 
-static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
-                                         struct snd_korg1212 ** rchip)
+static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
+                              struct snd_korg1212 **rchip)
 
 {
         int err, rc;
@@ -2429,7 +2429,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
  * Card initialisation
  */
 
-static int __devinit
+static int
 snd_korg1212_probe(struct pci_dev *pci,
                const struct pci_device_id *pci_id)
 {
@@ -2470,7 +2470,7 @@ snd_korg1212_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_korg1212_remove(struct pci_dev *pci)
+static void snd_korg1212_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2480,7 +2480,7 @@ static struct pci_driver korg1212_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_korg1212_ids,
        .probe = snd_korg1212_probe,
-       .remove = __devexit_p(snd_korg1212_remove),
+       .remove = snd_korg1212_remove,
 };
 
 module_pci_driver(korg1212_driver);
index ac15166bee6889477d5cc4c005adc8979c6b7ee5..322b638e8ec48056c7e433f2067e4aff80bd0014 100644 (file)
@@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip)
        lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */
 }
 
-static int __devinit lola_parse_tree(struct lola *chip)
+static int lola_parse_tree(struct lola *chip)
 {
        unsigned int val;
        int nid, err;
@@ -568,8 +568,8 @@ static int lola_dev_free(struct snd_device *device)
        return 0;
 }
 
-static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
-                                int dev, struct lola **rchip)
+static int lola_create(struct snd_card *card, struct pci_dev *pci,
+                      int dev, struct lola **rchip)
 {
        struct lola *chip;
        int err;
@@ -702,8 +702,8 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
        return err;
 }
 
-static int __devinit lola_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
+static int lola_probe(struct pci_dev *pci,
+                     const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -756,7 +756,7 @@ out_free:
        return err;
 }
 
-static void __devexit lola_remove(struct pci_dev *pci)
+static void lola_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -774,7 +774,7 @@ static struct pci_driver lola_driver = {
        .name = KBUILD_MODNAME,
        .id_table = lola_ids,
        .probe = lola_probe,
-       .remove = __devexit_p(lola_remove),
+       .remove = lola_remove,
 };
 
 module_pci_driver(lola_driver);
index 72f8ef0ac8652900119c8a8eee4a8788ecf4068e..eb1d6b97df164f20517222be0173df1e792dce1b 100644 (file)
@@ -120,7 +120,7 @@ int lola_set_granularity(struct lola *chip, unsigned int val, bool force)
  * Clock widget handling
  */
 
-int __devinit lola_init_clock_widget(struct lola *chip, int nid)
+int lola_init_clock_widget(struct lola *chip, int nid)
 {
        unsigned int val;
        int i, j, nitems, nb_verbs, idx, idx_list;
index 6b8d64812951a1c15626ef9ed37c731ee9dad502..52c8d6b0f39b9c7b35183f89642a816d8cdd7e58 100644 (file)
@@ -28,8 +28,8 @@
 #include <sound/tlv.h>
 #include "lola.h"
 
-static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
-                                  int dir, int nid)
+static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
+                        int dir, int nid)
 {
        unsigned int val;
        int err;
@@ -91,7 +91,7 @@ static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
        return 0;
 }
 
-int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp)
+int lola_init_pins(struct lola *chip, int dir, int *nidp)
 {
        int i, err, nid;
        nid = *nidp;
@@ -112,7 +112,7 @@ void lola_free_mixer(struct lola *chip)
                vfree(chip->mixer.array_saved);
 }
 
-int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
+int lola_init_mixer_widget(struct lola *chip, int nid)
 {
        unsigned int val;
        int err;
@@ -579,7 +579,7 @@ static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        return 0;
 }
 
-static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_analog_mixer = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
                   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -590,7 +590,7 @@ static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
        .tlv.c = lola_analog_vol_tlv,
 };
 
-static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name)
+static int create_analog_mixer(struct lola *chip, int dir, char *name)
 {
        if (!chip->pin[dir].num_pins)
                return 0;
@@ -644,7 +644,7 @@ static int lola_input_src_put(struct snd_kcontrol *kcontrol,
        return lola_set_src_config(chip, mask, true);
 }
 
-static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_input_src_mixer = {
        .name = "Digital SRC Capture Switch",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = lola_input_src_info,
@@ -656,7 +656,7 @@ static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
  * Lola16161 or Lola881 can have Hardware sample rate converters
  * on its digital input pins
  */
-static int __devinit create_input_src_mixer(struct lola *chip)
+static int create_input_src_mixer(struct lola *chip)
 {
        if (!chip->input_src_caps_mask)
                return 0;
@@ -726,7 +726,7 @@ static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
 /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
 static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
 
-static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_src_gain_mixer = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
                   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -736,8 +736,8 @@ static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
        .tlv.p = lola_src_gain_tlv,
 };
 
-static int __devinit create_src_gain_mixer(struct lola *chip,
-                                          int num, int ofs, char *name)
+static int create_src_gain_mixer(struct lola *chip,
+                                int num, int ofs, char *name)
 {
        lola_src_gain_mixer.name = name;
        lola_src_gain_mixer.private_value = ofs + (num << 8);
@@ -813,7 +813,7 @@ static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
 
-static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
+static struct snd_kcontrol_new lola_dest_gain_mixer = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
                   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -823,9 +823,9 @@ static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
        .tlv.p = lola_dest_gain_tlv,
 };
 
-static int __devinit create_dest_gain_mixer(struct lola *chip,
-                                           int src_num, int src_ofs,
-                                           int num, int ofs, char *name)
+static int create_dest_gain_mixer(struct lola *chip,
+                                 int src_num, int src_ofs,
+                                 int num, int ofs, char *name)
 {
        lola_dest_gain_mixer.count = num;
        lola_dest_gain_mixer.name = name;
@@ -838,7 +838,7 @@ static int __devinit create_dest_gain_mixer(struct lola *chip,
 
 /*
  */
-int __devinit lola_create_mixer(struct lola *chip)
+int lola_create_mixer(struct lola *chip)
 {
        int err;
 
index c44db68eecb57b01b95d01eb4d8e92e9495d7f14..5ea85e8b83ab5018029d92504902775170adb018 100644 (file)
@@ -597,7 +597,7 @@ static struct snd_pcm_ops lola_pcm_ops = {
        .page = snd_pcm_sgbuf_ops_page,
 };
 
-int __devinit lola_create_pcm(struct lola *chip)
+int lola_create_pcm(struct lola *chip)
 {
        struct snd_pcm *pcm;
        int i, err;
@@ -690,7 +690,7 @@ static int lola_init_stream(struct lola *chip, struct lola_stream *str,
        return 0;
 }
 
-int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp)
+int lola_init_pcm(struct lola *chip, int dir, int *nidp)
 {
        struct lola_pcm *pcm = &chip->pcm[dir];
        int i, nid, err;
index 9d7daf897c9d2f5c474e5eeaf6a47e21a23c5f1c..04df83defc092c52723cac488ca972737342e425 100644 (file)
@@ -206,7 +206,7 @@ static void lola_proc_regs_read(struct snd_info_entry *entry,
        }
 }
 
-void __devinit lola_proc_debug_new(struct lola *chip)
+void lola_proc_debug_new(struct lola *chip)
 {
        struct snd_info_entry *entry;
 
index 5579b08bb35b6337c646b6d2cb6be5215f0d01d9..298bc9b7299116b23a83e572c69cfb3224124351 100644 (file)
@@ -578,7 +578,7 @@ static int snd_lx6464es_dev_free(struct snd_device *device)
 }
 
 /* reset the dsp during initialization */
-static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
+static int lx_init_xilinx_reset(struct lx6464es *chip)
 {
        int i;
        u32 plx_reg = lx_plx_reg_read(chip, ePLX_CHIPSC);
@@ -620,7 +620,7 @@ static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
        return 0;
 }
 
-static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
+static int lx_init_xilinx_test(struct lx6464es *chip)
 {
        u32 reg;
 
@@ -650,7 +650,7 @@ static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
 }
 
 /* initialize ethersound */
-static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
+static int lx_init_ethersound_config(struct lx6464es *chip)
 {
        int i;
        u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES);
@@ -690,7 +690,7 @@ static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
        return 0;
 }
 
-static int __devinit lx_init_get_version_features(struct lx6464es *chip)
+static int lx_init_get_version_features(struct lx6464es *chip)
 {
        u32 dsp_version;
 
@@ -759,7 +759,7 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran)
 }
 
 /* initialize and test the xilinx dsp chip */
-static int __devinit lx_init_dsp(struct lx6464es *chip)
+static int lx_init_dsp(struct lx6464es *chip)
 {
        int err;
        int i;
@@ -835,7 +835,7 @@ static struct snd_pcm_ops lx_ops_capture = {
        .pointer   = lx_pcm_stream_pointer,
 };
 
-static int __devinit lx_pcm_create(struct lx6464es *chip)
+static int lx_pcm_create(struct lx6464es *chip)
 {
        int err;
        struct snd_pcm *pcm;
@@ -907,7 +907,7 @@ static int lx_control_playback_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new lx_control_playback_switch __devinitdata = {
+static struct snd_kcontrol_new lx_control_playback_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "PCM Playback Switch",
        .index = 0,
@@ -954,7 +954,7 @@ static void lx_proc_levels_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "\n");
 }
 
-static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip)
+static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
 {
        struct snd_info_entry *entry;
        int err = snd_card_proc_new(card, "levels", &entry);
@@ -966,9 +966,9 @@ static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip
 }
 
 
-static int __devinit snd_lx6464es_create(struct snd_card *card,
-                                        struct pci_dev *pci,
-                                        struct lx6464es **rchip)
+static int snd_lx6464es_create(struct snd_card *card,
+                              struct pci_dev *pci,
+                              struct lx6464es **rchip)
 {
        struct lx6464es *chip;
        int err;
@@ -1082,8 +1082,8 @@ alloc_failed:
        return err;
 }
 
-static int __devinit snd_lx6464es_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_lx6464es_probe(struct pci_dev *pci,
+                             const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -1136,7 +1136,7 @@ out_free:
 
 }
 
-static void __devexit snd_lx6464es_remove(struct pci_dev *pci)
+static void snd_lx6464es_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1147,7 +1147,7 @@ static struct pci_driver lx6464es_driver = {
        .name =     KBUILD_MODNAME,
        .id_table = snd_lx6464es_ids,
        .probe =    snd_lx6464es_probe,
-       .remove = __devexit_p(snd_lx6464es_remove),
+       .remove = snd_lx6464es_remove,
 };
 
 module_pci_driver(lx6464es_driver);
index 8c3e7fcefd99c91c38d39f92fd0cae8323cee210..633c8607d05374c7995d4a61af918d9f4b99eca9 100644 (file)
@@ -385,7 +385,7 @@ polling_successful:
 
 
 /* low-level dsp access */
-int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
+int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
 {
        u16 ret;
        unsigned long flags;
index 4d7ff797a6468abf5b5499cdfd92dab430d9948f..5ec5e04da1a5a02f2008b070c76e24fe3964765e 100644 (file)
@@ -109,7 +109,7 @@ struct lx_rmh {
 
 
 /* low-level dsp access */
-int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
+int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
 int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq);
 int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran);
 int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data);
index eb3cd3a4315eff8990b7f2d7162a6aaa640d35e6..9387533f70dc36c9d6b7cfd5498ff6a468fa09d8 100644 (file)
@@ -822,7 +822,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = {
 
 MODULE_DEVICE_TABLE(pci, snd_m3_ids);
 
-static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_amp_quirk_list[] = {
        SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c),
        SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
        SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
@@ -831,7 +831,7 @@ static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
        { } /* END */
 };
 
-static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_irda_quirk_list[] = {
        SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),
        SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),
        SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),
@@ -839,7 +839,7 @@ static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
 };
 
 /* hardware volume quirks */
-static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_hv_quirk_list[] = {
        /* Allegro chips */
        SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
        SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
@@ -917,7 +917,7 @@ static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
 };
 
 /* HP Omnibook quirks */
-static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = {
+static struct snd_pci_quirk m3_omnibook_quirk_list[] = {
        SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */
        SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */
        { } /* END */
@@ -1856,7 +1856,7 @@ static struct snd_pcm_ops snd_m3_capture_ops = {
        .pointer =      snd_m3_pcm_pointer,
 };
 
-static int __devinit
+static int
 snd_m3_pcm(struct snd_m3 * chip, int device)
 {
        struct snd_pcm *pcm;
@@ -2031,7 +2031,7 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip)
 #endif
 }
 
-static int __devinit snd_m3_mixer(struct snd_m3 *chip)
+static int snd_m3_mixer(struct snd_m3 *chip)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
@@ -2173,7 +2173,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip)
 }
 
 
-static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
+static int snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
 {
        int data_bytes = 2 * ( MINISRC_TMP_BUFFER_SIZE / 2 + 
                               MINISRC_IN_BUFFER_SIZE / 2 +
@@ -2488,7 +2488,7 @@ static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume);
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_SND_MAESTRO3_INPUT
-static int __devinit snd_m3_input_register(struct snd_m3 *chip)
+static int snd_m3_input_register(struct snd_m3 *chip)
 {
        struct input_dev *input_dev;
        int err;
@@ -2532,7 +2532,7 @@ static int snd_m3_dev_free(struct snd_device *device)
        return snd_m3_free(chip);
 }
 
-static int __devinit
+static int
 snd_m3_create(struct snd_card *card, struct pci_dev *pci,
              int enable_amp,
              int amp_gpio,
@@ -2700,7 +2700,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 
 /*
  */
-static int __devinit
+static int
 snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -2770,7 +2770,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        return 0;
 }
 
-static void __devexit snd_m3_remove(struct pci_dev *pci)
+static void snd_m3_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2780,7 +2780,7 @@ static struct pci_driver m3_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_m3_ids,
        .probe = snd_m3_probe,
-       .remove = __devexit_p(snd_m3_remove),
+       .remove = snd_m3_remove,
        .driver = {
                .pm = M3_PM_OPS,
        },
index 0762610c99c0e7046f490d0d71e9a304a9e940c7..01f7f37a84101dff11742a415ad607a9ac2d095c 100644 (file)
@@ -1004,7 +1004,7 @@ static int snd_mixart_chip_dev_free(struct snd_device *device)
 
 /*
  */
-static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
+static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
 {
        int err;
        struct snd_mixart *chip;
@@ -1180,7 +1180,7 @@ static void snd_mixart_proc_read(struct snd_info_entry *entry,
        } /* endif elf loaded */
 }
 
-static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
+static void snd_mixart_proc_init(struct snd_mixart *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1209,8 +1209,8 @@ static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
 /*
  *    probe function - creates the card manager
  */
-static int __devinit snd_mixart_probe(struct pci_dev *pci,
-                                     const struct pci_device_id *pci_id)
+static int snd_mixart_probe(struct pci_dev *pci,
+                           const struct pci_device_id *pci_id)
 {
        static int dev;
        struct mixart_mgr *mgr;
@@ -1374,7 +1374,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_mixart_remove(struct pci_dev *pci)
+static void snd_mixart_remove(struct pci_dev *pci)
 {
        snd_mixart_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1384,7 +1384,7 @@ static struct pci_driver mixart_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_mixart_ids,
        .probe = snd_mixart_probe,
-       .remove = __devexit_p(snd_mixart_remove),
+       .remove = snd_mixart_remove,
 };
 
 module_pci_driver(mixart_driver);
index e0f4d87555a04ace24920b66fe96bf8994d6e111..ece1f831c16a834c8c0806ea5d5c812bc257f24f 100644 (file)
@@ -546,14 +546,6 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw
 }
 
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_MIXARTLOADER) && !defined(CONFIG_SND_MIXART) /* built-in kernel */
-#define SND_MIXART_FW_LOADER   /* use the standard firmware loader */
-#endif
-#endif
-
-#ifdef SND_MIXART_FW_LOADER
-
 int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
 {
        static char *fw_files[3] = {
@@ -583,71 +575,3 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
 MODULE_FIRMWARE("mixart/miXart8.xlx");
 MODULE_FIRMWARE("mixart/miXart8.elf");
 MODULE_FIRMWARE("mixart/miXart8AES.xlx");
-
-#else /* old style firmware loading */
-
-/* miXart hwdep interface id string */
-#define SND_MIXART_HWDEP_ID       "miXart Loader"
-
-static int mixart_hwdep_dsp_status(struct snd_hwdep *hw,
-                                  struct snd_hwdep_dsp_status *info)
-{
-       struct mixart_mgr *mgr = hw->private_data;
-
-       strcpy(info->id, "miXart");
-        info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
-
-       if (mgr->dsp_loaded & (1 <<  MIXART_MOTHERBOARD_ELF_INDEX))
-               info->chip_ready = 1;
-
-       info->version = MIXART_DRIVER_VERSION;
-       return 0;
-}
-
-static int mixart_hwdep_dsp_load(struct snd_hwdep *hw,
-                                struct snd_hwdep_dsp_image *dsp)
-{
-       struct mixart_mgr* mgr = hw->private_data;
-       struct firmware fw;
-       int err;
-
-       fw.size = dsp->length;
-       fw.data = vmalloc(dsp->length);
-       if (! fw.data) {
-               snd_printk(KERN_ERR "miXart: cannot allocate image size %d\n",
-                          (int)dsp->length);
-               return -ENOMEM;
-       }
-       if (copy_from_user((void *) fw.data, dsp->image, dsp->length)) {
-               vfree(fw.data);
-               return -EFAULT;
-       }
-       err = mixart_dsp_load(mgr, dsp->index, &fw);
-       vfree(fw.data);
-       if (err < 0)
-               return err;
-       mgr->dsp_loaded |= 1 << dsp->index;
-       return err;
-}
-
-int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
-{
-       int err;
-       struct snd_hwdep *hw;
-
-       /* only create hwdep interface for first cardX (see "index" module parameter)*/
-       if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0)
-               return err;
-
-       hw->iface = SNDRV_HWDEP_IFACE_MIXART;
-       hw->private_data = mgr;
-       hw->ops.dsp_status = mixart_hwdep_dsp_status;
-       hw->ops.dsp_load = mixart_hwdep_dsp_load;
-       hw->exclusive = 1;
-       sprintf(hw->name,  SND_MIXART_HWDEP_ID);
-       mgr->dsp_loaded = 0;
-
-       return snd_card_register(mgr->chip[0]->card);
-}
-
-#endif /* SND_MIXART_FW_LOADER */
index e80e9a1e84aa4b8cd6ccfaf12abe49de0b063343..563a193e36a3d84d65998c45fb0fb0b5279eb532 100644 (file)
@@ -928,7 +928,7 @@ static struct snd_pcm_ops snd_nm256_capture_ops = {
        .mmap =         snd_pcm_lib_mmap_iomem,
 };
 
-static int __devinit
+static int
 snd_nm256_pcm(struct nm256 *chip, int device)
 {
        struct snd_pcm *pcm;
@@ -1295,7 +1295,7 @@ snd_nm256_ac97_reset(struct snd_ac97 *ac97)
 }
 
 /* create an ac97 mixer interface */
-static int __devinit
+static int
 snd_nm256_mixer(struct nm256 *chip)
 {
        struct snd_ac97_bus *pbus;
@@ -1336,7 +1336,7 @@ snd_nm256_mixer(struct nm256 *chip)
  * RAM.
  */
 
-static int __devinit
+static int
 snd_nm256_peek_for_sig(struct nm256 *chip)
 {
        /* The signature is located 1K below the end of video RAM.  */
@@ -1472,7 +1472,7 @@ static int snd_nm256_dev_free(struct snd_device *device)
        return snd_nm256_free(chip);
 }
 
-static int __devinit
+static int
 snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
                 struct nm256 **chip_ret)
 {
@@ -1639,7 +1639,7 @@ __error:
 
 enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 };
 
-static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
+static struct snd_pci_quirk nm256_quirks[] = {
        /* HP omnibook 4150 has cs4232 codec internally */
        SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED),
        /* Reset workarounds to avoid lock-ups */
@@ -1650,8 +1650,8 @@ static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
 };
 
 
-static int __devinit snd_nm256_probe(struct pci_dev *pci,
-                                    const struct pci_device_id *pci_id)
+static int snd_nm256_probe(struct pci_dev *pci,
+                          const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct nm256 *chip;
@@ -1742,7 +1742,7 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_nm256_remove(struct pci_dev *pci)
+static void snd_nm256_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1753,7 +1753,7 @@ static struct pci_driver nm256_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_nm256_ids,
        .probe = snd_nm256_probe,
-       .remove = __devexit_p(snd_nm256_remove),
+       .remove = snd_nm256_remove,
        .driver = {
                .pm = NM256_PM_OPS,
        },
index 2becae155a48d2f0c49bcb999194bc61a469e139..ada6c256378e18660061c59c37352785314b41f8 100644 (file)
@@ -756,8 +756,8 @@ static const struct oxygen_model model_generic = {
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
-static int __devinit get_oxygen_model(struct oxygen *chip,
-                                     const struct pci_device_id *id)
+static int get_oxygen_model(struct oxygen *chip,
+                           const struct pci_device_id *id)
 {
        static const char *const names[] = {
                [MODEL_MERIDIAN]        = "AuzenTech X-Meridian",
@@ -848,8 +848,8 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
        return 0;
 }
 
-static int __devinit generic_oxygen_probe(struct pci_dev *pci,
-                                         const struct pci_device_id *pci_id)
+static int generic_oxygen_probe(struct pci_dev *pci,
+                               const struct pci_device_id *pci_id)
 {
        static int dev;
        int err;
@@ -871,7 +871,7 @@ static struct pci_driver oxygen_driver = {
        .name = KBUILD_MODNAME,
        .id_table = oxygen_ids,
        .probe = generic_oxygen_probe,
-       .remove = __devexit_p(oxygen_pci_remove),
+       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index 3d71423b23bcf5450b2926c5b900fa76a91a8559..64b9fda5f04a71f4d0898d083468a6ed94437d8f 100644 (file)
@@ -52,13 +52,14 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
        { OXYGEN_PCI_SUBID(0x1043, 0x835d) },
        { OXYGEN_PCI_SUBID(0x1043, 0x835e) },
        { OXYGEN_PCI_SUBID(0x1043, 0x838e) },
+       { OXYGEN_PCI_SUBID(0x1043, 0x8522) },
        { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
        { }
 };
 MODULE_DEVICE_TABLE(pci, xonar_ids);
 
-static int __devinit get_xonar_model(struct oxygen *chip,
-                                    const struct pci_device_id *id)
+static int get_xonar_model(struct oxygen *chip,
+                          const struct pci_device_id *id)
 {
        if (get_xonar_pcm179x_model(chip, id) >= 0)
                return 0;
@@ -69,8 +70,8 @@ static int __devinit get_xonar_model(struct oxygen *chip,
        return -EINVAL;
 }
 
-static int __devinit xonar_probe(struct pci_dev *pci,
-                                const struct pci_device_id *pci_id)
+static int xonar_probe(struct pci_dev *pci,
+                      const struct pci_device_id *pci_id)
 {
        static int dev;
        int err;
@@ -92,7 +93,7 @@ static struct pci_driver xonar_driver = {
        .name = KBUILD_MODNAME,
        .id_table = xonar_ids,
        .probe = xonar_probe,
-       .remove = __devexit_p(oxygen_pci_remove),
+       .remove = oxygen_pci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &oxygen_pci_pm,
index c8febf4b9bd6e10c9763c989ee1d059486f019bc..d231b93d6ab5443604aa651ff859e266f7d6a60c 100644 (file)
@@ -431,8 +431,8 @@ static const struct oxygen_model model_xonar_d1 = {
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
-int __devinit get_xonar_cs43xx_model(struct oxygen *chip,
-                                    const struct pci_device_id *id)
+int get_xonar_cs43xx_model(struct oxygen *chip,
+                          const struct pci_device_id *id)
 {
        switch (id->subdevice) {
        case 0x834f:
index 8433aa7c3d754064f9e0b57cae437277161f09f5..c8c7f2c9b355ae8f4dde5d8deb4b68a11a64f296 100644 (file)
@@ -1087,8 +1087,8 @@ static const struct oxygen_model model_xonar_st = {
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
-int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
-                                     const struct pci_device_id *id)
+int get_xonar_pcm179x_model(struct oxygen *chip,
+                           const struct pci_device_id *id)
 {
        switch (id->subdevice) {
        case 0x8269:
index 63cff90706bf1749b9b7154f1c6ec81c903f68fd..6ce68604c25e4834460b3c0533e8b1eaca511151 100644 (file)
@@ -1255,7 +1255,6 @@ static void dump_wm87x6_registers(struct oxygen *chip,
 }
 
 static const struct oxygen_model model_xonar_ds = {
-       .shortname = "Xonar DS",
        .longname = "Asus Virtuoso 66",
        .chip = "AV200",
        .init = xonar_ds_init,
@@ -1321,12 +1320,17 @@ static const struct oxygen_model model_xonar_hdav_slim = {
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
-int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
-                                    const struct pci_device_id *id)
+int get_xonar_wm87x6_model(struct oxygen *chip,
+                          const struct pci_device_id *id)
 {
        switch (id->subdevice) {
        case 0x838e:
                chip->model = model_xonar_ds;
+               chip->model.shortname = "Xonar DS";
+               break;
+       case 0x8522:
+               chip->model = model_xonar_ds;
+               chip->model.shortname = "Xonar DSX";
                break;
        case 0x835e:
                chip->model = model_xonar_hdav_slim;
index be4f1456009a55ea33d5c8597da0607fc4b203a3..b97384ad946dae84ec724f4c91d2b46a226b50df 100644 (file)
@@ -1203,8 +1203,8 @@ static int pcxhr_chip_dev_free(struct snd_device *device)
 
 /*
  */
-static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
-                                 struct snd_card *card, int idx)
+static int pcxhr_create(struct pcxhr_mgr *mgr,
+                       struct snd_card *card, int idx)
 {
        int err;
        struct snd_pcxhr *chip;
@@ -1453,7 +1453,7 @@ static void pcxhr_proc_ltc(struct snd_info_entry *entry,
        }
 }
 
-static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
+static void pcxhr_proc_init(struct snd_pcxhr *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1513,8 +1513,8 @@ static int pcxhr_free(struct pcxhr_mgr *mgr)
 /*
  *    probe function - creates the card manager
  */
-static int __devinit pcxhr_probe(struct pci_dev *pci,
-                                const struct pci_device_id *pci_id)
+static int pcxhr_probe(struct pci_dev *pci,
+                      const struct pci_device_id *pci_id)
 {
        static int dev;
        struct pcxhr_mgr *mgr;
@@ -1688,7 +1688,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit pcxhr_remove(struct pci_dev *pci)
+static void pcxhr_remove(struct pci_dev *pci)
 {
        pcxhr_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1698,7 +1698,7 @@ static struct pci_driver pcxhr_driver = {
        .name = KBUILD_MODNAME,
        .id_table = pcxhr_ids,
        .probe = pcxhr_probe,
-       .remove = __devexit_p(pcxhr_remove),
+       .remove = pcxhr_remove,
 };
 
 module_pci_driver(pcxhr_driver);
index bf207e317f71864ad2dc35b4003be764b81f5c39..d995175c1c48c44960071683fd03aff64d260b42 100644 (file)
 #include "pcxhr_mix22.h"
 
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */
-#define SND_PCXHR_FW_LOADER    /* use the standard firmware loader */
-#endif
-#endif
-
-
 static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
 /*
  * get basic information and init pcxhr card
@@ -362,8 +355,6 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
 /*
  * fw loader entry
  */
-#ifdef SND_PCXHR_FW_LOADER
-
 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
 {
        static char *fw_files[][5] = {
@@ -424,80 +415,3 @@ MODULE_FIRMWARE("pcxhr/xlxc924.dat");
 MODULE_FIRMWARE("pcxhr/dspe924.e56");
 MODULE_FIRMWARE("pcxhr/dspb924.b56");
 MODULE_FIRMWARE("pcxhr/dspd222.d56");
-
-
-#else /* old style firmware loading */
-
-/* pcxhr hwdep interface id string */
-#define PCXHR_HWDEP_ID       "pcxhr loader"
-
-
-static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw,
-                                 struct snd_hwdep_dsp_status *info)
-{
-       struct pcxhr_mgr *mgr = hw->private_data;
-       sprintf(info->id, "pcxhr%d", mgr->fw_file_set);
-        info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX;
-
-       if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))
-               info->chip_ready = 1;
-
-       info->version = PCXHR_DRIVER_VERSION;
-       return 0;
-}
-
-static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
-                               struct snd_hwdep_dsp_image *dsp)
-{
-       struct pcxhr_mgr *mgr = hw->private_data;
-       int err;
-       struct firmware fw;
-
-       fw.size = dsp->length;
-       fw.data = vmalloc(fw.size);
-       if (! fw.data) {
-               snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image "
-                          "(%lu bytes)\n", (unsigned long)fw.size);
-               return -ENOMEM;
-       }
-       if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) {
-               vfree(fw.data);
-               return -EFAULT;
-       }
-       err = pcxhr_dsp_load(mgr, dsp->index, &fw);
-       vfree(fw.data);
-       if (err < 0)
-               return err;
-       mgr->dsp_loaded |= 1 << dsp->index;
-       return 0;
-}
-
-int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
-{
-       int err;
-       struct snd_hwdep *hw;
-
-       /* only create hwdep interface for first cardX
-        * (see "index" module parameter)
-        */
-       err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw);
-       if (err < 0)
-               return err;
-
-       hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
-       hw->private_data = mgr;
-       hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
-       hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
-       hw->exclusive = 1;
-       /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */
-       hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0;
-       mgr->dsp_loaded = 0;
-       sprintf(hw->name, PCXHR_HWDEP_ID);
-
-       err = snd_card_register(mgr->chip[0]->card);
-       if (err < 0)
-               return err;
-       return 0;
-}
-
-#endif /* SND_PCXHR_FW_LOADER */
index 7d291542c5baba8803cbc3fddae2d33121e2f3d0..63c1c80415541c8a7207ded0c1cab82e8fb952a2 100644 (file)
@@ -1706,7 +1706,7 @@ static struct snd_pcm_ops snd_riptide_capture_ops = {
        .pointer = snd_riptide_pointer,
 };
 
-static int __devinit
+static int
 snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
@@ -1857,7 +1857,7 @@ static int snd_riptide_dev_free(struct snd_device *device)
        return snd_riptide_free(chip);
 }
 
-static int __devinit
+static int
 snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
                   struct snd_riptide **rchip)
 {
@@ -1993,7 +1993,7 @@ snd_riptide_proc_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "\n");
 }
 
-static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
+static void snd_riptide_proc_init(struct snd_riptide *chip)
 {
        struct snd_info_entry *entry;
 
@@ -2001,7 +2001,7 @@ static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
                snd_info_set_text_ops(entry, chip, snd_riptide_proc_read);
 }
 
-static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
+static int snd_riptide_mixer(struct snd_riptide *chip)
 {
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
@@ -2027,7 +2027,7 @@ static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
 
 #ifdef SUPPORT_JOYSTICK
 
-static int __devinit
+static int
 snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
 {
        static int dev;
@@ -2060,7 +2060,7 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
        return 0;
 }
 
-static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
+static void snd_riptide_joystick_remove(struct pci_dev *pci)
 {
        struct gameport *gameport = pci_get_drvdata(pci);
        if (gameport) {
@@ -2071,7 +2071,7 @@ static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
 }
 #endif
 
-static int __devinit
+static int
 snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -2176,7 +2176,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        return err;
 }
 
-static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
+static void snd_card_riptide_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2186,7 +2186,7 @@ static struct pci_driver driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_riptide_ids,
        .probe = snd_card_riptide_probe,
-       .remove = __devexit_p(snd_card_riptide_remove),
+       .remove = snd_card_riptide_remove,
        .driver = {
                .pm = RIPTIDE_PM_OPS,
        },
@@ -2197,7 +2197,7 @@ static struct pci_driver joystick_driver = {
        .name = KBUILD_MODNAME "-joystick",
        .id_table = snd_riptide_joystick_ids,
        .probe = snd_riptide_joystick_probe,
-       .remove = __devexit_p(snd_riptide_joystick_remove),
+       .remove = snd_riptide_joystick_remove,
 };
 #endif
 
index 46b3629dda22d3d9fbd33f281b2dc13c79815f56..2450663e1a189c84d4def85589a5c220d99133af 100644 (file)
@@ -1332,7 +1332,7 @@ snd_rme32_free_adat_pcm(struct snd_pcm *pcm)
        rme32->adat_pcm = NULL;
 }
 
-static int __devinit snd_rme32_create(struct rme32 * rme32)
+static int snd_rme32_create(struct rme32 *rme32)
 {
        struct pci_dev *pci = rme32->pci;
        int err;
@@ -1554,7 +1554,7 @@ snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe
        }
 }
 
-static void __devinit snd_rme32_proc_init(struct rme32 * rme32)
+static void snd_rme32_proc_init(struct rme32 *rme32)
 {
        struct snd_info_entry *entry;
 
@@ -1922,7 +1922,7 @@ static void snd_rme32_card_free(struct snd_card *card)
        snd_rme32_free(card->private_data);
 }
 
-static int __devinit
+static int
 snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 {
        static int dev;
@@ -1978,7 +1978,7 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        return 0;
 }
 
-static void __devexit snd_rme32_remove(struct pci_dev *pci)
+static void snd_rme32_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1988,7 +1988,7 @@ static struct pci_driver rme32_driver = {
        .name =         KBUILD_MODNAME,
        .id_table =     snd_rme32_ids,
        .probe =        snd_rme32_probe,
-       .remove =       __devexit_p(snd_rme32_remove),
+       .remove =       snd_rme32_remove,
 };
 
 module_pci_driver(rme32_driver);
index 9b98dc406988386b62a6c9f07e31181f98d2bb29..5fb88ac82aa93f6f4f0d0021ba0775ebf952e1ac 100644 (file)
@@ -270,8 +270,7 @@ snd_rme96_playback_pointer(struct snd_pcm_substream *substream);
 static snd_pcm_uframes_t
 snd_rme96_capture_pointer(struct snd_pcm_substream *substream);
 
-static void __devinit 
-snd_rme96_proc_init(struct rme96 *rme96);
+static void snd_rme96_proc_init(struct rme96 *rme96);
 
 static int
 snd_rme96_create_switches(struct snd_card *card,
@@ -1538,7 +1537,7 @@ snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
        rme96->adat_pcm = NULL;
 }
 
-static int __devinit
+static int
 snd_rme96_create(struct rme96 *rme96)
 {
        struct pci_dev *pci = rme96->pci;
@@ -1786,8 +1785,7 @@ snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer
        }
 }
 
-static void __devinit 
-snd_rme96_proc_init(struct rme96 *rme96)
+static void snd_rme96_proc_init(struct rme96 *rme96)
 {
        struct snd_info_entry *entry;
 
@@ -2326,7 +2324,7 @@ static void snd_rme96_card_free(struct snd_card *card)
        snd_rme96_free(card->private_data);
 }
 
-static int __devinit
+static int
 snd_rme96_probe(struct pci_dev *pci,
                const struct pci_device_id *pci_id)
 {
@@ -2389,7 +2387,7 @@ snd_rme96_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_rme96_remove(struct pci_dev *pci)
+static void snd_rme96_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2399,7 +2397,7 @@ static struct pci_driver rme96_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_rme96_ids,
        .probe = snd_rme96_probe,
-       .remove = __devexit_p(snd_rme96_remove),
+       .remove = snd_rme96_remove,
 };
 
 module_pci_driver(rme96_driver);
index 0d6930c4f4b7bc4c2d4cecd0a074cbd30b3305bb..4fae81f21efbd25a1645bf25a5b296580b4b8d86 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 #include <linux/math64.h>
+#include <linux/vmalloc.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -59,13 +60,11 @@ MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
                "{RME HDSP-9652},"
                "{RME HDSP-9632}}");
-#ifdef HDSP_FW_LOADER
 MODULE_FIRMWARE("rpm_firmware.bin");
 MODULE_FIRMWARE("multiface_firmware.bin");
 MODULE_FIRMWARE("multiface_firmware_rev11.bin");
 MODULE_FIRMWARE("digiface_firmware.bin");
 MODULE_FIRMWARE("digiface_firmware_rev11.bin");
-#endif
 
 #define HDSP_MAX_CHANNELS        26
 #define HDSP_MAX_DS_CHANNELS     14
@@ -423,12 +422,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
 #define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
 #define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
 
-/* use hotplug firmware loader? */
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(HDSP_USE_HWDEP_LOADER)
-#define HDSP_FW_LOADER
-#endif
-#endif
+#define HDSP_FIRMWARE_SIZE     (24413 * 4)
 
 struct hdsp_9632_meters {
     u32 input_peak[16];
@@ -475,7 +469,8 @@ struct hdsp {
        enum HDSP_IO_Type     io_type;               /* ditto, but for code use */
         unsigned short        firmware_rev;
        unsigned short        state;                 /* stores state bits */
-       u32                   firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
+       const struct firmware *firmware;
+       u32                  *fw_uploaded;
        size_t                period_bytes;          /* guess what this is */
        unsigned char         max_channels;
        unsigned char         qs_in_channels;        /* quad speed mode for H9632 */
@@ -712,6 +707,17 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
 
        int i;
        unsigned long flags;
+       const u32 *cache;
+
+       if (hdsp->fw_uploaded)
+               cache = hdsp->fw_uploaded;
+       else {
+               if (!hdsp->firmware)
+                       return -ENODEV;
+               cache = (u32 *)hdsp->firmware->data;
+               if (!cache)
+                       return -ENODEV;
+       }
 
        if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
 
@@ -727,8 +733,8 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
 
                hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
 
-               for (i = 0; i < 24413; ++i) {
-                       hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
+               for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) {
+                       hdsp_write(hdsp, HDSP_fifoData, cache[i]);
                        if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
                                snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
                                return -EIO;
@@ -798,9 +804,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp)
 }
 
 
-#ifdef HDSP_FW_LOADER
 static int hdsp_request_fw_loader(struct hdsp *hdsp);
-#endif
 
 static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
 {
@@ -813,10 +817,8 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
                snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
                /* try to load firmware */
                if (! (hdsp->state & HDSP_FirmwareCached)) {
-#ifdef HDSP_FW_LOADER
                        if (! hdsp_request_fw_loader(hdsp))
                                return 0;
-#endif
                        snd_printk(KERN_ERR
                                   "Hammerfall-DSP: No firmware loaded nor "
                                   "cached, please upload firmware.\n");
@@ -3673,9 +3675,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
                        }
                } else {
                        int err = -EINVAL;
-#ifdef HDSP_FW_LOADER
                        err = hdsp_request_fw_loader(hdsp);
-#endif
                        if (err < 0) {
                                snd_iprintf(buffer,
                                            "No firmware loaded nor cached, "
@@ -4020,7 +4020,7 @@ static void snd_hdsp_free_buffers(struct hdsp *hdsp)
        snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
 }
 
-static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
+static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
 {
        unsigned long pb_bus, cb_bus;
 
@@ -5100,8 +5100,18 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
                if (hdsp_check_for_iobox (hdsp))
                        return -EIO;
 
-               if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
+               if (!hdsp->fw_uploaded) {
+                       hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE);
+                       if (!hdsp->fw_uploaded)
+                               return -ENOMEM;
+               }
+
+               if (copy_from_user(hdsp->fw_uploaded, firmware_data,
+                                  HDSP_FIRMWARE_SIZE)) {
+                       vfree(hdsp->fw_uploaded);
+                       hdsp->fw_uploaded = NULL;
                        return -EFAULT;
+               }
 
                hdsp->state |= HDSP_FirmwareCached;
 
@@ -5330,7 +5340,6 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp
        return 0;
 }
 
-#ifdef HDSP_FW_LOADER
 /* load firmware via hotplug fw loader */
 static int hdsp_request_fw_loader(struct hdsp *hdsp)
 {
@@ -5373,16 +5382,13 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp)
                snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
                return -ENOENT;
        }
-       if (fw->size < sizeof(hdsp->firmware_cache)) {
+       if (fw->size < HDSP_FIRMWARE_SIZE) {
                snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
-                          (int)fw->size, (int)sizeof(hdsp->firmware_cache));
-               release_firmware(fw);
+                          (int)fw->size, HDSP_FIRMWARE_SIZE);
                return -EINVAL;
        }
 
-       memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
-
-       release_firmware(fw);
+       hdsp->firmware = fw;
 
        hdsp->state |= HDSP_FirmwareCached;
 
@@ -5406,10 +5412,9 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp)
        }
        return 0;
 }
-#endif
 
-static int __devinit snd_hdsp_create(struct snd_card *card,
-                                    struct hdsp *hdsp)
+static int snd_hdsp_create(struct snd_card *card,
+                          struct hdsp *hdsp)
 {
        struct pci_dev *pci = hdsp->pci;
        int err;
@@ -5504,7 +5509,6 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
                        return err;
 
                if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-#ifdef HDSP_FW_LOADER
                        if ((err = hdsp_request_fw_loader(hdsp)) < 0)
                                /* we don't fail as this can happen
                                   if userspace is not ready for
@@ -5514,7 +5518,6 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
                        else
                                /* init is complete, we return */
                                return 0;
-#endif
                        /* we defer initialization */
                        snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
                        if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
@@ -5568,6 +5571,10 @@ static int snd_hdsp_free(struct hdsp *hdsp)
 
        snd_hdsp_free_buffers(hdsp);
 
+       if (hdsp->firmware)
+               release_firmware(hdsp->firmware);
+       vfree(hdsp->fw_uploaded);
+
        if (hdsp->iobase)
                iounmap(hdsp->iobase);
 
@@ -5586,8 +5593,8 @@ static void snd_hdsp_card_free(struct snd_card *card)
                snd_hdsp_free(hdsp);
 }
 
-static int __devinit snd_hdsp_probe(struct pci_dev *pci,
-                                   const struct pci_device_id *pci_id)
+static int snd_hdsp_probe(struct pci_dev *pci,
+                         const struct pci_device_id *pci_id)
 {
        static int dev;
        struct hdsp *hdsp;
@@ -5630,7 +5637,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_hdsp_remove(struct pci_dev *pci)
+static void snd_hdsp_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -5640,7 +5647,7 @@ static struct pci_driver hdsp_driver = {
        .name =     KBUILD_MODNAME,
        .id_table = snd_hdsp_ids,
        .probe =    snd_hdsp_probe,
-       .remove = __devexit_p(snd_hdsp_remove),
+       .remove = snd_hdsp_remove,
 };
 
 module_pci_driver(hdsp_driver);
index 748e36c66603a7f9928f70a6f13ea8e64b875f76..6e02e064d7b43df1159554899f1007a9f223bc7b 100644 (file)
@@ -962,10 +962,10 @@ static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
 MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
 
 /* prototypes */
-static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
-                                                  struct hdspm * hdspm);
-static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
-                                         struct hdspm * hdspm);
+static int snd_hdspm_create_alsa_devices(struct snd_card *card,
+                                        struct hdspm *hdspm);
+static int snd_hdspm_create_pcm(struct snd_card *card,
+                               struct hdspm *hdspm);
 
 static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
@@ -1845,8 +1845,8 @@ static struct snd_rawmidi_ops snd_hdspm_midi_input =
        .trigger =      snd_hdspm_midi_input_trigger,
 };
 
-static int __devinit snd_hdspm_create_midi (struct snd_card *card,
-                                           struct hdspm *hdspm, int id)
+static int snd_hdspm_create_midi(struct snd_card *card,
+                                struct hdspm *hdspm, int id)
 {
        int err;
        char buf[32];
@@ -2887,330 +2887,50 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-
-#define HDSPM_LINE_OUT(xname, xindex) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_line_out, \
-       .get = snd_hdspm_get_line_out, \
-       .put = snd_hdspm_put_line_out \
-}
-
-static int hdspm_line_out(struct hdspm * hdspm)
-{
-       return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
-}
-
-
-static int hdspm_set_line_output(struct hdspm * hdspm, int out)
-{
-       if (out)
-               hdspm->control_register |= HDSPM_LineOut;
-       else
-               hdspm->control_register &= ~HDSPM_LineOut;
-       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-       return 0;
-}
-
-#define snd_hdspm_info_line_out                snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
-       spin_lock_irq(&hdspm->lock);
-       ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
-       spin_unlock_irq(&hdspm->lock);
-       return 0;
-}
-
-static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-       int change;
-       unsigned int val;
-
-       if (!snd_hdspm_use_is_exclusive(hdspm))
-               return -EBUSY;
-       val = ucontrol->value.integer.value[0] & 1;
-       spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_line_out(hdspm);
-       hdspm_set_line_output(hdspm, val);
-       spin_unlock_irq(&hdspm->lock);
-       return change;
-}
-
-
-#define HDSPM_TX_64(xname, xindex) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_tx_64, \
-       .get = snd_hdspm_get_tx_64, \
-       .put = snd_hdspm_put_tx_64 \
-}
-
-static int hdspm_tx_64(struct hdspm * hdspm)
-{
-       return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
-}
-
-static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
-{
-       if (out)
-               hdspm->control_register |= HDSPM_TX_64ch;
-       else
-               hdspm->control_register &= ~HDSPM_TX_64ch;
-       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-       return 0;
-}
-
-#define snd_hdspm_info_tx_64           snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
-       spin_lock_irq(&hdspm->lock);
-       ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
-       spin_unlock_irq(&hdspm->lock);
-       return 0;
-}
-
-static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-       int change;
-       unsigned int val;
-
-       if (!snd_hdspm_use_is_exclusive(hdspm))
-               return -EBUSY;
-       val = ucontrol->value.integer.value[0] & 1;
-       spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_tx_64(hdspm);
-       hdspm_set_tx_64(hdspm, val);
-       spin_unlock_irq(&hdspm->lock);
-       return change;
-}
-
-
-#define HDSPM_C_TMS(xname, xindex) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_c_tms, \
-       .get = snd_hdspm_get_c_tms, \
-       .put = snd_hdspm_put_c_tms \
-}
-
-static int hdspm_c_tms(struct hdspm * hdspm)
-{
-       return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
-}
-
-static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
-{
-       if (out)
-               hdspm->control_register |= HDSPM_clr_tms;
-       else
-               hdspm->control_register &= ~HDSPM_clr_tms;
-       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-       return 0;
-}
-
-#define snd_hdspm_info_c_tms           snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
-       spin_lock_irq(&hdspm->lock);
-       ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
-       spin_unlock_irq(&hdspm->lock);
-       return 0;
-}
-
-static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-       int change;
-       unsigned int val;
-
-       if (!snd_hdspm_use_is_exclusive(hdspm))
-               return -EBUSY;
-       val = ucontrol->value.integer.value[0] & 1;
-       spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_c_tms(hdspm);
-       hdspm_set_c_tms(hdspm, val);
-       spin_unlock_irq(&hdspm->lock);
-       return change;
-}
-
-
-#define HDSPM_SAFE_MODE(xname, xindex) \
+#define HDSPM_TOGGLE_SETTING(xname, xindex) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
        .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_safe_mode, \
-       .get = snd_hdspm_get_safe_mode, \
-       .put = snd_hdspm_put_safe_mode \
+       .private_value = xindex, \
+       .info = snd_hdspm_info_toggle_setting, \
+       .get = snd_hdspm_get_toggle_setting, \
+       .put = snd_hdspm_put_toggle_setting \
 }
 
-static int hdspm_safe_mode(struct hdspm * hdspm)
+static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
 {
-       return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
+       return (hdspm->control_register & regmask) ? 1 : 0;
 }
 
-static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
+static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
 {
        if (out)
-               hdspm->control_register |= HDSPM_AutoInp;
-       else
-               hdspm->control_register &= ~HDSPM_AutoInp;
-       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-       return 0;
-}
-
-#define snd_hdspm_info_safe_mode       snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
-                                  struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
-       spin_lock_irq(&hdspm->lock);
-       ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
-       spin_unlock_irq(&hdspm->lock);
-       return 0;
-}
-
-static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
-                                  struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-       int change;
-       unsigned int val;
-
-       if (!snd_hdspm_use_is_exclusive(hdspm))
-               return -EBUSY;
-       val = ucontrol->value.integer.value[0] & 1;
-       spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_safe_mode(hdspm);
-       hdspm_set_safe_mode(hdspm, val);
-       spin_unlock_irq(&hdspm->lock);
-       return change;
-}
-
-
-#define HDSPM_EMPHASIS(xname, xindex) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_emphasis, \
-       .get = snd_hdspm_get_emphasis, \
-       .put = snd_hdspm_put_emphasis \
-}
-
-static int hdspm_emphasis(struct hdspm * hdspm)
-{
-       return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
-}
-
-static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
-{
-       if (emp)
-               hdspm->control_register |= HDSPM_Emphasis;
+               hdspm->control_register |= regmask;
        else
-               hdspm->control_register &= ~HDSPM_Emphasis;
+               hdspm->control_register &= ~regmask;
        hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 
        return 0;
 }
 
-#define snd_hdspm_info_emphasis                snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+#define snd_hdspm_info_toggle_setting          snd_ctl_boolean_mono_info
 
-       spin_lock_irq(&hdspm->lock);
-       ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
-       spin_unlock_irq(&hdspm->lock);
-       return 0;
-}
-
-static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-       int change;
-       unsigned int val;
-
-       if (!snd_hdspm_use_is_exclusive(hdspm))
-               return -EBUSY;
-       val = ucontrol->value.integer.value[0] & 1;
-       spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_emphasis(hdspm);
-       hdspm_set_emphasis(hdspm, val);
-       spin_unlock_irq(&hdspm->lock);
-       return change;
-}
-
-
-#define HDSPM_DOLBY(xname, xindex) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_dolby, \
-       .get = snd_hdspm_get_dolby, \
-       .put = snd_hdspm_put_dolby \
-}
-
-static int hdspm_dolby(struct hdspm * hdspm)
-{
-       return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
-}
-
-static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
-{
-       if (dol)
-               hdspm->control_register |= HDSPM_Dolby;
-       else
-               hdspm->control_register &= ~HDSPM_Dolby;
-       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-       return 0;
-}
-
-#define snd_hdspm_info_dolby           snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
+static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+       u32 regmask = kcontrol->private_value;
 
        spin_lock_irq(&hdspm->lock);
-       ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
+       ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
        spin_unlock_irq(&hdspm->lock);
        return 0;
 }
 
-static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
+static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+       u32 regmask = kcontrol->private_value;
        int change;
        unsigned int val;
 
@@ -3218,64 +2938,8 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
                return -EBUSY;
        val = ucontrol->value.integer.value[0] & 1;
        spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_dolby(hdspm);
-       hdspm_set_dolby(hdspm, val);
-       spin_unlock_irq(&hdspm->lock);
-       return change;
-}
-
-
-#define HDSPM_PROFESSIONAL(xname, xindex) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-       .name = xname, \
-       .index = xindex, \
-       .info = snd_hdspm_info_professional, \
-       .get = snd_hdspm_get_professional, \
-       .put = snd_hdspm_put_professional \
-}
-
-static int hdspm_professional(struct hdspm * hdspm)
-{
-       return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
-}
-
-static int hdspm_set_professional(struct hdspm * hdspm, int dol)
-{
-       if (dol)
-               hdspm->control_register |= HDSPM_Professional;
-       else
-               hdspm->control_register &= ~HDSPM_Professional;
-       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-       return 0;
-}
-
-#define snd_hdspm_info_professional    snd_ctl_boolean_mono_info
-
-static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-
-       spin_lock_irq(&hdspm->lock);
-       ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
-       spin_unlock_irq(&hdspm->lock);
-       return 0;
-}
-
-static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-       int change;
-       unsigned int val;
-
-       if (!snd_hdspm_use_is_exclusive(hdspm))
-               return -EBUSY;
-       val = ucontrol->value.integer.value[0] & 1;
-       spin_lock_irq(&hdspm->lock);
-       change = (int) val != hdspm_professional(hdspm);
-       hdspm_set_professional(hdspm, val);
+       change = (int) val != hdspm_toggle_setting(hdspm, regmask);
+       hdspm_set_toggle_setting(hdspm, regmask, val);
        spin_unlock_irq(&hdspm->lock);
        return change;
 }
@@ -4476,10 +4140,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
        HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
        HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
-       HDSPM_LINE_OUT("Line Out", 0),
-       HDSPM_TX_64("TX 64 channels mode", 0),
-       HDSPM_C_TMS("Clear Track Marker", 0),
-       HDSPM_SAFE_MODE("Safe Mode", 0),
+       HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
+       HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
+       HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
+       HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
        HDSPM_INPUT_SELECT("Input Select", 0),
        HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
@@ -4492,9 +4156,9 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
        HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
        HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
        HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
-       HDSPM_TX_64("TX 64 channels mode", 0),
-       HDSPM_C_TMS("Clear Track Marker", 0),
-       HDSPM_SAFE_MODE("Safe Mode", 0),
+       HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
+       HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
+       HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
        HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
 
@@ -4587,11 +4251,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
        HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
        HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
        HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
-       HDSPM_LINE_OUT("Line Out", 0),
-       HDSPM_EMPHASIS("Emphasis", 0),
-       HDSPM_DOLBY("Non Audio", 0),
-       HDSPM_PROFESSIONAL("Professional", 0),
-       HDSPM_C_TMS("Clear Track Marker", 0),
+       HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
+       HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
+       HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
+       HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
+       HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
        HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
        HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
 };
@@ -5233,7 +4897,7 @@ static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
 }
 
 
-static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
+static void snd_hdspm_proc_init(struct hdspm *hdspm)
 {
        struct snd_info_entry *entry;
 
@@ -6266,7 +5930,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
                info.system_clock_mode = hdspm_system_clock_mode(hdspm);
                info.clock_source = hdspm_clock_source(hdspm);
                info.autosync_ref = hdspm_autosync_ref(hdspm);
-               info.line_out = hdspm_line_out(hdspm);
+               info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
                info.passthru = 0;
                spin_unlock_irq(&hdspm->lock);
                if (copy_to_user(argp, &info, sizeof(info)))
@@ -6369,8 +6033,8 @@ static struct snd_pcm_ops snd_hdspm_capture_ops = {
        .page = snd_pcm_sgbuf_ops_page,
 };
 
-static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
-                                           struct hdspm * hdspm)
+static int snd_hdspm_create_hwdep(struct snd_card *card,
+                                 struct hdspm *hdspm)
 {
        struct snd_hwdep *hw;
        int err;
@@ -6395,7 +6059,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
 /*------------------------------------------------------------
    memory interface
  ------------------------------------------------------------*/
-static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
+static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
 {
        int err;
        struct snd_pcm *pcm;
@@ -6436,8 +6100,8 @@ static void hdspm_set_sgbuf(struct hdspm *hdspm,
 
 
 /* ------------- ALSA Devices ---------------------------- */
-static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
-                                         struct hdspm *hdspm)
+static int snd_hdspm_create_pcm(struct snd_card *card,
+                               struct hdspm *hdspm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -6472,8 +6136,8 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
                snd_hdspm_flush_midi_input(hdspm, i);
 }
 
-static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
-                                                  struct hdspm * hdspm)
+static int snd_hdspm_create_alsa_devices(struct snd_card *card,
+                                        struct hdspm *hdspm)
 {
        int err, i;
 
@@ -6531,8 +6195,9 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_hdspm_create(struct snd_card *card,
-               struct hdspm *hdspm) {
+static int snd_hdspm_create(struct snd_card *card,
+                           struct hdspm *hdspm)
+{
 
        struct pci_dev *pci = hdspm->pci;
        int err;
@@ -6905,8 +6570,8 @@ static void snd_hdspm_card_free(struct snd_card *card)
 }
 
 
-static int __devinit snd_hdspm_probe(struct pci_dev *pci,
-                                    const struct pci_device_id *pci_id)
+static int snd_hdspm_probe(struct pci_dev *pci,
+                          const struct pci_device_id *pci_id)
 {
        static int dev;
        struct hdspm *hdspm;
@@ -6964,7 +6629,7 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_hdspm_remove(struct pci_dev *pci)
+static void snd_hdspm_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -6974,7 +6639,7 @@ static struct pci_driver hdspm_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_hdspm_ids,
        .probe = snd_hdspm_probe,
-       .remove = __devexit_p(snd_hdspm_remove),
+       .remove = snd_hdspm_remove,
 };
 
 module_pci_driver(hdspm_driver);
index a15fc100ab0c320808229729d00c4a55eb1d7da4..773a67fff4cdeb64469170912e82034919e5a841 100644 (file)
@@ -1757,7 +1757,7 @@ snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buff
        snd_iprintf(buffer, "\n");
 }
 
-static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
+static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
 {
        struct snd_info_entry *entry;
 
@@ -1788,7 +1788,7 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652)
        return 0;
 }
 
-static int __devinit snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
+static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
 {
        unsigned long pb_bus, cb_bus;
 
@@ -2414,8 +2414,8 @@ static struct snd_pcm_ops snd_rme9652_capture_ops = {
        .copy =         snd_rme9652_capture_copy,
 };
 
-static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
-                                        struct snd_rme9652 *rme9652)
+static int snd_rme9652_create_pcm(struct snd_card *card,
+                                 struct snd_rme9652 *rme9652)
 {
        struct snd_pcm *pcm;
        int err;
@@ -2438,9 +2438,9 @@ static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
        return 0;
 }
 
-static int __devinit snd_rme9652_create(struct snd_card *card,
-                                    struct snd_rme9652 *rme9652,
-                                    int precise_ptr)
+static int snd_rme9652_create(struct snd_card *card,
+                             struct snd_rme9652 *rme9652,
+                             int precise_ptr)
 {
        struct pci_dev *pci = rme9652->pci;
        int err;
@@ -2578,8 +2578,8 @@ static void snd_rme9652_card_free(struct snd_card *card)
                snd_rme9652_free(rme9652);
 }
 
-static int __devinit snd_rme9652_probe(struct pci_dev *pci,
-                                      const struct pci_device_id *pci_id)
+static int snd_rme9652_probe(struct pci_dev *pci,
+                            const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_rme9652 *rme9652;
@@ -2625,7 +2625,7 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_rme9652_remove(struct pci_dev *pci)
+static void snd_rme9652_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2635,7 +2635,7 @@ static struct pci_driver rme9652_driver = {
        .name     = KBUILD_MODNAME,
        .id_table = snd_rme9652_ids,
        .probe    = snd_rme9652_probe,
-       .remove   = __devexit_p(snd_rme9652_remove),
+       .remove   = snd_rme9652_remove,
 };
 
 module_pci_driver(rme9652_driver);
index 51e43407ebc539f657b6d7da9ab3647917f2e8af..d59abe1682c58f9d394340d48c38e1860f906e89 100644 (file)
@@ -894,7 +894,7 @@ static struct snd_pcm_ops sis_capture_ops = {
        .pointer = sis_pcm_pointer,
 };
 
-static int __devinit sis_pcm_create(struct sis7019 *sis)
+static int sis_pcm_create(struct sis7019 *sis)
 {
        struct snd_pcm *pcm;
        int rc;
@@ -1013,7 +1013,7 @@ static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
                                        (reg << 8) | cmd[ac97->num]);
 }
 
-static int __devinit sis_mixer_create(struct sis7019 *sis)
+static int sis_mixer_create(struct sis7019 *sis)
 {
        struct snd_ac97_bus *bus;
        struct snd_ac97_template ac97;
@@ -1171,7 +1171,7 @@ static int sis_chip_init(struct sis7019 *sis)
        outl(SIS_DMA_CSR_PCI_SETTINGS, io + SIS_DMA_CSR);
 
        /* Reset the synchronization groups for all of the channels
-        * to be asyncronous. If we start doing SPDIF or 5.1 sound, etc.
+        * to be asynchronous. If we start doing SPDIF or 5.1 sound, etc.
         * we'll need to change how we handle these. Until then, we just
         * assign sub-mixer 0 to all playback channels, and avoid any
         * attenuation on the audio.
@@ -1326,8 +1326,8 @@ static int sis_alloc_suspend(struct sis7019 *sis)
        return 0;
 }
 
-static int __devinit sis_chip_create(struct snd_card *card,
-                                       struct pci_dev *pci)
+static int sis_chip_create(struct snd_card *card,
+                          struct pci_dev *pci)
 {
        struct sis7019 *sis = card->private_data;
        struct voice *voice;
@@ -1417,8 +1417,8 @@ error_out:
        return rc;
 }
 
-static int __devinit snd_sis7019_probe(struct pci_dev *pci,
-                                       const struct pci_device_id *pci_id)
+static int snd_sis7019_probe(struct pci_dev *pci,
+                            const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct sis7019 *sis;
@@ -1478,7 +1478,7 @@ error_out:
        return rc;
 }
 
-static void __devexit snd_sis7019_remove(struct pci_dev *pci)
+static void snd_sis7019_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1488,7 +1488,7 @@ static struct pci_driver sis7019_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_sis7019_ids,
        .probe = snd_sis7019_probe,
-       .remove = __devexit_p(snd_sis7019_remove),
+       .remove = snd_sis7019_remove,
        .driver = {
                .pm = SIS_PM_OPS,
        },
index baa9946bedf019cb098032be10ee5df4c233cc05..a2e7686e7ae3300f78240db2755fc23899ecec30 100644 (file)
@@ -877,7 +877,8 @@ static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
        .pointer =      snd_sonicvibes_capture_pointer,
 };
 
-static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm)
+static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device,
+                             struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1087,7 +1088,7 @@ static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_c
        return change;
 }
 
-static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_controls[] = {
 SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
 SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
 SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
@@ -1118,7 +1119,7 @@ static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
        sonic->master_volume = NULL;
 }
 
-static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic)
+static int snd_sonicvibes_mixer(struct sonicvibes *sonic)
 {
        struct snd_card *card;
        struct snd_kcontrol *kctl;
@@ -1175,7 +1176,7 @@ static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "MIDI to ext. Tx  : %s\n", tmp & 0x04 ? "on" : "off");
 }
 
-static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
+static void snd_sonicvibes_proc_init(struct sonicvibes *sonic)
 {
        struct snd_info_entry *entry;
 
@@ -1188,10 +1189,10 @@ static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
  */
 
 #ifdef SUPPORT_JOYSTICK
-static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =
+static struct snd_kcontrol_new snd_sonicvibes_game_control =
 SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
 
-static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
+static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
 {
        struct gameport *gp;
 
@@ -1246,11 +1247,11 @@ static int snd_sonicvibes_dev_free(struct snd_device *device)
        return snd_sonicvibes_free(sonic);
 }
 
-static int __devinit snd_sonicvibes_create(struct snd_card *card,
-                                       struct pci_dev *pci,
-                                       int reverb,
-                                       int mge,
-                                       struct sonicvibes ** rsonic)
+static int snd_sonicvibes_create(struct snd_card *card,
+                                struct pci_dev *pci,
+                                int reverb,
+                                int mge,
+                                struct sonicvibes **rsonic)
 {
        struct sonicvibes *sonic;
        unsigned int dmaa, dmac;
@@ -1401,7 +1402,7 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
  *  MIDI section
  */
 
-static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] = {
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
 SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
@@ -1422,8 +1423,8 @@ static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
        outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
 }
 
-static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
-                                        struct snd_rawmidi *rmidi)
+static int snd_sonicvibes_midi(struct sonicvibes *sonic,
+                              struct snd_rawmidi *rmidi)
 {
        struct snd_mpu401 * mpu = rmidi->private_data;
        struct snd_card *card = sonic->card;
@@ -1441,8 +1442,8 @@ static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
        return 0;
 }
 
-static int __devinit snd_sonic_probe(struct pci_dev *pci,
-                                    const struct pci_device_id *pci_id)
+static int snd_sonic_probe(struct pci_dev *pci,
+                          const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -1524,7 +1525,7 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_sonic_remove(struct pci_dev *pci)
+static void snd_sonic_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1534,7 +1535,7 @@ static struct pci_driver sonicvibes_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_sonic_ids,
        .probe = snd_sonic_probe,
-       .remove = __devexit_p(snd_sonic_remove),
+       .remove = snd_sonic_remove,
 };
 
 module_pci_driver(sonicvibes_driver);
index 8a6f1f76e8709508cb186a4957ad2776e2865392..1aefd6204a63f26347f856881b3522d00e37e169 100644 (file)
@@ -73,8 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_trident_ids) = {
 
 MODULE_DEVICE_TABLE(pci, snd_trident_ids);
 
-static int __devinit snd_trident_probe(struct pci_dev *pci,
-                                      const struct pci_device_id *pci_id)
+static int snd_trident_probe(struct pci_dev *pci,
+                            const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -166,7 +166,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_trident_remove(struct pci_dev *pci)
+static void snd_trident_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -176,7 +176,7 @@ static struct pci_driver trident_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_trident_ids,
        .probe = snd_trident_probe,
-       .remove = __devexit_p(snd_trident_remove),
+       .remove = snd_trident_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_trident_pm,
index 06b10d1a76e56c3593e09f704ba5efb3b6688577..fb0e1586a6f87cc25bbce39a64744e1fea468de5 100644 (file)
@@ -2171,8 +2171,8 @@ static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
   
   ---------------------------------------------------------------------------*/
 
-int __devinit snd_trident_pcm(struct snd_trident * trident,
-                             int device, struct snd_pcm ** rpcm)
+int snd_trident_pcm(struct snd_trident *trident,
+                   int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -2229,8 +2229,8 @@ int __devinit snd_trident_pcm(struct snd_trident * trident,
   
   ---------------------------------------------------------------------------*/
 
-int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
-                                      int device, struct snd_pcm ** rpcm)
+int snd_trident_foldback_pcm(struct snd_trident *trident,
+                            int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *foldback;
        int err;
@@ -2286,8 +2286,8 @@ int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
   
   ---------------------------------------------------------------------------*/
 
-int __devinit snd_trident_spdif_pcm(struct snd_trident * trident,
-                                   int device, struct snd_pcm ** rpcm)
+int snd_trident_spdif_pcm(struct snd_trident *trident,
+                         int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *spdif;
        int err;
@@ -2371,7 +2371,7 @@ static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
@@ -2434,7 +2434,7 @@ static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_default =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -2467,7 +2467,7 @@ static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_mask =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -2529,7 +2529,7 @@ static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_stream =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -2579,7 +2579,7 @@ static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_ac97_rear_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Rear Path",
@@ -2637,7 +2637,7 @@ static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_vol_music_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Music Playback Volume",
@@ -2648,7 +2648,7 @@ static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
        .tlv = { .p = db_scale_gvol },
 };
 
-static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_vol_wave_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Wave Playback Volume",
@@ -2715,7 +2715,7 @@ static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_vol_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "PCM Front Playback Volume",
@@ -2779,7 +2779,7 @@ static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_pan_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "PCM Pan Playback Control",
@@ -2836,7 +2836,7 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
 
-static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_rvol_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "PCM Reverb Playback Volume",
@@ -2892,7 +2892,7 @@ static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_cvol_control =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "PCM Chorus Playback Volume",
@@ -2972,7 +2972,7 @@ static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_tr
   
   ---------------------------------------------------------------------------*/
 
-static int __devinit snd_trident_mixer(struct snd_trident * trident, int pcm_spdif_device)
+static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)
 {
        struct snd_ac97_template _ac97;
        struct snd_card *card = trident->card;
@@ -3191,7 +3191,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
        }
 }
 
-int __devinit snd_trident_create_gameport(struct snd_trident *chip)
+int snd_trident_create_gameport(struct snd_trident *chip)
 {
        struct gameport *gp;
 
@@ -3225,7 +3225,7 @@ static inline void snd_trident_free_gameport(struct snd_trident *chip)
        }
 }
 #else
-int __devinit snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
+int snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
 static inline void snd_trident_free_gameport(struct snd_trident *chip) { }
 #endif /* CONFIG_GAMEPORT */
 
@@ -3329,7 +3329,7 @@ static void snd_trident_proc_read(struct snd_info_entry *entry,
        }
 }
 
-static void __devinit snd_trident_proc_init(struct snd_trident * trident)
+static void snd_trident_proc_init(struct snd_trident *trident)
 {
        struct snd_info_entry *entry;
        const char *s = "trident";
@@ -3358,7 +3358,7 @@ static int snd_trident_dev_free(struct snd_device *device)
   
   ---------------------------------------------------------------------------*/
 
-static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
+static int snd_trident_tlb_alloc(struct snd_trident *trident)
 {
        int i;
 
@@ -3539,7 +3539,7 @@ static int snd_trident_sis_init(struct snd_trident *trident)
   
   ---------------------------------------------------------------------------*/
 
-int __devinit snd_trident_create(struct snd_card *card,
+int snd_trident_create(struct snd_card *card,
                       struct pci_dev *pci,
                       int pcm_streams,
                       int pcm_spdif_device,
index f0b4efdb483c3ea627cb8a544b9a8b9c6ff2bc58..6442f611a07bfc0d907dcfb1dd1b75c8aff1d2e2 100644 (file)
@@ -1437,7 +1437,7 @@ static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset,
 /*
  * create pcm instances for VIA8233, 8233C and 8235 (not 8233A)
  */
-static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
+static int snd_via8233_pcm_new(struct via82xx *chip)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_chmap *chmap;
@@ -1505,7 +1505,7 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
 /*
  * create pcm instances for VIA8233A
  */
-static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
+static int snd_via8233a_pcm_new(struct via82xx *chip)
 {
        struct snd_pcm *pcm;
        struct snd_pcm_chmap *chmap;
@@ -1566,7 +1566,7 @@ static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
 /*
  * create a pcm instance for via686a/b
  */
-static int __devinit snd_via686_pcm_new(struct via82xx *chip)
+static int snd_via686_pcm_new(struct via82xx *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1643,7 +1643,7 @@ static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol,
        return val != oval;
 }
 
-static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_capture_source = {
        .name = "Input Source Select",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = snd_via8233_capture_source_info,
@@ -1683,7 +1683,7 @@ static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control = {
        .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = snd_via8233_dxs3_spdif_info,
@@ -1772,7 +1772,7 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1);
 
-static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control = {
        .name = "PCM Playback Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1783,7 +1783,7 @@ static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata =
        .tlv = { .p = db_scale_dxs }
 };
 
-static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_dxs_volume_control = {
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .device = 0,
        /* .subdevice set later */
@@ -1895,7 +1895,7 @@ static struct ac97_quirk ac97_quirks[] = {
        { } /* terminator */
 };
 
-static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
+static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
 {
        struct snd_ac97_template ac97;
        int err;
@@ -1930,7 +1930,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *qui
 
 #ifdef SUPPORT_JOYSTICK
 #define JOYSTICK_ADDR  0x200
-static int __devinit snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
+static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
 {
        struct gameport *gp;
        struct resource *r;
@@ -1990,7 +1990,7 @@ static inline void snd_via686_free_gameport(struct via82xx *chip) { }
  *
  */
 
-static int __devinit snd_via8233_init_misc(struct via82xx *chip)
+static int snd_via8233_init_misc(struct via82xx *chip)
 {
        int i, err, caps;
        unsigned char val;
@@ -2047,7 +2047,7 @@ static int __devinit snd_via8233_init_misc(struct via82xx *chip)
        return 0;
 }
 
-static int __devinit snd_via686_init_misc(struct via82xx *chip)
+static int snd_via686_init_misc(struct via82xx *chip)
 {
        unsigned char legacy, legacy_cfg;
        int rev_h = 0;
@@ -2137,7 +2137,7 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry,
        }
 }
 
-static void __devinit snd_via82xx_proc_init(struct via82xx *chip)
+static void snd_via82xx_proc_init(struct via82xx *chip)
 {
        struct snd_info_entry *entry;
 
@@ -2370,12 +2370,12 @@ static int snd_via82xx_dev_free(struct snd_device *device)
        return snd_via82xx_free(chip);
 }
 
-static int __devinit snd_via82xx_create(struct snd_card *card,
-                                       struct pci_dev *pci,
-                                       int chip_type,
-                                       int revision,
-                                       unsigned int ac97_clock,
-                                       struct via82xx ** r_via)
+static int snd_via82xx_create(struct snd_card *card,
+                             struct pci_dev *pci,
+                             int chip_type,
+                             int revision,
+                             unsigned int ac97_clock,
+                             struct via82xx **r_via)
 {
        struct via82xx *chip;
        int err;
@@ -2452,7 +2452,7 @@ struct via823x_info {
        char *name;
        int type;
 };
-static struct via823x_info via823x_cards[] __devinitdata = {
+static struct via823x_info via823x_cards[] = {
        { VIA_REV_PRE_8233, "VIA 8233-Pre", TYPE_VIA8233 },
        { VIA_REV_8233C, "VIA 8233C", TYPE_VIA8233 },
        { VIA_REV_8233, "VIA 8233", TYPE_VIA8233 },
@@ -2466,7 +2466,7 @@ static struct via823x_info via823x_cards[] __devinitdata = {
  * auto detection of DXS channel supports.
  */
 
-static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
+static struct snd_pci_quirk dxs_whitelist[] = {
        SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE),
        SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
        SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
@@ -2510,7 +2510,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
        { } /* terminator */
 };
 
-static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
+static int check_dxs_list(struct pci_dev *pci, int revision)
 {
        const struct snd_pci_quirk *w;
 
@@ -2535,8 +2535,8 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
        return VIA_DXS_48K;
 };
 
-static int __devinit snd_via82xx_probe(struct pci_dev *pci,
-                                      const struct pci_device_id *pci_id)
+static int snd_via82xx_probe(struct pci_dev *pci,
+                            const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct via82xx *chip;
@@ -2643,7 +2643,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_via82xx_remove(struct pci_dev *pci)
+static void snd_via82xx_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -2653,7 +2653,7 @@ static struct pci_driver via82xx_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_via82xx_ids,
        .probe = snd_via82xx_probe,
-       .remove = __devexit_p(snd_via82xx_remove),
+       .remove = snd_via82xx_remove,
        .driver = {
                .pm = SND_VIA82XX_PM_OPS,
        },
index 8e0efc416f22f74bd68ba1f1fa89565073ee2bb0..4f5fd80b7e5688ef008691f908e4b781b5d186dd 100644 (file)
@@ -836,7 +836,7 @@ static void init_viadev(struct via82xx_modem *chip, int idx, unsigned int reg_of
 /*
  * create a pcm instance for via686a/b
  */
-static int __devinit snd_via686_pcm_new(struct via82xx_modem *chip)
+static int snd_via686_pcm_new(struct via82xx_modem *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -885,7 +885,7 @@ static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
 }
 
 
-static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip)
+static int snd_via82xx_mixer_new(struct via82xx_modem *chip)
 {
        struct snd_ac97_template ac97;
        int err;
@@ -928,7 +928,7 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_
        }
 }
 
-static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip)
+static void snd_via82xx_proc_init(struct via82xx_modem *chip)
 {
        struct snd_info_entry *entry;
 
@@ -1103,12 +1103,12 @@ static int snd_via82xx_dev_free(struct snd_device *device)
        return snd_via82xx_free(chip);
 }
 
-static int __devinit snd_via82xx_create(struct snd_card *card,
-                                       struct pci_dev *pci,
-                                       int chip_type,
-                                       int revision,
-                                       unsigned int ac97_clock,
-                                       struct via82xx_modem ** r_via)
+static int snd_via82xx_create(struct snd_card *card,
+                             struct pci_dev *pci,
+                             int chip_type,
+                             int revision,
+                             unsigned int ac97_clock,
+                             struct via82xx_modem **r_via)
 {
        struct via82xx_modem *chip;
        int err;
@@ -1168,8 +1168,8 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
 }
 
 
-static int __devinit snd_via82xx_probe(struct pci_dev *pci,
-                                      const struct pci_device_id *pci_id)
+static int snd_via82xx_probe(struct pci_dev *pci,
+                            const struct pci_device_id *pci_id)
 {
        struct snd_card *card;
        struct via82xx_modem *chip;
@@ -1224,7 +1224,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
        return err;
 }
 
-static void __devexit snd_via82xx_remove(struct pci_dev *pci)
+static void snd_via82xx_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -1234,7 +1234,7 @@ static struct pci_driver via82xx_modem_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_via82xx_modem_ids,
        .probe = snd_via82xx_probe,
-       .remove = __devexit_p(snd_via82xx_remove),
+       .remove = snd_via82xx_remove,
        .driver = {
                .pm = SND_VIA82XX_PM_OPS,
        },
index fdfbaf8572336ddd31648a127d668701d60b0a28..e2f1ab37e1548661dae8f8cadce87764db7d52d6 100644 (file)
@@ -134,9 +134,9 @@ static int snd_vx222_dev_free(struct snd_device *device)
 }
 
 
-static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
-                                     struct snd_vx_hardware *hw,
-                                     struct snd_vx222 **rchip)
+static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
+                           struct snd_vx_hardware *hw,
+                           struct snd_vx222 **rchip)
 {
        struct vx_core *chip;
        struct snd_vx222 *vx;
@@ -188,8 +188,8 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci
 }
 
 
-static int __devinit snd_vx222_probe(struct pci_dev *pci,
-                                    const struct pci_device_id *pci_id)
+static int snd_vx222_probe(struct pci_dev *pci,
+                          const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -251,7 +251,7 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_vx222_remove(struct pci_dev *pci)
+static void snd_vx222_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -300,7 +300,7 @@ static struct pci_driver vx222_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_vx222_ids,
        .probe = snd_vx222_probe,
-       .remove = __devexit_p(snd_vx222_remove),
+       .remove = snd_vx222_remove,
        .driver = {
                .pm = SND_VX222_PM_OPS,
        },
index e01fe34db9eca55ec0feb02082b5f25b87917b62..01c49655a3c1014bb9dec01784971b6e8a4d250c 100644 (file)
@@ -79,8 +79,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ymfpci_ids) = {
 MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
 
 #ifdef SUPPORT_JOYSTICK
-static int __devinit snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
-                                               int legacy_ctrl, int legacy_ctrl2)
+static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
+                                     int legacy_ctrl, int legacy_ctrl2)
 {
        struct gameport *gp;
        struct resource *r = NULL;
@@ -167,8 +167,8 @@ static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, i
 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { }
 #endif /* SUPPORT_JOYSTICK */
 
-static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
-                                          const struct pci_device_id *pci_id)
+static int snd_card_ymfpci_probe(struct pci_dev *pci,
+                                const struct pci_device_id *pci_id)
 {
        static int dev;
        struct snd_card *card;
@@ -344,7 +344,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
        return 0;
 }
 
-static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
+static void snd_card_ymfpci_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
        pci_set_drvdata(pci, NULL);
@@ -354,7 +354,7 @@ static struct pci_driver ymfpci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = snd_ymfpci_ids,
        .probe = snd_card_ymfpci_probe,
-       .remove = __devexit_p(snd_card_ymfpci_remove),
+       .remove = snd_card_ymfpci_remove,
 #ifdef CONFIG_PM_SLEEP
        .driver = {
                .pm = &snd_ymfpci_pm,
index 3a6f03f9b02f6bf9645dd3f473396881e3fed1ad..22056c50fe39fde10184856c33e14d20bf1743a1 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
 
@@ -598,7 +597,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
        }
 }
 
-static int __devinit snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
+static int snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
 {
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
                                4096, &chip->ac3_tmp_base) < 0)
@@ -1144,7 +1143,7 @@ static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
        .pointer =              snd_ymfpci_capture_pointer,
 };
 
-int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1187,7 +1186,7 @@ static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
        .pointer =              snd_ymfpci_capture_pointer,
 };
 
-int __devinit snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1225,7 +1224,8 @@ static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
        .pointer =              snd_ymfpci_playback_pointer,
 };
 
-int __devinit snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device,
+                        struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1270,7 +1270,8 @@ static const struct snd_pcm_chmap_elem surround_map[] = {
        { }
 };
 
-int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
+int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device,
+                      struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1339,7 +1340,7 @@ static int snd_ymfpci_spdif_default_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_default =
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1367,7 +1368,7 @@ static int snd_ymfpci_spdif_mask_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_mask =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READ,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1414,7 +1415,7 @@ static int snd_ymfpci_spdif_stream_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_stream =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1462,7 +1463,7 @@ static int snd_ymfpci_drec_source_put(struct snd_kcontrol *kcontrol, struct snd_
        return reg != old_reg;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_drec_source = {
        .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
        .name =         "Direct Recording Source",
@@ -1632,7 +1633,7 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        return change;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_dup4ch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "4ch Duplication",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -1641,7 +1642,7 @@ static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
        .put = snd_ymfpci_put_dup4ch,
 };
 
-static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_controls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Wave Playback Volume",
@@ -1735,7 +1736,7 @@ static int snd_ymfpci_gpio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_rear_shared __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_rear_shared = {
        .name = "Shared Rear/Line-In Switch",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info = snd_ymfpci_gpio_sw_info,
@@ -1799,7 +1800,7 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_ymfpci_pcm_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_pcm_volume = {
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "PCM Playback Volume",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1826,7 +1827,7 @@ static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97)
        chip->ac97 = NULL;
 }
 
-int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
+int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
 {
        struct snd_ac97_template ac97;
        struct snd_kcontrol *kctl;
@@ -1970,7 +1971,7 @@ static struct snd_timer_hardware snd_ymfpci_timer_hw = {
        .precise_resolution = snd_ymfpci_timer_precise_resolution,
 };
 
-int __devinit snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
+int snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
 {
        struct snd_timer *timer = NULL;
        struct snd_timer_id tid;
@@ -2006,7 +2007,7 @@ static void snd_ymfpci_proc_read(struct snd_info_entry *entry,
                snd_iprintf(buffer, "%04x: %04x\n", i, snd_ymfpci_readl(chip, i));
 }
 
-static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
+static int snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
 {
        struct snd_info_entry *entry;
        
@@ -2128,7 +2129,7 @@ static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
        snd_ymfpci_enable_dsp(chip);
 }
 
-static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
+static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
 {
        long size, playback_ctrl_size;
        int voice, bank, reg;
@@ -2261,7 +2262,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
 #endif
 
 #ifdef CONFIG_PM_SLEEP
-       vfree(chip->saved_regs);
+       kfree(chip->saved_regs);
 #endif
        if (chip->irq >= 0)
                free_irq(chip->irq, chip);
@@ -2394,10 +2395,10 @@ static int snd_ymfpci_resume(struct device *dev)
 SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume);
 #endif /* CONFIG_PM_SLEEP */
 
-int __devinit snd_ymfpci_create(struct snd_card *card,
-                               struct pci_dev * pci,
-                               unsigned short old_legacy_ctrl,
-                               struct snd_ymfpci ** rchip)
+int snd_ymfpci_create(struct snd_card *card,
+                     struct pci_dev *pci,
+                     unsigned short old_legacy_ctrl,
+                     struct snd_ymfpci **rchip)
 {
        struct snd_ymfpci *chip;
        int err;
@@ -2471,7 +2472,8 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
        }
 
 #ifdef CONFIG_PM_SLEEP
-       chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32));
+       chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32),
+                                  GFP_KERNEL);
        if (chip->saved_regs == NULL) {
                snd_ymfpci_free(chip);
                return -ENOMEM;
index b36679384b27b6ab1486481d15a6e779c9c6a126..5fbf5db2543d40c531efdac069df3ffd13b8a2a8 100644 (file)
@@ -477,7 +477,7 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
 #define AMP_CH_SPK     0
 #define AMP_CH_HD      1
 
-static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Speaker Playback Volume",
          .info = snd_pmac_awacs_info_volume_amp,
@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
        },
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Headphone Playback Switch",
        .info = snd_pmac_boolean_stereo_info,
@@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
        .private_value = AMP_CH_HD,
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Speaker Playback Switch",
        .info = snd_pmac_boolean_stereo_info,
@@ -595,46 +595,46 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
 /*
  * lists of mixer elements
  */
-static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers[] = {
        AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
        AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
 /*     AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] = {
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] = {
        AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
        AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] = {
        AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
@@ -642,34 +642,34 @@ static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
 /* FIXME: is this correct order?
  * screamer (powerbook G3 pismo) seems to have different bits...
  */
-static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] = {
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] = {
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] = {
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac =
 AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 =
 AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] = {
        AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Mic Boost Capture Volume",
          .info = snd_pmac_screamer_mic_boost_info,
@@ -678,34 +678,34 @@ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
        },
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] =
 {
        AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __devinitdata =
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] =
 {
        AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
        AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata =
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] =
 {
        AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
        AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] = {
        AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw =
 AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 =
 AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 =
 AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
 
 
@@ -872,7 +872,7 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
 /*
  * initialize chip
  */
-int __devinit
+int
 snd_pmac_awacs_init(struct snd_pmac *chip)
 {
        int pm7500 = IS_PM7500;
index a9d350789f5563a22f1f3184826125599ef8b36e..0040f048221fa39553ab35398a3d872101bb306c 100644 (file)
@@ -215,7 +215,7 @@ static struct snd_kcontrol_new snd_pmac_beep_mixer = {
 };
 
 /* Initialize beep stuff */
-int __devinit snd_pmac_attach_beep(struct snd_pmac *chip)
+int snd_pmac_attach_beep(struct snd_pmac *chip)
 {
        struct pmac_beep *beep;
        struct input_dev *input_dev;
index 00e2d5166d0a2fc277da60e02bebb1206608a5d3..cb4f0a5e984e9572ed47e433715db7f047753fe5 100644 (file)
@@ -467,7 +467,7 @@ static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
 /*
  * Burgundy mixers
  */
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
        BURGUNDY_VOLUME_W("Master Playback Volume", 0,
                        MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
        BURGUNDY_VOLUME_W("CD Capture Volume", 0,
@@ -495,7 +495,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = {
  */    BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
                        MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
 };
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
        BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
                        MASK_ADDR_BURGUNDY_VOLLINE, 16),
        BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
@@ -521,7 +521,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
        BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
                        MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
 };
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
        BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
                        MASK_ADDR_BURGUNDY_VOLMIC, 16),
        BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
@@ -537,33 +537,33 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
 /*     BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
  *             MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
 };
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac =
 BURGUNDY_SWITCH_B("Master Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
        BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac =
 BURGUNDY_SWITCH_B("Master Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_INTERN
        | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac =
 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac =
 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_INTERN, 0, 0);
-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac =
 BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac =
 BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __devinitdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac =
 BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
@@ -617,7 +617,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
 /*
  * initialize burgundy
  */
-int __devinit snd_pmac_burgundy_init(struct snd_pmac *chip)
+int snd_pmac_burgundy_init(struct snd_pmac *chip)
 {
        int imac = of_machine_is_compatible("iMac");
        int i, err;
index 24200b7bdacec5a74ab335fbb4ec0fc78062d2d3..b86526223e4e96b3939355f1f12f995c7c822a26 100644 (file)
@@ -244,7 +244,7 @@ static void daca_cleanup(struct snd_pmac *chip)
 }
 
 /* exported */
-int __devinit snd_pmac_daca_init(struct snd_pmac *chip)
+int snd_pmac_daca_init(struct snd_pmac *chip)
 {
        int i, err;
        struct pmac_daca *mix;
index 4080becf4cef0f892d453143b517dd23df46f59d..01aecc2b50738353ad8a96f618c01be631981240 100644 (file)
@@ -115,7 +115,7 @@ void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
        }
 }
 
-int __devinit snd_pmac_tumbler_post_init(void)
+int snd_pmac_tumbler_post_init(void)
 {
        int err;
        
@@ -130,7 +130,7 @@ int __devinit snd_pmac_tumbler_post_init(void)
 }
 
 /* exported */
-int __devinit snd_pmac_keywest_init(struct pmac_keywest *i2c)
+int snd_pmac_keywest_init(struct pmac_keywest *i2c)
 {
        int err;
 
index ab96cde7417b833d6e9e14e44aea7cb91cf965ba..c93fbbb201fed94645cf9819ec2fcf287b3389fe 100644 (file)
@@ -702,7 +702,7 @@ static struct snd_pcm_ops snd_pmac_capture_ops = {
        .pointer =      snd_pmac_capture_pointer,
 };
 
-int __devinit snd_pmac_pcm_new(struct snd_pmac *chip)
+int snd_pmac_pcm_new(struct snd_pmac *chip)
 {
        struct snd_pcm *pcm;
        int err;
@@ -907,7 +907,7 @@ static int snd_pmac_dev_free(struct snd_device *device)
  * check the machine support byteswap (little-endian)
  */
 
-static void __devinit detect_byte_swap(struct snd_pmac *chip)
+static void detect_byte_swap(struct snd_pmac *chip)
 {
        struct device_node *mio;
 
@@ -933,7 +933,7 @@ static void __devinit detect_byte_swap(struct snd_pmac *chip)
 /*
  * detect a sound chip
  */
-static int __devinit snd_pmac_detect(struct snd_pmac *chip)
+static int snd_pmac_detect(struct snd_pmac *chip)
 {
        struct device_node *sound;
        struct device_node *dn;
@@ -1146,7 +1146,7 @@ static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = {
+static struct snd_kcontrol_new auto_mute_controls[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Auto Mute Switch",
          .info = snd_pmac_boolean_mono_info,
@@ -1161,7 +1161,7 @@ static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = {
        },
 };
 
-int __devinit snd_pmac_add_automute(struct snd_pmac *chip)
+int snd_pmac_add_automute(struct snd_pmac *chip)
 {
        int err;
        chip->auto_mute = 1;
@@ -1178,7 +1178,7 @@ int __devinit snd_pmac_add_automute(struct snd_pmac *chip)
 /*
  * create and detect a pmac chip record
  */
-int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
+int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
 {
        struct snd_pmac *chip;
        struct device_node *np;
index 210cafe0489020ea970ac2724a68797a5be23a6e..09fc848d32ecd475951f09513e492e78a03d2a1c 100644 (file)
@@ -51,7 +51,7 @@ static struct platform_device *device;
 /*
  */
 
-static int __devinit snd_pmac_probe(struct platform_device *devptr)
+static int snd_pmac_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_pmac *chip;
@@ -136,7 +136,7 @@ __error:
 }
 
 
-static int __devexit snd_pmac_remove(struct platform_device *devptr)
+static int snd_pmac_remove(struct platform_device *devptr)
 {
        snd_card_free(platform_get_drvdata(devptr));
        platform_set_drvdata(devptr, NULL);
@@ -168,7 +168,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r
 
 static struct platform_driver snd_pmac_driver = {
        .probe          = snd_pmac_probe,
-       .remove         = __devexit_p(snd_pmac_remove),
+       .remove         = snd_pmac_remove,
        .driver         = {
                .name   = SND_PMAC_DRIVER,
                .owner  = THIS_MODULE,
index 9b18b5243a56a74bc704fc3e2c79901ac8ec0079..8c7dcbe0118dbce433c0dd7850f5ad467d90a8d4 100644 (file)
@@ -786,7 +786,7 @@ static struct snd_pcm_ops snd_ps3_pcm_spdif_ops = {
 };
 
 
-static int __devinit snd_ps3_map_mmio(void)
+static int snd_ps3_map_mmio(void)
 {
        the_card.mapped_mmio_vaddr =
                ioremap(the_card.ps3_dev->m_region->bus_addr,
@@ -808,7 +808,7 @@ static void snd_ps3_unmap_mmio(void)
        the_card.mapped_mmio_vaddr = NULL;
 }
 
-static int __devinit snd_ps3_allocate_irq(void)
+static int snd_ps3_allocate_irq(void)
 {
        int ret;
        u64 lpar_addr, lpar_size;
@@ -866,7 +866,7 @@ static void snd_ps3_free_irq(void)
        ps3_irq_plug_destroy(the_card.irq_no);
 }
 
-static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
+static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
 {
        uint64_t val;
        int ret;
@@ -882,7 +882,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
                        ret);
 }
 
-static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
+static void snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
 {
        /*
         * avsetting driver seems to never change the followings
@@ -906,7 +906,7 @@ static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
                   PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT);
 }
 
-static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
+static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
 {
        int ret;
        pr_debug("%s: start\n", __func__);
@@ -928,7 +928,7 @@ static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
        return ret;
 }
 
-static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
+static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
 {
        int i, ret;
        u64 lpar_addr, lpar_size;
index 9cea84c3e0c65e8d557618a4f82ecc2aa97d06db..b23354a4ceca7023d99cee8da266d0186c0dd208 100644 (file)
@@ -844,7 +844,7 @@ static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
 
 /*
  */
-static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
+static struct snd_kcontrol_new tumbler_mixers[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Master Playback Volume",
          .info = tumbler_info_master_volume,
@@ -868,7 +868,7 @@ static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
        },
 };
 
-static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snapper_mixers[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Master Playback Volume",
          .info = tumbler_info_master_volume,
@@ -901,7 +901,7 @@ static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
        },
 };
 
-static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_hp_sw = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Headphone Playback Switch",
        .info = snd_pmac_boolean_mono_info,
@@ -909,7 +909,7 @@ static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
        .put = tumbler_put_mute_switch,
        .private_value = TUMBLER_MUTE_HP,
 };
-static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_speaker_sw = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Speaker Playback Switch",
        .info = snd_pmac_boolean_mono_info,
@@ -917,7 +917,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
        .put = tumbler_put_mute_switch,
        .private_value = TUMBLER_MUTE_AMP,
 };
-static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_lineout_sw = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Line Out Playback Switch",
        .info = snd_pmac_boolean_mono_info,
@@ -925,7 +925,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
        .put = tumbler_put_mute_switch,
        .private_value = TUMBLER_MUTE_LINE,
 };
-static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = {
+static struct snd_kcontrol_new tumbler_drc_sw = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "DRC Switch",
        .info = snd_pmac_boolean_mono_info,
@@ -1276,7 +1276,7 @@ static void tumbler_resume(struct snd_pmac *chip)
 #endif
 
 /* initialize tumbler */
-static int __devinit tumbler_init(struct snd_pmac *chip)
+static int tumbler_init(struct snd_pmac *chip)
 {
        int irq;
        struct pmac_tumbler *mix = chip->mixer_data;
@@ -1349,7 +1349,7 @@ static void tumbler_cleanup(struct snd_pmac *chip)
 }
 
 /* exported */
-int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip)
+int snd_pmac_tumbler_init(struct snd_pmac *chip)
 {
        int i, err;
        struct pmac_tumbler *mix;
index d48b523207eb979b8dc034e3ea7bcd92cd304179..e59a73a9bc427602717633ea66953a73950d2d18 100644 (file)
@@ -540,7 +540,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
-static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
+static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "PCM Playback Switch",
        .index = 0,
@@ -549,7 +549,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
        .put = aica_pcmswitch_put
 };
 
-static struct snd_kcontrol_new snd_aica_pcmvolume_control __devinitdata = {
+static struct snd_kcontrol_new snd_aica_pcmvolume_control = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "PCM Playback Volume",
        .index = 0,
@@ -574,8 +574,7 @@ static int load_aica_firmware(void)
        return err;
 }
 
-static int __devinit add_aicamixer_controls(struct snd_card_aica
-                                           *dreamcastcard)
+static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard)
 {
        int err;
        err = snd_ctl_add
@@ -591,7 +590,7 @@ static int __devinit add_aicamixer_controls(struct snd_card_aica
        return 0;
 }
 
-static int __devexit snd_aica_remove(struct platform_device *devptr)
+static int snd_aica_remove(struct platform_device *devptr)
 {
        struct snd_card_aica *dreamcastcard;
        dreamcastcard = platform_get_drvdata(devptr);
@@ -603,7 +602,7 @@ static int __devexit snd_aica_remove(struct platform_device *devptr)
        return 0;
 }
 
-static int __devinit snd_aica_probe(struct platform_device *devptr)
+static int snd_aica_probe(struct platform_device *devptr)
 {
        int err;
        struct snd_card_aica *dreamcastcard;
@@ -652,7 +651,7 @@ static int __devinit snd_aica_probe(struct platform_device *devptr)
 
 static struct platform_driver snd_aica_driver = {
        .probe = snd_aica_probe,
-       .remove = __devexit_p(snd_aica_remove),
+       .remove = snd_aica_remove,
        .driver = {
                .name = SND_AICA_DRIVER,
                .owner  = THIS_MODULE,
index 0a3394751ed20c3d0d352077a30be7d107b50657..e68c4fc91a0304002537845b4a8b1182ab107258 100644 (file)
@@ -261,7 +261,7 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
        .mmap           = snd_pcm_lib_mmap_iomem,
 };
 
-static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
+static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
 {
        int err;
        struct snd_pcm *pcm;
@@ -346,9 +346,9 @@ static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
 }
 
 /* create  --  chip-specific constructor for the cards components */
-static int __devinit snd_sh_dac_create(struct snd_card *card,
-                                      struct platform_device *devptr,
-                                      struct snd_sh_dac **rchip)
+static int snd_sh_dac_create(struct snd_card *card,
+                            struct platform_device *devptr,
+                            struct snd_sh_dac **rchip)
 {
        struct snd_sh_dac *chip;
        int err;
@@ -392,7 +392,7 @@ static int __devinit snd_sh_dac_create(struct snd_card *card,
 }
 
 /* driver .probe  --  constructor */
-static int __devinit snd_sh_dac_probe(struct platform_device *devptr)
+static int snd_sh_dac_probe(struct platform_device *devptr)
 {
        struct snd_sh_dac *chip;
        struct snd_card *card;
index 72b09cfd3dc367d4aa28826e750e27aa2ffb1885..d1b691bf8e2d918cb3e8fd97e61cce74c464cd76 100644 (file)
@@ -6,6 +6,14 @@ config SND_ATMEL_SOC
          the ATMEL SSC interface. You will also need
          to select the audio interfaces to support below.
 
+config SND_ATMEL_SOC_PDC
+       tristate
+       depends on SND_ATMEL_SOC
+
+config SND_ATMEL_SOC_DMA
+       tristate
+       depends on SND_ATMEL_SOC
+
 config SND_ATMEL_SOC_SSC
        tristate
        depends on SND_ATMEL_SOC
@@ -16,8 +24,8 @@ config SND_ATMEL_SOC_SSC
 
 config SND_AT91_SOC_SAM9G20_WM8731
        tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
-       depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \
-                   AT91_PROGRAMMABLE_CLOCKS
+       depends on ATMEL_SSC && SND_ATMEL_SOC && AT91_PROGRAMMABLE_CLOCKS
+       select SND_ATMEL_SOC_PDC
        select SND_ATMEL_SOC_SSC
        select SND_SOC_WM8731
        help
@@ -27,6 +35,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
 config SND_AT91_SOC_AFEB9260
        tristate "SoC Audio support for AFEB9260 board"
        depends on ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
+       select SND_ATMEL_SOC_PDC
        select SND_ATMEL_SOC_SSC
        select SND_SOC_TLV320AIC23
        help
index a5c0bf19da78f01e823fc614c61528c30272a67c..41967ccb6f41e3968753d4922ad03f2439ad81b9 100644 (file)
@@ -1,8 +1,12 @@
 # AT91 Platform Support
 snd-soc-atmel-pcm-objs := atmel-pcm.o
+snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
+snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 
 obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
+obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
+obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 
 # AT91 Machine Support
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
new file mode 100644 (file)
index 0000000..30184a4
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * atmel-pcm-dma.c  --  ALSA PCM DMA support for the Atmel SoC.
+ *
+ *  Copyright (C) 2012 Atmel
+ *
+ * Author: Bo Shen <voice.shen@atmel.com>
+ *
+ * Based on atmel-pcm by:
+ * Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * Copyright 2008 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/atmel-ssc.h>
+#include <linux/platform_data/dma-atmel.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "atmel-pcm.h"
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_RESUME |
+                                 SNDRV_PCM_INFO_PAUSE,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+       .period_bytes_min       = 256,          /* lighting DMA overhead */
+       .period_bytes_max       = 2 * 0xffff,   /* if 2 bytes format */
+       .periods_min            = 8,
+       .periods_max            = 1024,         /* no limit */
+       .buffer_bytes_max       = ATMEL_SSC_DMABUF_SIZE,
+};
+
+/**
+ * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC
+ *
+ * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to
+ * check if any overrun occured.
+ */
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+       struct snd_pcm_substream *substream)
+{
+       struct atmel_pcm_dma_params *prtd;
+
+       prtd = snd_dmaengine_pcm_get_data(substream);
+
+       if (ssc_sr & prtd->mask->ssc_error) {
+               if (snd_pcm_running(substream))
+                       pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x)\n",
+                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                               ? "underrun" : "overrun", prtd->name,
+                               ssc_sr);
+
+               /* stop RX and capture: will be enabled again at restart */
+               ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable);
+               snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+
+               /* now drain RHR and read status to remove xrun condition */
+               ssc_readx(prtd->ssc->regs, SSC_RHR);
+               ssc_readx(prtd->ssc->regs, SSC_SR);
+       }
+}
+
+/*--------------------------------------------------------------------------*\
+ * DMAENGINE operations
+\*--------------------------------------------------------------------------*/
+static bool filter(struct dma_chan *chan, void *slave)
+{
+       struct at_dma_slave *sl = slave;
+
+       if (sl->dma_dev == chan->device->dev) {
+               chan->private = sl;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct atmel_pcm_dma_params *prtd;
+       struct ssc_device *ssc;
+       struct dma_chan *dma_chan;
+       struct dma_slave_config slave_config;
+       int ret;
+
+       prtd = snd_dmaengine_pcm_get_data(substream);
+       ssc = prtd->ssc;
+
+       ret = snd_hwparams_to_dma_slave_config(substream, params,
+                       &slave_config);
+       if (ret) {
+               pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
+               return ret;
+       }
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR;
+               slave_config.dst_maxburst = 1;
+       } else {
+               slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR;
+               slave_config.src_maxburst = 1;
+       }
+
+       slave_config.device_fc = false;
+
+       dma_chan = snd_dmaengine_pcm_get_chan(substream);
+       if (dmaengine_slave_config(dma_chan, &slave_config)) {
+               pr_err("atmel-pcm: failed to configure dma channel\n");
+               ret = -EBUSY;
+               return ret;
+       }
+
+       return 0;
+}
+
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct atmel_pcm_dma_params *prtd;
+       struct ssc_device *ssc;
+       struct at_dma_slave *sdata = NULL;
+       int ret;
+
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+       prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       ssc = prtd->ssc;
+       if (ssc->pdev)
+               sdata = ssc->pdev->dev.platform_data;
+
+       ret = snd_dmaengine_pcm_open(substream, filter, sdata);
+       if (ret) {
+               pr_err("atmel-pcm: dmaengine pcm open failed\n");
+               return -EINVAL;
+       }
+
+       snd_dmaengine_pcm_set_data(substream, prtd);
+
+       ret = atmel_pcm_configure_dma(substream, params);
+       if (ret) {
+               pr_err("atmel-pcm: failed to configure dmai\n");
+               goto err;
+       }
+
+       prtd->dma_intr_handler = atmel_pcm_dma_irq;
+
+       return 0;
+err:
+       snd_dmaengine_pcm_close(substream);
+       return ret;
+}
+
+static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
+{
+       struct atmel_pcm_dma_params *prtd;
+
+       prtd = snd_dmaengine_pcm_get_data(substream);
+
+       ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
+       ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
+
+       return 0;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+       snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware);
+
+       return 0;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+       snd_dmaengine_pcm_close(substream);
+
+       return 0;
+}
+
+static struct snd_pcm_ops atmel_pcm_ops = {
+       .open           = atmel_pcm_open,
+       .close          = atmel_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = atmel_pcm_hw_params,
+       .prepare        = atmel_pcm_dma_prepare,
+       .trigger        = snd_dmaengine_pcm_trigger,
+       .pointer        = snd_dmaengine_pcm_pointer_no_residue,
+       .mmap           = atmel_pcm_mmap,
+};
+
+static struct snd_soc_platform_driver atmel_soc_platform = {
+       .ops            = &atmel_pcm_ops,
+       .pcm_new        = atmel_pcm_new,
+       .pcm_free       = atmel_pcm_free,
+};
+
+int atmel_pcm_dma_platform_register(struct device *dev)
+{
+       return snd_soc_register_platform(dev, &atmel_soc_platform);
+}
+EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
+
+void atmel_pcm_dma_platform_unregister(struct device *dev)
+{
+       snd_soc_unregister_platform(dev);
+}
+EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
+
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Atmel DMA based PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c
new file mode 100644 (file)
index 0000000..6a293c7
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * atmel-pcm.c  --  ALSA PCM interface for the Atmel atmel SoC.
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author:     Nicolas Pitre
+ * Created:    Nov 30, 2004
+ * Copyright:  (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "atmel-pcm.h"
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ *      them against real values for AT32
+ */
+static const struct snd_pcm_hardware atmel_pcm_hardware = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_PAUSE,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 8192,
+       .periods_min            = 2,
+       .periods_max            = 1024,
+       .buffer_bytes_max       = ATMEL_SSC_DMABUF_SIZE,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct atmel_runtime_data {
+       struct atmel_pcm_dma_params *params;
+       dma_addr_t dma_buffer;          /* physical address of dma buffer */
+       dma_addr_t dma_buffer_end;      /* first address beyond DMA buffer */
+       size_t period_size;
+
+       dma_addr_t period_ptr;          /* physical address of next period */
+
+       /* PDC register save */
+       u32 pdc_xpr_save;
+       u32 pdc_xcr_save;
+       u32 pdc_xnpr_save;
+       u32 pdc_xncr_save;
+};
+
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+       struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+       static int count;
+
+       count++;
+
+       if (ssc_sr & params->mask->ssc_endbuf) {
+               pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                               ? "underrun" : "overrun",
+                               params->name, ssc_sr, count);
+
+               /* re-start the PDC */
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_disable);
+               prtd->period_ptr += prtd->period_size;
+               if (prtd->period_ptr >= prtd->dma_buffer_end)
+                       prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xcr,
+                          prtd->period_size / params->pdc_xfer_size);
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_enable);
+       }
+
+       if (ssc_sr & params->mask->ssc_endx) {
+               /* Load the PDC next pointer and counter registers */
+               prtd->period_ptr += prtd->period_size;
+               if (prtd->period_ptr >= prtd->dma_buffer_end)
+                       prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xnpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xncr,
+                          prtd->period_size / params->pdc_xfer_size);
+       }
+
+       snd_pcm_period_elapsed(substream);
+}
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct atmel_runtime_data *prtd = runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+       /* this may get called several times by oss emulation
+        * with different params */
+
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+       runtime->dma_bytes = params_buffer_bytes(params);
+
+       prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
+
+       prtd->dma_buffer = runtime->dma_addr;
+       prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+       prtd->period_size = params_period_bytes(params);
+
+       pr_debug("atmel-pcm: "
+               "hw_params: DMA for %s initialized "
+               "(dma_bytes=%u, period_size=%u)\n",
+               prtd->params->name,
+               runtime->dma_bytes,
+               prtd->period_size);
+       return 0;
+}
+
+static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+
+       if (params != NULL) {
+               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+                          params->mask->pdc_disable);
+               prtd->params->dma_intr_handler = NULL;
+       }
+
+       return 0;
+}
+
+static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+
+       ssc_writex(params->ssc->regs, SSC_IDR,
+                  params->mask->ssc_endx | params->mask->ssc_endbuf);
+       ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                  params->mask->pdc_disable);
+       return 0;
+}
+
+static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
+       int cmd)
+{
+       struct snd_pcm_runtime *rtd = substream->runtime;
+       struct atmel_runtime_data *prtd = rtd->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+       int ret = 0;
+
+       pr_debug("atmel-pcm:buffer_size = %ld,"
+               "dma_area = %p, dma_bytes = %u\n",
+               rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xcr,
+                          prtd->period_size / params->pdc_xfer_size);
+
+               prtd->period_ptr += prtd->period_size;
+               ssc_writex(params->ssc->regs, params->pdc->xnpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xncr,
+                          prtd->period_size / params->pdc_xfer_size);
+
+               pr_debug("atmel-pcm: trigger: "
+                       "period_ptr=%lx, xpr=%u, "
+                       "xcr=%u, xnpr=%u, xncr=%u\n",
+                       (unsigned long)prtd->period_ptr,
+                       ssc_readx(params->ssc->regs, params->pdc->xpr),
+                       ssc_readx(params->ssc->regs, params->pdc->xcr),
+                       ssc_readx(params->ssc->regs, params->pdc->xnpr),
+                       ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+               ssc_writex(params->ssc->regs, SSC_IER,
+                          params->mask->ssc_endx | params->mask->ssc_endbuf);
+               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+                          params->mask->pdc_enable);
+
+               pr_debug("sr=%u imr=%u\n",
+                       ssc_readx(params->ssc->regs, SSC_SR),
+                       ssc_readx(params->ssc->regs, SSC_IER));
+               break;          /* SNDRV_PCM_TRIGGER_START */
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_disable);
+               break;
+
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_enable);
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static snd_pcm_uframes_t atmel_pcm_pointer(
+       struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct atmel_runtime_data *prtd = runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+       dma_addr_t ptr;
+       snd_pcm_uframes_t x;
+
+       ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+       x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+       if (x == runtime->buffer_size)
+               x = 0;
+
+       return x;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct atmel_runtime_data *prtd;
+       int ret = 0;
+
+       snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
+
+       /* ensure that buffer size is a multiple of period size */
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto out;
+
+       prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
+       if (prtd == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       runtime->private_data = prtd;
+
+ out:
+       return ret;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+
+       kfree(prtd);
+       return 0;
+}
+
+static struct snd_pcm_ops atmel_pcm_ops = {
+       .open           = atmel_pcm_open,
+       .close          = atmel_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = atmel_pcm_hw_params,
+       .hw_free        = atmel_pcm_hw_free,
+       .prepare        = atmel_pcm_prepare,
+       .trigger        = atmel_pcm_trigger,
+       .pointer        = atmel_pcm_pointer,
+       .mmap           = atmel_pcm_mmap,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+#ifdef CONFIG_PM
+static int atmel_pcm_suspend(struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime *runtime = dai->runtime;
+       struct atmel_runtime_data *prtd;
+       struct atmel_pcm_dma_params *params;
+
+       if (!runtime)
+               return 0;
+
+       prtd = runtime->private_data;
+       params = prtd->params;
+
+       /* disable the PDC and save the PDC registers */
+
+       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
+
+       prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+       prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+       prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+       prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+       return 0;
+}
+
+static int atmel_pcm_resume(struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime *runtime = dai->runtime;
+       struct atmel_runtime_data *prtd;
+       struct atmel_pcm_dma_params *params;
+
+       if (!runtime)
+               return 0;
+
+       prtd = runtime->private_data;
+       params = prtd->params;
+
+       /* restore the PDC registers and enable the PDC */
+       ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
+       return 0;
+}
+#else
+#define atmel_pcm_suspend      NULL
+#define atmel_pcm_resume       NULL
+#endif
+
+static struct snd_soc_platform_driver atmel_soc_platform = {
+       .ops            = &atmel_pcm_ops,
+       .pcm_new        = atmel_pcm_new,
+       .pcm_free       = atmel_pcm_free,
+       .suspend        = atmel_pcm_suspend,
+       .resume         = atmel_pcm_resume,
+};
+
+int atmel_pcm_pdc_platform_register(struct device *dev)
+{
+       return snd_soc_register_platform(dev, &atmel_soc_platform);
+}
+EXPORT_SYMBOL(atmel_pcm_pdc_platform_register);
+
+void atmel_pcm_pdc_platform_unregister(struct device *dev)
+{
+       snd_soc_unregister_platform(dev);
+}
+EXPORT_SYMBOL(atmel_pcm_pdc_platform_unregister);
+
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("Atmel PCM module");
+MODULE_LICENSE("GPL");
index 9b84f985770ee4e09ca1d7a8ab04cbe410fda037..e99f1811300aef179a5c1d5c33dc702249175681 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
 #include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
-
 #include "atmel-pcm.h"
 
-
-/*--------------------------------------------------------------------------*\
- * Hardware definition
-\*--------------------------------------------------------------------------*/
-/* TODO: These values were taken from the AT91 platform driver, check
- *      them against real values for AT32
- */
-static const struct snd_pcm_hardware atmel_pcm_hardware = {
-       .info                   = SNDRV_PCM_INFO_MMAP |
-                                 SNDRV_PCM_INFO_MMAP_VALID |
-                                 SNDRV_PCM_INFO_INTERLEAVED |
-                                 SNDRV_PCM_INFO_PAUSE,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
-       .period_bytes_min       = 32,
-       .period_bytes_max       = 8192,
-       .periods_min            = 2,
-       .periods_max            = 1024,
-       .buffer_bytes_max       = 32 * 1024,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Data types
-\*--------------------------------------------------------------------------*/
-struct atmel_runtime_data {
-       struct atmel_pcm_dma_params *params;
-       dma_addr_t dma_buffer;          /* physical address of dma buffer */
-       dma_addr_t dma_buffer_end;      /* first address beyond DMA buffer */
-       size_t period_size;
-
-       dma_addr_t period_ptr;          /* physical address of next period */
-
-       /* PDC register save */
-       u32 pdc_xpr_save;
-       u32 pdc_xcr_save;
-       u32 pdc_xnpr_save;
-       u32 pdc_xncr_save;
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Helper functions
-\*--------------------------------------------------------------------------*/
 static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        int stream)
 {
        struct snd_pcm_substream *substream = pcm->streams[stream].substream;
        struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = atmel_pcm_hardware.buffer_bytes_max;
+       size_t size = ATMEL_SSC_DMABUF_SIZE;
 
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
        buf->private_data = NULL;
        buf->area = dma_alloc_coherent(pcm->card->dev, size,
-                                         &buf->addr, GFP_KERNEL);
-       pr_debug("atmel-pcm:"
-               "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
-               (void *) buf->area,
-               (void *) buf->addr,
-               size);
+                       &buf->addr, GFP_KERNEL);
+       pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%d\n",
+                       (void *)buf->area, (void *)buf->addr, size);
 
        if (!buf->area)
                return -ENOMEM;
@@ -113,258 +58,19 @@ static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        buf->bytes = size;
        return 0;
 }
-/*--------------------------------------------------------------------------*\
- * ISR
-\*--------------------------------------------------------------------------*/
-static void atmel_pcm_dma_irq(u32 ssc_sr,
-       struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-       static int count;
-
-       count++;
-
-       if (ssc_sr & params->mask->ssc_endbuf) {
-               pr_warning("atmel-pcm: buffer %s on %s"
-                               " (SSC_SR=%#x, count=%d)\n",
-                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-                               ? "underrun" : "overrun",
-                               params->name, ssc_sr, count);
-
-               /* re-start the PDC */
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_disable);
-               prtd->period_ptr += prtd->period_size;
-               if (prtd->period_ptr >= prtd->dma_buffer_end)
-                       prtd->period_ptr = prtd->dma_buffer;
-
-               ssc_writex(params->ssc->regs, params->pdc->xpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xcr,
-                          prtd->period_size / params->pdc_xfer_size);
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_enable);
-       }
-
-       if (ssc_sr & params->mask->ssc_endx) {
-               /* Load the PDC next pointer and counter registers */
-               prtd->period_ptr += prtd->period_size;
-               if (prtd->period_ptr >= prtd->dma_buffer_end)
-                       prtd->period_ptr = prtd->dma_buffer;
-
-               ssc_writex(params->ssc->regs, params->pdc->xnpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xncr,
-                          prtd->period_size / params->pdc_xfer_size);
-       }
-
-       snd_pcm_period_elapsed(substream);
-}
-
-
-/*--------------------------------------------------------------------------*\
- * PCM operations
-\*--------------------------------------------------------------------------*/
-static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct atmel_runtime_data *prtd = runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
-       /* this may get called several times by oss emulation
-        * with different params */
-
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
-
-       prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
-
-       prtd->dma_buffer = runtime->dma_addr;
-       prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
-       prtd->period_size = params_period_bytes(params);
-
-       pr_debug("atmel-pcm: "
-               "hw_params: DMA for %s initialized "
-               "(dma_bytes=%u, period_size=%u)\n",
-               prtd->params->name,
-               runtime->dma_bytes,
-               prtd->period_size);
-       return 0;
-}
-
-static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-
-       if (params != NULL) {
-               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
-                          params->mask->pdc_disable);
-               prtd->params->dma_intr_handler = NULL;
-       }
-
-       return 0;
-}
-
-static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-
-       ssc_writex(params->ssc->regs, SSC_IDR,
-                  params->mask->ssc_endx | params->mask->ssc_endbuf);
-       ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                  params->mask->pdc_disable);
-       return 0;
-}
-
-static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
-       int cmd)
-{
-       struct snd_pcm_runtime *rtd = substream->runtime;
-       struct atmel_runtime_data *prtd = rtd->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-       int ret = 0;
-
-       pr_debug("atmel-pcm:buffer_size = %ld,"
-               "dma_area = %p, dma_bytes = %u\n",
-               rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               prtd->period_ptr = prtd->dma_buffer;
-
-               ssc_writex(params->ssc->regs, params->pdc->xpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xcr,
-                          prtd->period_size / params->pdc_xfer_size);
-
-               prtd->period_ptr += prtd->period_size;
-               ssc_writex(params->ssc->regs, params->pdc->xnpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xncr,
-                          prtd->period_size / params->pdc_xfer_size);
-
-               pr_debug("atmel-pcm: trigger: "
-                       "period_ptr=%lx, xpr=%u, "
-                       "xcr=%u, xnpr=%u, xncr=%u\n",
-                       (unsigned long)prtd->period_ptr,
-                       ssc_readx(params->ssc->regs, params->pdc->xpr),
-                       ssc_readx(params->ssc->regs, params->pdc->xcr),
-                       ssc_readx(params->ssc->regs, params->pdc->xnpr),
-                       ssc_readx(params->ssc->regs, params->pdc->xncr));
-
-               ssc_writex(params->ssc->regs, SSC_IER,
-                          params->mask->ssc_endx | params->mask->ssc_endbuf);
-               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
-                          params->mask->pdc_enable);
-
-               pr_debug("sr=%u imr=%u\n",
-                       ssc_readx(params->ssc->regs, SSC_SR),
-                       ssc_readx(params->ssc->regs, SSC_IER));
-               break;          /* SNDRV_PCM_TRIGGER_START */
-
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_disable);
-               break;
-
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_enable);
-               break;
-
-       default:
-               ret = -EINVAL;
-       }
 
-       return ret;
-}
-
-static snd_pcm_uframes_t atmel_pcm_pointer(
-       struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct atmel_runtime_data *prtd = runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-       dma_addr_t ptr;
-       snd_pcm_uframes_t x;
-
-       ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
-       x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
-       if (x == runtime->buffer_size)
-               x = 0;
-
-       return x;
-}
-
-static int atmel_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct atmel_runtime_data *prtd;
-       int ret = 0;
-
-       snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
-
-       /* ensure that buffer size is a multiple of period size */
-       ret = snd_pcm_hw_constraint_integer(runtime,
-                                               SNDRV_PCM_HW_PARAM_PERIODS);
-       if (ret < 0)
-               goto out;
-
-       prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
-       if (prtd == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       runtime->private_data = prtd;
-
- out:
-       return ret;
-}
-
-static int atmel_pcm_close(struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-
-       kfree(prtd);
-       return 0;
-}
-
-static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+int atmel_pcm_mmap(struct snd_pcm_substream *substream,
        struct vm_area_struct *vma)
 {
        return remap_pfn_range(vma, vma->vm_start,
                       substream->dma_buffer.addr >> PAGE_SHIFT,
                       vma->vm_end - vma->vm_start, vma->vm_page_prot);
 }
+EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
 
-static struct snd_pcm_ops atmel_pcm_ops = {
-       .open           = atmel_pcm_open,
-       .close          = atmel_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
-       .hw_params      = atmel_pcm_hw_params,
-       .hw_free        = atmel_pcm_hw_free,
-       .prepare        = atmel_pcm_prepare,
-       .trigger        = atmel_pcm_trigger,
-       .pointer        = atmel_pcm_pointer,
-       .mmap           = atmel_pcm_mmap,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * ASoC platform driver
-\*--------------------------------------------------------------------------*/
 static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
+int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
@@ -376,6 +82,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+               pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
@@ -383,8 +90,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
        }
 
        if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               pr_debug("atmel-pcm:"
-                               "Allocating PCM capture DMA buffer\n");
+               pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -393,8 +99,9 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
  out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(atmel_pcm_new);
 
-static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
+void atmel_pcm_free(struct snd_pcm *pcm)
 {
        struct snd_pcm_substream *substream;
        struct snd_dma_buffer *buf;
@@ -413,89 +120,5 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
                buf->area = NULL;
        }
 }
+EXPORT_SYMBOL_GPL(atmel_pcm_free);
 
-#ifdef CONFIG_PM
-static int atmel_pcm_suspend(struct snd_soc_dai *dai)
-{
-       struct snd_pcm_runtime *runtime = dai->runtime;
-       struct atmel_runtime_data *prtd;
-       struct atmel_pcm_dma_params *params;
-
-       if (!runtime)
-               return 0;
-
-       prtd = runtime->private_data;
-       params = prtd->params;
-
-       /* disable the PDC and save the PDC registers */
-
-       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
-
-       prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
-       prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
-       prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
-       prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
-
-       return 0;
-}
-
-static int atmel_pcm_resume(struct snd_soc_dai *dai)
-{
-       struct snd_pcm_runtime *runtime = dai->runtime;
-       struct atmel_runtime_data *prtd;
-       struct atmel_pcm_dma_params *params;
-
-       if (!runtime)
-               return 0;
-
-       prtd = runtime->private_data;
-       params = prtd->params;
-
-       /* restore the PDC registers and enable the PDC */
-       ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
-       ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
-       ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
-       ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
-
-       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
-       return 0;
-}
-#else
-#define atmel_pcm_suspend      NULL
-#define atmel_pcm_resume       NULL
-#endif
-
-static struct snd_soc_platform_driver atmel_soc_platform = {
-       .ops            = &atmel_pcm_ops,
-       .pcm_new        = atmel_pcm_new,
-       .pcm_free       = atmel_pcm_free_dma_buffers,
-       .suspend        = atmel_pcm_suspend,
-       .resume         = atmel_pcm_resume,
-};
-
-static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
-{
-       return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
-}
-
-static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver atmel_pcm_driver = {
-       .driver = {
-                       .name = "atmel-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-
-       .probe = atmel_soc_platform_probe,
-       .remove = __devexit_p(atmel_soc_platform_remove),
-};
-
-module_platform_driver(atmel_pcm_driver);
-
-MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
-MODULE_DESCRIPTION("Atmel PCM module");
-MODULE_LICENSE("GPL");
index 5e0a95e643298b8f5210e7619139b48a02ae939f..bb45d20e7250aeace79a2595f5f9676349ba05d9 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <linux/atmel-ssc.h>
 
+#define ATMEL_SSC_DMABUF_SIZE  (64 * 1024)
+
 /*
  * Registers and status bits that are required by the PCM driver.
  */
@@ -50,6 +52,7 @@ struct atmel_pdc_regs {
 struct atmel_ssc_mask {
        u32     ssc_enable;             /* SSC recv/trans enable */
        u32     ssc_disable;            /* SSC recv/trans disable */
+       u32     ssc_error;              /* SSC error conditions */
        u32     ssc_endx;               /* SSC ENDTX or ENDRX */
        u32     ssc_endbuf;             /* SSC TXBUFE or RXBUFF */
        u32     pdc_enable;             /* PDC recv/trans enable */
@@ -80,4 +83,35 @@ struct atmel_pcm_dma_params {
 #define ssc_readx(base, reg)            (__raw_readl((base) + (reg)))
 #define ssc_writex(base, reg, value)    __raw_writel((value), (base) + (reg))
 
+int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd);
+void atmel_pcm_free(struct snd_pcm *pcm);
+int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+               struct vm_area_struct *vma);
+
+#ifdef CONFIG_SND_ATMEL_SOC_PDC
+int atmel_pcm_pdc_platform_register(struct device *dev);
+void atmel_pcm_pdc_platform_unregister(struct device *dev);
+#else
+static inline int atmel_pcm_pdc_platform_register(struct device *dev)
+{
+       return 0;
+}
+static inline void atmel_pcm_pdc_platform_unregister(struct device *dev)
+{
+}
+#endif
+
+#ifdef CONFIG_SND_ATMEL_SOC_DMA
+int atmel_pcm_dma_platform_register(struct device *dev);
+void atmel_pcm_dma_platform_unregister(struct device *dev);
+#else
+static inline int atmel_pcm_dma_platform_register(struct device *dev)
+{
+       return 0;
+}
+static inline void atmel_pcm_dma_platform_unregister(struct device *dev)
+{
+}
+#endif
+
 #endif /* _ATMEL_PCM_H */
index 354341ec0f42f1129adbaaf310366af46b866229..1c7663422054049265957743bad8c6f8678e9e17 100644 (file)
 #include "atmel_ssc_dai.h"
 
 
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES                1
-#else
 #define NUM_SSC_DEVICES                3
-#endif
 
 /*
  * SSC PDC registers required by the PCM DMA engine.
@@ -107,7 +103,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
        .pdc            = &pdc_rx_reg,
        .mask           = &ssc_rx_mask,
        } },
-#if NUM_SSC_DEVICES == 3
        {{
        .name           = "SSC1 PCM out",
        .pdc            = &pdc_tx_reg,
@@ -128,7 +123,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
        .pdc            = &pdc_rx_reg,
        .mask           = &ssc_rx_mask,
        } },
-#endif
 };
 
 
@@ -139,7 +133,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
        .dir_mask       = SSC_DIR_MASK_UNUSED,
        .initialized    = 0,
        },
-#if NUM_SSC_DEVICES == 3
        {
        .name           = "ssc1",
        .lock           = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
@@ -152,7 +145,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
        .dir_mask       = SSC_DIR_MASK_UNUSED,
        .initialized    = 0,
        },
-#endif
 };
 
 
@@ -690,27 +682,9 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
 static int atmel_ssc_probe(struct snd_soc_dai *dai)
 {
        struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
-       int ret = 0;
 
        snd_soc_dai_set_drvdata(dai, ssc_p);
 
-       /*
-        * Request SSC device
-        */
-       ssc_p->ssc = ssc_request(dai->id);
-       if (IS_ERR(ssc_p->ssc)) {
-               printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
-               ret = PTR_ERR(ssc_p->ssc);
-       }
-
-       return ret;
-}
-
-static int atmel_ssc_remove(struct snd_soc_dai *dai)
-{
-       struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
-
-       ssc_free(ssc_p->ssc);
        return 0;
 }
 
@@ -728,30 +702,8 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
 };
 
-static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
-       {
-               .name = "atmel-ssc-dai.0",
-               .probe = atmel_ssc_probe,
-               .remove = atmel_ssc_remove,
-               .suspend = atmel_ssc_suspend,
-               .resume = atmel_ssc_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .ops = &atmel_ssc_dai_ops,
-       },
-#if NUM_SSC_DEVICES == 3
-       {
-               .name = "atmel-ssc-dai.1",
+static struct snd_soc_dai_driver atmel_ssc_dai = {
                .probe = atmel_ssc_probe,
-               .remove = atmel_ssc_remove,
                .suspend = atmel_ssc_suspend,
                .resume = atmel_ssc_resume,
                .playback = {
@@ -765,50 +717,50 @@ static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
                        .rates = ATMEL_SSC_RATES,
                        .formats = ATMEL_SSC_FORMATS,},
                .ops = &atmel_ssc_dai_ops,
-       },
-       {
-               .name = "atmel-ssc-dai.2",
-               .probe = atmel_ssc_probe,
-               .remove = atmel_ssc_remove,
-               .suspend = atmel_ssc_suspend,
-               .resume = atmel_ssc_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .ops = &atmel_ssc_dai_ops,
-       },
-#endif
 };
 
-static __devinit int asoc_ssc_probe(struct platform_device *pdev)
+static int asoc_ssc_init(struct device *dev)
 {
-       BUG_ON(pdev->id < 0);
-       BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
-       return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]);
-}
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ssc_device *ssc = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
+       if (ret) {
+               dev_err(dev, "Could not register DAI: %d\n", ret);
+               goto err;
+       }
+
+       if (ssc->pdata->use_dma)
+               ret = atmel_pcm_dma_platform_register(dev);
+       else
+               ret = atmel_pcm_pdc_platform_register(dev);
+
+       if (ret) {
+               dev_err(dev, "Could not register PCM: %d\n", ret);
+               goto err_unregister_dai;
+       };
 
-static int __devexit asoc_ssc_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_dai(&pdev->dev);
        return 0;
+
+err_unregister_dai:
+       snd_soc_unregister_dai(dev);
+err:
+       return ret;
 }
 
-static struct platform_driver asoc_ssc_driver = {
-       .driver = {
-                       .name = "atmel-ssc-dai",
-                       .owner = THIS_MODULE,
-       },
+static void asoc_ssc_exit(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ssc_device *ssc = platform_get_drvdata(pdev);
 
-       .probe = asoc_ssc_probe,
-       .remove = __devexit_p(asoc_ssc_remove),
-};
+       if (ssc->pdata->use_dma)
+               atmel_pcm_dma_platform_unregister(dev);
+       else
+               atmel_pcm_pdc_platform_unregister(dev);
+
+       snd_soc_unregister_dai(dev);
+}
 
 /**
  * atmel_ssc_set_audio - Allocate the specified SSC for audio use.
@@ -816,50 +768,32 @@ static struct platform_driver asoc_ssc_driver = {
 int atmel_ssc_set_audio(int ssc_id)
 {
        struct ssc_device *ssc;
-       static struct platform_device *dma_pdev;
-       struct platform_device *ssc_pdev;
        int ret;
 
-       if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
-               return -EINVAL;
-
-       /* Allocate a dummy device for DMA if we don't have one already */
-       if (!dma_pdev) {
-               dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
-               if (!dma_pdev)
-                       return -ENOMEM;
-
-               ret = platform_device_add(dma_pdev);
-               if (ret < 0) {
-                       platform_device_put(dma_pdev);
-                       dma_pdev = NULL;
-                       return ret;
-               }
-       }
-
-       ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
-       if (!ssc_pdev)
-               return -ENOMEM;
-
        /* If we can grab the SSC briefly to parent the DAI device off it */
        ssc = ssc_request(ssc_id);
-       if (IS_ERR(ssc))
-               pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n",
+       if (IS_ERR(ssc)) {
+               pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
                        PTR_ERR(ssc));
-       else {
-               ssc_pdev->dev.parent = &(ssc->pdev->dev);
-               ssc_free(ssc);
+               return PTR_ERR(ssc);
+       } else {
+               ssc_info[ssc_id].ssc = ssc;
        }
 
-       ret = platform_device_add(ssc_pdev);
-       if (ret < 0)
-               platform_device_put(ssc_pdev);
+       ret = asoc_ssc_init(&ssc->pdev->dev);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
 
-module_platform_driver(asoc_ssc_driver);
+void atmel_ssc_put_audio(int ssc_id)
+{
+       struct ssc_device *ssc = ssc_info[ssc_id].ssc;
+
+       ssc_free(ssc);
+       asoc_ssc_exit(&ssc->pdev->dev);
+}
+EXPORT_SYMBOL_GPL(atmel_ssc_put_audio);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
index 5d4f0f9b4d9a875eb935ec79488b76ff17073ab0..b1f08d51149526006021c7314aa4f3e15847de3d 100644 (file)
@@ -117,6 +117,7 @@ struct atmel_ssc_info {
        struct atmel_ssc_state ssc_state;
 };
 
-int atmel_ssc_set_audio(int ssc);
+int atmel_ssc_set_audio(int ssc_id);
+void atmel_ssc_put_audio(int ssc_id);
 
 #endif /* _AT91_SSC_DAI_H */
index c88351488f45c5c6adb0529a212ab257531a90fd..da976291da9e28c46c55f45ff9ba70ea52544181 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 
+#include <linux/pinctrl/consumer.h>
+
 #include <linux/atmel-ssc.h>
 
 #include <sound/core.h>
@@ -179,10 +181,10 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link at91sam9g20ek_dai = {
        .name = "WM8731",
        .stream_name = "WM8731 PCM",
-       .cpu_dai_name = "atmel-ssc-dai.0",
+       .cpu_dai_name = "at91rm9200_ssc.0",
        .codec_dai_name = "wm8731-hifi",
        .init = at91sam9g20ek_wm8731_init,
-       .platform_name = "atmel-pcm-audio",
+       .platform_name = "at91rm9200_ssc.0",
        .codec_name = "wm8731.0-001b",
        .ops = &at91sam9g20ek_ops,
 };
@@ -195,20 +197,31 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
        .set_bias_level = at91sam9g20ek_set_bias_level,
 };
 
-static struct platform_device *at91sam9g20ek_snd_device;
-
-static int __init at91sam9g20ek_init(void)
+static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *codec_np, *cpu_np;
        struct clk *pllb;
+       struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
+       struct pinctrl *pinctrl;
        int ret;
 
-       if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
-               return -ENODEV;
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               dev_err(&pdev->dev, "Failed to request pinctrl for mck\n");
+               return PTR_ERR(pinctrl);
+       }
+
+       if (!np) {
+               if (!(machine_is_at91sam9g20ek() ||
+                       machine_is_at91sam9g20ek_2mmc()))
+                       return -ENODEV;
+       }
 
        ret = atmel_ssc_set_audio(0);
-       if (ret != 0) {
-               pr_err("Failed to set SSC 0 for audio: %d\n", ret);
-               return ret;
+       if (ret) {
+               dev_err(&pdev->dev, "ssc channel is not valid\n");
+               return -EINVAL;
        }
 
        /*
@@ -236,45 +249,92 @@ static int __init at91sam9g20ek_init(void)
 
        clk_set_rate(mclk, MCLK_RATE);
 
-       at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!at91sam9g20ek_snd_device) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               ret = -ENOMEM;
-               goto err_mclk;
+       card->dev = &pdev->dev;
+
+       /* Parse device node info */
+       if (np) {
+               ret = snd_soc_of_parse_card_name(card, "atmel,model");
+               if (ret)
+                       goto err;
+
+               ret = snd_soc_of_parse_audio_routing(card,
+                       "atmel,audio-routing");
+               if (ret)
+                       goto err;
+
+               /* Parse codec info */
+               at91sam9g20ek_dai.codec_name = NULL;
+               codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
+               if (!codec_np) {
+                       dev_err(&pdev->dev, "codec info missing\n");
+                       return -EINVAL;
+               }
+               at91sam9g20ek_dai.codec_of_node = codec_np;
+
+               /* Parse dai and platform info */
+               at91sam9g20ek_dai.cpu_dai_name = NULL;
+               at91sam9g20ek_dai.platform_name = NULL;
+               cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+               if (!cpu_np) {
+                       dev_err(&pdev->dev, "dai and pcm info missing\n");
+                       return -EINVAL;
+               }
+               at91sam9g20ek_dai.cpu_of_node = cpu_np;
+               at91sam9g20ek_dai.platform_of_node = cpu_np;
+
+               of_node_put(codec_np);
+               of_node_put(cpu_np);
        }
 
-       platform_set_drvdata(at91sam9g20ek_snd_device,
-                       &snd_soc_at91sam9g20ek);
-
-       ret = platform_device_add(at91sam9g20ek_snd_device);
+       ret = snd_soc_register_card(card);
        if (ret) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               goto err_device_add;
+               printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
        }
 
        return ret;
 
-err_device_add:
-       platform_device_put(at91sam9g20ek_snd_device);
 err_mclk:
        clk_put(mclk);
        mclk = NULL;
 err:
+       atmel_ssc_put_audio(0);
        return ret;
 }
 
-static void __exit at91sam9g20ek_exit(void)
+static int at91sam9g20ek_audio_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(at91sam9g20ek_snd_device);
-       at91sam9g20ek_snd_device = NULL;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       atmel_ssc_put_audio(0);
+       snd_soc_unregister_card(card);
        clk_put(mclk);
        mclk = NULL;
+
+       return 0;
 }
 
-module_init(at91sam9g20ek_init);
-module_exit(at91sam9g20ek_exit);
+#ifdef CONFIG_OF
+static const struct of_device_id at91sam9g20ek_wm8731_dt_ids[] = {
+       { .compatible = "atmel,at91sam9g20ek-wm8731-audio", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, at91sam9g20ek_wm8731_dt_ids);
+#endif
+
+static struct platform_driver at91sam9g20ek_audio_driver = {
+       .driver = {
+               .name   = "at91sam9g20ek-audio",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
+       },
+       .probe  = at91sam9g20ek_audio_probe,
+       .remove = at91sam9g20ek_audio_remove,
+};
+
+module_platform_driver(at91sam9g20ek_audio_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_ALIAS("platform:at91sam9g20ek-audio");
 MODULE_LICENSE("GPL");
index c5ac2449563a5140524702c5db367c5a2f52bb5f..ea7d9d157022a59be25323d071e3993bc0b98799 100644 (file)
@@ -223,7 +223,7 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
        .ops                    = &alchemy_ac97c_ops,
 };
 
-static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
+static int au1xac97c_drvprobe(struct platform_device *pdev)
 {
        int ret;
        struct resource *iores, *dmares;
@@ -276,7 +276,7 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit au1xac97c_drvremove(struct platform_device *pdev)
+static int au1xac97c_drvremove(struct platform_device *pdev)
 {
        struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
 
@@ -330,7 +330,7 @@ static struct platform_driver au1xac97c_driver = {
                .pm     = AU1XPSCAC97_PMOPS,
        },
        .probe          = au1xac97c_drvprobe,
-       .remove         = __devexit_p(au1xac97c_drvremove),
+       .remove         = au1xac97c_drvremove,
 };
 
 static int __init au1xac97c_load(void)
index 511d83c11a9a0e2799688df405a590ebc0a19ac4..376d976bcc2da652d9e047f561392b1915fcbe8d 100644 (file)
@@ -34,14 +34,14 @@ static struct snd_soc_card db1000_ac97 = {
        .num_links      = 1,
 };
 
-static int __devinit db1000_audio_probe(struct platform_device *pdev)
+static int db1000_audio_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &db1000_ac97;
        card->dev = &pdev->dev;
        return snd_soc_register_card(card);
 }
 
-static int __devexit db1000_audio_remove(struct platform_device *pdev)
+static int db1000_audio_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        snd_soc_unregister_card(card);
@@ -55,7 +55,7 @@ static struct platform_driver db1000_audio_driver = {
                .pm     = &snd_soc_pm_ops,
        },
        .probe          = db1000_audio_probe,
-       .remove         = __devexit_p(db1000_audio_remove),
+       .remove         = db1000_audio_remove,
 };
 
 module_platform_driver(db1000_audio_driver);
index 30ea513d81d730cefa1027be46726a1c69e8df5f..a497a0cfeba153aa70630b0dfadc7e69bf2d0e7c 100644 (file)
@@ -167,7 +167,7 @@ static struct snd_soc_card db1550_i2s_machine = {
 
 /*-------------------------  COMMON PART  ---------------------------*/
 
-static struct snd_soc_card *db1200_cards[] __devinitdata = {
+static struct snd_soc_card *db1200_cards[] = {
        &db1200_ac97_machine,
        &db1200_i2s_machine,
        &db1300_ac97_machine,
@@ -176,7 +176,7 @@ static struct snd_soc_card *db1200_cards[] __devinitdata = {
        &db1550_i2s_machine,
 };
 
-static int __devinit db1200_audio_probe(struct platform_device *pdev)
+static int db1200_audio_probe(struct platform_device *pdev)
 {
        const struct platform_device_id *pid = platform_get_device_id(pdev);
        struct snd_soc_card *card;
@@ -186,7 +186,7 @@ static int __devinit db1200_audio_probe(struct platform_device *pdev)
        return snd_soc_register_card(card);
 }
 
-static int __devexit db1200_audio_remove(struct platform_device *pdev)
+static int db1200_audio_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        snd_soc_unregister_card(card);
@@ -201,7 +201,7 @@ static struct platform_driver db1200_audio_driver = {
        },
        .id_table       = db1200_pids,
        .probe          = db1200_audio_probe,
-       .remove         = __devexit_p(db1200_audio_remove),
+       .remove         = db1200_audio_remove,
 };
 
 module_platform_driver(db1200_audio_driver);
index 8372cd35f0d6bea6701df54c829037a89c4e67cc..3b4eafaf30d3177d223f1a28c4374e55d32e8e68 100644 (file)
@@ -347,7 +347,7 @@ static struct snd_soc_platform_driver au1xpsc_soc_platform = {
        .pcm_free       = au1xpsc_pcm_free_dma_buffers,
 };
 
-static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
+static int au1xpsc_pcm_drvprobe(struct platform_device *pdev)
 {
        struct au1xpsc_audio_dmadata *dmadata;
 
@@ -362,7 +362,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
        return snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
 }
 
-static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
+static int au1xpsc_pcm_drvremove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
 
@@ -375,7 +375,7 @@ static struct platform_driver au1xpsc_pcm_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = au1xpsc_pcm_drvprobe,
-       .remove         = __devexit_p(au1xpsc_pcm_drvremove),
+       .remove         = au1xpsc_pcm_drvremove,
 };
 
 module_platform_driver(au1xpsc_pcm_driver);
index 0a91b186a86f1baaceae28f921058cf5c72d3e9e..befd1074f9bdbd9b008dc6324b5669a7f8a549c7 100644 (file)
@@ -322,7 +322,7 @@ static struct snd_soc_platform_driver alchemy_pcm_soc_platform = {
        .pcm_free       = alchemy_pcm_free_dma_buffers,
 };
 
-static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
+static int alchemy_pcm_drvprobe(struct platform_device *pdev)
 {
        struct alchemy_pcm_ctx *ctx;
 
@@ -335,7 +335,7 @@ static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
        return snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform);
 }
 
-static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev)
+static int alchemy_pcm_drvremove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
 
@@ -348,7 +348,7 @@ static struct platform_driver alchemy_pcmdma_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = alchemy_pcm_drvprobe,
-       .remove         = __devexit_p(alchemy_pcm_drvremove),
+       .remove         = alchemy_pcm_drvremove,
 };
 
 module_platform_driver(alchemy_pcmdma_driver);
index d4b9e364a47afbeb972f82e1605c9d67566564bf..072448afc21993a1e772cb71c078ce2fc07dd735 100644 (file)
@@ -225,7 +225,7 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
        .ops = &au1xi2s_dai_ops,
 };
 
-static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
+static int au1xi2s_drvprobe(struct platform_device *pdev)
 {
        struct resource *iores, *dmares;
        struct au1xpsc_audio_data *ctx;
@@ -263,7 +263,7 @@ static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
        return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
 }
 
-static int __devexit au1xi2s_drvremove(struct platform_device *pdev)
+static int au1xi2s_drvremove(struct platform_device *pdev)
 {
        struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
 
@@ -309,7 +309,7 @@ static struct platform_driver au1xi2s_driver = {
                .pm     = AU1XI2SC_PMOPS,
        },
        .probe          = au1xi2s_drvprobe,
-       .remove         = __devexit_p(au1xi2s_drvremove),
+       .remove         = au1xi2s_drvremove,
 };
 
 module_platform_driver(au1xi2s_driver);
index 476b79a1c11a764e4ea80ab484ec4eb8a16701a9..6ba07e365967221384760d2917bc1b8850ca5895 100644 (file)
@@ -361,7 +361,7 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
        .ops = &au1xpsc_ac97_dai_ops,
 };
 
-static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
+static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 {
        int ret;
        struct resource *iores, *dmares;
@@ -427,7 +427,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
+static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
 {
        struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
 
@@ -495,7 +495,7 @@ static struct platform_driver au1xpsc_ac97_driver = {
                .pm     = AU1XPSCAC97_PMOPS,
        },
        .probe          = au1xpsc_ac97_drvprobe,
-       .remove         = __devexit_p(au1xpsc_ac97_drvremove),
+       .remove         = au1xpsc_ac97_drvremove,
 };
 
 static int __init au1xpsc_ac97_load(void)
index 0607ba3d925831bb79e0221942256e8dc2c191fc..360b4e50d7c836eccac7000f3216cb61d3c9d146 100644 (file)
@@ -288,7 +288,7 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
        .ops = &au1xpsc_i2s_dai_ops,
 };
 
-static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
+static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 {
        struct resource *iores, *dmares;
        unsigned long sel;
@@ -353,7 +353,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
        return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
 }
 
-static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
+static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
 {
        struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
 
@@ -418,7 +418,7 @@ static struct platform_driver au1xpsc_i2s_driver = {
                .pm     = AU1XPSCI2S_PMOPS,
        },
        .probe          = au1xpsc_i2s_drvprobe,
-       .remove         = __devexit_p(au1xpsc_i2s_drvremove),
+       .remove         = au1xpsc_i2s_drvremove,
 };
 
 module_platform_driver(au1xpsc_i2s_driver);
index d7dc9bde09760ce5bc44fe6bd8bf0f4b79843a4d..7e2f36004a5acd605f9223e93d168143e11bcd25 100644 (file)
@@ -453,12 +453,12 @@ static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
        .pcm_free       = bf5xx_pcm_free_dma_buffers,
 };
 
-static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
+static int bf5xx_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);
 }
 
-static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
+static int bf5xx_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -471,7 +471,7 @@ static struct platform_driver bf5xx_pcm_driver = {
        },
 
        .probe = bf5xx_soc_platform_probe,
-       .remove = __devexit_p(bf5xx_soc_platform_remove),
+       .remove = bf5xx_soc_platform_remove,
 };
 
 module_platform_driver(bf5xx_pcm_driver);
index f4e9dc4e262e6c63a6a5e1cf318c4b58cab3b431..8e41bcb020eb5beba44505b7df5c1cfae0ee64e0 100644 (file)
@@ -282,7 +282,7 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE, },
 };
 
-static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev)
+static int asoc_bfin_ac97_probe(struct platform_device *pdev)
 {
        struct sport_device *sport_handle;
        int ret;
@@ -352,7 +352,7 @@ gpio_err:
        return ret;
 }
 
-static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
+static int asoc_bfin_ac97_remove(struct platform_device *pdev)
 {
        struct sport_device *sport_handle = platform_get_drvdata(pdev);
 
@@ -372,7 +372,7 @@ static struct platform_driver asoc_bfin_ac97_driver = {
        },
 
        .probe = asoc_bfin_ac97_probe,
-       .remove = __devexit_p(asoc_bfin_ac97_remove),
+       .remove = asoc_bfin_ac97_remove,
 };
 
 module_platform_driver(asoc_bfin_ac97_driver);
index 16b9c9efd19a79aba78c8e01ec9e4095300501d6..d23f4b0ea54f3779f9e655ef7e7557c8e8671f26 100644 (file)
@@ -75,7 +75,7 @@ static struct snd_soc_card bf5xx_ad1836 = {
        .num_links = 1,
 };
 
-static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
+static int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &bf5xx_ad1836;
        const char **link_name;
@@ -98,7 +98,7 @@ static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev)
+static int bf5xx_ad1836_driver_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -113,7 +113,7 @@ static struct platform_driver bf5xx_ad1836_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = bf5xx_ad1836_driver_probe,
-       .remove = __devexit_p(bf5xx_ad1836_driver_remove),
+       .remove = bf5xx_ad1836_driver_remove,
 };
 module_platform_driver(bf5xx_ad1836_driver);
 
index 63205d723eab769f8ddb5b007bc2d85cfb484bc4..262c1de364d87a06ee43125203e18d54f26a968f 100644 (file)
@@ -292,12 +292,12 @@ static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
        .pcm_free       = bf5xx_pcm_free_dma_buffers,
 };
 
-static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
+static int bfin_i2s_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
 }
 
-static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
+static int bfin_i2s_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -310,7 +310,7 @@ static struct platform_driver bfin_i2s_pcm_driver = {
        },
 
        .probe = bfin_i2s_soc_platform_probe,
-       .remove = __devexit_p(bfin_i2s_soc_platform_remove),
+       .remove = bfin_i2s_soc_platform_remove,
 };
 
 module_platform_driver(bfin_i2s_pcm_driver);
index 4dccf0374fe744fd54aaf379caf92e3eec5feda6..168d88bccb41cc18f18b22e41296783e9fb17ad8 100644 (file)
@@ -245,7 +245,7 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
        .ops = &bf5xx_i2s_dai_ops,
 };
 
-static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
+static int bf5xx_i2s_probe(struct platform_device *pdev)
 {
        struct sport_device *sport_handle;
        int ret;
@@ -267,7 +267,7 @@ static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
+static int bf5xx_i2s_remove(struct platform_device *pdev)
 {
        struct sport_device *sport_handle = platform_get_drvdata(pdev);
 
@@ -281,7 +281,7 @@ static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_i2s_driver = {
        .probe  = bf5xx_i2s_probe,
-       .remove = __devexit_p(bf5xx_i2s_remove),
+       .remove = bf5xx_i2s_remove,
        .driver = {
                .name = "bfin-i2s",
                .owner = THIS_MODULE,
index 254490cf1876a4234edc363b743cf06aa966fb27..0e6b888bb4cce6c7a44c79d49c7b284692deeea6 100644 (file)
@@ -317,12 +317,12 @@ static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
        .pcm_free       = bf5xx_pcm_free_dma_buffers,
 };
 
-static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
+static int bf5xx_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
 }
 
-static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
+static int bf5xx_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -335,7 +335,7 @@ static struct platform_driver bfin_tdm_driver = {
        },
 
        .probe = bf5xx_soc_platform_probe,
-       .remove = __devexit_p(bf5xx_soc_platform_remove),
+       .remove = bf5xx_soc_platform_remove,
 };
 
 module_platform_driver(bfin_tdm_driver);
index 594f88217c746e0f8639988b9851c105e2f5c0e5..c1e516ec53ad174c2c46d0d6735f9e96d2205915 100644 (file)
@@ -249,7 +249,7 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
        .ops = &bf5xx_tdm_dai_ops,
 };
 
-static int __devinit bfin_tdm_probe(struct platform_device *pdev)
+static int bfin_tdm_probe(struct platform_device *pdev)
 {
        struct sport_device *sport_handle;
        int ret;
@@ -295,7 +295,7 @@ sport_config_err:
        return ret;
 }
 
-static int __devexit bfin_tdm_remove(struct platform_device *pdev)
+static int bfin_tdm_remove(struct platform_device *pdev)
 {
        struct sport_device *sport_handle = platform_get_drvdata(pdev);
 
@@ -307,7 +307,7 @@ static int __devexit bfin_tdm_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_tdm_driver = {
        .probe  = bfin_tdm_probe,
-       .remove = __devexit_p(bfin_tdm_remove),
+       .remove = bfin_tdm_remove,
        .driver = {
                .name   = "bfin-tdm",
                .owner  = THIS_MODULE,
index c3c2466d3a4214a220d21a72add7376760a6fea2..8f337972f438f155daffe7cec9bb5fe8405f9748 100644 (file)
@@ -186,7 +186,7 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
        .ops = &bfin_i2s_dai_ops,
 };
 
-static int __devinit bfin_i2s_probe(struct platform_device *pdev)
+static int bfin_i2s_probe(struct platform_device *pdev)
 {
        struct sport_device *sport;
        struct device *dev = &pdev->dev;
@@ -208,7 +208,7 @@ static int __devinit bfin_i2s_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit bfin_i2s_remove(struct platform_device *pdev)
+static int bfin_i2s_remove(struct platform_device *pdev)
 {
        struct sport_device *sport = platform_get_drvdata(pdev);
 
@@ -220,7 +220,7 @@ static int __devexit bfin_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_i2s_driver = {
        .probe  = bfin_i2s_probe,
-       .remove = __devexit_p(bfin_i2s_remove),
+       .remove = bfin_i2s_remove,
        .driver = {
                .name = "bfin-i2s",
                .owner = THIS_MODULE,
index f3adbdbdd5e1a0a96f93caf305c6ba0a74619e2d..4ef9683bcad89c95906c5bf638ea2b73fc08edd6 100644 (file)
@@ -157,7 +157,7 @@ static int bfin_eval_adau1373_probe(struct platform_device *pdev)
        return snd_soc_register_card(&bfin_eval_adau1373);
 }
 
-static int __devexit bfin_eval_adau1373_remove(struct platform_device *pdev)
+static int bfin_eval_adau1373_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -173,7 +173,7 @@ static struct platform_driver bfin_eval_adau1373_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = bfin_eval_adau1373_probe,
-       .remove = __devexit_p(bfin_eval_adau1373_remove),
+       .remove = bfin_eval_adau1373_remove,
 };
 
 module_platform_driver(bfin_eval_adau1373_driver);
index b0531fc9d814058409b5cf585e99eaf0e3f7352d..3b55081a96c0f83bf63b10e031964ff42e644734 100644 (file)
@@ -97,7 +97,7 @@ static int bfin_eval_adau1701_probe(struct platform_device *pdev)
        return snd_soc_register_card(&bfin_eval_adau1701);
 }
 
-static int __devexit bfin_eval_adau1701_remove(struct platform_device *pdev)
+static int bfin_eval_adau1701_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -113,7 +113,7 @@ static struct platform_driver bfin_eval_adau1701_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = bfin_eval_adau1701_probe,
-       .remove = __devexit_p(bfin_eval_adau1701_remove),
+       .remove = bfin_eval_adau1701_remove,
 };
 
 module_platform_driver(bfin_eval_adau1701_driver);
index 84b09987b7f319cbaf01e2cb05be11c666404280..3b1b61a4481571960bda090c7342b2a465a7f9ea 100644 (file)
@@ -122,7 +122,7 @@ static int bfin_eval_adav80x_probe(struct platform_device *pdev)
        return snd_soc_register_card(&bfin_eval_adav80x);
 }
 
-static int __devexit bfin_eval_adav80x_remove(struct platform_device *pdev)
+static int bfin_eval_adav80x_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -145,7 +145,7 @@ static struct platform_driver bfin_eval_adav80x_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = bfin_eval_adav80x_probe,
-       .remove = __devexit_p(bfin_eval_adav80x_remove),
+       .remove = bfin_eval_adav80x_remove,
        .id_table = bfin_eval_adav80x_ids,
 };
 
index e01cb02abd3a91e17cfc9b3e22ee1df563feb22b..5db68cf7b281ab8fbb2af67310b01e7f75e4612b 100644 (file)
@@ -80,7 +80,7 @@ static struct snd_soc_card snd_soc_edb93xx = {
        .num_links      = 1,
 };
 
-static int __devinit edb93xx_probe(struct platform_device *pdev)
+static int edb93xx_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &snd_soc_edb93xx;
        int ret;
@@ -101,7 +101,7 @@ static int __devinit edb93xx_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit edb93xx_remove(struct platform_device *pdev)
+static int edb93xx_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -117,7 +117,7 @@ static struct platform_driver edb93xx_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = edb93xx_probe,
-       .remove         = __devexit_p(edb93xx_remove),
+       .remove         = edb93xx_remove,
 };
 
 module_platform_driver(edb93xx_driver);
index c3521653cfd3fcac901fbcf076752b5b10c654e5..f3f50e6fd6eb29218f622664b37ba7065946b57c 100644 (file)
@@ -352,7 +352,7 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
        .ops                    = &ep93xx_ac97_dai_ops,
 };
 
-static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
+static int ep93xx_ac97_probe(struct platform_device *pdev)
 {
        struct ep93xx_ac97_info *info;
        struct resource *res;
@@ -402,7 +402,7 @@ fail:
        return ret;
 }
 
-static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
+static int ep93xx_ac97_remove(struct platform_device *pdev)
 {
        struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
 
@@ -420,7 +420,7 @@ static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
 
 static struct platform_driver ep93xx_ac97_driver = {
        .probe  = ep93xx_ac97_probe,
-       .remove = __devexit_p(ep93xx_ac97_remove),
+       .remove = ep93xx_ac97_remove,
        .driver = {
                .name = "ep93xx-ac97",
                .owner = THIS_MODULE,
index ac4a7515e7be4d5e417d17eec041b3b1151c4df0..3365d4e843b7382a663380bd9311bdd762828be0 100644 (file)
@@ -422,7 +422,7 @@ fail:
        return err;
 }
 
-static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
+static int ep93xx_i2s_remove(struct platform_device *pdev)
 {
        struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
 
@@ -436,7 +436,7 @@ static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver ep93xx_i2s_driver = {
        .probe  = ep93xx_i2s_probe,
-       .remove = __devexit_p(ep93xx_i2s_remove),
+       .remove = ep93xx_i2s_remove,
        .driver = {
                .name   = "ep93xx-i2s",
                .owner  = THIS_MODULE,
index 665d9c94cc17ebeca825898ebac89f5c04937dd7..72eb7a49e16afb0a52e668aa41d1e85994c97092 100644 (file)
@@ -213,12 +213,12 @@ static struct snd_soc_platform_driver ep93xx_soc_platform = {
        .pcm_free       = &ep93xx_pcm_free_dma_buffers,
 };
 
-static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
+static int ep93xx_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
 }
 
-static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
+static int ep93xx_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -231,7 +231,7 @@ static struct platform_driver ep93xx_pcm_driver = {
        },
 
        .probe = ep93xx_soc_platform_probe,
-       .remove = __devexit_p(ep93xx_soc_platform_remove),
+       .remove = ep93xx_soc_platform_remove,
 };
 
 module_platform_driver(ep93xx_pcm_driver);
index dd997094eb301f8134b0b11db3a12ac6ed16d782..a397bb0d8179650e60967ed65fd4e02665940e6c 100644 (file)
@@ -41,7 +41,7 @@ static struct snd_soc_card snd_soc_simone = {
 
 static struct platform_device *simone_snd_ac97_device;
 
-static int __devinit simone_probe(struct platform_device *pdev)
+static int simone_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &snd_soc_simone;
        int ret;
@@ -63,7 +63,7 @@ static int __devinit simone_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit simone_remove(struct platform_device *pdev)
+static int simone_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -79,7 +79,7 @@ static struct platform_driver simone_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = simone_probe,
-       .remove         = __devexit_p(simone_remove),
+       .remove         = simone_remove,
 };
 
 module_platform_driver(simone_driver);
index a193cea3cf3cc73406a201db9e5aeb10b7772cc6..9d77fe28dfcca9bbda6b346a4e33af7c67154709 100644 (file)
@@ -98,7 +98,7 @@ static struct snd_soc_card snd_soc_snappercl15 = {
        .num_links      = 1,
 };
 
-static int __devinit snappercl15_probe(struct platform_device *pdev)
+static int snappercl15_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &snd_soc_snappercl15;
        int ret;
@@ -119,7 +119,7 @@ static int __devinit snappercl15_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit snappercl15_remove(struct platform_device *pdev)
+static int snappercl15_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -135,7 +135,7 @@ static struct platform_driver snappercl15_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = snappercl15_probe,
-       .remove         = __devexit_p(snappercl15_remove),
+       .remove         = snappercl15_remove,
 };
 
 module_platform_driver(snappercl15_driver);
index 9fd3b6827bba91c6717fdd9a006cf8612ce81d18..60159c07448da792e62e8e68f61e7d48d7ec04a4 100644 (file)
@@ -1423,7 +1423,7 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
        .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes),
 };
 
-static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+static int pm860x_codec_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm860x_priv *pm860x;
@@ -1463,7 +1463,7 @@ out:
        return -EINVAL;
 }
 
-static int __devexit pm860x_codec_remove(struct platform_device *pdev)
+static int pm860x_codec_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        platform_set_drvdata(pdev, NULL);
@@ -1476,7 +1476,7 @@ static struct platform_driver pm860x_codec_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = pm860x_codec_probe,
-       .remove = __devexit_p(pm860x_codec_remove),
+       .remove = pm860x_codec_remove,
 };
 
 module_platform_driver(pm860x_codec_driver);
index b92759a3936157e0884b98f752935ccbef7b8945..3a847828932ae01e13b2be5ca8f587c0048f17eb 100644 (file)
@@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_LM4857 if I2C
        select SND_SOC_LM49453 if I2C
        select SND_SOC_MAX98088 if I2C
+       select SND_SOC_MAX98090 if I2C
        select SND_SOC_MAX98095 if I2C
        select SND_SOC_MAX9850 if I2C
        select SND_SOC_MAX9768 if I2C
@@ -54,6 +55,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_PCM3008
        select SND_SOC_RT5631 if I2C
        select SND_SOC_SGTL5000 if I2C
+       select SND_SOC_SI476X if MFD_SI476X_CORE
        select SND_SOC_SN95031 if INTEL_SCU_IPC
        select SND_SOC_SPDIF
        select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
@@ -146,6 +148,13 @@ config SND_SOC_WM_HUBS
        default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
        default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
 
+config SND_SOC_WM_ADSP
+       tristate
+       default y if SND_SOC_WM5102=y
+       default y if SND_SOC_WM2200=y
+       default m if SND_SOC_WM5102=m
+       default m if SND_SOC_WM2200=m
+
 config SND_SOC_AB8500_CODEC
        tristate
 
@@ -229,6 +238,7 @@ config SND_SOC_CX20442
        tristate
 
 config SND_SOC_JZ4740_CODEC
+       select REGMAP_MMIO
        tristate
 
 config SND_SOC_L3
@@ -258,6 +268,9 @@ config SND_SOC_LM49453
 config SND_SOC_MAX98088
        tristate
 
+config SND_SOC_MAX98090
+       tristate
+
 config SND_SOC_MAX98095
        tristate
 
@@ -277,6 +290,9 @@ config SND_SOC_RT5631
 config SND_SOC_SGTL5000
        tristate
 
+config SND_SOC_SI476X
+       tristate
+
 config SND_SOC_SIGMADSP
        tristate
        select CRC32
index 9bd4d95aab4ffcecb9abf5bff4e0c94d7203adee..f6e8e36cceb77b60d5c34fc5bec54ece440c6653 100644 (file)
@@ -34,6 +34,7 @@ snd-soc-lm4857-objs := lm4857.o
 snd-soc-lm49453-objs := lm49453.o
 snd-soc-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
+snd-soc-max98090-objs := max98090.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
@@ -45,6 +46,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5632-objs := alc5632.o
 snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-si476x-objs := si476x.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-tx-objs := spdif_transciever.o
 snd-soc-spdif-rx-objs := spdif_receiver.o
@@ -62,6 +64,7 @@ snd-soc-twl6040-objs := twl6040.o
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
+snd-soc-wm-adsp-objs := wm_adsp.o
 snd-soc-wm0010-objs := wm0010.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
@@ -155,6 +158,7 @@ obj-$(CONFIG_SND_SOC_LM4857)        += snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_LM49453)   += snd-soc-lm49453.o
 obj-$(CONFIG_SND_SOC_MAX9768)  += snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
+obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
 obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)  += snd-soc-mc13783.o
@@ -164,6 +168,7 @@ obj-$(CONFIG_SND_SOC_PCM3008)       += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_RT5631)   += snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SI476X)   += snd-soc-si476x.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
@@ -229,6 +234,7 @@ obj-$(CONFIG_SND_SOC_WM9090)        += snd-soc-wm9090.o
 obj-$(CONFIG_SND_SOC_WM9705)   += snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_WM_ADSP)  += snd-soc-wm-adsp.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
 
 # Amp
index af547490b4f7f6e0b1dbada793259c64a513a203..6c12ac206ee9ab8f2d4fc018c22e3e45bb2365d1 100644 (file)
@@ -2356,7 +2356,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
        return 0;
 }
 
-struct snd_soc_dai_driver ab8500_codec_dai[] = {
+static struct snd_soc_dai_driver ab8500_codec_dai[] = {
        {
                .name = "ab8500-codec-dai.0",
                .id = 0,
@@ -2554,7 +2554,7 @@ static struct snd_soc_codec_driver ab8500_codec_driver = {
        .num_dapm_routes =      ARRAY_SIZE(ab8500_dapm_routes),
 };
 
-static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
+static int ab8500_codec_driver_probe(struct platform_device *pdev)
 {
        int status;
        struct ab8500_codec_drvdata *drvdata;
@@ -2580,7 +2580,7 @@ static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
        return status;
 }
 
-static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev)
+static int ab8500_codec_driver_remove(struct platform_device *pdev)
 {
        dev_info(&pdev->dev, "%s Enter.\n", __func__);
 
@@ -2595,7 +2595,7 @@ static struct platform_driver ab8500_codec_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ab8500_codec_driver_probe,
-       .remove         = __devexit_p(ab8500_codec_driver_remove),
+       .remove         = ab8500_codec_driver_remove,
        .suspend        = NULL,
        .resume         = NULL,
 };
index ea06b834a7de45c216e8922927a7aad892be411b..ef2ae32ffc669849bbfb791eb657ed4ff2501497 100644 (file)
@@ -118,13 +118,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
        .resume =       ac97_soc_resume,
 };
 
-static __devinit int ac97_probe(struct platform_device *pdev)
+static int ac97_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_ac97, &ac97_dai, 1);
 }
 
-static int __devexit ac97_remove(struct platform_device *pdev)
+static int ac97_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -137,7 +137,7 @@ static struct platform_driver ac97_codec_driver = {
        },
 
        .probe = ac97_probe,
-       .remove = __devexit_p(ac97_remove),
+       .remove = ac97_remove,
 };
 
 module_platform_driver(ac97_codec_driver);
index dce6ebeef4527cfb176063e91c90a9a741ee3f89..9a92b7962f41b67e3ba8461d1a88c584ef4822b0 100644 (file)
@@ -360,7 +360,7 @@ static const struct regmap_config ad1836_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit ad1836_spi_probe(struct spi_device *spi)
+static int ad1836_spi_probe(struct spi_device *spi)
 {
        struct ad1836_priv *ad1836;
        int ret;
@@ -383,7 +383,7 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit ad1836_spi_remove(struct spi_device *spi)
+static int ad1836_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -405,7 +405,7 @@ static struct spi_driver ad1836_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad1836_spi_probe,
-       .remove         = __devexit_p(ad1836_spi_remove),
+       .remove         = ad1836_spi_remove,
        .id_table       = ad1836_ids,
 };
 
index 2f752660f6789760381aaec5f0391aac94b33bde..aea7e52cf714117a445347cbe528f6732d2bd662 100644 (file)
@@ -378,7 +378,7 @@ static const struct regmap_config ad193x_spi_regmap_config = {
        .volatile_reg = adau193x_reg_volatile,
 };
 
-static int __devinit ad193x_spi_probe(struct spi_device *spi)
+static int ad193x_spi_probe(struct spi_device *spi)
 {
        struct ad193x_priv *ad193x;
 
@@ -397,7 +397,7 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi)
                        &ad193x_dai, 1);
 }
 
-static int __devexit ad193x_spi_remove(struct spi_device *spi)
+static int ad193x_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -409,7 +409,7 @@ static struct spi_driver ad193x_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad193x_spi_probe,
-       .remove         = __devexit_p(ad193x_spi_remove),
+       .remove         = ad193x_spi_remove,
 };
 #endif
 
@@ -430,8 +430,8 @@ static const struct i2c_device_id ad193x_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ad193x_id);
 
-static int __devinit ad193x_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int ad193x_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
 {
        struct ad193x_priv *ad193x;
 
@@ -450,7 +450,7 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client,
                        &ad193x_dai, 1);
 }
 
-static int __devexit ad193x_i2c_remove(struct i2c_client *client)
+static int ad193x_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -461,7 +461,7 @@ static struct i2c_driver ad193x_i2c_driver = {
                .name = "ad193x",
        },
        .probe    = ad193x_i2c_probe,
-       .remove   = __devexit_p(ad193x_i2c_remove),
+       .remove   = ad193x_i2c_remove,
        .id_table = ad193x_id,
 };
 #endif
index 8c39dddd7d0063d90adcf587c5e6dc19c37f73ad..f385342947d33317118d924fd5a88c44e3b9532c 100644 (file)
@@ -255,13 +255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
        .read = ac97_read,
 };
 
-static __devinit int ad1980_probe(struct platform_device *pdev)
+static int ad1980_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_ad1980, &ad1980_dai, 1);
 }
 
-static int __devexit ad1980_remove(struct platform_device *pdev)
+static int ad1980_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -274,7 +274,7 @@ static struct platform_driver ad1980_codec_driver = {
        },
 
        .probe = ad1980_probe,
-       .remove = __devexit_p(ad1980_remove),
+       .remove = ad1980_remove,
 };
 
 module_platform_driver(ad1980_codec_driver);
index ee7a68dcefd2442b1650b16395025bc2eed39990..b1f2baf42b48233678ae051bea1bd2b9fb747327 100644 (file)
@@ -47,7 +47,7 @@ static int ad73311_probe(struct platform_device *pdev)
                        &soc_codec_dev_ad73311, &ad73311_dai, 1);
 }
 
-static int __devexit ad73311_remove(struct platform_device *pdev)
+static int ad73311_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -60,7 +60,7 @@ static struct platform_driver ad73311_codec_driver = {
        },
 
        .probe = ad73311_probe,
-       .remove = __devexit_p(ad73311_remove),
+       .remove = ad73311_remove,
 };
 
 module_platform_driver(ad73311_codec_driver);
index 704544bfc90dc564c774593ee7d0300098c47d6c..068b3ae56a1767c8242ea9b454f15ca7f045dcea 100644 (file)
@@ -1353,8 +1353,8 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
        .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes),
 };
 
-static int __devinit adau1373_i2c_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
+static int adau1373_i2c_probe(struct i2c_client *client,
+                             const struct i2c_device_id *id)
 {
        struct adau1373 *adau1373;
        int ret;
@@ -1370,7 +1370,7 @@ static int __devinit adau1373_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static int __devexit adau1373_i2c_remove(struct i2c_client *client)
+static int adau1373_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1388,7 +1388,7 @@ static struct i2c_driver adau1373_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = adau1373_i2c_probe,
-       .remove = __devexit_p(adau1373_i2c_remove),
+       .remove = adau1373_i2c_remove,
        .id_table = adau1373_i2c_id,
 };
 
index 51f2f3cd81364658d0b78d48c7baddb7cac5abd2..dafdbe87edeb56d82369db5f310658a25298ee17 100644 (file)
@@ -489,8 +489,8 @@ static struct snd_soc_codec_driver adau1701_codec_drv = {
        .set_sysclk             = adau1701_set_sysclk,
 };
 
-static __devinit int adau1701_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int adau1701_i2c_probe(struct i2c_client *client,
+                             const struct i2c_device_id *id)
 {
        struct adau1701 *adau1701;
        int ret;
@@ -505,7 +505,7 @@ static __devinit int adau1701_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static __devexit int adau1701_i2c_remove(struct i2c_client *client)
+static int adau1701_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -523,7 +523,7 @@ static struct i2c_driver adau1701_i2c_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = adau1701_i2c_probe,
-       .remove         = __devexit_p(adau1701_i2c_remove),
+       .remove         = adau1701_i2c_remove,
        .id_table       = adau1701_i2c_id,
 };
 
index ebd7b37b902bb4019dee2059a633c120d20cc4f7..3c839cc4e00ecb48a5e3948567c14dbede7706a3 100644 (file)
@@ -839,8 +839,8 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
        .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
 };
 
-static int __devinit adav80x_bus_probe(struct device *dev,
-               enum snd_soc_control_type control_type)
+static int adav80x_bus_probe(struct device *dev,
+                            enum snd_soc_control_type control_type)
 {
        struct adav80x *adav80x;
        int ret;
@@ -860,7 +860,7 @@ static int __devinit adav80x_bus_probe(struct device *dev,
        return ret;
 }
 
-static int __devexit adav80x_bus_remove(struct device *dev)
+static int adav80x_bus_remove(struct device *dev)
 {
        snd_soc_unregister_codec(dev);
        kfree(dev_get_drvdata(dev));
@@ -868,12 +868,12 @@ static int __devexit adav80x_bus_remove(struct device *dev)
 }
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit adav80x_spi_probe(struct spi_device *spi)
+static int adav80x_spi_probe(struct spi_device *spi)
 {
        return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
 }
 
-static int __devexit adav80x_spi_remove(struct spi_device *spi)
+static int adav80x_spi_remove(struct spi_device *spi)
 {
        return adav80x_bus_remove(&spi->dev);
 }
@@ -884,7 +884,7 @@ static struct spi_driver adav80x_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = adav80x_spi_probe,
-       .remove         = __devexit_p(adav80x_spi_remove),
+       .remove         = adav80x_spi_remove,
 };
 #endif
 
@@ -895,13 +895,13 @@ static const struct i2c_device_id adav80x_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, adav80x_id);
 
-static int __devinit adav80x_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int adav80x_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
 {
        return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
 }
 
-static int __devexit adav80x_i2c_remove(struct i2c_client *client)
+static int adav80x_i2c_remove(struct i2c_client *client)
 {
        return adav80x_bus_remove(&client->dev);
 }
@@ -912,7 +912,7 @@ static struct i2c_driver adav80x_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = adav80x_i2c_probe,
-       .remove = __devexit_p(adav80x_i2c_remove),
+       .remove = adav80x_i2c_remove,
        .id_table = adav80x_id,
 };
 #endif
index 8103b938b8c001214858e9a628ae60908424cde3..506d474c4d2227372b6b8e4a6743ca8f67ef7da3 100644 (file)
@@ -36,13 +36,13 @@ static struct snd_soc_dai_driver ads117x_dai = {
 
 static struct snd_soc_codec_driver soc_codec_dev_ads117x;
 
-static __devinit int ads117x_probe(struct platform_device *pdev)
+static int ads117x_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_ads117x, &ads117x_dai, 1);
 }
 
-static int __devexit ads117x_remove(struct platform_device *pdev)
+static int ads117x_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -55,7 +55,7 @@ static struct platform_driver ads117x_codec_driver = {
        },
 
        .probe = ads117x_probe,
-       .remove = __devexit_p(ads117x_remove),
+       .remove = ads117x_remove,
 };
 
 module_platform_driver(ads117x_codec_driver);
index 31d4483245d0db951584a0e1619b91c8ac8fa726..6f6c335a5baab15d93466a212cc63d0b71ea7197 100644 (file)
@@ -15,6 +15,8 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <linux/spi/spi.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <sound/asoundef.h>
 
 /* AK4104 registers addresses */
@@ -98,14 +100,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
        val = 0;
 
        switch (params_rate(params)) {
+       case 22050:
+               val |= IEC958_AES3_CON_FS_22050;
+               break;
+       case 24000:
+               val |= IEC958_AES3_CON_FS_24000;
+               break;
+       case 32000:
+               val |= IEC958_AES3_CON_FS_32000;
+               break;
        case 44100:
                val |= IEC958_AES3_CON_FS_44100;
                break;
        case 48000:
                val |= IEC958_AES3_CON_FS_48000;
                break;
-       case 32000:
-               val |= IEC958_AES3_CON_FS_32000;
+       case 88200:
+               val |= IEC958_AES3_CON_FS_88200;
+               break;
+       case 96000:
+               val |= IEC958_AES3_CON_FS_96000;
+               break;
+       case 176400:
+               val |= IEC958_AES3_CON_FS_176400;
+               break;
+       case 192000:
+               val |= IEC958_AES3_CON_FS_192000;
                break;
        default:
                dev_err(codec->dev, "unsupported sampling rate\n");
@@ -186,6 +206,7 @@ static const struct regmap_config ak4104_regmap = {
 
 static int ak4104_spi_probe(struct spi_device *spi)
 {
+       struct device_node *np = spi->dev.of_node;
        struct ak4104_private *ak4104;
        unsigned int val;
        int ret;
@@ -201,52 +222,62 @@ static int ak4104_spi_probe(struct spi_device *spi)
        if (ak4104 == NULL)
                return -ENOMEM;
 
-       ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+       ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
        if (IS_ERR(ak4104->regmap)) {
                ret = PTR_ERR(ak4104->regmap);
                return ret;
        }
 
+       if (np) {
+               enum of_gpio_flags flags;
+               int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
+
+               if (gpio_is_valid(gpio)) {
+                       ret = devm_gpio_request_one(&spi->dev, gpio,
+                                    flags & OF_GPIO_ACTIVE_LOW ?
+                                       GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+                                    "ak4104 reset");
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
        /* read the 'reserved' register - according to the datasheet, it
         * should contain 0x5b. Not a good way to verify the presence of
         * the device, but there is no hardware ID register. */
        ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
        if (ret != 0)
-               goto err;
-       if (val != AK4104_RESERVED_VAL) {
-               ret = -ENODEV;
-               goto err;
-       }
+               return ret;
+       if (val != AK4104_RESERVED_VAL)
+               return -ENODEV;
 
        spi_set_drvdata(spi, ak4104);
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_device_ak4104, &ak4104_dai, 1);
-       if (ret != 0)
-               goto err;
-
-       return 0;
-
-err:
-       regmap_exit(ak4104->regmap);
        return ret;
 }
 
-static int __devexit ak4104_spi_remove(struct spi_device *spi)
+static int ak4104_spi_remove(struct spi_device *spi)
 {
-       struct ak4104_private *ak4101 = spi_get_drvdata(spi);
-       regmap_exit(ak4101->regmap);
        snd_soc_unregister_codec(&spi->dev);
        return 0;
 }
 
+static const struct of_device_id ak4104_of_match[] = {
+       { .compatible = "asahi-kasei,ak4104", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ak4104_of_match);
+
 static struct spi_driver ak4104_spi_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = ak4104_of_match,
        },
        .probe  = ak4104_spi_probe,
-       .remove = __devexit_p(ak4104_spi_remove),
+       .remove = ak4104_spi_remove,
 };
 
 module_spi_driver(ak4104_spi_driver);
index 618fdc30f73eb3889f2372e4bba9033d3675270d..684fe910669fd884f04e3900c03fc3631773e821 100644 (file)
@@ -436,8 +436,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
        .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
 };
 
-static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int ak4535_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct ak4535_priv *ak4535;
        int ret;
@@ -447,7 +447,7 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
        if (ak4535 == NULL)
                return -ENOMEM;
 
-       ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+       ak4535->regmap = devm_regmap_init_i2c(i2c, &ak4535_regmap);
        if (IS_ERR(ak4535->regmap)) {
                ret = PTR_ERR(ak4535->regmap);
                dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -458,18 +458,13 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_ak4535, &ak4535_dai, 1);
-       if (ret != 0)
-               regmap_exit(ak4535->regmap);
 
        return ret;
 }
 
-static __devexit int ak4535_i2c_remove(struct i2c_client *client)
+static int ak4535_i2c_remove(struct i2c_client *client)
 {
-       struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(ak4535->regmap);
        return 0;
 }
 
@@ -485,7 +480,7 @@ static struct i2c_driver ak4535_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    ak4535_i2c_probe,
-       .remove =   __devexit_p(ak4535_i2c_remove),
+       .remove =   ak4535_i2c_remove,
        .id_table = ak4535_i2c_id,
 };
 
index 543a12f471be65a70c9b88a529c9d2dd42f8b7ed..5f9af1fb76e862a1fb2eb4e73176d47cccf4aef8 100644 (file)
@@ -557,8 +557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
 };
 
 
-static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int ak4641_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct ak4641_platform_data *pdata = i2c->dev.platform_data;
        struct ak4641_priv *ak4641;
@@ -610,7 +610,7 @@ err_out:
        return ret;
 }
 
-static int __devexit ak4641_i2c_remove(struct i2c_client *i2c)
+static int ak4641_i2c_remove(struct i2c_client *i2c)
 {
        struct ak4641_platform_data *pdata = i2c->dev.platform_data;
 
@@ -640,7 +640,7 @@ static struct i2c_driver ak4641_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    ak4641_i2c_probe,
-       .remove =   __devexit_p(ak4641_i2c_remove),
+       .remove =   ak4641_i2c_remove,
        .id_table = ak4641_i2c_id,
 };
 
index b3e24f289421a7fda3dda11043039179c4777535..1f0cdab03294725b4ba02f6a28e4b6ce68eb6e89 100644 (file)
@@ -194,12 +194,6 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
        {"LINEOUT Mixer", "DACL", "DAC"},
 };
 
-/* codec private data */
-struct ak4642_priv {
-       unsigned int sysclk;
-       enum snd_soc_control_type control_type;
-};
-
 /*
  * ak4642 register cache
  */
@@ -468,10 +462,9 @@ static int ak4642_resume(struct snd_soc_codec *codec)
 
 static int ak4642_probe(struct snd_soc_codec *codec)
 {
-       struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -520,27 +513,15 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int ak4642_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
-       struct ak4642_priv *ak4642;
-       int ret;
-
-       ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv),
-                             GFP_KERNEL);
-       if (!ak4642)
-               return -ENOMEM;
-
-       i2c_set_clientdata(i2c, ak4642);
-       ak4642->control_type = SND_SOC_I2C;
-
-       ret =  snd_soc_register_codec(&i2c->dev,
+       return snd_soc_register_codec(&i2c->dev,
                                (struct snd_soc_codec_driver *)id->driver_data,
                                &ak4642_dai, 1);
-       return ret;
 }
 
-static __devexit int ak4642_i2c_remove(struct i2c_client *client)
+static int ak4642_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -560,7 +541,7 @@ static struct i2c_driver ak4642_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = ak4642_i2c_probe,
-       .remove         = __devexit_p(ak4642_i2c_remove),
+       .remove         = ak4642_i2c_remove,
        .id_table       = ak4642_i2c_id,
 };
 #endif
index 2b457976a7bff0f18ada9248acdc0c25b4bd82cd..25bdf6ad4a546c16363381a1a4922c4a334ea48d 100644 (file)
@@ -655,8 +655,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
        .num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
 };
 
-static int __devinit ak4671_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int ak4671_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
 {
        struct ak4671_priv *ak4671;
        int ret;
@@ -674,7 +674,7 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static __devexit int ak4671_i2c_remove(struct i2c_client *client)
+static int ak4671_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -692,7 +692,7 @@ static struct i2c_driver ak4671_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ak4671_i2c_probe,
-       .remove = __devexit_p(ak4671_i2c_remove),
+       .remove = ak4671_i2c_remove,
        .id_table = ak4671_i2c_id,
 };
 
index 1960478ce6bb883dbf02af92e242e2b538ea8823..256c364193a54ea6864adbf79640b3480983285a 100644 (file)
@@ -991,8 +991,8 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
  *    low  = 0x1a
  *    high = 0x1b
  */
-static __devinit int alc5623_i2c_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int alc5623_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
 {
        struct alc5623_platform_data *pdata;
        struct alc5623_priv *alc5623;
@@ -1058,7 +1058,7 @@ static __devinit int alc5623_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static __devexit int alc5623_i2c_remove(struct i2c_client *client)
+static int alc5623_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1079,7 +1079,7 @@ static struct i2c_driver alc5623_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = alc5623_i2c_probe,
-       .remove =  __devexit_p(alc5623_i2c_remove),
+       .remove =  alc5623_i2c_remove,
        .id_table = alc5623_i2c_table,
 };
 
index 7dd02420b36d3976f21b86ac8e50f0af0372a36f..f2e62e45f91288916a252486a4ac130c5d7dd022 100644 (file)
@@ -1116,8 +1116,8 @@ static struct regmap_config alc5632_regmap = {
  *    low  = 0x1a
  *    high = 0x1b
  */
-static __devinit int alc5632_i2c_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int alc5632_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
 {
        struct alc5632_priv *alc5632;
        int ret, ret1, ret2;
@@ -1179,7 +1179,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static __devexit int alc5632_i2c_remove(struct i2c_client *client)
+static int alc5632_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1198,7 +1198,7 @@ static struct i2c_driver alc5632_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = alc5632_i2c_probe,
-       .remove =  __devexit_p(alc5632_i2c_remove),
+       .remove =  alc5632_i2c_remove,
        .id_table = alc5632_i2c_table,
 };
 
index 054967d8bac2f6d089214e390b1bd6ce416f64b2..adf397b9d0e650eb19768e7bc6c592352014a595 100644 (file)
@@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
 
+static const char *arizona_vol_ramp_text[] = {
+       "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+       "15ms/6dB", "30ms/6dB",
+};
+
+const struct soc_enum arizona_in_vd_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+                       ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
+
+const struct soc_enum arizona_in_vi_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+                       ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
+
+const struct soc_enum arizona_out_vd_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+                       ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
+
+const struct soc_enum arizona_out_vi_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+                       ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
+
 static const char *arizona_lhpf_mode_text[] = {
        "Low-pass", "High-pass"
 };
@@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
        case 49152000:
                val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
                break;
+       case 67737600:
+       case 73728000:
+               val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
+       case 90316800:
+       case 98304000:
+               val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
+       case 135475200:
+       case 147456000:
+               val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
        default:
                return -EINVAL;
        }
@@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
                return -EBUSY;
        }
 
+       dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
+               arizona_dai_clk_str(clk_id));
+
        memset(&routes, 0, sizeof(routes));
        routes[0].sink = dai->driver->capture.stream_name;
        routes[1].sink = dai->driver->playback.stream_name;
@@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
        routes[1].source = arizona_dai_clk_str(clk_id);
        snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
 
+       dai_priv->clk = clk_id;
+
        return snd_soc_dapm_sync(&codec->dapm);
 }
 
@@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
        bool ena;
        int ret;
 
+       if (fll->fref == Fref && fll->fout == Fout)
+               return 0;
+
        ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
        if (ret != 0) {
                arizona_fll_err(fll, "Failed to read current state: %d\n",
@@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
                if (ena)
                        pm_runtime_put_autosuspend(arizona->dev);
 
+               fll->fref = Fref;
+               fll->fout = Fout;
+
                return 0;
        }
 
@@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
                                   ARIZONA_FLL1_SYNC_ENA);
 
        ret = wait_for_completion_timeout(&fll->ok,
-                                         msecs_to_jiffies(25));
+                                         msecs_to_jiffies(250));
        if (ret == 0)
                arizona_fll_warn(fll, "Timed out waiting for lock\n");
 
+       fll->fref = Fref;
+       fll->fout = Fout;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll);
index 36ec64946120077455ab218c85aef34eaa29ef9a..41dae1ed3b714a4734448b1d3c99938af1fe9d9a 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <sound/soc.h>
 
+#include "wm_adsp.h"
+
 #define ARIZONA_CLK_SYSCLK         1
 #define ARIZONA_CLK_ASYNCCLK       2
 #define ARIZONA_CLK_OPCLK          3
 #define ARIZONA_MIXER_VOL_SHIFT                 1
 #define ARIZONA_MIXER_VOL_WIDTH                 7
 
-#define ARIZONA_MAX_DAI 3
+#define ARIZONA_MAX_DAI  4
+#define ARIZONA_MAX_ADSP 4
 
 struct arizona;
+struct wm_adsp;
 
 struct arizona_dai_priv {
        int clk;
 };
 
 struct arizona_priv {
+       struct wm_adsp adsp[ARIZONA_MAX_ADSP];
        struct arizona *arizona;
        int sysclk;
        int asyncclk;
@@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        const struct snd_kcontrol_new name##_mux =      \
                SOC_DAPM_VALUE_ENUM("Route", name##_enum)
 
+#define ARIZONA_MUX_ENUMS(name, base_reg) \
+       static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg);      \
+       static ARIZONA_MUX_CTL_DECL(name)
+
 #define ARIZONA_MIXER_ENUMS(name, base_reg) \
-       static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
-       static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
-       static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
-       static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
-       static ARIZONA_MUX_CTL_DECL(name##_in1); \
-       static ARIZONA_MUX_CTL_DECL(name##_in2); \
-       static ARIZONA_MUX_CTL_DECL(name##_in3); \
-       static ARIZONA_MUX_CTL_DECL(name##_in4)
+       ARIZONA_MUX_ENUMS(name##_in1, base_reg);     \
+       ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \
+       ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \
+       ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6)
+
+#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
+       ARIZONA_MUX_ENUMS(name##_aux1, base_reg);       \
+       ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8);   \
+       ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16);  \
+       ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24);  \
+       ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32);  \
+       ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
 
 #define ARIZONA_MUX(name, ctrl) \
        SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
+#define ARIZONA_MUX_WIDGETS(name, name_str) \
+       ARIZONA_MUX(name_str " Input", &name##_mux)
+
 #define ARIZONA_MIXER_WIDGETS(name, name_str)  \
        ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
        ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
@@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define ARIZONA_DSP_WIDGETS(name, name_str) \
+       ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
+       ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
+       ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
+
+#define ARIZONA_MUX_ROUTES(name) \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Input")
+
 #define ARIZONA_MIXER_ROUTES(widget, name) \
        { widget, NULL, name " Mixer" },         \
        { name " Mixer", NULL, name " Input 1" }, \
@@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define ARIZONA_DSP_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
+       ARIZONA_MIXER_ROUTES(name, name "L"), \
+       ARIZONA_MIXER_ROUTES(name, name "R")
+
+extern const struct soc_enum arizona_in_vi_ramp;
+extern const struct soc_enum arizona_in_vd_ramp;
+
+extern const struct soc_enum arizona_out_vi_ramp;
+extern const struct soc_enum arizona_out_vd_ramp;
+
 extern const struct soc_enum arizona_lhpf1_mode;
 extern const struct soc_enum arizona_lhpf2_mode;
 extern const struct soc_enum arizona_lhpf3_mode;
@@ -146,6 +197,8 @@ struct arizona_fll {
        unsigned int vco_mult;
        struct completion lock;
        struct completion ok;
+       unsigned int fref;
+       unsigned int fout;
 
        char lock_name[ARIZONA_FLL_NAME_LEN];
        char clock_ok_name[ARIZONA_FLL_NAME_LEN];
index 064cd6a935163ebf4fa0619b80f67154e1733528..23316c887b19211f7c7473767b956895abda397f 100644 (file)
@@ -201,7 +201,7 @@ static struct platform_driver cq93vc_codec_driver = {
        },
 
        .probe = cq93vc_platform_probe,
-       .remove = __devexit_p(cq93vc_platform_remove),
+       .remove = cq93vc_platform_remove,
 };
 
 module_platform_driver(cq93vc_codec_driver);
index e3f0a7f3131e14b7895aadf2daf8bf81f6058d8b..4f1127935fdf5f9578970b13fcf73b8815d469e5 100644 (file)
@@ -474,15 +474,25 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
        int ret;
        int gpio_nreset = -EINVAL;
+       int amutec_eq_bmutec = 0;
 
 #ifdef CONFIG_OF
-       if (of_match_device(cs4271_dt_ids, codec->dev))
+       if (of_match_device(cs4271_dt_ids, codec->dev)) {
                gpio_nreset = of_get_named_gpio(codec->dev->of_node,
                                                "reset-gpio", 0);
+
+               if (!of_get_property(codec->dev->of_node,
+                                    "cirrus,amutec-eq-bmutec", NULL))
+                       amutec_eq_bmutec = 1;
+       }
 #endif
 
-       if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
-               gpio_nreset = cs4271plat->gpio_nreset;
+       if (cs4271plat) {
+               if (gpio_is_valid(cs4271plat->gpio_nreset))
+                       gpio_nreset = cs4271plat->gpio_nreset;
+
+               amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+       }
 
        if (gpio_nreset >= 0)
                if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        /* Power-up sequence requires 85 uS */
        udelay(85);
 
+       if (amutec_eq_bmutec)
+               snd_soc_update_bits(codec, CS4271_MODE2,
+                                   CS4271_MODE2_MUTECAEQUB,
+                                   CS4271_MODE2_MUTECAEQUB);
+
        return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
                ARRAY_SIZE(cs4271_snd_controls));
 }
@@ -555,7 +570,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit cs4271_spi_probe(struct spi_device *spi)
+static int cs4271_spi_probe(struct spi_device *spi)
 {
        struct cs4271_private *cs4271;
 
@@ -570,7 +585,7 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
                &cs4271_dai, 1);
 }
 
-static int __devexit cs4271_spi_remove(struct spi_device *spi)
+static int cs4271_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -583,7 +598,7 @@ static struct spi_driver cs4271_spi_driver = {
                .of_match_table = of_match_ptr(cs4271_dt_ids),
        },
        .probe          = cs4271_spi_probe,
-       .remove         = __devexit_p(cs4271_spi_remove),
+       .remove         = cs4271_spi_remove,
 };
 #endif /* defined(CONFIG_SPI_MASTER) */
 
@@ -594,8 +609,8 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
 
-static int __devinit cs4271_i2c_probe(struct i2c_client *client,
-                                     const struct i2c_device_id *id)
+static int cs4271_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
 {
        struct cs4271_private *cs4271;
 
@@ -610,7 +625,7 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
                &cs4271_dai, 1);
 }
 
-static int __devexit cs4271_i2c_remove(struct i2c_client *client)
+static int cs4271_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -624,7 +639,7 @@ static struct i2c_driver cs4271_i2c_driver = {
        },
        .id_table       = cs4271_i2c_id,
        .probe          = cs4271_i2c_probe,
-       .remove         = __devexit_p(cs4271_i2c_remove),
+       .remove         = cs4271_i2c_remove,
 };
 #endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
 
index 97a81051e88d125c9937057e3b51324a7bb0f9ae..99bb1c69499e42a6791ae12c55dde2d53efb7f49 100644 (file)
@@ -1271,7 +1271,7 @@ static struct i2c_driver cs42l52_i2c_driver = {
        },
        .id_table = cs42l52_id,
        .probe =    cs42l52_i2c_probe,
-       .remove =   __devexit_p(cs42l52_i2c_remove),
+       .remove =   cs42l52_i2c_remove,
 };
 
 module_i2c_driver(cs42l52_i2c_driver);
index 2c08c4cb465a1995b5b8897c72fea887dcdfbe80..a0791ecf6d95e64514b5320717b586f83c32d7ac 100644 (file)
@@ -1345,8 +1345,8 @@ static struct regmap_config cs42l73_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
-                                      const struct i2c_device_id *id)
+static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+                            const struct i2c_device_id *id)
 {
        struct cs42l73_private *cs42l73;
        int ret;
@@ -1406,7 +1406,7 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
        return 0;
 }
 
-static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
+static int cs42l73_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1426,7 +1426,7 @@ static struct i2c_driver cs42l73_i2c_driver = {
                   },
        .id_table = cs42l73_id,
        .probe = cs42l73_i2c_probe,
-       .remove = __devexit_p(cs42l73_i2c_remove),
+       .remove = cs42l73_i2c_remove,
 
 };
 
index af5db70805199e81b06e7d48a8e844ae504489b2..9c12314565024fcb80d5091a6fc57a6dddf0555b 100644 (file)
@@ -1218,8 +1218,8 @@ static const struct regmap_config da7210_regmap_config_i2c = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int da7210_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct da7210_priv *da7210;
        int ret;
@@ -1231,7 +1231,7 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, da7210);
 
-       da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
+       da7210->regmap = devm_regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
        if (IS_ERR(da7210->regmap)) {
                ret = PTR_ERR(da7210->regmap);
                dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
@@ -1245,24 +1245,15 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_da7210, &da7210_dai, 1);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
-               goto err_regmap;
-       }
-       return ret;
-
-err_regmap:
-       regmap_exit(da7210->regmap);
 
        return ret;
 }
 
-static int __devexit da7210_i2c_remove(struct i2c_client *client)
+static int da7210_i2c_remove(struct i2c_client *client)
 {
-       struct da7210_priv *da7210 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(da7210->regmap);
        return 0;
 }
 
@@ -1279,7 +1270,7 @@ static struct i2c_driver da7210_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = da7210_i2c_probe,
-       .remove         = __devexit_p(da7210_i2c_remove),
+       .remove         = da7210_i2c_remove,
        .id_table       = da7210_i2c_id,
 };
 #endif
@@ -1323,7 +1314,7 @@ static const struct regmap_config da7210_regmap_config_spi = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit da7210_spi_probe(struct spi_device *spi)
+static int da7210_spi_probe(struct spi_device *spi)
 {
        struct da7210_priv *da7210;
        int ret;
@@ -1346,24 +1337,15 @@ static int __devinit da7210_spi_probe(struct spi_device *spi)
        if (ret != 0)
                dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret);
 
-       ret =  snd_soc_register_codec(&spi->dev,
+       ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_da7210, &da7210_dai, 1);
-       if (ret < 0)
-               goto err_regmap;
-
-       return ret;
-
-err_regmap:
-       regmap_exit(da7210->regmap);
 
        return ret;
 }
 
-static int __devexit da7210_spi_remove(struct spi_device *spi)
+static int da7210_spi_remove(struct spi_device *spi)
 {
-       struct da7210_priv *da7210 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(da7210->regmap);
        return 0;
 }
 
@@ -1373,7 +1355,7 @@ static struct spi_driver da7210_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = da7210_spi_probe,
-       .remove = __devexit_p(da7210_spi_remove)
+       .remove = da7210_spi_remove
 };
 #endif
 
index 01be2a320e21b71b1932a95d376031b943200129..dc0284dc9e6f85dde0fa61819b5e86145f55d608 100644 (file)
@@ -1557,8 +1557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
        .reg_cache_size         = ARRAY_SIZE(da732x_reg_cache),
 };
 
-static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int da732x_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct da732x_priv *da732x;
        unsigned int reg;
@@ -1596,7 +1596,7 @@ err:
        return ret;
 }
 
-static __devexit int da732x_i2c_remove(struct i2c_client *client)
+static int da732x_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -1615,7 +1615,7 @@ static struct i2c_driver da732x_i2c_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = da732x_i2c_probe,
-       .remove         = __devexit_p(da732x_i2c_remove),
+       .remove         = da732x_i2c_remove,
        .id_table       = da732x_i2c_id,
 };
 
index f379b085c39204dfeb2a6fc34d7c07d9f15c9f0b..fc9802d1281dcad0d8ba57ea9d62a02322b5864a 100644 (file)
 #define DA9055_AIF_FORMAT_I2S_MODE     (0 << 0)
 #define DA9055_AIF_FORMAT_LEFT_J       (1 << 0)
 #define DA9055_AIF_FORMAT_RIGHT_J      (2 << 0)
+#define DA9055_AIF_FORMAT_DSP          (3 << 0)
 #define DA9055_AIF_WORD_S16_LE         (0 << 2)
 #define DA9055_AIF_WORD_S20_3LE                (1 << 2)
 #define DA9055_AIF_WORD_S24_LE         (2 << 2)
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = {
                        6, 1, 0),
 };
 
+/* Headphone Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_hp_l_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0);
+
+static const struct snd_kcontrol_new da9055_dapm_hp_r_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0);
+
+/* Lineout Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_lineout_control =
+SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0);
+
 /* DAPM widgets */
 static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
        /* Input Side */
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
                           &da9055_dapm_mixoutr_controls[0],
                           ARRAY_SIZE(da9055_dapm_mixoutr_controls)),
 
+       /* Output Enable Switches */
+       SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_l_control),
+       SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_r_control),
+       SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_lineout_control),
+
        /* Output PGAs */
        SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0),
        SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0),
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = {
        {"Out Mixer Right", "DAC Right Switch", "DAC Right"},
 
        {"MIXOUT Left", NULL, "Out Mixer Left"},
-       {"Headphone Left", NULL, "MIXOUT Left"},
+       {"Headphone Left Enable", "Switch", "MIXOUT Left"},
+       {"Headphone Left", NULL, "Headphone Left Enable"},
        {"Headphone Left", NULL, "Charge Pump"},
        {"HPL", NULL, "Headphone Left"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Headphone Right", NULL, "MIXOUT Right"},
+       {"Headphone Right Enable", "Switch", "MIXOUT Right"},
+       {"Headphone Right", NULL, "Headphone Right Enable"},
        {"Headphone Right", NULL, "Charge Pump"},
        {"HPR", NULL, "Headphone Right"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Lineout", NULL, "MIXOUT Right"},
+       {"Lineout Enable", "Switch", "MIXOUT Right"},
+       {"Lineout", NULL, "Lineout Enable"},
        {"LINE", NULL, "Lineout"},
 };
 
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_RIGHT_J:
                aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J;
                break;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif_ctrl = DA9055_AIF_FORMAT_DSP;
+               break;
        default:
                return -EINVAL;
        }
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
                            DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
 
        /*
-        * There are two separate control bits for input and output mixers as
-        * well as headphone and line outs.
+        * There are two separate control bits for input and output mixers.
         * One to enable corresponding amplifier and other to enable its
         * output. As amplifier bits are related to power control, they are
         * being managed by DAPM while other (non power related) bits are
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL,
                            DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN);
 
-       snd_soc_update_bits(codec, DA9055_HP_L_CTRL,
-                           DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE);
-       snd_soc_update_bits(codec, DA9055_HP_R_CTRL,
-                           DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE);
-
-       snd_soc_update_bits(codec, DA9055_LINE_CTRL,
-                           DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE);
-
        /* Set this as per your system configuration */
        snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ);
 
@@ -1467,8 +1484,8 @@ static const struct regmap_config da9055_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int da9055_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct da9055_priv *da9055;
        struct da9055_platform_data *pdata = dev_get_platdata(&i2c->dev);
@@ -1500,7 +1517,7 @@ static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit da9055_remove(struct i2c_client *client)
+static int da9055_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1519,7 +1536,7 @@ static struct i2c_driver da9055_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = da9055_i2c_probe,
-       .remove         = __devexit_p(da9055_remove),
+       .remove         = da9055_remove,
        .id_table       = da9055_i2c_id,
 };
 
index bfe46aa90362fe262b7894d0bd9451ad3042f23f..4f4f7f41a7d11b5fa79245f06474d27d54fe3e47 100644 (file)
@@ -33,13 +33,13 @@ static struct snd_soc_dai_driver dfbmcs320_dai = {
 
 static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320;
 
-static int __devinit dfbmcs320_probe(struct platform_device *pdev)
+static int dfbmcs320_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320,
                        &dfbmcs320_dai, 1);
 }
 
-static int __devexit dfbmcs320_remove(struct platform_device *pdev)
+static int dfbmcs320_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
 
@@ -52,7 +52,7 @@ static struct platform_driver dfmcs320_driver = {
                .owner = THIS_MODULE,
        },
        .probe = dfbmcs320_probe,
-       .remove = __devexit_p(dfbmcs320_remove),
+       .remove = dfbmcs320_remove,
 };
 
 module_platform_driver(dfmcs320_driver);
index 3e929f079a1f0eb4b3fa472482d68503703da8c4..66967ba6f7576c8f1fc816bb7e894f3e7799e3a2 100644 (file)
@@ -66,13 +66,13 @@ static struct snd_soc_codec_driver soc_dmic = {
        .probe  = dmic_probe,
 };
 
-static int __devinit dmic_dev_probe(struct platform_device *pdev)
+static int dmic_dev_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_dmic, &dmic_dai, 1);
 }
 
-static int __devexit dmic_dev_remove(struct platform_device *pdev)
+static int dmic_dev_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -86,7 +86,7 @@ static struct platform_driver dmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = dmic_dev_probe,
-       .remove = __devexit_p(dmic_dev_remove),
+       .remove = dmic_dev_remove,
 };
 
 module_platform_driver(dmic_driver);
index 1bf55602c9ebf2ecf97ca2912a99815a5e707493..53b455b8c07a76dfabd63e46d2ca934a418061bb 100644 (file)
@@ -1119,8 +1119,8 @@ static const struct regmap_config isabelle_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
-                                       const struct i2c_device_id *id)
+static int isabelle_i2c_probe(struct i2c_client *i2c,
+                             const struct i2c_device_id *id)
 {
        struct regmap *isabelle_regmap;
        int ret = 0;
@@ -1145,7 +1145,7 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit isabelle_i2c_remove(struct i2c_client *client)
+static int isabelle_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1163,7 +1163,7 @@ static struct i2c_driver isabelle_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = isabelle_i2c_probe,
-       .remove = __devexit_p(isabelle_i2c_remove),
+       .remove = isabelle_i2c_remove,
        .id_table = isabelle_i2c_id,
 };
 
index 85d9cabe6d555d9e28e3812f1d97f631434ff461..d991529e1aff1a021210b8887a35b2b609601130 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/regmap.h>
 
 #include <linux/delay.h>
 
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/tlv.h>
 
 #define JZ4740_REG_CODEC_1 0x0
-#define JZ4740_REG_CODEC_2 0x1
+#define JZ4740_REG_CODEC_2 0x4
 
 #define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
 #define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
 #define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET    4
 #define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET  0
 
-static const uint32_t jz4740_codec_regs[] = {
-       0x021b2302, 0x00170803,
+static const struct reg_default jz4740_codec_reg_defaults[] = {
+       { JZ4740_REG_CODEC_1, 0x021b2302 },
+       { JZ4740_REG_CODEC_2, 0x00170803 },
 };
 
 struct jz4740_codec {
-       void __iomem *base;
-       struct resource *mem;
+       struct regmap *regmap;
 };
 
-static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
-       return readl(jz4740_codec->base + (reg << 2));
-}
-
-static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int val)
-{
-       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
-       u32 *cache = codec->reg_cache;
-
-       cache[reg] = val;
-       writel(val, jz4740_codec->base + (reg << 2));
+static const unsigned int jz4740_mic_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 2, TLV_DB_SCALE_ITEM(0, 600, 0),
+       3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0),
+};
 
-       return 0;
-}
+static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0);
+static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0);
 
 static const struct snd_kcontrol_new jz4740_codec_controls[] = {
-       SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
-                       JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
-       SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2,
-                       JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
+       SOC_SINGLE_TLV("Master Playback Volume", JZ4740_REG_CODEC_2,
+                       JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0,
+                       jz4740_out_tlv),
+       SOC_SINGLE_TLV("Master Capture Volume", JZ4740_REG_CODEC_2,
+                       JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0,
+                       jz4740_in_tlv),
        SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
                        JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
-       SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
-                       JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
+       SOC_SINGLE_TLV("Mic Capture Volume", JZ4740_REG_CODEC_2,
+                       JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0,
+                       jz4740_mic_tlv),
 };
 
 static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
@@ -163,8 +158,8 @@ static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
 static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
+       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(dai->codec);
        uint32_t val;
-       struct snd_soc_codec *codec = dai->codec;
 
        switch (params_rate(params)) {
        case 8000:
@@ -200,7 +195,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
 
        val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
 
-       snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
+       regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_2,
                                JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
 
        return 0;
@@ -230,25 +225,23 @@ static struct snd_soc_dai_driver jz4740_codec_dai = {
        .symmetric_rates = 1,
 };
 
-static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
+static void jz4740_codec_wakeup(struct regmap *regmap)
 {
-       int i;
-       uint32_t *cache = codec->reg_cache;
-
-       snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+       regmap_update_bits(regmap, JZ4740_REG_CODEC_1,
                JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
        udelay(2);
 
-       snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+       regmap_update_bits(regmap, JZ4740_REG_CODEC_1,
                JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
 
-       for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i)
-               jz4740_codec_write(codec, i, cache[i]);
+       regcache_sync(regmap);
 }
 
 static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+       struct regmap *regmap = jz4740_codec->regmap;
        unsigned int mask;
        unsigned int value;
 
@@ -261,12 +254,12 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
                                JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
                value = 0;
 
-               snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+               regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
                break;
        case SND_SOC_BIAS_STANDBY:
                /* The only way to clear the suspend flag is to reset the codec */
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
-                       jz4740_codec_wakeup(codec);
+                       jz4740_codec_wakeup(regmap);
 
                mask = JZ4740_CODEC_1_VREF_DISABLE |
                        JZ4740_CODEC_1_VREF_AMP_DISABLE |
@@ -275,13 +268,14 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
                        JZ4740_CODEC_1_VREF_AMP_DISABLE |
                        JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
 
-               snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+               regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
                break;
        case SND_SOC_BIAS_OFF:
                mask = JZ4740_CODEC_1_SUSPEND;
                value = JZ4740_CODEC_1_SUSPEND;
 
-               snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+               regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
+               regcache_mark_dirty(regmap);
                break;
        default:
                break;
@@ -294,7 +288,9 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
 
 static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
 {
-       snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+
+       regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1,
                        JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
 
        jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -331,12 +327,7 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
        .remove = jz4740_codec_dev_remove,
        .suspend = jz4740_codec_suspend,
        .resume = jz4740_codec_resume,
-       .read = jz4740_codec_read,
-       .write = jz4740_codec_write,
        .set_bias_level = jz4740_codec_set_bias_level,
-       .reg_cache_default      = jz4740_codec_regs,
-       .reg_word_size = sizeof(u32),
-       .reg_cache_size = 2,
 
        .controls = jz4740_codec_controls,
        .num_controls = ARRAY_SIZE(jz4740_codec_controls),
@@ -346,11 +337,23 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
        .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes),
 };
 
-static int __devinit jz4740_codec_probe(struct platform_device *pdev)
+static const struct regmap_config jz4740_codec_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = JZ4740_REG_CODEC_2,
+
+       .reg_defaults = jz4740_codec_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(jz4740_codec_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int jz4740_codec_probe(struct platform_device *pdev)
 {
        int ret;
        struct jz4740_codec *jz4740_codec;
        struct resource *mem;
+       void __iomem *base;
 
        jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec),
                                    GFP_KERNEL);
@@ -358,56 +361,29 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
-               ret = -ENOENT;
-               goto err_out;
-       }
-
-       mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
-       if (!mem) {
-               dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-               ret = -EBUSY;
-               goto err_out;
-       }
+       base = devm_request_and_ioremap(&pdev->dev, mem);
+       if (!base)
+               return -EBUSY;
 
-       jz4740_codec->base = ioremap(mem->start, resource_size(mem));
-       if (!jz4740_codec->base) {
-               dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
-               ret = -EBUSY;
-               goto err_release_mem_region;
-       }
-       jz4740_codec->mem = mem;
+       jz4740_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                           &jz4740_codec_regmap_config);
+       if (IS_ERR(jz4740_codec->regmap))
+               return PTR_ERR(jz4740_codec->regmap);
 
        platform_set_drvdata(pdev, jz4740_codec);
 
        ret = snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
-       if (ret) {
+       if (ret)
                dev_err(&pdev->dev, "Failed to register codec\n");
-               goto err_iounmap;
-       }
 
-       return 0;
-
-err_iounmap:
-       iounmap(jz4740_codec->base);
-err_release_mem_region:
-       release_mem_region(mem->start, resource_size(mem));
-err_out:
        return ret;
 }
 
-static int __devexit jz4740_codec_remove(struct platform_device *pdev)
+static int jz4740_codec_remove(struct platform_device *pdev)
 {
-       struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
-       struct resource *mem = jz4740_codec->mem;
-
        snd_soc_unregister_codec(&pdev->dev);
 
-       iounmap(jz4740_codec->base);
-       release_mem_region(mem->start, resource_size(mem));
-
        platform_set_drvdata(pdev, NULL);
 
        return 0;
@@ -415,7 +391,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
 
 static struct platform_driver jz4740_codec_driver = {
        .probe = jz4740_codec_probe,
-       .remove = __devexit_p(jz4740_codec_remove),
+       .remove = jz4740_codec_remove,
        .driver = {
                .name = "jz4740-codec",
                .owner = THIS_MODULE,
index 81a328c78838250c952609275af6888e875e6057..9f9f59573f721344995233da13ddf875f43436fc 100644 (file)
@@ -209,8 +209,8 @@ static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
        .set_bias_level = lm4857_set_bias_level,
 };
 
-static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
-       const struct i2c_device_id *id)
+static int lm4857_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct lm4857 *lm4857;
        int ret;
@@ -228,7 +228,7 @@ static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
+static int lm4857_i2c_remove(struct i2c_client *i2c)
 {
        snd_soc_unregister_codec(&i2c->dev);
        return 0;
@@ -246,7 +246,7 @@ static struct i2c_driver lm4857_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = lm4857_i2c_probe,
-       .remove = __devexit_p(lm4857_i2c_remove),
+       .remove = lm4857_i2c_remove,
        .id_table = lm4857_i2c_id,
 };
 
index 99b0a9dcff346ac68b3915ae320b60645cb6a01f..d75257d40a496d26e9bb513f6fd000abe6f13a76 100644 (file)
@@ -1483,8 +1483,8 @@ static const struct regmap_config lm49453_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
-                                      const struct i2c_device_id *id)
+static int lm49453_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
 {
        struct lm49453_priv *lm49453;
        int ret = 0;
@@ -1497,7 +1497,7 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, lm49453);
 
-       lm49453->regmap = regmap_init_i2c(i2c, &lm49453_regmap_config);
+       lm49453->regmap = devm_regmap_init_i2c(i2c, &lm49453_regmap_config);
        if (IS_ERR(lm49453->regmap)) {
                ret = PTR_ERR(lm49453->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -1508,21 +1508,15 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
        ret =  snd_soc_register_codec(&i2c->dev,
                                      &soc_codec_dev_lm49453,
                                      lm49453_dai, ARRAY_SIZE(lm49453_dai));
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
-               regmap_exit(lm49453->regmap);
-               return ret;
-       }
 
        return ret;
 }
 
-static int __devexit lm49453_i2c_remove(struct i2c_client *client)
+static int lm49453_i2c_remove(struct i2c_client *client)
 {
-       struct lm49453_priv *lm49453 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(lm49453->regmap);
        return 0;
 }
 
@@ -1538,7 +1532,7 @@ static struct i2c_driver lm49453_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = lm49453_i2c_probe,
-       .remove = __devexit_p(lm49453_i2c_remove),
+       .remove = lm49453_i2c_remove,
        .id_table = lm49453_i2c_id,
 };
 
index 17b3ec2d05cb1ebade50fe27eb95b4a62dfbfc20..a6ac2313047def253ddc0ff4ebddde4947803c1b 100644 (file)
@@ -159,8 +159,8 @@ static const struct regmap_config max9768_i2c_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit max9768_i2c_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
+static int max9768_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
 {
        struct max9768 *max9768;
        struct max9768_pdata *pdata = client->dev.platform_data;
@@ -187,7 +187,7 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, max9768);
 
-       max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+       max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config);
        if (IS_ERR(max9768->regmap)) {
                err = PTR_ERR(max9768->regmap);
                goto err_gpio_free;
@@ -195,12 +195,10 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
 
        err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
        if (err)
-               goto err_regmap_free;
+               goto err_gpio_free;
 
        return 0;
 
- err_regmap_free:
-       regmap_exit(max9768->regmap);
  err_gpio_free:
        if (gpio_is_valid(max9768->shdn_gpio))
                gpio_free(max9768->shdn_gpio);
@@ -210,12 +208,11 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
        return err;
 }
 
-static int __devexit max9768_i2c_remove(struct i2c_client *client)
+static int max9768_i2c_remove(struct i2c_client *client)
 {
        struct max9768 *max9768 = i2c_get_clientdata(client);
 
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(max9768->regmap);
 
        if (gpio_is_valid(max9768->shdn_gpio))
                gpio_free(max9768->shdn_gpio);
@@ -237,7 +234,7 @@ static struct i2c_driver max9768_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max9768_i2c_probe,
-       .remove = __devexit_p(max9768_i2c_remove),
+       .remove = max9768_i2c_remove,
        .id_table = max9768_i2c_id,
 };
 module_i2c_driver(max9768_i2c_driver);
index 3264a5169306fc3f8d769912173f803fae3d17a4..a4c16fd70f77546450851951245f803ec4bf004c 100644 (file)
@@ -2084,7 +2084,7 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit max98088_i2c_remove(struct i2c_client *client)
+static int max98088_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -2098,13 +2098,13 @@ static const struct i2c_device_id max98088_i2c_id[] = {
 MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
 
 static struct i2c_driver max98088_i2c_driver = {
-       .driver = {
-               .name = "max98088",
-               .owner = THIS_MODULE,
-       },
-       .probe  = max98088_i2c_probe,
-       .remove = __devexit_p(max98088_i2c_remove),
-       .id_table = max98088_i2c_id,
+       .driver = {
+               .name = "max98088",
+               .owner = THIS_MODULE,
+       },
+       .probe  = max98088_i2c_probe,
+       .remove = max98088_i2c_remove,
+       .id_table = max98088_i2c_id,
 };
 
 module_i2c_driver(max98088_i2c_driver);
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
new file mode 100644 (file)
index 0000000..c9772ca
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * max98090.c -- MAX98090 ALSA SoC Audio driver
+ * based on Rev0p8 datasheet
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on
+ *
+ * max98095.c
+ * Copyright 2011 Maxim Integrated Products
+ *
+ * https://github.com/hardkernel/linux/commit/\
+ *     3417d7166b17113b3b33b0a337c74d1c7cc313df#sound/soc/codecs/max98090.c
+ * Copyright 2011 Maxim Integrated Products
+ *
+ * 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/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+/*
+ *
+ * MAX98090 Registers Definition
+ *
+ */
+
+/* RESET / STATUS / INTERRUPT REGISTERS */
+#define MAX98090_0x00_SW_RESET         0x00
+#define MAX98090_0x01_INT_STS          0x01
+#define MAX98090_0x02_JACK_STS         0x02
+#define MAX98090_0x03_INT_MASK         0x03
+
+/* QUICK SETUP REGISTERS */
+#define MAX98090_0x04_SYS_CLK          0x04
+#define MAX98090_0x05_SAMPLE_RATE      0x05
+#define MAX98090_0x06_DAI_IF           0x06
+#define MAX98090_0x07_DAC_PATH         0x07
+#define MAX98090_0x08_MIC_TO_ADC       0x08
+#define MAX98090_0x09_LINE_TO_ADC      0x09
+#define MAX98090_0x0A_ANALOG_MIC_LOOP  0x0A
+#define MAX98090_0x0B_ANALOG_LINE_LOOP 0x0B
+
+/* ANALOG INPUT CONFIGURATION REGISTERS */
+#define MAX98090_0x0D_INPUT_CONFIG     0x0D
+#define MAX98090_0x0E_LINE_IN_LVL      0x0E
+#define MAX98090_0x0F_LINI_IN_CFG      0x0F
+#define MAX98090_0x10_MIC1_IN_LVL      0x10
+#define MAX98090_0x11_MIC2_IN_LVL      0x11
+
+/* MICROPHONE CONFIGURATION REGISTERS  */
+#define MAX98090_0x12_MIC_BIAS_VOL     0x12
+#define MAX98090_0x13_DIGITAL_MIC_CFG  0x13
+#define MAX98090_0x14_DIGITAL_MIC_MODE 0x14
+
+/* ADC PATH AND CONFIGURATION REGISTERS */
+#define MAX98090_0x15_L_ADC_MIX                0x15
+#define MAX98090_0x16_R_ADC_MIX                0x16
+#define MAX98090_0x17_L_ADC_LVL                0x17
+#define MAX98090_0x18_R_ADC_LVL                0x18
+#define MAX98090_0x19_ADC_BIQUAD_LVL   0x19
+#define MAX98090_0x1A_ADC_SIDETONE     0x1A
+
+/* CLOCK CONFIGURATION REGISTERS */
+#define MAX98090_0x1B_SYS_CLK          0x1B
+#define MAX98090_0x1C_CLK_MODE         0x1C
+#define MAX98090_0x1D_ANY_CLK1         0x1D
+#define MAX98090_0x1E_ANY_CLK2         0x1E
+#define MAX98090_0x1F_ANY_CLK3         0x1F
+#define MAX98090_0x20_ANY_CLK4         0x20
+#define MAX98090_0x21_MASTER_MODE      0x21
+
+/* INTERFACE CONTROL REGISTERS */
+#define MAX98090_0x22_DAI_IF_FMT       0x22
+#define MAX98090_0x23_DAI_TDM_FMT1     0x23
+#define MAX98090_0x24_DAI_TDM_FMT2     0x24
+#define MAX98090_0x25_DAI_IO_CFG       0x25
+#define MAX98090_0x26_FILTER_CFG       0x26
+#define MAX98090_0x27_DAI_PLAYBACK_LVL 0x27
+#define MAX98090_0x28_EQ_PLAYBACK_LVL  0x28
+
+/* HEADPHONE CONTROL REGISTERS */
+#define MAX98090_0x29_L_HP_MIX         0x29
+#define MAX98090_0x2A_R_HP_MIX         0x2A
+#define MAX98090_0x2B_HP_CTR           0x2B
+#define MAX98090_0x2C_L_HP_VOL         0x2C
+#define MAX98090_0x2D_R_HP_VOL         0x2D
+
+/* SPEAKER CONFIGURATION REGISTERS */
+#define MAX98090_0x2E_L_SPK_MIX                0x2E
+#define MAX98090_0x2F_R_SPK_MIX                0x2F
+#define MAX98090_0x30_SPK_CTR          0x30
+#define MAX98090_0x31_L_SPK_VOL                0x31
+#define MAX98090_0x32_R_SPK_VOL                0x32
+
+/* ALC CONFIGURATION REGISTERS */
+#define MAX98090_0x33_ALC_TIMING       0x33
+#define MAX98090_0x34_ALC_COMPRESSOR   0x34
+#define MAX98090_0x35_ALC_EXPANDER     0x35
+#define MAX98090_0x36_ALC_GAIN         0x36
+
+/* RECEIVER AND LINE_OUTPUT REGISTERS */
+#define MAX98090_0x37_RCV_LOUT_L_MIX   0x37
+#define MAX98090_0x38_RCV_LOUT_L_CNTL  0x38
+#define MAX98090_0x39_RCV_LOUT_L_VOL   0x39
+#define MAX98090_0x3A_LOUT_R_MIX       0x3A
+#define MAX98090_0x3B_LOUT_R_CNTL      0x3B
+#define MAX98090_0x3C_LOUT_R_VOL       0x3C
+
+/* JACK DETECT AND ENABLE REGISTERS */
+#define MAX98090_0x3D_JACK_DETECT      0x3D
+#define MAX98090_0x3E_IN_ENABLE                0x3E
+#define MAX98090_0x3F_OUT_ENABLE       0x3F
+#define MAX98090_0x40_LVL_CTR          0x40
+#define MAX98090_0x41_DSP_FILTER_ENABLE        0x41
+
+/* BIAS AND POWER MODE CONFIGURATION REGISTERS */
+#define MAX98090_0x42_BIAS_CTR         0x42
+#define MAX98090_0x43_DAC_CTR          0x43
+#define MAX98090_0x44_ADC_CTR          0x44
+#define MAX98090_0x45_DEV_SHUTDOWN     0x45
+
+/* REVISION ID REGISTER */
+#define MAX98090_0xFF_REV_ID           0xFF
+
+#define MAX98090_REG_MAX_CACHED                0x45
+#define MAX98090_REG_END               0xFF
+
+/*
+ *
+ * MAX98090 Registers Bit Fields
+ *
+ */
+
+/* MAX98090_0x06_DAI_IF */
+#define MAX98090_DAI_IF_MASK           0x3F
+#define MAX98090_RJ_M                  (1 << 5)
+#define MAX98090_RJ_S                  (1 << 4)
+#define MAX98090_LJ_M                  (1 << 3)
+#define MAX98090_LJ_S                  (1 << 2)
+#define MAX98090_I2S_M                 (1 << 1)
+#define MAX98090_I2S_S                 (1 << 0)
+
+/* MAX98090_0x45_DEV_SHUTDOWN */
+#define MAX98090_SHDNRUN               (1 << 7)
+
+/* codec private data */
+struct max98090_priv {
+       struct regmap *regmap;
+};
+
+static const struct reg_default max98090_reg_defaults[] = {
+       /* RESET / STATUS / INTERRUPT REGISTERS */
+       {MAX98090_0x00_SW_RESET,                0x00},
+       {MAX98090_0x01_INT_STS,                 0x00},
+       {MAX98090_0x02_JACK_STS,                0x00},
+       {MAX98090_0x03_INT_MASK,                0x04},
+
+       /* QUICK SETUP REGISTERS */
+       {MAX98090_0x04_SYS_CLK,                 0x00},
+       {MAX98090_0x05_SAMPLE_RATE,             0x00},
+       {MAX98090_0x06_DAI_IF,                  0x00},
+       {MAX98090_0x07_DAC_PATH,                0x00},
+       {MAX98090_0x08_MIC_TO_ADC,              0x00},
+       {MAX98090_0x09_LINE_TO_ADC,             0x00},
+       {MAX98090_0x0A_ANALOG_MIC_LOOP,         0x00},
+       {MAX98090_0x0B_ANALOG_LINE_LOOP,        0x00},
+
+       /* ANALOG INPUT CONFIGURATION REGISTERS */
+       {MAX98090_0x0D_INPUT_CONFIG,            0x00},
+       {MAX98090_0x0E_LINE_IN_LVL,             0x1B},
+       {MAX98090_0x0F_LINI_IN_CFG,             0x00},
+       {MAX98090_0x10_MIC1_IN_LVL,             0x11},
+       {MAX98090_0x11_MIC2_IN_LVL,             0x11},
+
+       /* MICROPHONE CONFIGURATION REGISTERS  */
+       {MAX98090_0x12_MIC_BIAS_VOL,            0x00},
+       {MAX98090_0x13_DIGITAL_MIC_CFG,         0x00},
+       {MAX98090_0x14_DIGITAL_MIC_MODE,        0x00},
+
+       /* ADC PATH AND CONFIGURATION REGISTERS */
+       {MAX98090_0x15_L_ADC_MIX,               0x00},
+       {MAX98090_0x16_R_ADC_MIX,               0x00},
+       {MAX98090_0x17_L_ADC_LVL,               0x03},
+       {MAX98090_0x18_R_ADC_LVL,               0x03},
+       {MAX98090_0x19_ADC_BIQUAD_LVL,          0x00},
+       {MAX98090_0x1A_ADC_SIDETONE,            0x00},
+
+       /* CLOCK CONFIGURATION REGISTERS */
+       {MAX98090_0x1B_SYS_CLK,                 0x00},
+       {MAX98090_0x1C_CLK_MODE,                0x00},
+       {MAX98090_0x1D_ANY_CLK1,                0x00},
+       {MAX98090_0x1E_ANY_CLK2,                0x00},
+       {MAX98090_0x1F_ANY_CLK3,                0x00},
+       {MAX98090_0x20_ANY_CLK4,                0x00},
+       {MAX98090_0x21_MASTER_MODE,             0x00},
+
+       /* INTERFACE CONTROL REGISTERS */
+       {MAX98090_0x22_DAI_IF_FMT,              0x00},
+       {MAX98090_0x23_DAI_TDM_FMT1,            0x00},
+       {MAX98090_0x24_DAI_TDM_FMT2,            0x00},
+       {MAX98090_0x25_DAI_IO_CFG,              0x00},
+       {MAX98090_0x26_FILTER_CFG,              0x80},
+       {MAX98090_0x27_DAI_PLAYBACK_LVL,        0x00},
+       {MAX98090_0x28_EQ_PLAYBACK_LVL,         0x00},
+
+       /* HEADPHONE CONTROL REGISTERS */
+       {MAX98090_0x29_L_HP_MIX,                0x00},
+       {MAX98090_0x2A_R_HP_MIX,                0x00},
+       {MAX98090_0x2B_HP_CTR,                  0x00},
+       {MAX98090_0x2C_L_HP_VOL,                0x1A},
+       {MAX98090_0x2D_R_HP_VOL,                0x1A},
+
+       /* SPEAKER CONFIGURATION REGISTERS */
+       {MAX98090_0x2E_L_SPK_MIX,               0x00},
+       {MAX98090_0x2F_R_SPK_MIX,               0x00},
+       {MAX98090_0x30_SPK_CTR,                 0x00},
+       {MAX98090_0x31_L_SPK_VOL,               0x2C},
+       {MAX98090_0x32_R_SPK_VOL,               0x2C},
+
+       /* ALC CONFIGURATION REGISTERS */
+       {MAX98090_0x33_ALC_TIMING,              0x00},
+       {MAX98090_0x34_ALC_COMPRESSOR,          0x00},
+       {MAX98090_0x35_ALC_EXPANDER,            0x00},
+       {MAX98090_0x36_ALC_GAIN,                0x00},
+
+       /* RECEIVER AND LINE_OUTPUT REGISTERS */
+       {MAX98090_0x37_RCV_LOUT_L_MIX,          0x00},
+       {MAX98090_0x38_RCV_LOUT_L_CNTL,         0x00},
+       {MAX98090_0x39_RCV_LOUT_L_VOL,          0x15},
+       {MAX98090_0x3A_LOUT_R_MIX,              0x00},
+       {MAX98090_0x3B_LOUT_R_CNTL,             0x00},
+       {MAX98090_0x3C_LOUT_R_VOL,              0x15},
+
+       /* JACK DETECT AND ENABLE REGISTERS */
+       {MAX98090_0x3D_JACK_DETECT,             0x00},
+       {MAX98090_0x3E_IN_ENABLE,               0x00},
+       {MAX98090_0x3F_OUT_ENABLE,              0x00},
+       {MAX98090_0x40_LVL_CTR,                 0x00},
+       {MAX98090_0x41_DSP_FILTER_ENABLE,       0x00},
+
+       /* BIAS AND POWER MODE CONFIGURATION REGISTERS */
+       {MAX98090_0x42_BIAS_CTR,                0x00},
+       {MAX98090_0x43_DAC_CTR,                 0x00},
+       {MAX98090_0x44_ADC_CTR,                 0x06},
+       {MAX98090_0x45_DEV_SHUTDOWN,            0x00},
+};
+
+static const unsigned int max98090_hp_tlv[] = {
+       TLV_DB_RANGE_HEAD(5),
+       0x0,    0x6,    TLV_DB_SCALE_ITEM(-6700, 400, 0),
+       0x7,    0xE,    TLV_DB_SCALE_ITEM(-4000, 300, 0),
+       0xF,    0x15,   TLV_DB_SCALE_ITEM(-1700, 200, 0),
+       0x16,   0x1B,   TLV_DB_SCALE_ITEM(-400, 100, 0),
+       0x1C,   0x1F,   TLV_DB_SCALE_ITEM(150, 50, 0),
+};
+
+static struct snd_kcontrol_new max98090_snd_controls[] = {
+       SOC_DOUBLE_R_TLV("Headphone Volume", MAX98090_0x2C_L_HP_VOL,
+                        MAX98090_0x2D_R_HP_VOL, 0, 31, 0, max98090_hp_tlv),
+};
+
+/* Left HeadPhone Mixer Switch */
+static struct snd_kcontrol_new max98090_left_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x29_L_HP_MIX, 1, 1, 0),
+       SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x29_L_HP_MIX, 0, 1, 0),
+};
+
+/* Right HeadPhone Mixer Switch */
+static struct snd_kcontrol_new max98090_right_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x2A_R_HP_MIX, 1, 1, 0),
+       SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x2A_R_HP_MIX, 0, 1, 0),
+};
+
+static struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
+       /* Output */
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+
+       /* PGA */
+       SND_SOC_DAPM_PGA("HPL Out", MAX98090_0x3F_OUT_ENABLE, 7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HPR Out", MAX98090_0x3F_OUT_ENABLE, 6, 0, NULL, 0),
+
+       /* Mixer */
+       SND_SOC_DAPM_MIXER("HPL Mixer", SND_SOC_NOPM, 0, 0,
+                          max98090_left_hp_mixer_controls,
+                          ARRAY_SIZE(max98090_left_hp_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("HPR Mixer", SND_SOC_NOPM, 0, 0,
+                          max98090_right_hp_mixer_controls,
+                          ARRAY_SIZE(max98090_right_hp_mixer_controls)),
+
+       /* DAC */
+       SND_SOC_DAPM_DAC("DACL", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 0, 0),
+       SND_SOC_DAPM_DAC("DACR", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 1, 0),
+};
+
+static struct snd_soc_dapm_route max98090_audio_map[] = {
+       /* Output */
+       {"HPL", NULL, "HPL Out"},
+       {"HPR", NULL, "HPR Out"},
+
+       /* PGA */
+       {"HPL Out", NULL, "HPL Mixer"},
+       {"HPR Out", NULL, "HPR Mixer"},
+
+       /* Mixer*/
+       {"HPL Mixer", "DACR Switch", "DACR"},
+       {"HPL Mixer", "DACL Switch", "DACL"},
+
+       {"HPR Mixer", "DACR Switch", "DACR"},
+       {"HPR Mixer", "DACL Switch", "DACL"},
+};
+
+static bool max98090_volatile(struct device *dev, unsigned int reg)
+{
+       if ((reg == MAX98090_0x01_INT_STS)      ||
+           (reg == MAX98090_0x02_JACK_STS)     ||
+           (reg >  MAX98090_REG_MAX_CACHED))
+               return true;
+
+       return false;
+}
+
+static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params,
+               struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       unsigned int val;
+
+       switch (params_rate(params)) {
+       case 96000:
+               val = 1 << 5;
+               break;
+       case 32000:
+               val = 1 << 4;
+               break;
+       case 48000:
+               val = 1 << 3;
+               break;
+       case 44100:
+               val = 1 << 2;
+               break;
+       case 16000:
+               val = 1 << 1;
+               break;
+       case 8000:
+               val = 1 << 0;
+               break;
+       default:
+               dev_err(codec->dev, "unsupported rate\n");
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, MAX98090_0x05_SAMPLE_RATE, 0x03F, val);
+
+       return 0;
+}
+
+static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       unsigned int val;
+
+       snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+                           MAX98090_SHDNRUN, 0);
+
+       switch (freq) {
+       case 26000000:
+               val = 1 << 7;
+               break;
+       case 19200000:
+               val = 1 << 6;
+               break;
+       case 13000000:
+               val = 1 << 5;
+               break;
+       case 12288000:
+               val = 1 << 4;
+               break;
+       case 12000000:
+               val = 1 << 3;
+               break;
+       case 11289600:
+               val = 1 << 2;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid master clock frequency\n");
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, MAX98090_0x04_SYS_CLK, 0xFD, val);
+
+       snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+                           MAX98090_SHDNRUN, MAX98090_SHDNRUN);
+
+       dev_dbg(dai->dev, "sysclk is %uHz\n", freq);
+
+       return 0;
+}
+
+static int max98090_dai_set_fmt(struct snd_soc_dai *dai,
+                               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int is_master;
+       u8 val;
+
+       /* master/slave mode */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               is_master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               is_master = 0;
+               break;
+       default:
+               dev_err(codec->dev, "unsupported clock\n");
+               return -EINVAL;
+       }
+
+       /* format */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               val = (is_master) ? MAX98090_I2S_M : MAX98090_I2S_S;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               val = (is_master) ? MAX98090_RJ_M : MAX98090_RJ_S;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               val = (is_master) ? MAX98090_LJ_M : MAX98090_LJ_S;
+               break;
+       default:
+               dev_err(codec->dev, "unsupported format\n");
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, MAX98090_0x06_DAI_IF,
+                           MAX98090_DAI_IF_MASK, val);
+
+       return 0;
+}
+
+#define MAX98090_RATES SNDRV_PCM_RATE_8000_96000
+#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops max98090_dai_ops = {
+       .set_sysclk     = max98090_dai_set_sysclk,
+       .set_fmt        = max98090_dai_set_fmt,
+       .hw_params      = max98090_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver max98090_dai = {
+       .name = "max98090-Hifi",
+       .playback = {
+               .stream_name    = "Playback",
+               .channels_min   = 1,
+               .channels_max   = 2,
+               .rates          = MAX98090_RATES,
+               .formats        = MAX98090_FORMATS,
+       },
+       .ops = &max98090_dai_ops,
+};
+
+static int max98090_probe(struct snd_soc_codec *codec)
+{
+       struct max98090_priv *priv = snd_soc_codec_get_drvdata(codec);
+       struct device *dev = codec->dev;
+       int ret;
+
+       codec->control_data = priv->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+       if (ret < 0) {
+               dev_err(dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       /* Device active */
+       snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+                           MAX98090_SHDNRUN, MAX98090_SHDNRUN);
+
+       return 0;
+}
+
+static int max98090_remove(struct snd_soc_codec *codec)
+{
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98090 = {
+       .probe                  = max98090_probe,
+       .remove                 = max98090_remove,
+       .controls               = max98090_snd_controls,
+       .num_controls           = ARRAY_SIZE(max98090_snd_controls),
+       .dapm_widgets           = max98090_dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(max98090_dapm_widgets),
+       .dapm_routes            = max98090_audio_map,
+       .num_dapm_routes        = ARRAY_SIZE(max98090_audio_map),
+};
+
+static const struct regmap_config max98090_regmap = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = MAX98090_REG_END,
+       .volatile_reg           = max98090_volatile,
+       .cache_type             = REGCACHE_RBTREE,
+       .reg_defaults           = max98090_reg_defaults,
+       .num_reg_defaults       = ARRAY_SIZE(max98090_reg_defaults),
+};
+
+static int max98090_i2c_probe(struct i2c_client *i2c,
+                             const struct i2c_device_id *id)
+{
+       struct max98090_priv *priv;
+       struct device *dev = &i2c->dev;
+       unsigned int val;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(struct max98090_priv),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
+       if (IS_ERR(priv->regmap)) {
+               ret = PTR_ERR(priv->regmap);
+               dev_err(dev, "Failed to init regmap: %d\n", ret);
+               return ret;
+       }
+
+       i2c_set_clientdata(i2c, priv);
+
+       ret = regmap_read(priv->regmap, MAX98090_0xFF_REV_ID, &val);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read device revision: %d\n", ret);
+               return ret;
+       }
+       dev_info(dev, "revision 0x%02x\n", val);
+
+       ret = snd_soc_register_codec(dev,
+                                    &soc_codec_dev_max98090,
+                                    &max98090_dai, 1);
+
+       return ret;
+}
+
+static int max98090_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       return 0;
+}
+
+static const struct i2c_device_id max98090_i2c_id[] = {
+       { "max98090", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
+
+static struct i2c_driver max98090_i2c_driver = {
+       .driver = {
+               .name = "max98090",
+               .owner = THIS_MODULE,
+       },
+       .probe          = max98090_i2c_probe,
+       .remove         = max98090_i2c_remove,
+       .id_table       = max98090_i2c_id,
+};
+module_i2c_driver(max98090_i2c_driver);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98090 driver");
+MODULE_AUTHOR("Peter Hsiang, Kuninori Morimoto");
+MODULE_LICENSE("GPL");
index 38d43c59d3f4cfbc67cc11f2d86af73f8ae910b9..41cdd164297046c3045c9463ab6183810e02a126 100644 (file)
@@ -2511,7 +2511,7 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit max98095_i2c_remove(struct i2c_client *client)
+static int max98095_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -2529,7 +2529,7 @@ static struct i2c_driver max98095_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe  = max98095_i2c_probe,
-       .remove = __devexit_p(max98095_i2c_remove),
+       .remove = max98095_i2c_remove,
        .id_table = max98095_i2c_id,
 };
 
index efe535c37b39eb82f110e76328f3345fb3fdd10e..58c38a5b481ccb7658a8a6a285d5874d13659d50 100644 (file)
@@ -329,8 +329,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
        .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes),
 };
 
-static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
-               const struct i2c_device_id *id)
+static int max9850_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
 {
        struct max9850_priv *max9850;
        int ret;
@@ -347,7 +347,7 @@ static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int max9850_i2c_remove(struct i2c_client *client)
+static int max9850_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -365,7 +365,7 @@ static struct i2c_driver max9850_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max9850_i2c_probe,
-       .remove = __devexit_p(max9850_i2c_remove),
+       .remove = max9850_i2c_remove,
        .id_table = max9850_i2c_id,
 };
 
index d15e5943c85e931bc0ffd5472b27768bbadaeb79..6b6c74cd83e2bcc2d9e5292cca7c2b70618eaa18 100644 (file)
@@ -258,8 +258,8 @@ int max9877_add_controls(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(max9877_add_controls);
 
-static int __devinit max9877_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int max9877_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
 {
        i2c = client;
 
@@ -268,7 +268,7 @@ static int __devinit max9877_i2c_probe(struct i2c_client *client,
        return 0;
 }
 
-static __devexit int max9877_i2c_remove(struct i2c_client *client)
+static int max9877_i2c_remove(struct i2c_client *client)
 {
        i2c = NULL;
 
@@ -287,7 +287,7 @@ static struct i2c_driver max9877_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max9877_i2c_probe,
-       .remove = __devexit_p(max9877_i2c_remove),
+       .remove = max9877_i2c_remove,
        .id_table = max9877_i2c_id,
 };
 
index bc955999c8aa56c15fb30e99bbc8a7eecb930a67..5402dfbbb7162f668d8841a83ad3c04db5d2516f 100644 (file)
@@ -779,7 +779,7 @@ static struct platform_driver mc13783_codec_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = mc13783_codec_probe,
-       .remove = __devexit_p(mc13783_codec_remove),
+       .remove = mc13783_codec_remove,
 };
 
 module_platform_driver(mc13783_codec_driver);
index 96aa5fa051609357cda4555e52bd4d4b5b509909..26118828782b9b5b4ced3c372ccf128b971cebde 100644 (file)
@@ -626,8 +626,8 @@ static const struct regmap_config ml26124_i2c_regmap = {
        .write_flag_mask = 0x01,
 };
 
-static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int ml26124_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
 {
        struct ml26124_priv *priv;
        int ret;
@@ -649,7 +649,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
                        &soc_codec_dev_ml26124, &ml26124_dai, 1);
 }
 
-static __devexit int ml26124_i2c_remove(struct i2c_client *client)
+static int ml26124_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -667,7 +667,7 @@ static struct i2c_driver ml26124_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ml26124_i2c_probe,
-       .remove = __devexit_p(ml26124_i2c_remove),
+       .remove = ml26124_i2c_remove,
        .id_table = ml26124_i2c_id,
 };
 
index 1bf5c74f5f96e2ac601f300152a1d670bc9af92c..529d06444c546711c1fcbabffbf75c660486ce1b 100644 (file)
@@ -39,13 +39,13 @@ static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
        },
 };
 
-static __devinit int omap_hdmi_codec_probe(struct platform_device *pdev)
+static int omap_hdmi_codec_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec,
                        &omap_hdmi_codec_dai, 1);
 }
 
-static __devexit int omap_hdmi_codec_remove(struct platform_device *pdev)
+static int omap_hdmi_codec_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -58,7 +58,7 @@ static struct platform_driver omap_hdmi_codec_driver = {
        },
 
        .probe          = omap_hdmi_codec_probe,
-       .remove         = __devexit_p(omap_hdmi_codec_remove),
+       .remove         = omap_hdmi_codec_remove,
 };
 
 module_platform_driver(omap_hdmi_codec_driver);
index edcaa7ea548757b3825acb27a1af9fd958d9121b..f2a6282b41f4e07a1627463222b4ba9d091a7cf1 100644 (file)
@@ -149,13 +149,13 @@ static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
        .resume =       pcm3008_soc_resume,
 };
 
-static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
+static int pcm3008_codec_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
 }
 
-static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
+static int pcm3008_codec_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -165,7 +165,7 @@ MODULE_ALIAS("platform:pcm3008-codec");
 
 static struct platform_driver pcm3008_codec_driver = {
        .probe          = pcm3008_codec_probe,
-       .remove         = __devexit_p(pcm3008_codec_remove),
+       .remove         = pcm3008_codec_remove,
        .driver         = {
                .name   = "pcm3008-codec",
                .owner  = THIS_MODULE,
index 960d0e93cce9463a3592c17d74de0f9d5ad4bf19..912c9cbc27242eb48229506e86b3295a81967185 100644 (file)
@@ -1382,7 +1382,7 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
                                        timesofbclk);
        if (coeff < 0) {
                dev_err(codec->dev, "Fail to get coeff\n");
-               return -EINVAL;
+               return coeff;
        }
 
        switch (params_format(params)) {
@@ -1748,7 +1748,7 @@ static int rt5631_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+static int rt5631_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1760,7 +1760,7 @@ static struct i2c_driver rt5631_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = rt5631_i2c_probe,
-       .remove   = __devexit_p(rt5631_i2c_remove),
+       .remove   = rt5631_i2c_remove,
        .id_table = rt5631_i2c_id,
 };
 
index df2f99d1d428940424d419378ce6cf9d82a937bf..cb1675cd8e1c5ffd9b404b9d12ee9c404f6f2efd 100644 (file)
@@ -1404,8 +1404,8 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
        .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
 };
 
-static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
-                                       const struct i2c_device_id *id)
+static int sgtl5000_i2c_probe(struct i2c_client *client,
+                             const struct i2c_device_id *id)
 {
        struct sgtl5000_priv *sgtl5000;
        int ret;
@@ -1422,7 +1422,7 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
+static int sgtl5000_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -1449,7 +1449,7 @@ static struct i2c_driver sgtl5000_i2c_driver = {
                   .of_match_table = sgtl5000_dt_ids,
                   },
        .probe = sgtl5000_i2c_probe,
-       .remove = __devexit_p(sgtl5000_i2c_remove),
+       .remove = sgtl5000_i2c_remove,
        .id_table = sgtl5000_id,
 };
 
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
new file mode 100644 (file)
index 0000000..f2d61a1
--- /dev/null
@@ -0,0 +1,255 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include <linux/i2c.h>
+
+#include <linux/mfd/si476x-core.h>
+
+enum si476x_audio_registers {
+       SI476X_DIGITAL_IO_OUTPUT_FORMAT         = 0x0203,
+       SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE    = 0x0202,
+};
+
+enum si476x_digital_io_output_format {
+       SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT       = 11,
+       SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT     = 8,
+};
+
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK    ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+                                                 (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK   (0b1111110)
+
+enum si476x_daudio_formats {
+       SI476X_DAUDIO_MODE_I2S          = (0x0 << 1),
+       SI476X_DAUDIO_MODE_DSP_A        = (0x6 << 1),
+       SI476X_DAUDIO_MODE_DSP_B        = (0x7 << 1),
+       SI476X_DAUDIO_MODE_LEFT_J       = (0x8 << 1),
+       SI476X_DAUDIO_MODE_RIGHT_J      = (0x9 << 1),
+
+       SI476X_DAUDIO_MODE_IB           = (1 << 5),
+       SI476X_DAUDIO_MODE_IF           = (1 << 6),
+};
+
+enum si476x_pcm_format {
+       SI476X_PCM_FORMAT_S8            = 2,
+       SI476X_PCM_FORMAT_S16_LE        = 4,
+       SI476X_PCM_FORMAT_S20_3LE       = 5,
+       SI476X_PCM_FORMAT_S24_LE        = 6,
+};
+
+static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
+                                     unsigned int reg)
+{
+       int err;
+       struct si476x_core *core = codec->control_data;
+
+       si476x_core_lock(core);
+       err = si476x_core_cmd_get_property(core, reg);
+       si476x_core_unlock(core);
+
+       return err;
+}
+
+static int si476x_codec_write(struct snd_soc_codec *codec,
+                             unsigned int reg, unsigned int val)
+{
+       int err;
+       struct si476x_core *core = codec->control_data;
+
+       si476x_core_lock(core);
+       err = si476x_core_cmd_set_property(core, reg, val);
+       si476x_core_unlock(core);
+
+       return err;
+}
+
+static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                   unsigned int fmt)
+{
+       int err;
+       u16 format = 0;
+
+       if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+               return -EINVAL;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               format |= SI476X_DAUDIO_MODE_DSP_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               format |= SI476X_DAUDIO_MODE_DSP_B;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               format |= SI476X_DAUDIO_MODE_I2S;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               format |= SI476X_DAUDIO_MODE_RIGHT_J;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               format |= SI476X_DAUDIO_MODE_LEFT_J;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       format |= SI476X_DAUDIO_MODE_IB;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case SND_SOC_DAIFMT_I2S:
+       case SND_SOC_DAIFMT_RIGHT_J:
+       case SND_SOC_DAIFMT_LEFT_J:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       format |= SI476X_DAUDIO_MODE_IB |
+                               SI476X_DAUDIO_MODE_IF;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       format |= SI476X_DAUDIO_MODE_IB;
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       format |= SI476X_DAUDIO_MODE_IF;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+                                 SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
+                                 format);
+       if (err < 0) {
+               dev_err(codec_dai->codec->dev, "Failed to set output format\n");
+               return err;
+       }
+       
+       return 0;
+}
+
+static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       int rate, width, err;
+
+       rate = params_rate(params);
+       if (rate < 32000 || rate > 48000) {
+               dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate);
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               width = SI476X_PCM_FORMAT_S8;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               width = SI476X_PCM_FORMAT_S16_LE;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               width = SI476X_PCM_FORMAT_S20_3LE;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               width = SI476X_PCM_FORMAT_S24_LE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
+                           rate);
+       if (err < 0) {
+               dev_err(dai->codec->dev, "Failed to set sample rate\n");
+               return err;
+       }
+
+       err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+                                 SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
+                                 (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | 
+                                 (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
+       if (err < 0) {
+               dev_err(dai->codec->dev, "Failed to set output width\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int si476x_codec_probe(struct snd_soc_codec *codec)
+{
+       codec->control_data = i2c_mfd_cell_to_core(codec->dev);
+       return 0;
+}
+
+static struct snd_soc_dai_ops si476x_dai_ops = {
+       .hw_params      = si476x_codec_hw_params,
+       .set_fmt        = si476x_codec_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver si476x_dai = {
+       .name           = "si476x-codec",
+       .capture        = {
+               .stream_name    = "Capture",
+               .channels_min   = 2,
+               .channels_max   = 2,
+
+               .rates = SNDRV_PCM_RATE_32000 |
+               SNDRV_PCM_RATE_44100 |
+               SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+               SNDRV_PCM_FMTBIT_S16_LE |
+               SNDRV_PCM_FMTBIT_S20_3LE |
+               SNDRV_PCM_FMTBIT_S24_LE
+       },
+       .ops            = &si476x_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_si476x = {
+       .probe  = si476x_codec_probe,
+       .read   = si476x_codec_read,
+       .write  = si476x_codec_write,
+};
+
+static int si476x_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x,
+                                     &si476x_dai, 1);
+}
+
+static int si476x_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+MODULE_ALIAS("platform:si476x-codec");
+
+static struct platform_driver si476x_platform_driver = {
+       .driver         = {
+               .name   = "si476x-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = si476x_platform_probe,
+       .remove         = si476x_platform_remove,
+};
+module_platform_driver(si476x_platform_driver);
+
+MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>");
+MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
+MODULE_LICENSE("GPL");
index 50dbdb9357ead627961f08a170d8430b99faca07..d1ae869d3181b1ddfc40f6fc8c4be9c67272d583 100644 (file)
@@ -896,14 +896,14 @@ struct snd_soc_codec_driver sn95031_codec = {
        .num_dapm_routes        = ARRAY_SIZE(sn95031_audio_map),
 };
 
-static int __devinit sn95031_device_probe(struct platform_device *pdev)
+static int sn95031_device_probe(struct platform_device *pdev)
 {
        pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
        return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
                        sn95031_dais, ARRAY_SIZE(sn95031_dais));
 }
 
-static int __devexit sn95031_device_remove(struct platform_device *pdev)
+static int sn95031_device_remove(struct platform_device *pdev)
 {
        pr_debug("codec device remove called\n");
        snd_soc_unregister_codec(&pdev->dev);
@@ -916,7 +916,7 @@ static struct platform_driver sn95031_codec_driver = {
                .owner          = THIS_MODULE,
        },
        .probe          = sn95031_device_probe,
-       .remove         = __devexit_p(sn95031_device_remove),
+       .remove         = sn95031_device_remove,
 };
 
 module_platform_driver(sn95031_codec_driver);
index 079066fef4255217adce5319e58be0d15acdcb91..f8d30e5f63714c4d58154b0bffebeee424b11dbc 100644 (file)
@@ -691,7 +691,7 @@ static const struct regmap_config ssm2602_regmap_config = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit ssm2602_spi_probe(struct spi_device *spi)
+static int ssm2602_spi_probe(struct spi_device *spi)
 {
        struct ssm2602_priv *ssm2602;
        int ret;
@@ -713,7 +713,7 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit ssm2602_spi_remove(struct spi_device *spi)
+static int ssm2602_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -725,7 +725,7 @@ static struct spi_driver ssm2602_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ssm2602_spi_probe,
-       .remove         = __devexit_p(ssm2602_spi_remove),
+       .remove         = ssm2602_spi_remove,
 };
 #endif
 
@@ -736,7 +736,7 @@ static struct spi_driver ssm2602_spi_driver = {
  *    low  = 0x1a
  *    high = 0x1b
  */
-static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
+static int ssm2602_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
        struct ssm2602_priv *ssm2602;
@@ -759,7 +759,7 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit ssm2602_i2c_remove(struct i2c_client *client)
+static int ssm2602_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -780,7 +780,7 @@ static struct i2c_driver ssm2602_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ssm2602_i2c_probe,
-       .remove = __devexit_p(ssm2602_i2c_remove),
+       .remove = ssm2602_i2c_remove,
        .id_table = ssm2602_i2c_id,
 };
 #endif
index 0935bfe624711646e622b0637ccd56484dfd115d..cfb55fe35e98691cbaf7b18404b93e02c1cce73c 100644 (file)
@@ -995,8 +995,8 @@ static const struct regmap_config sta32x_regmap = {
        .volatile_reg =         sta32x_reg_is_volatile,
 };
 
-static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int sta32x_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct sta32x_priv *sta32x;
        int ret, i;
@@ -1033,7 +1033,7 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int sta32x_i2c_remove(struct i2c_client *client)
+static int sta32x_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1053,7 +1053,7 @@ static struct i2c_driver sta32x_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    sta32x_i2c_probe,
-       .remove =   __devexit_p(sta32x_i2c_remove),
+       .remove =   sta32x_i2c_remove,
        .id_table = sta32x_i2c_id,
 };
 
index 9e31448623866e9e7665b289bdca1665b4924db2..ab355c4f0b2de0aa786e754360a6a877a0855756 100644 (file)
@@ -380,8 +380,8 @@ static const struct regmap_config sta529_regmap = {
        .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
 };
 
-static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
-               const struct i2c_device_id *id)
+static int sta529_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct sta529 *sta529;
        int ret;
@@ -412,7 +412,7 @@ static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit sta529_i2c_remove(struct i2c_client *client)
+static int sta529_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -431,7 +431,7 @@ static struct i2c_driver sta529_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = sta529_i2c_probe,
-       .remove         = __devexit_p(sta529_i2c_remove),
+       .remove         = sta529_i2c_remove,
        .id_table       = sta529_i2c_id,
 };
 
index 982e437799a8e62aa8085a9d5b509fa4d8f8a387..2eda85ba79acd2cdd442b78fa4631542f0caffdd 100644 (file)
@@ -385,13 +385,13 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
        .reg_cache_default = stac9766_reg,
 };
 
-static __devinit int stac9766_probe(struct platform_device *pdev)
+static int stac9766_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
 }
 
-static int __devexit stac9766_remove(struct platform_device *pdev)
+static int stac9766_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -404,7 +404,7 @@ static struct platform_driver stac9766_codec_driver = {
        },
 
        .probe = stac9766_probe,
-       .remove = __devexit_p(stac9766_remove),
+       .remove = stac9766_remove,
 };
 
 module_platform_driver(stac9766_codec_driver);
index f230292ba96bbfc0c5cf7c7264dd4435de3d7590..17df4e32feac401c551ffef564dd10c25ae6bf49 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
@@ -65,6 +66,7 @@ struct aic32x4_priv {
        u32 power_cfg;
        u32 micpga_routing;
        bool swapdacs;
+       int rstn_gpio;
 };
 
 /* 0dB min, 1dB steps */
@@ -627,10 +629,20 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
 {
        struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
        u32 tmp_reg;
+       int ret;
 
        codec->hw_write = (hw_write_t) i2c_master_send;
        codec->control_data = aic32x4->control_data;
 
+       if (aic32x4->rstn_gpio >= 0) {
+               ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
+                               GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+               if (ret != 0)
+                       return ret;
+               ndelay(10);
+               gpio_set_value(aic32x4->rstn_gpio, 1);
+       }
+
        snd_soc_write(codec, AIC32X4_RESET, 0x01);
 
        /* Power platform configuration */
@@ -675,6 +687,16 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
                             ARRAY_SIZE(aic32x4_snd_controls));
        aic32x4_add_widgets(codec);
 
+       /*
+        * Workaround: for an unknown reason, the ADC needs to be powered up
+        * and down for the first capture to work properly. It seems related to
+        * a HW BUG or some kind of behavior not documented in the datasheet.
+        */
+       tmp_reg = snd_soc_read(codec, AIC32X4_ADCSETUP);
+       snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg |
+                               AIC32X4_LADC_EN | AIC32X4_RADC_EN);
+       snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg);
+
        return 0;
 }
 
@@ -694,8 +716,8 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
        .set_bias_level = aic32x4_set_bias_level,
 };
 
-static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int aic32x4_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
 {
        struct aic32x4_pdata *pdata = i2c->dev.platform_data;
        struct aic32x4_priv *aic32x4;
@@ -713,10 +735,12 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
                aic32x4->power_cfg = pdata->power_cfg;
                aic32x4->swapdacs = pdata->swapdacs;
                aic32x4->micpga_routing = pdata->micpga_routing;
+               aic32x4->rstn_gpio = pdata->rstn_gpio;
        } else {
                aic32x4->power_cfg = 0;
                aic32x4->swapdacs = false;
                aic32x4->micpga_routing = 0;
+               aic32x4->rstn_gpio = -1;
        }
 
        ret = snd_soc_register_codec(&i2c->dev,
@@ -724,7 +748,7 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int aic32x4_i2c_remove(struct i2c_client *client)
+static int aic32x4_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -742,7 +766,7 @@ static struct i2c_driver aic32x4_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    aic32x4_i2c_probe,
-       .remove =   __devexit_p(aic32x4_i2c_remove),
+       .remove =   aic32x4_i2c_remove,
        .id_table = aic32x4_i2c_id,
 };
 
index aae2b2440398aaac19a62eac62b6e7788e41035c..35774223fd91f2a03c4ce4ed56c45df3f3ff2a3d 100644 (file)
@@ -94,6 +94,9 @@
 #define AIC32X4_WORD_LEN_24BITS                0x02
 #define AIC32X4_WORD_LEN_32BITS                0x03
 
+#define AIC32X4_LADC_EN                        (1 << 7)
+#define AIC32X4_RADC_EN                        (1 << 6)
+
 #define AIC32X4_I2S_MODE               0x00
 #define AIC32X4_DSP_MODE               0x01
 #define AIC32X4_RIGHT_JUSTIFIED_MODE   0x02
index d2e16c5d7d1f71ca5d4425e7c6d8a83dc7bcb7ec..782b0cded2e69350046d942cfa67c836e521ce1a 100644 (file)
@@ -1514,8 +1514,8 @@ static struct snd_soc_dai_driver dac33_dai = {
        .ops = &dac33_dai_ops,
 };
 
-static int __devinit dac33_i2c_probe(struct i2c_client *client,
-                                    const struct i2c_device_id *id)
+static int dac33_i2c_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
 {
        struct tlv320dac33_platform_data *pdata;
        struct tlv320dac33_priv *dac33;
@@ -1586,7 +1586,7 @@ err_gpio:
        return ret;
 }
 
-static int __devexit dac33_i2c_remove(struct i2c_client *client)
+static int dac33_i2c_remove(struct i2c_client *client)
 {
        struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
 
@@ -1617,7 +1617,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = dac33_i2c_probe,
-       .remove         = __devexit_p(dac33_i2c_remove),
+       .remove         = dac33_i2c_remove,
        .id_table       = tlv320dac33_i2c_id,
 };
 
index 565ff39ad3a35ced5598c9532bc33b85f1d8983a..8d75aa152c8cd29dab7133791db83955d5a6bd14 100644 (file)
@@ -359,8 +359,8 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
 
-static int __devinit tpa6130a2_probe(struct i2c_client *client,
-                                    const struct i2c_device_id *id)
+static int tpa6130a2_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
 {
        struct device *dev;
        struct tpa6130a2_data *data;
@@ -455,7 +455,7 @@ err_gpio:
        return ret;
 }
 
-static int __devexit tpa6130a2_remove(struct i2c_client *client)
+static int tpa6130a2_remove(struct i2c_client *client)
 {
        struct tpa6130a2_data *data = i2c_get_clientdata(client);
 
@@ -483,7 +483,7 @@ static struct i2c_driver tpa6130a2_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tpa6130a2_probe,
-       .remove = __devexit_p(tpa6130a2_remove),
+       .remove = tpa6130a2_remove,
        .id_table = tpa6130a2_id,
 };
 
index e7f608996c41e1292c6a00efc56935b9acab75af..63b280b060359f12ffda4f018f4f9e012f32eac2 100644 (file)
@@ -2334,13 +2334,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
        .num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
+static int twl4030_codec_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
                        twl4030_dai, ARRAY_SIZE(twl4030_dai));
 }
 
-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
+static int twl4030_codec_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -2350,7 +2350,7 @@ MODULE_ALIAS("platform:twl4030-codec");
 
 static struct platform_driver twl4030_codec_driver = {
        .probe          = twl4030_codec_probe,
-       .remove         = __devexit_p(twl4030_codec_remove),
+       .remove         = twl4030_codec_remove,
        .driver         = {
                .name   = "twl4030-codec",
                .owner  = THIS_MODULE,
index 00b85cc1b9a3508f8db9a677bac90d4e2af50038..3fc3fc64dd8b47a85ca142d3ef95dfe637908754 100644 (file)
@@ -1229,13 +1229,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
        .num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
-static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+static int twl6040_codec_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
                                      twl6040_dai, ARRAY_SIZE(twl6040_dai));
 }
 
-static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+static int twl6040_codec_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -1247,7 +1247,7 @@ static struct platform_driver twl6040_codec_driver = {
                .owner = THIS_MODULE,
        },
        .probe = twl6040_codec_probe,
-       .remove = __devexit_p(twl6040_codec_remove),
+       .remove = twl6040_codec_remove,
 };
 
 module_platform_driver(twl6040_codec_driver);
index 6c3d43b8ee858538346565ec5915f4b2acf004d9..6d0aa44c375755fb8715c2089d27d4a3686598f1 100644 (file)
@@ -601,13 +601,13 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
        .set_bias_level = uda134x_set_bias_level,
 };
 
-static int __devinit uda134x_codec_probe(struct platform_device *pdev)
+static int uda134x_codec_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_uda134x, &uda134x_dai, 1);
 }
 
-static int __devexit uda134x_codec_remove(struct platform_device *pdev)
+static int uda134x_codec_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -619,7 +619,7 @@ static struct platform_driver uda134x_codec_driver = {
                .owner = THIS_MODULE,
        },
        .probe = uda134x_codec_probe,
-       .remove = __devexit_p(uda134x_codec_remove),
+       .remove = uda134x_codec_remove,
 };
 
 module_platform_driver(uda134x_codec_driver);
index 2502214b84abe918514f9462039ef1f941bb3f59..fd0a314bc209a4005e8b3488930b6b7d3215526f 100644 (file)
@@ -795,8 +795,8 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int uda1380_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
 {
        struct uda1380_priv *uda1380;
        int ret;
@@ -814,7 +814,7 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
+static int uda1380_i2c_remove(struct i2c_client *i2c)
 {
        snd_soc_unregister_codec(&i2c->dev);
        return 0;
@@ -832,7 +832,7 @@ static struct i2c_driver uda1380_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    uda1380_i2c_probe,
-       .remove =   __devexit_p(uda1380_i2c_remove),
+       .remove =   uda1380_i2c_remove,
        .id_table = uda1380_i2c_id,
 };
 #endif
index 7b24d6d192e17d8cd5b61ade0d59988dde07c924..54cd3da09abd036471291901461331231ce78ab7 100644 (file)
@@ -485,13 +485,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
        .remove = wl1273_remove,
 };
 
-static int __devinit wl1273_platform_probe(struct platform_device *pdev)
+static int wl1273_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
                                      &wl1273_dai, 1);
 }
 
-static int __devexit wl1273_platform_remove(struct platform_device *pdev)
+static int wl1273_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -505,7 +505,7 @@ static struct platform_driver wl1273_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = wl1273_platform_probe,
-       .remove         = __devexit_p(wl1273_platform_remove),
+       .remove         = wl1273_platform_remove,
 };
 
 module_platform_driver(wl1273_platform_driver);
index 99afc003a084cabfc47511047247c0416da8931f..ad2fee4bb4cd12ea133e9a455758a6d9a921d4f7 100644 (file)
@@ -31,6 +31,9 @@
 
 #define DEVICE_ID_WM0010       10
 
+/* We only support v1 of the .dfw INFO record */
+#define INFO_VERSION           1
+
 enum dfw_cmd {
        DFW_CMD_FUSE = 0x01,
        DFW_CMD_CODE_HDR,
@@ -46,6 +49,13 @@ struct dfw_binrec {
        uint8_t data[0];
 } __packed;
 
+struct dfw_inforec {
+       u8 info_version;
+       u8 tool_major_version;
+       u8 tool_minor_version;
+       u8 dsp_target;
+};
+
 struct dfw_pllrec {
        u8 command;
        u32 length:24;
@@ -97,7 +107,6 @@ struct wm0010_priv {
 
        enum wm0010_state state;
        bool boot_failed;
-       int boot_done;
        bool ready;
        bool pll_running;
        int max_spi_freq;
@@ -234,7 +243,7 @@ static void wm0010_boot_xfer_complete(void *data)
                        break;
 
                case 0x55555555:
-                       if (wm0010->boot_done == 0)
+                       if (wm0010->state < WM0010_STAGE2)
                                break;
                        dev_err(codec->dev,
                                "%d: ROM bootloader running in stage 2\n", i);
@@ -321,7 +330,6 @@ static void wm0010_boot_xfer_complete(void *data)
                        break;
        }
 
-       wm0010->boot_done++;
        if (xfer->done)
                complete(xfer->done);
 }
@@ -334,94 +342,198 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len)
                data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i]));
 }
 
-static int wm0010_boot(struct snd_soc_codec *codec)
+static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec)
 {
        struct spi_device *spi = to_spi_device(codec->dev);
        struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
-       unsigned long flags;
        struct list_head xfer_list;
        struct wm0010_boot_xfer *xfer;
        int ret;
        struct completion done;
        const struct firmware *fw;
        const struct dfw_binrec *rec;
-       struct spi_message m;
-       struct spi_transfer t;
-       struct dfw_pllrec pll_rec;
-       u32 *img, *p;
-       u64 *img_swap;
-       u8 *out;
+       const struct dfw_inforec *inforec;
+       u64 *img;
+       u8 *out, dsp;
        u32 len, offset;
-       int i;
 
-       spin_lock_irqsave(&wm0010->irq_lock, flags);
-       if (wm0010->state != WM0010_POWER_OFF)
-               dev_warn(wm0010->dev, "DSP already powered up!\n");
-       spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+       INIT_LIST_HEAD(&xfer_list);
 
-       if (wm0010->sysclk > 26000000) {
-               dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
-               ret = -ECANCELED;
-               goto err;
+       ret = request_firmware(&fw, name, codec->dev);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request application: %d\n",
+                       ret);
+               return ret;
        }
 
-       INIT_LIST_HEAD(&xfer_list);
+       rec = (const struct dfw_binrec *)fw->data;
+       inforec = (const struct dfw_inforec *)rec->data;
+       offset = 0;
+       dsp = inforec->dsp_target;
+       wm0010->boot_failed = false;
+       BUG_ON(!list_empty(&xfer_list));
+       init_completion(&done);
 
-       mutex_lock(&wm0010->lock);
-       wm0010->pll_running = false;
+       /* First record should be INFO */
+       if (rec->command != DFW_CMD_INFO) {
+               dev_err(codec->dev, "First record not INFO\r\n");
+               ret = -EINVAL;
+               goto abort;
+       }
 
-       dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
+       if (inforec->info_version != INFO_VERSION) {
+               dev_err(codec->dev,
+                       "Unsupported version (%02d) of INFO record\r\n",
+                       inforec->info_version);
+               ret = -EINVAL;
+               goto abort;
+       }
 
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
-                                   wm0010->core_supplies);
-       if (ret != 0) {
-               dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
-                       ret);
-               mutex_unlock(&wm0010->lock);
-               goto err;
+       dev_dbg(codec->dev, "Version v%02d INFO record found\r\n",
+               inforec->info_version);
+
+       /* Check it's a DSP file */
+       if (dsp != DEVICE_ID_WM0010) {
+               dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
+               ret = -EINVAL;
+               goto abort;
        }
 
-       ret = regulator_enable(wm0010->dbvdd);
-       if (ret != 0) {
-               dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
-               goto err_core;
+       /* Skip the info record as we don't need to send it */
+       offset += ((rec->length) + 8);
+       rec = (void *)&rec->data[rec->length];
+
+       while (offset < fw->size) {
+               dev_dbg(codec->dev,
+                       "Packet: command %d, data length = 0x%x\r\n",
+                       rec->command, rec->length);
+               len = rec->length + 8;
+
+               out = kzalloc(len, GFP_KERNEL);
+               if (!out) {
+                       dev_err(codec->dev,
+                               "Failed to allocate RX buffer\n");
+                       ret = -ENOMEM;
+                       goto abort1;
+               }
+
+               img = kzalloc(len, GFP_KERNEL);
+               if (!img) {
+                       dev_err(codec->dev,
+                               "Failed to allocate image buffer\n");
+                       ret = -ENOMEM;
+                       goto abort1;
+               }
+
+               byte_swap_64((u64 *)&rec->command, img, len);
+
+               xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
+               if (!xfer) {
+                       dev_err(codec->dev, "Failed to allocate xfer\n");
+                       ret = -ENOMEM;
+                       goto abort1;
+               }
+
+               xfer->codec = codec;
+               list_add_tail(&xfer->list, &xfer_list);
+
+               spi_message_init(&xfer->m);
+               xfer->m.complete = wm0010_boot_xfer_complete;
+               xfer->m.context = xfer;
+               xfer->t.tx_buf = img;
+               xfer->t.rx_buf = out;
+               xfer->t.len = len;
+               xfer->t.bits_per_word = 8;
+
+               if (!wm0010->pll_running) {
+                       xfer->t.speed_hz = wm0010->sysclk / 6;
+               } else {
+                       xfer->t.speed_hz = wm0010->max_spi_freq;
+
+                       if (wm0010->board_max_spi_speed &&
+                          (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
+                                       xfer->t.speed_hz = wm0010->board_max_spi_speed;
+               }
+
+               /* Store max usable spi frequency for later use */
+               wm0010->max_spi_freq = xfer->t.speed_hz;
+
+               spi_message_add_tail(&xfer->t, &xfer->m);
+
+               offset += ((rec->length) + 8);
+               rec = (void *)&rec->data[rec->length];
+
+               if (offset >= fw->size) {
+                       dev_dbg(codec->dev, "All transfers scheduled\n");
+                       xfer->done = &done;
+               }
+
+               ret = spi_async(spi, &xfer->m);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Write failed: %d\n", ret);
+                       goto abort1;
+               }
+
+               if (wm0010->boot_failed) {
+                       dev_dbg(codec->dev, "Boot fail!\n");
+                       ret = -EINVAL;
+                       goto abort1;
+               }
        }
 
-       /* Release reset */
-       gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
-       spin_lock_irqsave(&wm0010->irq_lock, flags);
-       wm0010->state = WM0010_OUT_OF_RESET;
-       spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+       wait_for_completion(&done);
+
+       ret = 0;
+
+abort1:
+       while (!list_empty(&xfer_list)) {
+               xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
+                                       list);
+               kfree(xfer->t.rx_buf);
+               kfree(xfer->t.tx_buf);
+               list_del(&xfer->list);
+               kfree(xfer);
+       }
+
+abort:
+       release_firmware(fw);
+       return ret;
+}
+
+static int wm0010_stage2_load(struct snd_soc_codec *codec)
+{
+       struct spi_device *spi = to_spi_device(codec->dev);
+       struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
+       const struct firmware *fw;
+       struct spi_message m;
+       struct spi_transfer t;
+       u32 *img;
+       u8 *out;
+       int i;
+       int ret = 0;
 
-       /* First the bootloader */
        ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
                        ret);
-               goto abort;
+               return ret;
        }
 
-       if (!wait_for_completion_timeout(&wm0010->boot_completion,
-                                        msecs_to_jiffies(10)))
-               dev_err(codec->dev, "Failed to get interrupt from DSP\n");
-
-       spin_lock_irqsave(&wm0010->irq_lock, flags);
-       wm0010->state = WM0010_BOOTROM;
-       spin_unlock_irqrestore(&wm0010->irq_lock, flags);
-
        dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size);
 
        /* Copy to local buffer first as vmalloc causes problems for dma */
        img = kzalloc(fw->size, GFP_KERNEL);
        if (!img) {
                dev_err(codec->dev, "Failed to allocate image buffer\n");
-               goto abort;
+               ret = -ENOMEM;
+               goto abort2;
        }
 
        out = kzalloc(fw->size, GFP_KERNEL);
        if (!out) {
                dev_err(codec->dev, "Failed to allocate output buffer\n");
-               goto abort;
+               ret = -ENOMEM;
+               goto abort1;
        }
 
        memcpy(img, &fw->data[0], fw->size);
@@ -447,20 +559,97 @@ static int wm0010_boot(struct snd_soc_codec *codec)
        /* Look for errors from the boot ROM */
        for (i = 0; i < fw->size; i++) {
                if (out[i] != 0x55) {
-                       ret = -EBUSY;
                        dev_err(codec->dev, "Boot ROM error: %x in %d\n",
                                out[i], i);
                        wm0010_mark_boot_failure(wm0010);
+                       ret = -EBUSY;
                        goto abort;
                }
        }
-
-       release_firmware(fw);
-       kfree(img);
+abort:
        kfree(out);
+abort1:
+       kfree(img);
+abort2:
+       release_firmware(fw);
+
+       return ret;
+}
+
+static int wm0010_boot(struct snd_soc_codec *codec)
+{
+       struct spi_device *spi = to_spi_device(codec->dev);
+       struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
+       unsigned long flags;
+       int ret;
+       const struct firmware *fw;
+       struct spi_message m;
+       struct spi_transfer t;
+       struct dfw_pllrec pll_rec;
+       u32 *p, len;
+       u64 *img_swap;
+       u8 *out;
+       int i;
+
+       spin_lock_irqsave(&wm0010->irq_lock, flags);
+       if (wm0010->state != WM0010_POWER_OFF)
+               dev_warn(wm0010->dev, "DSP already powered up!\n");
+       spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+       if (wm0010->sysclk > 26000000) {
+               dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
+               ret = -ECANCELED;
+               goto err;
+       }
+
+       mutex_lock(&wm0010->lock);
+       wm0010->pll_running = false;
+
+       dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
+                                   wm0010->core_supplies);
+       if (ret != 0) {
+               dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
+                       ret);
+               mutex_unlock(&wm0010->lock);
+               goto err;
+       }
+
+       ret = regulator_enable(wm0010->dbvdd);
+       if (ret != 0) {
+               dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
+               goto err_core;
+       }
+
+       /* Release reset */
+       gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
+       spin_lock_irqsave(&wm0010->irq_lock, flags);
+       wm0010->state = WM0010_OUT_OF_RESET;
+       spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+       /* First the bootloader */
+       ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
+                       ret);
+               goto abort;
+       }
+
+       if (!wait_for_completion_timeout(&wm0010->boot_completion,
+                                        msecs_to_jiffies(20)))
+               dev_err(codec->dev, "Failed to get interrupt from DSP\n");
+
+       spin_lock_irqsave(&wm0010->irq_lock, flags);
+       wm0010->state = WM0010_BOOTROM;
+       spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+       ret = wm0010_stage2_load(codec);
+       if (ret)
+               goto abort;
 
        if (!wait_for_completion_timeout(&wm0010->boot_completion,
-                                        msecs_to_jiffies(10)))
+                                        msecs_to_jiffies(20)))
                dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n");
 
        spin_lock_irqsave(&wm0010->irq_lock, flags);
@@ -535,110 +724,10 @@ static int wm0010_boot(struct snd_soc_codec *codec)
        } else
                dev_dbg(codec->dev, "Not enabling DSP PLL.");
 
-       ret = request_firmware(&fw, "wm0010.dfw", codec->dev);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request application: %d\n",
-                       ret);
-               goto abort;
-       }
-
-       rec = (const struct dfw_binrec *)fw->data;
-       offset = 0;
-       wm0010->boot_done = 0;
-       wm0010->boot_failed = false;
-       BUG_ON(!list_empty(&xfer_list));
-       init_completion(&done);
+       ret = wm0010_firmware_load("wm0010.dfw", codec);
 
-       /* First record should be INFO */
-       if (rec->command != DFW_CMD_INFO) {
-               dev_err(codec->dev, "First record not INFO\r\n");
-               goto abort;
-       }
-
-       /* Check it's a 0010 file */
-       if (rec->data[0] != DEVICE_ID_WM0010) {
-               dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
+       if (ret != 0)
                goto abort;
-       }
-
-       /* Skip the info record as we don't need to send it */
-       offset += ((rec->length) + 8);
-       rec = (void *)&rec->data[rec->length];
-
-       while (offset < fw->size) {
-               dev_dbg(codec->dev,
-                       "Packet: command %d, data length = 0x%x\r\n",
-                       rec->command, rec->length);
-               len = rec->length + 8;
-
-               out = kzalloc(len, GFP_KERNEL);
-               if (!out) {
-                       dev_err(codec->dev,
-                               "Failed to allocate RX buffer\n");
-                       goto abort;
-               }
-
-               img_swap = kzalloc(len, GFP_KERNEL);
-               if (!img_swap) {
-                       dev_err(codec->dev,
-                               "Failed to allocate image buffer\n");
-                       goto abort;
-               }
-
-               /* We need to re-order for 0010 */
-               byte_swap_64((u64 *)&rec->command, img_swap, len);
-
-               xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
-               if (!xfer) {
-                       dev_err(codec->dev, "Failed to allocate xfer\n");
-                       goto abort;
-               }
-
-               xfer->codec = codec;
-               list_add_tail(&xfer->list, &xfer_list);
-
-               spi_message_init(&xfer->m);
-               xfer->m.complete = wm0010_boot_xfer_complete;
-               xfer->m.context = xfer;
-               xfer->t.tx_buf = img_swap;
-               xfer->t.rx_buf = out;
-               xfer->t.len = len;
-               xfer->t.bits_per_word = 8;
-
-               if (!wm0010->pll_running) {
-                       xfer->t.speed_hz = wm0010->sysclk / 6;
-               } else {
-                       xfer->t.speed_hz = wm0010->max_spi_freq;
-
-                       if (wm0010->board_max_spi_speed &&
-                          (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
-                                       xfer->t.speed_hz = wm0010->board_max_spi_speed;
-               }
-
-               /* Store max usable spi frequency for later use */
-               wm0010->max_spi_freq = xfer->t.speed_hz;
-
-               spi_message_add_tail(&xfer->t, &xfer->m);
-
-               offset += ((rec->length) + 8);
-               rec = (void *)&rec->data[rec->length];
-
-               if (offset >= fw->size) {
-                       dev_dbg(codec->dev, "All transfers scheduled\n");
-                       xfer->done = &done;
-               }
-
-               ret = spi_async(spi, &xfer->m);
-               if (ret != 0) {
-                       dev_err(codec->dev, "Write failed: %d\n", ret);
-                       goto abort;
-               }
-
-               if (wm0010->boot_failed)
-                       goto abort;
-       }
-
-       wait_for_completion(&done);
 
        spin_lock_irqsave(&wm0010->irq_lock, flags);
        wm0010->state = WM0010_FIRMWARE;
@@ -646,17 +735,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
 
        mutex_unlock(&wm0010->lock);
 
-       release_firmware(fw);
-
-       while (!list_empty(&xfer_list)) {
-               xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
-                                       list);
-               kfree(xfer->t.rx_buf);
-               kfree(xfer->t.tx_buf);
-               list_del(&xfer->list);
-               kfree(xfer);
-       }
-
        return 0;
 
 abort:
@@ -784,7 +862,6 @@ static irqreturn_t wm0010_irq(int irq, void *data)
        struct wm0010_priv *wm0010 = data;
 
        switch (wm0010->state) {
-       case WM0010_POWER_OFF:
        case WM0010_OUT_OF_RESET:
        case WM0010_BOOTROM:
        case WM0010_STAGE2:
@@ -808,7 +885,7 @@ static int wm0010_probe(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int __devinit wm0010_spi_probe(struct spi_device *spi)
+static int wm0010_spi_probe(struct spi_device *spi)
 {
        unsigned long gpio_flags;
        int ret;
@@ -908,7 +985,7 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit wm0010_spi_remove(struct spi_device *spi)
+static int wm0010_spi_remove(struct spi_device *spi)
 {
        struct wm0010_priv *wm0010 = spi_get_drvdata(spi);
 
@@ -930,7 +1007,7 @@ static struct spi_driver wm0010_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = wm0010_spi_probe,
-       .remove         = __devexit_p(wm0010_spi_remove),
+       .remove         = wm0010_spi_remove,
 };
 
 module_spi_driver(wm0010_spi_driver);
index 951d7b49476a5a04d6e04447801be14963fe31e3..6e6b93d4696ed9ec85e6502eb1c1a7cabc0fd63a 100644 (file)
@@ -153,7 +153,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
        .idle_bias_off = true,
 };
 
-static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+static int wm1250_ev1_pdata(struct i2c_client *i2c)
 {
        struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm1250_priv *wm1250;
@@ -199,8 +199,8 @@ static void wm1250_ev1_free(struct i2c_client *i2c)
                gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
 }
 
-static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *i2c_id)
+static int wm1250_ev1_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *i2c_id)
 {
        int id, board, rev, ret;
 
@@ -237,7 +237,7 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
        return 0;
 }
 
-static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
+static int wm1250_ev1_remove(struct i2c_client *i2c)
 {
        snd_soc_unregister_codec(&i2c->dev);
        wm1250_ev1_free(i2c);
@@ -257,7 +257,7 @@ static struct i2c_driver wm1250_ev1_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm1250_ev1_probe,
-       .remove =   __devexit_p(wm1250_ev1_remove),
+       .remove =   wm1250_ev1_remove,
        .id_table = wm1250_ev1_i2c_id,
 };
 
index 683dc43b1d87898508b011e7ca4aee7087049f7e..1cbe88f01d634137e0d7e85218556e1c81710d59 100644 (file)
@@ -646,7 +646,7 @@ static const struct snd_kcontrol_new wm2000_controls[] = {
 static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
                                  struct snd_kcontrol *kcontrol, int event)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = w->codec;
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
        if (SND_SOC_DAPM_EVENT_ON(event))
@@ -764,8 +764,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm2000 = {
        .num_controls = ARRAY_SIZE(wm2000_controls),
 };
 
-static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *i2c_id)
+static int wm2000_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *i2c_id)
 {
        struct wm2000_priv *wm2000;
        struct wm2000_platform_data *pdata;
@@ -871,7 +871,7 @@ out:
        return ret;
 }
 
-static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
+static int wm2000_i2c_remove(struct i2c_client *i2c)
 {
        snd_soc_unregister_codec(&i2c->dev);
 
@@ -890,7 +890,7 @@ static struct i2c_driver wm2000_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm2000_i2c_probe,
-       .remove = __devexit_p(wm2000_i2c_remove),
+       .remove = wm2000_i2c_remove,
        .id_table = wm2000_i2c_id,
 };
 
index eab64a193989ac2917773a4df7613cbf644dd58f..afcf31df77e06efe19c709630f53990741348227 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/firmware.h>
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <sound/wm2200.h>
 
 #include "wm2200.h"
+#include "wmfw.h"
+#include "wm_adsp.h"
+
+#define WM2200_DSP_CONTROL_1                   0x00
+#define WM2200_DSP_CONTROL_2                   0x02
+#define WM2200_DSP_CONTROL_3                   0x03
+#define WM2200_DSP_CONTROL_4                   0x04
+#define WM2200_DSP_CONTROL_5                   0x06
+#define WM2200_DSP_CONTROL_6                   0x07
+#define WM2200_DSP_CONTROL_7                   0x08
+#define WM2200_DSP_CONTROL_8                   0x09
+#define WM2200_DSP_CONTROL_9                   0x0A
+#define WM2200_DSP_CONTROL_10                  0x0B
+#define WM2200_DSP_CONTROL_11                  0x0C
+#define WM2200_DSP_CONTROL_12                  0x0D
+#define WM2200_DSP_CONTROL_13                  0x0F
+#define WM2200_DSP_CONTROL_14                  0x10
+#define WM2200_DSP_CONTROL_15                  0x11
+#define WM2200_DSP_CONTROL_16                  0x12
+#define WM2200_DSP_CONTROL_17                  0x13
+#define WM2200_DSP_CONTROL_18                  0x14
+#define WM2200_DSP_CONTROL_19                  0x16
+#define WM2200_DSP_CONTROL_20                  0x17
+#define WM2200_DSP_CONTROL_21                  0x18
+#define WM2200_DSP_CONTROL_22                  0x1A
+#define WM2200_DSP_CONTROL_23                  0x1B
+#define WM2200_DSP_CONTROL_24                  0x1C
+#define WM2200_DSP_CONTROL_25                  0x1E
+#define WM2200_DSP_CONTROL_26                  0x20
+#define WM2200_DSP_CONTROL_27                  0x21
+#define WM2200_DSP_CONTROL_28                  0x22
+#define WM2200_DSP_CONTROL_29                  0x23
+#define WM2200_DSP_CONTROL_30                  0x24
+#define WM2200_DSP_CONTROL_31                  0x26
 
 /* The code assumes DCVDD is generated internally */
 #define WM2200_NUM_CORE_SUPPLIES 2
@@ -49,6 +84,7 @@ struct wm2200_fll {
 
 /* codec private data */
 struct wm2200_priv {
+       struct wm_adsp dsp[2];
        struct regmap *regmap;
        struct device *dev;
        struct snd_soc_codec *codec;
@@ -64,6 +100,72 @@ struct wm2200_priv {
        int sysclk;
 };
 
+#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
+#define WM2200_DSP_SPACING 12288
+
+#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
+
+static const struct regmap_range_cfg wm2200_ranges[] = {
+       { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE,
+         .range_max = WM2200_DSP1_DM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_3,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
+
+       { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE,
+         .range_max = WM2200_DSP1_PM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_2,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
+
+       { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE,
+         .range_max = WM2200_DSP1_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP1_CONTROL_4,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
+
+       { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE,
+         .range_max = WM2200_DSP2_DM_BASE + 4095,
+         .selector_reg = WM2200_DSP2_CONTROL_3,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
+
+       { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE,
+         .range_max = WM2200_DSP2_PM_BASE + 11287,
+         .selector_reg = WM2200_DSP2_CONTROL_2,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
+
+       { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE,
+         .range_max = WM2200_DSP2_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP2_CONTROL_4,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
+};
+
+static const struct wm_adsp_region wm2200_dsp1_regions[] = {
+       { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE },
+       { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE },
+       { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE },
+};
+
+static const struct wm_adsp_region wm2200_dsp2_regions[] = {
+       { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE },
+       { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE },
+       { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE },
+};
+
 static struct reg_default wm2200_reg_defaults[] = {
        { 0x000B, 0x0000 },   /* R11    - Tone Generator 1 */
        { 0x0102, 0x0000 },   /* R258   - Clocking 3 */
@@ -407,6 +509,16 @@ static struct reg_default wm2200_reg_defaults[] = {
 
 static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -423,6 +535,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 
 static bool wm2200_readable_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -880,7 +1002,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
 static const char *wm2200_mixer_texts[] = {
        "None",
        "Tone Generator",
-       "AEC loopback",
+       "AEC Loopback",
        "IN1L",
        "IN1R",
        "IN2L",
@@ -976,6 +1098,20 @@ static int wm2200_mixer_values[] = {
        static WM2200_MUX_CTL_DECL(name##_in3); \
        static WM2200_MUX_CTL_DECL(name##_in4)
 
+#define WM2200_DSP_ENUMS(name, base_reg) \
+       static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg);     \
+       static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
+       static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
+       static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
+       static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
+       static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
+       static WM2200_MUX_CTL_DECL(name##_aux1); \
+       static WM2200_MUX_CTL_DECL(name##_aux2); \
+       static WM2200_MUX_CTL_DECL(name##_aux3); \
+       static WM2200_MUX_CTL_DECL(name##_aux4); \
+       static WM2200_MUX_CTL_DECL(name##_aux5); \
+       static WM2200_MUX_CTL_DECL(name##_aux6);
+
 static const struct snd_kcontrol_new wm2200_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
           WM2200_IN1_OSR_SHIFT, 1, 0),
@@ -1051,6 +1187,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
 
+WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
+
 WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
 
@@ -1064,8 +1203,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define WM2200_DSP_WIDGETS(name, name_str) \
+       WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
+       WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
+       WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
+
 #define WM2200_MIXER_INPUT_ROUTES(name)        \
        { name, "Tone Generator", "Tone Generator" }, \
+       { name, "AEC Loopback", "AEC Loopback" }, \
         { name, "IN1L", "IN1L PGA" }, \
         { name, "IN1R", "IN1R PGA" }, \
         { name, "IN2L", "IN2L PGA" }, \
@@ -1106,6 +1256,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
        WM2200_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define WM2200_DSP_AUX_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
+
+static const char *wm2200_aec_loopback_texts[] = {
+       "OUT1L", "OUT1R", "OUT2L", "OUT2R",
+};
+
+static const struct soc_enum wm2200_aec_loopback =
+       SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
+                       WM2200_AEC_LOOPBACK_SRC_SHIFT,
+                       ARRAY_SIZE(wm2200_aec_loopback_texts),
+                       wm2200_aec_loopback_texts);
+
+static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
+       SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
+
 static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
                    NULL, 0),
@@ -1165,8 +1342,8 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
                 NULL, 0),
 
-SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+WM_ADSP1("DSP1", 0),
+WM_ADSP1("DSP2", 1),
 
 SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
@@ -1181,6 +1358,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
 SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
 
+SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
+                WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
+
 SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
                   WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
@@ -1231,10 +1411,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"),
 WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
 WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
 
-WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
-WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
-WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
-WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+WM2200_DSP_WIDGETS(DSP1, "DSP1"),
+WM2200_DSP_WIDGETS(DSP2, "DSP2"),
 
 WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
 WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
@@ -1326,11 +1504,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
        { "SPK", NULL, "OUT2L" },
        { "SPK", NULL, "OUT2R" },
 
+       { "AEC Loopback", "OUT1L", "OUT1L" },
+       { "AEC Loopback", "OUT1R", "OUT1R" },
+       { "AEC Loopback", "OUT2L", "OUT2L" },
+       { "AEC Loopback", "OUT2R", "OUT2R" },
+
        WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
        WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
 
+       WM2200_DSP_AUX_ROUTES("DSP1"),
+       WM2200_DSP_AUX_ROUTES("DSP2"),
+
        WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
        WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
        WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
@@ -1968,12 +2154,15 @@ static const struct regmap_config wm2200_regmap = {
        .reg_bits = 16,
        .val_bits = 16,
 
-       .max_register = WM2200_MAX_REGISTER,
+       .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
+                                              WM2200_DSP_SPACING),
        .reg_defaults = wm2200_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
        .volatile_reg = wm2200_volatile_register,
        .readable_reg = wm2200_readable_register,
        .cache_type = REGCACHE_RBTREE,
+       .ranges = wm2200_ranges,
+       .num_ranges = ARRAY_SIZE(wm2200_ranges),
 };
 
 static const unsigned int wm2200_dig_vu[] = {
@@ -1995,8 +2184,8 @@ static const unsigned int wm2200_mic_ctrl_reg[] = {
        WM2200_IN3L_CONTROL,
 };
 
-static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm2200_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm2200_priv *wm2200;
@@ -2011,14 +2200,30 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        wm2200->dev = &i2c->dev;
        init_completion(&wm2200->fll_lock);
 
-       wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+       wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
        if (IS_ERR(wm2200->regmap)) {
                ret = PTR_ERR(wm2200->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
                        ret);
-               goto err;
+               return ret;
+       }
+
+       for (i = 0; i < 2; i++) {
+               wm2200->dsp[i].type = WMFW_ADSP1;
+               wm2200->dsp[i].part = "wm2200";
+               wm2200->dsp[i].num = i + 1;
+               wm2200->dsp[i].dev = &i2c->dev;
+               wm2200->dsp[i].regmap = wm2200->regmap;
        }
 
+       wm2200->dsp[0].base = WM2200_DSP1_CONTROL_1;
+       wm2200->dsp[0].mem = wm2200_dsp1_regions;
+       wm2200->dsp[0].num_mems = ARRAY_SIZE(wm2200_dsp1_regions);
+
+       wm2200->dsp[1].base = WM2200_DSP2_CONTROL_1;
+       wm2200->dsp[1].mem = wm2200_dsp2_regions;
+       wm2200->dsp[1].num_mems = ARRAY_SIZE(wm2200_dsp2_regions);
+
        if (pdata)
                wm2200->pdata = *pdata;
 
@@ -2027,12 +2232,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
                wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
-                                wm2200->core_supplies);
+       ret = devm_regulator_bulk_get(&i2c->dev,
+                                     ARRAY_SIZE(wm2200->core_supplies),
+                                     wm2200->core_supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
                        ret);
-               goto err_regmap;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
@@ -2040,12 +2246,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
                        ret);
-               goto err_core;
+               return ret;
        }
 
        if (wm2200->pdata.ldo_ena) {
-               ret = gpio_request_one(wm2200->pdata.ldo_ena,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 LDOENA");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
                                wm2200->pdata.ldo_ena, ret);
@@ -2055,8 +2262,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.reset) {
-               ret = gpio_request_one(wm2200->pdata.reset,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 /RESET");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
                                wm2200->pdata.reset, ret);
@@ -2166,45 +2374,28 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
 err_pm_runtime:
        pm_runtime_disable(&i2c->dev);
 err_reset:
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
 err_ldo:
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
                               wm2200->core_supplies);
-err_core:
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
-err_regmap:
-       regmap_exit(wm2200->regmap);
-err:
        return ret;
 }
 
-static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+static int wm2200_i2c_remove(struct i2c_client *i2c)
 {
        struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
 
        snd_soc_unregister_codec(&i2c->dev);
        if (i2c->irq)
                free_irq(i2c->irq, wm2200);
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
-       regmap_exit(wm2200->regmap);
 
        return 0;
 }
@@ -2267,7 +2458,7 @@ static struct i2c_driver wm2200_i2c_driver = {
                .pm = &wm2200_pm,
        },
        .probe =    wm2200_i2c_probe,
-       .remove =   __devexit_p(wm2200_i2c_remove),
+       .remove =   wm2200_i2c_remove,
        .id_table = wm2200_i2c_id,
 };
 
index 7f567585832eae40c9ff03b33a49f0612427c877..5a5f3693623568d2d6268e9bc10e7055664c5d3d 100644 (file)
@@ -1233,7 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
        { "PWM2", NULL, "PWM2 Driver" },
 };
 
-static const __devinitconst struct reg_default wm5100_reva_patches[] = {
+static const struct reg_default wm5100_reva_patches[] = {
        { WM5100_AUDIO_IF_1_10, 0 },
        { WM5100_AUDIO_IF_1_11, 1 },
        { WM5100_AUDIO_IF_1_12, 2 },
@@ -2414,8 +2414,8 @@ static const unsigned int wm5100_mic_ctrl_reg[] = {
        WM5100_IN4L_CONTROL,
 };
 
-static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm5100_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm5100_priv *wm5100;
@@ -2639,7 +2639,7 @@ err:
        return ret;
 }
 
-static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
+static int wm5100_i2c_remove(struct i2c_client *i2c)
 {
        struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
 
@@ -2717,7 +2717,7 @@ static struct i2c_driver wm5100_i2c_driver = {
                .pm = &wm5100_pm,
        },
        .probe =    wm5100_i2c_probe,
-       .remove =   __devexit_p(wm5100_i2c_remove),
+       .remove =   wm5100_i2c_remove,
        .id_table = wm5100_i2c_id,
 };
 
index 7394e73fa43c0e526e7ab4e83480fb89bbf9891d..688ade0805897557baac586aeb6387a70361fd2c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "arizona.h"
 #include "wm5102.h"
+#include "wm_adsp.h"
 
 struct wm5102_priv {
        struct arizona_priv core;
@@ -42,6 +43,13 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct wm_adsp_region wm5102_dsp1_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
+};
+
 static const struct reg_default wm5102_sysclk_reva_patch[] = {
        { 0x3000, 0x2225 },
        { 0x3001, 0x3a03 },
@@ -627,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
                 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+                  ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+                  ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+                  ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+                  ARIZONA_EQ4_ENA_MASK),
+
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -687,6 +707,14 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
+ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -708,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-          ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-          ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-          ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
-          ARIZONA_OUT4_OSR_SHIFT, 1, 0),
 SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
           ARIZONA_OUT5_OSR_SHIFT, 1, 0),
 
@@ -745,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
                 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_1R,
-                      ARIZONA_OUT1L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_2R,
-                      ARIZONA_OUT2L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-                    ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
 
 SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
           ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
@@ -819,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
 
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
 
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
 
 static const char *wm5102_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@@ -864,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
 
 SND_SOC_DAPM_SIGGEN("TONE"),
 SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
 
 SND_SOC_DAPM_INPUT("IN1L"),
 SND_SOC_DAPM_INPUT("IN1R"),
@@ -894,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
                    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
 
 SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
                 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@@ -996,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
 SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
                    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
 
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
                       ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
 
@@ -1071,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
 
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
+
+WM_ADSP2("DSP1", 0),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1094,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "Noise Generator", "Noise Generator" }, \
        { name, "Tone Generator 1", "Tone Generator 1" }, \
        { name, "Tone Generator 2", "Tone Generator 2" }, \
+       { name, "Haptics", "HAPTICS" }, \
        { name, "AEC", "AEC Loopback" }, \
        { name, "IN1L", "IN1L PGA" }, \
        { name, "IN1R", "IN1R PGA" }, \
@@ -1127,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "ASRC1L", "ASRC1L" }, \
        { name, "ASRC1R", "ASRC1R" }, \
        { name, "ASRC2L", "ASRC2L" }, \
-       { name, "ASRC2R", "ASRC2R" }
+       { name, "ASRC2R", "ASRC2R" }, \
+       { name, "DSP1.1", "DSP1" }, \
+       { name, "DSP1.2", "DSP1" }, \
+       { name, "DSP1.3", "DSP1" }, \
+       { name, "DSP1.4", "DSP1" }, \
+       { name, "DSP1.5", "DSP1" }, \
+       { name, "DSP1.6", "DSP1" }
 
 static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "AIF2 Capture", NULL, "DBVDD2" },
@@ -1213,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "IN3L PGA", NULL, "IN3L" },
        { "IN3R PGA", NULL, "IN3R" },
 
+       { "ASRC1L", NULL, "ASRC1L Input" },
+       { "ASRC1R", NULL, "ASRC1R Input" },
+       { "ASRC2L", NULL, "ASRC2L Input" },
+       { "ASRC2R", NULL, "ASRC2R Input" },
+
        ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
        ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
        ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@@ -1255,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
        ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
 
-       ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
-       ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
-       ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
-       ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+       ARIZONA_MUX_ROUTES("ASRC1L"),
+       ARIZONA_MUX_ROUTES("ASRC1R"),
+       ARIZONA_MUX_ROUTES("ASRC2L"),
+       ARIZONA_MUX_ROUTES("ASRC2R"),
+
+       ARIZONA_DSP_ROUTES("DSP1"),
 
        { "AEC Loopback", "HPOUT1L", "OUT1L" },
        { "AEC Loopback", "HPOUT1R", "OUT1R" },
@@ -1377,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 static int wm5102_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        codec->control_data = priv->core.arizona->regmap;
-       return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+
+       ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       if (ret != 0)
+               return ret;
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+       priv->core.arizona->dapm = &codec->dapm;
+
+       return 0;
+}
+
+static int wm5102_codec_remove(struct snd_soc_codec *codec)
+{
+       struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->core.arizona->dapm = NULL;
+
+       return 0;
 }
 
 #define WM5102_DIG_VU 0x0200
@@ -1406,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
        .probe = wm5102_codec_probe,
+       .remove = wm5102_codec_remove,
 
        .idle_bias_off = true,
 
@@ -1420,11 +1475,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
        .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
 };
 
-static int __devinit wm5102_probe(struct platform_device *pdev)
+static int wm5102_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct wm5102_priv *wm5102;
-       int i;
+       int i, ret;
 
        wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
                              GFP_KERNEL);
@@ -1434,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
 
        wm5102->core.arizona = arizona;
 
+       wm5102->core.adsp[0].part = "wm5102";
+       wm5102->core.adsp[0].num = 1;
+       wm5102->core.adsp[0].type = WMFW_ADSP2;
+       wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
+       wm5102->core.adsp[0].dev = arizona->dev;
+       wm5102->core.adsp[0].regmap = arizona->regmap;
+       wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
+       wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
+
+       ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+       if (ret != 0)
+               return ret;
+
        for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
                wm5102->fll[i].vco_mult = 1;
 
@@ -1459,7 +1527,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
                                      wm5102_dai, ARRAY_SIZE(wm5102_dai));
 }
 
-static int __devexit wm5102_remove(struct platform_device *pdev)
+static int wm5102_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -1473,7 +1541,7 @@ static struct platform_driver wm5102_codec_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm5102_probe,
-       .remove = __devexit_p(wm5102_remove),
+       .remove = wm5102_remove,
 };
 
 module_platform_driver(wm5102_codec_driver);
index 9211e4192f710b305ca46420e0be64037a0f6967..ae80c8c285360cffd1ef82af06626ceccf2769d2 100644 (file)
@@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
                 ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+                  ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+                  ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+                  ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+                  ARIZONA_EQ4_ENA_MASK),
+
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -148,6 +160,11 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
 SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
           ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
 
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
@@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
 
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
 
 static const char *wm5110_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
@@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
 
 SND_SOC_DAPM_SIGGEN("TONE"),
 SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
 
 SND_SOC_DAPM_INPUT("IN1L"),
 SND_SOC_DAPM_INPUT("IN1R"),
@@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
 
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
        { name, "Noise Generator", "Noise Generator" }, \
        { name, "Tone Generator 1", "Tone Generator 1" }, \
        { name, "Tone Generator 2", "Tone Generator 2" }, \
+       { name, "Haptics", "HAPTICS" }, \
        { name, "AEC", "AEC Loopback" }, \
        { name, "IN1L", "IN1L PGA" }, \
        { name, "IN1R", "IN1R PGA" }, \
@@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
        ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
 
-       ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
-       ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
-       ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
-       ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+       ARIZONA_MUX_ROUTES("ASRC1L"),
+       ARIZONA_MUX_ROUTES("ASRC1R"),
+       ARIZONA_MUX_ROUTES("ASRC2L"),
+       ARIZONA_MUX_ROUTES("ASRC2R"),
 
        { "HPOUT1L", NULL, "OUT1L" },
        { "HPOUT1R", NULL, "OUT1R" },
@@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 static int wm5110_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        codec->control_data = priv->core.arizona->regmap;
-       return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       priv->core.arizona->dapm = &codec->dapm;
+
+       ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       if (ret != 0)
+               return ret;
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+       priv->core.arizona->dapm = &codec->dapm;
+
+       return 0;
+}
+
+static int wm5110_codec_remove(struct snd_soc_codec *codec)
+{
+       struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->core.arizona->dapm = NULL;
+
+       return 0;
 }
 
 #define WM5110_DIG_VU 0x0200
@@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
        .probe = wm5110_codec_probe,
+       .remove = wm5110_codec_remove,
 
        .idle_bias_off = true,
 
@@ -949,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
        .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
 };
 
-static int __devinit wm5110_probe(struct platform_device *pdev)
+static int wm5110_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct wm5110_priv *wm5110;
@@ -988,7 +1031,7 @@ static int __devinit wm5110_probe(struct platform_device *pdev)
                                      wm5110_dai, ARRAY_SIZE(wm5110_dai));
 }
 
-static int __devexit wm5110_remove(struct platform_device *pdev)
+static int wm5110_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -1002,7 +1045,7 @@ static struct platform_driver wm5110_codec_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm5110_probe,
-       .remove = __devexit_p(wm5110_remove),
+       .remove = wm5110_remove,
 };
 
 module_platform_driver(wm5110_codec_driver);
index a4cae060bf2626de702f88c4b62dee0e3f110860..fb92fb47d636c1a92d04d1633b9aacf2d42b31d7 100644 (file)
@@ -1500,7 +1500,7 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
        for (i = 0; i < ARRAY_SIZE(supply_names); i++)
                priv->supplies[i].supply = supply_names[i];
 
-       ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+       ret = devm_regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
                                 priv->supplies);
        if (ret != 0)
                return ret;
@@ -1607,8 +1607,6 @@ static int  wm8350_codec_remove(struct snd_soc_codec *codec)
 
        wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
 
-       regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-
        return 0;
 }
 
@@ -1627,13 +1625,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
        .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes),
 };
 
-static int __devinit wm8350_probe(struct platform_device *pdev)
+static int wm8350_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
                        &wm8350_dai, 1);
 }
 
-static int __devexit wm8350_remove(struct platform_device *pdev)
+static int wm8350_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -1645,7 +1643,7 @@ static struct platform_driver wm8350_codec_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = wm8350_probe,
-       .remove = __devexit_p(wm8350_remove),
+       .remove = wm8350_remove,
 };
 
 module_platform_driver(wm8350_codec_driver);
index 5d277a915f8180a4a5b4bc301ecad54d7b7c6b9f..af6d227e67be02f72da11eaefa12a97d2fcd8c80 100644 (file)
@@ -1373,7 +1373,7 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
        codec->control_data = priv->wm8400 = wm8400;
        priv->codec = codec;
 
-       ret = regulator_bulk_get(wm8400->dev,
+       ret = devm_regulator_bulk_get(wm8400->dev,
                                 ARRAY_SIZE(power), &power[0]);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
@@ -1398,15 +1398,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-       if (!schedule_work(&priv->work)) {
-               ret = -EINVAL;
-               goto err_regulator;
-       }
+       if (!schedule_work(&priv->work))
+               return -EINVAL;
        return 0;
-
-err_regulator:
-       regulator_bulk_free(ARRAY_SIZE(power), power);
-       return ret;
 }
 
 static int  wm8400_codec_remove(struct snd_soc_codec *codec)
@@ -1417,8 +1411,6 @@ static int  wm8400_codec_remove(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1,
                     reg & (~WM8400_CODEC_ENA));
 
-       regulator_bulk_free(ARRAY_SIZE(power), power);
-
        return 0;
 }
 
@@ -1439,13 +1431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
        .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
 };
 
-static int __devinit wm8400_probe(struct platform_device *pdev)
+static int wm8400_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
                        &wm8400_dai, 1);
 }
 
-static int __devexit wm8400_remove(struct platform_device *pdev)
+static int wm8400_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -1457,7 +1449,7 @@ static struct platform_driver wm8400_codec_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = wm8400_probe,
-       .remove = __devexit_p(wm8400_remove),
+       .remove = wm8400_remove,
 };
 
 module_platform_driver(wm8400_codec_driver);
index c12a54e72e891d071a51e2c4d069c006c6a9ff18..6ed5433943eaae4716f54a75f7b4cf4d9fd83fc2 100644 (file)
@@ -608,10 +608,7 @@ static int wm8510_probe(struct snd_soc_codec *codec)
 /* power down chip */
 static int wm8510_remove(struct snd_soc_codec *codec)
 {
-       struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
-
        wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       kfree(wm8510);
        return 0;
 }
 
@@ -648,7 +645,7 @@ static const struct regmap_config wm8510_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8510_spi_probe(struct spi_device *spi)
+static int wm8510_spi_probe(struct spi_device *spi)
 {
        struct wm8510_priv *wm8510;
        int ret;
@@ -670,7 +667,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8510_spi_remove(struct spi_device *spi)
+static int wm8510_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -683,13 +680,13 @@ static struct spi_driver wm8510_spi_driver = {
                .of_match_table = wm8510_of_match,
        },
        .probe          = wm8510_spi_probe,
-       .remove         = __devexit_p(wm8510_spi_remove),
+       .remove         = wm8510_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8510_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8510_priv *wm8510;
        int ret;
@@ -711,7 +708,7 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8510_i2c_remove(struct i2c_client *client)
+static int wm8510_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -730,7 +727,7 @@ static struct i2c_driver wm8510_i2c_driver = {
                .of_match_table = wm8510_of_match,
        },
        .probe =    wm8510_i2c_probe,
-       .remove =   __devexit_p(wm8510_i2c_remove),
+       .remove =   wm8510_i2c_remove,
        .id_table = wm8510_i2c_id,
 };
 #endif
index 8d5c276735012361cebb34f24dd123f0564354a3..139bf9ac94078152470fc639816a328eac8dbfa6 100644 (file)
@@ -453,8 +453,8 @@ static const struct regmap_config wm8523_regmap = {
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8523_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8523_priv *wm8523;
        unsigned int val;
@@ -528,7 +528,7 @@ err_enable:
        return ret;
 }
 
-static __devexit int wm8523_i2c_remove(struct i2c_client *client)
+static int wm8523_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -547,7 +547,7 @@ static struct i2c_driver wm8523_i2c_driver = {
                .of_match_table = wm8523_of_match,
        },
        .probe =    wm8523_i2c_probe,
-       .remove =   __devexit_p(wm8523_i2c_remove),
+       .remove =   wm8523_i2c_remove,
        .id_table = wm8523_i2c_id,
 };
 #endif
index 8b8bb70f1eb959e5ef3a762e88ffce716f75107d..5b428b060d418da78286a605060c4cb4c019801b 100644 (file)
@@ -429,7 +429,7 @@ static const struct regmap_config wm8711_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8711_spi_probe(struct spi_device *spi)
+static int wm8711_spi_probe(struct spi_device *spi)
 {
        struct wm8711_priv *wm8711;
        int ret;
@@ -451,7 +451,7 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8711_spi_remove(struct spi_device *spi)
+static int wm8711_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
 
@@ -465,13 +465,13 @@ static struct spi_driver wm8711_spi_driver = {
                .of_match_table = wm8711_of_match,
        },
        .probe          = wm8711_spi_probe,
-       .remove         = __devexit_p(wm8711_spi_remove),
+       .remove         = wm8711_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8711_i2c_probe(struct i2c_client *client,
-                                     const struct i2c_device_id *id)
+static int wm8711_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
 {
        struct wm8711_priv *wm8711;
        int ret;
@@ -493,7 +493,7 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static __devexit int wm8711_i2c_remove(struct i2c_client *client)
+static int wm8711_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -512,7 +512,7 @@ static struct i2c_driver wm8711_i2c_driver = {
                .of_match_table = wm8711_of_match,
        },
        .probe =    wm8711_i2c_probe,
-       .remove =   __devexit_p(wm8711_i2c_remove),
+       .remove =   wm8711_i2c_remove,
        .id_table = wm8711_i2c_id,
 };
 #endif
index e81705620718eacf785fc10ecab3d74a0adbebcb..462f5e4d5c05ffcc3c4876d35bca320ff1743afb 100644 (file)
@@ -45,13 +45,13 @@ static struct snd_soc_dai_driver wm8727_dai = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm8727;
 
-static __devinit int wm8727_probe(struct platform_device *pdev)
+static int wm8727_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_wm8727, &wm8727_dai, 1);
 }
 
-static int __devexit wm8727_remove(struct platform_device *pdev)
+static int wm8727_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -64,7 +64,7 @@ static struct platform_driver wm8727_codec_driver = {
        },
 
        .probe = wm8727_probe,
-       .remove = __devexit_p(wm8727_remove),
+       .remove = wm8727_remove,
 };
 
 module_platform_driver(wm8727_codec_driver);
index 00a12a0c3919b12e1cf325a84d82bec1031e9b04..c6a292dcded0c11eda10c5dfa8fd70e2be84ec0c 100644 (file)
@@ -280,7 +280,7 @@ static const struct regmap_config wm8728_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8728_spi_probe(struct spi_device *spi)
+static int wm8728_spi_probe(struct spi_device *spi)
 {
        struct wm8728_priv *wm8728;
        int ret;
@@ -302,7 +302,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8728_spi_remove(struct spi_device *spi)
+static int wm8728_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
 
@@ -316,13 +316,13 @@ static struct spi_driver wm8728_spi_driver = {
                .of_match_table = wm8728_of_match,
        },
        .probe          = wm8728_spi_probe,
-       .remove         = __devexit_p(wm8728_spi_remove),
+       .remove         = wm8728_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8728_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8728_priv *wm8728;
        int ret;
@@ -344,7 +344,7 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8728_i2c_remove(struct i2c_client *client)
+static int wm8728_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -363,7 +363,7 @@ static struct i2c_driver wm8728_i2c_driver = {
                .of_match_table = wm8728_of_match,
        },
        .probe =    wm8728_i2c_probe,
-       .remove =   __devexit_p(wm8728_i2c_remove),
+       .remove =   wm8728_i2c_remove,
        .id_table = wm8728_i2c_id,
 };
 #endif
index bb1d26919b10c1ce05553317ede7a25c05c4e006..5276062d6c79fa59d0c2c0992a5f9b52993fa156 100644 (file)
@@ -631,7 +631,7 @@ static const struct regmap_config wm8731_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8731_spi_probe(struct spi_device *spi)
+static int wm8731_spi_probe(struct spi_device *spi)
 {
        struct wm8731_priv *wm8731;
        int ret;
@@ -661,7 +661,7 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit wm8731_spi_remove(struct spi_device *spi)
+static int wm8731_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -674,13 +674,13 @@ static struct spi_driver wm8731_spi_driver = {
                .of_match_table = wm8731_of_match,
        },
        .probe          = wm8731_spi_probe,
-       .remove         = __devexit_p(wm8731_spi_remove),
+       .remove         = wm8731_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8731_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8731_priv *wm8731;
        int ret;
@@ -710,7 +710,7 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
        return 0;
 }
 
-static __devexit int wm8731_i2c_remove(struct i2c_client *client)
+static int wm8731_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -729,7 +729,7 @@ static struct i2c_driver wm8731_i2c_driver = {
                .of_match_table = wm8731_of_match,
        },
        .probe =    wm8731_i2c_probe,
-       .remove =   __devexit_p(wm8731_i2c_remove),
+       .remove =   wm8731_i2c_remove,
        .id_table = wm8731_i2c_id,
 };
 #endif
index 5c9634f4c1f054c00d7e69f3d1e1c67041be6b99..2f167a8ca01b507cb3b61521de5db174b186b073 100644 (file)
@@ -645,8 +645,8 @@ static const struct regmap_config wm8737_regmap = {
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8737_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8737_priv *wm8737;
        int ret, i;
@@ -679,7 +679,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
 
 }
 
-static __devexit int wm8737_i2c_remove(struct i2c_client *client)
+static int wm8737_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -699,13 +699,13 @@ static struct i2c_driver wm8737_i2c_driver = {
                .of_match_table = wm8737_of_match,
        },
        .probe =    wm8737_i2c_probe,
-       .remove =   __devexit_p(wm8737_i2c_remove),
+       .remove =   wm8737_i2c_remove,
        .id_table = wm8737_i2c_id,
 };
 #endif
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8737_spi_probe(struct spi_device *spi)
+static int wm8737_spi_probe(struct spi_device *spi)
 {
        struct wm8737_priv *wm8737;
        int ret, i;
@@ -737,7 +737,7 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8737_spi_remove(struct spi_device *spi)
+static int wm8737_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
 
@@ -751,7 +751,7 @@ static struct spi_driver wm8737_spi_driver = {
                .of_match_table = wm8737_of_match,
        },
        .probe          = wm8737_spi_probe,
-       .remove         = __devexit_p(wm8737_spi_remove),
+       .remove         = wm8737_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
index 4281a08021384d30f0eb4673e9298f5e862f7d86..b18813cc7ba9f06c87b399834abbceac5d3b9f49 100644 (file)
@@ -522,7 +522,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap);
+       wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap);
        if (IS_ERR(wm8741->regmap)) {
                ret = PTR_ERR(wm8741->regmap);
                dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -562,7 +562,7 @@ static struct i2c_driver wm8741_i2c_driver = {
 #endif
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8741_spi_probe(struct spi_device *spi)
+static int wm8741_spi_probe(struct spi_device *spi)
 {
        struct wm8741_priv *wm8741;
        int ret, i;
@@ -582,7 +582,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
                return ret;
        }
 
-       wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap);
+       wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap);
        if (IS_ERR(wm8741->regmap)) {
                ret = PTR_ERR(wm8741->regmap);
                dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
@@ -596,7 +596,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8741_spi_remove(struct spi_device *spi)
+static int wm8741_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -609,7 +609,7 @@ static struct spi_driver wm8741_spi_driver = {
                .of_match_table = wm8741_of_match,
        },
        .probe          = wm8741_spi_probe,
-       .remove         = __devexit_p(wm8741_spi_remove),
+       .remove         = wm8741_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
index 89151ca5e7766b69cd57447e611fcf1301fd301f..50d5ff616232676bb094054d44a0c1076ddba0ab 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
  * We can't read the WM8750 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8750_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8750_reg_defaults[] = {
+       {  0, 0x0097 },
+       {  1, 0x0097 },
+       {  2, 0x0079 },
+       {  3, 0x0079 },
+       {  4, 0x0000 },
+       {  5, 0x0008 },
+       {  6, 0x0000 },
+       {  7, 0x000a },
+       {  8, 0x0000 },
+       {  9, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 14, 0x0000 },
+       { 15, 0x0000 },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 38, 0x0050 },
+       { 39, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
 /* codec private data */
 struct wm8750_priv {
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
 };
 
 #define wm8750_reset(c)        snd_soc_write(c, WM8750_RESET, 0)
@@ -668,10 +700,9 @@ static int wm8750_resume(struct snd_soc_codec *codec)
 
 static int wm8750_probe(struct snd_soc_codec *codec)
 {
-       struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -711,9 +742,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
        .suspend =      wm8750_suspend,
        .resume =       wm8750_resume,
        .set_bias_level = wm8750_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8750_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8750_reg,
 
        .controls = wm8750_snd_controls,
        .num_controls = ARRAY_SIZE(wm8750_snd_controls),
@@ -730,10 +758,21 @@ static const struct of_device_id wm8750_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8750_of_match);
 
+static const struct regmap_config wm8750_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8750_MOUTV,
+
+       .reg_defaults = wm8750_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8750_spi_probe(struct spi_device *spi)
+static int wm8750_spi_probe(struct spi_device *spi)
 {
        struct wm8750_priv *wm8750;
+       struct regmap *regmap;
        int ret;
 
        wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
@@ -741,7 +780,10 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
        if (wm8750 == NULL)
                return -ENOMEM;
 
-       wm8750->control_type = SND_SOC_SPI;
+       regmap = devm_regmap_init_spi(spi, &wm8750_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        spi_set_drvdata(spi, wm8750);
 
        ret = snd_soc_register_codec(&spi->dev,
@@ -749,7 +791,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8750_spi_remove(struct spi_device *spi)
+static int wm8750_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -770,15 +812,16 @@ static struct spi_driver wm8750_spi_driver = {
        },
        .id_table       = wm8750_spi_ids,
        .probe          = wm8750_spi_probe,
-       .remove         = __devexit_p(wm8750_spi_remove),
+       .remove         = wm8750_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8750_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8750_priv *wm8750;
+       struct regmap *regmap;
        int ret;
 
        wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
@@ -787,14 +830,17 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8750);
-       wm8750->control_type = SND_SOC_I2C;
+
+       regmap = devm_regmap_init_i2c(i2c, &wm8750_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8750, &wm8750_dai, 1);
        return ret;
 }
 
-static __devexit int wm8750_i2c_remove(struct i2c_client *client)
+static int wm8750_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -814,7 +860,7 @@ static struct i2c_driver wm8750_i2c_driver = {
                .of_match_table = wm8750_of_match,
        },
        .probe =    wm8750_i2c_probe,
-       .remove =   __devexit_p(wm8750_i2c_remove),
+       .remove =   wm8750_i2c_remove,
        .id_table = wm8750_i2c_id,
 };
 #endif
index 2e4a775ae560861543f9d2d1bb74aef096e5181d..0a4ab4c423d123f0bf1ce0e16ed6d261c4b5a52d 100644 (file)
@@ -1550,7 +1550,7 @@ static const struct regmap_config wm8753_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8753_spi_probe(struct spi_device *spi)
+static int wm8753_spi_probe(struct spi_device *spi)
 {
        struct wm8753_priv *wm8753;
        int ret;
@@ -1562,36 +1562,25 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, wm8753);
 
-       wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+       wm8753->regmap = devm_regmap_init_spi(spi, &wm8753_regmap);
        if (IS_ERR(wm8753->regmap)) {
                ret = PTR_ERR(wm8753->regmap);
                dev_err(&spi->dev, "Failed to allocate register map: %d\n",
                        ret);
-               goto err;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
                                     wm8753_dai, ARRAY_SIZE(wm8753_dai));
-       if (ret != 0) {
+       if (ret != 0)
                dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
-               goto err_regmap;
-       }
 
-       return 0;
-
-err_regmap:
-       regmap_exit(wm8753->regmap);
-err:
        return ret;
 }
 
-static int __devexit wm8753_spi_remove(struct spi_device *spi)
+static int wm8753_spi_remove(struct spi_device *spi)
 {
-       struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
-
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(wm8753->regmap);
-       kfree(wm8753);
        return 0;
 }
 
@@ -1602,13 +1591,13 @@ static struct spi_driver wm8753_spi_driver = {
                .of_match_table = wm8753_of_match,
        },
        .probe          = wm8753_spi_probe,
-       .remove         = __devexit_p(wm8753_spi_remove),
+       .remove         = wm8753_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8753_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8753_priv *wm8753;
        int ret;
@@ -1620,35 +1609,25 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm8753);
 
-       wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+       wm8753->regmap = devm_regmap_init_i2c(i2c, &wm8753_regmap);
        if (IS_ERR(wm8753->regmap)) {
                ret = PTR_ERR(wm8753->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
                        ret);
-               goto err;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
                                     wm8753_dai, ARRAY_SIZE(wm8753_dai));
-       if (ret != 0) {
+       if (ret != 0)
                dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
-               goto err_regmap;
-       }
 
-       return 0;
-
-err_regmap:
-       regmap_exit(wm8753->regmap);
-err:
        return ret;
 }
 
-static __devexit int wm8753_i2c_remove(struct i2c_client *client)
+static int wm8753_i2c_remove(struct i2c_client *client)
 {
-       struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm8753->regmap);
        return 0;
 }
 
@@ -1665,7 +1644,7 @@ static struct i2c_driver wm8753_i2c_driver = {
                .of_match_table = wm8753_of_match,
        },
        .probe =    wm8753_i2c_probe,
-       .remove =   __devexit_p(wm8753_i2c_remove),
+       .remove =   wm8753_i2c_remove,
        .id_table = wm8753_i2c_id,
 };
 #endif
index c7c0034d39669a5e4b548bd7a46f40eb716f00cd..89a18d82f303e168f874a418840a9d33a4923910 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_device.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
        "DVDD"
 };
 
-static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
-       0x7f, 0x7f, 0x7f, 0x7f,
-       0x7f, 0x7f, 0x7f, 0x7f,
-       0x7f, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0, 0x90, 0,
-       0, 0x22, 0x22, 0x3e,
-       0xc, 0xc, 0x100, 0x189,
-       0x189, 0x8770
+static const struct reg_default wm8770_reg_defaults[] = {
+       {  0, 0x7f },
+       {  1, 0x7f },
+       {  2, 0x7f },
+       {  3, 0x7f },
+       {  4, 0x7f },
+       {  5, 0x7f },
+       {  6, 0x7f },
+       {  7, 0x7f },
+       {  8, 0x7f },
+       {  9, 0xff },
+       { 10, 0xff },
+       { 11, 0xff },
+       { 12, 0xff },
+       { 13, 0xff },
+       { 14, 0xff },
+       { 15, 0xff },
+       { 16, 0xff },
+       { 17, 0xff },
+       { 18, 0    },
+       { 19, 0x90 },
+       { 20, 0    },
+       { 21, 0    },
+       { 22, 0x22 },
+       { 23, 0x22 },
+       { 24, 0x3e },
+       { 25, 0xc  },
+       { 26, 0xc  },
+       { 27, 0x100 },
+       { 28, 0x189 },
+       { 29, 0x189 },
+       { 30, 0x8770 },
 };
 
+static bool wm8770_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8770_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
+
 struct wm8770_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
        struct snd_soc_codec *codec;
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \
        struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
                                     disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8770->codec->cache_sync = 1; \
+               regcache_mark_dirty(wm8770->regmap);    \
        } \
        return 0; \
 }
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai,
        return 0;
 }
 
-static void wm8770_sync_cache(struct snd_soc_codec *codec)
-{
-       int i;
-       u16 *cache;
-
-       if (!codec->cache_sync)
-               return;
-
-       codec->cache_only = 0;
-       cache = codec->reg_cache;
-       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
-                       continue;
-               snd_soc_write(codec, i, cache[i]);
-       }
-       codec->cache_sync = 0;
-}
-
 static int wm8770_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
                                        ret);
                                return ret;
                        }
-                       wm8770_sync_cache(codec);
+
+                       regcache_sync(wm8770->regmap);
+
                        /* global powerup */
                        snd_soc_write(codec, WM8770_PWDNCTRL, 0);
                }
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = {
        .symmetric_rates = 1
 };
 
-#ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec)
-{
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
-
-static int wm8770_resume(struct snd_soc_codec *codec)
-{
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       return 0;
-}
-#else
-#define wm8770_suspend NULL
-#define wm8770_resume NULL
-#endif
-
 static int wm8770_probe(struct snd_soc_codec *codec)
 {
        struct wm8770_priv *wm8770;
        int ret;
-       int i;
 
        wm8770 = snd_soc_codec_get_drvdata(codec);
        wm8770->codec = codec;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
-               wm8770->supplies[i].supply = wm8770_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
-                                wm8770->supplies);
-       if (ret) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               return ret;
-       }
-
-       wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
-       wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
-       wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
-
-       /* This should really be moved into the regulator core */
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
-               ret = regulator_register_notifier(wm8770->supplies[i].consumer,
-                                                 &wm8770->disable_nb[i]);
-               if (ret) {
-                       dev_err(codec->dev,
-                               "Failed to register regulator notifier: %d\n",
-                               ret);
-               }
-       }
-
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
                                    wm8770->supplies);
        if (ret) {
                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_reg_get;
+               return ret;
        }
 
        ret = wm8770_reset(codec);
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
                goto err_reg_enable;
        }
 
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        /* latch the volume update bits */
        snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
        snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec)
        /* mute all DACs */
        snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
 
-       snd_soc_add_codec_controls(codec, wm8770_snd_controls,
-                            ARRAY_SIZE(wm8770_snd_controls));
-       snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
-                                 ARRAY_SIZE(wm8770_dapm_widgets));
-       snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
-                               ARRAY_SIZE(wm8770_intercon));
-       return 0;
-
 err_reg_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-err_reg_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
        return ret;
 }
 
-static int wm8770_remove(struct snd_soc_codec *codec)
-{
-       struct wm8770_priv *wm8770;
-       int i;
-
-       wm8770 = snd_soc_codec_get_drvdata(codec);
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
-               regulator_unregister_notifier(wm8770->supplies[i].consumer,
-                                             &wm8770->disable_nb[i]);
-       regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-       return 0;
-}
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
        .probe = wm8770_probe,
-       .remove = wm8770_remove,
-       .suspend = wm8770_suspend,
-       .resume = wm8770_resume,
        .set_bias_level = wm8770_set_bias_level,
        .idle_bias_off = true,
-       .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
-       .reg_word_size = sizeof (u16),
-       .reg_cache_default = wm8770_reg_defs
+
+       .controls = wm8770_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8770_snd_controls),
+       .dapm_widgets = wm8770_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets),
+       .dapm_routes = wm8770_intercon,
+       .num_dapm_routes = ARRAY_SIZE(wm8770_intercon),
 };
 
 static const struct of_device_id wm8770_of_match[] = {
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8770_of_match);
 
-static int __devinit wm8770_spi_probe(struct spi_device *spi)
+static const struct regmap_config wm8770_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8770_RESET,
+
+       .reg_defaults = wm8770_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+
+       .volatile_reg = wm8770_volatile_reg,
+};
+
+static int wm8770_spi_probe(struct spi_device *spi)
 {
        struct wm8770_priv *wm8770;
-       int ret;
+       int ret, i;
 
        wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
                              GFP_KERNEL);
        if (!wm8770)
                return -ENOMEM;
 
-       wm8770->control_type = SND_SOC_SPI;
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
+               wm8770->supplies[i].supply = wm8770_supply_names[i];
+
+       ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies),
+                                     wm8770->supplies);
+       if (ret) {
+               dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
+       }
+
+       wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
+       wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
+       wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
+
+       /* This should really be moved into the regulator core */
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
+               ret = regulator_register_notifier(wm8770->supplies[i].consumer,
+                                                 &wm8770->disable_nb[i]);
+               if (ret) {
+                       dev_err(&spi->dev,
+                               "Failed to register regulator notifier: %d\n",
+                               ret);
+               }
+       }
+
+       wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap);
+       if (IS_ERR(wm8770->regmap))
+               return PTR_ERR(wm8770->regmap);
+
        spi_set_drvdata(spi, wm8770);
 
        ret = snd_soc_register_codec(&spi->dev,
@@ -708,9 +697,17 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8770_spi_remove(struct spi_device *spi)
+static int wm8770_spi_remove(struct spi_device *spi)
 {
+       struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
+               regulator_unregister_notifier(wm8770->supplies[i].consumer,
+                                             &wm8770->disable_nb[i]);
+
        snd_soc_unregister_codec(&spi->dev);
+
        return 0;
 }
 
@@ -721,7 +718,7 @@ static struct spi_driver wm8770_spi_driver = {
                .of_match_table = wm8770_of_match,
        },
        .probe = wm8770_spi_probe,
-       .remove = __devexit_p(wm8770_spi_remove)
+       .remove = wm8770_spi_remove
 };
 
 module_spi_driver(wm8770_spi_driver);
index c32249ddb2e025c4cb457095f47524b4e334424e..f31017ed138128badd671cf851a029d5171ae7f9 100644 (file)
@@ -492,7 +492,7 @@ static const struct regmap_config wm8776_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8776_spi_probe(struct spi_device *spi)
+static int wm8776_spi_probe(struct spi_device *spi)
 {
        struct wm8776_priv *wm8776;
        int ret;
@@ -514,7 +514,7 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8776_spi_remove(struct spi_device *spi)
+static int wm8776_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -527,13 +527,13 @@ static struct spi_driver wm8776_spi_driver = {
                .of_match_table = wm8776_of_match,
        },
        .probe          = wm8776_spi_probe,
-       .remove         = __devexit_p(wm8776_spi_remove),
+       .remove         = wm8776_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8776_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8776_priv *wm8776;
        int ret;
@@ -555,7 +555,7 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8776_i2c_remove(struct i2c_client *client)
+static int wm8776_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -575,7 +575,7 @@ static struct i2c_driver wm8776_i2c_driver = {
                .of_match_table = wm8776_of_match,
        },
        .probe =    wm8776_i2c_probe,
-       .remove =   __devexit_p(wm8776_i2c_remove),
+       .remove =   wm8776_i2c_remove,
        .id_table = wm8776_i2c_id,
 };
 #endif
index 3fdea98f732ec3814dd96f2150ffa5fe4c6b4349..f1fdbf63abb4f41e4e8c1a69b92e1357f3d6df00 100644 (file)
@@ -42,13 +42,13 @@ static struct snd_soc_dai_driver wm8782_dai = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm8782;
 
-static __devinit int wm8782_probe(struct platform_device *pdev)
+static int wm8782_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_wm8782, &wm8782_dai, 1);
 }
 
-static int __devexit wm8782_remove(struct platform_device *pdev)
+static int wm8782_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8782_probe,
-       .remove = __devexit_p(wm8782_remove),
+       .remove = wm8782_remove,
 };
 
 module_platform_driver(wm8782_codec_driver);
index c088020172ab66e25bbc8e0f30f554b77debb202..d321a875b029dc693fb2b7483dd73ceea1ce4ee8 100644 (file)
@@ -702,7 +702,7 @@ static struct regmap_config wm8804_regmap_config = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8804_spi_probe(struct spi_device *spi)
+static int wm8804_spi_probe(struct spi_device *spi)
 {
        struct wm8804_priv *wm8804;
        int ret;
@@ -711,7 +711,7 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
        if (!wm8804)
                return -ENOMEM;
 
-       wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+       wm8804->regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config);
        if (IS_ERR(wm8804->regmap)) {
                ret = PTR_ERR(wm8804->regmap);
                return ret;
@@ -725,11 +725,9 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8804_spi_remove(struct spi_device *spi)
+static int wm8804_spi_remove(struct spi_device *spi)
 {
-       struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(wm8804->regmap);
        return 0;
 }
 
@@ -740,13 +738,13 @@ static struct spi_driver wm8804_spi_driver = {
                .of_match_table = wm8804_of_match,
        },
        .probe = wm8804_spi_probe,
-       .remove = __devexit_p(wm8804_spi_remove)
+       .remove = wm8804_spi_remove
 };
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8804_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8804_priv *wm8804;
        int ret;
@@ -755,7 +753,7 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
        if (!wm8804)
                return -ENOMEM;
 
-       wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
+       wm8804->regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config);
        if (IS_ERR(wm8804->regmap)) {
                ret = PTR_ERR(wm8804->regmap);
                return ret;
@@ -765,23 +763,12 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8804, &wm8804_dai, 1);
-       if (ret != 0)
-               goto err;
-
-       return 0;
-
-err:
-       regmap_exit(wm8804->regmap);
        return ret;
 }
 
-static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
+static int wm8804_i2c_remove(struct i2c_client *i2c)
 {
-       struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
-
        snd_soc_unregister_codec(&i2c->dev);
-       regmap_exit(wm8804->regmap);
-
        return 0;
 }
 
@@ -798,7 +785,7 @@ static struct i2c_driver wm8804_i2c_driver = {
                .of_match_table = wm8804_of_match,
        },
        .probe = wm8804_i2c_probe,
-       .remove = __devexit_p(wm8804_i2c_remove),
+       .remove = wm8804_i2c_remove,
        .id_table = wm8804_i2c_id
 };
 #endif
index e781f865e5d7673d3fd2caae65a6e69d201e9ae6..7c8257c5a17ba5f591cd408e63ff2912e7ed49c7 100644 (file)
@@ -1247,7 +1247,7 @@ static const struct regmap_config wm8900_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8900_spi_probe(struct spi_device *spi)
+static int wm8900_spi_probe(struct spi_device *spi)
 {
        struct wm8900_priv *wm8900;
        int ret;
@@ -1269,7 +1269,7 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8900_spi_remove(struct spi_device *spi)
+static int wm8900_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -1281,13 +1281,13 @@ static struct spi_driver wm8900_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = wm8900_spi_probe,
-       .remove         = __devexit_p(wm8900_spi_remove),
+       .remove         = wm8900_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8900_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8900_priv *wm8900;
        int ret;
@@ -1309,7 +1309,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+static int wm8900_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1327,7 +1327,7 @@ static struct i2c_driver wm8900_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8900_i2c_probe,
-       .remove =   __devexit_p(wm8900_i2c_remove),
+       .remove =   wm8900_i2c_remove,
        .id_table = wm8900_i2c_id,
 };
 #endif
index 839414f9e2ed3866d41f09c96cd3d50ec9dcc045..134e41c870b9a0077ae364eef131e471d15c96bf 100644 (file)
@@ -2020,8 +2020,8 @@ static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
        return 0;
 }
 
-static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8903_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
        struct wm8903_priv *wm8903;
@@ -2206,7 +2206,7 @@ err:
        return ret;
 }
 
-static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+static int wm8903_i2c_remove(struct i2c_client *client)
 {
        struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
 
@@ -2237,7 +2237,7 @@ static struct i2c_driver wm8903_i2c_driver = {
                .of_match_table = wm8903_of_match,
        },
        .probe =    wm8903_i2c_probe,
-       .remove =   __devexit_p(wm8903_i2c_remove),
+       .remove =   wm8903_i2c_remove,
        .id_table = wm8903_i2c_id,
 };
 
index 7c8df52a8d9d3710e11d87d352bed367a81c4920..3ff195c541dbf839e946e036f1f314aa27662f38 100644 (file)
@@ -2111,8 +2111,8 @@ static const struct regmap_config wm8904_regmap = {
        .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
 };
 
-static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8904_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8904_priv *wm8904;
        unsigned int val;
@@ -2247,7 +2247,7 @@ err_enable:
        return ret;
 }
 
-static __devexit int wm8904_i2c_remove(struct i2c_client *client)
+static int wm8904_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -2267,7 +2267,7 @@ static struct i2c_driver wm8904_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8904_i2c_probe,
-       .remove =   __devexit_p(wm8904_i2c_remove),
+       .remove =   wm8904_i2c_remove,
        .id_table = wm8904_i2c_id,
 };
 
index b20aa4e7c3f9c2f85f84deaddc06aee763061987..b1591c61c254ebc1f12d0a19e682e45df632ed77 100644 (file)
@@ -742,8 +742,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
        .volatile_register = wm8940_volatile_register,
 };
 
-static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8940_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8940_priv *wm8940;
        int ret;
@@ -762,7 +762,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8940_i2c_remove(struct i2c_client *client)
+static int wm8940_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -781,7 +781,7 @@ static struct i2c_driver wm8940_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8940_i2c_probe,
-       .remove =   __devexit_p(wm8940_i2c_remove),
+       .remove =   wm8940_i2c_remove,
        .id_table = wm8940_i2c_id,
 };
 
index 2f1c075755b1fc7dd4827fbcd547da0556e9e2a9..82c8ba9757202402cfe53e44b0a7dd587df502b5 100644 (file)
@@ -1012,8 +1012,8 @@ static const struct regmap_config wm8955_regmap = {
        .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
 };
 
-static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8955_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8955_priv *wm8955;
        int ret;
@@ -1023,7 +1023,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
        if (wm8955 == NULL)
                return -ENOMEM;
 
-       wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+       wm8955->regmap = devm_regmap_init_i2c(i2c, &wm8955_regmap);
        if (IS_ERR(wm8955->regmap)) {
                ret = PTR_ERR(wm8955->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -1035,22 +1035,13 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8955, &wm8955_dai, 1);
-       if (ret != 0)
-               goto err;
 
        return ret;
-
-err:
-       regmap_exit(wm8955->regmap);
-       return ret;
 }
 
-static __devexit int wm8955_i2c_remove(struct i2c_client *client)
+static int wm8955_i2c_remove(struct i2c_client *client)
 {
-       struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm8955->regmap);
 
        return 0;
 }
@@ -1067,7 +1058,7 @@ static struct i2c_driver wm8955_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8955_i2c_probe,
-       .remove =   __devexit_p(wm8955_i2c_remove),
+       .remove =   wm8955_i2c_remove,
        .id_table = wm8955_i2c_id,
 };
 
index 00121ba3659718ab4c4af6ff5135373762de4765..b0710d817a65964dd5418502e366f310d36b6dd7 100644 (file)
@@ -195,7 +195,7 @@ ok:
 static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int i;
 
        /* If the DSP is already running then noop */
@@ -210,9 +210,9 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
                            WM8958_DSP2_ENA, WM8958_DSP2_ENA);
 
        /* If we've got user supplied MBC settings use them */
-       if (pdata && pdata->num_mbc_cfgs) {
+       if (control->pdata.num_mbc_cfgs) {
                struct wm8958_mbc_cfg *cfg
-                       = &pdata->mbc_cfgs[wm8994->mbc_cfg];
+                       = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
 
                for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
                        snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1,
@@ -239,7 +239,7 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
 static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int i, ena;
 
        if (wm8994->mbc_vss)
@@ -249,26 +249,26 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
                            WM8958_DSP2_ENA, WM8958_DSP2_ENA);
 
        /* If we've got user supplied settings use them */
-       if (pdata && pdata->num_mbc_cfgs) {
+       if (control->pdata.num_mbc_cfgs) {
                struct wm8958_mbc_cfg *cfg
-                       = &pdata->mbc_cfgs[wm8994->mbc_cfg];
+                       = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
 
                for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
                        snd_soc_write(codec, i + 0x2800,
                                      cfg->combined_regs[i]);
        }
 
-       if (pdata && pdata->num_vss_cfgs) {
+       if (control->pdata.num_vss_cfgs) {
                struct wm8958_vss_cfg *cfg
-                       = &pdata->vss_cfgs[wm8994->vss_cfg];
+                       = &control->pdata.vss_cfgs[wm8994->vss_cfg];
 
                for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
                        snd_soc_write(codec, i + 0x2600, cfg->regs[i]);
        }
 
-       if (pdata && pdata->num_vss_hpf_cfgs) {
+       if (control->pdata.num_vss_hpf_cfgs) {
                struct wm8958_vss_hpf_cfg *cfg
-                       = &pdata->vss_hpf_cfgs[wm8994->vss_hpf_cfg];
+                       = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
 
                for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
                        snd_soc_write(codec, i + 0x2400, cfg->regs[i]);
@@ -300,7 +300,7 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
 static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int i;
 
        wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false);
@@ -309,9 +309,9 @@ static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path)
                            WM8958_DSP2_ENA, WM8958_DSP2_ENA);
 
        /* If we've got user supplied settings use them */
-       if (pdata && pdata->num_enh_eq_cfgs) {
+       if (control->pdata.num_enh_eq_cfgs) {
                struct wm8958_enh_eq_cfg *cfg
-                       = &pdata->enh_eq_cfgs[wm8994->enh_eq_cfg];
+                       = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
 
                for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
                        snd_soc_write(codec, i + 0x2200,
@@ -458,7 +458,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int value = ucontrol->value.integer.value[0];
        int reg;
 
@@ -467,7 +467,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
        if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
                return -EBUSY;
 
-       if (value >= pdata->num_mbc_cfgs)
+       if (value >= control->pdata.num_mbc_cfgs)
                return -EINVAL;
 
        wm8994->mbc_cfg = value;
@@ -548,7 +548,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int value = ucontrol->value.integer.value[0];
        int reg;
 
@@ -557,7 +557,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
        if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
                return -EBUSY;
 
-       if (value >= pdata->num_vss_cfgs)
+       if (value >= control->pdata.num_vss_cfgs)
                return -EINVAL;
 
        wm8994->vss_cfg = value;
@@ -581,7 +581,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int value = ucontrol->value.integer.value[0];
        int reg;
 
@@ -590,7 +590,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
        if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
                return -EBUSY;
 
-       if (value >= pdata->num_vss_hpf_cfgs)
+       if (value >= control->pdata.num_vss_hpf_cfgs)
                return -EINVAL;
 
        wm8994->vss_hpf_cfg = value;
@@ -748,7 +748,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
        int value = ucontrol->value.integer.value[0];
        int reg;
 
@@ -757,7 +757,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
        if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
                return -EBUSY;
 
-       if (value >= pdata->num_enh_eq_cfgs)
+       if (value >= control->pdata.num_enh_eq_cfgs)
                return -EINVAL;
 
        wm8994->enh_eq_cfg = value;
@@ -883,13 +883,6 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
                wm8994->mbc_vss = fw;
                mutex_unlock(&codec->mutex);
        }
-
-       /* We can't have more than one request outstanding at once so
-        * we daisy chain.
-        */
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
-                               codec, wm8958_enh_eq_loaded);
 }
 
 static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
@@ -897,25 +890,18 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
        struct snd_soc_codec *codec = context;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
-       if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0)
-               return;
-
-       mutex_lock(&codec->mutex);
-       wm8994->mbc = fw;
-       mutex_unlock(&codec->mutex);
-
-       /* We can't have more than one request outstanding at once so
-        * we daisy chain.
-        */
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
-                               codec, wm8958_mbc_vss_loaded);
+       if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) {
+               mutex_lock(&codec->mutex);
+               wm8994->mbc = fw;
+               mutex_unlock(&codec->mutex);
+       }
 }
 
 void wm8958_dsp2_init(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int ret, i;
 
        wm8994->dsp_active = -1;
@@ -932,9 +918,12 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
        request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
                                "wm8958_mbc.wfw", codec->dev, GFP_KERNEL,
                                codec, wm8958_mbc_loaded);
-
-       if (!pdata)
-               return;
+       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                               "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
+                               codec, wm8958_mbc_vss_loaded);
+       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                               "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
+                               codec, wm8958_enh_eq_loaded);
 
        if (pdata->num_mbc_cfgs) {
                struct snd_kcontrol_new control[] = {
index f0f6f66017859c7e8b5fcab1f470565d8a6cdd88..9bb9273259937770ac4f8b188b05f803a1079121 100644 (file)
@@ -1028,8 +1028,8 @@ static const struct regmap_config wm8960_regmap = {
        .volatile_reg = wm8960_volatile,
 };
 
-static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8960_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
        struct wm8960_priv *wm8960;
@@ -1040,7 +1040,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
        if (wm8960 == NULL)
                return -ENOMEM;
 
-       wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap);
+       wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
        if (IS_ERR(wm8960->regmap))
                return PTR_ERR(wm8960->regmap);
 
@@ -1062,7 +1062,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8960_i2c_remove(struct i2c_client *client)
+static int wm8960_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1080,7 +1080,7 @@ static struct i2c_driver wm8960_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8960_i2c_probe,
-       .remove =   __devexit_p(wm8960_i2c_remove),
+       .remove =   wm8960_i2c_remove,
        .id_table = wm8960_i2c_id,
 };
 
index f387670d0d7591c1860c071087c81736974e9fc5..900328e28a1596cc1cd189185f18460113de440c 100644 (file)
@@ -937,8 +937,8 @@ static const struct regmap_config wm8961_regmap = {
        .readable_reg = wm8961_readable,
 };
 
-static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8961_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8961_priv *wm8961;
        unsigned int val;
@@ -993,7 +993,7 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8961_i2c_remove(struct i2c_client *client)
+static int wm8961_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -1012,7 +1012,7 @@ static struct i2c_driver wm8961_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8961_i2c_probe,
-       .remove =   __devexit_p(wm8961_i2c_remove),
+       .remove =   wm8961_i2c_remove,
        .id_table = wm8961_i2c_id,
 };
 
index ce6720073798ddd352df483182b1653b121ec096..bd4b0db4cdaadb11fe12caed12b8e8e2f5bab7b1 100644 (file)
@@ -3588,8 +3588,8 @@ static const struct regmap_config wm8962_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8962_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm8962_priv *wm8962;
@@ -3610,7 +3610,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
                wm8962->supplies[i].supply = wm8962_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
+       ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
                                 wm8962->supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
@@ -3621,10 +3621,10 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
                                    wm8962->supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
+               return ret;
        }
 
-       wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap);
+       wm8962->regmap = devm_regmap_init_i2c(i2c, &wm8962_regmap);
        if (IS_ERR(wm8962->regmap)) {
                ret = PTR_ERR(wm8962->regmap);
                dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -3641,20 +3641,20 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
        ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, &reg);
        if (ret < 0) {
                dev_err(&i2c->dev, "Failed to read ID register\n");
-               goto err_regmap;
+               goto err_enable;
        }
        if (reg != 0x6243) {
                dev_err(&i2c->dev,
                        "Device is not a WM8962, ID %x != 0x6243\n", reg);
                ret = -EINVAL;
-               goto err_regmap;
+               goto err_enable;
        }
 
        ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, &reg);
        if (ret < 0) {
                dev_err(&i2c->dev, "Failed to read device revision: %d\n",
                        ret);
-               goto err_regmap;
+               goto err_enable;
        }
 
        dev_info(&i2c->dev, "customer id %x revision %c\n",
@@ -3667,7 +3667,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
        ret = wm8962_reset(wm8962);
        if (ret < 0) {
                dev_err(&i2c->dev, "Failed to issue reset\n");
-               goto err_regmap;
+               goto err_enable;
        }
 
        if (pdata && pdata->in4_dc_measure) {
@@ -3686,30 +3686,22 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8962, &wm8962_dai, 1);
        if (ret < 0)
-               goto err_regmap;
+               goto err_enable;
 
        /* The drivers should power up as needed */
        regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 
        return 0;
 
-err_regmap:
-       regmap_exit(wm8962->regmap);
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 err:
        return ret;
 }
 
-static __devexit int wm8962_i2c_remove(struct i2c_client *client)
+static int wm8962_i2c_remove(struct i2c_client *client)
 {
-       struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm8962->regmap);
-       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
        return 0;
 }
 
@@ -3773,7 +3765,7 @@ static struct i2c_driver wm8962_i2c_driver = {
                .pm = &wm8962_pm,
        },
        .probe =    wm8962_i2c_probe,
-       .remove =   __devexit_p(wm8962_i2c_remove),
+       .remove =   wm8962_i2c_remove,
        .id_table = wm8962_i2c_id,
 };
 
index 5ce6477584438b3a8555bada53f8e17c1dd7cc5e..67aba78a7ca5d8de561d2a3c70a0f5a6e4307f7d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -34,7 +35,6 @@ static struct workqueue_struct *wm8971_workq = NULL;
 
 /* codec private data */
 struct wm8971_priv {
-       enum snd_soc_control_type control_type;
        unsigned int sysclk;
 };
 
@@ -43,18 +43,50 @@ struct wm8971_priv {
  * We can't read the WM8971 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8971_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8971_reg_defaults[] = {
+       {  0, 0x0097 },
+       {  1, 0x0097 },
+       {  2, 0x0079 },
+       {  3, 0x0079 },
+       {  4, 0x0000 },
+       {  5, 0x0008 },
+       {  6, 0x0000 },
+       {  7, 0x000a },
+       {  8, 0x0000 },
+       {  9, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 14, 0x0000 },
+       { 15, 0x0000 },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 38, 0x0050 },
+       { 39, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
 #define wm8971_reset(c)        snd_soc_write(c, WM8971_RESET, 0)
@@ -613,11 +645,10 @@ static int wm8971_resume(struct snd_soc_codec *codec)
 
 static int wm8971_probe(struct snd_soc_codec *codec)
 {
-       struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
        u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -667,9 +698,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .suspend =      wm8971_suspend,
        .resume =       wm8971_resume,
        .set_bias_level = wm8971_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8971_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8971_reg,
 
        .controls = wm8971_snd_controls,
        .num_controls = ARRAY_SIZE(wm8971_snd_controls),
@@ -679,10 +707,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
 };
 
-static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static const struct regmap_config wm8971_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8971_MOUTV,
+
+       .reg_defaults = wm8971_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int wm8971_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8971_priv *wm8971;
+       struct regmap *regmap;
        int ret;
 
        wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
@@ -690,7 +729,10 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
        if (wm8971 == NULL)
                return -ENOMEM;
 
-       wm8971->control_type = SND_SOC_I2C;
+       regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        i2c_set_clientdata(i2c, wm8971);
 
        ret = snd_soc_register_codec(&i2c->dev,
@@ -699,7 +741,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8971_i2c_remove(struct i2c_client *client)
+static int wm8971_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -717,7 +759,7 @@ static struct i2c_driver wm8971_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8971_i2c_probe,
-       .remove =   __devexit_p(wm8971_i2c_remove),
+       .remove =   wm8971_i2c_remove,
        .id_table = wm8971_i2c_id,
 };
 
index 9a39511af52ad180bda356d210a7594de1c3f80f..ea58b73e86b28df311fda7545463089b90e89b6b 100644 (file)
@@ -625,8 +625,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
        .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
 };
 
-static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8974_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        int ret;
 
@@ -636,7 +636,7 @@ static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8974_i2c_remove(struct i2c_client *client)
+static int wm8974_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -655,7 +655,7 @@ static struct i2c_driver wm8974_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8974_i2c_probe,
-       .remove =   __devexit_p(wm8974_i2c_remove),
+       .remove =   wm8974_i2c_remove,
        .id_table = wm8974_i2c_id,
 };
 
index 4c0a8e496131c1cc2bf9933605dee7664928520d..f347af3a67c2d2d390e50d523b33cd3372530b1c 100644 (file)
@@ -527,9 +527,6 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)
                        return idx;
 
                wm8978->mclk_idx = idx;
-
-               /* GPIO1 into default mode as input - before configuring PLL */
-               snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0);
        } else {
                return -EINVAL;
        }
@@ -1038,8 +1035,8 @@ static const struct regmap_config wm8978_regmap_config = {
        .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
 };
 
-static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8978_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8978_priv *wm8978;
        int ret;
@@ -1049,7 +1046,7 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
        if (wm8978 == NULL)
                return -ENOMEM;
 
-       wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+       wm8978->regmap = devm_regmap_init_i2c(i2c, &wm8978_regmap_config);
        if (IS_ERR(wm8978->regmap)) {
                ret = PTR_ERR(wm8978->regmap);
                dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -1062,29 +1059,22 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
        ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8978, &wm8978_dai, 1);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        return 0;
-
-err:
-       regmap_exit(wm8978->regmap);
-       return ret;
 }
 
-static __devexit int wm8978_i2c_remove(struct i2c_client *client)
+static int wm8978_i2c_remove(struct i2c_client *client)
 {
-       struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm8978->regmap);
 
        return 0;
 }
@@ -1101,7 +1091,7 @@ static struct i2c_driver wm8978_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8978_i2c_probe,
-       .remove =   __devexit_p(wm8978_i2c_remove),
+       .remove =   wm8978_i2c_remove,
        .id_table = wm8978_i2c_id,
 };
 
index d8879f262d2762dcf860db46388961ed84063f33..9fe1e041da498cec9bc335959c92d569ca0102b9 100644 (file)
@@ -1087,7 +1087,7 @@ static const struct regmap_config wm8983_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8983_spi_probe(struct spi_device *spi)
+static int wm8983_spi_probe(struct spi_device *spi)
 {
        struct wm8983_priv *wm8983;
        int ret;
@@ -1110,7 +1110,7 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit wm8983_spi_remove(struct spi_device *spi)
+static int wm8983_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
        return 0;
@@ -1122,13 +1122,13 @@ static struct spi_driver wm8983_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8983_spi_probe,
-       .remove = __devexit_p(wm8983_spi_remove)
+       .remove = wm8983_spi_remove
 };
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8983_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8983_priv *wm8983;
        int ret;
@@ -1152,7 +1152,7 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8983_i2c_remove(struct i2c_client *client)
+static int wm8983_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
@@ -1170,7 +1170,7 @@ static struct i2c_driver wm8983_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8983_i2c_probe,
-       .remove = __devexit_p(wm8983_i2c_remove),
+       .remove = wm8983_i2c_remove,
        .id_table = wm8983_i2c_id
 };
 #endif
index 14f666398d0c9a0bb7677fa6a1bdbac43125c0fe..ab3782657ac81e7ae11afa0142e1d2d5a1e4d483 100644 (file)
@@ -1111,7 +1111,7 @@ static const struct regmap_config wm8985_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8985_spi_probe(struct spi_device *spi)
+static int wm8985_spi_probe(struct spi_device *spi)
 {
        struct wm8985_priv *wm8985;
        int ret;
@@ -1122,33 +1122,22 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, wm8985);
 
-       wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+       wm8985->regmap = devm_regmap_init_spi(spi, &wm8985_regmap);
        if (IS_ERR(wm8985->regmap)) {
                ret = PTR_ERR(wm8985->regmap);
                dev_err(&spi->dev, "Failed to allocate register map: %d\n",
                        ret);
-               goto err;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&spi->dev,
                                     &soc_codec_dev_wm8985, &wm8985_dai, 1);
-       if (ret != 0)
-               goto err;
-
-       return 0;
-
-err:
-       regmap_exit(wm8985->regmap);
        return ret;
 }
 
-static int __devexit wm8985_spi_remove(struct spi_device *spi)
+static int wm8985_spi_remove(struct spi_device *spi)
 {
-       struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
-
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(wm8985->regmap);
-
        return 0;
 }
 
@@ -1158,13 +1147,13 @@ static struct spi_driver wm8985_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8985_spi_probe,
-       .remove = __devexit_p(wm8985_spi_remove)
+       .remove = wm8985_spi_remove
 };
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8985_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8985_priv *wm8985;
        int ret;
@@ -1175,33 +1164,22 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm8985);
 
-       wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+       wm8985->regmap = devm_regmap_init_i2c(i2c, &wm8985_regmap);
        if (IS_ERR(wm8985->regmap)) {
                ret = PTR_ERR(wm8985->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
                        ret);
-               goto err;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8985, &wm8985_dai, 1);
-       if (ret != 0)
-               goto err;
-
-       return 0;
-
-err:
-       regmap_exit(wm8985->regmap);
        return ret;
 }
 
-static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
+static int wm8985_i2c_remove(struct i2c_client *i2c)
 {
-       struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
-
        snd_soc_unregister_codec(&i2c->dev);
-       regmap_exit(wm8985->regmap);
-
        return 0;
 }
 
@@ -1217,7 +1195,7 @@ static struct i2c_driver wm8985_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8985_i2c_probe,
-       .remove = __devexit_p(wm8985_i2c_remove),
+       .remove = wm8985_i2c_remove,
        .id_table = wm8985_i2c_id
 };
 #endif
index 1d4c5cf47b06ba24d49509d904b5460e3ad22891..39b9acceb595185d60821270073d9e5895305baa 100644 (file)
@@ -872,7 +872,7 @@ static struct regmap_config wm8988_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8988_spi_probe(struct spi_device *spi)
+static int wm8988_spi_probe(struct spi_device *spi)
 {
        struct wm8988_priv *wm8988;
        int ret;
@@ -882,7 +882,7 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
        if (wm8988 == NULL)
                return -ENOMEM;
 
-       wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+       wm8988->regmap = devm_regmap_init_spi(spi, &wm8988_regmap);
        if (IS_ERR(wm8988->regmap)) {
                ret = PTR_ERR(wm8988->regmap);
                dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
@@ -893,17 +893,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_wm8988, &wm8988_dai, 1);
-       if (ret != 0)
-               regmap_exit(wm8988->regmap);
-
        return ret;
 }
 
-static int __devexit wm8988_spi_remove(struct spi_device *spi)
+static int wm8988_spi_remove(struct spi_device *spi)
 {
-       struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(wm8988->regmap);
        return 0;
 }
 
@@ -913,13 +908,13 @@ static struct spi_driver wm8988_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = wm8988_spi_probe,
-       .remove         = __devexit_p(wm8988_spi_remove),
+       .remove         = wm8988_spi_remove,
 };
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8988_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8988_priv *wm8988;
        int ret;
@@ -931,7 +926,7 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm8988);
 
-       wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+       wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap);
        if (IS_ERR(wm8988->regmap)) {
                ret = PTR_ERR(wm8988->regmap);
                dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -940,17 +935,12 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8988, &wm8988_dai, 1);
-       if (ret != 0)
-               regmap_exit(wm8988->regmap);
-
        return ret;
 }
 
-static __devexit int wm8988_i2c_remove(struct i2c_client *client)
+static int wm8988_i2c_remove(struct i2c_client *client)
 {
-       struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm8988->regmap);
        return 0;
 }
 
@@ -966,7 +956,7 @@ static struct i2c_driver wm8988_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8988_i2c_probe,
-       .remove =   __devexit_p(wm8988_i2c_remove),
+       .remove =   wm8988_i2c_remove,
        .id_table = wm8988_i2c_id,
 };
 #endif
index c28c83e5395d93d76288bebd356df1abdf791f49..837978e16e9dc85150b96ed5b8671cd569138e38 100644 (file)
@@ -1382,8 +1382,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8990_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8990_priv *wm8990;
        int ret;
@@ -1401,7 +1401,7 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8990_i2c_remove(struct i2c_client *client)
+static int wm8990_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -1420,7 +1420,7 @@ static struct i2c_driver wm8990_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8990_i2c_probe,
-       .remove =   __devexit_p(wm8990_i2c_remove),
+       .remove =   wm8990_i2c_remove,
        .id_table = wm8990_i2c_id,
 };
 #endif
index fe439f027e102b9274883a9a879dc5cf320bb6a1..3a39df7a38295a36a28d7865405cb7c0096089d1 100644 (file)
@@ -1357,8 +1357,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
        .reg_cache_default = wm8991_reg_defs
 };
 
-static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8991_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8991_priv *wm8991;
        int ret;
@@ -1376,7 +1376,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
        return ret;
 }
 
-static __devexit int wm8991_i2c_remove(struct i2c_client *client)
+static int wm8991_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
 
@@ -1395,7 +1395,7 @@ static struct i2c_driver wm8991_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8991_i2c_probe,
-       .remove = __devexit_p(wm8991_i2c_remove),
+       .remove = wm8991_i2c_remove,
        .id_table = wm8991_i2c_id,
 };
 
index 94737a30716b7acf9fd47382b09f461c6a5ffec0..433d59a0f3efa025598cf5c63f42640120893f90 100644 (file)
@@ -1645,8 +1645,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
        .set_bias_level = wm8993_set_bias_level,
 };
 
-static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8993_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8993_priv *wm8993;
        unsigned int reg;
@@ -1660,7 +1660,7 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
        wm8993->dev = &i2c->dev;
        init_completion(&wm8993->fll_lock);
 
-       wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+       wm8993->regmap = devm_regmap_init_i2c(i2c, &wm8993_regmap);
        if (IS_ERR(wm8993->regmap)) {
                ret = PTR_ERR(wm8993->regmap);
                dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -1672,18 +1672,18 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
                wm8993->supplies[i].supply = wm8993_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+       ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
                                 wm8993->supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
                                    wm8993->supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
+               return ret;
        }
 
        ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
@@ -1742,23 +1742,17 @@ err_irq:
                free_irq(i2c->irq, wm8993);
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err:
-       regmap_exit(wm8993->regmap);
        return ret;
 }
 
-static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
+static int wm8993_i2c_remove(struct i2c_client *i2c)
 {
        struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
 
        snd_soc_unregister_codec(&i2c->dev);
        if (i2c->irq)
                free_irq(i2c->irq, wm8993);
-       regmap_exit(wm8993->regmap);
        regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
 
        return 0;
 }
@@ -1775,7 +1769,7 @@ static struct i2c_driver wm8993_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8993_i2c_probe,
-       .remove =   __devexit_p(wm8993_i2c_remove),
+       .remove =   wm8993_i2c_remove,
        .id_table = wm8993_i2c_id,
 };
 
index b2b2b37131bddc4acfb8fb0e51a9bba220da9907..3b269fa226bdabec90e97c2b77bd8347909a9df7 100644 (file)
@@ -91,8 +91,6 @@ static int wm8994_retune_mobile_base[] = {
        WM8994_AIF2_EQ_GAINS_1,
 };
 
-static void wm8958_default_micdet(u16 status, void *data);
-
 static const struct wm8958_micd_rate micdet_rates[] = {
        { 32768,       true,  1, 4 },
        { 32768,       false, 1, 1 },
@@ -110,15 +108,12 @@ static const struct wm8958_micd_rate jackdet_rates[] = {
 static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
        int best, i, sysclk, val;
        bool idle;
        const struct wm8958_micd_rate *rates;
        int num_rates;
 
-       if (!(wm8994->pdata && wm8994->pdata->micd_rates) &&
-           wm8994->jack_cb != wm8958_default_micdet)
-               return;
-
        idle = !wm8994->jack_mic;
 
        sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
@@ -127,9 +122,9 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
        else
                sysclk = wm8994->aifclk[0];
 
-       if (wm8994->pdata && wm8994->pdata->micd_rates) {
-               rates = wm8994->pdata->micd_rates;
-               num_rates = wm8994->pdata->num_micd_rates;
+       if (control->pdata.micd_rates) {
+               rates = control->pdata.micd_rates;
+               num_rates = control->pdata.num_micd_rates;
        } else if (wm8994->jackdet) {
                rates = jackdet_rates;
                num_rates = ARRAY_SIZE(jackdet_rates);
@@ -326,7 +321,8 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
 static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int base = wm8994_drc_base[drc];
        int cfg = wm8994->drc_cfg[drc];
        int save, i;
@@ -362,7 +358,8 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int drc = wm8994_get_drc(kcontrol->id.name);
        int value = ucontrol->value.integer.value[0];
 
@@ -394,7 +391,8 @@ static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
 static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int base = wm8994_retune_mobile_base[block];
        int iface, best, best_val, save, i, cfg;
 
@@ -465,7 +463,8 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
        int value = ucontrol->value.integer.value[0];
 
@@ -736,7 +735,7 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
-       if (!wm8994->jackdet || !wm8994->jack_cb)
+       if (!wm8994->jackdet || !wm8994->micdet[0].jack)
                return;
 
        if (wm8994->active_refcount)
@@ -862,7 +861,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                            WM8994_BIAS_SRC |
                                            WM8994_STARTUP_BIAS_ENA |
                                            WM8994_VMID_BUF_ENA |
-                                           (0x3 << WM8994_VMID_RAMP_SHIFT));
+                                           (0x2 << WM8994_VMID_RAMP_SHIFT));
 
                        /* Main bias enable, VMID=2x40k */
                        snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -870,7 +869,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                            WM8994_VMID_SEL_MASK,
                                            WM8994_BIAS_ENA | 0x2);
 
-                       msleep(50);
+                       msleep(300);
 
                        snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
                                            WM8994_VMID_RAMP_MASK |
@@ -939,16 +938,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_BIAS_SRC |
                                    WM8994_VMID_DISCH);
 
-               switch (wm8994->vmid_mode) {
-               case WM8994_VMID_FORCE:
-                       msleep(350);
-                       break;
-               default:
-                       break;
-               }
+               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                   WM8994_VMID_SEL_MASK, 0);
 
-               snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
-                                   WM8994_VROI, WM8994_VROI);
+               msleep(400);
 
                /* Active discharge */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
@@ -957,17 +950,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_LINEOUT1_DISCH |
                                    WM8994_LINEOUT2_DISCH);
 
-               msleep(150);
-
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
                                    WM8994_LINEOUT1N_ENA |
                                    WM8994_LINEOUT1P_ENA |
                                    WM8994_LINEOUT2N_ENA |
                                    WM8994_LINEOUT2P_ENA, 0);
 
-               snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
-                                   WM8994_VROI, 0);
-
                /* Switch off startup biases */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
                                    WM8994_BIAS_SRC |
@@ -976,10 +964,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_VMID_RAMP_MASK, 0);
 
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
-
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                   WM8994_VMID_RAMP_MASK, 0);
+                                   WM8994_VMID_SEL_MASK, 0);
        }
 
        pm_runtime_put(codec->dev);
@@ -2277,6 +2262,18 @@ out:
 
        configure_clock(codec);
 
+       /*
+        * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
+        * for detection.
+        */
+       if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
+               dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+               snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+                                   WM8994_AIF1CLK_RATE_MASK, 0x1);
+               snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+                                   WM8994_AIF2CLK_RATE_MASK, 0x1);
+       }
+
        return 0;
 }
 
@@ -2365,6 +2362,18 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
 
        configure_clock(codec);
 
+       /*
+        * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
+        * for detection.
+        */
+       if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
+               dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+               snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+                                   WM8994_AIF1CLK_RATE_MASK, 0x1);
+               snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+                                   WM8994_AIF2CLK_RATE_MASK, 0x1);
+       }
+
        return 0;
 }
 
@@ -3082,7 +3091,8 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
 static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
 {
        struct snd_soc_codec *codec = wm8994->hubs.codec;
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        struct snd_kcontrol_new controls[] = {
                SOC_ENUM_EXT("AIF1.1 EQ Mode",
                             wm8994->retune_mobile_enum,
@@ -3149,7 +3159,8 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
 static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
 {
        struct snd_soc_codec *codec = wm8994->hubs.codec;
-       struct wm8994_pdata *pdata = wm8994->pdata;
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int ret, i;
 
        if (!pdata)
@@ -3389,38 +3400,80 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-/* Default microphone detection handler for WM8958 - the user can
- * override this if they wish.
- */
-static void wm8958_default_micdet(u16 status, void *data)
+static void wm1811_micd_stop(struct snd_soc_codec *codec)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+       if (!wm8994->jackdet)
+               return;
+
+       mutex_lock(&wm8994->accdet_lock);
+
+       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0);
+
+       wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
+
+       mutex_unlock(&wm8994->accdet_lock);
+
+       if (wm8994->wm8994->pdata.jd_ext_cap)
+               snd_soc_dapm_disable_pin(&codec->dapm,
+                                        "MICBIAS2");
+}
+
+static void wm8958_button_det(struct snd_soc_codec *codec, u16 status)
 {
-       struct snd_soc_codec *codec = data;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int report;
 
-       dev_dbg(codec->dev, "MICDET %x\n", status);
+       report = 0;
+       if (status & 0x4)
+               report |= SND_JACK_BTN_0;
+
+       if (status & 0x8)
+               report |= SND_JACK_BTN_1;
+
+       if (status & 0x10)
+               report |= SND_JACK_BTN_2;
+
+       if (status & 0x20)
+               report |= SND_JACK_BTN_3;
+
+       if (status & 0x40)
+               report |= SND_JACK_BTN_4;
+
+       if (status & 0x80)
+               report |= SND_JACK_BTN_5;
+
+       snd_soc_jack_report(wm8994->micdet[0].jack, report,
+                           wm8994->btn_mask);
+}
+
+static void wm8958_mic_id(void *data, u16 status)
+{
+       struct snd_soc_codec *codec = data;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
        /* Either nothing present or just starting detection */
        if (!(status & WM8958_MICD_STS)) {
-               if (!wm8994->jackdet) {
-                       /* If nothing present then clear our statuses */
-                       dev_dbg(codec->dev, "Detected open circuit\n");
-                       wm8994->jack_mic = false;
-                       wm8994->mic_detecting = true;
+               /* If nothing present then clear our statuses */
+               dev_dbg(codec->dev, "Detected open circuit\n");
+               wm8994->jack_mic = false;
+               wm8994->mic_detecting = true;
 
-                       wm8958_micd_set_rate(codec);
+               wm1811_micd_stop(codec);
 
-                       snd_soc_jack_report(wm8994->micdet[0].jack, 0,
-                                           wm8994->btn_mask |
-                                           SND_JACK_HEADSET);
-               }
+               wm8958_micd_set_rate(codec);
+
+               snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+                                   wm8994->btn_mask |
+                                   SND_JACK_HEADSET);
                return;
        }
 
        /* If the measurement is showing a high impedence we've got a
         * microphone.
         */
-       if (wm8994->mic_detecting && (status & 0x600)) {
+       if (status & 0x600) {
                dev_dbg(codec->dev, "Detected microphone\n");
 
                wm8994->mic_detecting = false;
@@ -3433,64 +3486,67 @@ static void wm8958_default_micdet(u16 status, void *data)
        }
 
 
-       if (wm8994->mic_detecting && status & 0xfc) {
+       if (status & 0xfc) {
                dev_dbg(codec->dev, "Detected headphone\n");
                wm8994->mic_detecting = false;
 
                wm8958_micd_set_rate(codec);
 
                /* If we have jackdet that will detect removal */
-               if (wm8994->jackdet) {
-                       mutex_lock(&wm8994->accdet_lock);
-
-                       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-                                           WM8958_MICD_ENA, 0);
-
-                       wm1811_jackdet_set_mode(codec,
-                                               WM1811_JACKDET_MODE_JACK);
-
-                       mutex_unlock(&wm8994->accdet_lock);
-
-                       if (wm8994->pdata->jd_ext_cap)
-                               snd_soc_dapm_disable_pin(&codec->dapm,
-                                                        "MICBIAS2");
-               }
+               wm1811_micd_stop(codec);
 
                snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
                                    SND_JACK_HEADSET);
        }
+}
 
-       /* Report short circuit as a button */
-       if (wm8994->jack_mic) {
-               report = 0;
-               if (status & 0x4)
-                       report |= SND_JACK_BTN_0;
+/* Deferred mic detection to allow for extra settling time */
+static void wm1811_mic_work(struct work_struct *work)
+{
+       struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
+                                                 mic_work.work);
+       struct wm8994 *control = wm8994->wm8994;
+       struct snd_soc_codec *codec = wm8994->hubs.codec;
 
-               if (status & 0x8)
-                       report |= SND_JACK_BTN_1;
+       pm_runtime_get_sync(codec->dev);
 
-               if (status & 0x10)
-                       report |= SND_JACK_BTN_2;
+       /* If required for an external cap force MICBIAS on */
+       if (control->pdata.jd_ext_cap) {
+               snd_soc_dapm_force_enable_pin(&codec->dapm,
+                                             "MICBIAS2");
+               snd_soc_dapm_sync(&codec->dapm);
+       }
 
-               if (status & 0x20)
-                       report |= SND_JACK_BTN_3;
+       mutex_lock(&wm8994->accdet_lock);
 
-               if (status & 0x40)
-                       report |= SND_JACK_BTN_4;
+       dev_dbg(codec->dev, "Starting mic detection\n");
 
-               if (status & 0x80)
-                       report |= SND_JACK_BTN_5;
+       /* Use a user-supplied callback if we have one */
+       if (wm8994->micd_cb) {
+               wm8994->micd_cb(wm8994->micd_cb_data);
+       } else {
+               /*
+                * Start off measument of microphone impedence to find out
+                * what's actually there.
+                */
+               wm8994->mic_detecting = true;
+               wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
 
-               snd_soc_jack_report(wm8994->micdet[0].jack, report,
-                                   wm8994->btn_mask);
+               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                   WM8958_MICD_ENA, WM8958_MICD_ENA);
        }
+
+       mutex_unlock(&wm8994->accdet_lock);
+
+       pm_runtime_put(codec->dev);
 }
 
 static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 {
        struct wm8994_priv *wm8994 = data;
+       struct wm8994 *control = wm8994->wm8994;
        struct snd_soc_codec *codec = wm8994->hubs.codec;
-       int reg;
+       int reg, delay;
        bool present;
 
        pm_runtime_get_sync(codec->dev);
@@ -3521,18 +3577,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
                snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
                                    WM1811_JACKDET_DB, 0);
 
-               /*
-                * Start off measument of microphone impedence to find
-                * out what's actually there.
-                */
-               wm8994->mic_detecting = true;
-               wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
-
-               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-                                   WM8958_MICD_ENA, WM8958_MICD_ENA);
+               delay = control->pdata.micdet_delay;
+               schedule_delayed_work(&wm8994->mic_work,
+                                     msecs_to_jiffies(delay));
        } else {
                dev_dbg(codec->dev, "Jack not detected\n");
 
+               cancel_delayed_work_sync(&wm8994->mic_work);
+
                snd_soc_update_bits(codec, WM8958_MICBIAS2,
                                    WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
 
@@ -3549,14 +3601,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 
        mutex_unlock(&wm8994->accdet_lock);
 
-       /* If required for an external cap force MICBIAS on */
-       if (wm8994->pdata->jd_ext_cap) {
-               if (present)
-                       snd_soc_dapm_force_enable_pin(&codec->dapm,
-                                                     "MICBIAS2");
-               else
-                       snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
-       }
+       /* Turn off MICBIAS if it was on for an external cap */
+       if (control->pdata.jd_ext_cap && !present)
+               snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
 
        if (present)
                snd_soc_jack_report(wm8994->micdet[0].jack,
@@ -3599,7 +3646,8 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work)
  * detection algorithm.
  */
 int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-                     wm8958_micdet_cb cb, void *cb_data)
+                     wm1811_micdet_cb det_cb, void *det_cb_data,
+                     wm1811_mic_id_cb id_cb, void *id_cb_data)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
@@ -3614,27 +3662,32 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
        }
 
        if (jack) {
-               if (!cb) {
-                       dev_dbg(codec->dev, "Using default micdet callback\n");
-                       cb = wm8958_default_micdet;
-                       cb_data = codec;
-               }
-
                snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
                snd_soc_dapm_sync(&codec->dapm);
 
                wm8994->micdet[0].jack = jack;
-               wm8994->jack_cb = cb;
-               wm8994->jack_cb_data = cb_data;
 
-               wm8994->mic_detecting = true;
-               wm8994->jack_mic = false;
+               if (det_cb) {
+                       wm8994->micd_cb = det_cb;
+                       wm8994->micd_cb_data = det_cb_data;
+               } else {
+                       wm8994->mic_detecting = true;
+                       wm8994->jack_mic = false;
+               }
+
+               if (id_cb) {
+                       wm8994->mic_id_cb = id_cb;
+                       wm8994->mic_id_cb_data = id_cb_data;
+               } else {
+                       wm8994->mic_id_cb = wm8958_mic_id;
+                       wm8994->mic_id_cb_data = codec;
+               }
 
                wm8958_micd_set_rate(codec);
 
                /* Detect microphones and short circuits by default */
-               if (wm8994->pdata->micd_lvl_sel)
-                       micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
+               if (control->pdata.micd_lvl_sel)
+                       micd_lvl_sel = control->pdata.micd_lvl_sel;
                else
                        micd_lvl_sel = 0x41;
 
@@ -3728,10 +3781,22 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
        trace_snd_soc_jack_irq(dev_name(codec->dev));
 #endif
 
-       if (wm8994->jack_cb)
-               wm8994->jack_cb(reg, wm8994->jack_cb_data);
+       /* Avoid a transient report when the accessory is being removed */
+       if (wm8994->jackdet) {
+               reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
+               if (reg < 0) {
+                       dev_err(codec->dev, "Failed to read jack status: %d\n",
+                               reg);
+               } else if (!(reg & WM1811_JACKDET_LVL)) {
+                       dev_dbg(codec->dev, "Ignoring removed jack\n");
+                       return IRQ_HANDLED;
+               }
+       }
+
+       if (wm8994->mic_detecting)
+               wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg);
        else
-               dev_warn(codec->dev, "Accessory detection with no callback\n");
+               wm8958_button_det(codec, reg);
 
 out:
        pm_runtime_put(codec->dev);
@@ -3779,15 +3844,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 
        mutex_init(&wm8994->accdet_lock);
-       INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
        INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
                          wm1811_jackdet_bootstrap);
 
+       switch (control->type) {
+       case WM8994:
+               INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
+               break;
+       case WM1811:
+               INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
+               break;
+       default:
+               break;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
                init_completion(&wm8994->fll_locked[i]);
 
-       if (wm8994->pdata && wm8994->pdata->micdet_irq)
-               wm8994->micdet_irq = wm8994->pdata->micdet_irq;
+       wm8994->micdet_irq = control->pdata.micdet_irq;
 
        pm_runtime_enable(codec->dev);
        pm_runtime_idle(codec->dev);
@@ -3800,8 +3874,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        switch (control->type) {
        case WM8994:
                /* Single ended line outputs should have VMID on. */
-               if (!wm8994->pdata->lineout1_diff ||
-                   !wm8994->pdata->lineout2_diff)
+               if (!control->pdata.lineout1_diff ||
+                   !control->pdata.lineout2_diff)
                        codec->dapm.idle_bias_off = 0;
 
                switch (wm8994->revision) {
@@ -3839,20 +3913,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                wm8994->hubs.no_cache_dac_hp_direct = true;
                wm8994->fll_byp = true;
 
-               switch (control->cust_id) {
-               case 0:
-               case 2:
-                       wm8994->hubs.dcs_codes_l = -9;
-                       wm8994->hubs.dcs_codes_r = -7;
-                       break;
-               case 1:
-               case 3:
-                       wm8994->hubs.dcs_codes_l = -8;
-                       wm8994->hubs.dcs_codes_r = -7;
-                       break;
-               default:
-                       break;
-               }
+               wm8994->hubs.dcs_codes_l = -9;
+               wm8994->hubs.dcs_codes_r = -7;
 
                snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
                                    WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
@@ -4225,7 +4287,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
        .set_bias_level = wm8994_set_bias_level,
 };
 
-static int __devinit wm8994_probe(struct platform_device *pdev)
+static int wm8994_probe(struct platform_device *pdev)
 {
        struct wm8994_priv *wm8994;
 
@@ -4236,13 +4298,12 @@ static int __devinit wm8994_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, wm8994);
 
        wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
-       wm8994->pdata = dev_get_platdata(pdev->dev.parent);
 
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
                        wm8994_dai, ARRAY_SIZE(wm8994_dai));
 }
 
-static int __devexit wm8994_remove(struct platform_device *pdev)
+static int wm8994_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -4266,7 +4327,7 @@ static int wm8994_resume(struct device *dev)
 {
        struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
 
-       if (wm8994->jackdet && wm8994->jack_cb)
+       if (wm8994->jackdet && wm8994->jackdet_mode)
                regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
                                   WM1811_JACKDET_MODE_MASK,
                                   WM1811_JACKDET_MODE_AUDIO);
@@ -4286,7 +4347,7 @@ static struct platform_driver wm8994_codec_driver = {
                .pm = &wm8994_pm_ops,
        },
        .probe = wm8994_probe,
-       .remove = __devexit_p(wm8994_remove),
+       .remove = wm8994_remove,
 };
 
 module_platform_driver(wm8994_codec_driver);
index ccbce5791e95829b5d98ce472ac50d922e6e4703..45f192702024485fa23e87567eeda19bf0080e22 100644 (file)
@@ -39,12 +39,14 @@ enum wm8994_vmid_mode {
        WM8994_VMID_FORCE,
 };
 
-typedef void (*wm8958_micdet_cb)(u16 status, void *data);
+typedef void (*wm1811_micdet_cb)(void *data);
+typedef void (*wm1811_mic_id_cb)(void *data, u16 status);
 
 int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
                      int micbias);
 int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-                     wm8958_micdet_cb cb, void *cb_data);
+                     wm1811_micdet_cb cb, void *det_cb_data,
+                     wm1811_mic_id_cb id_cb, void *id_cb_data);
 
 int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
 
@@ -138,12 +140,13 @@ struct wm8994_priv {
        int jackdet_mode;
        struct delayed_work jackdet_bootstrap;
 
-       wm8958_micdet_cb jack_cb;
-       void *jack_cb_data;
        int micdet_irq;
+       wm1811_micdet_cb micd_cb;
+       void *micd_cb_data;
+       wm1811_mic_id_cb mic_id_cb;
+       void *mic_id_cb_data;
 
        int revision;
-       struct wm8994_pdata *pdata;
 
        unsigned int aif1clk_enable:1;
        unsigned int aif2clk_enable:1;
index 28c89b094c6ee6a5af57bab43a4a7f1c7d84f1f7..90a65c427541fb9290616379f7b53bc17c01d0ea 100644 (file)
@@ -2256,46 +2256,33 @@ static struct regmap_config wm8995_regmap = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8995_spi_probe(struct spi_device *spi)
+static int wm8995_spi_probe(struct spi_device *spi)
 {
        struct wm8995_priv *wm8995;
        int ret;
 
-       wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL);
+       wm8995 = devm_kzalloc(&spi->dev, sizeof(*wm8995), GFP_KERNEL);
        if (!wm8995)
                return -ENOMEM;
 
        spi_set_drvdata(spi, wm8995);
 
-       wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap);
+       wm8995->regmap = devm_regmap_init_spi(spi, &wm8995_regmap);
        if (IS_ERR(wm8995->regmap)) {
                ret = PTR_ERR(wm8995->regmap);
                dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
-               goto err_alloc;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&spi->dev,
                                     &soc_codec_dev_wm8995, wm8995_dai,
                                     ARRAY_SIZE(wm8995_dai));
-       if (ret < 0)
-               goto err_regmap;
-
-       return ret;
-
-err_regmap:
-       regmap_exit(wm8995->regmap);
-err_alloc:
-       kfree(wm8995);
-
        return ret;
 }
 
-static int __devexit wm8995_spi_remove(struct spi_device *spi)
+static int wm8995_spi_remove(struct spi_device *spi)
 {
-       struct wm8995_priv *wm8995 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(wm8995->regmap);
-       kfree(wm8995);
        return 0;
 }
 
@@ -2305,55 +2292,42 @@ static struct spi_driver wm8995_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8995_spi_probe,
-       .remove = __devexit_p(wm8995_spi_remove)
+       .remove = wm8995_spi_remove
 };
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8995_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8995_priv *wm8995;
        int ret;
 
-       wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL);
+       wm8995 = devm_kzalloc(&i2c->dev, sizeof(*wm8995), GFP_KERNEL);
        if (!wm8995)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8995);
 
-       wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap);
+       wm8995->regmap = devm_regmap_init_i2c(i2c, &wm8995_regmap);
        if (IS_ERR(wm8995->regmap)) {
                ret = PTR_ERR(wm8995->regmap);
                dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret);
-               goto err_alloc;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8995, wm8995_dai,
                                     ARRAY_SIZE(wm8995_dai));
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
-               goto err_regmap;
-       }
-
-       return ret;
-
-err_regmap:
-       regmap_exit(wm8995->regmap);
-err_alloc:
-       kfree(wm8995);
 
        return ret;
 }
 
-static __devexit int wm8995_i2c_remove(struct i2c_client *client)
+static int wm8995_i2c_remove(struct i2c_client *client)
 {
-       struct wm8995_priv *wm8995 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm8995->regmap);
-       kfree(wm8995);
        return 0;
 }
 
@@ -2370,7 +2344,7 @@ static struct i2c_driver wm8995_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8995_i2c_probe,
-       .remove = __devexit_p(wm8995_i2c_remove),
+       .remove = wm8995_i2c_remove,
        .id_table = wm8995_i2c_id
 };
 #endif
index 6dcb02c3666fc4e37f6763aa977dec746c15cbe0..46fe83d2b2242610799180edd6774c0dc3cfe674 100644 (file)
@@ -2765,8 +2765,8 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
        },
 };
 
-static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8996_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm8996_priv *wm8996;
        int ret, i;
@@ -3077,7 +3077,7 @@ err:
        return ret;
 }
 
-static __devexit int wm8996_i2c_remove(struct i2c_client *client)
+static int wm8996_i2c_remove(struct i2c_client *client)
 {
        struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
        int i;
@@ -3107,7 +3107,7 @@ static struct i2c_driver wm8996_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm8996_i2c_probe,
-       .remove =   __devexit_p(wm8996_i2c_remove),
+       .remove =   wm8996_i2c_remove,
        .id_table = wm8996_i2c_id,
 };
 
index 2de74e1ea2259ae0750d90d0f3e769698b43469a..630b3d776ec27133cd54f2c3dd440ae304c83417 100644 (file)
@@ -1327,8 +1327,8 @@ static const struct regmap_config wm9081_regmap = {
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm9081_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct wm9081_priv *wm9081;
        unsigned int reg;
@@ -1341,28 +1341,27 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm9081);
 
-       wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
+       wm9081->regmap = devm_regmap_init_i2c(i2c, &wm9081_regmap);
        if (IS_ERR(wm9081->regmap)) {
                ret = PTR_ERR(wm9081->regmap);
                dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
-               goto err_regmap;
+               return ret;
        }
        if (reg != 0x9081) {
                dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
-               ret = -EINVAL;
-               goto err_regmap;
+               return -EINVAL;
        }
 
        ret = wm9081_reset(wm9081->regmap);
        if (ret < 0) {
                dev_err(&i2c->dev, "Failed to issue reset\n");
-               goto err_regmap;
+               return ret;
        }
 
        if (dev_get_platdata(&i2c->dev))
@@ -1382,23 +1381,14 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9081, &wm9081_dai, 1);
        if (ret < 0)
-               goto err_regmap;
+               return ret;
 
        return 0;
-
-err_regmap:
-       regmap_exit(wm9081->regmap);
-err:
-
-       return ret;
 }
 
-static __devexit int wm9081_i2c_remove(struct i2c_client *client)
+static int wm9081_i2c_remove(struct i2c_client *client)
 {
-       struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(wm9081->regmap);
        return 0;
 }
 
@@ -1414,7 +1404,7 @@ static struct i2c_driver wm9081_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe =    wm9081_i2c_probe,
-       .remove =   __devexit_p(wm9081_i2c_remove),
+       .remove =   wm9081_i2c_remove,
        .id_table = wm9081_i2c_id,
 };
 #endif
index c7ddc56175d12ad799f449a814db1432d341305f..a07fe1618eec439d3ba001573331f4046b4e2095 100644 (file)
@@ -628,7 +628,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
        }
 
-       wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+       wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap);
        if (IS_ERR(wm9090->regmap)) {
                ret = PTR_ERR(wm9090->regmap);
                dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -637,16 +637,16 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 
        ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
        if (ret < 0)
-               goto err;
+               return ret;
+
        if (reg != 0x9093) {
                dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        }
 
        ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
        if (ret < 0)
-               goto err;
+               return ret;
 
        if (i2c->dev.platform_data)
                memcpy(&wm9090->pdata, i2c->dev.platform_data,
@@ -658,23 +658,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                        &soc_codec_dev_wm9090,  NULL, 0);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        return 0;
-
-err:
-       regmap_exit(wm9090->regmap);
-       return ret;
 }
 
-static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
+static int wm9090_i2c_remove(struct i2c_client *i2c)
 {
-       struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
-
        snd_soc_unregister_codec(&i2c->dev);
-       regmap_exit(wm9090->regmap);
-
        return 0;
 }
 
@@ -691,7 +683,7 @@ static struct i2c_driver wm9090_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm9090_i2c_probe,
-       .remove = __devexit_p(wm9090_i2c_remove),
+       .remove = wm9090_i2c_remove,
        .id_table = wm9090_id,
 };
 
index e8e782a0c78d0791b88d509ae5fa33c9e6a77840..05b1f346695bce8d10c7e406ed6413a744117102 100644 (file)
@@ -382,13 +382,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
        .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map),
 };
 
-static __devinit int wm9705_probe(struct platform_device *pdev)
+static int wm9705_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
 }
 
-static int __devexit wm9705_remove(struct platform_device *pdev)
+static int wm9705_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -401,7 +401,7 @@ static struct platform_driver wm9705_codec_driver = {
        },
 
        .probe = wm9705_probe,
-       .remove = __devexit_p(wm9705_remove),
+       .remove = wm9705_remove,
 };
 
 module_platform_driver(wm9705_codec_driver);
index 4dd73ea08d0b51287c8a394dd269798fc5dc8b06..8e9a6a3eeb1a257886415be532a186a1900de1e7 100644 (file)
@@ -685,13 +685,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
        .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map),
 };
 
-static __devinit int wm9712_probe(struct platform_device *pdev)
+static int wm9712_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
 }
 
-static int __devexit wm9712_remove(struct platform_device *pdev)
+static int wm9712_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -704,7 +704,7 @@ static struct platform_driver wm9712_codec_driver = {
        },
 
        .probe = wm9712_probe,
-       .remove = __devexit_p(wm9712_remove),
+       .remove = wm9712_remove,
 };
 
 module_platform_driver(wm9712_codec_driver);
index 3eb19fb71d17209e0bccc071ed3f481471201276..f7afa68d8c7fce0a119eb98810e969609e28e225 100644 (file)
@@ -1254,13 +1254,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
        .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map),
 };
 
-static __devinit int wm9713_probe(struct platform_device *pdev)
+static int wm9713_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev,
                        &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
 }
 
-static int __devexit wm9713_remove(struct platform_device *pdev)
+static int wm9713_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
        return 0;
@@ -1273,7 +1273,7 @@ static struct platform_driver wm9713_codec_driver = {
        },
 
        .probe = wm9713_probe,
-       .remove = __devexit_p(wm9713_remove),
+       .remove = wm9713_remove,
 };
 
 module_platform_driver(wm9713_codec_driver);
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
new file mode 100644 (file)
index 0000000..ffc89fa
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ * wm_adsp.c  --  Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/registers.h>
+
+#include "wm_adsp.h"
+
+#define adsp_crit(_dsp, fmt, ...) \
+       dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_err(_dsp, fmt, ...) \
+       dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_warn(_dsp, fmt, ...) \
+       dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_info(_dsp, fmt, ...) \
+       dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_dbg(_dsp, fmt, ...) \
+       dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+
+#define ADSP1_CONTROL_1                   0x00
+#define ADSP1_CONTROL_2                   0x02
+#define ADSP1_CONTROL_3                   0x03
+#define ADSP1_CONTROL_4                   0x04
+#define ADSP1_CONTROL_5                   0x06
+#define ADSP1_CONTROL_6                   0x07
+#define ADSP1_CONTROL_7                   0x08
+#define ADSP1_CONTROL_8                   0x09
+#define ADSP1_CONTROL_9                   0x0A
+#define ADSP1_CONTROL_10                  0x0B
+#define ADSP1_CONTROL_11                  0x0C
+#define ADSP1_CONTROL_12                  0x0D
+#define ADSP1_CONTROL_13                  0x0F
+#define ADSP1_CONTROL_14                  0x10
+#define ADSP1_CONTROL_15                  0x11
+#define ADSP1_CONTROL_16                  0x12
+#define ADSP1_CONTROL_17                  0x13
+#define ADSP1_CONTROL_18                  0x14
+#define ADSP1_CONTROL_19                  0x16
+#define ADSP1_CONTROL_20                  0x17
+#define ADSP1_CONTROL_21                  0x18
+#define ADSP1_CONTROL_22                  0x1A
+#define ADSP1_CONTROL_23                  0x1B
+#define ADSP1_CONTROL_24                  0x1C
+#define ADSP1_CONTROL_25                  0x1E
+#define ADSP1_CONTROL_26                  0x20
+#define ADSP1_CONTROL_27                  0x21
+#define ADSP1_CONTROL_28                  0x22
+#define ADSP1_CONTROL_29                  0x23
+#define ADSP1_CONTROL_30                  0x24
+#define ADSP1_CONTROL_31                  0x26
+
+/*
+ * ADSP1 Control 19
+ */
+#define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+
+/*
+ * ADSP1 Control 30
+ */
+#define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define ADSP1_START                       0x0001  /* DSP1_START */
+#define ADSP1_START_MASK                  0x0001  /* DSP1_START */
+#define ADSP1_START_SHIFT                      0  /* DSP1_START */
+#define ADSP1_START_WIDTH                      1  /* DSP1_START */
+
+#define ADSP2_CONTROL  0
+#define ADSP2_CLOCKING 1
+#define ADSP2_STATUS1  4
+
+/*
+ * ADSP2 Control
+ */
+
+#define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
+#define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define ADSP2_START                       0x0001  /* DSP1_START */
+#define ADSP2_START_MASK                  0x0001  /* DSP1_START */
+#define ADSP2_START_SHIFT                      0  /* DSP1_START */
+#define ADSP2_START_WIDTH                      1  /* DSP1_START */
+
+/*
+ * ADSP2 clocking
+ */
+#define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
+
+/*
+ * ADSP2 Status 1
+ */
+#define ADSP2_RAM_RDY                     0x0001
+#define ADSP2_RAM_RDY_MASK                0x0001
+#define ADSP2_RAM_RDY_SHIFT                    0
+#define ADSP2_RAM_RDY_WIDTH                    1
+
+
+static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
+                                                       int type)
+{
+       int i;
+
+       for (i = 0; i < dsp->num_mems; i++)
+               if (dsp->mem[i].type == type)
+                       return &dsp->mem[i];
+
+       return NULL;
+}
+
+static int wm_adsp_load(struct wm_adsp *dsp)
+{
+       const struct firmware *firmware;
+       struct regmap *regmap = dsp->regmap;
+       unsigned int pos = 0;
+       const struct wmfw_header *header;
+       const struct wmfw_adsp1_sizes *adsp1_sizes;
+       const struct wmfw_adsp2_sizes *adsp2_sizes;
+       const struct wmfw_footer *footer;
+       const struct wmfw_region *region;
+       const struct wm_adsp_region *mem;
+       const char *region_name;
+       char *file, *text;
+       unsigned int reg;
+       int regions = 0;
+       int ret, offset, type, sizes;
+
+       file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (file == NULL)
+               return -ENOMEM;
+
+       snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
+       file[PAGE_SIZE - 1] = '\0';
+
+       ret = request_firmware(&firmware, file, dsp->dev);
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to request '%s'\n", file);
+               goto out;
+       }
+       ret = -EINVAL;
+
+       pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+       if (pos >= firmware->size) {
+               adsp_err(dsp, "%s: file too short, %zu bytes\n",
+                        file, firmware->size);
+               goto out_fw;
+       }
+
+       header = (void*)&firmware->data[0];
+
+       if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+               adsp_err(dsp, "%s: invalid magic\n", file);
+               goto out_fw;
+       }
+
+       if (header->ver != 0) {
+               adsp_err(dsp, "%s: unknown file format %d\n",
+                        file, header->ver);
+               goto out_fw;
+       }
+
+       if (header->core != dsp->type) {
+               adsp_err(dsp, "%s: invalid core %d != %d\n",
+                        file, header->core, dsp->type);
+               goto out_fw;
+       }
+
+       switch (dsp->type) {
+       case WMFW_ADSP1:
+               pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+               adsp1_sizes = (void *)&(header[1]);
+               footer = (void *)&(adsp1_sizes[1]);
+               sizes = sizeof(*adsp1_sizes);
+
+               adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
+                        file, le32_to_cpu(adsp1_sizes->dm),
+                        le32_to_cpu(adsp1_sizes->pm),
+                        le32_to_cpu(adsp1_sizes->zm));
+               break;
+
+       case WMFW_ADSP2:
+               pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
+               adsp2_sizes = (void *)&(header[1]);
+               footer = (void *)&(adsp2_sizes[1]);
+               sizes = sizeof(*adsp2_sizes);
+
+               adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
+                        file, le32_to_cpu(adsp2_sizes->xm),
+                        le32_to_cpu(adsp2_sizes->ym),
+                        le32_to_cpu(adsp2_sizes->pm),
+                        le32_to_cpu(adsp2_sizes->zm));
+               break;
+
+       default:
+               BUG_ON(NULL == "Unknown DSP type");
+               goto out_fw;
+       }
+
+       if (le32_to_cpu(header->len) != sizeof(*header) +
+           sizes + sizeof(*footer)) {
+               adsp_err(dsp, "%s: unexpected header length %d\n",
+                        file, le32_to_cpu(header->len));
+               goto out_fw;
+       }
+
+       adsp_dbg(dsp, "%s: timestamp %llu\n", file,
+                le64_to_cpu(footer->timestamp));
+
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*region)) {
+               region = (void *)&(firmware->data[pos]);
+               region_name = "Unknown";
+               reg = 0;
+               text = NULL;
+               offset = le32_to_cpu(region->offset) & 0xffffff;
+               type = be32_to_cpu(region->type) & 0xff;
+               mem = wm_adsp_find_region(dsp, type);
+               
+               switch (type) {
+               case WMFW_NAME_TEXT:
+                       region_name = "Firmware name";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_INFO_TEXT:
+                       region_name = "Information";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "Absolute";
+                       reg = offset;
+                       break;
+               case WMFW_ADSP1_PM:
+                       BUG_ON(!mem);
+                       region_name = "PM";
+                       reg = mem->base + (offset * 3);
+                       break;
+               case WMFW_ADSP1_DM:
+                       BUG_ON(!mem);
+                       region_name = "DM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP2_XM:
+                       BUG_ON(!mem);
+                       region_name = "XM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP2_YM:
+                       BUG_ON(!mem);
+                       region_name = "YM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP1_ZM:
+                       BUG_ON(!mem);
+                       region_name = "ZM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               default:
+                       adsp_warn(dsp,
+                                 "%s.%d: Unknown region type %x at %d(%x)\n",
+                                 file, regions, type, pos, pos);
+                       break;
+               }
+
+               adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
+                        regions, le32_to_cpu(region->len), offset,
+                        region_name);
+
+               if (text) {
+                       memcpy(text, region->data, le32_to_cpu(region->len));
+                       adsp_info(dsp, "%s: %s\n", file, text);
+                       kfree(text);
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, region->data,
+                                              le32_to_cpu(region->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+                                       file, regions,
+                                       le32_to_cpu(region->len), offset,
+                                       region_name, ret);
+                               goto out_fw;
+                       }
+               }
+
+               pos += le32_to_cpu(region->len) + sizeof(*region);
+               regions++;
+       }
+       
+       if (pos > firmware->size)
+               adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+                         file, regions, pos - firmware->size);
+
+out_fw:
+       release_firmware(firmware);
+out:
+       kfree(file);
+
+       return ret;
+}
+
+static int wm_adsp_load_coeff(struct wm_adsp *dsp)
+{
+       struct regmap *regmap = dsp->regmap;
+       struct wmfw_coeff_hdr *hdr;
+       struct wmfw_coeff_item *blk;
+       const struct firmware *firmware;
+       const char *region_name;
+       int ret, pos, blocks, type, offset, reg;
+       char *file;
+
+       file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (file == NULL)
+               return -ENOMEM;
+
+       snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
+       file[PAGE_SIZE - 1] = '\0';
+
+       ret = request_firmware(&firmware, file, dsp->dev);
+       if (ret != 0) {
+               adsp_warn(dsp, "Failed to request '%s'\n", file);
+               ret = 0;
+               goto out;
+       }
+       ret = -EINVAL;
+
+       if (sizeof(*hdr) >= firmware->size) {
+               adsp_err(dsp, "%s: file too short, %zu bytes\n",
+                       file, firmware->size);
+               goto out_fw;
+       }
+
+       hdr = (void*)&firmware->data[0];
+       if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+               adsp_err(dsp, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
+               (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+               (le32_to_cpu(hdr->ver) >>  8) & 0xff,
+               le32_to_cpu(hdr->ver) & 0xff);
+
+       pos = le32_to_cpu(hdr->len);
+
+       blocks = 0;
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*blk)) {
+               blk = (void*)(&firmware->data[pos]);
+
+               type = be32_to_cpu(blk->type) & 0xff;
+               offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+               adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
+                        file, blocks, le32_to_cpu(blk->id),
+                        (le32_to_cpu(blk->ver) >> 16) & 0xff,
+                        (le32_to_cpu(blk->ver) >>  8) & 0xff,
+                        le32_to_cpu(blk->ver) & 0xff);
+               adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
+                        file, blocks, le32_to_cpu(blk->len), offset, type);
+
+               reg = 0;
+               region_name = "Unknown";
+               switch (type) {
+               case WMFW_NAME_TEXT:
+               case WMFW_INFO_TEXT:
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "register";
+                       reg = offset;
+                       break;
+               default:
+                       adsp_err(dsp, "Unknown region type %x\n", type);
+                       break;
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, blk->data,
+                                              le32_to_cpu(blk->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write to %x in %s\n",
+                                       file, blocks, reg, region_name);
+                       }
+               }
+
+               pos += le32_to_cpu(blk->len) + sizeof(*blk);
+               blocks++;
+       }
+
+       if (pos > firmware->size)
+               adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+                         file, blocks, pos - firmware->size);
+
+out_fw:
+       release_firmware(firmware);
+out:
+       kfree(file);
+       return 0;
+}
+
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol,
+                  int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_SYS_ENA, ADSP1_SYS_ENA);
+
+               ret = wm_adsp_load(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = wm_adsp_load_coeff(dsp);
+               if (ret != 0)
+                       goto err;
+
+               /* Start the core running */
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_CORE_ENA | ADSP1_START,
+                                  ADSP1_CORE_ENA | ADSP1_START);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               /* Halt the core */
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_CORE_ENA | ADSP1_START, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
+                                  ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_SYS_ENA, 0);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                          ADSP1_SYS_ENA, 0);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp1_event);
+
+static int wm_adsp2_ena(struct wm_adsp *dsp)
+{
+       unsigned int val;
+       int ret, count;
+
+       ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                ADSP2_SYS_ENA, ADSP2_SYS_ENA);
+       if (ret != 0)
+               return ret;
+
+       /* Wait for the RAM to start, should be near instantaneous */
+       count = 0;
+       do {
+               ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
+                                 &val);
+               if (ret != 0)
+                       return ret;
+       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+       if (!(val & ADSP2_RAM_RDY)) {
+               adsp_err(dsp, "Failed to start DSP RAM\n");
+               return -EBUSY;
+       }
+
+       adsp_dbg(dsp, "RAM ready after %d polls\n", count);
+       adsp_info(dsp, "RAM ready after %d polls\n", count);
+
+       return 0;
+}
+
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       unsigned int val;
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               /*
+                * For simplicity set the DSP clock rate to be the
+                * SYSCLK rate rather than making it configurable.
+                */
+               ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
+                                ret);
+                       return ret;
+               }
+               val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+                       >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+               ret = regmap_update_bits(dsp->regmap,
+                                        dsp->base + ADSP2_CLOCKING,
+                                        ADSP2_CLK_SEL_MASK, val);
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to set clock rate: %d\n",
+                                ret);
+                       return ret;
+               }
+
+               if (dsp->dvfs) {
+                       ret = regmap_read(dsp->regmap,
+                                         dsp->base + ADSP2_CLOCKING, &val);
+                       if (ret != 0) {
+                               dev_err(dsp->dev,
+                                       "Failed to read clocking: %d\n", ret);
+                               return ret;
+                       }
+
+                       if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+                               ret = regulator_enable(dsp->dvfs);
+                               if (ret != 0) {
+                                       dev_err(dsp->dev,
+                                               "Failed to enable supply: %d\n",
+                                               ret);
+                                       return ret;
+                               }
+
+                               ret = regulator_set_voltage(dsp->dvfs,
+                                                           1800000,
+                                                           1800000);
+                               if (ret != 0) {
+                                       dev_err(dsp->dev,
+                                               "Failed to raise supply: %d\n",
+                                               ret);
+                                       return ret;
+                               }
+                       }
+               }
+
+               ret = wm_adsp2_ena(dsp);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm_adsp_load(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = wm_adsp_load_coeff(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = regmap_update_bits(dsp->regmap,
+                                        dsp->base + ADSP2_CONTROL,
+                                        ADSP2_CORE_ENA | ADSP2_START,
+                                        ADSP2_CORE_ENA | ADSP2_START);
+               if (ret != 0)
+                       goto err;
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                  ADSP2_SYS_ENA | ADSP2_CORE_ENA |
+                                  ADSP2_START, 0);
+
+               if (dsp->dvfs) {
+                       ret = regulator_set_voltage(dsp->dvfs, 1200000,
+                                                   1800000);
+                       if (ret != 0)
+                               dev_warn(dsp->dev,
+                                        "Failed to lower supply: %d\n",
+                                        ret);
+
+                       ret = regulator_disable(dsp->dvfs);
+                       if (ret != 0)
+                               dev_err(dsp->dev,
+                                       "Failed to enable supply: %d\n",
+                                       ret);
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                          ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_event);
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
+{
+       int ret;
+
+       /*
+        * Disable the DSP memory by default when in reset for a small
+        * power saving.
+        */
+       ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
+                                ADSP2_MEM_ENA, 0);
+       if (ret != 0) {
+               adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
+               return ret;
+       }
+
+       if (dvfs) {
+               adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
+               if (IS_ERR(adsp->dvfs)) {
+                       ret = PTR_ERR(adsp->dvfs);
+                       dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
+                       return ret;
+               }
+
+               ret = regulator_enable(adsp->dvfs);
+               if (ret != 0) {
+                       dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
+               if (ret != 0) {
+                       dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = regulator_disable(adsp->dvfs);
+               if (ret != 0) {
+                       dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
new file mode 100644 (file)
index 0000000..ffd29a4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * wm_adsp.h  --  Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __WM_ADSP_H
+#define __WM_ADSP_H
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wmfw.h"
+
+struct regulator;
+
+struct wm_adsp_region {
+       int type;
+       unsigned int base;
+};
+
+struct wm_adsp {
+       const char *part;
+       int num;
+       int type;
+       struct device *dev;
+       struct regmap *regmap;
+
+       int base;
+
+       const struct wm_adsp_region *mem;
+       int num_mems;
+
+       struct regulator *dvfs;
+};
+
+#define WM_ADSP1(wname, num) \
+       { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = num, .event = wm_adsp1_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+#define WM_ADSP2(wname, num) \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = num, .event = wm_adsp2_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+
+#endif
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
new file mode 100644 (file)
index 0000000..5632ded
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * wmfw.h - Wolfson firmware format information
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __WMFW_H
+#define __WMFW_H
+
+#include <linux/types.h>
+
+struct wmfw_header {
+       char magic[4];
+       __le32 len;
+       __le16 rev;
+       u8 core;
+       u8 ver;
+} __packed;
+
+struct wmfw_footer {
+       __le64 timestamp;
+       __le32 checksum;
+} __packed;
+
+struct wmfw_adsp1_sizes {
+       __le32 dm;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_adsp2_sizes {
+       __le32 xm;
+       __le32 ym;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_region {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 len;
+       u8 data[];
+} __packed;
+
+struct wmfw_id_hdr {
+       __be32 core_id;
+       __be32 core_rev;
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 dm;
+       __be32 algs;
+} __packed;
+
+struct wmfw_adsp2_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 xm;
+       __be32 ym;
+       __be32 algs;
+} __packed;
+
+struct wmfw_alg_hdr {
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 dm;
+} __packed;
+
+struct wmfw_adsp2_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 xm;
+       __be32 ym;
+} __packed;
+
+struct wmfw_coeff_hdr {
+       u8 magic[4];
+       __le32 len;
+       __le32 ver;
+       u8 data[];
+} __packed;
+
+struct wmfw_coeff_item {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 id;
+       __le32 ver;
+       __le32 sr;
+       __le32 len;
+       u8 data[];
+} __packed;
+
+#define WMFW_ADSP1 1
+#define WMFW_ADSP2 2
+
+#define WMFW_ABSOLUTE  0xf0
+#define WMFW_NAME_TEXT 0xfe
+#define WMFW_INFO_TEXT 0xff
+
+#define WMFW_ADSP1_PM 2
+#define WMFW_ADSP1_DM 3
+#define WMFW_ADSP1_ZM 4
+
+#define WMFW_ADSP2_PM 2
+#define WMFW_ADSP2_ZM 4
+#define WMFW_ADSP2_XM 5
+#define WMFW_ADSP2_YM 6
+
+#endif
index 6fac5af13298ffa2c64ebf5bad1b5fde6a0ac6f6..d55e6477bff0c9a855379d26db50538ff7b5e178 100644 (file)
@@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
+       /* set the CPU system clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 714e51e5be5bd2c7038f1965a74545a01c5a268c..55e2bf652beff53d6694e3cf20d2d2e4d6f17393 100644 (file)
 #define ACLKXE         BIT(5)
 #define TX_ASYNC       BIT(6)
 #define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
 #define ACLKRE         BIT(5)
 #define RX_ASYNC       BIT(6)
 #define ACLKRPOL       BIT(7)
+#define ACLKRDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
 #define AHCLKXDIV(val) (val)
 #define AHCLKXPOL      BIT(14)
 #define AHCLKXE                BIT(15)
+#define AHCLKXDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
 #define AHCLKRDIV(val) (val)
 #define AHCLKRPOL      BIT(14)
 #define AHCLKRE                BIT(15)
+#define AHCLKRDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
@@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *base = dev->base;
 
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_B:
+       case SND_SOC_DAIFMT_AC97:
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               break;
+       default:
+               /* configure a full-word SYNC pulse (LRCLK) */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+
+               /* make 1st data bit occur one ACLK cycle after the frame sync */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+               break;
+       }
+
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* codec is clock and frame slave */
@@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | AHCLKX | AFSX);
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
@@ -554,59 +574,75 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-static int davinci_config_channel_size(struct davinci_audio_dev *dev,
-                                      int channel_size)
+static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
 {
-       u32 fmt = 0;
-       u32 mask, rotate;
-
-       switch (channel_size) {
-       case DAVINCI_AUDIO_WORD_8:
-               fmt = 0x03;
-               rotate = 6;
-               mask = 0x000000ff;
-               break;
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
 
-       case DAVINCI_AUDIO_WORD_12:
-               fmt = 0x05;
-               rotate = 5;
-               mask = 0x00000fff;
+       switch (div_id) {
+       case 0:         /* MCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+                              AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+                              AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
                break;
 
-       case DAVINCI_AUDIO_WORD_16:
-               fmt = 0x07;
-               rotate = 4;
-               mask = 0x0000ffff;
+       case 1:         /* BCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+                              ACLKXDIV(div - 1), ACLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+                              ACLKRDIV(div - 1), ACLKRDIV_MASK);
                break;
 
-       case DAVINCI_AUDIO_WORD_20:
-               fmt = 0x09;
-               rotate = 3;
-               mask = 0x000fffff;
+       case 2:         /* BCLK/LRCLK ratio */
+               dev->bclk_lrclk_ratio = div;
                break;
 
-       case DAVINCI_AUDIO_WORD_24:
-               fmt = 0x0B;
-               rotate = 2;
-               mask = 0x00ffffff;
-               break;
+       default:
+               return -EINVAL;
+       }
 
-       case DAVINCI_AUDIO_WORD_28:
-               fmt = 0x0D;
-               rotate = 1;
-               mask = 0x0fffffff;
-               break;
+       return 0;
+}
 
-       case DAVINCI_AUDIO_WORD_32:
-               fmt = 0x0F;
-               rotate = 0;
-               mask = 0xffffffff;
-               break;
+static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                   unsigned int freq, int dir)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
 
-       default:
-               return -EINVAL;
+       if (dir == SND_SOC_CLOCK_OUT) {
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+       } else {
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
        }
 
+       return 0;
+}
+
+static int davinci_config_channel_size(struct davinci_audio_dev *dev,
+                                      int word_length)
+{
+       u32 fmt;
+       u32 rotate = (32 - word_length) / 4;
+       u32 mask = (1ULL << word_length) - 1;
+
+       /*
+        * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
+        * callback, take it into account here. That allows us to for example
+        * send 32 bits per channel to the codec, while only 16 of them carry
+        * audio payload.
+        * The clock ratio is given for a full period of data (both left and
+        * right channels), so it has to be divided by 2.
+        */
+       if (dev->bclk_lrclk_ratio)
+               word_length = dev->bclk_lrclk_ratio / 2;
+
+       /* mapping of the XSSZ bit-field as described in the datasheet */
+       fmt = (word_length >> 1) - 1;
+
        mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
                                        RXSSZ(fmt), RXSSZ(0x0F));
        mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
@@ -709,8 +745,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* bit stream is MSB first  with no delay */
                /* DSP_B mode */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
-                               AHCLKXE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
                mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
 
@@ -720,14 +754,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "playback tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
        } else {
                /* bit stream is MSB first with no delay */
                /* DSP_B mode */
                mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
-                               AHCLKRE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
 
                if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
@@ -736,8 +766,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "capture tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
        }
 }
 
@@ -800,19 +828,27 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_U8:
        case SNDRV_PCM_FORMAT_S8:
                dma_params->data_type = 1;
-               word_length = DAVINCI_AUDIO_WORD_8;
+               word_length = 8;
                break;
 
        case SNDRV_PCM_FORMAT_U16_LE:
        case SNDRV_PCM_FORMAT_S16_LE:
                dma_params->data_type = 2;
-               word_length = DAVINCI_AUDIO_WORD_16;
+               word_length = 16;
+               break;
+
+       case SNDRV_PCM_FORMAT_U24_3LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               dma_params->data_type = 3;
+               word_length = 24;
                break;
 
+       case SNDRV_PCM_FORMAT_U24_LE:
+       case SNDRV_PCM_FORMAT_S24_LE:
        case SNDRV_PCM_FORMAT_U32_LE:
        case SNDRV_PCM_FORMAT_S32_LE:
                dma_params->data_type = 4;
-               word_length = DAVINCI_AUDIO_WORD_32;
+               word_length = 32;
                break;
 
        default:
@@ -880,13 +916,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .trigger        = davinci_mcasp_trigger,
        .hw_params      = davinci_mcasp_hw_params,
        .set_fmt        = davinci_mcasp_set_dai_fmt,
-
+       .set_clkdiv     = davinci_mcasp_set_clkdiv,
+       .set_sysclk     = davinci_mcasp_set_sysclk,
 };
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                                SNDRV_PCM_FMTBIT_U8 | \
                                SNDRV_PCM_FMTBIT_S16_LE | \
                                SNDRV_PCM_FMTBIT_U16_LE | \
+                               SNDRV_PCM_FMTBIT_S24_LE | \
+                               SNDRV_PCM_FMTBIT_U24_LE | \
+                               SNDRV_PCM_FMTBIT_S24_3LE | \
+                               SNDRV_PCM_FMTBIT_U24_3LE | \
                                SNDRV_PCM_FMTBIT_S32_LE | \
                                SNDRV_PCM_FMTBIT_U32_LE)
 
@@ -1089,7 +1130,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dev->tdm_slots = pdata->tdm_slots;
        dev->num_serializer = pdata->num_serializer;
        dev->serial_dir = pdata->serial_dir;
-       dev->codec_fmt = pdata->codec_fmt;
        dev->version = pdata->version;
        dev->txnumevt = pdata->txnumevt;
        dev->rxnumevt = pdata->rxnumevt;
@@ -1098,6 +1138,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
        dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
                                                        mem->start);
@@ -1115,6 +1156,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
        dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
                                                        mem->start);
index 0de9ed6ce038a8472aeb762d403fbf26d579bc24..0edd3b5a37fd86a5c04a54b66b8735d900e33a06 100644 (file)
 
 #include "davinci-pcm.h"
 
-#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 #define DAVINCI_MCASP_I2S_DAI  0
 #define DAVINCI_MCASP_DIT_DAI  1
 
-enum {
-       DAVINCI_AUDIO_WORD_8 = 0,
-       DAVINCI_AUDIO_WORD_12,
-       DAVINCI_AUDIO_WORD_16,
-       DAVINCI_AUDIO_WORD_20,
-       DAVINCI_AUDIO_WORD_24,
-       DAVINCI_AUDIO_WORD_32,
-       DAVINCI_AUDIO_WORD_28,  /* This is only valid for McASP */
-};
-
 struct davinci_audio_dev {
        struct davinci_pcm_dma_params dma_params[2];
        void __iomem *base;
-       int sample_rate;
        struct device *dev;
-       unsigned int codec_fmt;
 
        /* McASP specific data */
        int     tdm_slots;
@@ -50,6 +38,7 @@ struct davinci_audio_dev {
        u8      num_serializer;
        u8      *serial_dir;
        u8      version;
+       u8      bclk_lrclk_ratio;
 
        /* McASP FIFO related */
        u8      txnumevt;
index 93ea3bf567e1fd1835ff643ff4e73d67fecdce12..afab81f844ae82c32418d6d1f83301c2d29d1f4e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
+#include <linux/genalloc.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -23,7 +24,6 @@
 #include <sound/soc.h>
 
 #include <asm/dma.h>
-#include <mach/sram.h>
 
 #include "davinci-pcm.h"
 
@@ -67,13 +67,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -90,13 +86,9 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
                 SNDRV_PCM_INFO_PAUSE |
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -259,7 +251,9 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
        }
 }
 
-static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
+#ifdef CONFIG_GENERIC_ALLOCATOR
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
                struct snd_pcm_hardware *ppcm)
 {
        struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -271,9 +265,10 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
                return 0;
 
        ppcm->period_bytes_max = size;
-       iram_virt = sram_alloc(size, &iram_phys);
+       iram_virt = (void *)gen_pool_alloc(sram_pool, size);
        if (!iram_virt)
                goto exit1;
+       iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
        iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
        if (!iram_dma)
                goto exit2;
@@ -285,11 +280,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
        return 0;
 exit2:
        if (iram_virt)
-               sram_free(iram_virt, size);
+               gen_pool_free(sram_pool, (unsigned)iram_virt, size);
 exit1:
        return -ENOMEM;
 }
 
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct gen_pool *sram_pool = prtd->params->sram_pool;
+
+       gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
+}
+#else
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
+               struct snd_pcm_hardware *ppcm)
+{
+       return 0;
+}
+
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+}
+#endif
+
 /*
  * Only used with ping/pong.
  * This is called after runtime->dma_addr, period_bytes and data_type are valid
@@ -676,7 +693,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
 
        ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
                        &pcm_hardware_playback : &pcm_hardware_capture;
-       allocate_sram(substream, params->sram_size, ppcm);
+       allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
        snd_soc_set_runtime_hwparams(substream, ppcm);
        /* ensure that buffer size is a multiple of period size */
        ret = snd_pcm_hw_constraint_integer(runtime,
@@ -819,7 +836,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
                buf->area = NULL;
                iram_dma = buf->private_data;
                if (iram_dma) {
-                       sram_free(iram_dma->area, iram_dma->bytes);
+                       davinci_free_sram(substream, iram_dma);
                        kfree(iram_dma);
                }
        }
index fc4d01cdd8c95c92b11694faece56d77fc648bd9..b6ef7039dd097b4ac99c6e9b14a0c35ed59fd203 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _DAVINCI_PCM_H
 #define _DAVINCI_PCM_H
 
+#include <linux/genalloc.h>
 #include <linux/platform_data/davinci_asp.h>
 #include <mach/edma.h>
 
@@ -20,6 +21,7 @@ struct davinci_pcm_dma_params {
        unsigned short acnt;
        dma_addr_t dma_addr;            /* device physical address for DMA */
        unsigned sram_size;
+       struct gen_pool *sram_pool;     /* SRAM gen_pool for ping pong */
        enum dma_event_q asp_chan_q;    /* event queue number for ASP channel */
        enum dma_event_q ram_chan_q;    /* event queue number for RAM channel */
        unsigned char data_type;        /* xfer data type */
index 4563b28bd6254ddbeda6f0cd8229f22b10159ef7..3b98159d9645a8ecf917fb8c86c41de6a401c929 100644 (file)
@@ -46,6 +46,20 @@ config SND_SOC_P1022_DS
          This will also include the Wolfson Microelectronics WM8776 codec
          driver.
 
+config SND_SOC_P1022_RDK
+       tristate "ALSA SoC support for the Freescale / iVeia P1022 RDK board"
+       # I2C is necessary for the WM8960 driver
+       depends on P1022_RDK && I2C
+       select SND_SOC_FSL_SSI
+       select SND_SOC_FSL_UTILS
+       select SND_SOC_POWERPC_DMA
+       select SND_SOC_WM8960
+       default y if P1022_RDK
+       help
+         Say Y if you want to enable audio on the Freescale / iVeia
+         P1022 RDK board.  This will also include the Wolfson
+         Microelectronics WM8960 codec driver.
+
 config SND_SOC_MPC5200_I2S
        tristate "Freescale MPC5200 PSC in I2S mode driver"
        depends on PPC_MPC52xx && PPC_BESTCOMM
@@ -98,12 +112,12 @@ config SND_SOC_IMX_PCM
        tristate
 
 config SND_SOC_IMX_PCM_FIQ
-       tristate
+       bool
        select FIQ
        select SND_SOC_IMX_PCM
 
 config SND_SOC_IMX_PCM_DMA
-       tristate
+       bool
        select SND_SOC_DMAENGINE_PCM
        select SND_SOC_IMX_PCM
 
@@ -112,7 +126,7 @@ config SND_SOC_IMX_AUDMUX
 
 config SND_MXC_SOC_WM1133_EV1
        tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted"
-       depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
+       depends on MACH_MX31ADS_WM1133_EV1
        select SND_SOC_WM8350
        select SND_SOC_IMX_PCM_FIQ
        select SND_SOC_IMX_AUDMUX
index 5f3cf3f52ea03e16a1a374ca530f6daec7a2ed35..afd34794db539a0f5de4154a5a635a69f40913e1 100644 (file)
@@ -6,6 +6,10 @@ obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
 snd-soc-p1022-ds-objs := p1022_ds.o
 obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
 
+# P1022 RDK Machine Support
+snd-soc-p1022-rdk-objs := p1022_rdk.o
+obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
+
 # Freescale PowerPC SSI/DMA Platform Support
 snd-soc-fsl-ssi-objs := fsl_ssi.o
 snd-soc-fsl-utils-objs := fsl_utils.o
@@ -26,14 +30,18 @@ obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
 # i.MX Platform Support
 snd-soc-imx-ssi-objs := imx-ssi.o
 snd-soc-imx-audmux-objs := imx-audmux.o
+snd-soc-imx-pcm-objs := imx-pcm.o
+ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),)
+       snd-soc-imx-pcm-objs += imx-pcm-fiq.o
+endif
+ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),)
+       snd-soc-imx-pcm-objs += imx-pcm-dma.o
+endif
 
 obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
 obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
-snd-soc-imx-pcm-y := imx-pcm.o
-snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
-snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
index 267d5b4b63ceb8392c9bd1433e2f1f6c288b92cf..75ffdf0e2aada7dc3a75d1d481014b8e7f94d160 100644 (file)
@@ -93,7 +93,7 @@ static struct snd_soc_card eukrea_tlv320 = {
        .num_links      = 1,
 };
 
-static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
+static int eukrea_tlv320_probe(struct platform_device *pdev)
 {
        int ret;
        int int_port = 0, ext_port;
@@ -142,7 +142,7 @@ static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit eukrea_tlv320_remove(struct platform_device *pdev)
+static int eukrea_tlv320_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&eukrea_tlv320);
 
@@ -155,7 +155,7 @@ static struct platform_driver eukrea_tlv320_driver = {
                .owner = THIS_MODULE,
        },
        .probe = eukrea_tlv320_probe,
-       .remove = __devexit_p(eukrea_tlv320_remove),};
+       .remove = eukrea_tlv320_remove,};
 
 module_platform_driver(eukrea_tlv320_driver);
 
index 6feb26500580749fc4b19b18368fdcd2d73175d0..9cc5c1f82f093f5b171877e1bd5e5672cf9c46cd 100644 (file)
@@ -894,7 +894,7 @@ static struct snd_pcm_ops fsl_dma_ops = {
        .pointer        = fsl_dma_pointer,
 };
 
-static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
+static int fsl_soc_dma_probe(struct platform_device *pdev)
  {
        struct dma_object *dma;
        struct device_node *np = pdev->dev.of_node;
@@ -958,7 +958,7 @@ static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit fsl_soc_dma_remove(struct platform_device *pdev)
+static int fsl_soc_dma_remove(struct platform_device *pdev)
 {
        struct dma_object *dma = dev_get_drvdata(&pdev->dev);
 
@@ -983,7 +983,7 @@ static struct platform_driver fsl_soc_dma_driver = {
                .of_match_table = fsl_soc_dma_ids,
        },
        .probe = fsl_soc_dma_probe,
-       .remove = __devexit_p(fsl_soc_dma_remove),
+       .remove = fsl_soc_dma_remove,
 };
 
 module_platform_driver(fsl_soc_dma_driver);
index 4ed2afd47782cba1667cf109d3c63c6d501ba2a1..7decbd9b234094945f58065962ba6a6cb22c0200 100644 (file)
@@ -639,7 +639,7 @@ static void make_lowercase(char *s)
        }
 }
 
-static int __devinit fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe(struct platform_device *pdev)
 {
        struct fsl_ssi_private *ssi_private;
        int ret = 0;
index 524ce6210ceea8588594664064d7e4283e02d59e..251f4d981e0c6e8882c6f0d9c23efad821e87e05 100644 (file)
@@ -162,7 +162,7 @@ static void __init audmux_debugfs_init(void)
        }
 }
 
-static void __devexit audmux_debugfs_remove(void)
+static void audmux_debugfs_remove(void)
 {
        debugfs_remove_recursive(audmux_debugfs_root);
 }
@@ -244,7 +244,7 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
 }
 EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
 
-static int __devinit imx_audmux_probe(struct platform_device *pdev)
+static int imx_audmux_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct pinctrl *pinctrl;
@@ -278,7 +278,7 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit imx_audmux_remove(struct platform_device *pdev)
+static int imx_audmux_remove(struct platform_device *pdev)
 {
        if (audmux_type == IMX31_AUDMUX)
                audmux_debugfs_remove();
@@ -289,7 +289,7 @@ static int __devexit imx_audmux_remove(struct platform_device *pdev)
 
 static struct platform_driver imx_audmux_driver = {
        .probe          = imx_audmux_probe,
-       .remove         = __devexit_p(imx_audmux_remove),
+       .remove         = imx_audmux_remove,
        .id_table       = imx_audmux_ids,
        .driver = {
                .name   = DRIVER_NAME,
index 549b31fdc9dd4eabf268db09c5318e047e1a9646..4ae30f21fdb5385c003553e31c60bcaaa60d23cb 100644 (file)
@@ -98,7 +98,7 @@ static struct snd_soc_card imx_mc13783 = {
        .num_dapm_routes = ARRAY_SIZE(imx_mc13783_routes),
 };
 
-static int __devinit imx_mc13783_probe(struct platform_device *pdev)
+static int imx_mc13783_probe(struct platform_device *pdev)
 {
        int ret;
 
@@ -148,7 +148,7 @@ static int __devinit imx_mc13783_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit imx_mc13783_remove(struct platform_device *pdev)
+static int imx_mc13783_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&imx_mc13783);
 
@@ -161,7 +161,7 @@ static struct platform_driver imx_mc13783_audio_driver = {
                .owner = THIS_MODULE,
        },
        .probe = imx_mc13783_probe,
-       .remove = __devexit_p(imx_mc13783_remove)
+       .remove = imx_mc13783_remove
 };
 
 module_platform_driver(imx_mc13783_audio_driver);
index d85929b79c350cad32be2ad46e2963cdc93249da..bf363d8d044aa2f1c38d44f0c66a20f1131a65de 100644 (file)
@@ -154,12 +154,12 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
        .pcm_free       = imx_pcm_free,
 };
 
-static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
+static int imx_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
 }
 
-static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
+static int imx_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -171,7 +171,7 @@ static struct platform_driver imx_pcm_driver = {
                        .owner = THIS_MODULE,
        },
        .probe = imx_soc_platform_probe,
-       .remove = __devexit_p(imx_soc_platform_remove),
+       .remove = imx_soc_platform_remove,
 };
 
 module_platform_driver(imx_pcm_driver);
index 9ffc9e66308f297a5e9a6ed39c7a3ddece48b9d2..5ec362ae4d012b654cdadbfeace42036ed76764e 100644 (file)
@@ -281,7 +281,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
        .pcm_free       = imx_pcm_fiq_free,
 };
 
-static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
+static int imx_soc_platform_probe(struct platform_device *pdev)
 {
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
        int ret;
@@ -315,7 +315,7 @@ failed_register:
        return ret;
 }
 
-static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
+static int imx_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -328,7 +328,7 @@ static struct platform_driver imx_pcm_driver = {
        },
 
        .probe = imx_soc_platform_probe,
-       .remove = __devexit_p(imx_soc_platform_remove),
+       .remove = imx_soc_platform_remove,
 };
 
 module_platform_driver(imx_pcm_driver);
index 93dc360b17770cbb2833afdc6fc7eb5c70c5b19a..d5cd9eff3b48e92ca77349b930fe84056fcd7017 100644 (file)
@@ -103,3 +103,7 @@ void imx_pcm_free(struct snd_pcm *pcm)
        }
 }
 EXPORT_SYMBOL_GPL(imx_pcm_free);
+
+MODULE_DESCRIPTION("Freescale i.MX PCM driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
index 199408ec42612dfe57f63e3933457e901cf7bcfa..424347e9b2d7d89df9e2db3a264c78c0a8113014 100644 (file)
@@ -56,7 +56,7 @@ static const struct snd_soc_dapm_widget imx_sgtl5000_dapm_widgets[] = {
        SND_SOC_DAPM_SPK("Ext Spk", NULL),
 };
 
-static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
+static int imx_sgtl5000_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct device_node *ssi_np, *codec_np;
@@ -162,6 +162,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
        if (ret)
                goto clk_fail;
        data->card.num_links = 1;
+       data->card.owner = THIS_MODULE;
        data->card.dai_link = &data->dai;
        data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
        data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
@@ -184,7 +185,7 @@ fail:
        return ret;
 }
 
-static int __devexit imx_sgtl5000_remove(struct platform_device *pdev)
+static int imx_sgtl5000_remove(struct platform_device *pdev)
 {
        struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
 
@@ -210,7 +211,7 @@ static struct platform_driver imx_sgtl5000_driver = {
                .of_match_table = imx_sgtl5000_dt_ids,
        },
        .probe = imx_sgtl5000_probe,
-       .remove = __devexit_p(imx_sgtl5000_remove),
+       .remove = imx_sgtl5000_remove,
 };
 module_platform_driver(imx_sgtl5000_driver);
 
index dd566444e3c3b61b832a62e3763645393fcfbd88..3b480423747fc3d00f70978173a676736057c562 100644 (file)
@@ -638,7 +638,7 @@ failed_clk:
        return ret;
 }
 
-static int __devexit imx_ssi_remove(struct platform_device *pdev)
+static int imx_ssi_remove(struct platform_device *pdev)
 {
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
@@ -659,7 +659,7 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
 
 static struct platform_driver imx_ssi_driver = {
        .probe = imx_ssi_probe,
-       .remove = __devexit_p(imx_ssi_remove),
+       .remove = imx_ssi_remove,
 
        .driver = {
                .name = "imx-ssi",
index a313c0ae36dba38f5bd0abbb002f5072c72ec259..a4aec0488dd325cd87f68db6a5705d9b1fcd312a 100644 (file)
@@ -277,7 +277,7 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = {
  * - Probe/remove operations
  * - OF device match table
  */
-static int __devinit psc_ac97_of_probe(struct platform_device *op)
+static int psc_ac97_of_probe(struct platform_device *op)
 {
        int rc;
        struct snd_ac97 ac97;
@@ -310,7 +310,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op)
        return 0;
 }
 
-static int __devexit psc_ac97_of_remove(struct platform_device *op)
+static int psc_ac97_of_remove(struct platform_device *op)
 {
        mpc5200_audio_dma_destroy(op);
        snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
@@ -318,7 +318,7 @@ static int __devexit psc_ac97_of_remove(struct platform_device *op)
 }
 
 /* Match table for of_platform binding */
-static struct of_device_id psc_ac97_match[] __devinitdata = {
+static struct of_device_id psc_ac97_match[] = {
        { .compatible = "fsl,mpc5200-psc-ac97", },
        { .compatible = "fsl,mpc5200b-psc-ac97", },
        {}
@@ -327,7 +327,7 @@ MODULE_DEVICE_TABLE(of, psc_ac97_match);
 
 static struct platform_driver psc_ac97_driver = {
        .probe = psc_ac97_of_probe,
-       .remove = __devexit_p(psc_ac97_of_remove),
+       .remove = psc_ac97_of_remove,
        .driver = {
                .name = "mpc5200-psc-ac97",
                .owner = THIS_MODULE,
index ba1f0a66358f30288c6de2bf4fcba4e7468dd952..b95b966f25a06acbc97c6693c05e2560072884f3 100644 (file)
@@ -153,7 +153,7 @@ static struct snd_soc_dai_driver psc_i2s_dai[] = {{
  * - Probe/remove operations
  * - OF device match table
  */
-static int __devinit psc_i2s_of_probe(struct platform_device *op)
+static int psc_i2s_of_probe(struct platform_device *op)
 {
        int rc;
        struct psc_dma *psc_dma;
@@ -205,7 +205,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op)
 
 }
 
-static int __devexit psc_i2s_of_remove(struct platform_device *op)
+static int psc_i2s_of_remove(struct platform_device *op)
 {
        mpc5200_audio_dma_destroy(op);
        snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
@@ -213,7 +213,7 @@ static int __devexit psc_i2s_of_remove(struct platform_device *op)
 }
 
 /* Match table for of_platform binding */
-static struct of_device_id psc_i2s_match[] __devinitdata = {
+static struct of_device_id psc_i2s_match[] = {
        { .compatible = "fsl,mpc5200-psc-i2s", },
        { .compatible = "fsl,mpc5200b-psc-i2s", },
        {}
@@ -222,7 +222,7 @@ MODULE_DEVICE_TABLE(of, psc_i2s_match);
 
 static struct platform_driver psc_i2s_driver = {
        .probe = psc_i2s_of_probe,
-       .remove = __devexit_p(psc_i2s_of_remove),
+       .remove = psc_i2s_of_remove,
        .driver = {
                .name = "mpc5200-psc-i2s",
                .owner = THIS_MODULE,
index 9ff9318c52b9df42e7c8f61fb3aac2c3bba56983..228c52e71440dde17f0a41b4d0e34d9a260718d5 100644 (file)
@@ -368,7 +368,7 @@ error_alloc:
  *
  * This function is called when the platform device is removed.
  */
-static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
+static int mpc8610_hpcd_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct mpc8610_hpcd_data *machine_data =
@@ -382,7 +382,7 @@ static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
 
 static struct platform_driver mpc8610_hpcd_driver = {
        .probe = mpc8610_hpcd_probe,
-       .remove = __devexit_p(mpc8610_hpcd_remove),
+       .remove = mpc8610_hpcd_remove,
        .driver = {
                /* The name must match 'compatible' property in the device tree,
                 * in lowercase letters.
index 2b76877b1789479b0e7bfd1bd2a69640e298c77f..3d1074179057936faa402e90de0f8752822f60f4 100644 (file)
@@ -180,7 +180,7 @@ static struct snd_soc_card mx27vis_aic32x4 = {
        .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
 };
 
-static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
+static int mx27vis_aic32x4_probe(struct platform_device *pdev)
 {
        struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data;
        int ret;
@@ -219,7 +219,7 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
+static int mx27vis_aic32x4_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&mx27vis_aic32x4);
 
@@ -232,7 +232,7 @@ static struct platform_driver mx27vis_aic32x4_audio_driver = {
                .owner = THIS_MODULE,
        },
        .probe = mx27vis_aic32x4_probe,
-       .remove = __devexit_p(mx27vis_aic32x4_remove),
+       .remove = mx27vis_aic32x4_remove,
 };
 
 module_platform_driver(mx27vis_aic32x4_audio_driver);
index 144d496036370e84d888d71d33703e39370eff41..ba59c23a137b3e4e19b1f03047b93fcd5f376301 100644 (file)
@@ -376,7 +376,7 @@ error_put:
  *
  * This function is called when the platform device is removed.
  */
-static int __devexit p1022_ds_remove(struct platform_device *pdev)
+static int p1022_ds_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct machine_data *mdata =
@@ -390,7 +390,7 @@ static int __devexit p1022_ds_remove(struct platform_device *pdev)
 
 static struct platform_driver p1022_ds_driver = {
        .probe = p1022_ds_probe,
-       .remove = __devexit_p(p1022_ds_remove),
+       .remove = p1022_ds_remove,
        .driver = {
                /*
                 * The name must match 'compatible' property in the device tree,
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
new file mode 100644 (file)
index 0000000..f215519
--- /dev/null
@@ -0,0 +1,392 @@
+/**
+ * Freescale P1022RDK ALSA SoC Machine driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * Note: in order for audio to work correctly, the output controls need
+ * to be enabled, because they control the clock.  So for playback, for
+ * example:
+ *
+ *      amixer sset 'Left Output Mixer PCM' on
+ *      amixer sset 'Right Output Mixer PCM' on
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <asm/fsl_guts.h>
+
+#include "fsl_dma.h"
+#include "fsl_ssi.h"
+#include "fsl_utils.h"
+
+/* P1022-specific PMUXCR and DMUXCR bit definitions */
+
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK       0x0001c000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI  0x00010000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI                0x00018000
+
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK      0x00000c00
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI       0x00000000
+
+#define CCSR_GUTS_DMUXCR_PAD   1       /* DMA controller/channel set to pad */
+#define CCSR_GUTS_DMUXCR_SSI   2       /* DMA controller/channel set to SSI */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
+ */
+static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
+       unsigned int co, unsigned int ch, unsigned int device)
+{
+       unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+       clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
+}
+
+/* There's only one global utilities register */
+static phys_addr_t guts_phys;
+
+/**
+ * machine_data: machine-specific ASoC device data
+ *
+ * This structure contains data for a single sound platform device on an
+ * P1022 RDK.  Some of the data is taken from the device tree.
+ */
+struct machine_data {
+       struct snd_soc_dai_link dai[2];
+       struct snd_soc_card card;
+       unsigned int dai_format;
+       unsigned int codec_clk_direction;
+       unsigned int cpu_clk_direction;
+       unsigned int clk_frequency;
+       unsigned int dma_id[2];         /* 0 = DMA1, 1 = DMA2, etc */
+       unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
+       char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
+};
+
+/**
+ * p1022_rdk_machine_probe: initialize the board
+ *
+ * This function is used to initialize the board-specific hardware.
+ *
+ * Here we program the DMACR and PMUXCR registers.
+ */
+static int p1022_rdk_machine_probe(struct snd_soc_card *card)
+{
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Enable SSI Tx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
+                       CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
+
+       /* Enable SSI Rx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
+                       CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
+
+       /* Enable DMA Channel for SSI */
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_startup: program the board with various hardware parameters
+ *
+ * This function takes board-specific information, like clock frequencies
+ * and serial data formats, and passes that information to the codec and
+ * transport drivers.
+ */
+static int p1022_rdk_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct machine_data *mdata =
+               container_of(rtd->card, struct machine_data, card);
+       struct device *dev = rtd->card->dev;
+       int ret = 0;
+
+       /* Tell the codec driver what the serial protocol is. */
+       ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec driver audio format (ret=%i)\n",
+                       ret);
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, mdata->clk_frequency,
+               mdata->clk_frequency);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec PLL frequency (ret=%i)\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_machine_remove: Remove the sound device
+ *
+ * This function is called to remove the sound device for one SSI.  We
+ * de-program the DMACR and PMUXCR register.
+ */
+static int p1022_rdk_machine_remove(struct snd_soc_card *card)
+{
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Restore the signal routing */
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_ops: ASoC machine driver operations
+ */
+static struct snd_soc_ops p1022_rdk_ops = {
+       .startup = p1022_rdk_startup,
+};
+
+/**
+ * p1022_rdk_probe: platform probe function for the machine driver
+ *
+ * Although this is a machine driver, the SSI node is the "master" node with
+ * respect to audio hardware connections.  Therefore, we create a new ASoC
+ * device for each new SSI node that has a codec attached.
+ */
+static int p1022_rdk_probe(struct platform_device *pdev)
+{
+       struct device *dev = pdev->dev.parent;
+       /* ssi_pdev is the platform device for the SSI node that probed us */
+       struct platform_device *ssi_pdev =
+               container_of(dev, struct platform_device, dev);
+       struct device_node *np = ssi_pdev->dev.of_node;
+       struct device_node *codec_np = NULL;
+       struct machine_data *mdata;
+       const u32 *iprop;
+       int ret;
+
+       /* Find the codec node for this SSI. */
+       codec_np = of_parse_phandle(np, "codec-handle", 0);
+       if (!codec_np) {
+               dev_err(dev, "could not find codec node\n");
+               return -EINVAL;
+       }
+
+       mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
+       if (!mdata) {
+               ret = -ENOMEM;
+               goto error_put;
+       }
+
+       mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
+       mdata->dai[0].ops = &p1022_rdk_ops;
+
+       /* ASoC core can match codec with device node */
+       mdata->dai[0].codec_of_node = codec_np;
+
+       /*
+        * We register two DAIs per SSI, one for playback and the other for
+        * capture.  We support codecs that have separate DAIs for both playback
+        * and capture.
+        */
+       memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
+
+       /* The DAI names from the codec (snd_soc_dai_driver.name) */
+       mdata->dai[0].codec_dai_name = "wm8960-hifi";
+       mdata->dai[1].codec_dai_name = mdata->dai[0].codec_dai_name;
+
+       /*
+        * Configure the SSI for I2S slave mode.  Older device trees have
+        * an fsl,mode property, but we ignore that since there's really
+        * only one way to configure the SSI.
+        */
+       mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
+       mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+       mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+
+       /*
+        * In i2s-slave mode, the codec has its own clock source, so we
+        * need to get the frequency from the device tree and pass it to
+        * the codec driver.
+        */
+       iprop = of_get_property(codec_np, "clock-frequency", NULL);
+       if (!iprop || !*iprop) {
+               dev_err(&pdev->dev, "codec bus-frequency property is missing or invalid\n");
+               ret = -EINVAL;
+               goto error;
+       }
+       mdata->clk_frequency = be32_to_cpup(iprop);
+
+       if (!mdata->clk_frequency) {
+               dev_err(&pdev->dev, "unknown clock frequency\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* Find the playback DMA channel to use. */
+       mdata->dai[0].platform_name = mdata->platform_name[0];
+       ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
+                                      &mdata->dma_channel_id[0],
+                                      &mdata->dma_id[0]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid playback DMA phandle (ret=%i)\n",
+                       ret);
+               goto error;
+       }
+
+       /* Find the capture DMA channel to use. */
+       mdata->dai[1].platform_name = mdata->platform_name[1];
+       ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
+                                      &mdata->dma_channel_id[1],
+                                      &mdata->dma_id[1]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid capture DMA phandle (ret=%i)\n",
+                       ret);
+               goto error;
+       }
+
+       /* Initialize our DAI data structure.  */
+       mdata->dai[0].stream_name = "playback";
+       mdata->dai[1].stream_name = "capture";
+       mdata->dai[0].name = mdata->dai[0].stream_name;
+       mdata->dai[1].name = mdata->dai[1].stream_name;
+
+       mdata->card.probe = p1022_rdk_machine_probe;
+       mdata->card.remove = p1022_rdk_machine_remove;
+       mdata->card.name = pdev->name; /* The platform driver name */
+       mdata->card.owner = THIS_MODULE;
+       mdata->card.dev = &pdev->dev;
+       mdata->card.num_links = 2;
+       mdata->card.dai_link = mdata->dai;
+
+       /* Register with ASoC */
+       ret = snd_soc_register_card(&mdata->card);
+       if (ret) {
+               dev_err(&pdev->dev, "could not register card (ret=%i)\n", ret);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       kfree(mdata);
+error_put:
+       of_node_put(codec_np);
+       return ret;
+}
+
+/**
+ * p1022_rdk_remove: remove the platform device
+ *
+ * This function is called when the platform device is removed.
+ */
+static int p1022_rdk_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+
+       snd_soc_unregister_card(card);
+       kfree(mdata);
+
+       return 0;
+}
+
+static struct platform_driver p1022_rdk_driver = {
+       .probe = p1022_rdk_probe,
+       .remove = p1022_rdk_remove,
+       .driver = {
+               /*
+                * The name must match 'compatible' property in the device tree,
+                * in lowercase letters.
+                */
+               .name = "snd-soc-p1022rdk",
+               .owner = THIS_MODULE,
+       },
+};
+
+/**
+ * p1022_rdk_init: machine driver initialization.
+ *
+ * This function is called when this module is loaded.
+ */
+static int __init p1022_rdk_init(void)
+{
+       struct device_node *guts_np;
+       struct resource res;
+
+       /* Get the physical address of the global utilities registers */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+       if (of_address_to_resource(guts_np, 0, &res)) {
+               pr_err("snd-soc-p1022rdk: missing/invalid global utils node\n");
+               of_node_put(guts_np);
+               return -EINVAL;
+       }
+       guts_phys = res.start;
+       of_node_put(guts_np);
+
+       return platform_driver_register(&p1022_rdk_driver);
+}
+
+/**
+ * p1022_rdk_exit: machine driver exit
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit p1022_rdk_exit(void)
+{
+       platform_driver_unregister(&p1022_rdk_driver);
+}
+
+late_initcall(p1022_rdk_init);
+module_exit(p1022_rdk_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale / iVeia P1022 RDK ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
index 4b63ec8eb372ee917a06c314764a2d7f6804a892..8e52c1485df37bfdbe21cbbbc49e801663f4126c 100644 (file)
@@ -29,14 +29,14 @@ struct pcm030_audio_data {
 
 static struct snd_soc_dai_link pcm030_fabric_dai[] = {
 {
-       .name = "AC97",
+       .name = "AC97.0",
        .stream_name = "AC97 Analog",
        .codec_dai_name = "wm9712-hifi",
        .cpu_dai_name = "mpc5200-psc-ac97.0",
        .codec_name = "wm9712-codec",
 },
 {
-       .name = "AC97",
+       .name = "AC97.1",
        .stream_name = "AC97 IEC958",
        .codec_dai_name = "wm9712-aux",
        .cpu_dai_name = "mpc5200-psc-ac97.1",
@@ -101,7 +101,7 @@ static int __init pcm030_fabric_probe(struct platform_device *op)
        return ret;
 }
 
-static int __devexit pcm030_fabric_remove(struct platform_device *op)
+static int pcm030_fabric_remove(struct platform_device *op)
 {
        struct pcm030_audio_data *pdata = platform_get_drvdata(op);
        int ret;
@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(of, pcm030_audio_match);
 
 static struct platform_driver pcm030_fabric_driver = {
        .probe          = pcm030_fabric_probe,
-       .remove         = __devexit_p(pcm030_fabric_remove),
+       .remove         = pcm030_fabric_remove,
        .driver         = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 41349670adab8ab18c00ef9bc696b2826e4fcf87..6cef491f4823cc28467216c8fe207b4eb7df271d 100644 (file)
@@ -425,7 +425,7 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
        .resume = jz4740_i2s_resume,
 };
 
-static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
+static int jz4740_i2s_dev_probe(struct platform_device *pdev)
 {
        struct jz4740_i2s *i2s;
        int ret;
@@ -492,7 +492,7 @@ err_free:
        return ret;
 }
 
-static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
+static int jz4740_i2s_dev_remove(struct platform_device *pdev)
 {
        struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
 
@@ -512,7 +512,7 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver jz4740_i2s_driver = {
        .probe = jz4740_i2s_dev_probe,
-       .remove = __devexit_p(jz4740_i2s_dev_remove),
+       .remove = jz4740_i2s_dev_remove,
        .driver = {
                .name = "jz4740-i2s",
                .owner = THIS_MODULE,
index 9b8cf256847d1ef8ace03ee8b0a94a1735a03eae..710059292318878886d00383396413c3ec87c8d1 100644 (file)
@@ -335,12 +335,12 @@ static struct snd_soc_platform_driver jz4740_soc_platform = {
                .pcm_free       = jz4740_pcm_free,
 };
 
-static int __devinit jz4740_pcm_probe(struct platform_device *pdev)
+static int jz4740_pcm_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
 }
 
-static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
+static int jz4740_pcm_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -348,7 +348,7 @@ static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
 
 static struct platform_driver jz4740_pcm_driver = {
        .probe = jz4740_pcm_probe,
-       .remove = __devexit_p(jz4740_pcm_remove),
+       .remove = jz4740_pcm_remove,
        .driver = {
                .name = "jz4740-pcm-audio",
                .owner = THIS_MODULE,
index e8aaff18d7cc4c9b18ed2d178cc69c2ddc77a6cb..55fd6b5df55f5d988799b93ec64995fb4c06a038 100644 (file)
@@ -96,7 +96,7 @@ static const struct gpio qi_lb60_gpios[] = {
        { QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
 };
 
-static int __devinit qi_lb60_probe(struct platform_device *pdev)
+static int qi_lb60_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &qi_lb60;
        int ret;
@@ -116,7 +116,7 @@ static int __devinit qi_lb60_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit qi_lb60_remove(struct platform_device *pdev)
+static int qi_lb60_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -131,7 +131,7 @@ static struct platform_driver qi_lb60_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = qi_lb60_probe,
-       .remove         = __devexit_p(qi_lb60_remove),
+       .remove         = qi_lb60_remove,
 };
 
 module_platform_driver(qi_lb60_driver);
index 2ba08148655f32ee2fa7301c44d65b54e7ea02fb..d3d4bdca1cc62d0387ca558cb7b7b020209b6f63 100644 (file)
 #include "kirkwood.h"
 
 #define KIRKWOOD_RATES \
-       (SNDRV_PCM_RATE_44100 | \
-        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
+       (SNDRV_PCM_RATE_8000_192000 |           \
+        SNDRV_PCM_RATE_CONTINUOUS |            \
+        SNDRV_PCM_RATE_KNOT)
+
 #define KIRKWOOD_FORMATS \
        (SNDRV_PCM_FMTBIT_S16_LE | \
         SNDRV_PCM_FMTBIT_S24_LE | \
-        SNDRV_PCM_FMTBIT_S32_LE)
+        SNDRV_PCM_FMTBIT_S32_LE | \
+        SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
+        SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
 
 struct kirkwood_dma_priv {
        struct snd_pcm_substream *play_stream;
@@ -43,10 +47,10 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
                 SNDRV_PCM_INFO_PAUSE),
        .formats                = KIRKWOOD_FORMATS,
        .rates                  = KIRKWOOD_RATES,
-       .rate_min               = 44100,
-       .rate_max               = 96000,
+       .rate_min               = 8000,
+       .rate_max               = 384000,
        .channels_min           = 1,
-       .channels_max           = 2,
+       .channels_max           = 8,
        .buffer_bytes_max       = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS,
        .period_bytes_min       = KIRKWOOD_SND_MIN_PERIOD_BYTES,
        .period_bytes_max       = KIRKWOOD_SND_MAX_PERIOD_BYTES,
@@ -368,12 +372,12 @@ static struct snd_soc_platform_driver kirkwood_soc_platform = {
        .pcm_free       = kirkwood_dma_free_dma_buffers,
 };
 
-static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev)
+static int kirkwood_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
 }
 
-static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev)
+static int kirkwood_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -386,7 +390,7 @@ static struct platform_driver kirkwood_pcm_driver = {
        },
 
        .probe = kirkwood_soc_platform_probe,
-       .remove = __devexit_p(kirkwood_soc_platform_remove),
+       .remove = kirkwood_soc_platform_remove,
 };
 
 module_platform_driver(kirkwood_pcm_driver);
index 1d5db484d2df331b15e8e385cd32e2acd79e4d79..282d8b1163ba9583afd6e38e38400ce7efea29e9 100644 (file)
@@ -99,6 +99,29 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
        } while (value == 0);
 }
 
+static void kirkwood_set_rate(struct snd_soc_dai *dai,
+       struct kirkwood_dma_data *priv, unsigned long rate)
+{
+       uint32_t clks_ctrl;
+
+       if (rate == 44100 || rate == 48000 || rate == 96000) {
+               /* use internal dco for supported rates */
+               dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
+                       __func__, rate);
+               kirkwood_set_dco(priv->io, rate);
+
+               clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
+       } else if (!IS_ERR(priv->extclk)) {
+               /* use optional external clk for other rates */
+               dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
+                       __func__, rate, 256 * rate);
+               clk_set_rate(priv->extclk, 256 * rate);
+
+               clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
+       }
+       writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
+}
+
 static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -113,26 +136,21 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *dai)
 {
        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
-       unsigned int i2s_reg, reg;
-       unsigned long i2s_value, value;
+       uint32_t ctl_play, ctl_rec;
+       unsigned int i2s_reg;
+       unsigned long i2s_value;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                i2s_reg = KIRKWOOD_I2S_PLAYCTL;
-               reg = KIRKWOOD_PLAYCTL;
        } else {
                i2s_reg = KIRKWOOD_I2S_RECCTL;
-               reg = KIRKWOOD_RECCTL;
        }
 
-       /* set dco conf */
-       kirkwood_set_dco(priv->io, params_rate(params));
+       kirkwood_set_rate(dai, priv, params_rate(params));
 
        i2s_value = readl(priv->io+i2s_reg);
        i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
 
-       value = readl(priv->io+reg);
-       value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK;
-
        /*
         * Size settings in play/rec i2s control regs and play/rec control
         * regs must be the same.
@@ -140,38 +158,57 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
-               value |= KIRKWOOD_PLAYCTL_SIZE_16_C;
+               ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
+                          KIRKWOOD_PLAYCTL_I2S_EN;
+               ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
+                         KIRKWOOD_RECCTL_I2S_EN;
                break;
        /*
         * doesn't work... S20_3LE != kirkwood 20bit format ?
         *
        case SNDRV_PCM_FORMAT_S20_3LE:
                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
-               value |= KIRKWOOD_PLAYCTL_SIZE_20;
+               ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
+                          KIRKWOOD_PLAYCTL_I2S_EN;
+               ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
+                         KIRKWOOD_RECCTL_I2S_EN;
                break;
        */
        case SNDRV_PCM_FORMAT_S24_LE:
                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
-               value |= KIRKWOOD_PLAYCTL_SIZE_24;
+               ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
+                          KIRKWOOD_PLAYCTL_I2S_EN;
+               ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
+                         KIRKWOOD_RECCTL_I2S_EN;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
-               value |= KIRKWOOD_PLAYCTL_SIZE_32;
+               ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
+                          KIRKWOOD_PLAYCTL_I2S_EN;
+               ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
+                         KIRKWOOD_RECCTL_I2S_EN;
                break;
        default:
                return -EINVAL;
        }
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               value &= ~KIRKWOOD_PLAYCTL_MONO_MASK;
                if (params_channels(params) == 1)
-                       value |= KIRKWOOD_PLAYCTL_MONO_BOTH;
+                       ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
                else
-                       value |= KIRKWOOD_PLAYCTL_MONO_OFF;
+                       ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
+
+               priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
+                                   KIRKWOOD_PLAYCTL_I2S_EN |
+                                   KIRKWOOD_PLAYCTL_SPDIF_EN |
+                                   KIRKWOOD_PLAYCTL_SIZE_MASK);
+               priv->ctl_play |= ctl_play;
+       } else {
+               priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK;
+               priv->ctl_rec |= ctl_rec;
        }
 
        writel(i2s_value, priv->io+i2s_reg);
-       writel(value, priv->io+reg);
 
        return 0;
 }
@@ -205,20 +242,18 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
+               /* configure */
+               ctl = priv->ctl_play;
+               value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN |
+                               KIRKWOOD_PLAYCTL_SPDIF_EN);
+               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+
+               /* enable interrupts */
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
-               /* configure audio & enable i2s playback */
-               ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
-               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
-                               | KIRKWOOD_PLAYCTL_SPDIF_EN);
-
-               if (priv->burst == 32)
-                       ctl |= KIRKWOOD_PLAYCTL_BURST_32;
-               else
-                       ctl |= KIRKWOOD_PLAYCTL_BURST_128;
-               ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+               /* enable playback */
                writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
@@ -259,30 +294,24 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
-       unsigned long value;
+       uint32_t ctl, value;
 
        value = readl(priv->io + KIRKWOOD_RECCTL);
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
+               /* configure */
+               ctl = priv->ctl_rec;
+               value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
+               writel(value, priv->io + KIRKWOOD_RECCTL);
+
+               /* enable interrupts */
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
-               /* configure audio & enable i2s record */
-               value = readl(priv->io + KIRKWOOD_RECCTL);
-               value &= ~KIRKWOOD_RECCTL_BURST_MASK;
-               value &= ~KIRKWOOD_RECCTL_MONO;
-               value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE
-                       | KIRKWOOD_RECCTL_SPDIF_EN);
-
-               if (priv->burst == 32)
-                       value |= KIRKWOOD_RECCTL_BURST_32;
-               else
-                       value |= KIRKWOOD_RECCTL_BURST_128;
-               value |= KIRKWOOD_RECCTL_I2S_EN;
-
-               writel(value, priv->io + KIRKWOOD_RECCTL);
+               /* enable record */
+               writel(ctl, priv->io + KIRKWOOD_RECCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
@@ -389,112 +418,146 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = KIRKWOOD_I2S_RATES,
-               .formats = KIRKWOOD_I2S_FORMATS,},
+               .formats = KIRKWOOD_I2S_FORMATS,
+       },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = KIRKWOOD_I2S_RATES,
-               .formats = KIRKWOOD_I2S_FORMATS,},
+               .formats = KIRKWOOD_I2S_FORMATS,
+       },
        .ops = &kirkwood_i2s_dai_ops,
 };
 
-static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
+static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
+       .probe = kirkwood_i2s_probe,
+       .remove = kirkwood_i2s_remove,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_192000 |
+                        SNDRV_PCM_RATE_CONTINUOUS |
+                        SNDRV_PCM_RATE_KNOT,
+               .formats = KIRKWOOD_I2S_FORMATS,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_192000 |
+                        SNDRV_PCM_RATE_CONTINUOUS |
+                        SNDRV_PCM_RATE_KNOT,
+               .formats = KIRKWOOD_I2S_FORMATS,
+       },
+       .ops = &kirkwood_i2s_dai_ops,
+};
+
+static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 {
-       struct resource *mem;
-       struct kirkwood_asoc_platform_data *data =
-               pdev->dev.platform_data;
+       struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
+       struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
        struct kirkwood_dma_data *priv;
+       struct resource *mem;
        int err;
 
-       priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL);
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                dev_err(&pdev->dev, "allocation failed\n");
-               err = -ENOMEM;
-               goto error;
+               return -ENOMEM;
        }
        dev_set_drvdata(&pdev->dev, priv);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
                dev_err(&pdev->dev, "platform_get_resource failed\n");
-               err = -ENXIO;
-               goto err_alloc;
-       }
-
-       priv->mem = request_mem_region(mem->start, SZ_16K, DRV_NAME);
-       if (!priv->mem) {
-               dev_err(&pdev->dev, "request_mem_region failed\n");
-               err = -EBUSY;
-               goto err_alloc;
+               return -ENXIO;
        }
 
-       priv->io = ioremap(priv->mem->start, SZ_16K);
+       priv->io = devm_request_and_ioremap(&pdev->dev, mem);
        if (!priv->io) {
-               dev_err(&pdev->dev, "ioremap failed\n");
-               err = -ENOMEM;
-               goto err_iomem;
+               dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
+               return -ENOMEM;
        }
 
        priv->irq = platform_get_irq(pdev, 0);
        if (priv->irq <= 0) {
                dev_err(&pdev->dev, "platform_get_irq failed\n");
-               err = -ENXIO;
-               goto err_ioremap;
+               return -ENXIO;
        }
 
        if (!data) {
                dev_err(&pdev->dev, "no platform data ?!\n");
-               err = -EINVAL;
-               goto err_ioremap;
+               return -EINVAL;
        }
 
        priv->burst = data->burst;
 
-       priv->clk = clk_get(&pdev->dev, NULL);
+       priv->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(priv->clk)) {
                dev_err(&pdev->dev, "no clock\n");
-               err = PTR_ERR(priv->clk);
-               goto err_ioremap;
+               return PTR_ERR(priv->clk);
+       }
+
+       err = clk_prepare_enable(priv->clk);
+       if (err < 0)
+               return err;
+
+       priv->extclk = clk_get(&pdev->dev, "extclk");
+       if (!IS_ERR(priv->extclk)) {
+               if (priv->extclk == priv->clk) {
+                       clk_put(priv->extclk);
+                       priv->extclk = ERR_PTR(-EINVAL);
+               } else {
+                       dev_info(&pdev->dev, "found external clock\n");
+                       clk_prepare_enable(priv->extclk);
+                       soc_dai = &kirkwood_i2s_dai_extclk;
+               }
+       }
+
+       /* Some sensible defaults - this reflects the powerup values */
+       priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
+       priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
+
+       /* Select the burst size */
+       if (data->burst == 32) {
+               priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
+               priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
+       } else {
+               priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
+               priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
        }
-       clk_prepare_enable(priv->clk);
 
-       err = snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
+       err = snd_soc_register_dai(&pdev->dev, soc_dai);
        if (!err)
                return 0;
        dev_err(&pdev->dev, "snd_soc_register_dai failed\n");
 
+       if (!IS_ERR(priv->extclk)) {
+               clk_disable_unprepare(priv->extclk);
+               clk_put(priv->extclk);
+       }
        clk_disable_unprepare(priv->clk);
-       clk_put(priv->clk);
-
-err_ioremap:
-       iounmap(priv->io);
-err_iomem:
-       release_mem_region(priv->mem->start, SZ_16K);
-err_alloc:
-       kfree(priv);
-error:
+
        return err;
 }
 
-static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
+static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 {
        struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
 
        snd_soc_unregister_dai(&pdev->dev);
 
+       if (!IS_ERR(priv->extclk)) {
+               clk_disable_unprepare(priv->extclk);
+               clk_put(priv->extclk);
+       }
        clk_disable_unprepare(priv->clk);
-       clk_put(priv->clk);
-
-       iounmap(priv->io);
-       release_mem_region(priv->mem->start, SZ_16K);
-       kfree(priv);
 
        return 0;
 }
 
 static struct platform_driver kirkwood_i2s_driver = {
        .probe  = kirkwood_i2s_dev_probe,
-       .remove = __devexit_p(kirkwood_i2s_dev_remove),
+       .remove = kirkwood_i2s_dev_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index c28540aeea257d78091d0ea5739feeefed941ba7..b979c7154715a0ee9407c908f76f9f1ca9f91748 100644 (file)
@@ -71,7 +71,7 @@ static struct snd_soc_card openrd_client = {
        .num_links = ARRAY_SIZE(openrd_client_dai),
 };
 
-static int __devinit openrd_probe(struct platform_device *pdev)
+static int openrd_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &openrd_client;
        int ret;
@@ -85,7 +85,7 @@ static int __devinit openrd_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit openrd_remove(struct platform_device *pdev)
+static int openrd_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -99,7 +99,7 @@ static struct platform_driver openrd_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = openrd_probe,
-       .remove         = __devexit_p(openrd_remove),
+       .remove         = openrd_remove,
 };
 
 module_platform_driver(openrd_driver);
index c67bbc57498716534ba751765b46e60e9d08bf4d..1d0ed6f8add7ba5a7236f428476ab6f981522ab6 100644 (file)
@@ -92,7 +92,7 @@ static struct snd_soc_card t5325 = {
        .num_dapm_routes = ARRAY_SIZE(t5325_route),
 };
 
-static int __devinit t5325_probe(struct platform_device *pdev)
+static int t5325_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &t5325;
        int ret;
@@ -106,7 +106,7 @@ static int __devinit t5325_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit t5325_remove(struct platform_device *pdev)
+static int t5325_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -120,7 +120,7 @@ static struct platform_driver t5325_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = t5325_probe,
-       .remove         = __devexit_p(t5325_remove),
+       .remove         = t5325_remove,
 };
 
 module_platform_driver(t5325_driver);
index f9084d83e6bd2ae178d562c2c243de4bb1fb6fcf..4d92637ddb3fd878f86e4d4525fbd024d94b2618 100644 (file)
 #define KIRKWOOD_DCO_SPCR_STATUS               0x120c
 #define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK      (1<<16)
 
+#define KIRKWOOD_CLOCKS_CTRL                   0x1230
+#define KIRKWOOD_MCLK_SOURCE_MASK              (3<<0)
+#define KIRKWOOD_MCLK_SOURCE_DCO               (0<<0)
+#define KIRKWOOD_MCLK_SOURCE_EXTCLK            (3<<0)
+
 #define KIRKWOOD_ERR_CAUSE                     0x1300
 #define KIRKWOOD_ERR_MASK                      0x1304
 
 #define KIRKWOOD_SND_MAX_PERIOD_BYTES          0x4000
 
 struct kirkwood_dma_data {
-       struct resource *mem;
        void __iomem *io;
+       struct clk *clk;
+       struct clk *extclk;
+       uint32_t ctl_play;
+       uint32_t ctl_rec;
        int irq;
        int burst;
-       struct clk *clk;
 };
 
 #endif
index 2cc7782714b53830716fe74cea0c94c3527bc705..4139116c33b51f85bbc1794a885488f14811ec7e 100644 (file)
@@ -358,7 +358,7 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
+static int snd_mfld_mc_probe(struct platform_device *pdev)
 {
        int ret_val = 0, irq;
        struct mfld_mc_private *mc_drv_ctx;
@@ -417,7 +417,7 @@ unalloc:
        return ret_val;
 }
 
-static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
+static int snd_mfld_mc_remove(struct platform_device *pdev)
 {
        struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
 
@@ -435,7 +435,7 @@ static struct platform_driver snd_mfld_mc_driver = {
                .name = "msic_audio",
        },
        .probe = snd_mfld_mc_probe,
-       .remove = __devexit_p(snd_mfld_mc_remove),
+       .remove = snd_mfld_mc_remove,
 };
 
 module_platform_driver(snd_mfld_mc_driver);
index f82d766cbf9eb7ecd5ddd7cea788781d07b7af86..564b5b60319d7af26de86810515f7e9a276e93c0 100644 (file)
@@ -220,13 +220,13 @@ static struct snd_soc_platform_driver mxs_soc_platform = {
        .pcm_free       = mxs_pcm_free,
 };
 
-int __devinit mxs_pcm_platform_register(struct device *dev)
+int mxs_pcm_platform_register(struct device *dev)
 {
        return snd_soc_register_platform(dev, &mxs_soc_platform);
 }
 EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
 
-void __devexit mxs_pcm_platform_unregister(struct device *dev)
+void mxs_pcm_platform_unregister(struct device *dev)
 {
        snd_soc_unregister_platform(dev);
 }
index c294fbb523fce2dac76a70d9e5537a47fee40042..365d9d27a3216b2c8969451c83b0e49e0bbc9520 100644 (file)
@@ -229,6 +229,7 @@ int mxs_saif_put_mclk(unsigned int saif_id)
        saif->mclk_in_use = 0;
        return 0;
 }
+EXPORT_SYMBOL_GPL(mxs_saif_put_mclk);
 
 /*
  * Get MCLK and set clock rate, then enable it
@@ -282,6 +283,7 @@ int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(mxs_saif_get_mclk);
 
 /*
  * SAIF DAI format configuration.
@@ -655,7 +657,7 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mxs_saif_probe(struct platform_device *pdev)
+static int mxs_saif_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct resource *iores, *dmares;
@@ -790,7 +792,7 @@ failed_pdev_alloc:
        return ret;
 }
 
-static int __devexit mxs_saif_remove(struct platform_device *pdev)
+static int mxs_saif_remove(struct platform_device *pdev)
 {
        mxs_pcm_platform_unregister(&pdev->dev);
        snd_soc_unregister_dai(&pdev->dev);
@@ -806,7 +808,7 @@ MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
 
 static struct platform_driver mxs_saif_driver = {
        .probe = mxs_saif_probe,
-       .remove = __devexit_p(mxs_saif_remove),
+       .remove = mxs_saif_remove,
 
        .driver = {
                .name = "mxs-saif",
index 215113b05f7d07c6ec46ecb591ec69bd04c5c610..b1d9b5ebeeeb77d5028a1bd183b4828e7737d78d 100644 (file)
@@ -112,7 +112,7 @@ static struct snd_soc_card mxs_sgtl5000 = {
        .num_links      = ARRAY_SIZE(mxs_sgtl5000_dai),
 };
 
-static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct device_node *saif_np[2], *codec_np;
@@ -145,7 +145,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
        return ret;
 }
 
-static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
+static int mxs_sgtl5000_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &mxs_sgtl5000;
        int ret;
@@ -176,7 +176,7 @@ static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev)
+static int mxs_sgtl5000_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -200,7 +200,7 @@ static struct platform_driver mxs_sgtl5000_audio_driver = {
                .of_match_table = mxs_sgtl5000_dt_ids,
        },
        .probe = mxs_sgtl5000_probe,
-       .remove = __devexit_p(mxs_sgtl5000_remove),
+       .remove = mxs_sgtl5000_remove,
 };
 
 module_platform_driver(mxs_sgtl5000_audio_driver);
index 946020a647db2e1d5eec71f82fb9a3c936ced546..0418467a48489716475a3ff33cf8928b69d302c0 100644 (file)
@@ -314,7 +314,7 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = {
        .ops = &nuc900_ac97_dai_ops,
 };
 
-static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
+static int nuc900_ac97_drvprobe(struct platform_device *pdev)
 {
        struct nuc900_audio *nuc900_audio;
        int ret;
@@ -382,7 +382,7 @@ out0:
        return ret;
 }
 
-static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
+static int nuc900_ac97_drvremove(struct platform_device *pdev)
 {
        snd_soc_unregister_dai(&pdev->dev);
 
@@ -403,7 +403,7 @@ static struct platform_driver nuc900_ac97_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = nuc900_ac97_drvprobe,
-       .remove         = __devexit_p(nuc900_ac97_drvremove),
+       .remove         = nuc900_ac97_drvremove,
 };
 
 module_platform_driver(nuc900_ac97_driver);
index 37585b47f4e3c4a5ea48ce7513ef08093de7e08d..c894ff0f25809c997197496e810cc52d0299d40a 100644 (file)
@@ -337,12 +337,12 @@ static struct snd_soc_platform_driver nuc900_soc_platform = {
        .pcm_free       = nuc900_dma_free_dma_buffers,
 };
 
-static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)
+static int nuc900_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform);
 }
 
-static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev)
+static int nuc900_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -355,7 +355,7 @@ static struct platform_driver nuc900_pcm_driver = {
        },
 
        .probe = nuc900_soc_platform_probe,
-       .remove = __devexit_p(nuc900_soc_platform_remove),
+       .remove = nuc900_soc_platform_remove,
 };
 
 module_platform_driver(nuc900_pcm_driver);
index d8e96b2cd03ec201306ceaebf3962531f48f0cac..2600447fa74f823542f2668e216071d2240dfdf3 100644 (file)
@@ -575,7 +575,7 @@ static struct snd_soc_card ams_delta_audio_card = {
 };
 
 /* Module init/exit */
-static __devinit int ams_delta_probe(struct platform_device *pdev)
+static int ams_delta_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &ams_delta_audio_card;
        int ret;
@@ -591,7 +591,7 @@ static __devinit int ams_delta_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ams_delta_remove(struct platform_device *pdev)
+static int ams_delta_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -616,7 +616,7 @@ static struct platform_driver ams_delta_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ams_delta_probe,
-       .remove = __devexit_p(ams_delta_remove),
+       .remove = ams_delta_remove,
 };
 
 module_platform_driver(ams_delta_driver);
index a9a243860428d5c49fce866e1c38f1b2dd82ea5a..285c8368cb47bcaf3461b4470f09fb9d7159c0fc 100644 (file)
@@ -930,8 +930,7 @@ static const struct attribute_group sidetone_attr_group = {
        .attrs = (struct attribute **)sidetone_attrs,
 };
 
-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
-                                struct resource *res)
+static int omap_st_add(struct omap_mcbsp *mcbsp, struct resource *res)
 {
        struct omap_mcbsp_st_data *st_data;
        int err;
@@ -957,7 +956,7 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
  * 730 has only 2 McBSP, and both of them are MPU peripherals.
  */
-int __devinit omap_mcbsp_init(struct platform_device *pdev)
+int omap_mcbsp_init(struct platform_device *pdev)
 {
        struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
        struct resource *res;
@@ -1085,7 +1084,7 @@ err_thres:
        return ret;
 }
 
-void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
 {
        if (mcbsp->pdata->buffer_size)
                sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
index a89791c239a5d0b654d121501a8353a6ac6ec4a8..f93e0b0af3035dbda43ccb0a87653fcf7131f7ac 100644 (file)
@@ -347,7 +347,7 @@ int omap_st_enable(struct omap_mcbsp *mcbsp);
 int omap_st_disable(struct omap_mcbsp *mcbsp);
 int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
 
-int __devinit omap_mcbsp_init(struct platform_device *pdev);
-void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_init(struct platform_device *pdev);
+void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
 
 #endif /* __ASOC_MCBSP_H */
index a57a4e68dcc6166a2161b49b1d21ab7a8e49dc87..e7d93fa412a9c3387eef239300b44de4cac19dcb 100644 (file)
@@ -273,7 +273,7 @@ static struct snd_soc_card omap_abe_card = {
        .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
-static __devinit int omap_abe_probe(struct platform_device *pdev)
+static int omap_abe_probe(struct platform_device *pdev)
 {
        struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *node = pdev->dev.of_node;
@@ -331,8 +331,8 @@ static __devinit int omap_abe_probe(struct platform_device *pdev)
                        num_links = 1;
                }
 
-               of_property_read_u32(node, "ti,jack-detection",
-                                    &priv->jack_detection);
+               priv->jack_detection = of_property_read_bool(node,
+                                                          "ti,jack-detection");
                of_property_read_u32(node, "ti,mclk-freq",
                                     &priv->mclk_freq);
                if (!priv->mclk_freq) {
@@ -390,7 +390,7 @@ err_unregister:
        return ret;
 }
 
-static int __devexit omap_abe_remove(struct platform_device *pdev)
+static int omap_abe_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
@@ -417,7 +417,7 @@ static struct platform_driver omap_abe_driver = {
                .of_match_table = omap_abe_of_match,
        },
        .probe = omap_abe_probe,
-       .remove = __devexit_p(omap_abe_remove),
+       .remove = omap_abe_remove,
 };
 
 module_platform_driver(omap_abe_driver);
index 5a6aeaf552a89666672e4bc2a46a3106ba26a532..ba49ccd9eed9149f234907c6efb66af5587328e6 100644 (file)
@@ -448,7 +448,7 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
        .ops = &omap_dmic_dai_ops,
 };
 
-static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+static int asoc_dmic_probe(struct platform_device *pdev)
 {
        struct omap_dmic *dmic;
        struct resource *res;
@@ -518,7 +518,7 @@ err_put_clk:
        return ret;
 }
 
-static int __devexit asoc_dmic_remove(struct platform_device *pdev)
+static int asoc_dmic_remove(struct platform_device *pdev)
 {
        struct omap_dmic *dmic = platform_get_drvdata(pdev);
 
@@ -541,7 +541,7 @@ static struct platform_driver asoc_dmic_driver = {
                .of_match_table = omap_dmic_of_match,
        },
        .probe = asoc_dmic_probe,
-       .remove = __devexit_p(asoc_dmic_remove),
+       .remove = asoc_dmic_remove,
 };
 
 module_platform_driver(asoc_dmic_driver);
index eaa2ea0e3f8115eb03bc864708f24a14f20b4d46..d4eaa92e518ec22af5c3751be13653dff5b268f9 100644 (file)
@@ -45,7 +45,7 @@ static struct snd_soc_card snd_soc_omap_hdmi = {
        .num_links = 1,
 };
 
-static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+static int omap_hdmi_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &snd_soc_omap_hdmi;
        int ret;
@@ -61,7 +61,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+static int omap_hdmi_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -76,7 +76,7 @@ static struct platform_driver omap_hdmi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = omap_hdmi_probe,
-       .remove = __devexit_p(omap_hdmi_remove),
+       .remove = omap_hdmi_remove,
 };
 
 module_platform_driver(omap_hdmi_driver);
index f59c69fb400ee60861bf334067aa1ee29df00d12..7ea24819d570ec912f60fc978497578bddeb753b 100644 (file)
@@ -262,7 +262,7 @@ static struct snd_soc_dai_driver omap_hdmi_dai = {
        .ops = &omap_hdmi_dai_ops,
 };
 
-static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+static int omap_hdmi_probe(struct platform_device *pdev)
 {
        int ret;
        struct resource *hdmi_rsrc;
@@ -324,7 +324,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+static int omap_hdmi_remove(struct platform_device *pdev)
 {
        struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
 
@@ -345,7 +345,7 @@ static struct platform_driver hdmi_dai_driver = {
                .owner = THIS_MODULE,
        },
        .probe = omap_hdmi_probe,
-       .remove = __devexit_p(omap_hdmi_remove),
+       .remove = omap_hdmi_remove,
 };
 
 module_platform_driver(hdmi_dai_driver);
index 09167609c93e99521d8bf47a37b692c77e13c128..8d2defd6fdbe04375344a6f9fb440ceac935c347 100644 (file)
@@ -757,7 +757,7 @@ static const struct of_device_id omap_mcbsp_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match);
 
-static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
+static int asoc_mcbsp_probe(struct platform_device *pdev)
 {
        struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct omap_mcbsp *mcbsp;
@@ -798,7 +798,7 @@ static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
+static int asoc_mcbsp_remove(struct platform_device *pdev)
 {
        struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
 
@@ -824,7 +824,7 @@ static struct platform_driver asoc_mcbsp_driver = {
        },
 
        .probe = asoc_mcbsp_probe,
-       .remove = __devexit_p(asoc_mcbsp_remove),
+       .remove = asoc_mcbsp_remove,
 };
 
 module_platform_driver(asoc_mcbsp_driver);
index 56965bb3275ccd5c2fea1dc3fe143e3e3e7b622d..2fe8be20945278dc04cf23e22ef112abbf746383 100644 (file)
@@ -429,7 +429,7 @@ void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
 
-static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
+static int asoc_mcpdm_probe(struct platform_device *pdev)
 {
        struct omap_mcpdm *mcpdm;
        struct resource *res;
@@ -487,7 +487,7 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
        return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
 }
 
-static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
+static int asoc_mcpdm_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dai(&pdev->dev);
        return 0;
@@ -507,7 +507,7 @@ static struct platform_driver asoc_mcpdm_driver = {
        },
 
        .probe  = asoc_mcpdm_probe,
-       .remove = __devexit_p(asoc_mcpdm_remove),
+       .remove = asoc_mcpdm_remove,
 };
 
 module_platform_driver(asoc_mcpdm_driver);
index 52977aa303554d54113530805e421f450db68e33..47bdbd415ad87af59686327ad3be8f25c48bf2a4 100644 (file)
@@ -302,13 +302,13 @@ static struct snd_soc_platform_driver omap_soc_platform = {
        .pcm_free       = omap_pcm_free_dma_buffers,
 };
 
-static __devinit int omap_pcm_probe(struct platform_device *pdev)
+static int omap_pcm_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev,
                        &omap_soc_platform);
 }
 
-static int __devexit omap_pcm_remove(struct platform_device *pdev)
+static int omap_pcm_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -321,7 +321,7 @@ static struct platform_driver omap_pcm_driver = {
        },
 
        .probe = omap_pcm_probe,
-       .remove = __devexit_p(omap_pcm_remove),
+       .remove = omap_pcm_remove,
 };
 
 module_platform_driver(omap_pcm_driver);
index 3b97b87971f5462c3ea972ac6f92f5c25fc48106..4541d28b531495d7484f3a2dfcf4fe8472af451f 100644 (file)
@@ -107,7 +107,7 @@ static struct snd_soc_card omap_twl4030_card = {
        .num_links = ARRAY_SIZE(omap_twl4030_dai_links),
 };
 
-static __devinit int omap_twl4030_probe(struct platform_device *pdev)
+static int omap_twl4030_probe(struct platform_device *pdev)
 {
        struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *node = pdev->dev.of_node;
@@ -154,7 +154,7 @@ static __devinit int omap_twl4030_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit omap_twl4030_remove(struct platform_device *pdev)
+static int omap_twl4030_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -177,7 +177,7 @@ static struct platform_driver omap_twl4030_driver = {
                .of_match_table = omap_twl4030_of_match,
        },
        .probe = omap_twl4030_probe,
-       .remove = __devexit_p(omap_twl4030_remove),
+       .remove = omap_twl4030_remove,
 };
 
 module_platform_driver(omap_twl4030_driver);
index 1ff6bb9ade5c98fd1ac644b0567f42f367d543d8..771bff27ac3e4809e3ae38d75c9d22b648375247 100644 (file)
@@ -37,8 +37,6 @@
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
 
-#define ZOOM2_HEADSET_MUX_GPIO         (OMAP_MAX_GPIO_LINES + 15)
-
 static int zoom2_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
@@ -187,9 +185,6 @@ static int __init zoom2_soc_init(void)
        if (ret)
                goto err1;
 
-       BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
-       gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
-
        return 0;
 
 err1:
@@ -202,8 +197,6 @@ module_init(zoom2_soc_init);
 
 static void __exit zoom2_soc_exit(void)
 {
-       gpio_free(ZOOM2_HEADSET_MUX_GPIO);
-
        platform_device_unregister(zoom2_snd_device);
 }
 module_exit(zoom2_soc_exit);
index 5e666e03d3331d39921a95bee2b5dc5e13c55230..4ad76099dd43fdec0d9e7262db77f1e07cd20713 100644 (file)
@@ -140,7 +140,7 @@ static struct snd_soc_card brownstone = {
        .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map),
 };
 
-static int __devinit brownstone_probe(struct platform_device *pdev)
+static int brownstone_probe(struct platform_device *pdev)
 {
        int ret;
 
@@ -152,7 +152,7 @@ static int __devinit brownstone_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit brownstone_remove(struct platform_device *pdev)
+static int brownstone_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&brownstone);
        return 0;
@@ -164,7 +164,7 @@ static struct platform_driver mmp_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = brownstone_probe,
-       .remove         = __devexit_p(brownstone_remove),
+       .remove         = brownstone_remove,
 };
 
 module_platform_driver(mmp_driver);
index 863367ad89ce6aa1b173914f8c2541903d4f9846..f4cce1e8011242364807ebe21dc15b74acb1e3c7 100644 (file)
@@ -303,7 +303,7 @@ static struct snd_soc_card corgi = {
        .num_dapm_routes = ARRAY_SIZE(corgi_audio_map),
 };
 
-static int __devinit corgi_probe(struct platform_device *pdev)
+static int corgi_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &corgi;
        int ret;
@@ -317,7 +317,7 @@ static int __devinit corgi_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit corgi_remove(struct platform_device *pdev)
+static int corgi_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -331,7 +331,7 @@ static struct platform_driver corgi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = corgi_probe,
-       .remove         = __devexit_p(corgi_remove),
+       .remove         = corgi_remove,
 };
 
 module_platform_driver(corgi_driver);
index 7b1bc2390039ab324b5146daf63c5a72ec21411e..70d799b13f0d3fed2464c61046eb3e7439ebd8e4 100644 (file)
@@ -144,7 +144,7 @@ static struct gpio e740_audio_gpios[] = {
        { GPIO_E740_WM9705_nAVDD2, GPIOF_OUT_INIT_HIGH, "Audio power" },
 };
 
-static int __devinit e740_probe(struct platform_device *pdev)
+static int e740_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &e740;
        int ret;
@@ -165,7 +165,7 @@ static int __devinit e740_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit e740_remove(struct platform_device *pdev)
+static int e740_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -180,7 +180,7 @@ static struct platform_driver e740_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = e740_probe,
-       .remove         = __devexit_p(e740_remove),
+       .remove         = e740_remove,
 };
 
 module_platform_driver(e740_driver);
index 47b89d71e287bc087640cdf064a7c4f6a92cdfea..f94d2ab51351b63932ff6e62d434cb08671dcc54 100644 (file)
@@ -126,7 +126,7 @@ static struct gpio e750_audio_gpios[] = {
        { GPIO_E750_SPK_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
 };
 
-static int __devinit e750_probe(struct platform_device *pdev)
+static int e750_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &e750;
        int ret;
@@ -147,7 +147,7 @@ static int __devinit e750_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit e750_remove(struct platform_device *pdev)
+static int e750_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -162,7 +162,7 @@ static struct platform_driver e750_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = e750_probe,
-       .remove         = __devexit_p(e750_remove),
+       .remove         = e750_remove,
 };
 
 module_platform_driver(e750_driver);
index ea9707ec6f28e706847e9991ee756747eac5309a..8768a640dd71953a0c78b43d0df539d0b5c6ad18 100644 (file)
@@ -116,7 +116,7 @@ static struct gpio e800_audio_gpios[] = {
        { GPIO_E800_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
 };
 
-static int __devinit e800_probe(struct platform_device *pdev)
+static int e800_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &e800;
        int ret;
@@ -137,7 +137,7 @@ static int __devinit e800_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit e800_remove(struct platform_device *pdev)
+static int e800_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -152,7 +152,7 @@ static struct platform_driver e800_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = e800_probe,
-       .remove         = __devexit_p(e800_remove),
+       .remove         = e800_remove,
 };
 
 module_platform_driver(e800_driver);
index 2a342c92d829563fbe3089bac84e486078ce8ef3..dcc9b04bd92c0575295e45455a59bf34dd419938 100644 (file)
@@ -183,7 +183,7 @@ static struct gpio hx4700_audio_gpios[] = {
        { GPIO92_HX4700_HP_DRIVER, GPIOF_OUT_INIT_LOW, "EP_POWER" },
 };
 
-static int __devinit hx4700_audio_probe(struct platform_device *pdev)
+static int hx4700_audio_probe(struct platform_device *pdev)
 {
        int ret;
 
@@ -204,7 +204,7 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit hx4700_audio_remove(struct platform_device *pdev)
+static int hx4700_audio_remove(struct platform_device *pdev)
 {
        snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio);
        snd_soc_unregister_card(&snd_soc_card_hx4700);
@@ -223,7 +223,7 @@ static struct platform_driver hx4700_audio_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe  = hx4700_audio_probe,
-       .remove = __devexit_p(hx4700_audio_remove),
+       .remove = hx4700_audio_remove,
 };
 
 module_platform_driver(hx4700_audio_driver);
index b93dafd32b809e63dd8280441261cde86da9f9ab..eef1f7b7b38e27c9ffcfb1b340df0f66d3173275 100644 (file)
@@ -65,7 +65,7 @@ static struct snd_soc_card imote2 = {
        .num_links = 1,
 };
 
-static int __devinit imote2_probe(struct platform_device *pdev)
+static int imote2_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &imote2;
        int ret;
@@ -79,7 +79,7 @@ static int __devinit imote2_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit imote2_remove(struct platform_device *pdev)
+static int imote2_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -93,7 +93,7 @@ static struct platform_driver imote2_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = imote2_probe,
-       .remove         = __devexit_p(imote2_remove),
+       .remove         = imote2_remove,
 };
 
 module_platform_driver(imote2_driver);
index 8687c1c65d293dd932fc920880c4a889e0b19d97..97b711e12821e02c2b62c6ceb377fb4a942ee71f 100644 (file)
@@ -186,7 +186,7 @@ static struct snd_soc_card mioa701 = {
        .num_links = ARRAY_SIZE(mioa701_dai),
 };
 
-static int __devinit mioa701_wm9713_probe(struct platform_device *pdev)
+static int mioa701_wm9713_probe(struct platform_device *pdev)
 {
        int rc;
 
@@ -202,7 +202,7 @@ static int __devinit mioa701_wm9713_probe(struct platform_device *pdev)
        return rc;
 }
 
-static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
+static int mioa701_wm9713_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -212,7 +212,7 @@ static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
 
 static struct platform_driver mioa701_wm9713_driver = {
        .probe          = mioa701_wm9713_probe,
-       .remove         = __devexit_p(mioa701_wm9713_remove),
+       .remove         = mioa701_wm9713_remove,
        .driver         = {
                .name           = "mioa701-wm9713",
                .owner          = THIS_MODULE,
index e834faf859fdcf91e5c1889b1975b2fff357e206..190eb0bccf5f1a9467cbccbec281d623e9a4065d 100644 (file)
@@ -257,7 +257,7 @@ struct snd_soc_platform_driver mmp_soc_platform = {
        .pcm_free       = mmp_pcm_free_dma_buffers,
 };
 
-static __devinit int mmp_pcm_probe(struct platform_device *pdev)
+static int mmp_pcm_probe(struct platform_device *pdev)
 {
        struct mmp_audio_platdata *pdata = pdev->dev.platform_data;
 
@@ -274,7 +274,7 @@ static __devinit int mmp_pcm_probe(struct platform_device *pdev)
        return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform);
 }
 
-static int __devexit mmp_pcm_remove(struct platform_device *pdev)
+static int mmp_pcm_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -287,7 +287,7 @@ static struct platform_driver mmp_pcm_driver = {
        },
 
        .probe = mmp_pcm_probe,
-       .remove = __devexit_p(mmp_pcm_remove),
+       .remove = mmp_pcm_remove,
 };
 
 module_platform_driver(mmp_pcm_driver);
index 4d6cb8a30fc847643eddb4ac222de66b576e82bf..41c3a09b53eaab72824ffe36862407b18c56d32b 100644 (file)
@@ -405,7 +405,7 @@ struct snd_soc_dai_driver mmp_sspa_dai = {
        .ops = &mmp_sspa_dai_ops,
 };
 
-static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
+static int asoc_mmp_sspa_probe(struct platform_device *pdev)
 {
        struct sspa_priv *priv;
        struct resource *res;
@@ -453,7 +453,7 @@ static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
        return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai);
 }
 
-static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev)
+static int asoc_mmp_sspa_remove(struct platform_device *pdev)
 {
        struct sspa_priv *priv = platform_get_drvdata(pdev);
 
@@ -470,7 +470,7 @@ static struct platform_driver asoc_mmp_sspa_driver = {
                .owner = THIS_MODULE,
        },
        .probe = asoc_mmp_sspa_probe,
-       .remove = __devexit_p(asoc_mmp_sspa_remove),
+       .remove = asoc_mmp_sspa_remove,
 };
 
 module_platform_driver(asoc_mmp_sspa_driver);
index aa3da91907c66f23f1fe895da2128ec379888d34..2074e2daf9c6a341e002ff26771e05de9ce2f9a6 100644 (file)
@@ -187,7 +187,7 @@ put_device:
        return ret;
 }
 
-static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
+static int palm27x_asoc_remove(struct platform_device *pdev)
 {
        platform_device_unregister(palm27x_snd_device);
        return 0;
@@ -195,7 +195,7 @@ static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
 
 static struct platform_driver palm27x_wm9712_driver = {
        .probe          = palm27x_asoc_probe,
-       .remove         = __devexit_p(palm27x_asoc_remove),
+       .remove         = palm27x_asoc_remove,
        .driver         = {
                .name           = "palm27x-asoc",
                .owner          = THIS_MODULE,
index d2cc81735036ea8dd6a1aff7f61465caa29fd2fd..fafe46355c316b20df0f1e3fb114cae8d4cae9e2 100644 (file)
@@ -269,7 +269,7 @@ static struct snd_soc_card poodle = {
        .num_dapm_routes = ARRAY_SIZE(poodle_audio_map),
 };
 
-static int __devinit poodle_probe(struct platform_device *pdev)
+static int poodle_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &poodle;
        int ret;
@@ -291,7 +291,7 @@ static int __devinit poodle_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit poodle_remove(struct platform_device *pdev)
+static int poodle_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -305,7 +305,7 @@ static struct platform_driver poodle_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = poodle_probe,
-       .remove         = __devexit_p(poodle_remove),
+       .remove         = poodle_remove,
 };
 
 module_platform_driver(poodle_driver);
index 4da5fc55c7ee81d81369fae163344e8058c96b86..d3eb0c2eec7724a843f277647cb80d5ed8ecea9f 100644 (file)
@@ -794,12 +794,12 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
                .ops = &pxa_ssp_dai_ops,
 };
 
-static __devinit int asoc_ssp_probe(struct platform_device *pdev)
+static int asoc_ssp_probe(struct platform_device *pdev)
 {
        return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
 }
 
-static int __devexit asoc_ssp_remove(struct platform_device *pdev)
+static int asoc_ssp_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dai(&pdev->dev);
        return 0;
@@ -812,7 +812,7 @@ static struct platform_driver asoc_ssp_driver = {
        },
 
        .probe = asoc_ssp_probe,
-       .remove = __devexit_p(asoc_ssp_remove),
+       .remove = asoc_ssp_remove,
 };
 
 module_platform_driver(asoc_ssp_driver);
index 06ea2744cc88f161e8d3508137747ee7d5958669..4b0a009bd68388e0355ff82841b7673d46120181 100644 (file)
@@ -104,7 +104,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
 #define pxa2xx_ac97_resume     NULL
 #endif
 
-static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
 {
        return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
 }
@@ -234,7 +234,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 
 EXPORT_SYMBOL_GPL(soc_ac97_ops);
 
-static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
+static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 {
        if (pdev->id != -1) {
                dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
@@ -249,7 +249,7 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
                        ARRAY_SIZE(pxa_ac97_dai_driver));
 }
 
-static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
+static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
        return 0;
@@ -257,7 +257,7 @@ static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver pxa2xx_ac97_driver = {
        .probe          = pxa2xx_ac97_dev_probe,
-       .remove         = __devexit_p(pxa2xx_ac97_dev_remove),
+       .remove         = pxa2xx_ac97_dev_remove,
        .driver         = {
                .name   = "pxa2xx-ac97",
                .owner  = THIS_MODULE,
index 3075a426124cc119cfc43355c2403fba835ec4b4..6b1a06f67564abc2ce97450ed9cad05c1cd7a2ee 100644 (file)
@@ -365,7 +365,7 @@ static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
        return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
 }
 
-static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
+static int pxa2xx_i2s_drv_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dai(&pdev->dev);
        return 0;
@@ -373,7 +373,7 @@ static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
 
 static struct platform_driver pxa2xx_i2s_driver = {
        .probe = pxa2xx_i2s_drv_probe,
-       .remove = __devexit_p(pxa2xx_i2s_drv_remove),
+       .remove = pxa2xx_i2s_drv_remove,
 
        .driver = {
                .name = "pxa2xx-i2s",
index fdd6bedef9bd7d818dadf36049df53ed067d842d..ecff116cb7b034484cd3c420ae483d576ef0db95 100644 (file)
@@ -120,12 +120,12 @@ static struct snd_soc_platform_driver pxa2xx_soc_platform = {
        .pcm_free       = pxa2xx_pcm_free_dma_buffers,
 };
 
-static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)
+static int pxa2xx_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);
 }
 
-static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)
+static int pxa2xx_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -138,7 +138,7 @@ static struct platform_driver pxa_pcm_driver = {
        },
 
        .probe = pxa2xx_soc_platform_probe,
-       .remove = __devexit_p(pxa2xx_soc_platform_remove),
+       .remove = pxa2xx_soc_platform_remove,
 };
 
 module_platform_driver(pxa_pcm_driver);
index 2aec63f3706acf826f8f9424fa496a1a479814ab..a3fe19123f07218bbd8af8bb7bd1cf6a26af8067 100644 (file)
@@ -241,7 +241,7 @@ static struct snd_soc_card tosa = {
        .num_links = ARRAY_SIZE(tosa_dai),
 };
 
-static int __devinit tosa_probe(struct platform_device *pdev)
+static int tosa_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &tosa;
        int ret;
@@ -262,7 +262,7 @@ static int __devinit tosa_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit tosa_remove(struct platform_device *pdev)
+static int tosa_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -277,7 +277,7 @@ static struct platform_driver tosa_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tosa_probe,
-       .remove         = __devexit_p(tosa_remove),
+       .remove         = tosa_remove,
 };
 
 module_platform_driver(tosa_driver);
index 935491a8a7706f32e4d62e5cf9b50c66880168b1..f4ea4f6663a2c0d396997d7aef5cc1871f6ea6e5 100644 (file)
@@ -131,7 +131,7 @@ static struct snd_soc_card ttc_dkb_card = {
        .num_dapm_routes = ARRAY_SIZE(ttc_audio_map),
 };
 
-static int __devinit ttc_dkb_probe(struct platform_device *pdev)
+static int ttc_dkb_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &ttc_dkb_card;
        int ret;
@@ -146,7 +146,7 @@ static int __devinit ttc_dkb_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit ttc_dkb_remove(struct platform_device *pdev)
+static int ttc_dkb_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -161,7 +161,7 @@ static struct platform_driver ttc_dkb_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ttc_dkb_probe,
-       .remove         = __devexit_p(ttc_dkb_remove),
+       .remove         = ttc_dkb_remove,
 };
 
 module_platform_driver(ttc_dkb_driver);
index aaabdbaec19c6cf389f887669af54a3558f16aba..fee4d477a49cab75810ab7f02579a50516227450 100644 (file)
@@ -436,7 +436,7 @@ static struct snd_soc_dai_driver s6000_i2s_dai = {
        .ops = &s6000_i2s_dai_ops,
 };
 
-static int __devinit s6000_i2s_probe(struct platform_device *pdev)
+static int s6000_i2s_probe(struct platform_device *pdev)
 {
        struct s6000_i2s_dev *dev;
        struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
@@ -566,7 +566,7 @@ err_release_none:
        return ret;
 }
 
-static void __devexit s6000_i2s_remove(struct platform_device *pdev)
+static void s6000_i2s_remove(struct platform_device *pdev)
 {
        struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
        struct resource *region;
@@ -597,7 +597,7 @@ static void __devexit s6000_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver s6000_i2s_driver = {
        .probe  = s6000_i2s_probe,
-       .remove = __devexit_p(s6000_i2s_remove),
+       .remove = s6000_i2s_remove,
        .driver = {
                .name   = "s6000-i2s",
                .owner  = THIS_MODULE,
index 716da861c629399de5e5322b1556c4e7ae46d08e..1358c7de2521b7c296aaf2b031f78cf662523c96 100644 (file)
@@ -500,12 +500,12 @@ static struct snd_soc_platform_driver s6000_soc_platform = {
        .pcm_free =     s6000_pcm_free,
 };
 
-static int __devinit s6000_soc_platform_probe(struct platform_device *pdev)
+static int s6000_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
 }
 
-static int __devexit s6000_soc_platform_remove(struct platform_device *pdev)
+static int s6000_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -518,7 +518,7 @@ static struct platform_driver s6000_pcm_driver = {
        },
 
        .probe = s6000_soc_platform_probe,
-       .remove = __devexit_p(s6000_soc_platform_remove),
+       .remove = s6000_soc_platform_remove,
 };
 
 module_platform_driver(s6000_pcm_driver);
index 14fbcd30cae574dbc57b8f20eae191dc332c0f93..0df3c5644cfafb9629621b728339157cc8496cc7 100644 (file)
@@ -370,7 +370,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
        },
 };
 
-static __devinit int s3c_ac97_probe(struct platform_device *pdev)
+static int s3c_ac97_probe(struct platform_device *pdev)
 {
        struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
        struct s3c_audio_pdata *ac97_pdata;
@@ -442,7 +442,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto err2;
        }
-       clk_enable(s3c_ac97.ac97_clk);
+       clk_prepare_enable(s3c_ac97.ac97_clk);
 
        if (ac97_pdata->cfg_gpio(pdev)) {
                dev_err(&pdev->dev, "Unable to configure gpio\n");
@@ -462,13 +462,20 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
        if (ret)
                goto err5;
 
-       return 0;
+       ret = asoc_dma_platform_register(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
+               goto err6;
+       }
 
+       return 0;
+err6:
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
 err5:
        free_irq(irq_res->start, NULL);
 err4:
 err3:
-       clk_disable(s3c_ac97.ac97_clk);
+       clk_disable_unprepare(s3c_ac97.ac97_clk);
        clk_put(s3c_ac97.ac97_clk);
 err2:
        iounmap(s3c_ac97.regs);
@@ -478,17 +485,18 @@ err1:
        return ret;
 }
 
-static __devexit int s3c_ac97_remove(struct platform_device *pdev)
+static int s3c_ac97_remove(struct platform_device *pdev)
 {
        struct resource *mem_res, *irq_res;
 
+       asoc_dma_platform_unregister(&pdev->dev);
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
 
        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (irq_res)
                free_irq(irq_res->start, NULL);
 
-       clk_disable(s3c_ac97.ac97_clk);
+       clk_disable_unprepare(s3c_ac97.ac97_clk);
        clk_put(s3c_ac97.ac97_clk);
 
        iounmap(s3c_ac97.regs);
@@ -502,7 +510,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c_ac97_driver = {
        .probe  = s3c_ac97_probe,
-       .remove = __devexit_p(s3c_ac97_remove),
+       .remove = s3c_ac97_remove,
        .driver = {
                .name = "samsung-ac97",
                .owner = THIS_MODULE,
index a2ca1567b9e4ff93a481d99065820d887ff8a72c..ceed466af9ff8f25b0007b8399cec68c87a06daa 100644 (file)
 #include "../codecs/wm5102.h"
 #include "../codecs/wm9081.h"
 
-/*
- * 44.1kHz based clocks for the SYSCLK domain, use a very high clock
- * to allow all the DSP functionality to be enabled if desired.
- */
-#define SYSCLK_RATE (44100 * 1024)
-
-/* 48kHz based clocks for the ASYNC domain */
-#define ASYNCCLK_RATE (48000 * 512)
-
 /* BCLK2 is fixed at this currently */
 #define BCLK2_RATE (64 * 8000)
 
  */
 #define MCLK_RATE 24576000
 
-#define WM9081_AUDIO_RATE 44100
-#define WM9081_MCLK_RATE  (WM9081_AUDIO_RATE * 256)
+#define SYS_AUDIO_RATE 44100
+#define SYS_MCLK_RATE  (SYS_AUDIO_RATE * 512)
+
+#define DAI_AP_DSP    0
+#define DAI_DSP_CODEC 1
+#define DAI_CODEC_CP  2
+#define DAI_CODEC_SUB 3
+
+struct bells_drvdata {
+       int sysclk_rate;
+       int asyncclk_rate;
+};
+
+static struct bells_drvdata wm2200_drvdata = {
+       .sysclk_rate = 22579200,
+};
+
+static struct bells_drvdata wm5102_drvdata = {
+       .sysclk_rate = 45158400,
+       .asyncclk_rate = 49152000,
+};
+
+static struct bells_drvdata wm5110_drvdata = {
+       .sysclk_rate = 135475200,
+       .asyncclk_rate = 147456000,
+};
 
 static int bells_set_bias_level(struct snd_soc_card *card,
                                struct snd_soc_dapm_context *dapm,
                                enum snd_soc_bias_level level)
 {
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct bells_drvdata *bells = card->drvdata;
        int ret;
 
        if (dapm->dev != codec_dai->dev)
@@ -52,18 +68,21 @@ static int bells_set_bias_level(struct snd_soc_card *card,
 
        switch (level) {
        case SND_SOC_BIAS_PREPARE:
-               if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
-                       ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
-                                                   ARIZONA_FLL_SRC_MCLK1,
-                                                   MCLK_RATE,
-                                                   SYSCLK_RATE);
-                       if (ret < 0)
-                               pr_err("Failed to start FLL: %d\n", ret);
+               if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
+                       break;
 
+               ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
+                                           ARIZONA_FLL_SRC_MCLK1,
+                                           MCLK_RATE,
+                                           bells->sysclk_rate);
+               if (ret < 0)
+                       pr_err("Failed to start FLL: %d\n", ret);
+
+               if (bells->asyncclk_rate) {
                        ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
                                                    ARIZONA_FLL_SRC_AIF2BCLK,
                                                    BCLK2_RATE,
-                                                   ASYNCCLK_RATE);
+                                                   bells->asyncclk_rate);
                        if (ret < 0)
                                pr_err("Failed to start FLL: %d\n", ret);
                }
@@ -80,8 +99,9 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
                                     struct snd_soc_dapm_context *dapm,
                                     enum snd_soc_bias_level level)
 {
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct bells_drvdata *bells = card->drvdata;
        int ret;
 
        if (dapm->dev != codec_dai->dev)
@@ -95,10 +115,13 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
                        return ret;
                }
 
-               ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0);
-               if (ret < 0) {
-                       pr_err("Failed to stop FLL: %d\n", ret);
-                       return ret;
+               if (bells->asyncclk_rate) {
+                       ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
+                                                   0, 0, 0);
+                       if (ret < 0) {
+                               pr_err("Failed to stop FLL: %d\n", ret);
+                               return ret;
+                       }
                }
                break;
 
@@ -113,56 +136,73 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
 
 static int bells_late_probe(struct snd_soc_card *card)
 {
-       struct snd_soc_codec *codec = card->rtd[0].codec;
-       struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
-       struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
-       struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai;
-       struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai;
+       struct bells_drvdata *bells = card->drvdata;
+       struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
+       struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
+       struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
+       struct snd_soc_dai *aif2_dai;
+       struct snd_soc_dai *aif3_dai;
+       struct snd_soc_dai *wm9081_dai;
        int ret;
 
-       ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
+                                      ARIZONA_CLK_SRC_FLL1,
+                                      bells->sysclk_rate,
+                                      SND_SOC_CLOCK_IN);
        if (ret != 0) {
-               dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
+               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
+       ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
        if (ret != 0) {
-               dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
+               dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
-       if (ret != 0) {
+       ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+       if (ret != 0)
                dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
-               return ret;
-       }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
-                                      ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE,
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
+                                      SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+
+       if (card->num_rtd == DAI_CODEC_CP)
+               return 0;
+
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
+                                      ARIZONA_CLK_SRC_FLL2,
+                                      bells->asyncclk_rate,
                                       SND_SOC_CLOCK_IN);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+               dev_err(codec->dev, "Failed to set ASYNCCLK: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
-                                      WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT);
+       aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
+
+       ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+               dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
-                                      ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE,
-                                      SND_SOC_CLOCK_IN);
+       if (card->num_rtd == DAI_CODEC_SUB)
+               return 0;
+
+       aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
+       wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
+
+       ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+               dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
                return ret;
        }
 
        ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK,
-                                      0, WM9081_MCLK_RATE, 0);
+                                      0, SYS_MCLK_RATE, 0);
        if (ret != 0) {
                dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
                return ret;
@@ -181,22 +221,57 @@ static const struct snd_soc_pcm_stream baseband_params = {
 
 static const struct snd_soc_pcm_stream sub_params = {
        .formats = SNDRV_PCM_FMTBIT_S32_LE,
-       .rate_min = WM9081_AUDIO_RATE,
-       .rate_max = WM9081_AUDIO_RATE,
+       .rate_min = SYS_AUDIO_RATE,
+       .rate_max = SYS_AUDIO_RATE,
        .channels_min = 2,
        .channels_max = 2,
 };
 
+static struct snd_soc_dai_link bells_dai_wm2200[] = {
+       {
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
+               .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm0010-sdi1",
+               .platform_name = "samsung-i2s.0",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm2200",
+               .codec_name = "wm2200.1-003a",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
+       },
+};
+
 static struct snd_soc_dai_link bells_dai_wm5102[] = {
        {
-               .name = "CPU",
-               .stream_name = "CPU",
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm0010-sdi1",
+               .platform_name = "samsung-i2s.0",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
                .codec_dai_name = "wm5102-aif1",
-               .platform_name = "samsung-audio",
                .codec_name = "wm5102-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
        },
        {
                .name = "Baseband",
@@ -224,14 +299,25 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
 
 static struct snd_soc_dai_link bells_dai_wm5110[] = {
        {
-               .name = "CPU",
-               .stream_name = "CPU",
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm0010-sdi1",
+               .platform_name = "samsung-i2s.0",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
                .codec_dai_name = "wm5110-aif1",
-               .platform_name = "samsung-audio",
                .codec_name = "wm5110-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
        },
        {
                .name = "Baseband",
@@ -269,6 +355,24 @@ static struct snd_soc_dapm_route bells_routes[] = {
 };
 
 static struct snd_soc_card bells_cards[] = {
+       {
+               .name = "Bells WM2200",
+               .owner = THIS_MODULE,
+               .dai_link = bells_dai_wm2200,
+               .num_links = ARRAY_SIZE(bells_dai_wm2200),
+               .codec_conf = bells_codec_conf,
+               .num_configs = ARRAY_SIZE(bells_codec_conf),
+
+               .late_probe = bells_late_probe,
+
+               .dapm_routes = bells_routes,
+               .num_dapm_routes = ARRAY_SIZE(bells_routes),
+
+               .set_bias_level = bells_set_bias_level,
+               .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm2200_drvdata,
+       },
        {
                .name = "Bells WM5102",
                .owner = THIS_MODULE,
@@ -284,6 +388,8 @@ static struct snd_soc_card bells_cards[] = {
 
                .set_bias_level = bells_set_bias_level,
                .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm5102_drvdata,
        },
        {
                .name = "Bells WM5110",
@@ -300,11 +406,13 @@ static struct snd_soc_card bells_cards[] = {
 
                .set_bias_level = bells_set_bias_level,
                .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm5110_drvdata,
        },
 };
 
 
-static __devinit int bells_probe(struct platform_device *pdev)
+static int bells_probe(struct platform_device *pdev)
 {
        int ret;
 
@@ -321,7 +429,7 @@ static __devinit int bells_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit bells_remove(struct platform_device *pdev)
+static int bells_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&bells_cards[pdev->id]);
 
@@ -335,7 +443,7 @@ static struct platform_driver bells_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = bells_probe,
-       .remove = __devexit_p(bells_remove),
+       .remove = bells_remove,
 };
 
 module_platform_driver(bells_driver);
index b70964ea448cef264bf540597850558e7c9fd23c..db87628d7630cd0effc77588deb6f1fc7d337140 100644 (file)
@@ -432,30 +432,18 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
        .pcm_free       = dma_free_dma_buffers,
 };
 
-static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev)
+int asoc_dma_platform_register(struct device *dev)
 {
-       return snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);
+       return snd_soc_register_platform(dev, &samsung_asoc_platform);
 }
+EXPORT_SYMBOL_GPL(asoc_dma_platform_register);
 
-static int __devexit samsung_asoc_platform_remove(struct platform_device *pdev)
+void asoc_dma_platform_unregister(struct device *dev)
 {
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
+       snd_soc_unregister_platform(dev);
 }
-
-static struct platform_driver asoc_dma_driver = {
-       .driver = {
-               .name = "samsung-audio",
-               .owner = THIS_MODULE,
-       },
-
-       .probe = samsung_asoc_platform_probe,
-       .remove = __devexit_p(samsung_asoc_platform_remove),
-};
-
-module_platform_driver(asoc_dma_driver);
+EXPORT_SYMBOL_GPL(asoc_dma_platform_unregister);
 
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-audio");
index 7d1ead77ef2121751269bb74ca80681033f5d00c..73d8c7c8a1e8458119d9c2b5afecece3b64bfe1a 100644 (file)
@@ -21,4 +21,7 @@ struct s3c_dma_params {
        struct samsung_dma_ops *ops;
 };
 
+int asoc_dma_platform_register(struct device *dev);
+void asoc_dma_platform_unregister(struct device *dev);
+
 #endif
index c23c2ae91f58e441ae095ba30f7cbadcd9f1d000..d37ede58e0a8620eb21ba317a8885b7601d02c3b 100644 (file)
@@ -228,7 +228,7 @@ static struct snd_soc_dai_link goni_dai[] = {
        .stream_name = "WM8994 HiFi",
        .cpu_dai_name = "samsung-i2s.0",
        .codec_dai_name = "wm8994-aif1",
-       .platform_name = "samsung-audio",
+       .platform_name = "samsung-i2s.0",
        .codec_name = "wm8994-codec.0-001a",
        .init = goni_wm8994_init,
        .ops = &goni_hifi_ops,
index 6e3257717c54b24c49fa840e8696ccd169612d86..3870e9678b5d2a8a9d843d3f0766628df67bea48 100644 (file)
@@ -207,7 +207,7 @@ static struct snd_soc_dai_link h1940_uda1380_dai[] = {
                .cpu_dai_name   = "s3c24xx-iis",
                .codec_dai_name = "uda1380-hifi",
                .init           = h1940_uda1380_init,
-               .platform_name  = "samsung-audio",
+               .platform_name  = "s3c24xx-iis",
                .codec_name     = "uda1380-codec.0-001a",
                .ops            = &h1940_ops,
        },
index 40b00a13dcd1b1c664636406ae693faa0bdf996f..d2d124f1dd1b2a3c83cdd9c51c104be78b4f18b9 100644 (file)
@@ -49,8 +49,6 @@ struct i2s_dai {
        struct clk *clk;
        /* Clock for generating I2S signals */
        struct clk *op_clk;
-       /* Array of clock names for op_clk */
-       const char **src_clk;
        /* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */
        struct i2s_dai *pri_dai;
        /* Pointer to the Secondary_Fifo if it has one, NULL otherwise */
@@ -423,7 +421,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
                        if (i2s->op_clk) {
                                if ((clk_id && !(mod & MOD_IMS_SYSMUX)) ||
                                        (!clk_id && (mod & MOD_IMS_SYSMUX))) {
-                                       clk_disable(i2s->op_clk);
+                                       clk_disable_unprepare(i2s->op_clk);
                                        clk_put(i2s->op_clk);
                                } else {
                                        i2s->rclk_srcrate =
@@ -432,9 +430,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
                                }
                        }
 
-                       i2s->op_clk = clk_get(&i2s->pdev->dev,
-                                               i2s->src_clk[clk_id]);
-                       clk_enable(i2s->op_clk);
+                       if (clk_id)
+                               i2s->op_clk = clk_get(&i2s->pdev->dev,
+                                               "i2s_opclk1");
+                       else
+                               i2s->op_clk = clk_get(&i2s->pdev->dev,
+                                               "i2s_opclk0");
+                       clk_prepare_enable(i2s->op_clk);
                        i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
 
                        /* Over-ride the other's */
@@ -880,7 +882,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
                iounmap(i2s->addr);
                return -ENOENT;
        }
-       clk_enable(i2s->clk);
+       clk_prepare_enable(i2s->clk);
 
        if (other) {
                other->addr = i2s->addr;
@@ -922,7 +924,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
                if (i2s->quirks & QUIRK_NEED_RSTCLR)
                        writel(0, i2s->addr + I2SCON);
 
-               clk_disable(i2s->clk);
+               clk_disable_unprepare(i2s->clk);
                clk_put(i2s->clk);
 
                iounmap(i2s->addr);
@@ -950,8 +952,7 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
                                        SNDRV_PCM_FMTBIT_S16_LE | \
                                        SNDRV_PCM_FMTBIT_S24_LE)
 
-static __devinit
-struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
+static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 {
        struct i2s_dai *i2s;
 
@@ -992,7 +993,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
        return i2s;
 }
 
-static __devinit int samsung_i2s_probe(struct platform_device *pdev)
+static int samsung_i2s_probe(struct platform_device *pdev)
 {
        u32 dma_pl_chan, dma_cp_chan, dma_pl_sec_chan;
        struct i2s_dai *pri_dai, *sec_dai = NULL;
@@ -1007,6 +1008,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
                sec_dai = dev_get_drvdata(&pdev->dev);
                snd_soc_register_dai(&sec_dai->pdev->dev,
                        &sec_dai->i2s_dai_drv);
+               asoc_dma_platform_register(&pdev->dev);
                return 0;
        }
 
@@ -1067,7 +1069,6 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
                (struct s3c2410_dma_client *)&pri_dai->dma_capture;
        pri_dai->dma_playback.channel = dma_pl_chan;
        pri_dai->dma_capture.channel = dma_cp_chan;
-       pri_dai->src_clk = i2s_cfg->src_clk;
        pri_dai->dma_playback.dma_size = 4;
        pri_dai->dma_capture.dma_size = 4;
        pri_dai->base = regs_base;
@@ -1088,7 +1089,6 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
                        (struct s3c2410_dma_client *)&sec_dai->dma_playback;
                /* Use iDMA always if SysDMA not provided */
                sec_dai->dma_playback.channel = dma_pl_sec_chan ? : -1;
-               sec_dai->src_clk = i2s_cfg->src_clk;
                sec_dai->dma_playback.dma_size = 4;
                sec_dai->base = regs_base;
                sec_dai->quirks = quirks;
@@ -1107,6 +1107,8 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
 
        pm_runtime_enable(&pdev->dev);
 
+       asoc_dma_platform_register(&pdev->dev);
+
        return 0;
 err:
        release_mem_region(regs_base, resource_size(res));
@@ -1114,7 +1116,7 @@ err:
        return ret;
 }
 
-static __devexit int samsung_i2s_remove(struct platform_device *pdev)
+static int samsung_i2s_remove(struct platform_device *pdev)
 {
        struct i2s_dai *i2s, *other;
        struct resource *res;
@@ -1135,6 +1137,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
        i2s->pri_dai = NULL;
        i2s->sec_dai = NULL;
 
+       asoc_dma_platform_unregister(&pdev->dev);
        snd_soc_unregister_dai(&pdev->dev);
 
        return 0;
@@ -1142,7 +1145,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver samsung_i2s_driver = {
        .probe  = samsung_i2s_probe,
-       .remove = __devexit_p(samsung_i2s_remove),
+       .remove = samsung_i2s_remove,
        .driver = {
                .name = "samsung-i2s",
                .owner = THIS_MODULE,
index c227c3163caeacba809ce7fc0b0b0276062a5008..a07950b0c8ceba1756163c0d59b4c20b0ad7269e 100644 (file)
@@ -416,12 +416,12 @@ static struct snd_soc_platform_driver asoc_idma_platform = {
        .pcm_free = idma_free,
 };
 
-static int __devinit asoc_idma_platform_probe(struct platform_device *pdev)
+static int asoc_idma_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
 }
 
-static int __devexit asoc_idma_platform_remove(struct platform_device *pdev)
+static int asoc_idma_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -434,7 +434,7 @@ static struct platform_driver asoc_idma_driver = {
        },
 
        .probe = asoc_idma_platform_probe,
-       .remove = __devexit_p(asoc_idma_platform_remove),
+       .remove = asoc_idma_platform_remove,
 };
 
 module_platform_driver(asoc_idma_driver);
index 1578663a1faa55de01e5d9110ef41dfe9963f4d4..b5f6abd9d2216d7f9664ca337468ff7792c93b0d 100644 (file)
@@ -118,7 +118,7 @@ static struct snd_soc_dai_link jive_dai = {
        .stream_name    = "WM8750",
        .cpu_dai_name   = "s3c2412-i2s",
        .codec_dai_name = "wm8750-hifi",
-       .platform_name  = "samsung-audio",
+       .platform_name  = "s3c2412-i2s",
        .codec_name     = "wm8750.0-001a",
        .init           = jive_wm8750_init,
        .ops            = &jive_ops,
index ee52c8a007790972a62e9a84bdf196650a27e06b..bfb91f34a22a95f0a4c65084e085cc84a6db5349 100644 (file)
@@ -145,7 +145,7 @@ static struct snd_soc_dai_link littlemill_dai[] = {
                .stream_name = "CPU",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8994-aif1",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "wm8994-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
@@ -270,7 +270,7 @@ static int littlemill_late_probe(struct snd_soc_card *card)
                return ret;
 
        /* This will check device compatibility itself */
-       wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+       wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL, NULL, NULL);
 
        /* As will this */
        wm8994_mic_detect(codec, &littlemill_headset, 1);
@@ -297,7 +297,7 @@ static struct snd_soc_card littlemill = {
        .late_probe = littlemill_late_probe,
 };
 
-static __devinit int littlemill_probe(struct platform_device *pdev)
+static int littlemill_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &littlemill;
        int ret;
@@ -314,7 +314,7 @@ static __devinit int littlemill_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit littlemill_remove(struct platform_device *pdev)
+static int littlemill_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -330,7 +330,7 @@ static struct platform_driver littlemill_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = littlemill_probe,
-       .remove = __devexit_p(littlemill_remove),
+       .remove = littlemill_remove,
 };
 
 module_platform_driver(littlemill_driver);
index 69c4a5934a4d936c2dc48af9dcf980c987825ed2..9342fc270c2ba2ba62414ad388aaae1e92ad4660 100644 (file)
@@ -28,7 +28,7 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
        .cpu_dai_name = "samsung-ac97",
        .codec_dai_name = "ac97-hifi",
        .codec_name = "ac97-codec",
-       .platform_name = "samsung-audio",
+       .platform_name = "samsung-ac97",
 },
 };
 
index 6abf341c4a2ab3f4a224f1161770228dc07da93a..570cf522950824aca76801cce2184291b849821b 100644 (file)
@@ -99,7 +99,7 @@ static struct snd_soc_dai_link lowland_dai[] = {
                .stream_name = "CPU",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm5100-aif1",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "wm5100.1-001a",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                                SND_SOC_DAIFMT_CBM_CFM,
@@ -180,7 +180,7 @@ static struct snd_soc_card lowland = {
        .num_dapm_routes = ARRAY_SIZE(audio_paths),
 };
 
-static __devinit int lowland_probe(struct platform_device *pdev)
+static int lowland_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &lowland;
        int ret;
@@ -197,7 +197,7 @@ static __devinit int lowland_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lowland_remove(struct platform_device *pdev)
+static int lowland_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -213,7 +213,7 @@ static struct platform_driver lowland_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = lowland_probe,
-       .remove = __devexit_p(lowland_remove),
+       .remove = lowland_remove,
 };
 
 module_platform_driver(lowland_driver);
index 321d51134e47789a02c6d6483a0cb508a5b187c1..c7e965f80d2e41d46b7525cd21992ae8b7aec5d9 100644 (file)
@@ -364,7 +364,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
 { /* Hifi Playback - for similatious use with voice below */
        .name = "WM8753",
        .stream_name = "WM8753 HiFi",
-       .platform_name = "samsung-audio",
+       .platform_name = "s3c24xx-iis",
        .cpu_dai_name = "s3c24xx-iis",
        .codec_dai_name = "wm8753-hifi",
        .codec_name = "wm8753.0-001a",
index c86081992dfd9331eeaed79c97f656705162b450..13bab79ad93d2fb493608b7fa0b909df42be26ac 100644 (file)
@@ -490,7 +490,7 @@ static struct snd_soc_dai_driver s3c_pcm_dai[] = {
        },
 };
 
-static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
+static int s3c_pcm_dev_probe(struct platform_device *pdev)
 {
        struct s3c_pcm_info *pcm;
        struct resource *mem_res, *dmatx_res, *dmarx_res;
@@ -543,7 +543,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                ret = PTR_ERR(pcm->cclk);
                goto err1;
        }
-       clk_enable(pcm->cclk);
+       clk_prepare_enable(pcm->cclk);
 
        /* record our pcm structure for later use in the callbacks */
        dev_set_drvdata(&pdev->dev, pcm);
@@ -568,7 +568,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err4;
        }
-       clk_enable(pcm->pclk);
+       clk_prepare_enable(pcm->pclk);
 
        s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
                                                        + S3C_PCM_RXFIFO;
@@ -589,27 +589,36 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                goto err5;
        }
 
+       ret = asoc_dma_platform_register(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
+               goto err6;
+       }
+
        return 0;
 
+err6:
+       snd_soc_unregister_dai(&pdev->dev);
 err5:
-       clk_disable(pcm->pclk);
+       clk_disable_unprepare(pcm->pclk);
        clk_put(pcm->pclk);
 err4:
        iounmap(pcm->regs);
 err3:
        release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       clk_disable(pcm->cclk);
+       clk_disable_unprepare(pcm->cclk);
        clk_put(pcm->cclk);
 err1:
        return ret;
 }
 
-static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
+static int s3c_pcm_dev_remove(struct platform_device *pdev)
 {
        struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
        struct resource *mem_res;
 
+       asoc_dma_platform_unregister(&pdev->dev);
        snd_soc_unregister_dai(&pdev->dev);
 
        pm_runtime_disable(&pdev->dev);
@@ -619,8 +628,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem_res->start, resource_size(mem_res));
 
-       clk_disable(pcm->cclk);
-       clk_disable(pcm->pclk);
+       clk_disable_unprepare(pcm->cclk);
+       clk_disable_unprepare(pcm->pclk);
        clk_put(pcm->pclk);
        clk_put(pcm->cclk);
 
@@ -629,7 +638,7 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c_pcm_driver = {
        .probe  = s3c_pcm_dev_probe,
-       .remove = __devexit_p(s3c_pcm_dev_remove),
+       .remove = s3c_pcm_dev_remove,
        .driver = {
                .name = "samsung-pcm",
                .owner = THIS_MODULE,
index 21e12361a9cd137e1ae595a20c50210dcce9283a..a5826ea9cad63af16d20612155744c42c94320f0 100644 (file)
@@ -85,7 +85,7 @@ static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
                .cpu_dai_name   = "s3c24xx-iis",
                .codec_dai_name = "uda1380-hifi",
                .init           = rx1950_uda1380_init,
-               .platform_name  = "samsung-audio",
+               .platform_name  = "s3c24xx-iis",
                .codec_name     = "uda1380-codec.0-001a",
                .ops            = &rx1950_ops,
        },
index ac7701b3c5dc01a95138b3c5c72ecfe25eeacce5..22133771639359877a7a918a593d28f9eac3fa9d 100644 (file)
@@ -160,20 +160,38 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
        .ops = &s3c2412_i2s_dai_ops,
 };
 
-static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
+static int s3c2412_iis_dev_probe(struct platform_device *pdev)
 {
-       return s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+       int ret = 0;
+
+       ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+       if (ret) {
+               pr_err("failed to register the dai\n");
+               return ret;
+       }
+
+       ret = asoc_dma_platform_register(&pdev->dev);
+       if (ret) {
+               pr_err("failed to register the DMA: %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+err:
+       snd_soc_unregister_dai(&pdev->dev);
+       return ret;
 }
 
-static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
+static int s3c2412_iis_dev_remove(struct platform_device *pdev)
 {
+       asoc_dma_platform_unregister(&pdev->dev);
        snd_soc_unregister_dai(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver s3c2412_iis_driver = {
        .probe  = s3c2412_iis_dev_probe,
-       .remove = __devexit_p(s3c2412_iis_dev_remove),
+       .remove = s3c2412_iis_dev_remove,
        .driver = {
                .name = "s3c2412-iis",
                .owner = THIS_MODULE,
index 0aae3a3883dc4d348870a8db3aae43fc558065f7..ee10e8704e976f61f7ea6332416946af5471f59a 100644 (file)
@@ -465,20 +465,38 @@ static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
        .ops = &s3c24xx_i2s_dai_ops,
 };
 
-static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
+static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
+       int ret = 0;
+
+       ret = s3c_i2sv2_register_dai(&pdev->dev, -1, &s3c2412_i2s_dai);
+       if (ret) {
+               pr_err("failed to register the dai\n");
+               return ret;
+       }
+
+       ret = asoc_dma_platform_register(&pdev->dev);
+       if (ret) {
+               pr_err("failed to register the dma: %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+err:
+       snd_soc_unregister_dai(&pdev->dev);
+       return ret;
 }
 
-static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
+static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
 {
+       asoc_dma_platform_unregister(&pdev->dev);
        snd_soc_unregister_dai(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver s3c24xx_iis_driver = {
        .probe  = s3c24xx_iis_dev_probe,
-       .remove = __devexit_p(s3c24xx_iis_dev_remove),
+       .remove = s3c24xx_iis_dev_remove,
        .driver = {
                .name = "s3c24xx-iis",
                .owner = THIS_MODULE,
index 335a7d8a4a8d64b24cb6a8d50f31746d259ed094..2c015f62ead603564683c1920ec3613ad5df7768 100644 (file)
@@ -313,8 +313,8 @@ const struct dev_pm_ops simtec_audio_pmops = {
 EXPORT_SYMBOL_GPL(simtec_audio_pmops);
 #endif
 
-int __devinit simtec_audio_core_probe(struct platform_device *pdev,
-                                     struct snd_soc_card *card)
+int simtec_audio_core_probe(struct platform_device *pdev,
+                           struct snd_soc_card *card)
 {
        struct platform_device *snd_dev;
        int ret;
@@ -371,7 +371,7 @@ err_clk:
 }
 EXPORT_SYMBOL_GPL(simtec_audio_core_probe);
 
-int __devexit simtec_audio_remove(struct platform_device *pdev)
+int simtec_audio_remove(struct platform_device *pdev)
 {
        struct platform_device *snd_dev = platform_get_drvdata(pdev);
 
index 7ace6a87f41b5e673a49f87f1e659be6ea11cd73..d8a0543cae5e8d19834f0c963a55d51a372d0dba 100644 (file)
@@ -82,7 +82,7 @@ static struct snd_soc_dai_link simtec_dai_aic33 = {
        .codec_name     = "tlv320aic3x-codec.0-001a",
        .cpu_dai_name   = "s3c24xx-iis",
        .codec_dai_name = "tlv320aic3x-hifi",
-       .platform_name  = "samsung-audio",
+       .platform_name  = "s3c24xx-iis",
        .init           = simtec_hermes_init,
 };
 
@@ -99,7 +99,7 @@ static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
        .num_dapm_routes = ARRAY_SIZE(base_map),
 };
 
-static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
+static int simtec_audio_hermes_probe(struct platform_device *pd)
 {
        dev_info(&pd->dev, "probing....\n");
        return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
@@ -112,7 +112,7 @@ static struct platform_driver simtec_audio_hermes_platdrv = {
                .pm     = simtec_audio_pm,
        },
        .probe  = simtec_audio_hermes_probe,
-       .remove = __devexit_p(simtec_audio_remove),
+       .remove = simtec_audio_remove,
 };
 
 module_platform_driver(simtec_audio_hermes_platdrv);
index c42d5f00b0e1cc2cdc75bfcd625bc02a35aa7825..1ac0d7a63a3a0053170825af55c78fd7e599f590 100644 (file)
@@ -71,7 +71,7 @@ static struct snd_soc_dai_link simtec_dai_aic23 = {
        .codec_name     = "tlv320aic3x-codec.0-001a",
        .cpu_dai_name   = "s3c24xx-iis",
        .codec_dai_name = "tlv320aic3x-hifi",
-       .platform_name  = "samsung-audio",
+       .platform_name  = "s3c24xx-iis",
        .init           = simtec_tlv320aic23_init,
 };
 
@@ -88,7 +88,7 @@ static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
        .num_dapm_routes = ARRAY_SIZE(base_map),
 };
 
-static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
+static int simtec_audio_tlv320aic23_probe(struct platform_device *pd)
 {
        return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
 }
@@ -100,7 +100,7 @@ static struct platform_driver simtec_audio_tlv320aic23_driver = {
                .pm     = simtec_audio_pm,
        },
        .probe  = simtec_audio_tlv320aic23_probe,
-       .remove = __devexit_p(simtec_audio_remove),
+       .remove = simtec_audio_remove,
 };
 
 module_platform_driver(simtec_audio_tlv320aic23_driver);
index d731042e51b07db12aff2adc6685d97f3af6e00e..333e1b7f06c799307d2f9d7b46fc14074bd04caa 100644 (file)
@@ -224,7 +224,7 @@ static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
        .codec_dai_name = "uda134x-hifi",
        .cpu_dai_name = "s3c24xx-iis",
        .ops = &s3c24xx_uda134x_ops,
-       .platform_name  = "samsung-audio",
+       .platform_name  = "s3c24xx-iis",
 };
 
 static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
index f2dcb424ea255056aa6f3dbe224d9f0bfe14dfe7..58ae3237ef6945c0f4e29f890ad5ddc8bd526fac 100644 (file)
@@ -189,7 +189,7 @@ static struct snd_soc_dai_link smartq_dai[] = {
                .stream_name    = "SmartQ Hi-Fi",
                .cpu_dai_name   = "samsung-i2s.0",
                .codec_dai_name = "wm8750-hifi",
-               .platform_name  = "samsung-audio",
+               .platform_name  = "samsung-i2s.0",
                .codec_name     = "wm8750.0-0x1a",
                .init           = smartq_wm8987_init,
                .ops            = &smartq_hifi_ops,
index 720ba29bb7e4174e0929a77490f55b7f72c88f09..c390aad68cfbcf729292d3797a9c3e0340fac4bd 100644 (file)
@@ -24,7 +24,7 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
        .cpu_dai_name = "samsung-ac97",
        .codec_dai_name = "ac97-hifi",
        .codec_name = "ac97-codec",
-       .platform_name = "samsung-audio",
+       .platform_name = "samsung-ac97",
 },
 };
 
index beaa9c15d6978c64f3899596a7239f829fddb63d..a2f2363fe1c29d136434121377ccb5d3f4363f71 100644 (file)
@@ -151,7 +151,7 @@ static struct snd_soc_ops smdk_spdif_ops = {
 static struct snd_soc_dai_link smdk_dai = {
        .name = "S/PDIF",
        .stream_name = "S/PDIF PCM Playback",
-       .platform_name = "samsung-audio",
+       .platform_name = "samsung-spdif",
        .cpu_dai_name = "samsung-spdif",
        .codec_dai_name = "dit-hifi",
        .codec_name = "spdif-dit",
index ade2809cf393eebc97d74952b44c65aaa35835ac..7e2b710763be05c96537214189612fae3c538aa9 100644 (file)
@@ -176,7 +176,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Playback",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8580-hifi-playback",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "wm8580.0-001b",
                .ops = &smdk_ops,
        },
@@ -185,7 +185,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Capture",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8580-hifi-capture",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "wm8580.0-001b",
                .init = smdk_wm8580_init_paiftx,
                .ops = &smdk_ops,
@@ -195,7 +195,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Playback",
                .cpu_dai_name = "samsung-i2s.x",
                .codec_dai_name = "wm8580-hifi-playback",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.x",
                .codec_name = "wm8580.0-001b",
                .ops = &smdk_ops,
        },
index fab5322e9f055002a3acb8a1d6b0bae06f457f38..e43bd4294f99ad26011744f0192a83aaad89f9c3 100644 (file)
@@ -135,7 +135,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Capture",
                .cpu_dai_name = "samsung-pcm.0",
                .codec_dai_name = "wm8580-hifi-capture",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-pcm.0",
                .codec_name = "wm8580.0-001b",
                .ops = &smdk_wm8580_pcm_ops,
        },
@@ -153,7 +153,7 @@ static struct snd_soc_card smdk_pcm = {
  * is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4),
  * 2.0484Mhz, directly with MCLK both Codec and SoC.
  */
-static int __devinit snd_smdk_probe(struct platform_device *pdev)
+static int snd_smdk_probe(struct platform_device *pdev)
 {
        int ret = 0;
 
@@ -173,7 +173,7 @@ static int __devinit snd_smdk_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit snd_smdk_remove(struct platform_device *pdev)
+static int snd_smdk_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&smdk_pcm);
        platform_set_drvdata(pdev, NULL);
@@ -186,7 +186,7 @@ static struct platform_driver snd_smdk_driver = {
                .name = "samsung-smdk-pcm",
        },
        .probe = snd_smdk_probe,
-       .remove = __devexit_p(snd_smdk_remove),
+       .remove = snd_smdk_remove,
 };
 
 module_platform_driver(snd_smdk_driver);
index 48dd4dd9ee08dc7f51c6e523e633f52e922307fb..b0d0ab8bff5ae8299628cd1aec8d229af4a73af6 100644 (file)
@@ -127,7 +127,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Pri_Dai",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8994-aif1",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "wm8994-codec",
                .init = smdk_wm8994_init_paiftx,
                .ops = &smdk_ops,
@@ -136,7 +136,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Sec_Dai",
                .cpu_dai_name = "samsung-i2s.4",
                .codec_dai_name = "wm8994-aif1",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.4",
                .codec_name = "wm8994-codec",
                .ops = &smdk_ops,
        },
@@ -150,7 +150,7 @@ static struct snd_soc_card smdk = {
 };
 
 
-static int __devinit smdk_audio_probe(struct platform_device *pdev)
+static int smdk_audio_probe(struct platform_device *pdev)
 {
        int ret;
        struct snd_soc_card *card = &smdk;
@@ -164,7 +164,7 @@ static int __devinit smdk_audio_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit smdk_audio_remove(struct platform_device *pdev)
+static int smdk_audio_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -179,7 +179,7 @@ static struct platform_driver smdk_audio_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = smdk_audio_probe,
-       .remove         = __devexit_p(smdk_audio_remove),
+       .remove         = smdk_audio_remove,
 };
 
 module_platform_driver(smdk_audio_driver);
index 77ecba9351193c0ad2a8e6c6951449192e7bf3d2..3688a32000a2bc752122958abdd4818cfb7d7046 100644 (file)
@@ -116,7 +116,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .stream_name = "Primary PCM",
                .cpu_dai_name = "samsung-pcm.0",
                .codec_dai_name = "wm8994-aif1",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-pcm.0",
                .codec_name = "wm8994-codec",
                .ops = &smdk_wm8994_pcm_ops,
        },
@@ -129,7 +129,7 @@ static struct snd_soc_card smdk_pcm = {
        .num_links = 1,
 };
 
-static int __devinit snd_smdk_probe(struct platform_device *pdev)
+static int snd_smdk_probe(struct platform_device *pdev)
 {
        int ret = 0;
 
@@ -143,7 +143,7 @@ static int __devinit snd_smdk_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit snd_smdk_remove(struct platform_device *pdev)
+static int snd_smdk_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_card(&smdk_pcm);
        platform_set_drvdata(pdev, NULL);
@@ -156,7 +156,7 @@ static struct platform_driver snd_smdk_driver = {
                .name = "samsung-smdk-pcm",
        },
        .probe = snd_smdk_probe,
-       .remove = __devexit_p(snd_smdk_remove),
+       .remove = snd_smdk_remove,
 };
 
 module_platform_driver(snd_smdk_driver);
index 55b2ca7f3290a624d1b63145eb5997eafa770e7e..0d20e4ed27aacd4bf4ce989ad0eada0a25191765 100644 (file)
@@ -42,7 +42,7 @@ static struct snd_soc_card smdk;
 static struct snd_soc_dai_link smdk_dai = {
        .name = "AC97",
        .stream_name = "AC97 PCM",
-       .platform_name = "samsung-audio",
+       .platform_name = "samsung-ac97",
        .cpu_dai_name = "samsung-ac97",
        .codec_dai_name = "wm9713-hifi",
        .codec_name = "wm9713-codec",
index bc24c7af02b2e23ff57342b1901841c879198fd1..5008e5bd6ed8072c62a0b9feb34f136497801b50 100644 (file)
@@ -357,7 +357,7 @@ static struct snd_soc_dai_driver samsung_spdif_dai = {
        .resume = spdif_resume,
 };
 
-static __devinit int spdif_probe(struct platform_device *pdev)
+static int spdif_probe(struct platform_device *pdev)
 {
        struct s3c_audio_pdata *spdif_pdata;
        struct resource *mem_res, *dma_res;
@@ -397,7 +397,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err0;
        }
-       clk_enable(spdif->pclk);
+       clk_prepare_enable(spdif->pclk);
 
        spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
        if (IS_ERR(spdif->sclk)) {
@@ -405,7 +405,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err1;
        }
-       clk_enable(spdif->sclk);
+       clk_prepare_enable(spdif->sclk);
 
        /* Request S/PDIF Register's memory region */
        if (!request_mem_region(mem_res->start,
@@ -437,27 +437,35 @@ static __devinit int spdif_probe(struct platform_device *pdev)
 
        spdif->dma_playback = &spdif_stereo_out;
 
-       return 0;
+       ret = asoc_dma_platform_register(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register DMA: %d\n", ret);
+               goto err5;
+       }
 
+       return 0;
+err5:
+       snd_soc_unregister_dai(&pdev->dev);
 err4:
        iounmap(spdif->regs);
 err3:
        release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       clk_disable(spdif->sclk);
+       clk_disable_unprepare(spdif->sclk);
        clk_put(spdif->sclk);
 err1:
-       clk_disable(spdif->pclk);
+       clk_disable_unprepare(spdif->pclk);
        clk_put(spdif->pclk);
 err0:
        return ret;
 }
 
-static __devexit int spdif_remove(struct platform_device *pdev)
+static int spdif_remove(struct platform_device *pdev)
 {
        struct samsung_spdif_info *spdif = &spdif_info;
        struct resource *mem_res;
 
+       asoc_dma_platform_unregister(&pdev->dev);
        snd_soc_unregister_dai(&pdev->dev);
 
        iounmap(spdif->regs);
@@ -466,9 +474,9 @@ static __devexit int spdif_remove(struct platform_device *pdev)
        if (mem_res)
                release_mem_region(mem_res->start, resource_size(mem_res));
 
-       clk_disable(spdif->sclk);
+       clk_disable_unprepare(spdif->sclk);
        clk_put(spdif->sclk);
-       clk_disable(spdif->pclk);
+       clk_disable_unprepare(spdif->pclk);
        clk_put(spdif->pclk);
 
        return 0;
@@ -476,7 +484,7 @@ static __devexit int spdif_remove(struct platform_device *pdev)
 
 static struct platform_driver samsung_spdif_driver = {
        .probe  = spdif_probe,
-       .remove = __devexit_p(spdif_remove),
+       .remove = spdif_remove,
        .driver = {
                .name   = "samsung-spdif",
                .owner  = THIS_MODULE,
index c7e1c28528a4a6861593539a30afa1e41de30dd6..57df90d6b7c1bfdedbb5705fc0b2b0fef47d70d4 100644 (file)
@@ -198,7 +198,7 @@ static struct snd_soc_dai_link speyside_dai[] = {
                .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm0010-sdi1",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "spi0.0",
                .init = speyside_wm0010_init,
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
@@ -320,7 +320,7 @@ static struct snd_soc_card speyside = {
        .late_probe = speyside_late_probe,
 };
 
-static __devinit int speyside_probe(struct platform_device *pdev)
+static int speyside_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &speyside;
        int ret;
@@ -337,7 +337,7 @@ static __devinit int speyside_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit speyside_remove(struct platform_device *pdev)
+static int speyside_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -353,7 +353,7 @@ static struct platform_driver speyside_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = speyside_probe,
-       .remove = __devexit_p(speyside_remove),
+       .remove = speyside_remove,
 };
 
 module_platform_driver(speyside_driver);
index 9199649bf78628db3bab47a61f1fb02ffa2e4902..f21ff608a8199dd09f70b19b0bf92070a86fd28f 100644 (file)
@@ -110,7 +110,7 @@ static struct snd_soc_dai_link tobermory_dai[] = {
                .stream_name = "CPU",
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8962",
-               .platform_name = "samsung-audio",
+               .platform_name = "samsung-i2s.0",
                .codec_name = "wm8962.1-001a",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
@@ -214,7 +214,7 @@ static struct snd_soc_card tobermory = {
        .late_probe = tobermory_late_probe,
 };
 
-static __devinit int tobermory_probe(struct platform_device *pdev)
+static int tobermory_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &tobermory;
        int ret;
@@ -231,7 +231,7 @@ static __devinit int tobermory_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tobermory_remove(struct platform_device *pdev)
+static int tobermory_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -247,7 +247,7 @@ static struct platform_driver tobermory_driver = {
                .pm = &snd_soc_pm_ops,
        },
        .probe = tobermory_probe,
-       .remove = __devexit_p(tobermory_remove),
+       .remove = tobermory_remove,
 };
 
 module_platform_driver(tobermory_driver);
index 7da20186b19e63bdf7efe6372a33b41190e82a2f..19eff8fc4fdddda4a8ca47972a8c9700c7ea0af1 100644 (file)
@@ -348,12 +348,12 @@ static struct snd_soc_platform sh7760_soc_platform = {
        .pcm_free       = camelot_pcm_free,
 };
 
-static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev)
+static int sh7760_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform);
 }
 
-static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev)
+static int sh7760_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -366,7 +366,7 @@ static struct platform_driver sh7760_pcm_driver = {
        },
 
        .probe = sh7760_soc_platform_probe,
-       .remove = __devexit_p(sh7760_soc_platform_remove),
+       .remove = sh7760_soc_platform_remove,
 };
 
 module_platform_driver(sh7760_pcm_driver);
index 9d7f30774a44d9524cb71f6697fc0ce96825295c..a606d0f93d1cea4db2e88f47e8ba0d94b36aa59f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/workqueue.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 #include <sound/sh_fsi.h>
 
 /* PortA/PortB register */
@@ -188,6 +189,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
  *             --> go to codecs
  */
 
+/*
+ *     FSI clock
+ *
+ * FSIxCLK [CPG] (ick) ------->        |
+ *                             |-> FSI_DIV (div)-> FSI2
+ * FSIxCK [external] (xck) --->        |
+ */
+
 /*
  *             struct
  */
@@ -228,6 +237,20 @@ struct fsi_stream {
        dma_addr_t              dma;
 };
 
+struct fsi_clk {
+       /* see [FSI clock] */
+       struct clk *own;
+       struct clk *xck;
+       struct clk *ick;
+       struct clk *div;
+       int (*set_rate)(struct device *dev,
+                       struct fsi_priv *fsi,
+                       unsigned long rate);
+
+       unsigned long rate;
+       unsigned int count;
+};
+
 struct fsi_priv {
        void __iomem *base;
        struct fsi_master *master;
@@ -236,11 +259,17 @@ struct fsi_priv {
        struct fsi_stream playback;
        struct fsi_stream capture;
 
+       struct fsi_clk clock;
+
        u32 fmt;
 
        int chan_num:16;
        int clk_master:1;
+       int clk_cpg:1;
        int spdif:1;
+       int enable_stream:1;
+       int bit_clk_inv:1;
+       int lr_clk_inv:1;
 
        long rate;
 };
@@ -370,6 +399,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
        return fsi->spdif;
 }
 
+static int fsi_is_enable_stream(struct fsi_priv *fsi)
+{
+       return fsi->enable_stream;
+}
+
 static int fsi_is_play(struct snd_pcm_substream *substream)
 {
        return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
@@ -717,14 +751,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
 /*
  *             clock function
  */
+static int fsi_clk_init(struct device *dev,
+                       struct fsi_priv *fsi,
+                       int xck,
+                       int ick,
+                       int div,
+                       int (*set_rate)(struct device *dev,
+                                       struct fsi_priv *fsi,
+                                       unsigned long rate))
+{
+       struct fsi_clk *clock = &fsi->clock;
+       int is_porta = fsi_is_port_a(fsi);
+
+       clock->xck      = NULL;
+       clock->ick      = NULL;
+       clock->div      = NULL;
+       clock->rate     = 0;
+       clock->count    = 0;
+       clock->set_rate = set_rate;
+
+       clock->own = devm_clk_get(dev, NULL);
+       if (IS_ERR(clock->own))
+               return -EINVAL;
+
+       /* external clock */
+       if (xck) {
+               clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb");
+               if (IS_ERR(clock->xck)) {
+                       dev_err(dev, "can't get xck clock\n");
+                       return -EINVAL;
+               }
+               if (clock->xck == clock->own) {
+                       dev_err(dev, "cpu doesn't support xck clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* FSIACLK/FSIBCLK */
+       if (ick) {
+               clock->ick = devm_clk_get(dev,  is_porta ? "icka" : "ickb");
+               if (IS_ERR(clock->ick)) {
+                       dev_err(dev, "can't get ick clock\n");
+                       return -EINVAL;
+               }
+               if (clock->ick == clock->own) {
+                       dev_err(dev, "cpu doesn't support ick clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* FSI-DIV */
+       if (div) {
+               clock->div = devm_clk_get(dev,  is_porta ? "diva" : "divb");
+               if (IS_ERR(clock->div)) {
+                       dev_err(dev, "can't get div clock\n");
+                       return -EINVAL;
+               }
+               if (clock->div == clock->own) {
+                       dev_err(dev, "cpu doens't support div clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
+static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
+{
+       fsi->clock.rate = rate;
+}
+
+static int fsi_clk_is_valid(struct fsi_priv *fsi)
+{
+       return  fsi->clock.set_rate &&
+               fsi->clock.rate;
+}
+
+static int fsi_clk_enable(struct device *dev,
+                         struct fsi_priv *fsi,
+                         unsigned long rate)
+{
+       struct fsi_clk *clock = &fsi->clock;
+       int ret = -EINVAL;
+
+       if (!fsi_clk_is_valid(fsi))
+               return ret;
+
+       if (0 == clock->count) {
+               ret = clock->set_rate(dev, fsi, rate);
+               if (ret < 0) {
+                       fsi_clk_invalid(fsi);
+                       return ret;
+               }
+
+               if (clock->xck)
+                       clk_enable(clock->xck);
+               if (clock->ick)
+                       clk_enable(clock->ick);
+               if (clock->div)
+                       clk_enable(clock->div);
+
+               clock->count++;
+       }
+
+       return ret;
+}
+
+static int fsi_clk_disable(struct device *dev,
+                           struct fsi_priv *fsi)
+{
+       struct fsi_clk *clock = &fsi->clock;
+
+       if (!fsi_clk_is_valid(fsi))
+               return -EINVAL;
+
+       if (1 == clock->count--) {
+               if (clock->xck)
+                       clk_disable(clock->xck);
+               if (clock->ick)
+                       clk_disable(clock->ick);
+               if (clock->div)
+                       clk_disable(clock->div);
+       }
+
+       return 0;
+}
+
+static int fsi_clk_set_ackbpf(struct device *dev,
+                             struct fsi_priv *fsi,
+                             int ackmd, int bpfmd)
+{
+       u32 data = 0;
+
+       /* check ackmd/bpfmd relationship */
+       if (bpfmd > ackmd) {
+               dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd);
+               return -EINVAL;
+       }
+
+       /*  ACKMD */
+       switch (ackmd) {
+       case 512:
+               data |= (0x0 << 12);
+               break;
+       case 256:
+               data |= (0x1 << 12);
+               break;
+       case 128:
+               data |= (0x2 << 12);
+               break;
+       case 64:
+               data |= (0x3 << 12);
+               break;
+       case 32:
+               data |= (0x4 << 12);
+               break;
+       default:
+               dev_err(dev, "unsupported ackmd (%d)\n", ackmd);
+               return -EINVAL;
+       }
+
+       /* BPFMD */
+       switch (bpfmd) {
+       case 32:
+               data |= (0x0 << 8);
+               break;
+       case 64:
+               data |= (0x1 << 8);
+               break;
+       case 128:
+               data |= (0x2 << 8);
+               break;
+       case 256:
+               data |= (0x3 << 8);
+               break;
+       case 512:
+               data |= (0x4 << 8);
+               break;
+       case 16:
+               data |= (0x7 << 8);
+               break;
+       default:
+               dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd);
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd);
+
+       fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
+       udelay(10);
+
+       return 0;
+}
+
+static int fsi_clk_set_rate_external(struct device *dev,
+                                    struct fsi_priv *fsi,
+                                    unsigned long rate)
+{
+       struct clk *xck = fsi->clock.xck;
+       struct clk *ick = fsi->clock.ick;
+       unsigned long xrate;
+       int ackmd, bpfmd;
+       int ret = 0;
+
+       /* check clock rate */
+       xrate = clk_get_rate(xck);
+       if (xrate % rate) {
+               dev_err(dev, "unsupported clock rate\n");
+               return -EINVAL;
+       }
+
+       clk_set_parent(ick, xck);
+       clk_set_rate(ick, xrate);
+
+       bpfmd = fsi->chan_num * 32;
+       ackmd = xrate / rate;
+
+       dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate);
+
+       ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+       if (ret < 0)
+               dev_err(dev, "%s failed", __func__);
+
+       return ret;
+}
+
+static int fsi_clk_set_rate_cpg(struct device *dev,
+                               struct fsi_priv *fsi,
+                               unsigned long rate)
+{
+       struct clk *ick = fsi->clock.ick;
+       struct clk *div = fsi->clock.div;
+       unsigned long target = 0; /* 12288000 or 11289600 */
+       unsigned long actual, cout;
+       unsigned long diff, min;
+       unsigned long best_cout, best_act;
+       int adj;
+       int ackmd, bpfmd;
+       int ret = -EINVAL;
+
+       if (!(12288000 % rate))
+               target = 12288000;
+       if (!(11289600 % rate))
+               target = 11289600;
+       if (!target) {
+               dev_err(dev, "unsupported rate\n");
+               return ret;
+       }
+
+       bpfmd = fsi->chan_num * 32;
+       ackmd = target / rate;
+       ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+       if (ret < 0) {
+               dev_err(dev, "%s failed", __func__);
+               return ret;
+       }
+
+       /*
+        * The clock flow is
+        *
+        * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec]
+        *
+        * But, it needs to find best match of CPG and FSI_DIV
+        * combination, since it is difficult to generate correct
+        * frequency of audio clock from ick clock only.
+        * Because ick is created from its parent clock.
+        *
+        * target       = rate x [512/256/128/64]fs
+        * cout         = round(target x adjustment)
+        * actual       = cout / adjustment (by FSI-DIV) ~= target
+        * audio        = actual
+        */
+       min = ~0;
+       best_cout = 0;
+       best_act = 0;
+       for (adj = 1; adj < 0xffff; adj++) {
+
+               cout = target * adj;
+               if (cout > 100000000) /* max clock = 100MHz */
+                       break;
+
+               /* cout/actual audio clock */
+               cout    = clk_round_rate(ick, cout);
+               actual  = cout / adj;
+
+               /* find best frequency */
+               diff = abs(actual - target);
+               if (diff < min) {
+                       min             = diff;
+                       best_cout       = cout;
+                       best_act        = actual;
+               }
+       }
+
+       ret = clk_set_rate(ick, best_cout);
+       if (ret < 0) {
+               dev_err(dev, "ick clock failed\n");
+               return -EIO;
+       }
+
+       ret = clk_set_rate(div, clk_round_rate(div, best_act));
+       if (ret < 0) {
+               dev_err(dev, "div clock failed\n");
+               return -EIO;
+       }
+
+       dev_dbg(dev, "ick/div = %ld/%ld\n",
+               clk_get_rate(ick), clk_get_rate(div));
+
+       return ret;
+}
+
 static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
                              long rate, int enable)
 {
        set_rate_func set_rate = fsi_get_info_set_rate(fsi);
        int ret;
 
-       if (!set_rate)
-               return 0;
+       /*
+        * CAUTION
+        *
+        * set_rate will be deleted
+        */
+       if (!set_rate) {
+               if (enable)
+                       return fsi_clk_enable(dev, fsi, rate);
+               else
+                       return fsi_clk_disable(dev, fsi);
+       }
 
        ret = set_rate(dev, rate, enable);
        if (ret < 0) /* error */
@@ -792,10 +1147,9 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
  */
 static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
 {
-       u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
        int i;
 
-       if (enable_stream) {
+       if (fsi_is_enable_stream(fsi)) {
                /*
                 * stream mode
                 * see
@@ -953,8 +1307,6 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
 
 static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
-
        /*
         * we can use 16bit stream mode
         * when "playback" and "16bit data"
@@ -962,7 +1314,7 @@ static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
         * see
         *      fsi_pio_push16()
         */
-       if (enable_stream)
+       if (fsi_is_enable_stream(fsi))
                io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
                                 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
        else
@@ -1296,6 +1648,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
 
        /* clock inversion (CKG2) */
        data = 0;
+       if (fsi->bit_clk_inv)
+               data |= (1 << 0);
+       if (fsi->lr_clk_inv)
+               data |= (1 << 4);
+       if (fsi_is_clk_master(fsi))
+               data <<= 8;
+       /* FIXME
+        *
+        * SH_FSI_xxx_INV style will be removed
+        */
        if (SH_FSI_LRM_INV & flags)
                data |= 1 << 12;
        if (SH_FSI_BRM_INV & flags)
@@ -1334,14 +1696,21 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
        /* fifo init */
        fsi_fifo_init(fsi, io, dev);
 
+       /* start master clock */
+       if (fsi_is_clk_master(fsi))
+               return fsi_set_master_clk(dev, fsi, fsi->rate, 1);
+
        return 0;
 }
 
-static void fsi_hw_shutdown(struct fsi_priv *fsi,
+static int fsi_hw_shutdown(struct fsi_priv *fsi,
                            struct device *dev)
 {
+       /* stop master clock */
        if (fsi_is_clk_master(fsi))
-               fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+               return fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+
+       return 0;
 }
 
 static int fsi_dai_startup(struct snd_pcm_substream *substream,
@@ -1349,6 +1718,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
 
+       fsi_clk_invalid(fsi);
        fsi->rate = 0;
 
        return 0;
@@ -1359,6 +1729,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
 
+       fsi_clk_invalid(fsi);
        fsi->rate = 0;
 }
 
@@ -1372,13 +1743,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                fsi_stream_init(fsi, io, substream);
-               fsi_hw_startup(fsi, io, dai->dev);
-               ret = fsi_stream_transfer(io);
-               if (0 == ret)
+               if (!ret)
+                       ret = fsi_hw_startup(fsi, io, dai->dev);
+               if (!ret)
+                       ret = fsi_stream_transfer(io);
+               if (!ret)
                        fsi_stream_start(fsi, io);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
-               fsi_hw_shutdown(fsi, dai->dev);
+               if (!ret)
+                       ret = fsi_hw_shutdown(fsi, dai->dev);
                fsi_stream_stop(fsi, io);
                fsi_stream_quit(fsi, io);
                break;
@@ -1414,7 +1788,6 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
 
        fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
        fsi->chan_num = 2;
-       fsi->spdif = 1;
 
        return 0;
 }
@@ -1423,7 +1796,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
        set_rate_func set_rate = fsi_get_info_set_rate(fsi);
-       u32 flags = fsi_get_info_flags(fsi);
        int ret;
 
        /* set master/slave audio interface */
@@ -1437,23 +1809,50 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
-       if (fsi_is_clk_master(fsi) && !set_rate) {
-               dev_err(dai->dev, "platform doesn't have set_rate\n");
-               return -EINVAL;
-       }
-
-       /* set format */
-       switch (flags & SH_FSI_FMT_MASK) {
-       case SH_FSI_FMT_DAI:
-               ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+       /* set clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_IF:
+               fsi->bit_clk_inv = 0;
+               fsi->lr_clk_inv = 1;
                break;
-       case SH_FSI_FMT_SPDIF:
-               ret = fsi_set_fmt_spdif(fsi);
+       case SND_SOC_DAIFMT_IB_NF:
+               fsi->bit_clk_inv = 1;
+               fsi->lr_clk_inv = 0;
                break;
+       case SND_SOC_DAIFMT_IB_IF:
+               fsi->bit_clk_inv = 1;
+               fsi->lr_clk_inv = 1;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
        default:
-               ret = -EINVAL;
+               fsi->bit_clk_inv = 0;
+               fsi->lr_clk_inv = 0;
+               break;
+       }
+
+       if (fsi_is_clk_master(fsi)) {
+               /*
+                * CAUTION
+                *
+                * set_rate will be deleted
+                */
+               if (set_rate)
+                       dev_warn(dai->dev, "set_rate will be removed soon\n");
+
+               if (fsi->clk_cpg)
+                       fsi_clk_init(dai->dev, fsi, 0, 1, 1,
+                                    fsi_clk_set_rate_cpg);
+               else
+                       fsi_clk_init(dai->dev, fsi, 1, 1, 0,
+                                    fsi_clk_set_rate_external);
        }
 
+       /* set format */
+       if (fsi_is_spdif(fsi))
+               ret = fsi_set_fmt_spdif(fsi);
+       else
+               ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+
        return ret;
 }
 
@@ -1462,19 +1861,13 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       long rate = params_rate(params);
-       int ret;
 
-       if (!fsi_is_clk_master(fsi))
-               return 0;
-
-       ret = fsi_set_master_clk(dai->dev, fsi, rate, 1);
-       if (ret < 0)
-               return ret;
-
-       fsi->rate = rate;
+       if (fsi_is_clk_master(fsi)) {
+               fsi->rate = params_rate(params);
+               fsi_clk_valid(fsi, fsi->rate);
+       }
 
-       return ret;
+       return 0;
 }
 
 static const struct snd_soc_dai_ops fsi_dai_ops = {
@@ -1498,7 +1891,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
        .rates                  = FSI_RATES,
        .rate_min               = 8000,
        .rate_max               = 192000,
-       .channels_min           = 1,
+       .channels_min           = 2,
        .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
@@ -1586,14 +1979,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1602,14 +1995,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1624,15 +2017,29 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
 /*
  *             platform function
  */
-static void fsi_handler_init(struct fsi_priv *fsi)
+static void fsi_port_info_init(struct fsi_priv *fsi,
+                              struct sh_fsi_port_info *info)
+{
+       if (info->flags & SH_FSI_FMT_SPDIF)
+               fsi->spdif = 1;
+
+       if (info->flags & SH_FSI_CLK_CPG)
+               fsi->clk_cpg = 1;
+
+       if (info->flags & SH_FSI_ENABLE_STREAM_MODE)
+               fsi->enable_stream = 1;
+}
+
+static void fsi_handler_init(struct fsi_priv *fsi,
+                            struct sh_fsi_port_info *info)
 {
        fsi->playback.handler   = &fsi_pio_push_handler; /* default PIO */
        fsi->playback.priv      = fsi;
        fsi->capture.handler    = &fsi_pio_pop_handler;  /* default PIO */
        fsi->capture.priv       = fsi;
 
-       if (fsi->info->tx_id) {
-               fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
+       if (info->tx_id) {
+               fsi->playback.slave.shdma_slave.slave_id = info->tx_id;
                fsi->playback.handler = &fsi_dma_push_handler;
        }
 }
@@ -1642,10 +2049,16 @@ static int fsi_probe(struct platform_device *pdev)
        struct fsi_master *master;
        const struct platform_device_id *id_entry;
        struct sh_fsi_platform_info *info = pdev->dev.platform_data;
+       struct sh_fsi_port_info nul_info, *pinfo;
+       struct fsi_priv *fsi;
        struct resource *res;
        unsigned int irq;
        int ret;
 
+       nul_info.flags  = 0;
+       nul_info.tx_id  = 0;
+       nul_info.rx_id  = 0;
+
        id_entry = pdev->id_entry;
        if (!id_entry) {
                dev_err(&pdev->dev, "unknown fsi device\n");
@@ -1678,22 +2091,28 @@ static int fsi_probe(struct platform_device *pdev)
        spin_lock_init(&master->lock);
 
        /* FSI A setting */
-       master->fsia.base       = master->base;
-       master->fsia.master     = master;
-       master->fsia.info       = &info->port_a;
-       fsi_handler_init(&master->fsia);
-       ret = fsi_stream_probe(&master->fsia, &pdev->dev);
+       pinfo           = (info) ? &info->port_a : &nul_info;
+       fsi             = &master->fsia;
+       fsi->base       = master->base;
+       fsi->master     = master;
+       fsi->info       = pinfo;
+       fsi_port_info_init(fsi, pinfo);
+       fsi_handler_init(fsi, pinfo);
+       ret = fsi_stream_probe(fsi, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "FSIA stream probe failed\n");
                return ret;
        }
 
        /* FSI B setting */
-       master->fsib.base       = master->base + 0x40;
-       master->fsib.master     = master;
-       master->fsib.info       = &info->port_b;
-       fsi_handler_init(&master->fsib);
-       ret = fsi_stream_probe(&master->fsib, &pdev->dev);
+       pinfo           = (info) ? &info->port_b : &nul_info;
+       fsi             = &master->fsib;
+       fsi->base       = master->base + 0x40;
+       fsi->master     = master;
+       fsi->info       = pinfo;
+       fsi_port_info_init(fsi, pinfo);
+       fsi_handler_init(fsi, pinfo);
+       ret = fsi_stream_probe(fsi, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "FSIB stream probe failed\n");
                goto exit_fsia;
@@ -1702,7 +2121,7 @@ static int fsi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        dev_set_drvdata(&pdev->dev, master);
 
-       ret = request_irq(irq, &fsi_interrupt, 0,
+       ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0,
                          id_entry->name, master);
        if (ret) {
                dev_err(&pdev->dev, "irq request err\n");
@@ -1712,7 +2131,7 @@ static int fsi_probe(struct platform_device *pdev)
        ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
        if (ret < 0) {
                dev_err(&pdev->dev, "cannot snd soc register\n");
-               goto exit_free_irq;
+               goto exit_fsib;
        }
 
        ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
@@ -1726,8 +2145,6 @@ static int fsi_probe(struct platform_device *pdev)
 
 exit_snd_soc:
        snd_soc_unregister_platform(&pdev->dev);
-exit_free_irq:
-       free_irq(irq, master);
 exit_fsib:
        pm_runtime_disable(&pdev->dev);
        fsi_stream_remove(&master->fsib);
@@ -1743,7 +2160,6 @@ static int fsi_remove(struct platform_device *pdev)
 
        master = dev_get_drvdata(&pdev->dev);
 
-       free_irq(master->irq, master);
        pm_runtime_disable(&pdev->dev);
 
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
@@ -1774,10 +2190,6 @@ static void __fsi_resume(struct fsi_priv *fsi,
                return;
 
        fsi_hw_startup(fsi, io, dev);
-
-       if (fsi_is_clk_master(fsi) && fsi->rate)
-               fsi_set_master_clk(dev, fsi, fsi->rate, 1);
-
        fsi_stream_start(fsi, io);
 }
 
index 3474d7befe5ae537fc6e9862050f5e81dcce9daa..4cc2d64ef4765a68f458da65caedce29d8c86641 100644 (file)
@@ -310,13 +310,13 @@ static struct snd_soc_dai_driver sh4_hac_dai[] = {
 #endif
 };
 
-static int __devinit hac_soc_platform_probe(struct platform_device *pdev)
+static int hac_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_dais(&pdev->dev, sh4_hac_dai,
                        ARRAY_SIZE(sh4_hac_dai));
 }
 
-static int __devexit hac_soc_platform_remove(struct platform_device *pdev)
+static int hac_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai));
        return 0;
@@ -329,7 +329,7 @@ static struct platform_driver hac_pcm_driver = {
        },
 
        .probe = hac_soc_platform_probe,
-       .remove = __devexit_p(hac_soc_platform_remove),
+       .remove = hac_soc_platform_remove,
 };
 
 module_platform_driver(hac_pcm_driver);
index 52d4c17b12325ac079ed8b0cb65950c382290344..34facdc9e4acfd68594e3db561b2aca108235459 100644 (file)
@@ -726,7 +726,7 @@ static struct snd_soc_dai_driver siu_i2s_dai = {
        .ops = &siu_dai_ops,
 };
 
-static int __devinit siu_probe(struct platform_device *pdev)
+static int siu_probe(struct platform_device *pdev)
 {
        const struct firmware *fw_entry;
        struct resource *res, *region;
@@ -815,7 +815,7 @@ ereqfw:
        return ret;
 }
 
-static int __devexit siu_remove(struct platform_device *pdev)
+static int siu_remove(struct platform_device *pdev)
 {
        struct siu_info *info = dev_get_drvdata(&pdev->dev);
        struct resource *res;
@@ -843,7 +843,7 @@ static struct platform_driver siu_driver = {
                .name   = "siu-pcm-audio",
        },
        .probe          = siu_probe,
-       .remove         = __devexit_p(siu_remove),
+       .remove         = siu_remove,
 };
 
 module_platform_driver(siu_driver);
index ff82b56a886093e43c5456b14592452478d5d4a2..c8e73a7039348e7818b15bacb95b1e6e6268b856 100644 (file)
@@ -379,13 +379,13 @@ static struct snd_soc_dai_driver sh4_ssi_dai[] = {
 #endif
 };
 
-static int __devinit sh4_soc_dai_probe(struct platform_device *pdev)
+static int sh4_soc_dai_probe(struct platform_device *pdev)
 {
        return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai,
                        ARRAY_SIZE(sh4_ssi_dai));
 }
 
-static int __devexit sh4_soc_dai_remove(struct platform_device *pdev)
+static int sh4_soc_dai_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
        return 0;
@@ -398,7 +398,7 @@ static struct platform_driver sh4_ssi_driver = {
        },
 
        .probe = sh4_soc_dai_probe,
-       .remove = __devexit_p(sh4_soc_dai_remove),
+       .remove = sh4_soc_dai_remove,
 };
 
 module_platform_driver(sh4_ssi_driver);
index 9d56f0218f41688576fec511db272e6484480bdb..e72f55428f0ba8ece44cdea8f6f720efc5c1d868 100644 (file)
@@ -88,7 +88,7 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
                ret = snd_soc_write(codec, i, val);
                if (ret)
                        return ret;
-               dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
+               dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n",
                        i, val);
        }
        return 0;
@@ -156,7 +156,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
 
        /* Fall back to flat compression */
        if (i == ARRAY_SIZE(cache_types)) {
-               dev_warn(codec->dev, "Could not match compress type: %d\n",
+               dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n",
                         codec->compress_type);
                i = 0;
        }
@@ -166,7 +166,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
 
        if (codec->cache_ops->init) {
                if (codec->cache_ops->name)
-                       dev_dbg(codec->dev, "Initializing %s cache for %s codec\n",
+                       dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n",
                                codec->cache_ops->name, codec->name);
                return codec->cache_ops->init(codec);
        }
@@ -181,7 +181,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec)
 {
        if (codec->cache_ops && codec->cache_ops->exit) {
                if (codec->cache_ops->name)
-                       dev_dbg(codec->dev, "Destroying %s cache for %s codec\n",
+                       dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n",
                                codec->cache_ops->name, codec->name);
                return codec->cache_ops->exit(codec);
        }
@@ -265,7 +265,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec)
                name = "unknown";
 
        if (codec->cache_ops->name)
-               dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
+               dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n",
                        codec->cache_ops->name, codec->name);
        trace_snd_soc_cache_sync(codec, name, "start");
        ret = codec->cache_ops->sync(codec);
index 10d21be383f6d511221094a1fa3a9a3b9657a464..9c768bcb98a6460640577688b2f7f9d71d5a8106 100644 (file)
@@ -271,7 +271,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
        codec->debugfs_codec_root = debugfs_create_dir(codec->name,
                                                       debugfs_card_root);
        if (!codec->debugfs_codec_root) {
-               dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
+               dev_warn(codec->dev, "ASoC: Failed to create codec debugfs"
+                       " directory\n");
                return;
        }
 
@@ -284,7 +285,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
                                                 codec->debugfs_codec_root,
                                                 codec, &codec_reg_fops);
        if (!codec->debugfs_reg)
-               dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
+               dev_warn(codec->dev, "ASoC: Failed to create codec register"
+                       " debugfs file\n");
 
        snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
 }
@@ -302,7 +304,7 @@ static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
                                                       debugfs_card_root);
        if (!platform->debugfs_platform_root) {
                dev_warn(platform->dev,
-                       "Failed to create platform debugfs directory\n");
+                       "ASoC: Failed to create platform debugfs directory\n");
                return;
        }
 
@@ -430,7 +432,7 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
                                                    &card->pop_time);
        if (!card->debugfs_pop_time)
                dev_warn(card->dev,
-                      "Failed to create pop time debugfs file\n");
+                      "ASoC: Failed to create pop time debugfs file\n");
 }
 
 static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
@@ -475,7 +477,7 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
                        !strcmp(card->rtd[i].dai_link->name, dai_link))
                        return card->rtd[i].pcm->streams[stream].substream;
        }
-       dev_dbg(card->dev, "failed to find dai link %s\n", dai_link);
+       dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
@@ -489,7 +491,7 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
                if (!strcmp(card->rtd[i].dai_link->name, dai_link))
                        return &card->rtd[i];
        }
-       dev_dbg(card->dev, "failed to find rtd %s\n", dai_link);
+       dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
@@ -519,7 +521,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
                     codec->card->snd_card->number, 0, codec->name);
        err = device_register(&codec->ac97->dev);
        if (err < 0) {
-               snd_printk(KERN_ERR "Can't register ac97 bus\n");
+               dev_err(codec->dev, "ASoC: Can't register ac97 bus\n");
                codec->ac97->dev.bus = NULL;
                return err;
        }
@@ -628,7 +630,8 @@ int snd_soc_suspend(struct device *dev)
                                 */
                                if (codec->dapm.idle_bias_off) {
                                        dev_dbg(codec->dev,
-                                               "idle_bias_off CODEC on over suspend\n");
+                                               "ASoC: idle_bias_off CODEC on"
+                                               " over suspend\n");
                                        break;
                                }
                        case SND_SOC_BIAS_OFF:
@@ -639,7 +642,8 @@ int snd_soc_suspend(struct device *dev)
                                        regcache_mark_dirty(codec->control_data);
                                break;
                        default:
-                               dev_dbg(codec->dev, "CODEC is on over suspend\n");
+                               dev_dbg(codec->dev, "ASoC: CODEC is on"
+                                       " over suspend\n");
                                break;
                        }
                }
@@ -676,7 +680,7 @@ static void soc_resume_deferred(struct work_struct *work)
         * so userspace apps are blocked from touching us
         */
 
-       dev_dbg(card->dev, "starting resume work\n");
+       dev_dbg(card->dev, "ASoC: starting resume work\n");
 
        /* Bring us up into D2 so that DAPM starts enabling things */
        snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
@@ -708,7 +712,8 @@ static void soc_resume_deferred(struct work_struct *work)
                                codec->suspended = 0;
                                break;
                        default:
-                               dev_dbg(codec->dev, "CODEC was on over suspend\n");
+                               dev_dbg(codec->dev, "ASoC: CODEC was on over"
+                                       " suspend\n");
                                break;
                        }
                }
@@ -758,7 +763,7 @@ static void soc_resume_deferred(struct work_struct *work)
        if (card->resume_post)
                card->resume_post(card);
 
-       dev_dbg(card->dev, "resume work completed\n");
+       dev_dbg(card->dev, "ASoC: resume work completed\n");
 
        /* userspace can access us now we are back as we were before */
        snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
@@ -790,12 +795,12 @@ int snd_soc_resume(struct device *dev)
                ac97_control |= cpu_dai->driver->ac97_control;
        }
        if (ac97_control) {
-               dev_dbg(dev, "Resuming AC97 immediately\n");
+               dev_dbg(dev, "ASoC: Resuming AC97 immediately\n");
                soc_resume_deferred(&card->deferred_resume_work);
        } else {
-               dev_dbg(dev, "Scheduling resume work\n");
+               dev_dbg(dev, "ASoC: Scheduling resume work\n");
                if (!schedule_work(&card->deferred_resume_work))
-                       dev_err(dev, "resume work item may be lost\n");
+                       dev_err(dev, "ASoC: resume work item may be lost\n");
        }
 
        return 0;
@@ -818,7 +823,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
        struct snd_soc_dai *codec_dai, *cpu_dai;
        const char *platform_name;
 
-       dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
+       dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
 
        /* Find CPU DAI from registered DAIs*/
        list_for_each_entry(cpu_dai, &dai_list, list) {
@@ -836,7 +841,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
        }
 
        if (!rtd->cpu_dai) {
-               dev_err(card->dev, "CPU DAI %s not registered\n",
+               dev_err(card->dev, "ASoC: CPU DAI %s not registered\n",
                        dai_link->cpu_dai_name);
                return -EPROBE_DEFER;
        }
@@ -867,14 +872,14 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
                }
 
                if (!rtd->codec_dai) {
-                       dev_err(card->dev, "CODEC DAI %s not registered\n",
+                       dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
                                dai_link->codec_dai_name);
                        return -EPROBE_DEFER;
                }
        }
 
        if (!rtd->codec) {
-               dev_err(card->dev, "CODEC %s not registered\n",
+               dev_err(card->dev, "ASoC: CODEC %s not registered\n",
                        dai_link->codec_name);
                return -EPROBE_DEFER;
        }
@@ -898,7 +903,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
                rtd->platform = platform;
        }
        if (!rtd->platform) {
-               dev_err(card->dev, "platform %s not registered\n",
+               dev_err(card->dev, "ASoC: platform %s not registered\n",
                        dai_link->platform_name);
                return -EPROBE_DEFER;
        }
@@ -915,8 +920,8 @@ static int soc_remove_platform(struct snd_soc_platform *platform)
        if (platform->driver->remove) {
                ret = platform->driver->remove(platform);
                if (ret < 0)
-                       pr_err("asoc: failed to remove %s: %d\n",
-                               platform->name, ret);
+                       dev_err(platform->dev, "ASoC: failed to remove %d\n",
+                               ret);
        }
 
        /* Make sure all DAPM widgets are freed */
@@ -937,9 +942,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
        if (codec->driver->remove) {
                err = codec->driver->remove(codec);
                if (err < 0)
-                       dev_err(codec->dev,
-                               "asoc: failed to remove %s: %d\n",
-                               codec->name, err);
+                       dev_err(codec->dev, "ASoC: failed to remove %d\n", err);
        }
 
        /* Make sure all DAPM widgets are freed */
@@ -971,8 +974,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
                if (codec_dai->driver->remove) {
                        err = codec_dai->driver->remove(codec_dai);
                        if (err < 0)
-                               pr_err("asoc: failed to remove %s: %d\n",
-                                                       codec_dai->name, err);
+                               dev_err(codec_dai->dev,
+                                       "ASoC: failed to remove %s: %d\n",
+                                       codec_dai->name, err);
                }
                codec_dai->probed = 0;
                list_del(&codec_dai->card_list);
@@ -984,8 +988,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
                if (cpu_dai->driver->remove) {
                        err = cpu_dai->driver->remove(cpu_dai);
                        if (err < 0)
-                               pr_err("asoc: failed to remove %s: %d\n",
-                                                       cpu_dai->name, err);
+                               dev_err(cpu_dai->dev,
+                                       "ASoC: failed to remove %s: %d\n",
+                                       cpu_dai->name, err);
                }
                cpu_dai->probed = 0;
                list_del(&cpu_dai->card_list);
@@ -1099,8 +1104,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
                ret = driver->probe(codec);
                if (ret < 0) {
                        dev_err(codec->dev,
-                               "asoc: failed to probe CODEC %s: %d\n",
-                               codec->name, ret);
+                               "ASoC: failed to probe CODEC %d\n", ret);
                        goto err_probe;
                }
        }
@@ -1163,8 +1167,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
                ret = driver->probe(platform);
                if (ret < 0) {
                        dev_err(platform->dev,
-                               "asoc: failed to probe platform %s: %d\n",
-                               platform->name, ret);
+                               "ASoC: failed to probe platform %d\n", ret);
                        goto err_probe;
                }
        }
@@ -1229,7 +1232,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
        else if (dailess && aux_dev->init)
                ret = aux_dev->init(&codec->dapm);
        if (ret < 0) {
-               dev_err(card->dev, "asoc: failed to init %s: %d\n", name, ret);
+               dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret);
                return ret;
        }
        codec->name_prefix = temp;
@@ -1253,7 +1256,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
        ret = device_add(rtd->dev);
        if (ret < 0) {
                dev_err(card->dev,
-                       "asoc: failed to register runtime device: %d\n", ret);
+                       "ASoC: failed to register runtime device: %d\n", ret);
                return ret;
        }
        rtd->dev_registered = 1;
@@ -1262,14 +1265,13 @@ static int soc_post_component_init(struct snd_soc_card *card,
        ret = snd_soc_dapm_sys_add(rtd->dev);
        if (ret < 0)
                dev_err(codec->dev,
-                       "asoc: failed to add codec dapm sysfs entries: %d\n",
-                       ret);
+                       "ASoC: failed to add codec dapm sysfs entries: %d\n", ret);
 
        /* add codec sysfs entries */
        ret = device_create_file(rtd->dev, &dev_attr_codec_reg);
        if (ret < 0)
                dev_err(codec->dev,
-                       "asoc: failed to add codec sysfs files: %d\n", ret);
+                       "ASoC: failed to add codec sysfs files: %d\n", ret);
 
 #ifdef CONFIG_DEBUG_FS
        /* add DPCM sysfs entries */
@@ -1278,7 +1280,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
 
        ret = soc_dpcm_debugfs_add(rtd);
        if (ret < 0)
-               dev_err(rtd->dev, "asoc: failed to add dpcm sysfs entries: %d\n", ret);
+               dev_err(rtd->dev, "ASoC: failed to add dpcm sysfs entries: %d\n", ret);
 
 out:
 #endif
@@ -1333,7 +1335,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
        struct snd_soc_dapm_widget *play_w, *capture_w;
        int ret;
 
-       dev_dbg(card->dev, "probe %s dai link %d late %d\n",
+       dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
                        card->name, num, order);
 
        /* config components */
@@ -1359,8 +1361,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
                if (cpu_dai->driver->probe) {
                        ret = cpu_dai->driver->probe(cpu_dai);
                        if (ret < 0) {
-                               pr_err("asoc: failed to probe CPU DAI %s: %d\n",
-                                                       cpu_dai->name, ret);
+                               dev_err(cpu_dai->dev,
+                                       "ASoC: failed to probe CPU DAI %s: %d\n",
+                                       cpu_dai->name, ret);
                                module_put(cpu_dai->dev->driver->owner);
                                return ret;
                        }
@@ -1375,8 +1378,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
                if (codec_dai->driver->probe) {
                        ret = codec_dai->driver->probe(codec_dai);
                        if (ret < 0) {
-                               pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
-                                                       codec_dai->name, ret);
+                               dev_err(codec_dai->dev,
+                                       "ASoC: failed to probe CODEC DAI %s: %d\n",
+                                       codec_dai->name, ret);
                                return ret;
                        }
                }
@@ -1396,13 +1400,14 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 
        ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
        if (ret < 0)
-               pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
+               dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n",
+                       ret);
 
        if (cpu_dai->driver->compress_dai) {
                /*create compress_device"*/
                ret = soc_new_compress(rtd, num);
                if (ret < 0) {
-                       pr_err("asoc: can't create compress %s\n",
+                       dev_err(card->dev, "ASoC: can't create compress %s\n",
                                         dai_link->stream_name);
                        return ret;
                }
@@ -1412,7 +1417,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
                        /* create the pcm */
                        ret = soc_new_pcm(rtd, num);
                        if (ret < 0) {
-                               pr_err("asoc: can't create pcm %s :%d\n",
+                               dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
                                       dai_link->stream_name, ret);
                                return ret;
                        }
@@ -1424,7 +1429,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
                                ret = snd_soc_dapm_new_pcm(card, dai_link->params,
                                                   capture_w, play_w);
                                if (ret != 0) {
-                                       dev_err(card->dev, "Can't link %s to %s: %d\n",
+                                       dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
                                                play_w->name, capture_w->name, ret);
                                        return ret;
                                }
@@ -1436,7 +1441,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
                                ret = snd_soc_dapm_new_pcm(card, dai_link->params,
                                                   capture_w, play_w);
                                if (ret != 0) {
-                                       dev_err(card->dev, "Can't link %s to %s: %d\n",
+                                       dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
                                                play_w->name, capture_w->name, ret);
                                        return ret;
                                }
@@ -1473,7 +1478,8 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 
                ret = soc_ac97_dev_register(rtd->codec);
                if (ret < 0) {
-                       pr_err("asoc: AC97 device register failed:%d\n", ret);
+                       dev_err(rtd->codec->dev,
+                               "ASoC: AC97 device register failed: %d\n", ret);
                        return ret;
                }
 
@@ -1502,7 +1508,7 @@ static int soc_check_aux_dev(struct snd_soc_card *card, int num)
                        return 0;
        }
 
-       dev_err(card->dev, "%s not registered\n", aux_dev->codec_name);
+       dev_err(card->dev, "ASoC: %s not registered\n", aux_dev->codec_name);
 
        return -EPROBE_DEFER;
 }
@@ -1518,7 +1524,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
                if (!strcmp(codec->name, aux_dev->codec_name)) {
                        if (codec->probed) {
                                dev_err(codec->dev,
-                                       "asoc: codec already probed");
+                                       "ASoC: codec already probed");
                                ret = -EBUSY;
                                goto out;
                        }
@@ -1526,7 +1532,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
                }
        }
        /* codec not found */
-       dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
+       dev_err(card->dev, "ASoC: codec %s not found", aux_dev->codec_name);
        return -EPROBE_DEFER;
 
 found:
@@ -1569,8 +1575,8 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
                codec->compress_type = compress_type;
        ret = snd_soc_cache_init(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "Failed to set cache compression type: %d\n",
-                       ret);
+               dev_err(codec->dev, "ASoC: Failed to set cache compression"
+                       " type: %d\n", ret);
                return ret;
        }
        codec->cache_init = 1;
@@ -1626,8 +1632,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
                        card->owner, 0, &card->snd_card);
        if (ret < 0) {
-               pr_err("asoc: can't create sound card for card %s: %d\n",
-                       card->name, ret);
+               dev_err(card->dev, "ASoC: can't create sound card for"
+                       " card %s: %d\n", card->name, ret);
                goto base_error;
        }
        card->snd_card->dev = card->dev;
@@ -1663,8 +1669,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
                for (i = 0; i < card->num_links; i++) {
                        ret = soc_probe_link_components(card, i, order);
                        if (ret < 0) {
-                               pr_err("asoc: failed to instantiate card %s: %d\n",
-                                      card->name, ret);
+                               dev_err(card->dev,
+                                       "ASoC: failed to instantiate card %d\n",
+                                       ret);
                                goto probe_dai_err;
                        }
                }
@@ -1676,8 +1683,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
                for (i = 0; i < card->num_links; i++) {
                        ret = soc_probe_link_dais(card, i, order);
                        if (ret < 0) {
-                               pr_err("asoc: failed to instantiate card %s: %d\n",
-                                      card->name, ret);
+                               dev_err(card->dev,
+                                       "ASoC: failed to instantiate card %d\n",
+                                       ret);
                                goto probe_dai_err;
                        }
                }
@@ -1686,8 +1694,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        for (i = 0; i < card->num_aux_devs; i++) {
                ret = soc_probe_aux_dev(card, i);
                if (ret < 0) {
-                       pr_err("asoc: failed to add auxiliary devices %s: %d\n",
-                              card->name, ret);
+                       dev_err(card->dev,
+                               "ASoC: failed to add auxiliary devices %d\n",
+                               ret);
                        goto probe_aux_dev_err;
                }
        }
@@ -1712,7 +1721,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
                                                  dai_fmt);
                        if (ret != 0 && ret != -ENOTSUPP)
                                dev_warn(card->rtd[i].codec_dai->dev,
-                                        "Failed to set DAI format: %d\n",
+                                        "ASoC: Failed to set DAI format: %d\n",
                                         ret);
                }
 
@@ -1723,7 +1732,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
                                                  dai_fmt);
                        if (ret != 0 && ret != -ENOTSUPP)
                                dev_warn(card->rtd[i].cpu_dai->dev,
-                                        "Failed to set DAI format: %d\n",
+                                        "ASoC: Failed to set DAI format: %d\n",
                                         ret);
                } else if (dai_fmt) {
                        /* Flip the polarity for the "CPU" end */
@@ -1748,7 +1757,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
                                                  dai_fmt);
                        if (ret != 0 && ret != -ENOTSUPP)
                                dev_warn(card->rtd[i].cpu_dai->dev,
-                                        "Failed to set DAI format: %d\n",
+                                        "ASoC: Failed to set DAI format: %d\n",
                                         ret);
                }
        }
@@ -1775,7 +1784,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        if (card->late_probe) {
                ret = card->late_probe(card);
                if (ret < 0) {
-                       dev_err(card->dev, "%s late_probe() failed: %d\n",
+                       dev_err(card->dev, "ASoC: %s late_probe() failed: %d\n",
                                card->name, ret);
                        goto probe_aux_dev_err;
                }
@@ -1789,8 +1798,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 
        ret = snd_card_register(card->snd_card);
        if (ret < 0) {
-               pr_err("asoc: failed to register soundcard for %s: %d\n",
-                                                       card->name, ret);
+               dev_err(card->dev, "ASoC: failed to register soundcard %d\n",
+                               ret);
                goto probe_aux_dev_err;
        }
 
@@ -1799,8 +1808,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        for (i = 0; i < card->num_rtd; i++) {
                ret = soc_register_ac97_dai_link(&card->rtd[i]);
                if (ret < 0) {
-                       pr_err("asoc: failed to register AC97 %s: %d\n",
-                                                       card->name, ret);
+                       dev_err(card->dev, "ASoC: failed to register AC97:"
+                               " %d\n", ret);
                        while (--i >= 0)
                                soc_unregister_ac97_dai_link(card->rtd[i].codec);
                        goto probe_aux_dev_err;
@@ -1846,7 +1855,7 @@ static int soc_probe(struct platform_device *pdev)
                return -EINVAL;
 
        dev_warn(&pdev->dev,
-                "ASoC machine %s should use snd_soc_register_card()\n",
+                "ASoC: machine %s should use snd_soc_register_card()\n",
                 card->name);
 
        /* Bodge while we unpick instantiation */
@@ -1996,7 +2005,7 @@ int snd_soc_platform_read(struct snd_soc_platform *platform,
        unsigned int ret;
 
        if (!platform->driver->read) {
-               dev_err(platform->dev, "platform has no read back\n");
+               dev_err(platform->dev, "ASoC: platform has no read back\n");
                return -1;
        }
 
@@ -2012,7 +2021,7 @@ int snd_soc_platform_write(struct snd_soc_platform *platform,
                                         unsigned int reg, unsigned int val)
 {
        if (!platform->driver->write) {
-               dev_err(platform->dev, "platform has no write back\n");
+               dev_err(platform->dev, "ASoC: platform has no write back\n");
                return -1;
        }
 
@@ -2283,7 +2292,8 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
                err = snd_ctl_add(card, snd_soc_cnew(control, data,
                                                     control->name, prefix));
                if (err < 0) {
-                       dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+                       dev_err(dev, "ASoC: Failed to add %s: %d\n",
+                               control->name, err);
                        return err;
                }
        }
@@ -3534,15 +3544,14 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 * not both or neither.
                 */
                if (!!link->codec_name == !!link->codec_of_node) {
-                       dev_err(card->dev,
-                               "Neither/both codec name/of_node are set for %s\n",
-                               link->name);
+                       dev_err(card->dev, "ASoC: Neither/both codec"
+                               " name/of_node are set for %s\n", link->name);
                        return -EINVAL;
                }
                /* Codec DAI name must be specified */
                if (!link->codec_dai_name) {
-                       dev_err(card->dev, "codec_dai_name not set for %s\n",
-                               link->name);
+                       dev_err(card->dev, "ASoC: codec_dai_name not"
+                               " set for %s\n", link->name);
                        return -EINVAL;
                }
 
@@ -3551,8 +3560,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 * can be left unspecified, and a dummy platform will be used.
                 */
                if (link->platform_name && link->platform_of_node) {
-                       dev_err(card->dev,
-                               "Both platform name/of_node are set for %s\n", link->name);
+                       dev_err(card->dev, "ASoC: Both platform name/of_node"
+                               " are set for %s\n", link->name);
                        return -EINVAL;
                }
 
@@ -3562,9 +3571,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 * name alone..
                 */
                if (link->cpu_name && link->cpu_of_node) {
-                       dev_err(card->dev,
-                               "Neither/both cpu name/of_node are set for %s\n",
-                               link->name);
+                       dev_err(card->dev, "ASoC: Neither/both "
+                               "cpu name/of_node are set for %s\n",link->name);
                        return -EINVAL;
                }
                /*
@@ -3573,9 +3581,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (!link->cpu_dai_name &&
                    !(link->cpu_name || link->cpu_of_node)) {
-                       dev_err(card->dev,
-                               "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
-                               link->name);
+                       dev_err(card->dev, "ASoC: Neither cpu_dai_name nor "
+                               "cpu_name/of_node are set for %s\n", link->name);
                        return -EINVAL;
                }
        }
@@ -3622,7 +3629,7 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
 {
        if (card->instantiated)
                soc_cleanup_card_resources(card);
-       dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
+       dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
 
        return 0;
 }
@@ -3679,8 +3686,8 @@ static inline char *fmt_multiple_name(struct device *dev,
                struct snd_soc_dai_driver *dai_drv)
 {
        if (dai_drv->name == NULL) {
-               pr_err("asoc: error - multiple DAI %s registered with no name\n",
-                               dev_name(dev));
+               dev_err(dev, "ASoC: error - multiple DAI %s registered with"
+                               " no name\n", dev_name(dev));
                return NULL;
        }
 
@@ -3698,7 +3705,7 @@ int snd_soc_register_dai(struct device *dev,
        struct snd_soc_codec *codec;
        struct snd_soc_dai *dai;
 
-       dev_dbg(dev, "dai register %s\n", dev_name(dev));
+       dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev));
 
        dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
        if (dai == NULL)
@@ -3721,7 +3728,7 @@ int snd_soc_register_dai(struct device *dev,
 
        list_for_each_entry(codec, &codec_list, list) {
                if (codec->dev == dev) {
-                       dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
+                       dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n",
                                dai->name, codec->name);
                        dai->codec = codec;
                        break;
@@ -3735,7 +3742,7 @@ int snd_soc_register_dai(struct device *dev,
 
        mutex_unlock(&client_mutex);
 
-       pr_debug("Registered DAI '%s'\n", dai->name);
+       dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
 
        return 0;
 }
@@ -3761,7 +3768,7 @@ found:
        list_del(&dai->list);
        mutex_unlock(&client_mutex);
 
-       pr_debug("Unregistered DAI '%s'\n", dai->name);
+       dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name);
        kfree(dai->name);
        kfree(dai);
 }
@@ -3780,7 +3787,7 @@ int snd_soc_register_dais(struct device *dev,
        struct snd_soc_dai *dai;
        int i, ret = 0;
 
-       dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count);
+       dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
 
        for (i = 0; i < count; i++) {
 
@@ -3812,8 +3819,8 @@ int snd_soc_register_dais(struct device *dev,
 
                list_for_each_entry(codec, &codec_list, list) {
                        if (codec->dev == dev) {
-                               dev_dbg(dev, "Mapped DAI %s to CODEC %s\n",
-                                       dai->name, codec->name);
+                               dev_dbg(dev, "ASoC: Mapped DAI %s to "
+                                       "CODEC %s\n", dai->name, codec->name);
                                dai->codec = codec;
                                break;
                        }
@@ -3826,7 +3833,7 @@ int snd_soc_register_dais(struct device *dev,
 
                mutex_unlock(&client_mutex);
 
-               pr_debug("Registered DAI '%s'\n", dai->name);
+               dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name);
        }
 
        return 0;
@@ -3864,7 +3871,7 @@ int snd_soc_register_platform(struct device *dev,
 {
        struct snd_soc_platform *platform;
 
-       dev_dbg(dev, "platform register %s\n", dev_name(dev));
+       dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));
 
        platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
        if (platform == NULL)
@@ -3888,7 +3895,7 @@ int snd_soc_register_platform(struct device *dev,
        list_add(&platform->list, &platform_list);
        mutex_unlock(&client_mutex);
 
-       pr_debug("Registered platform '%s'\n", platform->name);
+       dev_dbg(dev, "ASoC: Registered platform '%s'\n", platform->name);
 
        return 0;
 }
@@ -3914,7 +3921,7 @@ found:
        list_del(&platform->list);
        mutex_unlock(&client_mutex);
 
-       pr_debug("Unregistered platform '%s'\n", platform->name);
+       dev_dbg(dev, "ASoC: Unregistered platform '%s'\n", platform->name);
        kfree(platform->name);
        kfree(platform);
 }
@@ -4007,7 +4014,7 @@ int snd_soc_register_codec(struct device *dev,
                codec->reg_size = reg_size;
                /* it is necessary to make a copy of the default register cache
                 * because in the case of using a compression type that requires
-                * the default register cache to be marked as __devinitconst the
+                * the default register cache to be marked as the
                 * kernel might have freed the array by the time we initialize
                 * the cache.
                 */
@@ -4043,11 +4050,11 @@ int snd_soc_register_codec(struct device *dev,
        if (num_dai) {
                ret = snd_soc_register_dais(dev, dai_drv, num_dai);
                if (ret < 0)
-                       dev_err(codec->dev, "Failed to regster DAIs: %d\n",
-                               ret);
+                       dev_err(codec->dev, "ASoC: Failed to regster"
+                               " DAIs: %d\n", ret);
        }
 
-       pr_debug("Registered codec '%s'\n", codec->name);
+       dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name);
        return 0;
 
 fail:
@@ -4082,7 +4089,7 @@ found:
        list_del(&codec->list);
        mutex_unlock(&client_mutex);
 
-       pr_debug("Unregistered codec '%s'\n", codec->name);
+       dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
 
        snd_soc_cache_exit(codec);
        kfree(codec->reg_def_copy);
@@ -4106,7 +4113,7 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card,
         */
        if (ret < 0 && ret != -EINVAL) {
                dev_err(card->dev,
-                       "Property '%s' could not be read: %d\n",
+                       "ASoC: Property '%s' could not be read: %d\n",
                        propname, ret);
                return ret;
        }
@@ -4125,15 +4132,13 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
 
        num_routes = of_property_count_strings(np, propname);
        if (num_routes < 0 || num_routes & 1) {
-               dev_err(card->dev,
-                    "Property '%s' does not exist or its length is not even\n",
-                    propname);
+               dev_err(card->dev, "ASoC: Property '%s' does not exist or its"
+                       " length is not even\n", propname);
                return -EINVAL;
        }
        num_routes /= 2;
        if (!num_routes) {
-               dev_err(card->dev,
-                       "Property '%s's length is zero\n",
+               dev_err(card->dev, "ASoC: Property '%s's length is zero\n",
                        propname);
                return -EINVAL;
        }
@@ -4142,7 +4147,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                              GFP_KERNEL);
        if (!routes) {
                dev_err(card->dev,
-                       "Could not allocate DAPM route table\n");
+                       "ASoC: Could not allocate DAPM route table\n");
                return -EINVAL;
        }
 
@@ -4150,9 +4155,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                ret = of_property_read_string_index(np, propname,
                        2 * i, &routes[i].sink);
                if (ret) {
-                       dev_err(card->dev,
-                               "Property '%s' index %d could not be read: %d\n",
-                               propname, 2 * i, ret);
+                       dev_err(card->dev, "ASoC: Property '%s' index %d"
+                               " could not be read: %d\n", propname, 2 * i,
+                               ret);
                        kfree(routes);
                        return -EINVAL;
                }
@@ -4160,8 +4165,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                        (2 * i) + 1, &routes[i].source);
                if (ret) {
                        dev_err(card->dev,
-                               "Property '%s' index %d could not be read: %d\n",
-                               propname, (2 * i) + 1, ret);
+                               "ASoC: Property '%s' index %d could not be"
+                               " read: %d\n", propname, (2 * i) + 1, ret);
                        kfree(routes);
                        return -EINVAL;
                }
index 6e35bcae02df4b6a0e79709482a018f099615e21..1e36bc81e5af1fb015ffef62f628781910984bbb 100644 (file)
@@ -220,7 +220,7 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
        else if (w->platform)
                return snd_soc_platform_read(w->platform, reg);
 
-       dev_err(w->dapm->dev, "no valid widget read method\n");
+       dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
        return -1;
 }
 
@@ -231,7 +231,7 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
        else if (w->platform)
                return snd_soc_platform_write(w->platform, reg, val);
 
-       dev_err(w->dapm->dev, "no valid widget write method\n");
+       dev_err(w->dapm->dev, "ASoC: no valid widget write method\n");
        return -1;
 }
 
@@ -546,7 +546,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
                        wlist = kzalloc(wlistsize, GFP_KERNEL);
                        if (wlist == NULL) {
                                dev_err(dapm->dev,
-                                       "asoc: can't allocate widget list for %s\n",
+                                       "ASoC: can't allocate widget list for %s\n",
                                        w->name);
                                return -ENOMEM;
                        }
@@ -595,9 +595,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
                                                      prefix);
                        ret = snd_ctl_add(card, path->kcontrol);
                        if (ret < 0) {
-                               dev_err(dapm->dev,
-                                       "asoc: failed to add dapm kcontrol %s: %d\n",
-                                       path->long_name, ret);
+                               dev_err(dapm->dev, "ASoC: failed to add widget"
+                                       " %s dapm kcontrol %s: %d\n",
+                                       w->name, path->long_name, ret);
                                kfree(wlist);
                                kfree(path->long_name);
                                path->long_name = NULL;
@@ -626,7 +626,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
 
        if (w->num_kcontrols != 1) {
                dev_err(dapm->dev,
-                       "asoc: mux %s has incorrect number of controls\n",
+                       "ASoC: mux %s has incorrect number of controls\n",
                        w->name);
                return -EINVAL;
        }
@@ -645,7 +645,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
        wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
        if (wlist == NULL) {
                dev_err(dapm->dev,
-                       "asoc: can't allocate widget list for %s\n", w->name);
+                       "ASoC: can't allocate widget list for %s\n", w->name);
                return -ENOMEM;
        }
        wlist->num_widgets = wlistentries;
@@ -677,7 +677,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
                                        name + prefix_len, prefix);
                ret = snd_ctl_add(card, kcontrol);
                if (ret < 0) {
-                       dev_err(dapm->dev, "failed to add kcontrol %s: %d\n",
+                       dev_err(dapm->dev, "ASoC: failed to add kcontrol %s: %d\n",
                                w->name, ret);
                        kfree(wlist);
                        return ret;
@@ -699,7 +699,7 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
 {
        if (w->num_kcontrols)
                dev_err(w->dapm->dev,
-                       "asoc: PGA controls not supported: '%s'\n", w->name);
+                       "ASoC: PGA controls not supported: '%s'\n", w->name);
 
        return 0;
 }
@@ -725,7 +725,7 @@ static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
        case SNDRV_CTL_POWER_D3hot:
        case SNDRV_CTL_POWER_D3cold:
                if (widget->ignore_suspend)
-                       dev_dbg(widget->dapm->dev, "%s ignoring suspend\n",
+                       dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
                                widget->name);
                return widget->ignore_suspend;
        default:
@@ -757,14 +757,14 @@ static int dapm_list_add_widget(struct snd_soc_dapm_widget_list **list,
                        wlistentries * sizeof(struct snd_soc_dapm_widget *);
        *list = krealloc(wlist, wlistsize, GFP_KERNEL);
        if (*list == NULL) {
-               dev_err(w->dapm->dev, "can't allocate widget list for %s\n",
+               dev_err(w->dapm->dev, "ASoC: can't allocate widget list for %s\n",
                        w->name);
                return -ENOMEM;
        }
        wlist = *list;
 
        /* insert the widget */
-       dev_dbg(w->dapm->dev, "added %s in widget list pos %d\n",
+       dev_dbg(w->dapm->dev, "ASoC: added %s in widget list pos %d\n",
                        w->name, wlist->num_widgets);
 
        wlist->widgets[wlist->num_widgets] = w;
@@ -844,7 +844,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                                int err;
                                err = dapm_list_add_widget(list, path->sink);
                                if (err < 0) {
-                                       dev_err(widget->dapm->dev, "could not add widget %s\n",
+                                       dev_err(widget->dapm->dev,
+                                               "ASoC: could not add widget %s\n",
                                                widget->name);
                                        return con;
                                }
@@ -943,7 +944,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                                int err;
                                err = dapm_list_add_widget(list, path->source);
                                if (err < 0) {
-                                       dev_err(widget->dapm->dev, "could not add widget %s\n",
+                                       dev_err(widget->dapm->dev,
+                                               "ASoC: could not add widget %s\n",
                                                widget->name);
                                        return con;
                                }
@@ -1024,7 +1026,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                        ret = regulator_allow_bypass(w->regulator, true);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "Failed to bypass %s: %d\n",
+                                        "ASoC: Failed to bypass %s: %d\n",
                                         w->name, ret);
                }
 
@@ -1034,7 +1036,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                        ret = regulator_allow_bypass(w->regulator, false);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "Failed to unbypass %s: %d\n",
+                                        "ASoC: Failed to unbypass %s: %d\n",
                                         w->name, ret);
                }
 
@@ -1253,7 +1255,7 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
                ret = w->event(w, NULL, event);
                trace_snd_soc_dapm_widget_event_done(w, event);
                if (ret < 0)
-                       pr_err("%s: %s event failed: %d\n",
+                       dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n",
                               ev_name, w->name, ret);
        }
 }
@@ -1402,7 +1404,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 
                if (ret < 0)
                        dev_err(w->dapm->dev,
-                               "Failed to apply widget power: %d\n", ret);
+                               "ASoC: Failed to apply widget power: %d\n", ret);
        }
 
        if (!list_empty(&pending))
@@ -1431,20 +1433,21 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
            (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
                ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
                if (ret != 0)
-                       pr_err("%s DAPM pre-event failed: %d\n",
+                       dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
                               w->name, ret);
        }
 
        ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
                                  update->val);
        if (ret < 0)
-               pr_err("%s DAPM update failed: %d\n", w->name, ret);
+               dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n",
+                       w->name, ret);
 
        if (w->event &&
            (w->event_flags & SND_SOC_DAPM_POST_REG)) {
                ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
                if (ret != 0)
-                       pr_err("%s DAPM post-event failed: %d\n",
+                       dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
                               w->name, ret);
        }
 }
@@ -1466,7 +1469,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
                if (ret != 0)
                        dev_err(d->dev,
-                               "Failed to turn on bias: %d\n", ret);
+                               "ASoC: Failed to turn on bias: %d\n", ret);
        }
 
        /* Prepare for a STADDBY->ON or ON->STANDBY transition */
@@ -1474,7 +1477,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
                if (ret != 0)
                        dev_err(d->dev,
-                               "Failed to prepare bias: %d\n", ret);
+                               "ASoC: Failed to prepare bias: %d\n", ret);
        }
 }
 
@@ -1492,7 +1495,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
             d->target_bias_level == SND_SOC_BIAS_OFF)) {
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
                if (ret != 0)
-                       dev_err(d->dev, "Failed to apply standby bias: %d\n",
+                       dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",
                                ret);
        }
 
@@ -1501,7 +1504,8 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
            d->target_bias_level == SND_SOC_BIAS_OFF) {
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
                if (ret != 0)
-                       dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
+                       dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
+                               ret);
 
                if (d->dev)
                        pm_runtime_put(d->dev);
@@ -1512,7 +1516,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
            d->target_bias_level == SND_SOC_BIAS_ON) {
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
                if (ret != 0)
-                       dev_err(d->dev, "Failed to apply active bias: %d\n",
+                       dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",
                                ret);
        }
 }
@@ -1838,7 +1842,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
 
        if (!dapm->debugfs_dapm) {
                dev_warn(dapm->dev,
-                      "Failed to create DAPM debugfs directory\n");
+                      "ASoC: Failed to create DAPM debugfs directory\n");
                return;
        }
 
@@ -2123,7 +2127,7 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
        struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
 
        if (!w) {
-               dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
+               dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
                return -EINVAL;
        }
 
@@ -2212,8 +2216,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
        if (!wsource)
                wsource = wtsource;
 
-       if (wsource == NULL || wsink == NULL)
+       if (wsource == NULL) {
+               dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
+                       route->source);
                return -ENODEV;
+       }
+       if (wsink == NULL) {
+               dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
+                       route->sink);
+               return -ENODEV;
+       }
 
        path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
        if (!path)
@@ -2308,7 +2320,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
        return 0;
 
 err:
-       dev_warn(dapm->dev, "asoc: no dapm match for %s --> %s --> %s\n",
+       dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
                 source, control, sink);
        kfree(path);
        return ret;
@@ -2325,7 +2337,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
 
        if (route->control) {
                dev_err(dapm->dev,
-                       "Removal of routes with controls not supported\n");
+                       "ASoC: Removal of routes with controls not supported\n");
                return -EINVAL;
        }
 
@@ -2360,7 +2372,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
                list_del(&path->list_source);
                kfree(path);
        } else {
-               dev_warn(dapm->dev, "Route %s->%s does not exist\n",
+               dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
                         source, sink);
        }
 
@@ -2389,8 +2401,10 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
        for (i = 0; i < num; i++) {
                r = snd_soc_dapm_add_route(dapm, route);
                if (r < 0) {
-                       dev_err(dapm->dev, "Failed to add route %s->%s\n",
-                               route->source, route->sink);
+                       dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
+                               route->source,
+                               route->control ? route->control : "direct",
+                               route->sink);
                        ret = r;
                }
                route++;
@@ -2438,19 +2452,19 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
        int count = 0;
 
        if (!source) {
-               dev_err(dapm->dev, "Unable to find source %s for weak route\n",
+               dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",
                        route->source);
                return -ENODEV;
        }
 
        if (!sink) {
-               dev_err(dapm->dev, "Unable to find sink %s for weak route\n",
+               dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",
                        route->sink);
                return -ENODEV;
        }
 
        if (route->control || route->connected)
-               dev_warn(dapm->dev, "Ignoring control for weak route %s->%s\n",
+               dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",
                         route->source, route->sink);
 
        list_for_each_entry(path, &source->sinks, list_source) {
@@ -2461,10 +2475,10 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
        }
 
        if (count == 0)
-               dev_err(dapm->dev, "No path found for weak route %s->%s\n",
+               dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",
                        route->source, route->sink);
        if (count > 1)
-               dev_warn(dapm->dev, "%d paths found for weak route %s->%s\n",
+               dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",
                         count, route->source, route->sink);
 
        return 0;
@@ -2601,7 +2615,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 
        if (snd_soc_volsw_is_stereo(mc))
                dev_warn(widget->dapm->dev,
-                        "Control '%s' is stereo, which is not supported\n",
+                        "ASoC: Control '%s' is stereo, which is not supported\n",
                         kcontrol->id.name);
 
        ucontrol->value.integer.value[0] =
@@ -2644,7 +2658,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 
        if (snd_soc_volsw_is_stereo(mc))
                dev_warn(widget->dapm->dev,
-                        "Control '%s' is stereo, which is not supported\n",
+                        "ASoC: Control '%s' is stereo, which is not supported\n",
                         kcontrol->id.name);
 
        val = (ucontrol->value.integer.value[0] & mask);
@@ -3021,7 +3035,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                w->regulator = devm_regulator_get(dapm->dev, w->name);
                if (IS_ERR(w->regulator)) {
                        ret = PTR_ERR(w->regulator);
-                       dev_err(dapm->dev, "Failed to request %s: %d\n",
+                       dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
                                w->name, ret);
                        return NULL;
                }
@@ -3031,7 +3045,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                w->clk = devm_clk_get(dapm->dev, w->name);
                if (IS_ERR(w->clk)) {
                        ret = PTR_ERR(w->clk);
-                       dev_err(dapm->dev, "Failed to request %s: %d\n",
+                       dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
                                w->name, ret);
                        return NULL;
                }
@@ -3182,7 +3196,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
        if (config->formats) {
                fmt = ffs(config->formats) - 1;
        } else {
-               dev_warn(w->dapm->dev, "Invalid format %llx specified\n",
+               dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n",
                         config->formats);
                fmt = 0;
        }
@@ -3215,7 +3229,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
                                                             params, source);
                        if (ret != 0) {
                                dev_err(source->dev,
-                                       "hw_params() failed: %d\n", ret);
+                                       "ASoC: hw_params() failed: %d\n", ret);
                                goto out;
                        }
                }
@@ -3226,7 +3240,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
                                                           sink);
                        if (ret != 0) {
                                dev_err(sink->dev,
-                                       "hw_params() failed: %d\n", ret);
+                                       "ASoC: hw_params() failed: %d\n", ret);
                                goto out;
                        }
                }
@@ -3235,14 +3249,14 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                ret = snd_soc_dai_digital_mute(sink, 0);
                if (ret != 0 && ret != -ENOTSUPP)
-                       dev_warn(sink->dev, "Failed to unmute: %d\n", ret);
+                       dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
                ret = 0;
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
                ret = snd_soc_dai_digital_mute(sink, 1);
                if (ret != 0 && ret != -ENOTSUPP)
-                       dev_warn(sink->dev, "Failed to mute: %d\n", ret);
+                       dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
                ret = 0;
                break;
 
@@ -3281,11 +3295,11 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
        template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
                SND_SOC_DAPM_PRE_PMD;
 
-       dev_dbg(card->dev, "adding %s widget\n", link_name);
+       dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
 
        w = snd_soc_dapm_new_control(&card->dapm, &template);
        if (!w) {
-               dev_err(card->dev, "Failed to create %s widget\n",
+               dev_err(card->dev, "ASoC: Failed to create %s widget\n",
                        link_name);
                return -ENOMEM;
        }
@@ -3319,12 +3333,12 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
                template.name = dai->driver->playback.stream_name;
                template.sname = dai->driver->playback.stream_name;
 
-               dev_dbg(dai->dev, "adding %s widget\n",
+               dev_dbg(dai->dev, "ASoC: adding %s widget\n",
                        template.name);
 
                w = snd_soc_dapm_new_control(dapm, &template);
                if (!w) {
-                       dev_err(dapm->dev, "Failed to create %s widget\n",
+                       dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
                                dai->driver->playback.stream_name);
                }
 
@@ -3337,12 +3351,12 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
                template.name = dai->driver->capture.stream_name;
                template.sname = dai->driver->capture.stream_name;
 
-               dev_dbg(dai->dev, "adding %s widget\n",
+               dev_dbg(dai->dev, "ASoC: adding %s widget\n",
                        template.name);
 
                w = snd_soc_dapm_new_control(dapm, &template);
                if (!w) {
-                       dev_err(dapm->dev, "Failed to create %s widget\n",
+                       dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
                                dai->driver->capture.stream_name);
                }
 
@@ -3518,11 +3532,11 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
        struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
 
        if (!w) {
-               dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
+               dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
                return -EINVAL;
        }
 
-       dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin);
+       dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
        w->connected = 1;
        w->force = 1;
        dapm_mark_dirty(w, "force enable");
@@ -3605,7 +3619,7 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
        struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
 
        if (!w) {
-               dev_err(dapm->dev, "dapm: unknown pin %s\n", pin);
+               dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
                return -EINVAL;
        }
 
@@ -3664,7 +3678,7 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        struct snd_soc_dapm_widget *w;
 
-       dev_dbg(codec->dev, "Auto NC: DAPMs: card:%p codec:%p\n",
+       dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n",
                &card->dapm, &codec->dapm);
 
        list_for_each_entry(w, &card->widgets, list) {
@@ -3674,7 +3688,7 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
                case snd_soc_dapm_input:
                case snd_soc_dapm_output:
                case snd_soc_dapm_micbias:
-                       dev_dbg(codec->dev, "Auto NC: Checking widget %s\n",
+                       dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n",
                                w->name);
                        if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
                                dev_dbg(codec->dev,
index bbc125748a3843decc6ffd04d171fcf6f6b9fc5c..111b7d921e890c0051444b1a28fb6edfe78fd837 100644 (file)
@@ -317,3 +317,5 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
+
+MODULE_LICENSE("GPL");
index 1ab5fe04bfccb066853fc664d9db9bea68a9f8ce..0bb5cccd77663a4d819a67731245e51564af3224 100644 (file)
@@ -66,7 +66,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        struct snd_soc_dapm_context *dapm;
        struct snd_soc_jack_pin *pin;
        int enable;
-       int oldstatus;
 
        trace_snd_soc_jack_report(jack, mask, status);
 
@@ -78,8 +77,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
 
        mutex_lock(&jack->mutex);
 
-       oldstatus = jack->status;
-
        jack->status &= ~mask;
        jack->status |= status & mask;
 
@@ -172,12 +169,13 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
 
        for (i = 0; i < count; i++) {
                if (!pins[i].pin) {
-                       printk(KERN_ERR "No name for pin %d\n", i);
+                       dev_err(jack->codec->dev, "ASoC: No name for pin %d\n",
+                               i);
                        return -EINVAL;
                }
                if (!pins[i].mask) {
-                       printk(KERN_ERR "No mask for pin %d (%s)\n", i,
-                              pins[i].pin);
+                       dev_err(jack->codec->dev, "ASoC: No mask for pin %d"
+                               " (%s)\n", i, pins[i].pin);
                        return -EINVAL;
                }
 
@@ -297,13 +295,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
 
        for (i = 0; i < count; i++) {
                if (!gpio_is_valid(gpios[i].gpio)) {
-                       printk(KERN_ERR "Invalid gpio %d\n",
+                       dev_err(jack->codec->dev, "ASoC: Invalid gpio %d\n",
                                gpios[i].gpio);
                        ret = -EINVAL;
                        goto undo;
                }
                if (!gpios[i].name) {
-                       printk(KERN_ERR "No name for gpio %d\n",
+                       dev_err(jack->codec->dev, "ASoC: No name for gpio %d\n",
                                gpios[i].gpio);
                        ret = -EINVAL;
                        goto undo;
@@ -332,7 +330,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                if (gpios[i].wake) {
                        ret = irq_set_irq_wake(gpio_to_irq(gpios[i].gpio), 1);
                        if (ret != 0)
-                               printk(KERN_ERR
+                               dev_err(jack->codec->dev, "ASoC: "
                                  "Failed to mark GPIO %d as wake source: %d\n",
                                        gpios[i].gpio, ret);
                }
index ef22d0bd9e9e62725f25f472aec279b75cf56e64..5c3ca2a3466170cd132464760dffd9b63155ebe9 100644 (file)
@@ -43,7 +43,7 @@ static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
 
                struct snd_soc_pcm_runtime *be = dpcm->be;
 
-               dev_dbg(be->dev, "pm: BE %s event %d dir %d\n",
+               dev_dbg(be->dev, "ASoC: BE %s event %d dir %d\n",
                                be->dai_link->name, event, dir);
 
                snd_soc_dapm_stream_event(be, dir, event);
@@ -70,18 +70,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
         */
        if (!soc_dai->rate) {
                dev_warn(soc_dai->dev,
-                        "Not enforcing symmetric_rates due to race\n");
+                        "ASoC: Not enforcing symmetric_rates due to race\n");
                return 0;
        }
 
-       dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
+       dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate);
 
        ret = snd_pcm_hw_constraint_minmax(substream->runtime,
                                           SNDRV_PCM_HW_PARAM_RATE,
                                           soc_dai->rate, soc_dai->rate);
        if (ret < 0) {
                dev_err(soc_dai->dev,
-                       "Unable to apply rate symmetry constraint: %d\n", ret);
+                       "ASoC: Unable to apply rate symmetry constraint: %d\n",
+                       ret);
                return ret;
        }
 
@@ -118,7 +119,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
                                                   sample_sizes[i], bits);
                if (ret != 0)
                        dev_warn(dai->dev,
-                                "Failed to set MSB %d/%d: %d\n",
+                                "ASoC: Failed to set MSB %d/%d: %d\n",
                                 bits, sample_sizes[i], ret);
        }
 }
@@ -149,8 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (cpu_dai->driver->ops->startup) {
                ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
                if (ret < 0) {
-                       dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
-                               cpu_dai->name, ret);
+                       dev_err(cpu_dai->dev, "ASoC: can't open interface"
+                               " %s: %d\n", cpu_dai->name, ret);
                        goto out;
                }
        }
@@ -158,8 +159,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (platform->driver->ops && platform->driver->ops->open) {
                ret = platform->driver->ops->open(substream);
                if (ret < 0) {
-                       dev_err(platform->dev, "can't open platform %s: %d\n",
-                               platform->name, ret);
+                       dev_err(platform->dev, "ASoC: can't open platform"
+                               " %s: %d\n", platform->name, ret);
                        goto platform_err;
                }
        }
@@ -167,8 +168,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (codec_dai->driver->ops->startup) {
                ret = codec_dai->driver->ops->startup(substream, codec_dai);
                if (ret < 0) {
-                       dev_err(codec_dai->dev, "can't open codec %s: %d\n",
-                               codec_dai->name, ret);
+                       dev_err(codec_dai->dev, "ASoC: can't open codec"
+                               " %s: %d\n", codec_dai->name, ret);
                        goto codec_dai_err;
                }
        }
@@ -176,7 +177,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
                ret = rtd->dai_link->ops->startup(substream);
                if (ret < 0) {
-                       pr_err("asoc: %s startup failed: %d\n",
+                       pr_err("ASoC: %s startup failed: %d\n",
                               rtd->dai_link->name, ret);
                        goto machine_err;
                }
@@ -238,18 +239,18 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        ret = -EINVAL;
        snd_pcm_limit_hw_rates(runtime);
        if (!runtime->hw.rates) {
-               printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
+               printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
                        codec_dai->name, cpu_dai->name);
                goto config_err;
        }
        if (!runtime->hw.formats) {
-               printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
+               printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
                        codec_dai->name, cpu_dai->name);
                goto config_err;
        }
        if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
            runtime->hw.channels_min > runtime->hw.channels_max) {
-               printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
+               printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
                                codec_dai->name, cpu_dai->name);
                goto config_err;
        }
@@ -270,12 +271,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                        goto config_err;
        }
 
-       pr_debug("asoc: %s <-> %s info:\n",
+       pr_debug("ASoC: %s <-> %s info:\n",
                        codec_dai->name, cpu_dai->name);
-       pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
-       pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+       pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
+       pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
                 runtime->hw.channels_max);
-       pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+       pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min,
                 runtime->hw.rate_max);
 
 dynamic:
@@ -330,7 +331,7 @@ static void close_delayed_work(struct work_struct *work)
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-       pr_debug("pop wq checking: %s status: %s waiting: %s\n",
+       dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
                 codec_dai->driver->playback.stream_name,
                 codec_dai->playback_active ? "active" : "inactive",
                 codec_dai->pop_wait ? "yes" : "no");
@@ -444,7 +445,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
                ret = rtd->dai_link->ops->prepare(substream);
                if (ret < 0) {
-                       pr_err("asoc: machine prepare error: %d\n", ret);
+                       dev_err(rtd->card->dev, "ASoC: machine prepare error:"
+                               " %d\n", ret);
                        goto out;
                }
        }
@@ -452,8 +454,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (platform->driver->ops && platform->driver->ops->prepare) {
                ret = platform->driver->ops->prepare(substream);
                if (ret < 0) {
-                       dev_err(platform->dev, "platform prepare error: %d\n",
-                               ret);
+                       dev_err(platform->dev, "ASoC: platform prepare error:"
+                               " %d\n", ret);
                        goto out;
                }
        }
@@ -461,7 +463,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (codec_dai->driver->ops->prepare) {
                ret = codec_dai->driver->ops->prepare(substream, codec_dai);
                if (ret < 0) {
-                       dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+                       dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
                                ret);
                        goto out;
                }
@@ -470,7 +472,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (cpu_dai->driver->ops->prepare) {
                ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
                if (ret < 0) {
-                       dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+                       dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n",
                                ret);
                        goto out;
                }
@@ -512,7 +514,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
                ret = rtd->dai_link->ops->hw_params(substream, params);
                if (ret < 0) {
-                       pr_err("asoc: machine hw_params failed: %d\n", ret);
+                       dev_err(rtd->card->dev, "ASoC: machine hw_params"
+                               " failed: %d\n", ret);
                        goto out;
                }
        }
@@ -520,8 +523,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (codec_dai->driver->ops->hw_params) {
                ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
                if (ret < 0) {
-                       dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
-                               codec_dai->name, ret);
+                       dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
+                               " %d\n", codec_dai->name, ret);
                        goto codec_err;
                }
        }
@@ -529,7 +532,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (cpu_dai->driver->ops->hw_params) {
                ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
                if (ret < 0) {
-                       dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+                       dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
                                cpu_dai->name, ret);
                        goto interface_err;
                }
@@ -538,7 +541,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (platform->driver->ops && platform->driver->ops->hw_params) {
                ret = platform->driver->ops->hw_params(substream, params);
                if (ret < 0) {
-                       dev_err(platform->dev, "%s hw params failed: %d\n",
+                       dev_err(platform->dev, "ASoC: %s hw params failed: %d\n",
                               platform->name, ret);
                        goto platform_err;
                }
@@ -760,7 +763,7 @@ static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
        struct snd_soc_dpcm *dpcm, *d;
 
        list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) {
-               dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
+               dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
                                stream ? "capture" : "playback",
                                dpcm->be->dai_link->name);
 
@@ -815,7 +818,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
                }
        }
 
-       dev_err(card->dev, "can't get %s BE for %s\n",
+       dev_err(card->dev, "ASoC: can't get %s BE for %s\n",
                stream ? "capture" : "playback", widget->name);
        return NULL;
 }
@@ -866,7 +869,7 @@ static int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
        /* get number of valid DAI paths and their widgets */
        paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
 
-       dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
+       dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
                        stream ? "capture" : "playback");
 
        *list_ = list;
@@ -903,7 +906,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
                if (widget && widget_in_list(list, widget))
                        continue;
 
-               dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
+               dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
                        stream ? "capture" : "playback",
                        dpcm->be->dai_link->name, fe->dai_link->name);
                dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
@@ -911,7 +914,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
                prune++;
        }
 
-       dev_dbg(fe->dev, "found %d old BE paths for pruning\n", prune);
+       dev_dbg(fe->dev, "ASoC: found %d old BE paths for pruning\n", prune);
        return prune;
 }
 
@@ -932,7 +935,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
                /* is there a valid BE rtd for this widget */
                be = dpcm_get_be(card, list->widgets[i], stream);
                if (!be) {
-                       dev_err(fe->dev, "no BE found for %s\n",
+                       dev_err(fe->dev, "ASoC: no BE found for %s\n",
                                        list->widgets[i]->name);
                        continue;
                }
@@ -948,7 +951,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
                /* newly connected FE and BE */
                err = dpcm_be_connect(fe, be, stream);
                if (err < 0) {
-                       dev_err(fe->dev, "can't connect %s\n",
+                       dev_err(fe->dev, "ASoC: can't connect %s\n",
                                list->widgets[i]->name);
                        break;
                } else if (err == 0) /* already connected */
@@ -959,7 +962,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
                new++;
        }
 
-       dev_dbg(fe->dev, "found %d new BE paths\n", new);
+       dev_dbg(fe->dev, "ASoC: found %d new BE paths\n", new);
        return new;
 }
 
@@ -998,7 +1001,7 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
                        snd_soc_dpcm_get_substream(be, stream);
 
                if (be->dpcm[stream].users == 0)
-                       dev_err(be->dev, "no users %s at close - state %d\n",
+                       dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
                                stream ? "capture" : "playback",
                                be->dpcm[stream].state);
 
@@ -1032,7 +1035,7 @@ static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
 
                /* first time the dpcm is open ? */
                if (be->dpcm[stream].users == DPCM_MAX_BE_USERS)
-                       dev_err(be->dev, "too many users %s at open %d\n",
+                       dev_err(be->dev, "ASoC: too many users %s at open %d\n",
                                stream ? "capture" : "playback",
                                be->dpcm[stream].state);
 
@@ -1043,15 +1046,15 @@ static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
                        continue;
 
-               dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
+               dev_dbg(be->dev, "ASoC: open BE %s\n", be->dai_link->name);
 
                be_substream->runtime = be->dpcm[stream].runtime;
                err = soc_pcm_open(be_substream);
                if (err < 0) {
-                       dev_err(be->dev, "BE open failed %d\n", err);
+                       dev_err(be->dev, "ASoC: BE open failed %d\n", err);
                        be->dpcm[stream].users--;
                        if (be->dpcm[stream].users < 0)
-                               dev_err(be->dev, "no users %s at unwind %d\n",
+                               dev_err(be->dev, "ASoC: no users %s at unwind %d\n",
                                        stream ? "capture" : "playback",
                                        be->dpcm[stream].state);
 
@@ -1076,7 +1079,7 @@ unwind:
                        continue;
 
                if (be->dpcm[stream].users == 0)
-                       dev_err(be->dev, "no users %s at close %d\n",
+                       dev_err(be->dev, "ASoC: no users %s at close %d\n",
                                stream ? "capture" : "playback",
                                be->dpcm[stream].state);
 
@@ -1128,16 +1131,16 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
 
        ret = dpcm_be_dai_startup(fe, fe_substream->stream);
        if (ret < 0) {
-               dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
+               dev_err(fe->dev,"ASoC: failed to start some BEs %d\n", ret);
                goto be_err;
        }
 
-       dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
+       dev_dbg(fe->dev, "ASoC: open FE %s\n", fe->dai_link->name);
 
        /* start the DAI frontend */
        ret = soc_pcm_open(fe_substream);
        if (ret < 0) {
-               dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
+               dev_err(fe->dev,"ASoC: failed to start FE %d\n", ret);
                goto unwind;
        }
 
@@ -1172,7 +1175,7 @@ static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
                        continue;
 
                if (be->dpcm[stream].users == 0)
-                       dev_err(be->dev, "no users %s at close - state %d\n",
+                       dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
                                stream ? "capture" : "playback",
                                be->dpcm[stream].state);
 
@@ -1183,7 +1186,7 @@ static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
                        continue;
 
-               dev_dbg(be->dev, "dpcm: close BE %s\n",
+               dev_dbg(be->dev, "ASoC: close BE %s\n",
                        dpcm->fe->dai_link->name);
 
                soc_pcm_close(be_substream);
@@ -1204,7 +1207,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
        /* shutdown the BEs */
        dpcm_be_dai_shutdown(fe, substream->stream);
 
-       dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
+       dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name);
 
        /* now shutdown the frontend */
        soc_pcm_close(substream);
@@ -1243,7 +1246,7 @@ static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
                        continue;
 
-               dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
+               dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
                        dpcm->fe->dai_link->name);
 
                soc_pcm_hw_free(be_substream);
@@ -1262,12 +1265,12 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 
-       dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
+       dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name);
 
        /* call hw_free on the frontend */
        err = soc_pcm_hw_free(substream);
        if (err < 0)
-               dev_err(fe->dev,"dpcm: hw_free FE %s failed\n",
+               dev_err(fe->dev,"ASoC: hw_free FE %s failed\n",
                        fe->dai_link->name);
 
        /* only hw_params backends that are either sinks or sources
@@ -1305,7 +1308,7 @@ static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
                        continue;
 
-               dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
+               dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
                        dpcm->fe->dai_link->name);
 
                /* copy params for each dpcm */
@@ -1318,7 +1321,7 @@ static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
                                        &dpcm->hw_params);
                        if (ret < 0) {
                                dev_err(be->dev,
-                                       "dpcm: hw_params BE fixup failed %d\n",
+                                       "ASoC: hw_params BE fixup failed %d\n",
                                        ret);
                                goto unwind;
                        }
@@ -1327,7 +1330,7 @@ static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
                ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
                if (ret < 0) {
                        dev_err(dpcm->be->dev,
-                               "dpcm: hw_params BE failed %d\n", ret);
+                               "ASoC: hw_params BE failed %d\n", ret);
                        goto unwind;
                }
 
@@ -1374,18 +1377,18 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
                        sizeof(struct snd_pcm_hw_params));
        ret = dpcm_be_dai_hw_params(fe, substream->stream);
        if (ret < 0) {
-               dev_err(fe->dev,"dpcm: hw_params BE failed %d\n", ret);
+               dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret);
                goto out;
        }
 
-       dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
+       dev_dbg(fe->dev, "ASoC: hw_params FE %s rate %d chan %x fmt %d\n",
                        fe->dai_link->name, params_rate(params),
                        params_channels(params), params_format(params));
 
        /* call hw_params on the frontend */
        ret = soc_pcm_hw_params(substream, params);
        if (ret < 0) {
-               dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
+               dev_err(fe->dev,"ASoC: hw_params FE failed %d\n", ret);
                dpcm_be_dai_hw_free(fe, stream);
         } else
                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
@@ -1401,12 +1404,12 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm,
 {
        int ret;
 
-       dev_dbg(dpcm->be->dev, "dpcm: trigger BE %s cmd %d\n",
+       dev_dbg(dpcm->be->dev, "ASoC: trigger BE %s cmd %d\n",
                        dpcm->fe->dai_link->name, cmd);
 
        ret = soc_pcm_trigger(substream, cmd);
        if (ret < 0)
-               dev_err(dpcm->be->dev,"dpcm: trigger BE failed %d\n", ret);
+               dev_err(dpcm->be->dev,"ASoC: trigger BE failed %d\n", ret);
 
        return ret;
 }
@@ -1517,12 +1520,12 @@ static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
        case SND_SOC_DPCM_TRIGGER_PRE:
                /* call trigger on the frontend before the backend. */
 
-               dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
+               dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
                                fe->dai_link->name, cmd);
 
                ret = soc_pcm_trigger(substream, cmd);
                if (ret < 0) {
-                       dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
                        goto out;
                }
 
@@ -1533,11 +1536,11 @@ static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
 
                ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
                if (ret < 0) {
-                       dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
                        goto out;
                }
 
-               dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
+               dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
                                fe->dai_link->name, cmd);
 
                ret = soc_pcm_trigger(substream, cmd);
@@ -1545,17 +1548,17 @@ static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
        case SND_SOC_DPCM_TRIGGER_BESPOKE:
                /* bespoke trigger() - handles both FE and BEs */
 
-               dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
+               dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n",
                                fe->dai_link->name, cmd);
 
                ret = soc_pcm_bespoke_trigger(substream, cmd);
                if (ret < 0) {
-                       dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
                        goto out;
                }
                break;
        default:
-               dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
+               dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
                                fe->dai_link->name);
                ret = -EINVAL;
                goto out;
@@ -1598,12 +1601,12 @@ static int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
                        continue;
 
-               dev_dbg(be->dev, "dpcm: prepare BE %s\n",
+               dev_dbg(be->dev, "ASoC: prepare BE %s\n",
                        dpcm->fe->dai_link->name);
 
                ret = soc_pcm_prepare(be_substream);
                if (ret < 0) {
-                       dev_err(be->dev, "dpcm: backend prepare failed %d\n",
+                       dev_err(be->dev, "ASoC: backend prepare failed %d\n",
                                ret);
                        break;
                }
@@ -1620,13 +1623,13 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
 
        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 
-       dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
+       dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name);
 
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 
        /* there is no point preparing this FE if there are no BEs */
        if (list_empty(&fe->dpcm[stream].be_clients)) {
-               dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
+               dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
                                fe->dai_link->name);
                ret = -EINVAL;
                goto out;
@@ -1639,7 +1642,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
        /* call prepare on the frontend */
        ret = soc_pcm_prepare(substream);
        if (ret < 0) {
-               dev_err(fe->dev,"dpcm: prepare FE %s failed\n",
+               dev_err(fe->dev,"ASoC: prepare FE %s failed\n",
                        fe->dai_link->name);
                goto out;
        }
@@ -1673,33 +1676,33 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
        enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
        int err;
 
-       dev_dbg(fe->dev, "runtime %s close on FE %s\n",
+       dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n",
                        stream ? "capture" : "playback", fe->dai_link->name);
 
        if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
                /* call bespoke trigger - FE takes care of all BE triggers */
-               dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
+               dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n",
                                fe->dai_link->name);
 
                err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
                if (err < 0)
-                       dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
+                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
        } else {
-               dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
+               dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n",
                        fe->dai_link->name);
 
                err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
                if (err < 0)
-                       dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
+                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
        }
 
        err = dpcm_be_dai_hw_free(fe, stream);
        if (err < 0)
-               dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
+               dev_err(fe->dev,"ASoC: hw_free FE failed %d\n", err);
 
        err = dpcm_be_dai_shutdown(fe, stream);
        if (err < 0)
-               dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
+               dev_err(fe->dev,"ASoC: shutdown FE failed %d\n", err);
 
        /* run the stream event for each BE */
        dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
@@ -1715,7 +1718,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
        enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
        int ret;
 
-       dev_dbg(fe->dev, "runtime %s open on FE %s\n",
+       dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
                        stream ? "capture" : "playback", fe->dai_link->name);
 
        /* Only start the BE if the FE is ready */
@@ -1761,22 +1764,22 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
 
        if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
                /* call trigger on the frontend - FE takes care of all BE triggers */
-               dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
+               dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n",
                                fe->dai_link->name);
 
                ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
                if (ret < 0) {
-                       dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
+                       dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret);
                        goto hw_free;
                }
        } else {
-               dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
+               dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n",
                        fe->dai_link->name);
 
                ret = dpcm_be_dai_trigger(fe, stream,
                                        SNDRV_PCM_TRIGGER_START);
                if (ret < 0) {
-                       dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
+                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
                        goto hw_free;
                }
        }
@@ -1805,7 +1808,7 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
        ret = dpcm_run_update_startup(fe, stream);
        if (ret < 0)
-               dev_err(fe->dev, "failed to startup some BEs\n");
+               dev_err(fe->dev, "ASoC: failed to startup some BEs\n");
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 
        return ret;
@@ -1818,7 +1821,7 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
        ret = dpcm_run_update_shutdown(fe, stream);
        if (ret < 0)
-               dev_err(fe->dev, "failed to shutdown some BEs\n");
+               dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 
        return ret;
@@ -1853,7 +1856,7 @@ int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
                        continue;
 
                /* DAPM sync will call this to update DSP paths */
-               dev_dbg(fe->dev, "DPCM runtime update for FE %s\n",
+               dev_dbg(fe->dev, "ASoC: DPCM runtime update for FE %s\n",
                        fe->dai_link->name);
 
                /* skip if FE doesn't have playback capability */
@@ -1862,7 +1865,7 @@ int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
 
                paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
                if (paths < 0) {
-                       dev_warn(fe->dev, "%s no valid %s path\n",
+                       dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
                                        fe->dai_link->name,  "playback");
                        mutex_unlock(&card->mutex);
                        return paths;
@@ -1891,7 +1894,7 @@ capture:
 
                paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
                if (paths < 0) {
-                       dev_warn(fe->dev, "%s no valid %s path\n",
+                       dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
                                        fe->dai_link->name,  "capture");
                        mutex_unlock(&card->mutex);
                        return paths;
@@ -1934,7 +1937,7 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
                if (be->dai_link->ignore_suspend)
                        continue;
 
-               dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
+               dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);
 
                if (drv->ops->digital_mute && dai->playback_active)
                                drv->ops->digital_mute(dai, mute);
@@ -1955,7 +1958,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
        fe->dpcm[stream].runtime = fe_substream->runtime;
 
        if (dpcm_path_get(fe, stream, &list) <= 0) {
-               dev_dbg(fe->dev, "asoc: %s no valid %s route\n",
+               dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
                        fe->dai_link->name, stream ? "capture" : "playback");
        }
 
@@ -2039,11 +2042,11 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
                        capture, &pcm);
        }
        if (ret < 0) {
-               dev_err(rtd->card->dev, "can't create pcm for %s\n",
+               dev_err(rtd->card->dev, "ASoC: can't create pcm for %s\n",
                        rtd->dai_link->name);
                return ret;
        }
-       dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
+       dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
 
        /* DAPM dai link stream work */
        INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
@@ -2097,7 +2100,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
        if (platform->driver->pcm_new) {
                ret = platform->driver->pcm_new(rtd);
                if (ret < 0) {
-                       dev_err(platform->dev, "pcm constructor failed\n");
+                       dev_err(platform->dev,
+                               "ASoC: pcm constructor failed: %d\n",
+                               ret);
                        return ret;
                }
        }
index 60053709e417b0bdcecc81d13ac676fc885021e7..fe4541df498cbd85eb4a10275a658ee15cdbab9b 100644 (file)
@@ -94,7 +94,7 @@ static struct snd_soc_dai_driver dummy_dai = {
        .name = "snd-soc-dummy-dai",
 };
 
-static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
+static int snd_soc_dummy_probe(struct platform_device *pdev)
 {
        int ret;
 
@@ -111,7 +111,7 @@ static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
        return ret;
 }
 
-static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
+static int snd_soc_dummy_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        snd_soc_unregister_codec(&pdev->dev);
@@ -125,7 +125,7 @@ static struct platform_driver soc_dummy_driver = {
                .owner = THIS_MODULE,
        },
        .probe = snd_soc_dummy_probe,
-       .remove = __devexit_p(snd_soc_dummy_remove),
+       .remove = snd_soc_dummy_remove,
 };
 
 static struct platform_device *soc_dummy_dev;
index 8c7f23729446b1582f6d7625d5933aad905e45d7..9b76cc5a114897613ed3d19e87b13b649037c4be 100644 (file)
@@ -184,12 +184,12 @@ struct snd_soc_platform_driver spear_soc_platform = {
        .pcm_free       =       spear_pcm_free,
 };
 
-static int __devinit spear_soc_platform_probe(struct platform_device *pdev)
+static int spear_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &spear_soc_platform);
 }
 
-static int __devexit spear_soc_platform_remove(struct platform_device *pdev)
+static int spear_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
 
@@ -203,7 +203,7 @@ static struct platform_driver spear_pcm_driver = {
        },
 
        .probe = spear_soc_platform_probe,
-       .remove = __devexit_p(spear_soc_platform_remove),
+       .remove = spear_soc_platform_remove,
 };
 
 module_platform_driver(spear_pcm_driver);
index bf99296bce95bcb9cd78997709f8ed034da1dec0..654318483877e0094e071ba73c1a7fe7e7bc0681 100644 (file)
@@ -131,7 +131,7 @@ static const struct regmap_config tegra20_das_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit tegra20_das_probe(struct platform_device *pdev)
+static int tegra20_das_probe(struct platform_device *pdev)
 {
        struct resource *res, *region;
        void __iomem *regs;
@@ -200,7 +200,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra20_das_remove(struct platform_device *pdev)
+static int tegra20_das_remove(struct platform_device *pdev)
 {
        if (!das)
                return -ENODEV;
@@ -210,14 +210,14 @@ static int __devexit tegra20_das_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra20_das_of_match[] __devinitconst = {
+static const struct of_device_id tegra20_das_of_match[] = {
        { .compatible = "nvidia,tegra20-das", },
        {},
 };
 
 static struct platform_driver tegra20_das_driver = {
        .probe = tegra20_das_probe,
-       .remove = __devexit_p(tegra20_das_remove),
+       .remove = tegra20_das_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index 0832e8afd73c9df70df50474d62e145b30eaa707..caa772de5a184cb021def3333323e4343343fc51 100644 (file)
@@ -331,7 +331,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
+static int tegra20_i2s_platform_probe(struct platform_device *pdev)
 {
        struct tegra20_i2s *i2s;
        struct resource *mem, *memregion, *dmareq;
@@ -447,7 +447,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
+static int tegra20_i2s_platform_remove(struct platform_device *pdev)
 {
        struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev);
 
@@ -463,12 +463,12 @@ static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra20_i2s_of_match[] __devinitconst = {
+static const struct of_device_id tegra20_i2s_of_match[] = {
        { .compatible = "nvidia,tegra20-i2s", },
        {},
 };
 
-static const struct dev_pm_ops tegra20_i2s_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra20_i2s_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
                           tegra20_i2s_runtime_resume, NULL)
 };
@@ -481,7 +481,7 @@ static struct platform_driver tegra20_i2s_driver = {
                .pm = &tegra20_i2s_pm_ops,
        },
        .probe = tegra20_i2s_platform_probe,
-       .remove = __devexit_p(tegra20_i2s_platform_remove),
+       .remove = tegra20_i2s_platform_remove,
 };
 module_platform_driver(tegra20_i2s_driver);
 
index 3ebc8670ba00f0bd4f0c901efefe50b433b309b0..04771d14d34342181932df8a5bccf07e19a5191b 100644 (file)
@@ -257,7 +257,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
+static int tegra20_spdif_platform_probe(struct platform_device *pdev)
 {
        struct tegra20_spdif *spdif;
        struct resource *mem, *memregion, *dmareq;
@@ -357,7 +357,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
+static int tegra20_spdif_platform_remove(struct platform_device *pdev)
 {
        struct tegra20_spdif *spdif = dev_get_drvdata(&pdev->dev);
 
@@ -373,7 +373,7 @@ static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct dev_pm_ops tegra20_spdif_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra20_spdif_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend,
                           tegra20_spdif_runtime_resume, NULL)
 };
@@ -385,7 +385,7 @@ static struct platform_driver tegra20_spdif_driver = {
                .pm = &tegra20_spdif_pm_ops,
        },
        .probe = tegra20_spdif_platform_probe,
-       .remove = __devexit_p(tegra20_spdif_platform_remove),
+       .remove = tegra20_spdif_platform_remove,
 };
 
 module_platform_driver(tegra20_spdif_driver);
index 64b67a3091964a655c19a6106aa671332cd2b89f..f354dc390a0be4c1b57ae473f8b357f9c66cb632 100644 (file)
@@ -287,7 +287,7 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
 }
 EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
 
-static const char * const configlink_clocks[] __devinitconst = {
+static const char * const configlink_clocks[] = {
        "i2s0",
        "i2s1",
        "i2s2",
@@ -299,7 +299,7 @@ static const char * const configlink_clocks[] __devinitconst = {
        "spdif_in",
 };
 
-struct of_dev_auxdata ahub_auxdata[] __devinitdata = {
+struct of_dev_auxdata ahub_auxdata[] = {
        OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL),
        OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL),
        OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL),
@@ -433,7 +433,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit tegra30_ahub_probe(struct platform_device *pdev)
+static int tegra30_ahub_probe(struct platform_device *pdev)
 {
        struct clk *clk;
        int i;
@@ -585,7 +585,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
+static int tegra30_ahub_remove(struct platform_device *pdev)
 {
        if (!ahub)
                return -ENODEV;
@@ -602,19 +602,19 @@ static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra30_ahub_of_match[] __devinitconst = {
+static const struct of_device_id tegra30_ahub_of_match[] = {
        { .compatible = "nvidia,tegra30-ahub", },
        {},
 };
 
-static const struct dev_pm_ops tegra30_ahub_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra30_ahub_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
                           tegra30_ahub_runtime_resume, NULL)
 };
 
 static struct platform_driver tegra30_ahub_driver = {
        .probe = tegra30_ahub_probe,
-       .remove = __devexit_p(tegra30_ahub_remove),
+       .remove = tegra30_ahub_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index 44184228d1f0acfbd3fe6c625da2bd832908608e..27e91dd0b91c7d9b8b69fcdfb18056cee31d1c96 100644 (file)
@@ -391,7 +391,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
+static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 {
        struct tegra30_i2s *i2s;
        u32 cif_ids[2];
@@ -492,7 +492,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
+static int tegra30_i2s_platform_remove(struct platform_device *pdev)
 {
        struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
 
@@ -508,12 +508,12 @@ static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra30_i2s_of_match[] __devinitconst = {
+static const struct of_device_id tegra30_i2s_of_match[] = {
        { .compatible = "nvidia,tegra30-i2s", },
        {},
 };
 
-static const struct dev_pm_ops tegra30_i2s_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra30_i2s_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
                           tegra30_i2s_runtime_resume, NULL)
 };
@@ -526,7 +526,7 @@ static struct platform_driver tegra30_i2s_driver = {
                .pm = &tegra30_i2s_pm_ops,
        },
        .probe = tegra30_i2s_platform_probe,
-       .remove = __devexit_p(tegra30_i2s_platform_remove),
+       .remove = tegra30_i2s_platform_remove,
 };
 module_platform_driver(tegra30_i2s_driver);
 
index 76cb1b363b71c2ce2d1be75c27113c3cf2154127..c80adb9da472a7ee2d71eb0de13d6d171e5266e1 100644 (file)
@@ -150,7 +150,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
        .fully_routed = true,
 };
 
-static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
+static int tegra_alc5632_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct snd_soc_card *card = &snd_soc_tegra_alc5632;
@@ -227,7 +227,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
+static int tegra_alc5632_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
@@ -242,7 +242,7 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+static const struct of_device_id tegra_alc5632_of_match[] = {
        { .compatible = "nvidia,tegra-audio-alc5632", },
        {},
 };
@@ -255,7 +255,7 @@ static struct platform_driver tegra_alc5632_driver = {
                .of_match_table = tegra_alc5632_of_match,
        },
        .probe = tegra_alc5632_probe,
-       .remove = __devexit_p(tegra_alc5632_remove),
+       .remove = tegra_alc5632_remove,
 };
 module_platform_driver(tegra_alc5632_driver);
 
index e18733963cb4b00111ca03f3ad3aebb2ed910124..c925ab0adeb6b0a2750106518f825cfd7b1ef864 100644 (file)
@@ -253,13 +253,13 @@ static struct snd_soc_platform_driver tegra_pcm_platform = {
        .pcm_free       = tegra_pcm_free,
 };
 
-int __devinit tegra_pcm_platform_register(struct device *dev)
+int tegra_pcm_platform_register(struct device *dev)
 {
        return snd_soc_register_platform(dev, &tegra_pcm_platform);
 }
 EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
 
-void __devexit tegra_pcm_platform_unregister(struct device *dev)
+void tegra_pcm_platform_unregister(struct device *dev)
 {
        snd_soc_unregister_platform(dev);
 }
index ea9166d5c4ebeba6c649e6fcb8551c290acc2849..c8ef88a67c59f56b201b2d41b10bc8b44512d510 100644 (file)
@@ -122,7 +122,7 @@ static struct snd_soc_card snd_soc_tegra_wm8753 = {
        .fully_routed = true,
 };
 
-static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
+static int tegra_wm8753_driver_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &snd_soc_tegra_wm8753;
        struct tegra_wm8753 *machine;
@@ -188,7 +188,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
+static int tegra_wm8753_driver_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
@@ -200,7 +200,7 @@ static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra_wm8753_of_match[] __devinitconst = {
+static const struct of_device_id tegra_wm8753_of_match[] = {
        { .compatible = "nvidia,tegra-audio-wm8753", },
        {},
 };
@@ -213,7 +213,7 @@ static struct platform_driver tegra_wm8753_driver = {
                .of_match_table = tegra_wm8753_of_match,
        },
        .probe = tegra_wm8753_driver_probe,
-       .remove = __devexit_p(tegra_wm8753_driver_remove),
+       .remove = tegra_wm8753_driver_remove,
 };
 module_platform_driver(tegra_wm8753_driver);
 
index cee13b7bfb949ffacd8e8cdabccea8030ba8659a..bbd79bf563031f755f6ef267664814a9f10e3c0c 100644 (file)
@@ -252,7 +252,7 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
        .fully_routed = true,
 };
 
-static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
+static int tegra_wm8903_driver_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct snd_soc_card *card = &snd_soc_tegra_wm8903;
@@ -402,7 +402,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
+static int tegra_wm8903_driver_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
@@ -417,7 +417,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra_wm8903_of_match[] __devinitconst = {
+static const struct of_device_id tegra_wm8903_of_match[] = {
        { .compatible = "nvidia,tegra-audio-wm8903", },
        {},
 };
@@ -430,7 +430,7 @@ static struct platform_driver tegra_wm8903_driver = {
                .of_match_table = tegra_wm8903_of_match,
        },
        .probe = tegra_wm8903_driver_probe,
-       .remove = __devexit_p(tegra_wm8903_driver_remove),
+       .remove = tegra_wm8903_driver_remove,
 };
 module_platform_driver(tegra_wm8903_driver);
 
index e69a4f7000d6166e0a0065365827486fb4c5fc99..7fcf6c2297db290b2c946bcc2cc9347bd209cfc9 100644 (file)
@@ -120,7 +120,7 @@ static struct snd_soc_card snd_soc_trimslice = {
        .fully_routed = true,
 };
 
-static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
+static int tegra_snd_trimslice_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &snd_soc_trimslice;
        struct tegra_trimslice *trimslice;
@@ -183,7 +183,7 @@ err:
        return ret;
 }
 
-static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
+static int tegra_snd_trimslice_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
@@ -195,7 +195,7 @@ static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id trimslice_of_match[] __devinitconst = {
+static const struct of_device_id trimslice_of_match[] = {
        { .compatible = "nvidia,tegra-audio-trimslice", },
        {},
 };
@@ -208,7 +208,7 @@ static struct platform_driver tegra_snd_trimslice_driver = {
                .of_match_table = trimslice_of_match,
        },
        .probe = tegra_snd_trimslice_probe,
-       .remove = __devexit_p(tegra_snd_trimslice_remove),
+       .remove = tegra_snd_trimslice_remove,
 };
 module_platform_driver(tegra_snd_trimslice_driver);
 
index 28db4ca997ca2b6c3f768de842ea84f567f4fd25..16ab69635e2e209da6913b58e700a8b2eec0c00d 100644 (file)
@@ -170,7 +170,7 @@ static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
        },
 };
 
-static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
+static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
 {
        struct txx9aclc_plat_drvdata *drvdata;
        struct resource *r;
@@ -208,7 +208,7 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
        return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
 }
 
-static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
+static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_dai(&pdev->dev);
        return 0;
@@ -216,7 +216,7 @@ static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver txx9aclc_ac97_driver = {
        .probe          = txx9aclc_ac97_dev_probe,
-       .remove         = __devexit_p(txx9aclc_ac97_dev_remove),
+       .remove         = txx9aclc_ac97_dev_remove,
        .driver         = {
                .name   = "txx9aclc-ac97",
                .owner  = THIS_MODULE,
index b609d2c64c555b0346b6c9cb7ade29cb95d6277f..45a6428cba8db9367d657a79320b13fb6b27bffb 100644 (file)
@@ -417,12 +417,12 @@ static struct snd_soc_platform_driver txx9aclc_soc_platform = {
        .pcm_free       = txx9aclc_pcm_free_dma_buffers,
 };
 
-static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)
+static int txx9aclc_soc_platform_probe(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);
 }
 
-static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)
+static int txx9aclc_soc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
        return 0;
@@ -435,7 +435,7 @@ static struct platform_driver txx9aclc_pcm_driver = {
        },
 
        .probe = txx9aclc_soc_platform_probe,
-       .remove = __devexit_p(txx9aclc_soc_platform_remove),
+       .remove = txx9aclc_soc_platform_remove,
 };
 
 module_platform_driver(txx9aclc_pcm_driver);
index 54f7e25b6f7d479d30bed372ba5d12ce1abacb22..ae6990738783ad18c84cd2914119f90c7a2727dc 100644 (file)
@@ -33,7 +33,7 @@ struct snd_soc_dai_link mop500_dai_links[] = {
                .stream_name = "ab8500_0",
                .cpu_dai_name = "ux500-msp-i2s.1",
                .codec_dai_name = "ab8500-codec-dai.0",
-               .platform_name = "ux500-pcm.0",
+               .platform_name = "ux500-msp-i2s.1",
                .codec_name = "ab8500-codec.0",
                .init = mop500_ab8500_machine_init,
                .ops = mop500_ab8500_ops,
@@ -43,7 +43,7 @@ struct snd_soc_dai_link mop500_dai_links[] = {
                .stream_name = "ab8500_1",
                .cpu_dai_name = "ux500-msp-i2s.3",
                .codec_dai_name = "ab8500-codec-dai.1",
-               .platform_name = "ux500-pcm.0",
+               .platform_name = "ux500-msp-i2s.3",
                .codec_name = "ab8500-codec.0",
                .init = NULL,
                .ops = mop500_ab8500_ops,
@@ -71,8 +71,8 @@ static void mop500_of_node_put(void)
        }
 }
 
-static int __devinit mop500_of_probe(struct platform_device *pdev,
-                               struct device_node *np)
+static int mop500_of_probe(struct platform_device *pdev,
+                          struct device_node *np)
 {
        struct device_node *codec_np, *msp_np[2];
        int i;
@@ -99,7 +99,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit mop500_probe(struct platform_device *pdev)
+static int mop500_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        int ret;
@@ -136,7 +136,7 @@ static int __devinit mop500_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit mop500_remove(struct platform_device *pdev)
+static int mop500_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *mop500_card = platform_get_drvdata(pdev);
 
@@ -161,7 +161,7 @@ static struct platform_driver snd_soc_mop500_driver = {
                .of_match_table = snd_soc_mop500_match,
        },
        .probe = mop500_probe,
-       .remove = __devexit_p(mop500_remove),
+       .remove = mop500_remove,
 };
 
 module_platform_driver(snd_soc_mop500_driver);
index be94bf9bf94f51b31b4ba5d1aaeeeabcc58ea043..94a3e5705aaa498495b16e0b50749b111e30f976 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ux500_msp_i2s.h"
 #include "ux500_msp_dai.h"
+#include "ux500_pcm.h"
 
 static int setup_pcm_multichan(struct snd_soc_dai *dai,
                        struct ux500_msp_config *msp_config)
@@ -398,11 +399,28 @@ static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
                return ret;
        }
 
-       /* Enable clock */
-       dev_dbg(dai->dev, "%s: Enabling MSP-clock.\n", __func__);
-       clk_enable(drvdata->clk);
+       /* Prepare and enable clocks */
+       dev_dbg(dai->dev, "%s: Enabling MSP-clocks.\n", __func__);
+       ret = clk_prepare_enable(drvdata->pclk);
+       if (ret) {
+               dev_err(drvdata->msp->dev,
+                       "%s: Failed to prepare/enable pclk!\n", __func__);
+               goto err_pclk;
+       }
 
-       return 0;
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret) {
+               dev_err(drvdata->msp->dev,
+                       "%s: Failed to prepare/enable clk!\n", __func__);
+               goto err_clk;
+       }
+
+       return ret;
+err_clk:
+       clk_disable_unprepare(drvdata->pclk);
+err_pclk:
+       regulator_disable(drvdata->reg_vape);
+       return ret;
 }
 
 static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
@@ -428,8 +446,9 @@ static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
                        __func__, dai->id, snd_pcm_stream_str(substream));
        }
 
-       /* Disable clock */
-       clk_disable(drvdata->clk);
+       /* Disable and unprepare clocks */
+       clk_disable_unprepare(drvdata->clk);
+       clk_disable_unprepare(drvdata->pclk);
 
        /* Disable regulator */
        ret = regulator_disable(drvdata->reg_vape);
@@ -749,7 +768,7 @@ static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
        },
 };
 
-static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
+static int ux500_msp_drv_probe(struct platform_device *pdev)
 {
        struct ux500_msp_i2s_drvdata *drvdata;
        int ret = 0;
@@ -780,6 +799,14 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
        }
        prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
 
+       drvdata->pclk = clk_get(&pdev->dev, "apb_pclk");
+       if (IS_ERR(drvdata->pclk)) {
+               ret = (int)PTR_ERR(drvdata->pclk);
+               dev_err(&pdev->dev, "%s: ERROR: clk_get of pclk failed (%d)!\n",
+                       __func__, ret);
+               goto err_pclk;
+       }
+
        drvdata->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(drvdata->clk)) {
                ret = (int)PTR_ERR(drvdata->clk);
@@ -806,27 +833,41 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
                goto err_init_msp;
        }
 
+       ret = ux500_pcm_register_platform(pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Error: %s: Failed to register PCM platform device!\n",
+                       __func__);
+               goto err_reg_plat;
+       }
+
        return 0;
 
+err_reg_plat:
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
 err_init_msp:
        clk_put(drvdata->clk);
-
 err_clk:
+       clk_put(drvdata->pclk);
+err_pclk:
        devm_regulator_put(drvdata->reg_vape);
 
        return ret;
 }
 
-static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
+static int ux500_msp_drv_remove(struct platform_device *pdev)
 {
        struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
 
+       ux500_pcm_unregister_platform(pdev);
+
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
 
        devm_regulator_put(drvdata->reg_vape);
        prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
 
        clk_put(drvdata->clk);
+       clk_put(drvdata->pclk);
 
        ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
 
index 98202a34a5dd16d3626171620ee270c2051713a7..9c778d9c383804cf998f40ce212bd3b6915b0634 100644 (file)
@@ -69,6 +69,7 @@ struct ux500_msp_i2s_drvdata {
        /* Clocks */
        unsigned int master_clk;
        struct clk *clk;
+       struct clk *pclk;
 
        /* Regulators */
        int vape_opp_constraint;
index b55b79f7536cd70fd1ce0da19d7aebf6a0256765..846fa82a58d013bbb04980fdfeab9aa44d4e505d 100644 (file)
@@ -281,7 +281,7 @@ static struct snd_soc_platform_driver ux500_pcm_soc_drv = {
        .pcm_new        = ux500_pcm_new,
 };
 
-static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev)
+int ux500_pcm_register_platform(struct platform_device *pdev)
 {
        int ret;
 
@@ -295,23 +295,12 @@ static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
 
-static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev)
+int ux500_pcm_unregister_platform(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
 
        return 0;
 }
-
-static struct platform_driver ux500_pcm_driver = {
-       .driver = {
-               .name = "ux500-pcm",
-               .owner = THIS_MODULE,
-       },
-
-       .probe = ux500_pcm_drv_probe,
-       .remove = __devexit_p(ux500_pcm_drv_remove),
-};
-module_platform_driver(ux500_pcm_driver);
-
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform);
index 77ed44d371e994a244d1393f0898fbae8a7af764..76d344476afc398d6cca59943eb065b195ce734d 100644 (file)
@@ -32,4 +32,7 @@
 #define UX500_PLATFORM_PERIODS_MAX             48
 #define UX500_PLATFORM_BUFFER_BYTES_MAX                (2048 * PAGE_SIZE)
 
+int ux500_pcm_register_platform(struct platform_device *pdev);
+int ux500_pcm_unregister_platform(struct platform_device *pdev);
+
 #endif
index 5701787c0e6bce406603ebb8590668d853900fd6..174d21fb56e2e326246231b30ce589a90919a9ff 100644 (file)
@@ -755,7 +755,7 @@ static struct snd_pcm_ops snd_amd7930_capture_ops = {
        .pointer        =       snd_amd7930_capture_pointer,
 };
 
-static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd)
+static int snd_amd7930_pcm(struct snd_amd7930 *amd)
 {
        struct snd_pcm *pcm;
        int err;
@@ -854,7 +854,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
        return change;
 }
 
-static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
+static struct snd_kcontrol_new amd7930_controls[] = {
        {
                .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
                .name           =       "Monitor Volume",
@@ -884,7 +884,7 @@ static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
        },
 };
 
-static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd)
+static int snd_amd7930_mixer(struct snd_amd7930 *amd)
 {
        struct snd_card *card;
        int idx, err;
@@ -933,10 +933,10 @@ static struct snd_device_ops snd_amd7930_dev_ops = {
        .dev_free       =       snd_amd7930_dev_free,
 };
 
-static int __devinit snd_amd7930_create(struct snd_card *card,
-                                       struct platform_device *op,
-                                       int irq, int dev,
-                                       struct snd_amd7930 **ramd)
+static int snd_amd7930_create(struct snd_card *card,
+                             struct platform_device *op,
+                             int irq, int dev,
+                             struct snd_amd7930 **ramd)
 {
        struct snd_amd7930 *amd;
        unsigned long flags;
@@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit amd7930_sbus_probe(struct platform_device *op)
+static int amd7930_sbus_probe(struct platform_device *op)
 {
        struct resource *rp = &op->resource[0];
        static int dev_num;
index f2eabd3f22fdde3453541b8a72a89da623e3d2ff..54aaad2a10f53aa87a42fb01a1e74491ec01b9b2 100644 (file)
@@ -702,7 +702,7 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer)
        return 0;
 }
 
-static void __devinit snd_cs4231_init(struct snd_cs4231 *chip)
+static void snd_cs4231_init(struct snd_cs4231 *chip)
 {
        unsigned long flags;
 
@@ -1019,7 +1019,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(
        return bytes_to_frames(substream->runtime, ptr);
 }
 
-static int __devinit snd_cs4231_probe(struct snd_cs4231 *chip)
+static int snd_cs4231_probe(struct snd_cs4231 *chip)
 {
        unsigned long flags;
        int i;
@@ -1218,7 +1218,7 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = {
        .pointer        =       snd_cs4231_capture_pointer,
 };
 
-static int __devinit snd_cs4231_pcm(struct snd_card *card)
+static int snd_cs4231_pcm(struct snd_card *card)
 {
        struct snd_cs4231 *chip = card->private_data;
        struct snd_pcm *pcm;
@@ -1247,7 +1247,7 @@ static int __devinit snd_cs4231_pcm(struct snd_card *card)
        return 0;
 }
 
-static int __devinit snd_cs4231_timer(struct snd_card *card)
+static int snd_cs4231_timer(struct snd_card *card)
 {
        struct snd_cs4231 *chip = card->private_data;
        struct snd_timer *timer;
@@ -1498,7 +1498,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
   .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \
                   ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) }
 
-static struct snd_kcontrol_new snd_cs4231_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cs4231_controls[] = {
 CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT,
                CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT,
@@ -1537,7 +1537,7 @@ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
 CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
 };
 
-static int __devinit snd_cs4231_mixer(struct snd_card *card)
+static int snd_cs4231_mixer(struct snd_card *card)
 {
        struct snd_cs4231 *chip = card->private_data;
        int err, idx;
@@ -1558,7 +1558,7 @@ static int __devinit snd_cs4231_mixer(struct snd_card *card)
 
 static int dev;
 
-static int __devinit cs4231_attach_begin(struct snd_card **rcard)
+static int cs4231_attach_begin(struct snd_card **rcard)
 {
        struct snd_card *card;
        struct snd_cs4231 *chip;
@@ -1589,7 +1589,7 @@ static int __devinit cs4231_attach_begin(struct snd_card **rcard)
        return 0;
 }
 
-static int __devinit cs4231_attach_finish(struct snd_card *card)
+static int cs4231_attach_finish(struct snd_card *card)
 {
        struct snd_cs4231 *chip = card->private_data;
        int err;
@@ -1793,9 +1793,9 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
        .dev_free       =       snd_cs4231_sbus_dev_free,
 };
 
-static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
-                                           struct platform_device *op,
-                                           int dev)
+static int snd_cs4231_sbus_create(struct snd_card *card,
+                                 struct platform_device *op,
+                                 int dev)
 {
        struct snd_cs4231 *chip = card->private_data;
        int err;
@@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit cs4231_sbus_probe(struct platform_device *op)
+static int cs4231_sbus_probe(struct platform_device *op)
 {
        struct resource *rp = &op->resource[0];
        struct snd_card *card;
@@ -1959,9 +1959,9 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
        .dev_free       =       snd_cs4231_ebus_dev_free,
 };
 
-static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
-                                           struct platform_device *op,
-                                           int dev)
+static int snd_cs4231_ebus_create(struct snd_card *card,
+                                 struct platform_device *op,
+                                 int dev)
 {
        struct snd_cs4231 *chip = card->private_data;
        int err;
@@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit cs4231_ebus_probe(struct platform_device *op)
+static int cs4231_ebus_probe(struct platform_device *op)
 {
        struct snd_card *card;
        int err;
@@ -2072,7 +2072,7 @@ static int __devinit cs4231_ebus_probe(struct platform_device *op)
 }
 #endif
 
-static int __devinit cs4231_probe(struct platform_device *op)
+static int cs4231_probe(struct platform_device *op)
 {
 #ifdef EBUS_SUPPORT
        if (!strcmp(op->dev.of_node->parent->name, "ebus"))
@@ -2086,7 +2086,7 @@ static int __devinit cs4231_probe(struct platform_device *op)
        return -ENODEV;
 }
 
-static int __devexit cs4231_remove(struct platform_device *op)
+static int cs4231_remove(struct platform_device *op)
 {
        struct snd_cs4231 *chip = dev_get_drvdata(&op->dev);
 
@@ -2115,7 +2115,7 @@ static struct platform_driver cs4231_driver = {
                .of_match_table = cs4231_match,
        },
        .probe          = cs4231_probe,
-       .remove         = __devexit_p(cs4231_remove),
+       .remove         = cs4231_remove,
 };
 
 module_platform_driver(cs4231_driver);
index ae35f5342e105dc3700e5589da6d23a4f4a6ab63..75e6016d3efe79e0b025115f2f0148a9e3403aa3 100644 (file)
@@ -745,7 +745,7 @@ static void dbri_reset(struct snd_dbri *dbri)
 }
 
 /* Lock must not be held before calling this */
-static void __devinit dbri_initialize(struct snd_dbri *dbri)
+static void dbri_initialize(struct snd_dbri *dbri)
 {
        s32 *cmd;
        u32 dma_addr;
@@ -1305,7 +1305,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins.
  * Lock must not be held before calling it.
 
 */
-static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
+static void cs4215_setup_pipes(struct snd_dbri *dbri)
 {
        unsigned long flags;
 
@@ -1338,7 +1338,7 @@ static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
        dbri_cmdwait(dbri);
 }
 
-static __devinit int cs4215_init_data(struct cs4215 *mm)
+static int cs4215_init_data(struct cs4215 *mm)
 {
        /*
         * No action, memory resetting only.
@@ -1630,7 +1630,7 @@ static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate,
 /*
  *
  */
-static __devinit int cs4215_init(struct snd_dbri *dbri)
+static int cs4215_init(struct snd_dbri *dbri)
 {
        u32 reg2 = sbus_readl(dbri->regs + REG2);
        dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
@@ -2217,7 +2217,7 @@ static struct snd_pcm_ops snd_dbri_ops = {
        .pointer = snd_dbri_pointer,
 };
 
-static int __devinit snd_dbri_pcm(struct snd_card *card)
+static int snd_dbri_pcm(struct snd_card *card)
 {
        struct snd_pcm *pcm;
        int err;
@@ -2409,7 +2409,7 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
   .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \
                        ((invert) << 24) },
 
-static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
+static struct snd_kcontrol_new dbri_controls[] = {
        {
         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
         .name  = "Playback Volume",
@@ -2436,7 +2436,7 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
        CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
 };
 
-static int __devinit snd_dbri_mixer(struct snd_card *card)
+static int snd_dbri_mixer(struct snd_card *card)
 {
        int idx, err;
        struct snd_dbri *dbri;
@@ -2500,7 +2500,7 @@ static void dbri_debug_read(struct snd_info_entry *entry,
 }
 #endif
 
-static void __devinit snd_dbri_proc(struct snd_card *card)
+static void snd_dbri_proc(struct snd_card *card)
 {
        struct snd_dbri *dbri = card->private_data;
        struct snd_info_entry *entry;
@@ -2523,9 +2523,9 @@ static void __devinit snd_dbri_proc(struct snd_card *card)
 */
 static void snd_dbri_free(struct snd_dbri *dbri);
 
-static int __devinit snd_dbri_create(struct snd_card *card,
-                                    struct platform_device *op,
-                                    int irq, int dev)
+static int snd_dbri_create(struct snd_card *card,
+                          struct platform_device *op,
+                          int irq, int dev)
 {
        struct snd_dbri *dbri = card->private_data;
        int err;
@@ -2593,7 +2593,7 @@ static void snd_dbri_free(struct snd_dbri *dbri)
                                  (void *)dbri->dma, dbri->dma_dvma);
 }
 
-static int __devinit dbri_probe(struct platform_device *op)
+static int dbri_probe(struct platform_device *op)
 {
        struct snd_dbri *dbri;
        struct resource *rp;
@@ -2663,7 +2663,7 @@ _err:
        return err;
 }
 
-static int __devexit dbri_remove(struct platform_device *op)
+static int dbri_remove(struct platform_device *op)
 {
        struct snd_card *card = dev_get_drvdata(&op->dev);
 
@@ -2694,7 +2694,7 @@ static struct platform_driver dbri_sbus_driver = {
                .of_match_table = dbri_match,
        },
        .probe          = dbri_probe,
-       .remove         = __devexit_p(dbri_remove),
+       .remove         = dbri_remove,
 };
 
 module_platform_driver(dbri_sbus_driver);
index c6500d00053b21314086f9d88f8dcd72e91e4cc7..4dd60d8a4889bbd82bae4cfee9bd23be2ea5a4a7 100644 (file)
@@ -330,7 +330,7 @@ static struct snd_pcm_ops at73c213_playback_ops = {
        .pointer        = snd_at73c213_pcm_pointer,
 };
 
-static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+static int snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
 {
        struct snd_pcm *pcm;
        int retval;
@@ -665,7 +665,7 @@ static int snd_at73c213_aux_capture_volume_info(
                        | (mask << 24) | (invert << 22))                \
 }
 
-static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_at73c213_controls[] = {
 AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1),
 AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1),
 AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1),
@@ -709,7 +709,7 @@ AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN,
 AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0),
 };
 
-static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip)
+static int snd_at73c213_mixer(struct snd_at73c213 *chip)
 {
        struct snd_card *card;
        int errval, idx;
@@ -744,7 +744,7 @@ cleanup:
 /*
  * Device functions
  */
-static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
 {
        /*
         * Continuous clock output.
@@ -774,7 +774,7 @@ static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
        return 0;
 }
 
-static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
+static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
 {
        int retval;
        unsigned char dac_ctrl = 0;
@@ -879,8 +879,8 @@ static int snd_at73c213_dev_free(struct snd_device *device)
        return 0;
 }
 
-static int __devinit snd_at73c213_dev_init(struct snd_card *card,
-                                        struct spi_device *spi)
+static int snd_at73c213_dev_init(struct snd_card *card,
+                                struct spi_device *spi)
 {
        static struct snd_device_ops ops = {
                .dev_free       = snd_at73c213_dev_free,
@@ -940,7 +940,7 @@ out:
        return retval;
 }
 
-static int __devinit snd_at73c213_probe(struct spi_device *spi)
+static int snd_at73c213_probe(struct spi_device *spi)
 {
        struct snd_card                 *card;
        struct snd_at73c213             *chip;
@@ -1007,7 +1007,7 @@ out:
        return retval;
 }
 
-static int __devexit snd_at73c213_remove(struct spi_device *spi)
+static int snd_at73c213_remove(struct spi_device *spi)
 {
        struct snd_card *card = dev_get_drvdata(&spi->dev);
        struct snd_at73c213 *chip = card->private_data;
@@ -1109,7 +1109,7 @@ static struct spi_driver at73c213_driver = {
        .probe          = snd_at73c213_probe,
        .suspend        = snd_at73c213_suspend,
        .resume         = snd_at73c213_resume,
-       .remove         = __devexit_p(snd_at73c213_remove),
+       .remove         = snd_at73c213_remove,
 };
 
 module_spi_driver(at73c213_driver);
index fc8cc823e4388ad15929d9b65f1fb065172fa2de..4394ae796356c2c46cce90e9e5e20707e85de06d 100644 (file)
@@ -82,8 +82,8 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
        }
 }
 
-static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
-               const struct usb_device_id *usb_id)
+static int usb6fire_chip_probe(struct usb_interface *intf,
+                              const struct usb_device_id *usb_id)
 {
        int ret;
        int i;
index 6c3d531a250efdc265acaf6bced48ab82aa32d05..9e6e3ffd86bbbc4212e72eb3d0c7cd69e6d44c8e 100644 (file)
@@ -125,16 +125,17 @@ static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
        return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
 }
 
-int __devinit usb6fire_comm_init(struct sfire_chip *chip)
+int usb6fire_comm_init(struct sfire_chip *chip)
 {
        struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
                        GFP_KERNEL);
-       struct urb *urb = &rt->receiver;
+       struct urb *urb;
        int ret;
 
        if (!rt)
                return -ENOMEM;
 
+       urb = &rt->receiver;
        rt->serial = 1;
        rt->chip = chip;
        usb_init_urb(urb);
index d2af0a5ddcf355995087c1e111a0b447b412b6a4..6a0840b0dcff2be78366119126e5842aa4ab325f 100644 (file)
@@ -36,7 +36,7 @@ struct comm_runtime {
                        u8 vh, u8 vl);
 };
 
-int __devinit usb6fire_comm_init(struct sfire_chip *chip);
+int usb6fire_comm_init(struct sfire_chip *chip);
 void usb6fire_comm_abort(struct sfire_chip *chip);
 void usb6fire_comm_destroy(struct sfire_chip *chip);
 #endif /* USB6FIRE_COMM_H */
index 07ed914d5e71a3c165287e88f2381fac98614726..f6434c245720416f7fae946e62979a43f4b66333 100644 (file)
@@ -411,7 +411,7 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct __devinitdata snd_kcontrol_new vol_elements[] = {
+static struct snd_kcontrol_new vol_elements[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Analog Playback Volume",
@@ -451,7 +451,7 @@ static struct __devinitdata snd_kcontrol_new vol_elements[] = {
        {}
 };
 
-static struct __devinitdata snd_kcontrol_new mute_elements[] = {
+static struct snd_kcontrol_new mute_elements[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Analog Playback Switch",
@@ -485,7 +485,7 @@ static struct __devinitdata snd_kcontrol_new mute_elements[] = {
        {}
 };
 
-static struct __devinitdata snd_kcontrol_new elements[] = {
+static struct snd_kcontrol_new elements[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Line/Phono Capture Route",
@@ -561,7 +561,7 @@ static int usb6fire_control_add_virtual(
        return 0;
 }
 
-int __devinit usb6fire_control_init(struct sfire_chip *chip)
+int usb6fire_control_init(struct sfire_chip *chip)
 {
        int i;
        int ret;
index 9a596d95474a997afbf4c5e2bdaa5534c061fa19..5a40ba1434897d73cc1777d144e5d3cb4f02c587 100644 (file)
@@ -50,7 +50,7 @@ struct control_runtime {
        u8 ivol_updated;
 };
 
-int __devinit usb6fire_control_init(struct sfire_chip *chip);
+int usb6fire_control_init(struct sfire_chip *chip);
 void usb6fire_control_abort(struct sfire_chip *chip);
 void usb6fire_control_destroy(struct sfire_chip *chip);
 #endif /* USB6FIRE_CONTROL_H */
index 008569895381ff2b6c444a7ff9b1ad73a86b0a70..c109c4f75aba5a15fcbfbf2fc8998183a0112327 100644 (file)
@@ -22,6 +22,6 @@ enum /* firmware state of device */
        FW_NOT_READY = 1
 };
 
-int __devinit usb6fire_fw_init(struct usb_interface *intf);
+int usb6fire_fw_init(struct usb_interface *intf);
 #endif /* USB6FIRE_FIRMWARE_H */
 
index f0e5179b242bd48ce3c17314b96b3e27fdf5c85b..26722423330dd283b62d3fd4c5b77409913372cb 100644 (file)
@@ -146,7 +146,7 @@ static struct snd_rawmidi_ops in_ops = {
        .trigger = usb6fire_midi_in_trigger
 };
 
-int __devinit usb6fire_midi_init(struct sfire_chip *chip)
+int usb6fire_midi_init(struct sfire_chip *chip)
 {
        int ret;
        struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime),
index 5114eccc1d8ee972222ca57e8738cdfde450ec48..c321006e5430ac763e593ecee6314c6cee8fd2d6 100644 (file)
@@ -38,7 +38,7 @@ struct midi_runtime {
        void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
 };
 
-int __devinit usb6fire_midi_init(struct sfire_chip *chip);
+int usb6fire_midi_init(struct sfire_chip *chip);
 void usb6fire_midi_abort(struct sfire_chip *chip);
 void usb6fire_midi_destroy(struct sfire_chip *chip);
 #endif /* USB6FIRE_MIDI_H */
index c97d05f0e966e95b8fdc3d0778e509e360c127c1..e2ca12fe92e946f662d47ae39983e176f7a50402 100644 (file)
@@ -135,6 +135,9 @@ static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
        struct control_runtime *ctrl_rt = rt->chip->control;
 
        if (rt->stream_state != STREAM_DISABLED) {
+
+               rt->stream_state = STREAM_STOPPING;
+
                for (i = 0; i < PCM_N_URBS; i++) {
                        usb_kill_urb(&rt->in_urbs[i].instance);
                        usb_kill_urb(&rt->out_urbs[i].instance);
@@ -559,9 +562,9 @@ static struct snd_pcm_ops pcm_ops = {
        .pointer = usb6fire_pcm_pointer,
 };
 
-static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
-               struct sfire_chip *chip, bool in, int ep,
-               void (*handler)(struct urb *))
+static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
+                                 struct sfire_chip *chip, bool in, int ep,
+                                 void (*handler)(struct urb *))
 {
        urb->chip = chip;
        usb_init_urb(&urb->instance);
@@ -578,7 +581,7 @@ static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
        urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
 }
 
-int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
+int usb6fire_pcm_init(struct sfire_chip *chip)
 {
        int i;
        int ret;
index 3104301b257df032a5047b3ea0dad5d4b7d43d3e..9b01133ee3fe9c22d3f51557430f011846e5bc8a 100644 (file)
@@ -69,7 +69,7 @@ struct pcm_runtime {
        bool stream_wait_cond;
 };
 
-int __devinit usb6fire_pcm_init(struct sfire_chip *chip);
+int usb6fire_pcm_init(struct sfire_chip *chip);
 void usb6fire_pcm_abort(struct sfire_chip *chip);
 void usb6fire_pcm_destroy(struct sfire_chip *chip);
 #endif /* USB6FIRE_PCM_H */
index ff77b28f3da167fe0dd0788bfc110b52964c4b6f..225dfd737265411bead537f7f839b75863432e51 100644 (file)
@@ -90,7 +90,7 @@ config SND_USB_CAIAQ_INPUT
 
 config SND_USB_US122L
        tristate "Tascam US-122L USB driver"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        select SND_HWDEP
        select SND_RAWMIDI
        help
index 00e5d0a469e1b065a6bee10b57d9fc1c41f2d716..adb8d03267a075eecf0bdd36421c5d7534cad978 100644 (file)
@@ -137,7 +137,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
-static struct snd_kcontrol_new kcontrol_template __devinitdata = {
+static struct snd_kcontrol_new kcontrol_template = {
        .iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .index = 0,
@@ -489,8 +489,8 @@ static struct caiaq_controller kontrols4_controller[] = {
        { "LED: FX2: Mode",                     133 | CNT_INTVAL },
 };
 
-static int __devinit add_controls(struct caiaq_controller *c, int num,
-                                 struct snd_usb_caiaqdev *dev)
+static int add_controls(struct caiaq_controller *c, int num,
+                       struct snd_usb_caiaqdev *dev)
 {
        int i, ret;
        struct snd_kcontrol *kc;
@@ -507,7 +507,7 @@ static int __devinit add_controls(struct caiaq_controller *c, int num,
        return 0;
 }
 
-int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
+int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
 {
        int ret = 0;
 
index 7da0d0aa72cb1b31b88865371c9584e13fbd54e4..c828f8189c258294b0b2a681487360ea22f6e150 100644 (file)
@@ -289,7 +289,7 @@ int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *dev,
                                          tmp, sizeof(tmp));
 }
 
-static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
+static void setup_card(struct snd_usb_caiaqdev *dev)
 {
        int ret;
        char val[4];
@@ -407,7 +407,7 @@ static int create_card(struct usb_device *usb_dev,
        return 0;
 }
 
-static int __devinit init_card(struct snd_usb_caiaqdev *dev)
+static int init_card(struct snd_usb_caiaqdev *dev)
 {
        char *c, usbpath[32];
        struct usb_device *usb_dev = dev->chip.dev;
@@ -481,7 +481,7 @@ static int __devinit init_card(struct snd_usb_caiaqdev *dev)
        return 0;
 }
 
-static int __devinit snd_probe(struct usb_interface *intf,
+static int snd_probe(struct usb_interface *intf,
                     const struct usb_device_id *id)
 {
        int ret;
index dbf7999d18b4e7b300c0063f73aadf5dfa3f0f95..ccf95cfe186f324a7a7b95dc4c71e118df063706 100644 (file)
@@ -25,9 +25,6 @@
  *
  *  NOTES:
  *
- *   - async unlink should be used for avoiding the sleep inside lock.
- *     2.4.22 usb-uhci seems buggy for async unlinking and results in
- *     oops.  in such a cse, pass async_unlink=0 option.
  *   - the linked URBs would be preferred but not used so far because of
  *     the instability of unlinking.
  *   - type II is not supported properly.  there is no device which supports
@@ -83,7 +80,6 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card *
 static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int nrpacks = 8;                /* max. number of packets per urb */
-static bool async_unlink = 1;
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
 static bool ignore_ctl_error;
 
@@ -99,8 +95,6 @@ module_param_array(pid, int, NULL, 0444);
 MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
 module_param(nrpacks, int, 0644);
 MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
-module_param(async_unlink, bool, 0444);
-MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
 module_param_array(device_setup, int, NULL, 0444);
 MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
 module_param(ignore_ctl_error, bool, 0444);
@@ -345,7 +339,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        chip->card = card;
        chip->setup = device_setup[idx];
        chip->nrpacks = nrpacks;
-       chip->async_unlink = async_unlink;
        chip->probing = 1;
 
        chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
index 814cb357ff88235dd87f37425985602867e3f5d5..8a751b4887ea87043fb34483a652f0d444145d5a 100644 (file)
@@ -27,6 +27,7 @@ struct audioformat {
        unsigned int nr_rates;          /* number of rate table entries */
        unsigned int *rate_table;       /* rate table */
        unsigned char clock;            /* associated clock */
+       struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */
 };
 
 struct snd_usb_substream;
@@ -109,6 +110,7 @@ struct snd_usb_substream {
        struct audioformat *cur_audiofmt;       /* current audioformat pointer (for hw_params callback) */
        snd_pcm_format_t pcm_format;    /* current audio format (for hw_params callback) */
        unsigned int channels;          /* current number of channels (for hw_params callback) */
+       unsigned int channels_max;      /* max channels in the all audiofmts */
        unsigned int cur_rate;          /* current rate (for hw_params callback) */
        unsigned int period_bytes;      /* current period bytes (for hw_params callback) */
        unsigned int altset_idx;     /* USB data format: index of alternate setting */
index 34de6f2faf6120b492eb65208b9c9805aafe44e3..21049b882ee6445d47714074fddbcb550cf5eef8 100644 (file)
@@ -485,15 +485,10 @@ __exit_unlock:
 static int wait_clear_urbs(struct snd_usb_endpoint *ep)
 {
        unsigned long end_time = jiffies + msecs_to_jiffies(1000);
-       unsigned int i;
        int alive;
 
        do {
-               alive = 0;
-               for (i = 0; i < ep->nurbs; i++)
-                       if (test_bit(i, &ep->active_mask))
-                               alive++;
-
+               alive = bitmap_weight(&ep->active_mask, ep->nurbs);
                if (!alive)
                        break;
 
@@ -520,33 +515,24 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
 /*
  * unlink active urbs.
  */
-static int deactivate_urbs(struct snd_usb_endpoint *ep, int force, int can_sleep)
+static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
 {
        unsigned int i;
-       int async;
 
        if (!force && ep->chip->shutdown) /* to be sure... */
                return -EBADFD;
 
-       async = !can_sleep && ep->chip->async_unlink;
-
        clear_bit(EP_FLAG_RUNNING, &ep->flags);
 
        INIT_LIST_HEAD(&ep->ready_playback_urbs);
        ep->next_packet_read_pos = 0;
        ep->next_packet_write_pos = 0;
 
-       if (!async && in_interrupt())
-               return 0;
-
        for (i = 0; i < ep->nurbs; i++) {
                if (test_bit(i, &ep->active_mask)) {
                        if (!test_and_set_bit(i, &ep->unlink_mask)) {
                                struct urb *u = ep->urb[i].urb;
-                               if (async)
-                                       usb_unlink_urb(u);
-                               else
-                                       usb_kill_urb(u);
+                               usb_unlink_urb(u);
                        }
                }
        }
@@ -566,7 +552,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
        ep->prepare_data_urb = NULL;
 
        /* stop urbs */
-       deactivate_urbs(ep, force, 1);
+       deactivate_urbs(ep, force);
        wait_clear_urbs(ep);
 
        for (i = 0; i < ep->nurbs; i++)
@@ -829,7 +815,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
  *
  * Returns an error if the URB submission failed, 0 in all other cases.
  */
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
 {
        int err;
        unsigned int i;
@@ -842,7 +828,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
                return 0;
 
        /* just to be sure */
-       deactivate_urbs(ep, 0, can_sleep);
+       deactivate_urbs(ep, false);
        if (can_sleep)
                wait_clear_urbs(ep);
 
@@ -896,7 +882,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
 __error:
        clear_bit(EP_FLAG_RUNNING, &ep->flags);
        ep->use_count--;
-       deactivate_urbs(ep, 0, 0);
+       deactivate_urbs(ep, false);
        return -EPIPE;
 }
 
@@ -910,9 +896,11 @@ __error:
  * actually be deactivated.
  *
  * Must be balanced to calls of snd_usb_endpoint_start().
+ *
+ * The caller needs to synchronize the pending stop operation via
+ * snd_usb_endpoint_sync_pending_stop().
  */
-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
-                          int force, int can_sleep, int wait)
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 {
        if (!ep)
                return;
@@ -921,16 +909,12 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                return;
 
        if (--ep->use_count == 0) {
-               deactivate_urbs(ep, force, can_sleep);
+               deactivate_urbs(ep, false);
                ep->data_subs = NULL;
                ep->sync_slave = NULL;
                ep->retire_data_urb = NULL;
                ep->prepare_data_urb = NULL;
-
-               if (wait)
-                       wait_clear_urbs(ep);
-               else
-                       set_bit(EP_FLAG_STOPPING, &ep->flags);
+               set_bit(EP_FLAG_STOPPING, &ep->flags);
        }
 }
 
@@ -952,7 +936,7 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
        if (!ep)
                return -EINVAL;
 
-       deactivate_urbs(ep, 1, 1);
+       deactivate_urbs(ep, true);
        wait_clear_urbs(ep);
 
        if (ep->use_count != 0)
@@ -1034,15 +1018,18 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
                /*
                 * Iterate through the inbound packet and prepare the lengths
                 * for the output packet. The OUT packet we are about to send
-                * will have the same amount of payload bytes than the IN
-                * packet we just received.
+                * will have the same amount of payload bytes per stride as the
+                * IN packet we just received. Since the actual size is scaled
+                * by the stride, use the sender stride to calculate the length
+                * in case the number of channels differ between the implicitly
+                * fed-back endpoint and the synchronizing endpoint.
                 */
 
                out_packet->packets = in_ctx->packets;
                for (i = 0; i < in_ctx->packets; i++) {
                        if (urb->iso_frame_desc[i].status == 0)
                                out_packet->packet_size[i] =
-                                       urb->iso_frame_desc[i].actual_length / ep->stride;
+                                       urb->iso_frame_desc[i].actual_length / sender->stride;
                        else
                                out_packet->packet_size[i] = 0;
                }
index 3d4c9705041ff5074c609dd2bfb303781a523c4e..447902dd8a4a8e5ef6338d274b260c9cd41b5403 100644 (file)
@@ -16,9 +16,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
                                struct audioformat *fmt,
                                struct snd_usb_endpoint *sync_ep);
 
-int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
-                          int force, int can_sleep, int wait);
+int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep);
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
index ddfef57c4c9fbe93c9551de6af2959051bba4c21..e831ee4238bbd79b2761c942dd900d2623f0912d 100644 (file)
@@ -155,7 +155,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
        if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
                snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
                                   chip->dev->devnum, fp->iface, fp->altsetting);
-               return -1;
+               return -EINVAL;
        }
 
        if (nr_rates) {
@@ -167,7 +167,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
                fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
                if (fp->rate_table == NULL) {
                        snd_printk(KERN_ERR "cannot malloc\n");
-                       return -1;
+                       return -ENOMEM;
                }
 
                fp->nr_rates = 0;
@@ -198,7 +198,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
                }
                if (!fp->nr_rates) {
                        hwc_debug("All rates were zero. Skipping format!\n");
-                       return -1;
+                       return -EINVAL;
                }
        } else {
                /* continuous rates */
@@ -383,7 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
                fp->formats = parse_audio_format_i_type(chip, fp, format,
                                                        fmt, protocol);
                if (!fp->formats)
-                       return -1;
+                       return -EINVAL;
        }
 
        /* gather possible sample rates */
@@ -409,7 +409,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
        if (fp->channels < 1) {
                snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
                           chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
-               return -1;
+               return -EINVAL;
        }
 
        return ret;
index eeefbce3873c11dc35a6e174c4ace79daeeaa8c1..34b9bb7fe87c8eabed83df8b7b77f510bedbc2b1 100644 (file)
@@ -116,6 +116,7 @@ struct snd_usb_midi {
        struct list_head list;
        struct timer_list error_timer;
        spinlock_t disc_lock;
+       struct rw_semaphore disc_rwsem;
        struct mutex mutex;
        u32 usb_id;
        int next_midi_device;
@@ -125,8 +126,10 @@ struct snd_usb_midi {
                struct snd_usb_midi_in_endpoint *in;
        } endpoints[MIDI_MAX_ENDPOINTS];
        unsigned long input_triggered;
-       unsigned int opened;
+       bool autopm_reference;
+       unsigned int opened[2];
        unsigned char disconnected;
+       unsigned char input_running;
 
        struct snd_kcontrol *roland_load_ctl;
 };
@@ -148,7 +151,6 @@ struct snd_usb_midi_out_endpoint {
                struct snd_usb_midi_out_endpoint* ep;
                struct snd_rawmidi_substream *substream;
                int active;
-               bool autopm_reference;
                uint8_t cable;          /* cable number << 4 */
                uint8_t state;
 #define STATE_UNKNOWN  0
@@ -1033,29 +1035,58 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi)
        snd_usbmidi_input_start(&umidi->list);
 }
 
-static void substream_open(struct snd_rawmidi_substream *substream, int open)
+static int substream_open(struct snd_rawmidi_substream *substream, int dir,
+                         int open)
 {
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
        struct snd_kcontrol *ctl;
+       int err;
+
+       down_read(&umidi->disc_rwsem);
+       if (umidi->disconnected) {
+               up_read(&umidi->disc_rwsem);
+               return open ? -ENODEV : 0;
+       }
 
        mutex_lock(&umidi->mutex);
        if (open) {
-               if (umidi->opened++ == 0 && umidi->roland_load_ctl) {
-                       ctl = umidi->roland_load_ctl;
-                       ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-                       snd_ctl_notify(umidi->card,
+               if (!umidi->opened[0] && !umidi->opened[1]) {
+                       err = usb_autopm_get_interface(umidi->iface);
+                       umidi->autopm_reference = err >= 0;
+                       if (err < 0 && err != -EACCES) {
+                               mutex_unlock(&umidi->mutex);
+                               up_read(&umidi->disc_rwsem);
+                               return -EIO;
+                       }
+                       if (umidi->roland_load_ctl) {
+                               ctl = umidi->roland_load_ctl;
+                               ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+                               snd_ctl_notify(umidi->card,
                                       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
-                       update_roland_altsetting(umidi);
+                               update_roland_altsetting(umidi);
+                       }
                }
+               umidi->opened[dir]++;
+               if (umidi->opened[1])
+                       snd_usbmidi_input_start(&umidi->list);
        } else {
-               if (--umidi->opened == 0 && umidi->roland_load_ctl) {
-                       ctl = umidi->roland_load_ctl;
-                       ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-                       snd_ctl_notify(umidi->card,
+               umidi->opened[dir]--;
+               if (!umidi->opened[1])
+                       snd_usbmidi_input_stop(&umidi->list);
+               if (!umidi->opened[0] && !umidi->opened[1]) {
+                       if (umidi->roland_load_ctl) {
+                               ctl = umidi->roland_load_ctl;
+                               ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+                               snd_ctl_notify(umidi->card,
                                       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
+                       }
+                       if (umidi->autopm_reference)
+                               usb_autopm_put_interface(umidi->iface);
                }
        }
        mutex_unlock(&umidi->mutex);
+       up_read(&umidi->disc_rwsem);
+       return 0;
 }
 
 static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
@@ -1063,7 +1094,6 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
        struct usbmidi_out_port* port = NULL;
        int i, j;
-       int err;
 
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
                if (umidi->endpoints[i].out)
@@ -1076,25 +1106,15 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
                snd_BUG();
                return -ENXIO;
        }
-       err = usb_autopm_get_interface(umidi->iface);
-       port->autopm_reference = err >= 0;
-       if (err < 0 && err != -EACCES)
-               return -EIO;
+
        substream->runtime->private_data = port;
        port->state = STATE_UNKNOWN;
-       substream_open(substream, 1);
-       return 0;
+       return substream_open(substream, 0, 1);
 }
 
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
-       struct snd_usb_midi* umidi = substream->rmidi->private_data;
-       struct usbmidi_out_port *port = substream->runtime->private_data;
-
-       substream_open(substream, 0);
-       if (port->autopm_reference)
-               usb_autopm_put_interface(umidi->iface);
-       return 0;
+       return substream_open(substream, 0, 0);
 }
 
 static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -1147,14 +1167,12 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
 
 static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
 {
-       substream_open(substream, 1);
-       return 0;
+       return substream_open(substream, 1, 1);
 }
 
 static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
 {
-       substream_open(substream, 0);
-       return 0;
+       return substream_open(substream, 1, 0);
 }
 
 static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -1403,9 +1421,12 @@ void snd_usbmidi_disconnect(struct list_head* p)
         * a timer may submit an URB. To reliably break the cycle
         * a flag under lock must be used
         */
+       down_write(&umidi->disc_rwsem);
        spin_lock_irq(&umidi->disc_lock);
        umidi->disconnected = 1;
        spin_unlock_irq(&umidi->disc_lock);
+       up_write(&umidi->disc_rwsem);
+
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
                struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
                if (ep->out)
@@ -2060,12 +2081,15 @@ void snd_usbmidi_input_stop(struct list_head* p)
        unsigned int i, j;
 
        umidi = list_entry(p, struct snd_usb_midi, list);
+       if (!umidi->input_running)
+               return;
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
                struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
                if (ep->in)
                        for (j = 0; j < INPUT_URBS; ++j)
                                usb_kill_urb(ep->in->urbs[j]);
        }
+       umidi->input_running = 0;
 }
 
 static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
@@ -2090,8 +2114,11 @@ void snd_usbmidi_input_start(struct list_head* p)
        int i;
 
        umidi = list_entry(p, struct snd_usb_midi, list);
+       if (umidi->input_running || !umidi->opened[1])
+               return;
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
                snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+       umidi->input_running = 1;
 }
 
 /*
@@ -2117,6 +2144,7 @@ int snd_usbmidi_create(struct snd_card *card,
        umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
        init_timer(&umidi->error_timer);
        spin_lock_init(&umidi->disc_lock);
+       init_rwsem(&umidi->disc_rwsem);
        mutex_init(&umidi->mutex);
        umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
                               le16_to_cpu(umidi->dev->descriptor.idProduct));
@@ -2229,9 +2257,6 @@ int snd_usbmidi_create(struct snd_card *card,
        }
 
        list_add_tail(&umidi->list, midi_list);
-
-       for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-               snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
        return 0;
 }
 
index 298070e8f2d4e354da19dbca3e3d704a7b799321..ed4d89c8b52a52e6425ce5c992cc5d324b339d35 100644 (file)
@@ -382,6 +382,8 @@ error:
 
 static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 {
+       validx += cval->idx_off;
+
        return (cval->mixer->protocol == UAC_VERSION_1) ?
                get_ctl_value_v1(cval, request, validx, value_ret) :
                get_ctl_value_v2(cval, request, validx, value_ret);
@@ -432,6 +434,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
        unsigned char buf[2];
        int idx = 0, val_len, err, timeout = 10;
 
+       validx += cval->idx_off;
+
        if (cval->mixer->protocol == UAC_VERSION_1) {
                val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
        } else { /* UAC_VERSION_2 */
@@ -719,8 +723,19 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                        return 0;
                }
                case UAC1_PROCESSING_UNIT:
-               case UAC1_EXTENSION_UNIT: {
+               case UAC1_EXTENSION_UNIT:
+               /* UAC2_PROCESSING_UNIT_V2 */
+               /* UAC2_EFFECT_UNIT */ {
                        struct uac_processing_unit_descriptor *d = p1;
+
+                       if (state->mixer->protocol == UAC_VERSION_2 &&
+                               hdr[2] == UAC2_EFFECT_UNIT) {
+                               /* UAC2/UAC1 unit IDs overlap here in an
+                                * uncompatible way. Ignore this unit for now.
+                                */
+                               return 0;
+                       }
+
                        if (d->bNrInPins) {
                                id = d->baSourceID[0];
                                break; /* continue to parse */
@@ -791,6 +806,33 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
                                  struct snd_kcontrol *kctl)
 {
        switch (cval->mixer->chip->usb_id) {
+       case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+               if (strcmp(kctl->id.name, "Effect Duration") == 0) {
+                       cval->min = 0x0000;
+                       cval->max = 0xffff;
+                       cval->res = 0x00e6;
+                       break;
+               }
+               if (strcmp(kctl->id.name, "Effect Volume") == 0 ||
+                   strcmp(kctl->id.name, "Effect Feedback Volume") == 0) {
+                       cval->min = 0x00;
+                       cval->max = 0xff;
+                       break;
+               }
+               if (strstr(kctl->id.name, "Effect Return") != NULL) {
+                       cval->min = 0xb706;
+                       cval->max = 0xff7b;
+                       cval->res = 0x0073;
+                       break;
+               }
+               if ((strstr(kctl->id.name, "Playback Volume") != NULL) ||
+                       (strstr(kctl->id.name, "Effect Send") != NULL)) {
+                       cval->min = 0xb5fb; /* -73 dB = 0xb6ff */
+                       cval->max = 0xfcfe;
+                       cval->res = 0x0073;
+               }
+               break;
+
        case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
        case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
                if (strcmp(kctl->id.name, "Effect Duration") == 0) {
@@ -1094,6 +1136,32 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
        return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
 }
 
+/* A lot of headsets/headphones have a "Speaker" mixer. Make sure we
+   rename it to "Headphone". We determine if something is a headphone
+   similar to how udev determines form factor. */
+static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
+                                       struct snd_card *card)
+{
+       const char *names_to_check[] = {
+               "Headset", "headset", "Headphone", "headphone", NULL};
+       const char **s;
+       bool found = 0;
+
+       if (strcmp("Speaker", kctl->id.name))
+               return;
+
+       for (s = names_to_check; *s; s++)
+               if (strstr(card->shortname, *s)) {
+                       found = 1;
+                       break;
+               }
+
+       if (!found)
+               return;
+
+       strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
+}
+
 static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                              unsigned int ctl_mask, int control,
                              struct usb_audio_term *iterm, int unitid,
@@ -1180,6 +1248,10 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                                len = snprintf(kctl->id.name, sizeof(kctl->id.name),
                                               "Feature %d", unitid);
                }
+
+               if (!mapped_name)
+                       check_no_speaker_on_headset(kctl, state->mixer->chip->card);
+
                /* determine the stream direction:
                 * if the connected output is USB stream, then it's likely a
                 * capture stream.  otherwise it should be playback (hopefully :)
index a7f3d45a8acf1f6255a86f88038ca64012069137..aab80df201bdde8f6015d9b2451abb0c24efddb7 100644 (file)
@@ -43,6 +43,7 @@ struct usb_mixer_elem_info {
        unsigned int id;
        unsigned int control;   /* CS or ICN (high byte) */
        unsigned int cmask; /* channel mask bitmap: 0 = master */
+       unsigned int idx_off; /* Control index offset */
        unsigned int ch_readonly;
        unsigned int master_readonly;
        int channels;
index ae2b7143522097bffd2a6060721d4f3db6b8000e..0422b1360af3a896da708a79365e3370be771fd8 100644 (file)
@@ -63,11 +63,12 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
  * Since there doesn't seem to be a devices that needs a multichannel
  * version, we keep it mono for simplicity.
  */
-static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
+static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer,
                                unsigned int unitid,
                                unsigned int control,
                                unsigned int cmask,
                                int val_type,
+                               unsigned int idx_off,
                                const char *name,
                                snd_kcontrol_tlv_rw_t *tlv_callback)
 {
@@ -85,6 +86,7 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
        cval->channels = 1;
        cval->control = control;
        cval->cmask = cmask;
+       cval->idx_off = idx_off;
 
        /* get_min_max() is called only for integer volumes later,
         * so provide a short-cut for booleans */
@@ -120,6 +122,18 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
        return 0;
 }
 
+static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
+                               unsigned int unitid,
+                               unsigned int control,
+                               unsigned int cmask,
+                               int val_type,
+                               const char *name,
+                               snd_kcontrol_tlv_rw_t *tlv_callback)
+{
+       return snd_create_std_mono_ctl_offset(mixer, unitid, control, cmask,
+               val_type, 0 /* Offset */, name, tlv_callback);
+}
+
 /*
  * Create a set of standard UAC controls from a table
  */
@@ -416,6 +430,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
        }
 }
 
+/* ASUS Xonar U1 / U3 controls */
+
 static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
                                   struct snd_ctl_elem_value *ucontrol)
 {
@@ -621,11 +637,13 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
 }
 
 /* M-Audio FastTrack Ultra quirks */
-/* FTU Effect switch */
+/* FTU Effect switch (also used by C400) */
 struct snd_ftu_eff_switch_priv_val {
        struct usb_mixer_interface *mixer;
        int cached_value;
        int is_cached;
+       int bUnitID;
+       int validx;
 };
 
 static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol,
@@ -660,9 +678,8 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
        struct snd_ftu_eff_switch_priv_val *pval;
        int err;
        unsigned char value[2];
+       int id, validx;
 
-       const int id = 6;
-       const int validx = 1;
        const int val_len = 2;
 
        value[0] = 0x00;
@@ -684,6 +701,8 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
        if (snd_BUG_ON(!chip))
                return -EINVAL;
 
+       id = pval->bUnitID;
+       validx = pval->validx;
 
        down_read(&mixer->chip->shutdown_rwsem);
        if (mixer->chip->shutdown)
@@ -714,10 +733,8 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        struct usb_mixer_interface *mixer;
        int changed, cur_val, err, new_val;
        unsigned char value[2];
+       int id, validx;
 
-
-       const int id = 6;
-       const int validx = 1;
        const int val_len = 2;
 
        changed = 0;
@@ -735,6 +752,9 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        if (snd_BUG_ON(!chip))
                return -EINVAL;
 
+       id = pval->bUnitID;
+       validx = pval->validx;
+
        if (!pval->is_cached) {
                /* Read current value */
                down_read(&mixer->chip->shutdown_rwsem);
@@ -779,7 +799,8 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        return changed;
 }
 
-static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
+static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
+       int validx, int bUnitID)
 {
        static struct snd_kcontrol_new template = {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -802,6 +823,8 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
        pval->cached_value = 0;
        pval->is_cached = 0;
        pval->mixer = mixer;
+       pval->bUnitID = bUnitID;
+       pval->validx = validx;
 
        template.private_value = (unsigned long) pval;
        kctl = snd_ctl_new1(&template, mixer->chip);
@@ -960,9 +983,10 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer)
        if (err < 0)
                return err;
 
-       err = snd_ftu_create_effect_switch(mixer);
+       err = snd_ftu_create_effect_switch(mixer, 1, 6);
        if (err < 0)
                return err;
+
        err = snd_ftu_create_effect_volume_ctl(mixer);
        if (err < 0)
                return err;
@@ -1005,6 +1029,178 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
        }
 }
 
+/* M-Audio Fast Track C400 */
+/* C400 volume controls, this control needs a volume quirk, see mixer.c */
+static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer)
+{
+       char name[64];
+       unsigned int cmask, offset;
+       int out, chan, err;
+
+       const unsigned int id = 0x40;
+       const int val_type = USB_MIXER_S16;
+       const int control = 1;
+
+       for (chan = 0; chan < 10; chan++) {
+               for (out = 0; out < 6; out++) {
+                       if (chan < 6) {
+                               snprintf(name, sizeof(name),
+                                       "PCM%d-Out%d Playback Volume",
+                                       chan + 1, out + 1);
+                       } else {
+                               snprintf(name, sizeof(name),
+                                       "In%d-Out%d Playback Volume",
+                                       chan - 5, out + 1);
+                       }
+
+                       cmask = (out == 0) ? 0 : 1 << (out - 1);
+                       offset = chan * 6;
+                       err = snd_create_std_mono_ctl_offset(mixer, id, control,
+                                               cmask, val_type, offset, name,
+                                               &snd_usb_mixer_vol_tlv);
+                       if (err < 0)
+                               return err;
+               }
+       }
+
+       return 0;
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_c400_create_effect_volume_ctl(struct usb_mixer_interface *mixer)
+{
+       static const char name[] = "Effect Volume";
+       const unsigned int id = 0x43;
+       const int val_type = USB_MIXER_U8;
+       const unsigned int control = 3;
+       const unsigned int cmask = 0;
+
+       return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+                                       name, snd_usb_mixer_vol_tlv);
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_c400_create_effect_duration_ctl(struct usb_mixer_interface *mixer)
+{
+       static const char name[] = "Effect Duration";
+       const unsigned int id = 0x43;
+       const int val_type = USB_MIXER_S16;
+       const unsigned int control = 4;
+       const unsigned int cmask = 0;
+
+       return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+                                       name, snd_usb_mixer_vol_tlv);
+}
+
+/* This control needs a volume quirk, see mixer.c */
+static int snd_c400_create_effect_feedback_ctl(struct usb_mixer_interface *mixer)
+{
+       static const char name[] = "Effect Feedback Volume";
+       const unsigned int id = 0x43;
+       const int val_type = USB_MIXER_U8;
+       const unsigned int control = 5;
+       const unsigned int cmask = 0;
+
+       return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
+                                       name, NULL);
+}
+
+static int snd_c400_create_effect_vol_ctls(struct usb_mixer_interface *mixer)
+{
+       char name[64];
+       unsigned int cmask;
+       int chan, err;
+
+       const unsigned int id = 0x42;
+       const int val_type = USB_MIXER_S16;
+       const int control = 1;
+
+       for (chan = 0; chan < 10; chan++) {
+               if (chan < 6) {
+                       snprintf(name, sizeof(name),
+                               "Effect Send DOut%d",
+                               chan + 1);
+               } else {
+                       snprintf(name, sizeof(name),
+                               "Effect Send AIn%d",
+                               chan - 5);
+               }
+
+               cmask = (chan == 0) ? 0 : 1 << (chan - 1);
+               err = snd_create_std_mono_ctl(mixer, id, control,
+                                               cmask, val_type, name,
+                                               &snd_usb_mixer_vol_tlv);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer)
+{
+       char name[64];
+       unsigned int cmask;
+       int chan, err;
+
+       const unsigned int id = 0x40;
+       const int val_type = USB_MIXER_S16;
+       const int control = 1;
+       const int chan_id[6] = { 0, 7, 2, 9, 4, 0xb };
+       const unsigned int offset = 0x3c;
+                               /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */
+
+       for (chan = 0; chan < 6; chan++) {
+               snprintf(name, sizeof(name),
+                       "Effect Return %d",
+                       chan + 1);
+
+               cmask = (chan_id[chan] == 0) ? 0 : 1 << (chan_id[chan] - 1);
+               err = snd_create_std_mono_ctl_offset(mixer, id, control,
+                                               cmask, val_type, offset, name,
+                                               &snd_usb_mixer_vol_tlv);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
+{
+       int err;
+
+       err = snd_c400_create_vol_ctls(mixer);
+       if (err < 0)
+               return err;
+
+       err = snd_c400_create_effect_vol_ctls(mixer);
+       if (err < 0)
+               return err;
+
+       err = snd_c400_create_effect_ret_vol_ctls(mixer);
+       if (err < 0)
+               return err;
+
+       err = snd_ftu_create_effect_switch(mixer, 2, 0x43);
+       if (err < 0)
+               return err;
+
+       err = snd_c400_create_effect_volume_ctl(mixer);
+       if (err < 0)
+               return err;
+
+       err = snd_c400_create_effect_duration_ctl(mixer);
+       if (err < 0)
+               return err;
+
+       err = snd_c400_create_effect_feedback_ctl(mixer);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
 /*
  * The mixer units for Ebox-44 are corrupt, and even where they
  * are valid they presents mono controls as L and R channels of
@@ -1102,13 +1298,18 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
                                              snd_audigy2nx_proc_read);
                break;
 
+       case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+               err = snd_c400_create_mixer(mixer);
+               break;
+
        case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
        case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
                err = snd_ftu_create_mixer(mixer);
                break;
 
-       case USB_ID(0x0b05, 0x1739):
-       case USB_ID(0x0b05, 0x1743):
+       case USB_ID(0x0b05, 0x1739): /* ASUS Xonar U1 */
+       case USB_ID(0x0b05, 0x1743): /* ASUS Xonar U1 (2) */
+       case USB_ID(0x0b05, 0x17a0): /* ASUS Xonar U3 */
                err = snd_xonar_u1_controls_create(mixer);
                break;
 
index ef6fa24fc473b08a89dd33ef8158f004185f54cb..c6593101c049b88ca6e5661f8765b3f3df0b4d33 100644 (file)
@@ -46,6 +46,9 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
        int frame_diff;
        int est_delay;
 
+       if (!subs->last_delay)
+               return 0; /* short path */
+
        current_frame_number = usb_get_current_frame_number(subs->dev);
        /*
         * HCD implementations use different widths, use lower 8 bits.
@@ -75,7 +78,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
                return SNDRV_PCM_POS_XRUN;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
-       substream->runtime->delay = snd_usb_pcm_delay(subs,
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               substream->runtime->delay = snd_usb_pcm_delay(subs,
                                                substream->runtime->rate);
        spin_unlock(&subs->lock);
        return hwptr_done / (substream->runtime->frame_bits >> 3);
@@ -173,11 +177,8 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
 {
        struct usb_device *dev = chip->dev;
        unsigned char data[1];
-       unsigned int ep;
        int err;
 
-       ep = get_endpoint(alts, 0)->bEndpointAddress;
-
        data[0] = 1;
        if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
                                   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
@@ -214,7 +215,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
        }
 }
 
-static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
+static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
 {
        int err;
 
@@ -266,16 +267,18 @@ static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
        return 0;
 }
 
-static void stop_endpoints(struct snd_usb_substream *subs,
-                          int force, int can_sleep, int wait)
+static void stop_endpoints(struct snd_usb_substream *subs, bool wait)
 {
        if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
-               snd_usb_endpoint_stop(subs->sync_endpoint,
-                                     force, can_sleep, wait);
+               snd_usb_endpoint_stop(subs->sync_endpoint);
 
        if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
-               snd_usb_endpoint_stop(subs->data_endpoint,
-                                     force, can_sleep, wait);
+               snd_usb_endpoint_stop(subs->data_endpoint);
+
+       if (wait) {
+               snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+               snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
+       }
 }
 
 static int deactivate_endpoints(struct snd_usb_substream *subs)
@@ -359,6 +362,19 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
 
        switch (subs->stream->chip->usb_id) {
+       case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
+               if (is_playback) {
+                       implicit_fb = 1;
+                       ep = 0x81;
+                       iface = usb_ifnum_to_if(dev, 3);
+
+                       if (!iface || iface->num_altsetting == 0)
+                               return -EINVAL;
+
+                       alts = &iface->altsetting[1];
+                       goto add_sync_ep;
+               }
+               break;
        case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
        case USB_ID(0x0763, 0x2081):
                if (is_playback) {
@@ -381,7 +397,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
                /* ... and check descriptor size before accessing bSynchAddress
                   because there is a version of the SB Audigy 2 NX firmware lacking
                   the audio fields in the endpoint descriptors */
-               if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 ||
+               if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
                    (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
                     get_endpoint(alts, 1)->bSynchAddress != 0 &&
                     !implicit_fb)) {
@@ -437,6 +453,103 @@ add_sync_ep:
        return 0;
 }
 
+/*
+ * Return the score of matching two audioformats.
+ * Veto the audioformat if:
+ * - It has no channels for some reason.
+ * - Requested PCM format is not supported.
+ * - Requested sample rate is not supported.
+ */
+static int match_endpoint_audioformats(struct audioformat *fp,
+       struct audioformat *match, int rate,
+       snd_pcm_format_t pcm_format)
+{
+       int i;
+       int score = 0;
+
+       if (fp->channels < 1) {
+               snd_printdd("%s: (fmt @%p) no channels\n", __func__, fp);
+               return 0;
+       }
+
+       if (!(fp->formats & (1ULL << pcm_format))) {
+               snd_printdd("%s: (fmt @%p) no match for format %d\n", __func__,
+                       fp, pcm_format);
+               return 0;
+       }
+
+       for (i = 0; i < fp->nr_rates; i++) {
+               if (fp->rate_table[i] == rate) {
+                       score++;
+                       break;
+               }
+       }
+       if (!score) {
+               snd_printdd("%s: (fmt @%p) no match for rate %d\n", __func__,
+                       fp, rate);
+               return 0;
+       }
+
+       if (fp->channels == match->channels)
+               score++;
+
+       snd_printdd("%s: (fmt @%p) score %d\n", __func__, fp, score);
+
+       return score;
+}
+
+/*
+ * Configure the sync ep using the rate and pcm format of the data ep.
+ */
+static int configure_sync_endpoint(struct snd_usb_substream *subs)
+{
+       int ret;
+       struct audioformat *fp;
+       struct audioformat *sync_fp = NULL;
+       int cur_score = 0;
+       int sync_period_bytes = subs->period_bytes;
+       struct snd_usb_substream *sync_subs =
+               &subs->stream->substream[subs->direction ^ 1];
+
+       /* Try to find the best matching audioformat. */
+       list_for_each_entry(fp, &sync_subs->fmt_list, list) {
+               int score = match_endpoint_audioformats(fp, subs->cur_audiofmt,
+                       subs->cur_rate, subs->pcm_format);
+
+               if (score > cur_score) {
+                       sync_fp = fp;
+                       cur_score = score;
+               }
+       }
+
+       if (unlikely(sync_fp == NULL)) {
+               snd_printk(KERN_ERR "%s: no valid audioformat for sync ep %x found\n",
+                       __func__, sync_subs->ep_num);
+               return -EINVAL;
+       }
+
+       /*
+        * Recalculate the period bytes if channel number differ between
+        * data and sync ep audioformat.
+        */
+       if (sync_fp->channels != subs->channels) {
+               sync_period_bytes = (subs->period_bytes / subs->channels) *
+                       sync_fp->channels;
+               snd_printdd("%s: adjusted sync ep period bytes (%d -> %d)\n",
+                       __func__, subs->period_bytes, sync_period_bytes);
+       }
+
+       ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
+                                         subs->pcm_format,
+                                         sync_fp->channels,
+                                         sync_period_bytes,
+                                         subs->cur_rate,
+                                         sync_fp,
+                                         NULL);
+
+       return ret;
+}
+
 /*
  * configure endpoint params
  *
@@ -447,7 +560,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
        int ret;
 
        /* format changed */
-       stop_endpoints(subs, 0, 0, 0);
+       stop_endpoints(subs, true);
        ret = snd_usb_endpoint_set_params(subs->data_endpoint,
                                          subs->pcm_format,
                                          subs->channels,
@@ -459,13 +572,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                return ret;
 
        if (subs->sync_endpoint)
-               ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
-                                                 subs->pcm_format,
-                                                 subs->channels,
-                                                 subs->period_bytes,
-                                                 subs->cur_rate,
-                                                 subs->cur_audiofmt,
-                                                 NULL);
+               ret = configure_sync_endpoint(subs);
+
        return ret;
 }
 
@@ -533,7 +641,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->period_bytes = 0;
        down_read(&subs->stream->chip->shutdown_rwsem);
        if (!subs->stream->chip->shutdown) {
-               stop_endpoints(subs, 0, 1, 1);
+               stop_endpoints(subs, true);
                deactivate_endpoints(subs);
        }
        up_read(&subs->stream->chip->shutdown_rwsem);
@@ -608,7 +716,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               ret = start_endpoints(subs, 1);
+               ret = start_endpoints(subs, true);
 
  unlock:
        up_read(&subs->stream->chip->shutdown_rwsem);
@@ -1013,7 +1121,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
        struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
        struct snd_usb_substream *subs = &as->substream[direction];
 
-       stop_endpoints(subs, 0, 0, 0);
+       stop_endpoints(subs, true);
 
        if (!as->chip->shutdown && subs->interface >= 0) {
                usb_set_interface(subs->dev, subs->interface, 0);
@@ -1195,6 +1303,9 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
                return;
 
        spin_lock_irqsave(&subs->lock, flags);
+       if (!subs->last_delay)
+               goto out; /* short path */
+
        est_delay = snd_usb_pcm_delay(subs, runtime->rate);
        /* update delay with exact number of samples played */
        if (processed > subs->last_delay)
@@ -1212,6 +1323,15 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
                snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
                        est_delay, subs->last_delay);
 
+       if (!subs->running) {
+               /* update last_frame_number for delay counting here since
+                * prepare_playback_urb won't be called during pause
+                */
+               subs->last_frame_number =
+                       usb_get_current_frame_number(subs->dev) & 0xff;
+       }
+
+ out:
        spin_unlock_irqrestore(&subs->lock, flags);
 }
 
@@ -1248,12 +1368,13 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
                subs->running = 1;
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
-               stop_endpoints(subs, 0, 0, 0);
+               stop_endpoints(subs, false);
                subs->running = 0;
                return 0;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                subs->data_endpoint->prepare_data_urb = NULL;
-               subs->data_endpoint->retire_data_urb = NULL;
+               /* keep retire_data_urb for delay calculation */
+               subs->data_endpoint->retire_data_urb = retire_playback_urb;
                subs->running = 0;
                return 0;
        }
@@ -1269,7 +1390,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               err = start_endpoints(subs, 0);
+               err = start_endpoints(subs, false);
                if (err < 0)
                        return err;
 
@@ -1277,7 +1398,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
                subs->running = 1;
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
-               stop_endpoints(subs, 0, 0, 0);
+               stop_endpoints(subs, false);
                subs->running = 0;
                return 0;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
index 88d8cebbb244ade66eb43db91be9d9b5cf9669d5..49f9af995d7af3cf6fda51ef8d76102e8e40177a 100644 (file)
@@ -1456,6 +1456,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* Advanced mode of the Roland VG-99, with MIDI and 24-bit PCM at 44.1
+        * kHz. In standard mode, the device has ID 0582:00b3, and offers
+        * 16-bit PCM at 44.1 kHz with no MIDI.
+        */
+       USB_DEVICE(0x0582, 0x00b2),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Roland",
+               .product_name = "VG-99",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0003,
+                                       .in_cables  = 0x0003
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        /* Roland SonicCell */
        USB_DEVICE(0x0582, 0x00c2),
@@ -2162,6 +2196,77 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2030),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "M-Audio", */
+               /* .product_name = "Fast Track C400", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
+                       },
+                       /* Playback */
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x01,
+                                       .ep_attr = 0x09,
+                                       .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
+                                       },
+                                       .clock = 0x81,
+                               }
+                       },
+                       /* Capture */
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 3,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x81,
+                                       .ep_attr = 0x05,
+                                       .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
+                                       },
+                                       .clock = 0x81,
+                               }
+                       },
+                       /* MIDI */
+                       {
+                               .ifnum = -1 /* Interface = 4 */
+                       }
+               }
+       }
+},
 {
        USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -2880,6 +2985,99 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
+/* Reloop Play */
+{
+       USB_DEVICE(0x200c, 0x100b),
+       .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_SYNC_ADAPTIVE,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000,
+                                       .rate_min = 44100,
+                                       .rate_max = 48000,
+                                       .nr_rates = 2,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
+{
+       /*
+        * Focusrite Scarlett 18i6
+        *
+        * Avoid mixer creation, which otherwise fails because some of
+        * the interface descriptor subtypes for interface 0 are
+        * unknown.  That should be fixed or worked-around but this at
+        * least allows the device to be used successfully with a DAW
+        * and an external mixer.  See comments below about other
+        * ignored interfaces.
+        */
+       USB_DEVICE(0x1235, 0x8004),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Focusrite",
+               .product_name = "Scarlett 18i6",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = & (const struct snd_usb_audio_quirk[]) {
+                       {
+                               /* InterfaceSubClass 1 (Control Device) */
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               /* InterfaceSubClass 1 (Control Device) */
+                               .ifnum = 3,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 4,
+                               .type = QUIRK_MIDI_STANDARD_INTERFACE
+                       },
+                       {
+                               /* InterfaceSubClass 1 (Device Firmware Update) */
+                               .ifnum = 5,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 {
        /*
         * Some USB MIDI devices don't have an audio control interface,
index 0f58b4b6d7023d0e4c47734216e276132c2fbe80..007fcecdf5cd1fa9536a24d6cac9059071393c69 100644 (file)
@@ -675,7 +675,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
  */
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
 {
-       /* it depends on altsetting wether the device is big-endian or not */
+       /* it depends on altsetting whether the device is big-endian or not */
        switch (chip->usb_id) {
        case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
                if (fp->altsetting == 2 || fp->altsetting == 3 ||
index 1de0c8c002a8a2d35bc80e7de9a9c764a5945fc2..ad181d538bd9658edd79fec07d2fae125c9ebd38 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <sound/core.h>
 #include <sound/pcm.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
 
 #include "usbaudio.h"
 #include "card.h"
@@ -47,6 +49,7 @@ static void free_substream(struct snd_usb_substream *subs)
        list_for_each_safe(p, n, &subs->fmt_list) {
                struct audioformat *fp = list_entry(p, struct audioformat, list);
                kfree(fp->rate_table);
+               kfree(fp->chmap);
                kfree(fp);
        }
        kfree(subs->rate_list.list);
@@ -99,6 +102,206 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->num_formats++;
        subs->fmt_type = fp->fmt_type;
        subs->ep_num = fp->endpoint;
+       if (fp->channels > subs->channels_max)
+               subs->channels_max = fp->channels;
+}
+
+/* kctl callbacks for usb-audio channel maps */
+static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+       struct snd_usb_substream *subs = info->private_data;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = subs->channels_max;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = SNDRV_CHMAP_LAST;
+       return 0;
+}
+
+/* check whether a duplicated entry exists in the audiofmt list */
+static bool have_dup_chmap(struct snd_usb_substream *subs,
+                          struct audioformat *fp)
+{
+       struct list_head *p;
+
+       for (p = fp->list.prev; p != &subs->fmt_list; p = p->prev) {
+               struct audioformat *prev;
+               prev = list_entry(p, struct audioformat, list);
+               if (prev->chmap &&
+                   !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
+                       return true;
+       }
+       return false;
+}
+
+static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+                            unsigned int size, unsigned int __user *tlv)
+{
+       struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+       struct snd_usb_substream *subs = info->private_data;
+       struct audioformat *fp;
+       unsigned int __user *dst;
+       int count = 0;
+
+       if (size < 8)
+               return -ENOMEM;
+       if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
+               return -EFAULT;
+       size -= 8;
+       dst = tlv + 2;
+       list_for_each_entry(fp, &subs->fmt_list, list) {
+               int i, ch_bytes;
+
+               if (!fp->chmap)
+                       continue;
+               if (have_dup_chmap(subs, fp))
+                       continue;
+               /* copy the entry */
+               ch_bytes = fp->chmap->channels * 4;
+               if (size < 8 + ch_bytes)
+                       return -ENOMEM;
+               if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
+                   put_user(ch_bytes, dst + 1))
+                       return -EFAULT;
+               dst += 2;
+               for (i = 0; i < fp->chmap->channels; i++, dst++) {
+                       if (put_user(fp->chmap->map[i], dst))
+                               return -EFAULT;
+               }
+
+               count += 8 + ch_bytes;
+               size -= 8 + ch_bytes;
+       }
+       if (put_user(count, tlv + 1))
+               return -EFAULT;
+       return 0;
+}
+
+static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+       struct snd_usb_substream *subs = info->private_data;
+       struct snd_pcm_chmap_elem *chmap = NULL;
+       int i;
+
+       memset(ucontrol->value.integer.value, 0,
+              sizeof(ucontrol->value.integer.value));
+       if (subs->cur_audiofmt)
+               chmap = subs->cur_audiofmt->chmap;
+       if (chmap) {
+               for (i = 0; i < chmap->channels; i++)
+                       ucontrol->value.integer.value[i] = chmap->map[i];
+       }
+       return 0;
+}
+
+/* create a chmap kctl assigned to the given USB substream */
+static int add_chmap(struct snd_pcm *pcm, int stream,
+                    struct snd_usb_substream *subs)
+{
+       struct audioformat *fp;
+       struct snd_pcm_chmap *chmap;
+       struct snd_kcontrol *kctl;
+       int err;
+
+       list_for_each_entry(fp, &subs->fmt_list, list)
+               if (fp->chmap)
+                       goto ok;
+       /* no chmap is found */
+       return 0;
+
+ ok:
+       err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap);
+       if (err < 0)
+               return err;
+
+       /* override handlers */
+       chmap->private_data = subs;
+       kctl = chmap->kctl;
+       kctl->info = usb_chmap_ctl_info;
+       kctl->get = usb_chmap_ctl_get;
+       kctl->tlv.c = usb_chmap_ctl_tlv;
+
+       return 0;
+}
+
+/* convert from USB ChannelConfig bits to ALSA chmap element */
+static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
+                                               int protocol)
+{
+       static unsigned int uac1_maps[] = {
+               SNDRV_CHMAP_FL,         /* left front */
+               SNDRV_CHMAP_FR,         /* right front */
+               SNDRV_CHMAP_FC,         /* center front */
+               SNDRV_CHMAP_LFE,        /* LFE */
+               SNDRV_CHMAP_SL,         /* left surround */
+               SNDRV_CHMAP_SR,         /* right surround */
+               SNDRV_CHMAP_FLC,        /* left of center */
+               SNDRV_CHMAP_FRC,        /* right of center */
+               SNDRV_CHMAP_RC,         /* surround */
+               SNDRV_CHMAP_SL,         /* side left */
+               SNDRV_CHMAP_SR,         /* side right */
+               SNDRV_CHMAP_TC,         /* top */
+               0 /* terminator */
+       };
+       static unsigned int uac2_maps[] = {
+               SNDRV_CHMAP_FL,         /* front left */
+               SNDRV_CHMAP_FR,         /* front right */
+               SNDRV_CHMAP_FC,         /* front center */
+               SNDRV_CHMAP_LFE,        /* LFE */
+               SNDRV_CHMAP_RL,         /* back left */
+               SNDRV_CHMAP_RR,         /* back right */
+               SNDRV_CHMAP_FLC,        /* front left of center */
+               SNDRV_CHMAP_FRC,        /* front right of center */
+               SNDRV_CHMAP_RC,         /* back center */
+               SNDRV_CHMAP_SL,         /* side left */
+               SNDRV_CHMAP_SR,         /* side right */
+               SNDRV_CHMAP_TC,         /* top center */
+               SNDRV_CHMAP_TFL,        /* top front left */
+               SNDRV_CHMAP_TFC,        /* top front center */
+               SNDRV_CHMAP_TFR,        /* top front right */
+               SNDRV_CHMAP_TRL,        /* top back left */
+               SNDRV_CHMAP_TRC,        /* top back center */
+               SNDRV_CHMAP_TRR,        /* top back right */
+               SNDRV_CHMAP_TFLC,       /* top front left of center */
+               SNDRV_CHMAP_TFRC,       /* top front right of center */
+               SNDRV_CHMAP_LLFE,       /* left LFE */
+               SNDRV_CHMAP_RLFE,       /* right LFE */
+               SNDRV_CHMAP_TSL,        /* top side left */
+               SNDRV_CHMAP_TSR,        /* top side right */
+               SNDRV_CHMAP_BC,         /* bottom center */
+               SNDRV_CHMAP_BLC,        /* bottom left center */
+               SNDRV_CHMAP_BRC,        /* bottom right center */
+               0 /* terminator */
+       };
+       struct snd_pcm_chmap_elem *chmap;
+       const unsigned int *maps;
+       int c;
+
+       if (!bits)
+               return NULL;
+       if (channels > ARRAY_SIZE(chmap->map))
+               return NULL;
+
+       chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
+       if (!chmap)
+               return NULL;
+
+       maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
+       chmap->channels = channels;
+       c = 0;
+       for (; bits && *maps; maps++, bits >>= 1) {
+               if (bits & 1)
+                       chmap->map[c++] = *maps;
+       }
+
+       for (; c < channels; c++)
+               chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
+
+       return chmap;
 }
 
 /*
@@ -140,7 +343,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                if (err < 0)
                        return err;
                snd_usb_init_substream(as, stream, fp);
-               return 0;
+               return add_chmap(as->pcm, stream, subs);
        }
 
        /* create a new pcm */
@@ -174,7 +377,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
 
        snd_usb_proc_pcm_format_add(as);
 
-       return 0;
+       return add_chmap(pcm, stream, &as->substream[stream]);
 }
 
 static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
@@ -218,8 +421,11 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
        return attributes;
 }
 
-static struct uac2_input_terminal_descriptor *
-       snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+/* find an input terminal descriptor (either UAC1 or UAC2) with the given
+ * terminal id
+ */
+static void *
+snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
                                               int terminal_id)
 {
        struct uac2_input_terminal_descriptor *term = NULL;
@@ -261,6 +467,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
        struct audioformat *fp = NULL;
        int num, protocol, clock = 0;
        struct uac_format_type_i_continuous_descriptor *fmt;
+       unsigned int chconfig;
 
        dev = chip->dev;
 
@@ -300,6 +507,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
                        continue;
 
+               chconfig = 0;
                /* get audio formats */
                switch (protocol) {
                default:
@@ -311,6 +519,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                case UAC_VERSION_1: {
                        struct uac1_as_header_descriptor *as =
                                snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+                       struct uac_input_terminal_descriptor *iterm;
 
                        if (!as) {
                                snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
@@ -325,6 +534,14 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                        }
 
                        format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+
+                       iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+                                                                      as->bTerminalLink);
+                       if (iterm) {
+                               num_channels = iterm->bNrChannels;
+                               chconfig = le16_to_cpu(iterm->wChannelConfig);
+                       }
+
                        break;
                }
 
@@ -355,6 +572,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                                                                            as->bTerminalLink);
                        if (input_term) {
                                clock = input_term->bCSourceID;
+                               chconfig = le32_to_cpu(input_term->bmChannelConfig);
                                break;
                        }
 
@@ -413,13 +631,13 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
                fp->datainterval = snd_usb_parse_datainterval(chip, alts);
                fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
-               /* num_channels is only set for v2 interfaces */
                fp->channels = num_channels;
                if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
                        fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
                                        * (fp->maxpacksize & 0x7ff);
                fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
                fp->clock = clock;
+               fp->chmap = convert_chmap(num_channels, chconfig, protocol);
 
                /* some quirks for attributes here */
 
@@ -455,6 +673,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                /* ok, let's parse further... */
                if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
                        kfree(fp->rate_table);
+                       kfree(fp->chmap);
                        kfree(fp);
                        fp = NULL;
                        continue;
@@ -464,6 +683,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                err = snd_usb_add_audio_stream(chip, stream, fp);
                if (err < 0) {
                        kfree(fp->rate_table);
+                       kfree(fp->chmap);
                        kfree(fp);
                        return err;
                }
index ef42797f56fb56adf950eef3b764c5533263a8d9..1ac3fd9cc5a625e89cc1290ab3274ebac6982793 100644 (file)
@@ -56,7 +56,6 @@ struct snd_usb_audio {
 
        int setup;                      /* from the 'device_setup' module param */
        int nrpacks;                    /* from the 'nrpacks' module param */
-       int async_unlink;               /* from the 'async_unlink' module param */
 
        struct usb_host_interface *ctrl_intf;   /* the audio control interface */
 };
index f93b776370b6f31fc52d68fe9b3dbf8085d34ed3..3179c711bd65e159ed5a043c42dfa43fa3333f41 100644 (file)
@@ -150,6 +150,8 @@ subaction_create(uint32_t *data, size_t length)
 
        /* we put the ack in the subaction struct for easy access. */
        sa = malloc(sizeof *sa - sizeof sa->packet + length);
+       if (!sa)
+               exit(EXIT_FAILURE);
        sa->ack = data[length / 4 - 1];
        sa->length = length;
        memcpy(&sa->packet, data, length);
@@ -180,6 +182,8 @@ link_transaction_lookup(int request_node, int response_node, int tlabel)
        }
 
        t = malloc(sizeof *t);
+       if (!t)
+               exit(EXIT_FAILURE);
        t->request_node = request_node;
        t->response_node = response_node;
        t->tlabel = tlabel;
index b38a1f9ad4606db6e8544ee5908789eaae0ac0f0..938e8904f64d100ab082a4f1fcca0e68f05592f7 100644 (file)
@@ -175,7 +175,7 @@ following filters are defined:
 
 +
 The option requires at least one branch type among any, any_call, any_ret, ind_call.
-The privilege levels may be ommitted, in which case, the privilege levels of the associated
+The privilege levels may be omitted, in which case, the privilege levels of the associated
 event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege
 levels are subject to permissions.  When sampling on multiple events, branch stack sampling
 is enabled for all the sampling events. The sampled branch type is the same for all events.
index c7ba7614061b22f04d78b5d60e3669dd8767fbed..35fc584a4ffee9677131dd5574f0e722f0a49e62 100755 (executable)
@@ -53,6 +53,9 @@ my %default = (
     "STOP_AFTER_FAILURE"       => 60,
     "STOP_TEST_AFTER"          => 600,
     "MAX_MONITOR_WAIT"         => 1800,
+    "GRUB_REBOOT"              => "grub2-reboot",
+    "SYSLINUX"                 => "extlinux",
+    "SYSLINUX_PATH"            => "/boot/extlinux",
 
 # required, and we will ask users if they don't have them but we keep the default
 # value something that is common.
@@ -105,7 +108,12 @@ my $scp_to_target;
 my $scp_to_target_install;
 my $power_off;
 my $grub_menu;
+my $grub_file;
 my $grub_number;
+my $grub_reboot;
+my $syslinux;
+my $syslinux_path;
+my $syslinux_label;
 my $target;
 my $make;
 my $pre_install;
@@ -232,6 +240,11 @@ my %option_map = (
     "ADD_CONFIG"               => \$addconfig,
     "REBOOT_TYPE"              => \$reboot_type,
     "GRUB_MENU"                        => \$grub_menu,
+    "GRUB_FILE"                        => \$grub_file,
+    "GRUB_REBOOT"              => \$grub_reboot,
+    "SYSLINUX"                 => \$syslinux,
+    "SYSLINUX_PATH"            => \$syslinux_path,
+    "SYSLINUX_LABEL"           => \$syslinux_label,
     "PRE_INSTALL"              => \$pre_install,
     "POST_INSTALL"             => \$post_install,
     "NO_INSTALL"               => \$no_install,
@@ -368,7 +381,7 @@ EOF
     ;
 $config_help{"REBOOT_TYPE"} = << "EOF"
  Way to reboot the box to the test kernel.
- Only valid options so far are "grub" and "script".
+ Only valid options so far are "grub", "grub2", "syslinux", and "script".
 
  If you specify grub, it will assume grub version 1
  and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
@@ -378,11 +391,19 @@ $config_help{"REBOOT_TYPE"} = << "EOF"
 
  The entry in /boot/grub/menu.lst must be entered in manually.
  The test will not modify that file.
+
+ If you specify grub2, then you also need to specify both \$GRUB_MENU
+ and \$GRUB_FILE.
+
+ If you specify syslinux, then you may use SYSLINUX to define the syslinux
+ command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
+ the syslinux install (defaults to /boot/extlinux). But you have to specify
+ SYSLINUX_LABEL to define the label to boot to for the test kernel.
 EOF
     ;
 $config_help{"GRUB_MENU"} = << "EOF"
  The grub title name for the test kernel to boot
- (Only mandatory if REBOOT_TYPE = grub)
+ (Only mandatory if REBOOT_TYPE = grub or grub2)
 
  Note, ktest.pl will not update the grub menu.lst, you need to
  manually add an option for the test. ktest.pl will search
@@ -393,6 +414,22 @@ $config_help{"GRUB_MENU"} = << "EOF"
  title Test Kernel
  kernel vmlinuz-test
  GRUB_MENU = Test Kernel
+
+ For grub2, a search of \$GRUB_FILE is performed for the lines
+ that begin with "menuentry". It will not detect submenus. The
+ menu must be a non-nested menu. Add the quotes used in the menu
+ to guarantee your selection, as the first menuentry with the content
+ of \$GRUB_MENU that is found will be used.
+EOF
+    ;
+$config_help{"GRUB_FILE"} = << "EOF"
+ If grub2 is used, the full path for the grub.cfg file is placed
+ here. Use something like /boot/grub2/grub.cfg to search.
+EOF
+    ;
+$config_help{"SYSLINUX_LABEL"} = << "EOF"
+ If syslinux is used, the label that boots the target kernel must
+ be specified with SYSLINUX_LABEL.
 EOF
     ;
 $config_help{"REBOOT_SCRIPT"} = << "EOF"
@@ -521,6 +558,15 @@ sub get_ktest_configs {
     if ($rtype eq "grub") {
        get_ktest_config("GRUB_MENU");
     }
+
+    if ($rtype eq "grub2") {
+       get_ktest_config("GRUB_MENU");
+       get_ktest_config("GRUB_FILE");
+    }
+
+    if ($rtype eq "syslinux") {
+       get_ktest_config("SYSLINUX_LABEL");
+    }
 }
 
 sub process_variables {
@@ -1123,6 +1169,9 @@ sub wait_for_monitor;
 sub reboot {
     my ($time) = @_;
 
+    # Make sure everything has been written to disk
+    run_ssh("sync");
+
     if (defined($time)) {
        start_monitor;
        # flush out current monitor
@@ -1452,8 +1501,44 @@ sub run_scp_mod {
     return run_scp($src, $dst, $cp_scp);
 }
 
+sub get_grub2_index {
+
+    return if (defined($grub_number));
+
+    doprint "Find grub2 menu ... ";
+    $grub_number = -1;
+
+    my $ssh_grub = $ssh_exec;
+    $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g;
+
+    open(IN, "$ssh_grub |")
+       or die "unable to get $grub_file";
+
+    my $found = 0;
+
+    while (<IN>) {
+       if (/^menuentry.*$grub_menu/) {
+           $grub_number++;
+           $found = 1;
+           last;
+       } elsif (/^menuentry\s/) {
+           $grub_number++;
+       }
+    }
+    close(IN);
+
+    die "Could not find '$grub_menu' in $grub_file on $machine"
+       if (!$found);
+    doprint "$grub_number\n";
+}
+
 sub get_grub_index {
 
+    if ($reboot_type eq "grub2") {
+       get_grub2_index;
+       return;
+    }
+
     if ($reboot_type ne "grub") {
        return;
     }
@@ -1524,6 +1609,10 @@ sub reboot_to {
 
     if ($reboot_type eq "grub") {
        run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
+    } elsif ($reboot_type eq "grub2") {
+       run_ssh "$grub_reboot $grub_number";
+    } elsif ($reboot_type eq "syslinux") {
+       run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
     } elsif (defined $reboot_script) {
        run_command "$reboot_script";
     }
@@ -1718,6 +1807,14 @@ sub do_post_install {
        dodie "Failed to run post install";
 }
 
+# Sometimes the reboot fails, and will hang. We try to ssh to the box
+# and if we fail, we force another reboot, that should powercycle it.
+sub test_booted {
+    if (!run_ssh "echo testing connection") {
+       reboot $sleep_time;
+    }
+}
+
 sub install {
 
     return if ($no_install);
@@ -1730,6 +1827,8 @@ sub install {
 
     my $cp_target = eval_kernel_version $target_image;
 
+    test_booted;
+
     run_scp_install "$outputdir/$build_target", "$cp_target" or
        dodie "failed to copy image";
 
@@ -1877,10 +1976,14 @@ sub make_oldconfig {
 
     if (!run_command "$make olddefconfig") {
        # Perhaps olddefconfig doesn't exist in this version of the kernel
-       # try a yes '' | oldconfig
-       doprint "olddefconfig failed, trying yes '' | make oldconfig\n";
-       run_command "yes '' | $make oldconfig" or
-           dodie "failed make config oldconfig";
+       # try oldnoconfig
+       doprint "olddefconfig failed, trying make oldnoconfig\n";
+       if (!run_command "$make oldnoconfig") {
+           doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
+           # try a yes '' | oldconfig
+           run_command "yes '' | $make oldconfig" or
+               dodie "failed make config oldconfig";
+       }
     }
 }
 
@@ -3700,6 +3803,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        $target = "$ssh_user\@$machine";
        if ($reboot_type eq "grub") {
            dodie "GRUB_MENU not defined" if (!defined($grub_menu));
+       } elsif ($reboot_type eq "grub2") {
+           dodie "GRUB_MENU not defined" if (!defined($grub_menu));
+           dodie "GRUB_FILE not defined" if (!defined($grub_file));
+       } elsif ($reboot_type eq "syslinux") {
+           dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
        }
     }
 
index de28a0a3b8fc90b6070ac557cf755fbaa366e32a..4012e93303444811f20175f36de47fc36f4720fc 100644 (file)
 # from other linux builds on the system.
 #LOCALVERSION = -test
 
+# For REBOOT_TYPE = grub2, you must specify where the grub.cfg
+# file is. This is the file that is searched to find the menu
+# option to boot to with GRUB_REBOOT
+#GRUB_FILE = /boot/grub2/grub.cfg
+
+# The tool for REBOOT_TYPE = grub2 to set the next reboot kernel
+# to boot into (one shot mode).
+# (default grub2_reboot)
+#GRUB_REBOOT = grub2_reboot
+
 # The grub title name for the test kernel to boot
-# (Only mandatory if REBOOT_TYPE = grub)
+# (Only mandatory if REBOOT_TYPE = grub or grub2)
 #
 # Note, ktest.pl will not update the grub menu.lst, you need to
 # manually add an option for the test. ktest.pl will search
 # For example, if in the /boot/grub/menu.lst the test kernel title has:
 # title Test Kernel
 # kernel vmlinuz-test
+#
+# For grub2, a search of top level "menuentry"s are done. No
+# submenu is searched. The menu is found by searching for the
+# contents of GRUB_MENU in the line that starts with "menuentry".
+# You may want to include the quotes around the option. For example:
+# for: menuentry 'Test Kernel'
+# do a: GRUB_MENU = 'Test Kernel'
+# For customizing, add your entry in /etc/grub.d/40_custom.
+#
 #GRUB_MENU = Test Kernel
 
+# For REBOOT_TYPE = syslinux, the name of the syslinux executable
+# (on the target) to use to set up the next reboot to boot the
+# test kernel.
+# (default extlinux)
+#SYSLINUX = syslinux
+
+# For REBOOT_TYPE = syslinux, the path that is passed to to the
+# syslinux command where syslinux is installed.
+# (default /boot/extlinux)
+#SYSLINUX_PATH = /boot/syslinux
+
+# For REBOOT_TYPE = syslinux, the syslinux label that references the
+# test kernel in the syslinux config file.
+# (default undefined)
+#SYSLINUX_LABEL = "test-kernel"
+
 # A script to reboot the target into the test kernel
 # This and SWITCH_TO_TEST are about the same, except
 # SWITCH_TO_TEST is run even for REBOOT_TYPE = grub.
 #POST_BUILD_DIE = 1
 
 # Way to reboot the box to the test kernel.
-# Only valid options so far are "grub" and "script"
+# Only valid options so far are "grub", "grub2", "syslinux" and "script"
 # (default grub)
 # If you specify grub, it will assume grub version 1
 # and will search in /boot/grub/menu.lst for the title $GRUB_MENU
 # your setup, then specify "script" and have a command or script
 # specified in REBOOT_SCRIPT to boot to the target.
 #
+# For REBOOT_TYPE = grub2, you must define both GRUB_MENU and
+# GRUB_FILE.
+#
+# For REBOOT_TYPE = syslinux, you must define SYSLINUX_LABEL, and
+# perhaps modify SYSLINUX (default extlinux) and SYSLINUX_PATH
+# (default /boot/extlinux)
+#
 # The entry in /boot/grub/menu.lst must be entered in manually.
 # The test will not modify that file.
 #REBOOT_TYPE = grub
index aca6edcbbc6fa09113389e87b3e76a55a871da98..af8c925e93ebd4536e41897c5fcfff10f3fffda8 100644 (file)
@@ -405,7 +405,6 @@ static char *cpio_replace_env(char *new_location)
        return new_location;
 }
 
-
 static int cpio_mkfile_line(const char *line)
 {
        char name[PATH_MAX + 1];
index 23a41a9f8db999f4b70fd4c0cd4b6ae8b26ee3c2..3642239252b0015593fe690ec0fa83ae5b841145 100644 (file)
@@ -105,6 +105,15 @@ static irqreturn_t kvm_assigned_dev_thread_intx(int irq, void *dev_id)
 }
 
 #ifdef __KVM_HAVE_MSI
+static irqreturn_t kvm_assigned_dev_msi(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+       int ret = kvm_set_irq_inatomic(assigned_dev->kvm,
+                                      assigned_dev->irq_source_id,
+                                      assigned_dev->guest_irq, 1);
+       return unlikely(ret == -EWOULDBLOCK) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+}
+
 static irqreturn_t kvm_assigned_dev_thread_msi(int irq, void *dev_id)
 {
        struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
@@ -117,6 +126,23 @@ static irqreturn_t kvm_assigned_dev_thread_msi(int irq, void *dev_id)
 #endif
 
 #ifdef __KVM_HAVE_MSIX
+static irqreturn_t kvm_assigned_dev_msix(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+       int index = find_index_from_host_irq(assigned_dev, irq);
+       u32 vector;
+       int ret = 0;
+
+       if (index >= 0) {
+               vector = assigned_dev->guest_msix_entries[index].vector;
+               ret = kvm_set_irq_inatomic(assigned_dev->kvm,
+                                          assigned_dev->irq_source_id,
+                                          vector, 1);
+       }
+
+       return unlikely(ret == -EWOULDBLOCK) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+}
+
 static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
 {
        struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
@@ -334,11 +360,6 @@ static int assigned_device_enable_host_intx(struct kvm *kvm,
 }
 
 #ifdef __KVM_HAVE_MSI
-static irqreturn_t kvm_assigned_dev_msi(int irq, void *dev_id)
-{
-       return IRQ_WAKE_THREAD;
-}
-
 static int assigned_device_enable_host_msi(struct kvm *kvm,
                                           struct kvm_assigned_dev_kernel *dev)
 {
@@ -363,11 +384,6 @@ static int assigned_device_enable_host_msi(struct kvm *kvm,
 #endif
 
 #ifdef __KVM_HAVE_MSIX
-static irqreturn_t kvm_assigned_dev_msix(int irq, void *dev_id)
-{
-       return IRQ_WAKE_THREAD;
-}
-
 static int assigned_device_enable_host_msix(struct kvm *kvm,
                                            struct kvm_assigned_dev_kernel *dev)
 {
index 9718e98d6d2a84956d113bd43f55d804bd30d049..b6eea5cc7b34d1074af9f26b724fed0eb5571725 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "iodev.h"
 
+#ifdef __KVM_HAVE_IOAPIC
 /*
  * --------------------------------------------------------------------
  * irqfd: Allows an fd to be used to inject an interrupt to the guest
@@ -332,7 +333,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
                mutex_lock(&kvm->irqfds.resampler_lock);
 
                list_for_each_entry(resampler,
-                                   &kvm->irqfds.resampler_list, list) {
+                                   &kvm->irqfds.resampler_list, link) {
                        if (resampler->notifier.gsi == irqfd->gsi) {
                                irqfd->resampler = resampler;
                                break;
@@ -425,17 +426,21 @@ fail:
        kfree(irqfd);
        return ret;
 }
+#endif
 
 void
 kvm_eventfd_init(struct kvm *kvm)
 {
+#ifdef __KVM_HAVE_IOAPIC
        spin_lock_init(&kvm->irqfds.lock);
        INIT_LIST_HEAD(&kvm->irqfds.items);
        INIT_LIST_HEAD(&kvm->irqfds.resampler_list);
        mutex_init(&kvm->irqfds.resampler_lock);
+#endif
        INIT_LIST_HEAD(&kvm->ioeventfds);
 }
 
+#ifdef __KVM_HAVE_IOAPIC
 /*
  * shutdown any irqfd's that match fd+gsi
  */
@@ -555,6 +560,7 @@ static void __exit irqfd_module_exit(void)
 
 module_init(irqfd_module_init);
 module_exit(irqfd_module_exit);
+#endif
 
 /*
  * --------------------------------------------------------------------
index 037cb6730e68eef3171b0e9660d1139b423d96de..4a340cb230134bd7fb15b62545ff8b5245ecbfa2 100644 (file)
@@ -52,7 +52,7 @@ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn,
        end_gfn = gfn + (size >> PAGE_SHIFT);
        gfn    += 1;
 
-       if (is_error_pfn(pfn))
+       if (is_error_noslot_pfn(pfn))
                return pfn;
 
        while (gfn < end_gfn)
@@ -106,7 +106,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
                 * important because we unmap and unpin in 4kb steps later.
                 */
                pfn = kvm_pin_pages(slot, gfn, page_size);
-               if (is_error_pfn(pfn)) {
+               if (is_error_noslot_pfn(pfn)) {
                        gfn += 1;
                        continue;
                }
@@ -168,11 +168,7 @@ int kvm_assign_device(struct kvm *kvm,
 
        r = iommu_attach_device(domain, &pdev->dev);
        if (r) {
-               printk(KERN_ERR "assign device %x:%x:%x.%x failed",
-                       pci_domain_nr(pdev->bus),
-                       pdev->bus->number,
-                       PCI_SLOT(pdev->devfn),
-                       PCI_FUNC(pdev->devfn));
+               dev_err(&pdev->dev, "kvm assign device failed ret %d", r);
                return r;
        }
 
index 2eb58af7ee99268b81a01680db591ea4991c47eb..656fa455e154abedceba3883cf865adfa73f873b 100644 (file)
@@ -102,6 +102,23 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
        return r;
 }
 
+static inline void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,
+                                  struct kvm_lapic_irq *irq)
+{
+       trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data);
+
+       irq->dest_id = (e->msi.address_lo &
+                       MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
+       irq->vector = (e->msi.data &
+                       MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
+       irq->dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo;
+       irq->trig_mode = (1 << MSI_DATA_TRIGGER_SHIFT) & e->msi.data;
+       irq->delivery_mode = e->msi.data & 0x700;
+       irq->level = 1;
+       irq->shorthand = 0;
+       /* TODO Deal with RH bit of MSI message address */
+}
+
 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
                struct kvm *kvm, int irq_source_id, int level)
 {
@@ -110,22 +127,26 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
        if (!level)
                return -1;
 
-       trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data);
+       kvm_set_msi_irq(e, &irq);
 
-       irq.dest_id = (e->msi.address_lo &
-                       MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
-       irq.vector = (e->msi.data &
-                       MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
-       irq.dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo;
-       irq.trig_mode = (1 << MSI_DATA_TRIGGER_SHIFT) & e->msi.data;
-       irq.delivery_mode = e->msi.data & 0x700;
-       irq.level = 1;
-       irq.shorthand = 0;
-
-       /* TODO Deal with RH bit of MSI message address */
        return kvm_irq_delivery_to_apic(kvm, NULL, &irq);
 }
 
+
+static int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *e,
+                        struct kvm *kvm)
+{
+       struct kvm_lapic_irq irq;
+       int r;
+
+       kvm_set_msi_irq(e, &irq);
+
+       if (kvm_irq_delivery_to_apic_fast(kvm, NULL, &irq, &r))
+               return r;
+       else
+               return -EWOULDBLOCK;
+}
+
 int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
 {
        struct kvm_kernel_irq_routing_entry route;
@@ -178,6 +199,44 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level)
        return ret;
 }
 
+/*
+ * Deliver an IRQ in an atomic context if we can, or return a failure,
+ * user can retry in a process context.
+ * Return value:
+ *  -EWOULDBLOCK - Can't deliver in atomic context: retry in a process context.
+ *  Other values - No need to retry.
+ */
+int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
+{
+       struct kvm_kernel_irq_routing_entry *e;
+       int ret = -EINVAL;
+       struct kvm_irq_routing_table *irq_rt;
+       struct hlist_node *n;
+
+       trace_kvm_set_irq(irq, level, irq_source_id);
+
+       /*
+        * Injection into either PIC or IOAPIC might need to scan all CPUs,
+        * which would need to be retried from thread context;  when same GSI
+        * is connected to both PIC and IOAPIC, we'd have to report a
+        * partial failure here.
+        * Since there's no easy way to do this, we only support injecting MSI
+        * which is limited to 1:1 GSI mapping.
+        */
+       rcu_read_lock();
+       irq_rt = rcu_dereference(kvm->irq_routing);
+       if (irq < irq_rt->nr_rt_entries)
+               hlist_for_each_entry(e, n, &irq_rt->map[irq], link) {
+                       if (likely(e->type == KVM_IRQ_ROUTING_MSI))
+                               ret = kvm_set_msi_inatomic(e, kvm);
+                       else
+                               ret = -EWOULDBLOCK;
+                       break;
+               }
+       rcu_read_unlock();
+       return ret;
+}
+
 void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
 {
        struct kvm_irq_ack_notifier *kian;
index be70035fd42a14edad4c24ae411c4b9d3fdf396c..1cd693a76a510c34a2d563d9fe68072802d28620 100644 (file)
@@ -212,6 +212,11 @@ void kvm_reload_remote_mmus(struct kvm *kvm)
        make_all_cpus_request(kvm, KVM_REQ_MMU_RELOAD);
 }
 
+void kvm_make_mclock_inprogress_request(struct kvm *kvm)
+{
+       make_all_cpus_request(kvm, KVM_REQ_MCLOCK_INPROGRESS);
+}
+
 int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
 {
        struct page *page;
@@ -709,8 +714,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
        int r;
        gfn_t base_gfn;
        unsigned long npages;
-       unsigned long i;
-       struct kvm_memory_slot *memslot;
+       struct kvm_memory_slot *memslot, *slot;
        struct kvm_memory_slot old, new;
        struct kvm_memslots *slots, *old_memslots;
 
@@ -761,13 +765,11 @@ int __kvm_set_memory_region(struct kvm *kvm,
 
        /* Check for overlaps */
        r = -EEXIST;
-       for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
-               struct kvm_memory_slot *s = &kvm->memslots->memslots[i];
-
-               if (s == memslot || !s->npages)
+       kvm_for_each_memslot(slot, kvm->memslots) {
+               if (slot->id >= KVM_MEMORY_SLOTS || slot == memslot)
                        continue;
-               if (!((base_gfn + npages <= s->base_gfn) ||
-                     (base_gfn >= s->base_gfn + s->npages)))
+               if (!((base_gfn + npages <= slot->base_gfn) ||
+                     (base_gfn >= slot->base_gfn + slot->npages)))
                        goto out_free;
        }
 
@@ -1208,7 +1210,7 @@ __gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn, bool atomic,
                return KVM_PFN_ERR_RO_FAULT;
 
        if (kvm_is_error_hva(addr))
-               return KVM_PFN_ERR_BAD;
+               return KVM_PFN_NOSLOT;
 
        /* Do not map writable pfn in the readonly memslot. */
        if (writable && memslot_is_readonly(slot)) {
@@ -1290,7 +1292,7 @@ EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic);
 
 static struct page *kvm_pfn_to_page(pfn_t pfn)
 {
-       if (is_error_pfn(pfn))
+       if (is_error_noslot_pfn(pfn))
                return KVM_ERR_PTR_BAD_PAGE;
 
        if (kvm_is_mmio_pfn(pfn)) {
@@ -1322,7 +1324,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
+       if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);
@@ -1848,6 +1850,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        atomic_inc(&kvm->online_vcpus);
 
        mutex_unlock(&kvm->lock);
+       kvm_arch_vcpu_postcreate(vcpu);
        return r;
 
 unlock_vcpu_destroy:
@@ -1929,10 +1932,6 @@ out_free1:
                        goto out;
                }
                r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
-               if (r)
-                       goto out_free2;
-               r = 0;
-out_free2:
                kfree(kvm_regs);
                break;
        }
@@ -1954,12 +1953,10 @@ out_free2:
                kvm_sregs = memdup_user(argp, sizeof(*kvm_sregs));
                if (IS_ERR(kvm_sregs)) {
                        r = PTR_ERR(kvm_sregs);
+                       kvm_sregs = NULL;
                        goto out;
                }
                r = kvm_arch_vcpu_ioctl_set_sregs(vcpu, kvm_sregs);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_GET_MP_STATE: {
@@ -1981,9 +1978,6 @@ out_free2:
                if (copy_from_user(&mp_state, argp, sizeof mp_state))
                        goto out;
                r = kvm_arch_vcpu_ioctl_set_mpstate(vcpu, &mp_state);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_TRANSLATE: {
@@ -2008,9 +2002,6 @@ out_free2:
                if (copy_from_user(&dbg, argp, sizeof dbg))
                        goto out;
                r = kvm_arch_vcpu_ioctl_set_guest_debug(vcpu, &dbg);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_SET_SIGNAL_MASK: {
@@ -2054,12 +2045,10 @@ out_free2:
                fpu = memdup_user(argp, sizeof(*fpu));
                if (IS_ERR(fpu)) {
                        r = PTR_ERR(fpu);
+                       fpu = NULL;
                        goto out;
                }
                r = kvm_arch_vcpu_ioctl_set_fpu(vcpu, fpu);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        default:
@@ -2129,8 +2118,6 @@ static long kvm_vm_ioctl(struct file *filp,
        switch (ioctl) {
        case KVM_CREATE_VCPU:
                r = kvm_vm_ioctl_create_vcpu(kvm, arg);
-               if (r < 0)
-                       goto out;
                break;
        case KVM_SET_USER_MEMORY_REGION: {
                struct kvm_userspace_memory_region kvm_userspace_mem;
@@ -2141,8 +2128,6 @@ static long kvm_vm_ioctl(struct file *filp,
                        goto out;
 
                r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, 1);
-               if (r)
-                       goto out;
                break;
        }
        case KVM_GET_DIRTY_LOG: {
@@ -2152,8 +2137,6 @@ static long kvm_vm_ioctl(struct file *filp,
                if (copy_from_user(&log, argp, sizeof log))
                        goto out;
                r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
-               if (r)
-                       goto out;
                break;
        }
 #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
@@ -2163,9 +2146,6 @@ static long kvm_vm_ioctl(struct file *filp,
                if (copy_from_user(&zone, argp, sizeof zone))
                        goto out;
                r = kvm_vm_ioctl_register_coalesced_mmio(kvm, &zone);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
        case KVM_UNREGISTER_COALESCED_MMIO: {
@@ -2174,9 +2154,6 @@ static long kvm_vm_ioctl(struct file *filp,
                if (copy_from_user(&zone, argp, sizeof zone))
                        goto out;
                r = kvm_vm_ioctl_unregister_coalesced_mmio(kvm, &zone);
-               if (r)
-                       goto out;
-               r = 0;
                break;
        }
 #endif
@@ -2285,8 +2262,6 @@ static long kvm_vm_compat_ioctl(struct file *filp,
                log.dirty_bitmap = compat_ptr(compat_log.dirty_bitmap);
 
                r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
-               if (r)
-                       goto out;
                break;
        }
        default: